【问题标题】:Drawing a circle using tkinter without create_oval使用没有 create_oval 的 tkinter 绘制圆
【发布时间】:2021-09-23 11:48:58
【问题描述】:

在最近的一项任务中,我的任务是使用中心坐标和半径作为参数在 tkinter 中绘制一个实心圆。对于任何圆,我知道半径**2 = (x-centerx)**2 + (y-centery)**2。有了这个,我可以拼凑起来:

def circle(img, color, radius, center):
x0, y0 = center
for i in range (radius):
    for x in range (x0-i, x0+i):
        for y in range (y0-i, y0+i):
            if (x-x0)**2 + (y-y0)**2 == i**2:
                img.put(color, (x,y))

但是,这只会导致实心圆圈的一些虚线轮廓,可能是因为所有点都是整数。因此,我对if 语句的边界进行了一些处理,并发现了一些奇怪的东西。对于:

def circle(img, color, radius, center):
x0, y0 = center
for i in range (radius):
    for x in range (x0-i, x0+i):
        for y in range (y0-i, y0+i):
            if i**2 - a <= (x-x0)**2 + (y-y0)**2 <= i**2 + a:
                img.put(color, (x,y))

a 越大,圆圈就越准确。这是如何运作的?由于我使用i**2 作为x,y 的边界,不应该增加a 导致更大的x,y 值被接受,从而使圆更方?

【问题讨论】:

    标签: python tkinter geometry


    【解决方案1】:

    对于实心圆,请考虑逐行填充(整数坐标的圆层没有明确定义)

    def circle(img, color, radius, center):
        x0, y0 = center
        for y in range (y0 - radius, y0 + radius + 1):
           wdt = int((radius*radius - y * y)**0.5)
           for x in range (x0-wdt, x0+wdt+1):
                img.put(color, (x,y))
    

    关于“这是如何工作的?”

    if i**2 - a <= (x-x0)**2 + (y-y0)**2 <= i**2 + a:
    

    在这里,您使用内半径 sqrt(i**2 - a) 和外半径 i 标记位于环中的像素。右边界 i**2 + a 没有什么意义,因为 x 和 y 范围受 i 限制。较大的a 值会产生更宽的环,因此会标记更多像素。在第一个代码中,您只标记了一些符合精确方程的像素(如毕达哥拉斯三元组)

    另请注意,有一些特殊的算法可以绘制连续圆周,例如 Breseham 算法和中点算法。

    【讨论】:

    • 这是一个更优雅的问题解决方案,但我仍然想知道为什么增加a 会导致越来越精确的循环。由于原始方程源自毕达哥拉斯公式,我认为更大的i**2 必然意味着更大的x,y。我的代码适用于我只是不知道为什么的作业。
    • @TripleEmu 我添加了一些解释
    • 我的答案还不清楚吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 2020-08-25
    • 1970-01-01
    相关资源
    最近更新 更多