Кривая Серпиньского


Еще одна интересная кривая, называемая кривая Серпиньского.
В моем примере приведена кривая 4-го порядка:

#
# Serpinski lines
# Artix, 2011-01-22
# Niklaus Wirth algorithm
#

from Tkinter import *
from math import *
import sys

SIZE_X=600
SIZE_Y=500
STEP=8
 
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 Serpin:
    
    turtle = None
 
    def __init__(self,turtle):
        self.turtle = turtle
        

    def make(self,level):
        self.turtle.move(-1.6*STEP*pow(2,level)-1, -1.6*STEP*pow(2,level)-1)
        self.A(level)
        self.turtle.line(-315,STEP)
        self.B(level)
        self.turtle.line(-225,STEP)
        self.C(level)
        self.turtle.line(-135,STEP)
        self.D(level)
        self.turtle.line(-45,STEP)
        
    def A(self,i):
        if i>0:
            self.A(i-1)
            self.turtle.line(45,STEP)
            self.B(i-1)
            self.turtle.line(0,2*STEP)
            self.D(i-1)
            self.turtle.line(-45,STEP)
            self.A(i-1)
     
    def B(self,i):
        if i>0:
            self.B(i-1)
            self.turtle.line(135,STEP)
            self.C(i-1)
            self.turtle.line(90,2*STEP)
            self.A(i-1)
            self.turtle.line(45,STEP)
            self.B(i-1)

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

    def D(self,i):
        if i>0:
            self.D(i-1)
            self.turtle.line(-45,STEP)
            self.A(i-1)
            self.turtle.line(-90,2*STEP)
            self.C(i-1)
            self.turtle.line(-135,STEP)
            self.D(i-1)

root = Tk()
root.title("Serpinski")
c = Canvas(root,width=SIZE_X,height=SIZE_Y,bg="black")
c.pack()
s = Serpin(Turtle(c))
s.make(4)
root.mainloop()

На Википедии, кстати, приводится другая реализация кривой
Серпиньского - без использования черепашьей графики.
Цитирую пример на PHP:

<?php

set_time_limit(5);

$i = 6;		// Количество итераций
$xy = 1500;	// Размер стороны картинки

$img = imagecreatetruecolor($xy, $xy);

$black = imagecolorallocate($img, 0, 0, 0);
$white = imagecolorallocate($img, 255, 255, 255);

$cycle = 0;
drawCarpet(0, 0, $xy, $xy, $i);
function drawCarpet($a, $b, $c, $d, $n) {
	global $img, $white, $cycle;
	$cycle++;

	if($n <= 0) return;

	$a1 = 2 * $a / 3 + $c / 3;
	$c1 = $a / 3 + 2 * $c / 3;
	$b1 = 2 * $b / 3 + $d / 3;
	$d1 = $b / 3 + 2 * $d / 3;

	imagefilledrectangle($img, $a1, $b1, $c1, $d1, $white);

	drawCarpet($a, $b, $a1, $b1, $n - 1);
	drawCarpet($a1, $b, $c1, $b1, $n - 1);
	drawCarpet($c1, $b, $c, $b1, $n - 1);

	drawCarpet($a, $b1, $a1, $d1, $n - 1);
	drawCarpet($c1, $b1, $c, $d1, $n - 1);

	drawCarpet($a, $d1, $a1, $d, $n - 1);
	drawCarpet($a1, $d1, $c1, $d, $n - 1);
	drawCarpet($c1, $d1, $c, $d, $n - 1);
}

imagefilledrectangle($img, 0, 0, (strlen($cycle) * 9) , 16, $white);
imagestring($img,21,0,0,$cycle,$black);

header('Content-Type: image/png');
imagepng($img);

?>