已知圆心整数像素坐标及整数半径,如何计算1像素厚圆边框的所有像素坐标
整数运算提取1像素圆形外边缘坐标实现方案
你之前采用曼哈顿距离|dx| + |dy| = r的逻辑得到的是旋转45度的正方形边缘,不符合圆形的欧氏距离轮廓要求,这里推荐用Bresenham中点圆算法实现,全程仅用整数运算,能精准生成1像素厚的圆形外边缘坐标。
核心逻辑
利用圆的八对称性:圆形沿x轴、y轴、直线y=x、直线y=-x对称,只需要计算第一象限中x从0到y的1/8圆弧上的点,就能对称映射出整个圆的所有边缘点,运算量极低。
算法通过整数决策参数判断下一个像素的位置,全程无浮点运算、无开方操作。
具体实现步骤
- 初始化参数:圆心整数坐标
(x0, y0),整数半径r,决策参数初始值d = 1 - r,初始坐标x = 0,y = r - 封装对称点添加逻辑:每次得到一组
(x,y)偏移量,就生成8个对称方向的真实坐标,加入结果集(x0 + x, y0 + y)、(x0 - x, y0 + y)、(x0 + x, y0 - y)、(x0 - x, y0 - y) (x0 + y, y0 + x)、(x0 - y, y0 + x)、(x0 + y, y0 - x)、(x0 - y, y0 - x) - 迭代生成1/8圆弧:循环执行直到
x >= y- x自增1
- 若
d < 0,说明当前中点在圆内部,y值保持不变,更新决策参数d = d + 2*x + 1 - 若
d >= 0,说明当前中点在圆外部,y值自减1,更新决策参数d = d + 2*(x - y) + 1 - 把当前
(x,y)对应的8个对称点加入结果集
- 最后对结果集去重即可(x=y或r=0时会生成重复坐标)
可直接运行的代码示例
def get_circle_edge(x0: int, y0: int, r: int) -> list[tuple[int, int]]: # 入参校验 if r < 0: return [] if r == 0: return [(x0, y0)] edge_points = [] # 对称添加8个方向的点 def add_sym_points(dx: int, dy: int): edge_points.append((x0 + dx, y0 + dy)) edge_points.append((x0 - dx, y0 + dy)) edge_points.append((x0 + dx, y0 - dy)) edge_points.append((x0 - dx, y0 - dy)) edge_points.append((x0 + dy, y0 + dx)) edge_points.append((x0 - dy, y0 + dx)) edge_points.append((x0 + dy, y0 - dx)) edge_points.append((x0 - dy, y0 - dx)) x, y = 0, r d = 1 - r add_sym_points(x, y) while x < y: x += 1 if d < 0: d += 2 * x + 1 else: y -= 1 d += 2 * (x - y) + 1 add_sym_points(x, y) # 去重后返回 return list(set(edge_points))
方案优势
- 全程仅用整数加减乘法,没有任何浮点运算,运算效率远高于遍历全量像素判断
dx²+dy²=r²的方案 - 生成的边缘严格为1像素厚度,没有多余点,完全符合圆形轮廓要求
- 迭代次数仅为
r/√2次,即使大半径的圆也能快速生成结果
内容的提问来源于stack exchange,提问作者Hugofac
相关产品推荐
相关产品推荐

