diff options
Diffstat (limited to 'penroseunit.pas')
-rw-r--r-- | penroseunit.pas | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/penroseunit.pas b/penroseunit.pas new file mode 100644 index 0000000..eac0a69 --- /dev/null +++ b/penroseunit.pas @@ -0,0 +1,161 @@ +unit penroseunit; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Graphics, lowlevelunit, matheunit; + +type + tTeil = record + Drachen: boolean; + Ursprung: tExtPoint; + Richtung,Groesze: extended; + id: int64; + end; + + tPenrose = class + private + teile: array of tTeil; + function teilEcken(i: longint): tExtPointArray; + function id2color(id: int64): tColor; + public + constructor create(level: longint); + procedure Zeichnen(breite, hoehe: longint; Canvas: TCanvas); + end; + +implementation + +uses + math; + +constructor tPenrose.create(level: longint); +var + i,j: longint; +begin + setlength(teile,5); + for j:=0 to 4 do begin + teile[j].Drachen:=true; + teile[j].Ursprung:=extPoint(0,0); + teile[j].Richtung:=2*pi/5*j; + teile[j].Groesze:=1; + teile[j].id:=0; + end; + for i:=0 to level-1 do + for j:=length(teile)-1 downto 0 do begin + if teile[j].Richtung<0 then + teile[j].Richtung:=teile[j].Richtung + 2*pi; + if teile[j].Richtung>=2*pi then + teile[j].Richtung:=teile[j].Richtung - 2*pi; + if teile[j].Drachen then begin + setlength(teile,length(teile)+2); + teile[length(teile)-1].Drachen:=false; + teile[length(teile)-1].Ursprung:=teile[j].Ursprung; + teile[length(teile)-1].Richtung:=teile[j].Richtung + 36/180*pi; + teile[length(teile)-1].Groesze:=teile[j].Groesze / 2 / cos(36/180*pi); + teile[length(teile)-1].id:=2*teile[j].id; + teile[length(teile)-2].Drachen:=true; + teile[length(teile)-2].Ursprung:=teile[j].Ursprung + teile[j].Groesze * + extPoint(cos(teile[j].Richtung + 36/180*pi),sin(teile[j].Richtung + 36/180*pi)); + teile[length(teile)-2].Richtung:=teile[j].Richtung - 108/180*pi; + teile[length(teile)-2].Groesze:=teile[j].Groesze / 2 / cos(36/180*pi); + teile[length(teile)-2].id:=2*teile[j].id+1; + teile[j].Ursprung:=teile[j].Ursprung + teile[j].Groesze * + extPoint(cos(teile[j].Richtung - 36/180*pi),sin(teile[j].Richtung - 36/180*pi)); + teile[j].Richtung:=teile[j].Richtung + 108/180*pi; + teile[j].Groesze:=teile[j].Groesze / 2 / cos(36/180*pi); + teile[j].id:=2*teile[j].id+1; + end + else begin + setlength(teile,length(teile)+1); + teile[length(teile)-1].Drachen:=true; + teile[length(teile)-1].Ursprung:=teile[j].Ursprung; + teile[length(teile)-1].Richtung:=teile[j].Richtung; + teile[length(teile)-1].Groesze:=teile[j].Groesze / 2 / cos(36/180*pi); + teile[length(teile)-1].id:=2*teile[j].id+1; + teile[j].Ursprung:=teile[j].Ursprung + teile[j].Groesze * + extPoint(cos(teile[j].Richtung - 36/180*pi),sin(teile[j].Richtung - 36/180*pi)); + teile[j].Richtung:=teile[j].Richtung + 144/180*pi; + teile[j].Groesze:=teile[j].Groesze / 2 / cos(36/180*pi); + teile[j].id:=2*teile[j].id; + end; + end; +end; + +function tPenrose.teilEcken(i: longint): tExtPointArray; +var + j: longint; +begin + setLength(result,4); + result[0]:=extPoint(0,0); + result[1]:=extPoint(cos(36/180*pi),sin(36/180*pi)); + result[2]:=extPoint(cos(36/180*pi) + (2*byte(teile[i].Drachen)-1)*sin(36/180*pi)*tan(18/180*pi),0); + result[3]:=extPoint(cos(-36/180*pi),sin(-36/180*pi)); + for j:=0 to 3 do + result[j]:=teile[i].Groesze * rotationsMatrix(teile[i].Richtung) * result[j] + teile[i].Ursprung; +end; + +function tPenrose.id2color(id: int64): tColor; +const + steps = 256; +var + farben: array[0..6] of tExt3dPoint; + r: tExt3dPoint; +var + i: integer; +begin + for i:=0 to 2 do + farben[2*i]:=ext3dPoint($ff*byte(i=2),$ff*byte(i=1),$ff*byte(i=0)); + for i:=0 to 2 do + farben[7-2*i]:=ext3dPoint($ff,$ff,$ff)-farben[2*i]; + farben[6]:=farben[0]; + id:=id mod (steps*(length(farben)-1)); + i:=id div steps; + r:=(id/steps - i) * farben[i+1] + (1+i-id/steps) * farben[i]; + result:=round(r['x']) + (round(r['y']) shl 8) + (round(r['z']) shl 16) +end; + +procedure tPenrose.Zeichnen(breite, hoehe: longint; Canvas: TCanvas); +var + lo,ru: tExtPoint; + ecken: tExtPointArray; + i,j: longint; + c: char; + Groesze: extended; + Verschiebung: tExtPoint; + points: array of tPoint; +begin + lo:=extPoint(0,0); + ru:=lo; + for i:=0 to length(teile)-1 do begin + ecken:=teilEcken(i); + for j:=0 to length(ecken)-1 do + for c:='x' to 'y' do begin + lo[c]:=min(lo[c],ecken[j][c]); + ru[c]:=max(ru[c],ecken[j][c]); + end; + end; + Groesze:=min( + (breite-1) / (ru['x']-lo['x']), + (hoehe-1) / (ru['y']-lo['y']) + ); + Verschiebung:=-Groesze * lo; + + canvas.brush.Color:=$ffffff; + canvas.rectangle(-10,-10,breite+10,hoehe+10); + for i:=0 to length(teile)-1 do begin + ecken:=teilEcken(i); + setLength(points,length(ecken)); + for j:=0 to length(ecken)-1 do begin + ecken[j]:=Verschiebung + Groesze * ecken[j]; + points[j]:=point(round(ecken[j]['x']),round(ecken[j]['y'])); + end; + canvas.brush.Color:=id2color(teile[i].id); + canvas.pen.Color:=canvas.brush.Color; + canvas.Polygon(points); + end; +end; + +end. + |