2 回答

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超3個贊
另一個三角形內(nèi)的“中點(diǎn)三角形”由一個三角形定義,該三角形的坐標(biāo)是周圍三角形各邊的中點(diǎn):
因此,對于三角形的每條線/邊,計(jì)算中點(diǎn):
def lineMidPoint( p1, p2 ):
""" Return the mid-point on the line p1 to p2 """
# Ref: https://en.wikipedia.org/wiki/Midpoint
x1, y1 = p1
x2, y2 = p2
x_mid = round( ( x1 + x2 ) / 2 )
y_mid = round( ( y1 + y2 ) / 2 )
return ( x_mid, y_mid )
在您的情況下,這將被多次調(diào)用p1,p2并p3生成 3 個“角”三角形:
# midpoints of each size
mid_p1 = lineMidPoint( p1, p2 )
mid_p2 = lineMidPoint( p2, p3 )
mid_p3 = lineMidPoint( p3, p1 )
# The 3 "corner" triangles
upper_triangle = [ mid_p1, p2, mid_p2 ]
left_triangle = [ p1, mid_p1, mid_p3 ]
right_triangle = [ mid_p3, mid_p2, p3 ]
# The inner triangle (for the sake of completeness)
inner_triangle = [ mid_p1, mid_p2, mid_p3 ]
然后,您需要將其包裝在遞歸調(diào)用中,并進(jìn)行某種深度救助。
就像是:
def drawTriangle( window, colour, points, bailout=5 ):
if ( bailout > 0 ):
# Calculate the 3 inner corner-triangles
p1, p2, p3 = points
mid_p1 = lineMidPoint( p1, p2 )
mid_p2 = lineMidPoint( p2, p3 ) # mid-point of each side
mid_p3 = lineMidPoint( p3, p1 )
# triangles between the original corners, and new mid-points
upper_triangle = [ mid_p1, p2, mid_p2 ]
left_triangle = [ p1, mid_p1, mid_p3 ]
right_triangle = [ mid_p3, mid_p2, p3 ]
drawTriangle( window, colour, upper_triangle, bailout-1 )
drawTriangle( window, colour, left_triangle, bailout-1 )
drawTriangle( window, colour, right_triangle, bailout-1 )
else:
pygame.draw.lines( window, colour, True, points ) # draw triangle
我認(rèn)為這畫出了一個謝爾賓斯基三角形

TA貢獻(xiàn)1891條經(jīng)驗(yàn) 獲得超3個贊
我不確定爭論的目的degree是什么,也許是為了限制遞歸深度?
這是一個基于您的問題的示例,使用遞歸 sierpinski 函數(shù):
import pygame
def draw_triangle(p1, p2, p3, color, line_width, screen):
pygame.draw.polygon(screen, color, [p1, p2, p3], line_width)
def midpoint(p1, p2):
""" Return the mid-point on the line p1 to p2 """
x1, y1 = p1
x2, y2 = p2
x_mid = (x1 + x2) // 2
y_mid = (y1 + y2) // 2
return (x_mid, y_mid)
def sierpinski(degree, p1, p2, p3, color, line_width, screen):
# p1 → bottom left, p2 → bottom right, p3 → top
# recursive function so check for exit condition first
if abs(p1[0] - p2[0]) <= 2 and abs(p2[0] - p3[0]) <= 2 and abs(p1[0] - p3[0]) <= 2:
return
draw_triangle(p1, p2, p3, color, line_width, screen)
a = midpoint(p1, p2)
b = midpoint(p1, p3)
c = midpoint(p2, p3)
# skip the centre triangle
sierpinski(degree, p1, a, b, color, line_width, screen)
sierpinski(degree, p2, a, c, color, line_width, screen)
sierpinski(degree, p3, b, c, color, line_width, screen)
height = 640
width = 640
pygame.init()
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
pygame.display.set_caption("Sierpiński")
clock = pygame.time.Clock()
update_screen = True
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.VIDEORESIZE:
width, height = event.dict["size"]
screen = pygame.display.set_mode((width, height), pygame.RESIZABLE)
update_screen = True
if update_screen:
# only draw the screen when required
screen.fill(pygame.color.Color("white"))
# determine initial points based on window size
p1 = [5, height - 5]
p2 = [(width - 10) // 2, 5]
p3 = [width - 5, height - 5]
sierpinski(None, p1, p2, p3, pygame.color.Color("black"), 1, screen)
pygame.display.update()
update_screen = False
# limit framerate
clock.tick(30)
pygame.quit()
為了簡潔起見,我刪除了顏色處理,而是使用pygame.color.Color接受其構(gòu)造函數(shù)的字符串參數(shù)。我還使用整數(shù)除法//來代替round(…).
根據(jù)遞歸函數(shù)的深度或復(fù)雜性,您可以重新繪制每一幀,但我想展示一個限制示例,以防函數(shù)復(fù)雜性增加。最后,我最近一直在調(diào)整屏幕大小,這似乎與一次繪制有關(guān),所以我也將其包括在內(nèi)。
編輯:我修改了該sierpinski函數(shù)以支持degree指定遞歸 dep 的參數(shù)
def sierpinski(degree, p1, p2, p3, color, line_width, screen):
# p1 → bottom left, p2 → bottom right, p3 → top
# recursive function so check for exit condition first
if degree is None:
if abs(p1[0] - p2[0]) <= 2 and abs(p2[0] - p3[0]) <= 2 and abs(p1[0] - p3[0]) <= 2:
return
else:
if degree == 0:
return
else:
degree -= 1
…
然后我添加了一些事件處理,以便可以使用鼠標(biāo)滾輪來增加和減少度數(shù),這顯示在標(biāo)題欄上:
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 4: # wheel up
if degree is None:
degree = 8
else:
degree += 1
if degree > maximum_degree:
degree = maximum_degree
update_screen = True
elif event.button == 5: # wheel down
if degree is None:
degree = 3
else:
degree -= 1
if degree < minimum_degree:
degree = minimum_degree
update_screen = True
…
添加回答
舉報(bào)