summaryrefslogtreecommitdiff
path: root/unit1.pas
diff options
context:
space:
mode:
Diffstat (limited to 'unit1.pas')
-rw-r--r--unit1.pas1125
1 files changed, 1125 insertions, 0 deletions
diff --git a/unit1.pas b/unit1.pas
new file mode 100644
index 0000000..f098124
--- /dev/null
+++ b/unit1.pas
@@ -0,0 +1,1125 @@
+unit Unit1;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
+ ComCtrls, vecMath, Math;
+
+type
+
+ { TForm1 }
+
+ TForm1 = class(TForm)
+ Button1: TButton;
+ Button2: TButton;
+ Button3: TButton;
+ Button4: TButton;
+ CheckBox1: TCheckBox;
+ Image1: TImage;
+ Image2: TImage;
+ Image3: TImage;
+ Label1: TLabel;
+ ProgressBar1: TProgressBar;
+ RadioGroup1: TRadioGroup;
+ ZeichenTimer: TTimer;
+ procedure FormActivate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure ZeichenTimerTimer(Sender: TObject);
+ procedure CheckBox1Click(Sender: TObject);
+ procedure CheckBox2Click(Sender: TObject);
+ procedure Image3MouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure Image3MouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+ procedure Image3MouseMove(Sender: TObject; Shift: TShiftState; X,
+ Y: Integer);
+ procedure FormResize(Sender: TObject);
+ procedure RadioGroup1Click(Sender: TObject);
+ procedure Button1Click(Sender: TObject);
+ procedure Button2Click(Sender: TObject);
+ procedure Button3Click(Sender: TObject);
+ procedure Button4Click(Sender: TObject);
+ private
+
+ public
+ Dim,Koerp: Integer;
+ Kanten: array of TPoint;
+ Ecken: array of TMatrix;
+ ProjektionL,
+ ProjektionR,
+ Rotation,
+ Beschl,Rot: TMatrix;
+ Zoom: extended;
+
+ procedure Drehen;
+ procedure BeschlBelegen;
+ procedure RotationInitialisieren;
+ procedure ProjektionenBelegen;
+ procedure KoerperErzeugen;
+ procedure Zeichnen;
+ procedure KantenZeichnen(Pte: array of TPoint; PZ: array of extended; drawZ: boolean; drawTo: TCanvas);
+ procedure drawColoredLine(wo: TCanvas; X1,Y1: Integer; Z1: extended; X2,Y2: Integer; Z2: Extended);
+ function farbVerlauf(x: Extended): TColor;
+ procedure SetZoom;
+ end;
+
+var
+ Form1: TForm1;
+
+implementation
+
+{$R *.lfm}
+
+uses
+ unit2;
+
+procedure TForm1.FormActivate(Sender: TObject);
+begin
+ Dim:=3;
+ Koerp:=-1;
+ RadioGroup1.OnClick(Sender);
+end;
+
+procedure TForm1.FormDestroy(Sender: TObject);
+var i: integer;
+begin
+ for i:=0 to length(Ecken)-1 do
+ Ecken[i].destroy;
+ ProjektionL.destroy;
+ ProjektionR.destroy;
+ Rotation.destroy;
+ Rot.destroy;
+ Beschl.destroy;
+end;
+
+procedure TForm1.FormCreate(Sender: TObject);
+begin
+ setlength(Ecken,0);
+ ProjektionL:=TMatrix.create;
+ ProjektionR:=TMatrix.create;
+ Rotation:=TMatrix.create;
+ Rot:=TMatrix.create;
+ Beschl:=TMatrix.create;
+end;
+
+procedure TForm1.ZeichenTimerTimer(Sender: TObject);
+var i: integer;
+begin
+ Zeichnen;
+ for i:=0 to ZeichenTimer.Interval div 10 do
+ begin
+ Drehen;
+ BeschlBelegen;
+ end;
+end;
+
+procedure TForm1.ProjektionenBelegen;
+var z,s: integer;
+ tmp: TMatrix;
+const alpha = 2*pi/360 * 10;
+begin
+ ProjektionL.destroy;
+ ProjektionL:=TMatrix.create;
+ ProjektionL.xdim:=4;
+ ProjektionL.ydim:=3;
+ for z:=0 to 2 do
+ for s:=0 to 3 do
+ ProjektionL.a[z,s]:=byte(z=s);
+
+ ProjektionR.destroy;
+ ProjektionR:=TMatrix.create;
+ ProjektionR.xdim:=4;
+ ProjektionR.ydim:=4;
+ ProjektionR.assign0;
+ ProjektionR.a[0,0]:=cos(alpha);
+ ProjektionR.a[0,2]:=sin(alpha);
+ ProjektionR.a[3,0]:=-sin(alpha);
+ ProjektionR.a[3,2]:=cos(alpha);
+ ProjektionR.a[1,1]:=1;
+ ProjektionR.a[2,3]:=1;
+
+ ProjektionR._times(ProjektionL);
+
+ tmp:=TMatrix.create;
+ tmp.xdim:=dim;
+ tmp.ydim:=4;
+ for s:=0 to dim-1 do
+ for z:=0 to 3 do
+ tmp.a[z,s]:=byte(z=s);
+
+ ProjektionR.times_(tmp);
+ ProjektionL.times_(tmp);
+end;
+
+procedure TForm1.KoerperErzeugen;
+function spiegleKante(Knr,Enr: integer; N: TMatrix): integer;
+var Es: array[boolean] of integer;
+ i: integer;
+ M,O: TMatrix;
+ bol,nk: boolean;
+ tmp: extended;
+begin
+ M:=TMatrix.create;
+ O:=TMatrix.create;
+ Es[false]:=Kanten[Knr].x;
+ Es[true]:=Kanten[Knr].y;
+ for bol:=false to true do begin
+ M.assign(Ecken[Enr]);
+ M.minus(Ecken[Es[bol]]);
+ M.transp;
+ M.times_(N);
+ tmp:=M.a[0,0];
+ M.assign(N);
+ M.times(2*tmp);
+ M.plus(Ecken[Es[bol]]);
+ tmp:=1;
+ for i:=0 to length(Ecken)-1 do begin
+ O.assign(M);
+ O.minus(Ecken[i]);
+ tmp:=min(tmp,O.len);
+ end;
+ if tmp>1e-6 then begin
+ Es[bol]:=length(Ecken);
+ setlength(Ecken,length(Ecken)+1);
+ Ecken[Es[bol]]:=TMatrix.create;
+ Ecken[Es[bol]].assign(M);
+ end
+ else begin
+ for i:=0 to length(Ecken)-1 do begin
+ O.assign(M);
+ O.minus(Ecken[i]);
+ if O.len <=1.1e-6 then begin
+ Es[bol]:=i;
+ break;
+ end;
+ end;
+ end;
+ end;
+ result:=-1;
+ nk:=true;
+ for i:=0 to length(kanten)-1 do
+ nk:=nk and ((Kanten[i].x<>Es[false]) or (Kanten[i].y<>Es[true]))
+ and ((Kanten[i].y<>Es[false]) or (Kanten[i].x<>Es[true]));
+ if nk then begin
+ setlength(Kanten,length(Kanten)+1);
+ Kanten[length(Kanten)-1].x:=Es[false];
+ Kanten[length(Kanten)-1].y:=Es[true];
+ result:=length(Kanten)-1;
+ end
+ else
+ for i:=0 to length(kanten)-1 do begin
+ if (Kanten[i].x=Es[false]) and (Kanten[i].y=Es[true]) then result:=i;
+ if (Kanten[i].y=Es[false]) and (Kanten[i].x=Es[true]) then result:=i;
+ end;
+ M.destroy;
+ O.destroy;
+end;
+
+var ral: array of array[boolean] of TMatrix;
+
+procedure rotierePunkt(Quelle: TMatrix; Achse: integer; umNull: boolean; var Ziel: TMatrix);
+var tang,otang: TMatrix;
+ tmp: extended;
+begin
+ Ziel.assign(Quelle);
+ if ral[Achse,true].len<1e-6 then exit;
+ if not umNull then Ziel.minus(ral[Achse,false]);
+ tang:=TMatrix.create;
+ otang:=TMatrix.create;
+ tang.assign(Ziel);
+ Ziel.transp;
+ Ziel.times_(ral[Achse,true]);
+ tmp:=Ziel.a[0,0];
+ Ziel.assign(ral[Achse,true]);
+ Ziel.times(tmp/sqr(ral[Achse,true].len));
+ tang.minus(Ziel);
+ if tang.len<1e-6 then begin
+ if not umNull then Ziel.plus(ral[Achse,false]);
+ tang.destroy;
+ otang.destroy;
+ exit;
+ end;
+ otang.assign(ral[Achse,true]);
+ otang.cross(tang);
+ otang.times(tang.len/otang.len*sin(ral[Achse,true].len));
+ tang.times(cos(ral[Achse,true].len));
+ Ziel.plus(tang);
+ Ziel.plus(otang);
+ if not umNull then Ziel.plus(ral[Achse,false]);
+ tang.destroy;
+ otang.destroy;
+end;
+
+procedure rotiereKante(Kante,Achse: integer);
+var M,N: TMatrix;
+ Es: array[boolean] of integer;
+ bol,gef: boolean;
+ i: integer;
+begin
+ M:=TMatrix.create;
+ N:=TMatrix.create;
+ Es[false]:=Kanten[Kante].x;
+ Es[true]:=Kanten[Kante].y;
+ for bol:=false to true do begin
+ rotierePunkt(Ecken[Es[bol]],Achse,false,M);
+ gef:=false;
+ for i:=0 to length(Ecken)-1 do begin
+ N.assign(M);
+ N.minus(Ecken[i]);
+ if N.len<1e-6 then begin
+ gef:=true;
+ Es[bol]:=i;
+ break;
+ end;
+ end;
+ if not gef then begin
+ setlength(Ecken,length(Ecken)+1);
+ Ecken[length(Ecken)-1]:=TMatrix.create;
+ Ecken[length(Ecken)-1].assign(M);
+ Es[bol]:=length(Ecken)-1;
+ end;
+ end;
+ gef:=false;
+ for i:=0 to length(Kanten)-1 do
+ gef:=gef or ((Kanten[i].x=Es[false]) and (Kanten[i].y=Es[true])) or
+ ((Kanten[i].y=Es[false]) and (Kanten[i].x=Es[true]));
+ if not gef then begin
+ setlength(Kanten,length(Kanten)+1);
+ Kanten[length(Kanten)-1].x:=Es[false];
+ Kanten[length(Kanten)-1].y:=Es[true];
+ end;
+
+ M.destroy;
+ N.destroy;
+end;
+
+var skl: array of TPoint;
+ i,j,k: integer;
+ M,N: TMatrix;
+ nsa,bol: boolean;
+ b,d,f,t,phi,tmp: extended;
+begin
+ case Koerp of
+ 0:
+ begin
+ if dim<>3 then exit;
+// b:=3/22*(7-sqrt(5)); // kurze Seite (lange Seite=1)
+ d:=3*sqrt((5-sqrt(5))/20); // kurze Diagonale
+ f:=1/11*sqrt((470+156*sqrt(5))/5); // lange Diagonale
+
+ Setlength(Ecken,16);
+ for i:=0 to length(Ecken)-1 do begin
+ Ecken[i]:=TMatrix.create;
+ Ecken[i].xdim:=1;
+ Ecken[i].ydim:=dim;
+ end;
+ Setlength(Kanten,35);
+ for i:=0 to length(Kanten)-1 do
+ Kanten[i].x:=-1;
+ Ecken[0].a[0,0]:=0;
+ Ecken[0].a[1,0]:=0;
+ Ecken[0].a[2,0]:=sqrt(1-sqr(d*cos(pi/5)/sin(2*pi/5))); // die berechnete Höhe
+ for i:=0 to 4 do begin
+ Ecken[i+1].a[0,0]:=cos(2*pi/5*i)*d*cos(pi/5)/sin(2*pi/5);
+ Ecken[i+1].a[1,0]:=sin(2*pi/5*i)*d*cos(pi/5)/sin(2*pi/5);
+ Ecken[i+1].a[2,0]:=0;
+ end;
+ M:=TMatrix.create;
+ M.xdim:=1;
+ M.ydim:=dim;
+ N:=TMatrix.create;
+ N.xdim:=1;
+ N.ydim:=dim;
+ for i:=0 to 4 do begin
+ Ecken[i+6].assign(Ecken[i+1]);
+ Ecken[i+6].plus(Ecken[(i+1) mod 5 +1]);
+ Ecken[i+6].times(-1/2);
+ Ecken[i+6].plus(Ecken[0]);
+ Ecken[i+6].times(-f/Ecken[i+6].len);
+ Ecken[i+6].plus(Ecken[0]);
+ Ecken[i+11].assign(Ecken[0]);
+ M.assign(Ecken[i+6]);
+ Ecken[i+11].times(0.5);
+ M.times(0.5);
+ Ecken[i+11].plus(M);
+ M.assign(Ecken[i+1]);
+ M.minus(Ecken[0]);
+ N.assign(Ecken[(i+1) mod 5+1]);
+ N.minus(Ecken[0]);
+ M.cross(N);
+ M.times(3/M.len);
+ Ecken[i+11].plus(M);
+ end;
+ for i:=0 to 4 do begin
+ Kanten[i].x:=0;
+ Kanten[i].y:=i+1;
+ Kanten[i+5].x:=i+1;
+ Kanten[i+5].y:=i+6;
+ Kanten[i+10].x:=i+6;
+ Kanten[i+10].y:=(i+1) mod 5 +1;
+ Kanten[i+15].x:=i+11;
+ Kanten[i+15].y:=0;
+ Kanten[i+20].x:=i+11;
+ Kanten[i+20].y:=i+1;
+ Kanten[i+25].x:=i+11;
+ Kanten[i+25].y:=i+6;
+ Kanten[i+30].x:=i+11;
+ Kanten[i+30].y:=(i+1) mod 5 +1;
+ end;
+
+ setlength(skl,5);
+ for i:=0 to 4 do begin
+ skl[i].x:=i+5;
+ skl[i].y:=(i+4) mod 5+10;
+ end;
+
+ repeat
+ nsa:=false;
+ i:=length(skl)-1;
+ while i>=0 do begin
+ M.assign(Ecken[Kanten[skl[i].x].x]);
+ M.minus(Ecken[Kanten[skl[i].x].y]);
+ N.assign(Ecken[Kanten[skl[i].y].x]);
+ N.minus(Ecken[Kanten[skl[i].y].y]);
+ N.cross(M);
+ N.times(1/N.len);
+ j:=length(skl)-1;
+ while j>=0 do begin
+ setlength(skl,length(skl)+1);
+ skl[length(skl)-1].x:=spiegleKante(skl[j].x,Kanten[skl[i].x].x,N);
+ skl[length(skl)-1].y:=spiegleKante(skl[j].y,Kanten[skl[i].x].x,N);
+ bol:=false;
+ for k:=0 to length(skl)-2 do
+ bol:=bol or ((skl[length(skl)-1].x=skl[k].x) and
+ (skl[length(skl)-1].y=skl[k].y)) or
+ ((skl[length(skl)-1].y=skl[k].x) and
+ (skl[length(skl)-1].x=skl[k].y));
+ if bol then setlength(skl,length(skl)-1)
+ else nsa:=true;
+ dec(j);
+ end;
+ dec(i);
+ end;
+ until not nsa;
+
+ for i:=0 to length(skl)-1 do begin
+ M.assign(Ecken[Kanten[skl[i].x].x]);
+ M.minus(Ecken[Kanten[skl[i].x].y]);
+ N.assign(Ecken[Kanten[skl[i].y].x]);
+ N.minus(Ecken[Kanten[skl[i].y].y]);
+ N.cross(M);
+ N.times(1/N.len);
+ j:=length(Kanten)-1;
+ while j>=0 do begin
+ spiegleKante(j,Kanten[skl[i].x].x,N);
+ dec(j);
+ end;
+ end;
+ M.destroy;
+ N.destroy;
+ end;
+ 1:
+ begin
+ if dim<>3 then exit;
+ phi:=(sqrt(5)+1)/2;
+ t:=1/12*(power(44+12*phi*(9+sqrt(81*phi-15)),1/3)+power(44+12*phi*(9-sqrt(81*phi-15)),1/3)-4);
+ b:=2*(1-2*sqr(t))/(1+2*t); // kurze Seite (lange Seite=1)
+ d:=2*(1-2*sqr(t)); // Diagonale
+ f:=sqrt(b*(b+d)); // (ganz) kurze Diagonale
+
+ Setlength(Ecken,21);
+ for i:=0 to length(Ecken)-1 do begin
+ Ecken[i]:=TMatrix.create;
+ Ecken[i].xdim:=1;
+ Ecken[i].ydim:=dim;
+ end;
+ Setlength(Kanten,45);
+ for i:=0 to length(Kanten)-1 do
+ Kanten[i].x:=-1;
+ Ecken[0].a[0,0]:=0;
+ Ecken[0].a[1,0]:=0;
+ Ecken[0].a[2,0]:=sqrt(1-sqr(d*cos(pi/5)/sin(2*pi/5))); // die berechnete Höhe
+ for i:=0 to 4 do begin
+ Ecken[i+1].a[0,0]:=cos(2*pi/5*i)*d*cos(pi/5)/sin(2*pi/5);
+ Ecken[i+1].a[1,0]:=sin(2*pi/5*i)*d*cos(pi/5)/sin(2*pi/5);
+ Ecken[i+1].a[2,0]:=0;
+ end;
+ M:=TMatrix.create;
+ M.xdim:=1;
+ M.ydim:=dim;
+ N:=TMatrix.create;
+ N.xdim:=1;
+ N.ydim:=dim;
+ for i:=0 to 4 do begin
+ Ecken[i+6].assign(Ecken[i+1]);
+ Ecken[i+6].plus(Ecken[(i+1) mod 5 +1]);
+ Ecken[i+6].times(1/2);
+ Ecken[i+6].minus(Ecken[0]);
+ Ecken[i+6].times(sqrt(sqr(b)-sqr((d-b)/2))/Ecken[i+6].len);
+ N.assign(Ecken[(i+1) mod 5 +1]);
+ N.minus(Ecken[i+1]);
+ N.times((d-b)/2/N.len);
+ Ecken[i+6].plus(N);
+ Ecken[i+6].plus(Ecken[i+1]);
+ N.times(b/N.len);
+ Ecken[i+11].assign(Ecken[i+6]);
+ Ecken[i+11].plus(N);
+ M.assign(Ecken[i+6]);
+ M.plus(Ecken[i+11]);
+ M.times(0.3);
+ Ecken[i+16].assign(Ecken[0]);
+ Ecken[i+16].times(0.7);
+ Ecken[i+16].plus(M);
+ M.assign(Ecken[i+1]);
+ M.minus(Ecken[0]);
+ N.assign(Ecken[(i+1) mod 5 +1]);
+ N.minus(Ecken[0]);
+ M.cross(N);
+ M.times(3/M.len);
+ Ecken[i+16].Plus(M);
+ end;
+ for i:=0 to 4 do begin
+ Kanten[i].x:=0;
+ Kanten[i].y:=i+1;
+ Kanten[i+5].x:=i+1;
+ Kanten[i+5].y:=i+6;
+ Kanten[i+10].x:=i+6;
+ Kanten[i+10].y:=i+11;
+ Kanten[i+15].x:=i+11;
+ Kanten[i+15].y:=(i+1) mod 5 +1;
+ Kanten[i+20].x:=0;
+ Kanten[i+20].y:=i+16;
+ Kanten[i+25].x:=i+1;
+ Kanten[i+25].y:=i+16;
+ Kanten[i+30].x:=i+6;
+ Kanten[i+30].y:=i+16;
+ Kanten[i+35].x:=i+11;
+ Kanten[i+35].y:=i+16;
+ Kanten[i+40].x:=(i+1) mod 5 +6;
+ Kanten[i+40].y:=i+16;
+ end;
+
+ setlength(ral,2);
+ for i:=0 to 3 do
+ ral[i div 2,odd(i)]:=TMatrix.create;
+ ral[0,false].assign(Ecken[0]); // die 5er-Symmetrieachse
+ ral[0,true].assign(Ecken[0]);
+ ral[0,true].times(2*pi/5/ral[0,true].len);
+
+ ral[1,false].assign(Ecken[6]); // die 3er-Symmetrieachse
+ tmp:=arccos((sqrt(3)/6*f)/sqrt(sqr(b)-sqr(f/2))); // Kippwinkel der Rotationsachse gegenüber Flächennormale
+ ral[1,true].assign(Ecken[1]);
+ ral[1,true].plus(Ecken[11]);
+ ral[1,true].times(-1/2);
+ ral[1,true].plus(Ecken[6]);
+ ral[1,true].times(1/ral[1,true].len);
+ N.assign(Ecken[1]);
+ N.minus(Ecken[11]);
+ N.cross(ral[1,true]);
+ N.times(1/N.len);
+ ral[1,true].times(sin(tmp));
+ N.times(cos(tmp));
+ ral[1,true].plus(N);
+ ral[1,true].times(2*pi/3/ral[1,true].len);
+
+ repeat
+ nsa:=false;
+ i:=length(ral)-1;
+ while i>=0 do begin
+ j:=length(ral)-1;
+ while j>=0 do begin
+ setlength(ral,length(ral)+1);
+ for bol:=false to true do begin
+ ral[length(ral)-1,bol]:=TMatrix.create;
+ rotierePunkt(ral[j,bol],i,bol,ral[length(ral)-1,bol]);
+ end;
+ bol:=false;
+ for k:=0 to length(ral)-2 do begin
+ M.assign(ral[k,false]);
+ M.minus(ral[length(ral)-1,false]);
+ if M.len<1e-6 then begin
+ M.assign(ral[k,true]);
+ M.minus(ral[length(ral)-1,true]);
+ if M.len<1e-6 then begin
+ bol:=true;
+ break;
+ end;
+ end;
+ end;
+ if bol then begin
+ ral[length(ral)-1,false].destroy;
+ ral[length(ral)-1,true].destroy;
+ setlength(ral,length(ral)-1);
+ end
+ else nsa:=true;
+ dec(j);
+ end;
+ dec(i);
+ end;
+ until not nsa;
+
+ for i:=0 to length(ral)-1 do begin
+ j:=length(Kanten)-1;
+ while j>=0 do begin
+ rotiereKante(j,i);
+ dec(j);
+ end;
+ end;
+
+ for i:=0 to 2*length(ral)-1 do
+ ral[i div 2,odd(i)].destroy;
+ setlength(ral,0);
+
+
+ M.destroy;
+ N.destroy;
+ end;
+ end{of Case};
+ M:=TMatrix.create;
+ M.assign0;
+ for i:=0 to length(Ecken)-1 do
+ M.plus(Ecken[i]);
+ M.times(-1/length(Ecken));
+ for i:=0 to length(Ecken)-1 do
+ Ecken[i].plus(M);
+ b:=0;
+ for i:=0 to length(Ecken)-1 do
+ b:=max(b,Ecken[i].len);
+ for i:=0 to length(Ecken)-1 do
+ Ecken[i].times(1/2/b);
+ M.Destroy;
+
+ for i:=0 to length(Kanten)-1 do
+ if Kanten[i].x>Kanten[i].y then begin
+ j:=Kanten[i].x;
+ Kanten[i].x:=Kanten[i].y;
+ Kanten[i].y:=j;
+ end;
+
+ for i:=0 to length(Kanten)-2 do begin
+ j:=i;
+ for k:=i+1 to length(Kanten)-1 do
+ if (Kanten[k].x<Kanten[j].x) or
+ ((Kanten[k].x=Kanten[j].x) and
+ (Kanten[k].y<Kanten[j].y)) then
+ j:=k;
+ if j>i then begin
+ k:=Kanten[j].x;
+ Kanten[j].x:=Kanten[i].x;
+ Kanten[i].x:=k;
+ k:=Kanten[j].y;
+ Kanten[j].y:=Kanten[i].y;
+ Kanten[i].y:=k;
+ end;
+ end;
+
+ SetZoom;
+end;
+
+procedure TForm1.CheckBox1Click(Sender: TObject);
+begin
+ ZeichenTimer.Enabled:=Checkbox1.Checked;
+ Image3.Visible:=not Checkbox1.Checked;
+end;
+
+procedure TForm1.CheckBox2Click(Sender: TObject);
+begin
+ ZeichenTimer.Interval:=30;
+end;
+
+procedure TForm1.KantenZeichnen(Pte: array of TPoint; PZ: array of extended; drawZ: boolean; drawTo: TCanvas);
+var i: integer;
+begin
+ if drawZ then
+ begin
+ for i:=0 to length(Kanten)-1 do
+ drawColoredLine(drawto,Pte[Kanten[i].X].X,Pte[Kanten[i].X].Y,PZ[Kanten[i].X],
+ Pte[Kanten[i].Y].X,Pte[Kanten[i].Y].Y,PZ[Kanten[i].Y]);
+ end
+ else
+ begin
+ for i:=0 to length(Kanten)-1 do
+ begin
+ drawto.MoveTo(Pte[Kanten[i].X].X,Pte[Kanten[i].X].Y);
+ drawto.LineTo(Pte[Kanten[i].Y].X,Pte[Kanten[i].Y].Y);
+ end;
+ end;
+end;
+
+procedure TForm1.drawColoredLine(wo: TCanvas; X1,Y1: Integer; Z1: extended; X2,Y2: Integer; Z2: Extended);
+var i: integer;
+ a,b,az,bz: extended;
+begin
+ if abs(X2-X1)>abs(Y1-Y2) then
+ begin
+ a:=(Y1-Y2)/(X1-X2);
+ b:=Y1-X1*a;
+ az:=(Z1-Z2)/(X1-X2);
+ bz:=Z1-X1*az;
+ if X1<X2 then
+ begin
+ for I:=X1 to X2 do
+ wo.Pixels[I,round(I*a + b)]:=farbVerlauf(I*az + bz);
+ end
+ else
+ begin
+ for I:=X2 to X1 do
+ wo.Pixels[I,round(I*a + b)]:=farbVerlauf(I*az + bz);
+ end;
+ end
+ else
+ begin
+ if Y1=Y2 then exit;
+ a:=(X1-X2)/(Y1-Y2);
+ b:=X1-Y1*a;
+ az:=(Z1-Z2)/(Y1-Y2);
+ bz:=Z1-Y1*az;
+ if Y1<Y2 then
+ begin
+ for I:=Y1 to Y2 do
+ wo.Pixels[round(I*a + b),I]:=farbVerlauf(I*az + bz);
+ end
+ else
+ begin
+ for I:=Y2 to Y1 do
+ wo.Pixels[round(I*a + b),I]:=farbVerlauf(I*az + bz);
+ end
+ end;
+end;
+
+function TForm1.farbVerlauf(x: Extended): TColor;
+begin
+ x:=5*x;
+ if x<1 then
+ begin
+ result:=min($FF,max($0,round($FF*x))) shl 16;
+ exit;
+ end;
+ x:=x-1;
+ if x<1 then
+ begin
+ result:=(min($FF,max($0,round($FF*(1-x)))) shl 16) or
+ (min($FF,max($0,round($FF*x))) shl 8);
+ exit;
+ end;
+ x:=x-1;
+ if x<1 then
+ begin
+ result:=$00FF00 or
+ min($FF,max($0,round($FF*x)));
+ exit;
+ end;
+ x:=x-1;
+ if x<1 then
+ begin
+ result:=$0000FF or
+ (min($FF,max($0,round($FF*(1-x)))) shl 8);
+ exit;
+ end;
+ x:=x-1;
+ result:=$0000FF or
+ (min($FF,max($0,round($FF*x))) shl 16);
+end;
+
+procedure TForm1.RotationInitialisieren;
+var z,s: integer;
+begin
+ Rot.xdim:=dim;
+ Rot.ydim:=dim;
+ repeat
+ for z:=0 to dim-1 do
+ for s:=0 to dim-1 do
+ Rot.a[z,s]:=0.01*random;
+ Rotation.assignId(dim);
+ Rotation.plus(Rot);
+ until Rotation.det>0;
+end;
+
+procedure TForm1.BeschlBelegen;
+var z,s: integer;
+ M: TMatrix;
+begin
+ M:=TMatrix.create;
+ M.xdim:=dim;
+ M.ydim:=dim;
+ repeat
+ for z:=0 to dim-1 do
+ for s:=0 to dim-1 do
+ M.a[z,s]:=0.02*random;
+ Beschl.assignId(dim);
+ Beschl.plus(M);
+ until Beschl.det>0;
+ Beschl.orthogonalize(true);
+ M.destroy;
+end;
+
+procedure TForm1.Drehen;
+begin
+ Rotation.assignId(dim);
+ Rotation.plus(Rot);
+ Rotation.orthogonalize(true);
+ Rot.times_(Beschl);
+ ProjektionL.times_(Rotation);
+ ProjektionR.times_(Rotation);
+end;
+
+procedure TForm1.Image3MouseDown(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ Image3.Tag:=floor(Y*dim*(dim-1)/2/Image3.Height)+
+ X*((dim*(dim-1)) div 2);
+end;
+
+procedure TForm1.Image3MouseUp(Sender: TObject; Button: TMouseButton;
+ Shift: TShiftState; X, Y: Integer);
+begin
+ Image3.Tag:=-1;
+end;
+
+procedure TForm1.Image3MouseMove(Sender: TObject; Shift: TShiftState; X,
+ Y: Integer);
+var M: TMatrix;
+ a1,a2: integer;
+const alpha = 2*pi/360 * 1;
+begin
+ if not(ssLeft in Shift) then exit;
+ Y:=Image3.Tag mod ((dim*(dim-1)) div 2);
+ X:=X - (Image3.Tag div ((dim*(dim-1)) div 2));
+ Image3.Tag:=Image3.Tag + X*((dim*(dim-1)) div 2);
+ M:=TMatrix.create;
+ M.assignId(dim);
+ a1:=0;
+ while Y>=0 do
+ begin
+ inc(a1);
+ Y:=Y-dim+a1;
+ end;
+ a2:=Y+dim;
+ dec(a1);
+ M.a[a1,a1]:=cos(alpha*X);
+ M.a[a1,a2]:=sin(alpha*X);
+ M.a[a2,a1]:=-sin(alpha*X);
+ M.a[a2,a2]:=cos(alpha*X);
+ ProjektionR.times_(M);
+ ProjektionL.times_(M);
+ M.destroy;
+ Zeichnen;
+end;
+
+procedure TForm1.Zeichnen;
+var Pkt: TMatrix;
+ Pkte: array[boolean] of array of TPoint;
+ PZ: array of extended;
+ i: integer;
+ b: boolean;
+ mi,ma: extended;
+begin
+ if length(Ecken)=0 then
+ exit;
+ setlength(Pkte[false],length(Ecken));
+ setlength(Pkte[true],length(Ecken));
+ setlength(PZ,length(Ecken));
+ for i:=0 to length(Pkte[false])-1 do
+ for b:=false to true do
+ begin
+ Pkt:=Ecken[i].duplicate;
+ if B then Pkt._times(ProjektionR)
+ else Pkt._times(ProjektionL);
+ PZ[i]:=Pkt.a[2,0];
+ Pkte[b,i]:=Pkt.asPoint(Zoom);
+ Pkte[b,i].x:=Pkte[b,i].x + Image1.Width div 2;
+ Pkte[b,i].y:=Pkte[b,i].y + Image1.Height div 2;
+ Pkt.destroy;
+ end;
+ mi:=PZ[0];
+ ma:=PZ[0];
+ for i:=0 to length(PZ)-1 do
+ begin
+ mi:=min(mi,PZ[i]);
+ ma:=max(ma,PZ[i]);
+ end;
+ ma:=max(ma,mi+0.00001);
+ for i:=0 to length(PZ)-1 do
+ PZ[i]:=(PZ[i]-mi)/(ma-mi);
+ Image1.Canvas.Rectangle(-10,-10,Image1.Width+10,Image1.Height+10);
+ KantenZeichnen(Pkte[true],PZ,false,Image1.Canvas);
+ Image2.Canvas.Rectangle(-10,-10,Image2.Width+10,Image2.Height+10);
+ KantenZeichnen(Pkte[false],PZ,false,Image2.Canvas);
+end;
+
+procedure TForm1.FormResize(Sender: TObject);
+var L,T: integer;
+begin
+ L:=Image1.Left;
+ T:=Image1.Top;
+ Image1.Free;
+ Image2.Free;
+ Image1:=TImage.Create(Form1);
+ Image2:=TImage.Create(Form1);
+ Image1.Parent:=Form1;
+ Image2.Parent:=Form1;
+ Image1.Left:=L;
+ Image1.Top:=T;
+ Image2.Top:=T;
+ Image1.Width:=min(Form1.ClientHeight-Image1.Top,(Form1.ClientWidth-Image1.Left) div 2);
+ Image1.Height:=Image1.Width;
+ Image2.Width:=Image1.Width;
+ Image2.Height:=Image2.Width;
+ Image2.Left:=Image1.Left+Image1.Width;
+ Progressbar1.Width:=Form1.Clientwidth-Progressbar1.Left;
+ SetZoom;
+ Zeichnen;
+end;
+
+procedure TForm1.SetZoom;
+begin
+ case Koerp of
+ 0: Zoom:=min(Image1.Width,Image1.Height)*0.9;
+ 1: Zoom:=min(Image1.Width,Image1.Height)*0.9;
+ end{of Case};
+end;
+
+procedure TForm1.RadioGroup1Click(Sender: TObject);
+var i: integer;
+begin
+ if Koerp = Radiogroup1.ItemIndex then exit;
+ Koerp:=RadioGroup1.ItemIndex;
+
+ for i:=0 to length(Ecken)-1 do
+ Ecken[i].destroy;
+ ProjektionenBelegen;
+ RotationInitialisieren;
+ BeschlBelegen;
+ KoerperErzeugen;
+ Image3.Canvas.Brush.Color:=Form1.Color;
+ Image3.Canvas.Rectangle(-10,-10,Image3.Width+10,Image3.Height+10);
+ For i:=1 to (dim*(dim-1)) div 2 do
+ begin
+ Image3.Canvas.MoveTo(10,round((I-0.5)*(Image3.Height*2/(dim*(dim-1)))));
+ Image3.Canvas.LineTo(Image3.Width-10,round((I-0.5)*(Image3.Height*2/(dim*(dim-1)))));
+ end;
+// Drehen;
+// BeschlBelegen;
+ Zeichnen;
+end;
+
+procedure TForm1.Button1Click(Sender: TObject);
+begin
+ Form2.Showmodal;
+end;
+
+procedure TForm1.Button2Click(Sender: TObject);
+var M: TMatrix;
+ I,J,K,L,N: Longint;
+ B: Boolean;
+ Memo1: TMemo;
+ s: String;
+ x: extended;
+ fcs: array of Longint;
+begin
+ M:=TMatrix.create;
+ M.xdim:=length(Kanten)-3;
+ for I:=0 to length(Kanten)-1 do begin
+ B:=Kanten[I].x=Kanten[I].y;
+ for J:=0 to I-1 do
+ B:=B or ((Kanten[I].X=Kanten[J].X) and (Kanten[I].Y=Kanten[J].Y))
+ or ((Kanten[I].X=Kanten[J].Y) and (Kanten[I].Y=Kanten[J].X));
+ if B then M.xdim:=M.xdim-1;
+ end;
+ M.ydim:=3*length(Ecken)-9;
+ if M.xdim<>M.ydim then begin
+ if MessageDlg(
+ 'Die Anzahl der Randbedingungen ('
+ +inttostr(M.xdim)+
+ ') unterscheidet sich von der Anzahl der Freiheitsgrade ('
+ +inttostr(M.ydim)+
+ ')! Genauere Erklärung gewünscht?',mterror,[mbYes,mbNo],0) = mrYes then begin
+ Memo1:=TMemo.Create(Form1);
+ Memo1.Parent:=Form1;
+ Memo1.Left:=Image1.Left;
+ Memo1.Top:=Image1.Top;
+ Memo1.Width:=Form1.ClientWidth-Memo1.Left;
+ Memo1.Height:=Form1.ClientHeight-Memo1.Top;
+ Memo1.Lines.Clear;
+ x:=0;
+ for I:=0 to length(Ecken)-1 do
+ x:=max(x,Ecken[I].len);
+ s:='';
+ for I:=0 to length(Kanten)-1 do
+ s:=s+' '+inttostr(Kanten[I].x)+'-'+inttostr(Kanten[I].y);
+ delete(s,1,1);
+ Memo1.Lines.Add(s);
+ Memo1.Lines.Add('');
+ s:='';
+ for I:=0 to length(Ecken)-1 do
+ if Ecken[I].len>=0.98*x then
+ s:=s+' '+inttostr(I);
+ delete(s,1,1);
+ Memo1.Lines.Add(s);
+ Memo1.Lines.Add('');
+ s:='';
+ for I:=0 to length(Kanten)-1 do
+ if (Ecken[Kanten[I].x].len>=0.98*x) or
+ (Ecken[Kanten[I].y].len>=0.98*x) then
+ s:=s+' '+inttostr(Kanten[I].x)+'-'+inttostr(Kanten[I].y);
+ delete(s,1,1);
+ Memo1.Lines.Add(s);
+ Memo1.Lines.Add('');
+ s:='';
+ for i:=0 to length(Ecken)-1 do
+ if Ecken[I].len>=0.98*x then begin
+ s:=s+' '+inttostr(i)+':';
+ for j:=0 to length(Kanten)-1 do
+ if (Kanten[j].x=i) or (Kanten[j].y=i) then
+ s:=s+inttostr(Kanten[j].x+Kanten[j].y-i)+',';
+ delete(s,length(s),1);
+ end;
+ delete(s,1,1);
+ Memo1.Lines.Add(s);
+ Application.ProcessMessages;
+ MessageDlg('Memo schließen.',mtInformation,[mbOk],0);
+ Memo1.Free;
+ end;
+ exit;
+ end;
+ M.assign0;
+
+ case Radiogroup1.ItemIndex of
+ 0: begin
+ // Ecken 1,6,11
+ setlength(fcs,3);
+ fcs[0]:=1;
+ fcs[1]:=6;
+ fcs[2]:=11;
+ end;
+ 1: begin
+ // Ecken 0,1,16
+ setlength(fcs,3);
+ fcs[0]:=0;
+ fcs[1]:=1;
+ fcs[2]:=16;
+ end;
+ end{of case};
+
+ j:=0;
+ for i:=0 to length(Kanten)-1 do begin
+ K:=Kanten[i].x;
+ L:=Kanten[i].y;
+ for N:=length(fcs)-1 downto 0 do begin
+ if fcs[N]=K then K:=-1;
+ if fcs[N]=L then L:=-1;
+ if K>=fcs[N] then dec(K);
+ if L>=fcs[N] then dec(L);
+ end;
+ if K<>-1 then
+ for N:=0 to 2 do
+ M.a[j,3*K+N]:=
+ M.a[j,3*K+N]
+ + Ecken[Kanten[i].x].a[N,0]
+ - Ecken[Kanten[i].y].a[N,0];
+ if L<>-1 then
+ for N:=0 to 2 do
+ M.a[j,3*L+N]:=
+ M.a[j,3*L+N]
+ + Ecken[Kanten[i].y].a[N,0]
+ - Ecken[Kanten[i].x].a[N,0];
+ if (K<>-1) or (L<>-1) then inc(j);
+ end;
+
+ M.Progressbar:=Progressbar1;
+ Messagedlg('det M = '+floattostr(M.det(dmGauss)),mtInformation,[mbOk],0);
+ M.Free;
+end;
+
+procedure TForm1.Button3Click(Sender: TObject);
+var I,J,K,L: Longint;
+ x: extended;
+begin
+ x:=0;
+ for I:=0 to length(Ecken)-1 do
+ x:=max(x,Ecken[I].len);
+ I:=length(Ecken)-1;
+ while I>=0 do begin
+ if Ecken[I].len>=0.98*x then begin
+ for J:=I+1 to length(Ecken)-1 do
+ Ecken[J-1].assign(Ecken[J]);
+ Ecken[length(Ecken)-1].Free;
+ setlength(Ecken,length(Ecken)-1);
+ J:=length(Kanten)-1;
+ L:=0;
+ while J>=0 do begin
+ if (Kanten[J].x=I) or (Kanten[J].y=I) then begin
+ inc(L);
+ for K:=J+1 to length(Kanten)-1 do
+ Kanten[K-1]:=Kanten[K];
+ setlength(Kanten,length(Kanten)-1);
+ end
+ else begin
+ if Kanten[J].x>I then dec(Kanten[J].x);
+ if Kanten[J].y>I then dec(Kanten[J].y);
+ end;
+ dec(J);
+ end;
+ if L<>4 then Form1.Caption:=Form1.Caption+' '+inttostr(L);
+ end;
+ dec(I);
+ end;
+ x:=0;
+ for I:=0 to length(Ecken)-1 do
+ x:=max(x,Ecken[I].len);
+ for i:=0 to length(Ecken)-1 do
+ Ecken[i].times(1/2/x);
+ Zeichnen;
+end;
+
+procedure TForm1.Button4Click(Sender: TObject);
+const mindim = 4;
+ maxdim = 9;
+var M: TMatrix;
+ dm: TDetMethode;
+ I,J,K,L: Longint;
+ ts,errs: array[mindim..maxdim,TDetMethode] of extended;
+ t1,t2: extended;
+ s: string;
+begin
+ M:=TMatrix.create;
+ t2:=0;
+ for I:=mindim to maxdim do begin
+ for dm:=low(dm) to high(dm) do begin
+ ts[I,dm]:=0;
+ errs[I,dm]:=0;
+ end;
+ for J:=1 to 50 do begin
+ M.assignId(I);
+ for K:=0 to I-1 do
+ for L:=0 to I-1 do
+ if random*50<=J then
+ M.a[K,L]:=M.a[K,L]+random-0.5;
+ for dm:=low(dm) to high(dm) do begin
+ ts[I,dm]:=ts[I,dm]-now;
+ t1:=M.det(dm);
+ ts[I,dm]:=ts[I,dm]+now;
+ if dm=low(dm) then t2:=t1;
+ errs[I,dm]:=sqr(t1-t2);
+ end;
+ end;
+ end;
+ M.Free;
+ s:='';
+ for i:=mindim to maxdim do begin
+ s:=s+inttostr(i)+': ';
+ for dm:=low(dm) to high(dm) do
+ s:=s+floattostr(errs[i,dm])+' '+floattostr(ts[i,dm]*24*60*60)+';';
+ delete(s,length(s),1);
+ s:=s+#13;
+ end;
+ delete(s,length(s),1);
+ Messagedlg(s,mtinformation,[mbOk],0);
+end;
+
+end.
+