Der Aufbau
. Grundgedanke
br />
Das Programm dient dazu, das Arbeiten mit dreieckigen, ebenen Flächen in diesem Teilgebiet der Analytik, Geometrie und Mathematik wesentlich zu vereinfachen, so daß sowohl für Anfänger, Fortgeschrittene als auch für Leute die täglich mit derartigen Problemstellungen konfrontiert werden, ein unheimlich schneller Zugang zu Daten zur Verfügung steht, die ohne diesem Programm erst mühselig errechnet oder konstruiert werden müßten.
Dieses Programm ist sehr benutzerfreundlich programmiert, um auch Erstbenutzern einen einfachen Umgang zu bieten. Der sofortige Einstieg und damit die Benutzung des Programms ist dadurch gewährleistet, daß das Format der Datei \"Dreieck.exe\" von nahezu allen Computern der gesamten Welt akzeptiert wird.
Trotz der Übersichtlichkeit des Programms \"Dreieck.exe\" ist nichts an gewonnenen Informationen verloren gegangen. Im Gegenteil: Durch die Unterteilung der ausgegebenen Daten in spezifische Gruppen wird auch Neulingen, die sich als Einsteiger auf diesem Gebiet unter Umständen mit der Flut an Informationen erdrückt fühlen könnten, ein schneller Überblick und ein einfaches Ablesen der Daten ermöglicht.
. Konzept
Die Anforderungen die an das Programm gestellt werden entsprechen denen, die an jeden Schüler einer achten Klasse Allgemeinbildenden Höheren Schule gestellt werden.
Dem Programm werden drei Koordinaten Paare zur Verfügung gestellt, aus denen es folgende Daten eruieren soll:
Seitenlängen, Winkel, Fläche, besondere Punkte, Euler\'sche Gerade und die Koordinaten für eine Transformation des Dreiecks auf den Bildschirm oder Drucker.
Als Vorarbeit dazu muß man sich bereits am Beginn ein gut durchdachtes Schema des Programmablaufes aufschreiben. Außerdem ist eine Durchrechnung der wichtigsten Rechenoperationen vor Beginn der Programmierung ebenfalls notwendig, um sich den darauf folgenden Programmiervorgang zu erleichtern. (siehe Seite 3)
Durch die Eingabe der Koordinaten jeweils als x-Wert und y-Wert, ist die Vektorrechnung die nächstliegende Rechenart.
Die Programmiersprache bietet hinsichtlich dieser Entscheidung nicht nur integer und real Variablen an, sondern auch Variablen mit der Bezeichnung Pointtype. Der Vorteil dieser ist, daß zwei Werte unter einem Variablennamen gespeichert werden können. Diese zwei Werte werden durch Endungen (.x oder .y), welche an den Variablennamen angehängt werden, unterschieden. Der Nachteil der Variablen des Typs Pointtype ist, daß die Werte der Zahlen integer sein müssen.
Aus diesem Grund, daß Pointtype integer beinhalten muß, verwendet man diese nur zur Ausgabe am Bildschirm, der ebenfalls Integerwerte (Anzahl der Pixel) voraussetzt.
Während man für alle anderen Rechenvorgänge zwei parallel laufende Realvariablen benutzt. Damit man nicht zu viele Variablennamen einführen muß, benutzt man die Möglichkeit ein Array of real zu erstellen, in welchem alle möglichen Werte unter einem Ausgangsvariablennamen gespeichert werden können.
. Die Programmstruktur
Natürlich kann man nicht darauf vertrauen, daß der Eingebende sich allen Ergebnissen oder Folgen seiner Eingabe bewußt ist. (zB: Eine Division durch Null, oder daß alle 3 Punkte in einer Geraden liegen,...)
Deshalb habe ich Sicherheitsvorraussetzungen in das Programm eingebaut, die eine fehlerfreie Benutzung ermöglichen:
1.) Eine Abfrage, ob nicht eine Seitenlänge gleich Null ist, was bei einem Dreieck nicht sein darf.
2.) Eine Abfrage vor einer Wurzelrechnung, ob die Determinante nicht negativ wird, was komplexe Zahlen als Folge hätte.
3.) Eine Prüfung, ob die drei eingegebenen Punkte kollinear sind, was bei einem Dreieck ebenfalls nicht möglich ist.
Weitere Abfragen dienen als zusätzliche Informationsquelle. (zB: Abfragen über den Typ des Dreiecks)
Das Programm an sich besteht aus einem relativ kurzen Hauptprogramm, in dem die Eingabe und die erste Ausgabe stattfindet, und weitere Wahlmöglichkeiten in einer Schleife abgefragt werden.
Neben dem Hauptprogramm gibt es für jede Aufgabe ein eigenes Unterprogramm; Eine Procedure oder eine Function.
(Details siehe Listing)
. Darstellung
Die Möglichkeiten der Darstellung sind natürlich eingeschränkt, da man auf die Rechnergeschwindigkeiten, Speicherkapazität, Größe des Files und etwaige andere Einschränkungen achten muß. Trotz all dem ist es mir aber gelungen eine akzeptable Darstellung auf den Bildschirm zu bringen.
Die Farbzusammenstellung entstand in Zusammenarbeit mit einer Zeichenlehrerin, die sich mit der Kombination von verschiedenen Farbtönen nach dem Farbkreis besser auskennt als ich.
Dadurch, daß die Druckroutine schwarzweiß drucken läßt, werden manche Farben, die auf dem Bildschirm erscheinen nicht gedruckt. Um dieses Problem zu umgehen, habe ich alle nichtdruckbaren Farben vor dem Druck in druckbare umgewandelt, und nach dem Drucken wieder in die augenfreundlichere Farbe zurück.
Ein weiteres Problem war die Darstellung einer endlos langen Gerade; Der Euler\'schen Gerade. Schon bei der Eingabe stelle ich den Maximalwert (egal ob auf x- oder y-Achse) fest. Darauf wird beim Zeichnen der Linie Rücksicht genommen. Es wird für den Anfangspunkt der negative Maximalwert (plus einer Konstante) als x-Achsenabstand angenommen und über die Geradengleichung die dazugehörige y-Koordinate ausgerechnet. Das Selbe noch einmal mit dem Endpunkt, nur mit dem Unterschied, daß der positive Maximalwert (plus einer Konstanten) verwendet wird.
Es ist keine Seltenheit, daß die Anfangspunkte außerhalb des dargestellten Teils des Koordinatenkreuzes, also außerhalb des Bildschirmes sind. Aber das ist ja schließlich auch Sinn und Zweck der Sache: Das Vermitteln des Eindrucks einer unendlichen Gerade.
Ein großes Problem war auch noch dem User gleichzeitig die Möglichkeit zu bieten das Dreieck mit all seinen Punkten grafisch zu betrachten sowie die Daten über das Dreieck nachzulesen und diese mit dem gezeichneten zu vergleichen.
Ich entschied mich für die \"Überblendungsmethode\".
Das was der Betrachter gerade sehen möchte kann er sich ansehen und beliebig oft zwischen \"Daten\" oder \"Fläche\" herumschalten.
Die Berechnung der Winkel des Dreiecks war am Schwierigsten. Denn es werden dem Programmierer weder die arccos- noch die arcsin- noch die tan-Funktion zur Verfügung gestellt. Da aber für die Winkelberechnung arccos unerläßlich ist, muß man sich diesen durch Formeln über arctan herleiten. Man darf aber hier wiederum 2 Sachen nicht vergessen:
1) Die arctan Formel für arccos funktioniert nicht bei Null, was eine Fallunterscheidung mit sich bringt.
2) Man darf nicht vergessen, daß das Ergebnis dieser Formel in Radianten ausgegeben wird und man diese erst in Degree\'s umwandeln muß, bevor man sie ausgeben kann.
Die Verwendung
. Prinzipiell
Das Programm \"Dreieck.exe\" ist zwar von mir mit einem Copyright versehen, steht aber, unter der Bedingung der Erwähnung meines Namens, hiermit zur freien Kopie und Nutzung zur Verfügung.
. Zweck
Die Anwendungsgebiete eines solchen Programmes liegen besonders im schulischen Bereich, in dem noch viel analytische Geometrie betrieben wird. Schüler könnten dieses Programm als einfach verwendbare Kontrollmöglichkeit für Übungen, oder als Hilfe bei Problemen verwenden. Für Lehrer ist besonders die schnelle Kontrollmöglichkeit ein wichtiger Aspekt, dem das Programm auf jeden Fall gerecht wird.
Das Listing
{_4_0_M}
program DREIECK;
{ Analytische Berechnung von Dreiecken (c) Marcus Meisel }
uses crt, graph, U_GRAF;
type
Welt = Array[1..100] of Real;
Bild = Array[1..100] of PointType;
const
Marcus : FillPatternType = ($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF);
var X,Y : Welt; (* Weltpunkte (X[1]/Y[1]), ............. *)
B : Bild; (* Bildpunkte (B[1].x/B[1].y), ......... *)
P,Q,R : PointType; (* EIN Bildpunkt (P.x/P.y) *)
N : Integer; (* Zählvariable *)
k1,k2 : Real; (* Achsenstreckungen *)
u,v,xa,ya: Real; (* Weltkoordinaten *)
max,diff : Real; (* Hilfsvariable *)
GD,GM : Integer; (* Grafiktreiber, Grafikmodus *)
X0,Y0 : Integer; (* Koordinaten-Ursprung *)
Taste : Char; (* Hilfsvariable *)
st : string; (* Umwandlung von Zahlen in String *)
a,bb,c : real; (* Seitenlängen des Dreiecks *)
s,w,h : pointtype; (* Schwer-,Inkreis-,und Höhenschnittpunkt*)
ha,hb,hc : pointtype; (* Streckensymetralen der Seiten *)
w1,w2,uu,Nv: pointtype; (* Winkelsym.Rv.1+2;Umkreis;Normalvektor *)
k,d,rad,rr : real; (* Steigung;Anstieg;Inkreisecht;Umkr.echt*)
Flach,t,f,g: real; (* Fläche;Geradengleichungsparameter *)
afa,bta,gma: real; (* Winkel Alpha,Beta,Gamma *)
radi,radu :word; (* Inkreisradius Umkreisradius im Bild *)
procedure GrafInit;
(* Grafik-Initialisierung und Koordinatenachsen-Zeichnen *)
begin
GD := Detect;
InitGraph(GD,GM,\'\');
SetColor(8); SetBkColor(7);
SetTextJustify(CenterText,TopText);
end;
PROCEDURE TITEL(name:string);
(*Titel am Beginn*)
var
OrigMode,i,j,k: Integer; (* Bildschirmmodusspeicher,Variablen *)
begin
OrigMode := LastMode;
TextMode(CO40);
textcolor(7); textbackground(1);
gotoxy(20-(round(length(name)/2)),20);Write(name);
for k:=1 to 32 do begin
for i:=1 to 30000 do for j:=1 to 40 do;
writeln;
end;
TextMode(OrigMode);
textcolor(10);textbackground(0);
gotoxy(32,20);Write(\'by Marcus Meisel_\');
for k:=1 to 27 do begin
for i:=1 to 30000 do for j:=1 to 40 do;
writeln;
end;
end;
procedure Trans(x,y,v1: Real; var P: PointType);
(* Bildet den reellwertigen Weltpunkt (x/y) auf den Bildpunkt P ab *)
(* v1 der Streckungsfaktor von X- und Y-Achse *)
(* Koordinatenursprung (X0/Y0) *)
begin
P.x := Round(X0 + x * v1);
P.y := Round(Y0 - y * v1);
end;
procedure Skalen;
(*Zeichnet das Koordinatenkreuz und die Skalen darauf ein*)
var i,hugo:integer; (* Laufvariable,Farbvariable *)
begin
SetColor(8); SetBkColor(7);Hugo:=6;
X0 := GetMaxX div 2; Y0 := GetMaxY div 2;
SetLineStyle(DottedLn,0,NormWidth);
line(0,Y0,GetMaxX,Y0);
line(X0,0,X0,GetMaxY);
SetLineStyle(SolidLn,0,NormWidth);
SetTextJustify(CenterText,TopText);
OutTextXY(X0,Y0+5,\'0/0\');
outtextxy(319,1,\'^\');
outtextxy(329,1,\'y\');
outtextxy(635,236,\'>\');
outtextxy(632,220,\'x\');
setcolor(9);
if max1 then begin
settextjustify(Lefttext,Centertext);setcolor(12);
outtextxy(30,20,\'Error: Winkelberechnung wird Komplex !\');taste:=readkey;halt;
end;
inverscos:=arctan(sqrt(1-zl*zl)/zl)*180/PI;
end;
procedure Winkel;
(*berechnet die Winkel des Dreiecks*)
var zahl:real; (*Ein Zwischenergebnis d. Winkelberechnung*)
begin
zahl:=((x[3]-x[1])*(x[2]-x[1])+(y[3]-y[1])*(y[2]-y[1]))/(bb*c);
afa:=abs(inverscos(zahl));
zahl:=((x[1]-x[2])*(x[3]-x[2])+(y[1]-y[2])*(y[3]-y[2]))/(c*a);
bta:=abs(inverscos(zahl));
gma:=180-(afa+bta);
end;
procedure Umkreis;
(*Berechnet dem Umkreismittelpunkt-und Radius und zeichnet diesen*)
begin
t:=(-(x[3]-x[2])*(x[7]-x[9])-(y[3]-y[2])*(y[7]-y[9]))/((x[3]-x[2])*x[13]+(y[3]-y[2])*y[13]);
X[15]:=x[7]+t*x[13]; {u.x}
Y[15]:=y[7]+t*y[13]; {u.y}
RR:=sqrt((x[1]-x[15])*(x[1]-x[15])+(y[1]-y[15])*(y[1]-y[15]));
radu:=round(RR*k1);
settextjustify(righttext,toptext);
trans(X[15],y[15],k1,B[15]);
ptgenau(b[15]);
outtextxy(b[15].x-2,b[15].y,\'U\');
setcolor(8);
circle(b[15].x,b[15].y,radu);
end;
procedure Hohenschnitt;
(*Berechnet und zeichnet den Höhenschnittpunkt und beschriftet diesen*)
begin
f:=(-(x[3]-x[2])*(x[3]-x[1])-(y[3]-y[2])*(y[3]-y[1]))/((x[3]-x[2])*x[13]+(y[3]-y[2])*y[13]);
X[16]:=x[3]+f*x[13]; {h.x}
Y[16]:=y[3]+f*y[13]; {h.y}
settextjustify(righttext,bottomtext);
trans(X[16],y[16],k1,B[16]);
ptgenau(b[16]);
outtextxy(b[16].x-2,b[16].y,\'H\');
end;
procedure Euler1;
(*beechnet die Geradengleichung er Eulerschen Gerade und gibt sie aus*)
var kk,dd:real; (* Steigung und d einer Geraden *)
stt:string; (* Stringvariable für Umwandlung von Zahl*)
xx,yy:pointtype; (* 2 Koordinatenvariablenpaare *)
begin
kk:=0;
if (abb) and (bbc) then begin
if (x[16]-x[15])0 then kk:=(y[16]-y[15])/(x[16]-x[15]);
settextjustify(Lefttext,Centertext);setcolor(12);
dd:=(y[16]-kk*x[16]);
str(kk:2:2,st);str(dd:2:2,stt);
setcolor(8);setfillpattern(Marcus,green);
Bar3d(10,300,310,340,3,topon);
st:=\'îuler`sche Gerade: y=\'+st+\'*x+\'+stt+\' !\';
outtextxy(20,320,st);
end;
end;
procedure Euler2;
(*zeichnet die Eulersche Gerade*)
var kk,dd:real; (* Steigung und d einer Geraden *)
stt:string; (* Umwandlung von Zahlen in String *)
xx,yy:pointtype; (* 2 Koordiinatenvariablenpaare *)
begin
kk:=0;
if (abb) and (bbc) then begin
if (x[16]-x[15])0 then kk:=(y[16]-y[15])/(x[16]-x[15]);
dd:=(y[16]-kk*x[16]);
trans(-max-19,kk*(-max-19)+dd,k1,xx);
trans(max+19,kk*(max+19)+dd,k1,yy);
setcolor(lightblue);line(xx.x,xx.y,yy.x,yy.y);setcolor(8);
end;
end;
procedure Flache;
(*Berechnet die Fläche,gibt diese aus, zeichnet das Dreieck neu, sodaß*)
(*Die Fläche besser sichtbar wird und eventuell die Daten wieder überdeckt*)
var i:integer; (* Laufvariable *)
ss:real; (* s für Heronsche Flächenformel *)
begin
Skalen;beschrift;
Inkreis;Halbierung;Schwerpunkt;Umkreis;Hohenschnitt;Euler2;
ss:=(a+bb+c)/2;
Flach:=sqrt(ss*(ss-a)*(ss-bb)*(ss-c));
str(Flach:3:3,st);st:=\'Die Fläche beträgt \'+st+\' Eý\';
settextjustify(Lefttext,Centertext);
outtextxy(30,50,st);taste:=readkey;
end;
procedure Daten;
(*Gibt alle die im Laufe des Programms gewonnenen Daten überschaulich aus*)
var stt:string; (* Umwandlung von Zahlen in String *)
vvv,helfi:integer; (* Kontrollvariable und Koordinatenvar. *)
begin
vvv:=0;
Euler2;
settextjustify(Lefttext,centertext);
setfillpattern(Marcus,green);
bar3d(10,80,310,280,3,topon);
str(a:3:3,st);st:=\'Seitenlängen : a=\'+st+\' E\';outtextxy(20,90,st);
str(bb:3:3,st);st:=\' b=\'+st+\' E\';outtextxy(20,100,st);
str(c:3:3,st);st:=\' c=\'+st+\' E\';outtextxy(20,110,st);
str(afa:2:2,st);st:=\'Winkel : =\'+st+\'°\';outtextxy(20,130,st);
str(bta:2:2,st);st:=\' =\'+st+\'°\';outtextxy(20,140,st);
str(gma:2:2,st);st:=\' =\'+st+\'°\';outtextxy(20,150,st);
str(x[16]:2:2,st);str(y[16]:2:2,stt);st:=\'Höhenschnittpunkt : H(\'+st+\'/\'+stt+\')\';
outtextxy(20,170,st);
str(x[15]:2:2,st);str(y[15]:2:2,stt);st:=\'Umkreismittelpunkt: U(\'+st+\'/\'+stt+\')\';
outtextxy(20,180,st);
str(rr:2:2,st);st:=\' Umkreisradius : R=\'+st+\' E\';
outtextxy(20,190,st);
str(x[10]:2:2,st);str(y[10]:2:2,stt);st:=\'Schwerpunkt : S(\'+st+\'/\'+stt+\')\';
outtextxy(20,200,st);
str(x[14]:2:2,st);str(y[14]:2:2,stt);st:=\'Inkreismittelpunkt: I(\'+st+\'/\'+stt+\')\';
outtextxy(20,210,st);
str(rad:2:2,st);st:=\' Inkreisradius : r=\'+st+\' E\';
outtextxy(20,220,st);
if ((x[15]=x[7]) and (y[15]=y[7])) or ((x[15]=x[8]) and (y[15]=y[8])) or ((x[15]=x[9]) and (y[15]=y[9])) then begin
st:=\'Dieses Dreieck ist rechtwinkelig !\';
outtextxy(20,260,st);vvv:=1;
end;
if ((a=bb) and (bb=c)) then begin
st:=\'Dieses Dreieck ist gleichseitig !\';
outtextxy(20,260,st);vvv:=2;
st:=\'Eulersche Gerade ist ein Punkt !\';helfi:=260+10;
outtextxy(20,helfi,st);
end;
if ((a=bb) or (bb=c) or (c=a)) then begin
st:=\'Dieses Dreieck ist gleichschenkelig !\';helfi:=260;
if vvv=2 then exit;
if vvv=1 then begin
st:=\' Und auch gleichschenkelig !\';helfi:=260+10;
end;
outtextxy(15,helfi,st);vvv:=0;
end;
Euler1;
end;
(* Hauptprogramm: Analytische Berechnung und Darstellung von Dreiecken *)
begin
titel(\'Dreieck\');
repeat
textcolor(7);textbackground(0);ClrScr; writeln;
writeln(\' Eingabe der Eckpunkte des Dreiecks \');
max := 0;
For N := 1 to 3 do begin
writeln;
write(N:2,\'-ter X-Wert: \'); readln(X[N]);
if abs(X[N]) > max then max := abs(X[N]);
write(N:2,\'-ter Y-Wert: \'); readln(Y[N]);
if abs(Y[N]) > max then max := abs(Y[N]);
end;
X[4] := X[1]; Y[4] := Y[1];
k1 := 200 / max;
writeln; write(\' \');
Taste := ReadKey;
textcolor(8);textbackground(7);clrscr;
GrafInit;skalen;
(* Dreieck zeichnen *)
setColor(14);setbkcolor(7);
For N := 1 to 4 do Trans(X[N],Y[N],k1,B[N]);
SetLineStyle(SolidLn,0,NormWidth);
drawpoly(4,B);beschrift;
lenge;Inkreis;Halbierung;Schwerpunkt;Umkreis;Hohenschnitt;Winkel;Euler2;
SetColor(8); SetBkColor(7);
SetTextJustify(centertext,Centertext);
OutTextXY(Succ(GetMaxX) div 2,GetMaxY-15,\'Für: Druck mit Epson...P / mit Laser...L Fläche...F Daten...D Ende...E\');
Repeat
taste := readkey;
if UpCase(Taste) = \'F\' then begin
SetFillStyle(XHatchFill,12);
FillPoly(4,B);Flache;
end;
if UpCase(Taste) = \'P\' then begin Skalen;GraphicPrint;end;
if UpCase(Taste) = \'L\' then Laser300;
if UpCase(Taste) = \'D\' then Daten;
until UpCase(Taste) = \'E\';
Closegraph;WINDOW(1,1,80,25);textcolor(7);textbackground(0);clrscr;
GOTOXY(32,12);Textcolor(red);write (\'Noch einmal (j/n) ?\');
repeat
taste:=UpCase (Readkey);
until (taste=\'J\') or (taste=\'N\');
until taste=\'N\';
Textcolor(7);Textbackground(0);clrscr;
end.
{_5_P_2}
|