中点画圆算法----计算机图形学

圆的对称特性:

 

一个八分圆上的点可以映射为其余七个八分圆的点

这里写图片描述

利用圆的对称性可以减少计算量,只需要计算出一个八分之一圆上需要画的点,就可以映射出整个圆

 

中点画圆算法:

(对于原点为(xc,yc)的圆,假定圆心在坐标原点(0,0)的像素位置,把计算出每个圆上像素点(x,y)加到屏幕位置上,即(xc+x,yc+y) )

 

现在来具体研究如何从点(0,R)到 (R/\sqrt{2} , R/\sqrt{2})顺时针地确定最佳逼近于该圆弧的像素序列。

假定横坐标为 xp 的像素中与该圆弧最近者已确定为 P=(xp,yp) ,那么,下一个像素只能是正右方的 E(xp+1,yp)或右下方的 SE(xp+1,yp-1)两者之一,如下图所示。

首先构造函数:F(x,y)=x^{2}+y^{2}-R^{2}

显然对于圆上的点,F(x, y)= 0;对于圆外的点,F(x, y)> 0 ; 对于圆内的点,F(x, y)< 0 .

假设 M 是 E 和 SE 的中点,即 M = (xp+1 , yp-0.5). 那么,当 F(M)< 0 时, M 在圆内,说明 E 距离圆弧更近,应取 E 作为下一个像素 ; 当 F(M)> 0 时,应取 SE 作为下一个像素。当 F(M)= 0 时,随便取 E 或 SE 。

 

构造判别式:

Di = F(M) =  F(xp+1, yp-0.5) =  (x_{p}+1)^{2} + (y_{p} - 0.5)^{2} - R^{2}

若 Di < 0 , 则应取 E 为下一个像素

D(i+1) =  F(Mse) =  F(xp+2, yp-1.5)=  (x_{p}+2)^{2} + (y_{p} - 1.5)^{2} - R^{2}

                                                                =   Di + 2*xp + 3

 

若 Di > 0 , 则应取 SE 为下一个像素

D(i+1) =  F(Me) =  F(xp+2, yp-0.5)=  (x_{p}+2)^{2} + (y_{p} - 0.5)^{2} - R^{2}

                                                                =   Di + (2*xp + 3) + (-2*yp + 2)

                                                                =   Di + 2*(xp - yp) + 5

 

起始位置(0,R)处初始决策参数  D0 为:

D0 =  F(0+1 , R-0.5)= 1.25 - R

 

注意:上述方法仅限于(0,R)到 (R/\sqrt{2} , R/\sqrt{2})区间,因为此区间圆弧切线斜率小于1。

如图,当点处于 (R/\sqrt{2} , R/\sqrt{2})到 (R,0)区间时,假如当前选定点为图中绿色点,则下一点应在点 A与点 B中进行选择,而不是点 A上方灰色点。这时,应由(R,0)开始,将 y 轴坐标递增 1 进行计算。

 

 

 

核心代码:

(具体实现时,考虑到浮点运算耗内存,使用 E = Di - 0.5 代替 Di , 则初始化运算 D0 = 1.25 - R 对应于 E = 1-R。判别式 Di < 0 对应于 E < 0 (由于E 始终是整数,所以 E < -0.25 等价于  E < 0)

from PySide2.QtCore import *
class Circle:
    def __init__(self, p, r):
        self.p = p
        self.r = r
    def points_list_circle(self):
        points = []
        if self.r < 1:
            return points
        e = 1 - self.r
        x = 0
        y = self.r
        ps0 = []
        ps1 = []
        ps2 = []
        ps3 = []
        ps4 = []
        ps5 = []
        ps6 = []
        ps7 = []
        while x <= y:
            #print("x:"+str(x)+" y:"+str(y))
            ps0.append(QPoint(x, y))
            ps1.append(QPoint(y, x))
            ps2.append(QPoint(-y, x))
            ps3.append(QPoint(-x, y))
            ps4.append(QPoint(y, -x))
            ps5.append(QPoint(x, -y))
            ps6.append(QPoint(-x, -y))
            ps7.append(QPoint(-y, -x))
            if e <= 0:
                e = e + 2*x + 3
            else:
                e = e + 2*x - 2*y + 5
                y -= 1
            x += 1


        for p1 in ps0:
            p1.setX(p1.x()+self.p.x())
            p1.setY(p1.y()+self.p.y())
            points.append(p1)
        for p1 in ps1:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)
        for p1 in ps2:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)
        for p1 in ps3:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)
        for p1 in ps4:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)
        for p1 in ps5:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)
        for p1 in ps6:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)
        for p1 in ps7:
            p1.setX(p1.x() + self.p.x())
            p1.setY(p1.y() + self.p.y())
            points.append(p1)

        return points

 

加上UI界面实现效果:

 

PS: 如需参考完整代码,请移步:https://download.csdn.net/download/qq_42185999/11834678   进行下载

  • 8
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
中点画圆算法计算机图形学中用于绘制圆形的一种算法。该算法通过计算圆上的像素点来绘制圆形。以下是使用中点画圆算法绘制圆形的步骤: 1. 定义圆的半径r和圆心坐标(xc, yc)。 2. 初始化变量x和y,使它们分别等于0和r。 3. 计算决策参数d,d的初始值为1-r。 4. 在每个步骤中,绘制8个对称的像素点。这些像素点的坐标分别为(x+xc, y+yc),(-x+xc, y+yc),(x+xc, -y+yc),(-x+xc, -y+yc),(y+xc, x+yc),(-y+xc, x+yc),(y+xc, -x+yc)和(-y+xc, -x+yc)。 5. 如果d小于0,则选择(x+1, y)作为下一个像素点,并将d更新为d+2x+3。 6. 如果d大于等于0,则选择(x+1, y-1)作为下一个像素点,并将d更新为d+2x-2y+5。 下面是使用中点画圆算法绘制圆形Python代码: ```python import pygame def draw_circle_midpoint(screen, xc, yc, r, color): x, y = 0, r d = 1 - r while x <= y: pygame.draw.circle(screen, color, (x+xc, y+yc), 1) pygame.draw.circle(screen, color, (-x+xc, y+yc), 1) pygame.draw.circle(screen, color, (x+xc, -y+yc), 1) pygame.draw.circle(screen, color, (-x+xc, -y+yc), 1) pygame.draw.circle(screen, color, (y+xc, x+yc), 1) pygame.draw.circle(screen, color, (-y+xc, x+yc), 1) pygame.draw.circle(screen, color, (y+xc, -x+yc), 1) pygame.draw.circle(screen, color, (-y+xc, -x+yc), 1) if d < 0: d = d + 2 * x + 3 else: d = d + 2 * (x - y) + 5 y = y - 1 x = x + 1 # 示例代码 pygame.init() screen = pygame.display.set_mode((640, 480)) draw_circle_midpoint(screen, 320, 240, 100, (255, 255, 255)) pygame.display.update() while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值