Кривая Гильберта (Пеано)


Первая такая кривая была построена Джузеппе Пеано в 1890. Тогда компьютеров еще не
было - алгоритм, наверное, вычерчивали по линейке. С питоном мы можем повторить опыт
гораздо быстрее и проще, причем сделать это можно сразу для разных порядков
рекурсии. Кое-какую логику пришлось подсмотреть у Вирта.

#
# Gilbert (Peano) lines
# Artix, 2011-01-22
# Niklaus Wirth algorithm
#

from Tkinter import *
from math import *
import sys

SIZE_X=600
SIZE_Y=500
STEP=6
 
class Turtle:
    x = 0
    y = 0
    a = 0
    pen = 1
    canvas = None
 
    def __init__(self,canvas):
        self.canvas = canvas
 
    def setpen(self,yes):
        self.pen = yes
 
    def rotate(self,g):
        self.a += g
 
    def move(self,sx,sy):
        self.x = sx
        self.y = sy
 
    def forward(self,length):
        new_x = self.x+cos(pi/180*self.a)*length
        new_y = self.y+sin(pi/180*self.a)*length
        cx = SIZE_X / 2
        cy = SIZE_Y / 2
        if self.pen:
            self.canvas.create_line(cx+self.x, cy-self.y, cx+new_x, cy-new_y,fill="green")
        self.x = new_x
        self.y = new_y
 
    def line(self,angle,length):
        new_x = self.x+cos(pi/180*angle)*length
        new_y = self.y+sin(pi/180*angle)*length
        cx = SIZE_X / 2
        cy = SIZE_Y / 2
        if self.pen:
            self.canvas.create_line(cx+self.x, cy-self.y, cx+new_x, cy-new_y,fill="green")
        self.x = new_x
        self.y = new_y
        

class Peano:
    
    turtle = None
 
    def __init__(self,turtle):
        self.turtle = turtle
        

    def make(self,level):
        self.turtle.move(0.5*STEP*pow(2,level)-1, -0.5*STEP*pow(2,level)-1)
        self.A(level)
        
    def A(self,i):
        if i>0:
            self.D(i-1)
            self.turtle.line(180,STEP)
            self.A(i-1)
            self.turtle.line(90,STEP)
            self.A(i-1)
            self.turtle.line(0,STEP)
            self.B(i-1)
     
    def B(self,i):
        if i>0:
            self.C(i-1)
            self.turtle.line(-90,STEP)
            self.B(i-1)
            self.turtle.line(0,STEP)
            self.B(i-1)
            self.turtle.line(90,STEP)
            self.A(i-1)

    def C(self,i):
        if i>0:
            self.B(i-1)
            self.turtle.line(0,STEP)
            self.C(i-1)
            self.turtle.line(-90,STEP)
            self.C(i-1)
            self.turtle.line(-180,STEP)
            self.D(i-1)

    def D(self,i):
        if i>0:
            self.A(i-1)
            self.turtle.line(90,STEP)
            self.D(i-1)
            self.turtle.line(180,STEP)
            self.D(i-1)
            self.turtle.line(270,STEP)
            self.C(i-1)

root = Tk()
root.title("Peano")
c = Canvas(root,width=SIZE_X,height=SIZE_Y,bg="black")
c.pack()
peano = Peano(Turtle(c))
peano.make(6)
 
root.mainloop()