填充圆绘制算法生成重复坐标点问题排查咨询
问题根源
重复点完全是逻辑设计问题,来源有两个:
- 同一水平扫描线被反复添加:中点圆迭代时x逐轮递增,但y只有决策变量d达到阈值才会递减,同一个y值会对应多轮x迭代。你每轮迭代都给当前y绘制从-x到x的水平线段,后一轮更长的线段会完全覆盖前一轮的短线段,被覆盖的点全部重复,示意图上下两端的
!就是这么来的——比如半径5时y=5的线段,x=0时加了1个点,x=1时加了3个点,x=2时加了5个点,中间的点被重复加了2-3次。 - 特殊位置点重叠:当迭代到x=y的对角线位置时,水平线段和垂直线段的端点完全重合,会重复添加四个对角线点;x=0或y=0的坐标轴位置,对称判断逻辑也会重复加点。
排查思路
按这几步查,很快能定位:
- 拿小半径(比如radius=2)单步调试,逐轮打印x、y值和当轮新增的点,对比已有点列表,一眼就能看到同一y值的线段被反复追加。
- 把返回的points转成set去重后算长度,和填充圆理论点数对比,差值就是重复点数量,可以快速验证修复有没有效果。
- 分别注释掉水平线段、垂直线段的绘制逻辑,单独看每部分输出的图形,就能定位哪段逻辑产生了重叠。
修复方案
方案1:最小改动快速修复
如果不想大改原有逻辑,直接在返回前对坐标去重即可,适合对性能要求不高的场景:
def get_filled_circle(radius): d = (5 - radius * 4) / 4.0 x = 0 y = radius points = [] while True: for idx in range(-x, x+1, 1): points.append((idx, y)) if y != 0: points.append((idx,-y)) for idx in range(-y, y+1, 1): points.append((idx, x)) if x != 0: points.append((idx,-x)) if (d < 0): d += 2 * x + 1 else: d += 2 * (x - y) + 1 y -= 1 x += 1 if (y < x): break # 新增去重逻辑,保持原有坐标顺序 seen = set() unique_points = [] for p in points: if p not in seen: seen.add(p) unique_points.append(p) return unique_points
方案2:逻辑层根治重复
核心思路是每个y值只绘制一次水平扫描线,从根源避免重复添加,性能更好:
def get_filled_circle(radius): d = (5 - radius * 4) / 4.0 x = 0 y = radius points = [] processed_y = set() # 记录已经绘制过的y值,避免重复绘制 while True: # 绘制y和-y的水平线段,仅在y首次出现时绘制 if y not in processed_y: for idx in range(-x, x + 1): points.append((idx, y)) if y != 0: points.append((idx, -y)) processed_y.add(y) processed_y.add(-y) # 绘制x和-x的水平线段,x逐轮递增天然不会重复 for idx in range(-y, y + 1): points.append((idx, x)) if x != 0: points.append((idx, -x)) if d < 0: d += 2 * x + 1 else: d += 2 * (x - y) + 1 y -= 1 x += 1 if y < x: break return points
修复后再绘制就不会出现!标记的重复点了,填充的圆形完全符合预期。
内容的提问来源于stack exchange,提问作者cyrus
相关产品推荐
相关产品推荐

