#Project4 Dragon Curve Solution # Josh Fuerst 10/10/12 # # extended to generate dragon curve on th fly # extended to do bracketed L0 systems # Hoffmann October 2012 # # coordinate system left native # from PIL import Image from PIL import ImageDraw import math import random #TODO1 write function makePixelBlack def colorPixel(position,myImage,color): x = position[0] y = position[1] myImage.putpixel((x,y),color) #TODO2 write function flipAxis def flipAxis(pos,bounds): x = pos[0] y = pos[1] #flip y axis for simplicity y = (bounds[1]-1) - y return [x,y] #TODO3 write function checkBounds def checkBounds(currentPosition,bounds): x = currentPosition[0] y = currentPosition[1] if x >= bounds[0]: x -= 1 elif x < 0: x += 1 if y >= bounds[1]: y -= 1 elif y < 0: y += 1 return (x,y) #TODO4 write drawLine function def drawLineNSEW(direction,myImage,currentPosition,color,length): direction = direction.upper() if color == (-1,-1,-1): r = random.randint(0,255) g = random.randint(0,255) b = random.randint(0,255) color = (r,g,b) # x = currentPosition[0] y = currentPosition[1] drw = ImageDraw.Draw(myImage) if direction == 'S': drw.line((x,y,x,y+length),color) y += length elif direction == 'N': drw.line((x,y,x,y-length),color) y -= length elif direction == 'E': drw.line((x,y,x+length,y),color) x += length elif direction == 'W': drw.line((x,y,x-length,y),color) x -= length else: print ("Invalid Input direction: ",direction) return currentPosition = checkBounds((x,y),myImage.size) del drw return currentPosition def drawLineAngle(state, length, head, drw, color): x0 = state[0] y0 = state[1] dr = state[2]+head if dr > 180: dr -= 360 if dr < -180: dr += 360 al = math.radians(dr) cs = math.cos(al) sn = math.sin(al) x1 = x0 + length*sn y1 = y0 - length*cs drw.line((x0,y0,int(x1),int(y1)),color) return (x1,y1,dr) def mapDraw(str,img,gen): state = (img.size[0]/2, img.size[1]-10, 0) # turtle state stack = [] drw = ImageDraw.Draw(img) if gen<3: line = 20 elif gen<4: line = 9 elif gen<5: line = 6 else: line = 3 #print('string arg', str) for ch in str: if ch == 'F': state = drawLineAngle(state,line,0,drw,(0,128,32)) elif ch == '+': state = (state[0],state[1], state[2]+22) elif ch == '-': state = (state[0],state[1], state[2]-22) elif ch == '[': stack.append(state) elif ch == ']': state = stack.pop() else: print('bad character', ch) #img.show() del drw def Lsystem(gen, img): # this is a fixed L-system, no generality str = 'F' for g in range(gen): str = rewrite(str) mapDraw(str,img,g) return def rewrite(str): L = [] for ch in str: if ch == 'F': L.append('F[-F]F[+F][F]') elif ch == '[' or ch == ']' or ch == '+' or ch == '-': L.append(ch) str = "".join(x for x in L) #print(str) return str def dragon(gen, root): if gen==1: return root return dragon(gen-1,'R')+root+dragon(gen-1,'L') def cvtLR2NSEW(str): orient = 'N' result = ['N'] for ch in str: if orient == 'N': if ch == "L": orient = 'W' else: orient = 'E' elif orient == 'S': if ch == "L": orient = 'E' else: orient = 'W' elif orient == 'E': if ch == "L": orient = 'N' else: orient = 'S' elif orient == 'W': if ch == "L": orient = 'S' else: orient = 'N' else: print('ill formed LR string') result.append(orient) return "".join(x for x in result) def control(): print("type command --") print(" 0 - exit") print(" 1 - dragon") print(" 2 - L-system") cmd = eval(input(":: ")) if cmd == 1: gen = eval(input("number of folds: ")) if gen<1: gen=1 if gen>15: gen=15 elif cmd == 2: gen = eval(input("generation: ")) else: gen = 0 return cmd, gen #TODO5 write main function # dragon curve parameters for number of folding # [width, height, length, (x0, y0)] dragP = [[], # 0 [100,100,50,(25,75)], [100,100,25,(25,50)], [100,100,20,(20,40)], [150,150,20,(60,40)], [150,150,15,(100,40)], # 5 [300,300,10,(130,200)], [300,300,10,(130,200)], [300,300,10,(130,200)], [500,500,10,(160,300)], [500,500,10,(110,300)], # 10 [550,550, 8,(150,190)], [650,650, 6,(250,180)], [], [], [800,800, 3,(550,540)] ] def main(): # launch dialogue c,g = control() while c > 0: if c > 2: break if c==1: print("dragon curve,",g,"folds") drag = cvtLR2NSEW(dragon(g,'R')) width = dragP[g][0] height = dragP[g][1] length = dragP[g][2] position = dragP[g][3] img = Image.new('RGB',(width,height),'white') for move in drag: position = drawLineNSEW(move,img,position,(0,0,0),length) img.show() img.save("dragon_image_" + str(g) + ".jpeg") elif c==2: print("Lsys gen",g) img = Image.new('RGB',(300,400),'white') Lsystem(g, img) img.show() img.save("Lsys_image_" + str(g) + ".jpeg") else: print("done") c,g = control() #break print("image saved") main()