Python 如何使用海龟填充形状区域
我使用turtle在Python中绘制了一个分形图形,并试图在经过足够高的迭代后得到这个分形的面积。对于那些感兴趣的人来说,这种分形与科赫雪花有关 我能够使用begin_fill()和end_fill()用黑色填充分形。然后,我用它来获取有效范围内每个像素的颜色。如果它不等于白色,那么我在计数中加上一个。此解决方案适用于分形的小迭代。然而,当尝试进行更高的迭代时,需要花费大量的时间 这是我的分形代码Python 如何使用海龟填充形状区域,python,turtle-graphics,fill,area,fractals,Python,Turtle Graphics,Fill,Area,Fractals,我使用turtle在Python中绘制了一个分形图形,并试图在经过足够高的迭代后得到这个分形的面积。对于那些感兴趣的人来说,这种分形与科赫雪花有关 我能够使用begin_fill()和end_fill()用黑色填充分形。然后,我用它来获取有效范围内每个像素的颜色。如果它不等于白色,那么我在计数中加上一个。此解决方案适用于分形的小迭代。然而,当尝试进行更高的迭代时,需要花费大量的时间 这是我的分形代码 def realSnowflake(length, n, s, show = False):
def realSnowflake(length, n, s, show = False):
#n: after n iterations
#s: number of sides (in Koch snowflake, it is 3)
#length: starting side length
turtle.begin_fill()
a = 360/s
for i in range(s):
snowflake(length, n, s)
turtle.right(a)
turtle.end_fill()
这是我查找该区域的代码
count = 0
canvas = turtle.getcanvas()
for x in range(x1, x2+1): #limits calculated through math
for y in range(y2, y1+1):
if get_pixel_color(x, y, canvas) != "white":
count += 1
我希望能够更快地找到这个分形的区域。它花费的时间最多的不是绘制分形图,而是x和y的双for循环。我认为,如果有一种方法可以在海龟填充时找到该区域,这将是最佳选择
绘制图像的复杂性不应影响所需的时间
计数黑色像素
不幸的是,在这种情况下确实如此。如果我们查找一个,我们会发现说明问题的文本“很慢”。但比这更糟糕的是,它实际上变慢了
此代码构建在画布上。查找\u overlapping()
以查找位于X、Y上方的高级对象。在tkinter为turtle填充对象的情况下,存在重叠,下面的代码中最多有三层。随着事实变得更加复杂,这一点也会增加。下面是我的代码来演示这一点:
from turtle import Screen, Turtle
from math import floor, ceil
from time import time
def koch_curve(turtle, iterations, length):
if iterations == 0:
turtle.forward(length)
else:
for angle in [60, -120, 60, 0]:
koch_curve(turtle, iterations - 1, length / 3)
turtle.left(angle)
def koch_snowflake(turtle, iterations, length):
turtle.begin_poly()
turtle.begin_fill()
for _ in range(3):
koch_curve(turtle, iterations, length)
turtle.right(120)
turtle.end_fill()
turtle.end_poly()
return turtle.get_poly()
def bounding_box(points):
x_coordinates, y_coordinates = zip(*points)
return [(min(x_coordinates), min(y_coordinates)), (max(x_coordinates), max(y_coordinates))]
def get_pixel_color(x, y):
ids = canvas.find_overlapping(x, y, x, y) # This is our bottleneck!
if ids: # if list is not empty
index = ids[-1]
return canvas.itemcget(index, 'fill')
return 'white' # default color
screen = Screen()
screen.setup(500, 500)
turtle = Turtle(visible=False)
turtle.color('red')
canvas = screen.getcanvas()
width, height = screen.window_width(), screen.window_height()
for iterations in range(1, 7):
screen.clear()
turtle.clear()
screen.tracer(False)
polygon_start_time = time()
polygon = koch_snowflake(turtle, iterations, 200)
polygon_elapsed = round((time() - polygon_start_time) * 1000) # milliseconds
screen.tracer(True)
((x_min, y_min), (x_max, y_max)) = bounding_box(polygon)
screen.update()
# Convert from turtle coordinates to tkinter coordinates
x1, y1 = floor(x_min), floor(-y_max)
x2, y2 = ceil(x_max), ceil(-y_min)
canvas.create_rectangle((x1, y1, x2, y2))
count = 0
pixel_count_start_time = time()
for x in range(x1, x2 + 1):
for y in range(y1, y2 + 1):
if get_pixel_color(x, y) == 'red':
count += 1
pixel_count_elapsed = round((time() - pixel_count_start_time) * 1000)
print(iterations, count, polygon_elapsed, pixel_count_elapsed, ((x1, y1), (x2, y2)))
screen.exitonclick()
控制台输出
> python3 test.py
1 23165 1 493 ((-1, -58), (201, 174))
2 26064 4 1058 ((-1, -58), (201, 174))
3 27358 9 1347 ((-1, -58), (201, 174))
4 28159 29 2262 ((0, -58), (201, 174))
5 28712 104 5925 ((0, -58), (201, 174))
6 28881 449 19759 ((0, -58), (200, 174))
>
字段如下所示:
> python3 test.py
1 23165 1 493 ((-1, -58), (201, 174))
2 26064 4 1058 ((-1, -58), (201, 174))
3 27358 9 1347 ((-1, -58), (201, 174))
4 28159 29 2262 ((0, -58), (201, 174))
5 28712 104 5925 ((0, -58), (201, 174))
6 28881 449 19759 ((0, -58), (200, 174))
>
请注意,分形由turtle绘制,但边界框由底层tkinter绘制,以验证我们正确转换了坐标
可能的解决方案
找到一种不依赖于
Find\u overlapping()
的方法。我认为接下来要研究的是将画布转换为位图图像,并对其进行像素计数,或者首先绘制位图图像。关于如何直接或间接地通过Postscript将画布转换为位图,这里有几个讨论。然后可以加载该图像并使用其中一个Python图像库来计算像素。虽然更复杂,但它应该提供一种计算像素的恒定时间方法。另外,还有一些库可以绘制位图,您可以将其加载到tkinter中进行视觉验证,但也可以直接进行像素计数。祝你好运 海龟在绘制分形图时找到面积,不太可能比在最终结果中一次性计算面积更有效。然而,绘制图像的复杂性不应影响计算黑色像素所需的时间,因为任何图像都必须访问和比较相同数量的像素-因此我认为您的问题在于您没有在此处共享的代码。你在哪里调用这个代码?而realSnowflake
函数中的snowflake
函数是什么?也许您应该分享一个最小的、可验证的和完整的示例,正如我在评论中所说的,在绘图过程中进行计算不太可能提高性能。正如您在问题中也说过的,当您绘制更复杂的分形时,性能似乎会变得更差,考虑到您提出的解决方案,这是没有意义的-因此可能会得出结论,问题出在代码的其余部分。但也许您的问题不是编码问题,而是通信问题。