summaryrefslogtreecommitdiff
path: root/penroseunit.pas
diff options
context:
space:
mode:
Diffstat (limited to 'penroseunit.pas')
-rw-r--r--penroseunit.pas161
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.
+