# -*- encoding: big5 -*- # # OR, -*- coding: big5 -*- // seems fine # # Sierpinski Triangle # # Author: # Jing-Shin Chang # # Emails: # jshin@csie.ncnu.edu.tw // shin@nlp.csie.ncnu.edu.tw // shin.jsc@gmail.com # # Last Update: # 2019/11/22 (v1.1.1) # # Revision: (v1.1) # - fix: pencolor: set before drawing instead of at beginning of A()/B() # - add: colors2 - RGB+YCM # - rename function as Sierpinski_Triangle() # - code clean up, rename sides as n_colors (v1.1.1) # # References: # https://zh.wikipedia.org/wiki/%E8%AC%9D%E7%88%BE%E8%B3%93%E6%96%AF%E5%9F%BA%E4%B8%89%E8%A7%92%E5%BD%A2 # """ 這條曲線以L系統來記述為: 變數: A , B 常數: + , - 公理: A 規則: A → B-A-B B → A+B+A A,B : 向前 - : 左轉60° + : 右轉60° """ #+1 from turtle import * # including mainloop #+2 from turtle import Turtle, Screen, mainloop from time import clock # TURTLEDEMO: # - Globals related to other modules must be declared in main when included by TURTLEDEMO #- t = Turtle() #- wn = Screen() #- wn.bgcolor("black") #- t.speed(0) # n_colors = 6 colors0 = ["yellow", "magenta", "yellow", "magenta", "yellow", "magenta"] colors1 = ["yellow", "magenta", "red", "magenta", "blue", "magenta"] colors2 = ["red", "yellow", "green", "cyan", "blue", "magenta"] n_colors = len(colors2) def gotoOrigin(x=0,y=0): t.penup() t.goto(x,y) t.pendown() def Sierpinski_Triangle(level=10, fwd=50): # A(level,fwd) # A=> 'B'-'A'-'B': bottom-left B first then top A, then bottom-right B B(level,fwd) # B=> 'A'+'B'+'A': bottom-left A first then top B, then bottom-right A def A(level,fwd,colors = colors2): if ( level <= 0 ): return "Done! with Level A(%d)" % level # t.pencolor(colors[level % n_colors]) #x will be overwritten by A/B(level-1) B(level-1,fwd) t.pencolor(colors[level % n_colors]) t.forward(fwd) t.left(60) print("f-",end='') A(level-1,fwd) t.pencolor(colors[level % n_colors]) t.forward(fwd) t.left(60) print("f-",end='') B(level-1,fwd) print("\nDone! with Level A(%d)" % level) return "Done! with Level A(%d)" % level def B(level,fwd,colors = colors2): if ( level <= 0 ): return "Done! with Level B(%d)" % level # t.pencolor(colors[level % n_colors]) #x will be overwritten by A/B(level-1) A(level-1,fwd) t.pencolor(colors[level % n_colors]) t.forward(fwd) t.right(60) print("f+",end='') B(level-1,fwd) t.pencolor(colors[level % n_colors]) t.forward(fwd) t.right(60) print("f+",end='') A(level-1,fwd) print("\nDone! with Level B(%d)" % level) return "Done! with Level B(%d)" % level def Tree(level, branch, x_root, y_root, fwd, angle, colors=colors2): import math as m if ( level <= 0 ): return "Done! with Tree Level(%d) Branch(%d)" % (level, branch) # configuration fwdScale = 0.8 angScale = 0.75 color = colors[(level+branch) % n_colors] # parameters for next level tree fwdNext = fwd*fwdScale angNext = angle*angScale # Left branch angleD = angle angleR = (angleD + 90) * m.pi/180.0 # adding 90deg since we are going north x_rootNext = x_root + fwd * m.cos(angleR) y_rootNext = y_root + fwd * m.sin(angleR) t.pencolor(color) gotoOrigin(x_root, y_root) t.left(angleD) t.forward(fwd) t.left(-angleD) Tree(level-1, -1, x_rootNext, y_rootNext, fwdNext, angNext, colors) # Middle branch angleD = 0 angleR = (angleD + 90) * m.pi/180.0 x_rootNext = x_root + fwd * m.cos(angleR) y_rootNext = y_root + fwd * m.sin(angleR) t.pencolor(color) gotoOrigin(x_root, y_root) # t.right(angleD) t.forward(fwd) # t.right(-angleD) Tree(level-1, 0, x_rootNext, y_rootNext, fwdNext, angNext, colors) # Right branch angleD = angle angleR = (- angleD + 90) * m.pi/180.0 x_rootNext = x_root + fwd * m.cos(angleR) y_rootNext = y_root + fwd * m.sin(angleR) t.pencolor(color) gotoOrigin(x_root, y_root) t.right(angleD) t.forward(fwd) t.right(-angleD) Tree(level-1, +1, x_rootNext, y_rootNext, fwdNext, angNext, colors) print("Done! with Tree Level(%d) Branch(%d)" % (level, branch)) return "Done! with Tree Level(%d) Branch(%d)" % (level, branch) def drawTree(level=3, branch=0, x_root=0, y_root=0, fwd=5, angle=60, colors=colors2): len_root = fwd*2 t.pencolor(colors[(level+branch) % n_colors]) # t.mode("standard") # ccw, heading East (0 deg) # t.home() # goto(0,0), heading East gotoOrigin(x_root,y_root) t.left(90) t.forward(len_root) Tree(level, branch, x_root, y_root=y_root+len_root, fwd=fwd, angle=angle, colors=colors) t.right(90) # resume angle for next drawTree() # # Try different parameter passing options # def main(): global t, wn t = Turtle() # Global must be declared in main when included in TURTLEDEMO wn = Screen() wn.bgcolor("black") # wn.bgcolor("white") t.speed(0) # doesn't look like speeding by this arg t0 = clock() gotoOrigin(-200,-100) t.hideturtle() # # Even-numbered levels [2,4,6,8] are increasingly larger with the same top A structure. # Odd-numbered levels have similar relationship (but in opposite orientation). # # Best demo level: 6 # if (False): Sierpinski_Triangle(level=2, fwd=5) Sierpinski_Triangle(level=4, fwd=5) Sierpinski_Triangle(level=6, fwd=5) Sierpinski_Triangle(level=8, fwd=5) else: Sierpinski_Triangle(level=0, fwd=5) drawTree(level=4, branch=0, x_root=0, y_root=-100, fwd=50, angle=80, colors=colors2) drawTree(level=3, branch=0, x_root=200, y_root=-200, fwd=50, angle=80, colors=colors2) drawTree(level=5, branch=0, x_root=-180, y_root=-200, fwd=50, angle=80, colors=colors2) t1 = clock() return "Done! in %.2f Seconds" % (t1-t0) if __name__ == "__main__": msg = main() print(msg) mainloop() # keep alive until closed by user # FIN