In vielen Bereichen der Naturwissenschaft und auch anderswo benötigt man dreidimensionale Funktionsdarstellungen. Gerade Darstellungen als Netzgraphik sind hier gefragt. Das hier vorgestellte Modul bietet in einfacher Weise eine Möglichkeit, solche Graphen darzustellen.
âWarum gerade ein Modul und nicht ein schönes Programm?â werden viele fragen. Ein Programm bietet, egal wie gut es auf- bzw. ausgebaut ist, beschrĂ€nkte FĂ€higkeiten, die möglicherweise nicht ausreichen. Aber programmieren kann man selbst. Ein einfaches Programm fĂŒr eigene Zwecke ist oft mit wenig Aufwand fertiggestellt. Alles schön und gut, aber jedesmal die Prozedur fĂŒr Netzgraphiken neu entwerfen? NatĂŒrlich nicht! Wozu bieten höhere, moderne Entwicklungspakete wie ST Pascal Plus 2.0 Möglichkeiten wie Include-Dateien oder Programm-Module?! Beides bietet sich an, obwohl reine Include-Dateien mit kompilierbarem Programmtext unnötig den Compiler beanspruchen und somit teure Zeit verschwenden. Also bleibt als Konzept nur die Library oder das Objectcode-Modul.
Das Netzgraphik-Modul ist keine richtige Library, da es nur aus einem einzigen Modul besteht. Wer eine Library möchte, kann jede Routine in ein Modul bringen und diese sieben Module in einer Library zusammenfassen. Dies hĂ€tte natĂŒrlich den Vorteil, daĂ der Programmcode kĂŒrzer wĂŒrde als mit einem groĂen Objectcode-Modul, unter der Voraussetzung, daĂ man nur einen Teil der Routinen benötigt. Da aber das hier vorgestellte Graphik-Modul noch eine akzeptable LĂ€nge hat, kann man auf den Library-Aufbau verzichten.
Nun aber zum Modul selbst. Das Modul besteht aus zwei Teilen, der notwendigen EXTERNAL-Deklarationen in der Include-Datei als âSchnittstelleâ zum Modul und dem kompilierten Sourcecode. Die EXTERNAL-Deklarationen sind einerseits die Kopfzeilen der Routinen mit dem Wörtchen âEXTERNALâ darunter statt dem Sourcecode aus dem Modul. Andererseits sind in der Include-Datei die Typen-Deklarationen ein wichtiger Punkt. Die Typen horizontal, vertikal, winkel, hor_pkte und ver_pkte geben EinschrĂ€nkungen des Integer-Zahlenbereiches. Hierbei sind horizontal und vertikal fĂŒr die möglichen Pixelkoordinaten, winkel fĂŒr mögliche Winkel in Grad und hor_pkte und ver_pkte fĂŒr mögl. Punkte im Netz zustĂ€ndig. Wichtiger sind die Typenpunkte, die die Koordinaten eines Punktes beinhalten; matrix, die einfach Matrixelemente enthĂ€lt, und Netzdaten.
Die Type netzdaten ist ein wesentlicher Teil der Library. Das Record enthĂ€lt alle(!) wichtigen Daten. Dadurch ist zwar der kB-Umfang recht groĂ (ĂŒber 60 kB), aber die Ăbergabe der Parameter bleibt ĂŒbersichtlich. Nun aber im einzelnen, kennung enthĂ€lt einen String, beispielsweise den Namen des Graphen. Die vier Werte maxxlinks, maxxrechts, maxyoben und maxyunten enthalten die maximal möglichen AusmaĂe des kompletten Graphen. Es handelt sich um Integer-Werte, da man ja auch ein Netz fehlerhaft berechnen kann. Es besteht somit die Möglichkeit, jederzeit zu ĂŒberprĂŒfen, ob die vom Bildschirm vorgegebenen Koordinaten eingehalten werden. In Abbildung 1 erkennt man vier Punkte (1, 2, 3, 4), die diese maximalen Koordinaten verdeutlichen sollen. Der schraffierte Bereich entspricht dem Netz ohne Funktionsdarstellung. Eine solche ĂberprĂŒfung findet beispielsweise in der Prozedur ausg_netz statt. Der Punkt (x0,y0) ist der Startpunkt des Netzes.
Die Werte breite und hoehe geben die AusmaĂe des Netzes (in Pixeln) ohne Funktionswerte im ungedrehten Zustand, also mit phi und psi gleich 0. Damit ist auch gleich erklĂ€rt, wofĂŒr phi und psi zustĂ€ndig sind. Trotzdem noch ein Bildchen, in dem die entsprechenden Werte verzeichnet sind. Genaugenommen ist die Abbildung 2 nur ein Ausschnitt der Abbildung 1.
Die Werte pkte_hor und pkte_ver geben an, wieviele Knoten, jeweils horizontal und vertikal, man auf dem Netz wĂŒnscht. Diese Werte werden selbstverstĂ€ndlich nicht in Pixeln gemessen. Das Array koord enthĂ€lt alle (Pixel-) Koordinaten des Netzes und das Array fkt_werte die dazugehörigen Funktionswerte. Da verschiedene Funktionen verschiedene Maxima und Minima haben, wird noch der VerstĂ€rkungsfaktor verst benötigt, der dafĂŒr sorgt, daĂ zwischen Maximum und Minimum 100 Pixel Abstand sind, und der Verschiebungsfaktor versch, der die Funktion so verschiebt, daĂ das Maximum 50 Pixel ĂŒber der Netzgrundebene liegt und das Minimum 50 darunter. Das angesprochene Maximum und ebenso das Minimum der Funktion im ausgewĂ€hlten Bereich x_min bis x_max bezĂŒglich der x-Achse und y_min bis y_max bezĂŒglich der y-Achse ist unter den Werte f_max und f_min zu finden. Somit ist dieses Record erlĂ€utert.
Wenden wir uns jetzt dem Sourcecode zu. Das Modul besteht aus sieben Routinen, drei Initialisierungs-, zwei Ausgabe- und zwei Datei-Routinen. Die erste Routine, procedure init_netz, berechnet die Pixelkoordinaten des Grundnetzes, d. h. ohne Funktionswerte. Hier wird ein Record ânetzdatenâ als Variable ĂŒbergeben.
Die nĂ€chste Routine, procedure init_function, berechnet die zum Netz gehörigen Funktionswerte. Neben einem Record ânetzdatenâ wird auch eine Funktion als Parameter ĂŒbergeben.
Ăhnlich aufgebaut ist die procedure init_matrix. Allerdings wird hier nicht eine Funktion, sondern eine Matrix, also bereits feste Werte, ĂŒbergeben. Dies ist vorteilhaft, wenn man etwa eine Funktion nicht explizit angeben kann und nur MeĂoder auch NĂ€herungswerte vorliegen hat.
HerzstĂŒck von NETZLIB ist die Ausgabe-Routine procedure ausg_netz. Das fertig aufgebaute Netz (ânetzdatenâ) und ein boolescher Wert werden an diese Prozedur ĂŒbergeben. Der boolesche Wert bestimmt, ob verdeckte Teile gelöscht werden sollen (TRUE) oder nicht (FALSE). Zum Zeichnen des Graphen wird dieser von hinten nach vorne auf dem Bildschirm aufgebaut. Sofern man keine Löschung verdeckter Teile benötigt, ist der Graphaufbau gleichgĂŒltig. WĂŒnscht man allerdings eine Löschung, so ist die Reihenfolge des Aufbaus wichtig. Von den Teilen, die am weitesten hinten liegen, sieht man ja spĂ€ter am wenigsten. Also werden diese zuerst gezeichnet. Nun steht man nur vor dem Problem, ob man erst eine Linie zeichnen möchte und dann löscht oder umgekehrt. Eigentlich scheint es ja (vom mathematischen Standpunkt her) egal zu sein. Da aber auf dem Bildschirm keine Linien, sondern nur âTreppenâ dargestellt werden können, spielt diese Frage doch eine Rolle. Der Effekt ist einfach: löscht man erst und zeichnet dann die Linie, erscheinen die Linien durchgehend. Löscht man allerdings hinterher, so kann es sein, daĂ Linien unterbrochen werden, was interessante, nĂŒtzliche Effekte hervorrufen kann.
Bild 1
Bild 2
Es folgt noch eine Routine, mit der man die Funktionswerte in eine Textdatei ausgeben kann. Die Routine procedure ausg_function legt dieses Textfile unter dem Namen âOUTPUT.DATâ an.
Die vorletzte Routine, procedure sfile_netz, sorgt dafĂŒr, daĂ ein Netz abgespeichert wird. Somit kann man die Daten spĂ€ter weiterverwenden oder auch an andere Programme, die NETZLIB nutzen, weitergeben. Der Name der Datei wird mit dem String name ĂŒbergeben.
Die Routine procedure lfile_netz schlieĂlich bewerkstelligt das Lesen einer mit sfile_netz abgespeicherten Datei.
Das warâs nun in aller KĂŒrze zum Sourcecode. Wichtig zu wissen ist allerdings noch, welche Teile des Records netzdaten verĂ€ndert, welche von den einzelnen Routinen nur benutzt oder nicht benötigt werden. Hierzu die Tabelle in Abbildung 3 (siehe nĂ€chste Seite).
Aus dieser Tabelle wird noch einiges ersichtlich. Einige Werte bei den Routinen init_netz und init_function sind austauschbar. So kann man einerseits unter Beibehaltung des Netzes die Funktionswerte verĂ€ndern, also Funktionen austauschen oder neue x- und y-Koordinaten wĂ€hlen. Hier sind x_max, x_min, y_max, y_min und indirekt fkt_werte, verst, versch, f_max, f_min verĂ€nderbar. Andererseits kann man das Netz austauschen. Hier dĂŒrfen dann x0, y0, breite, hoehe, phi und psi gewechselt werden.
Bei Nutzung der Prozedur init_matrix ist darauf zu achten, daĂ init_netz erst anschlieĂend aufzurufen ist. Dies ist darin begrĂŒndet, daĂ Werte, die von init_netz benötigt werden, erst noch von init_matrix verĂ€ndert werden mĂŒssen. Daher hat man bei Verwendung von Matrizen auch nicht die freie Wahl des Austausches wie bei Verwendung von Funktionen.
Der Wert kennung steht dem Programmierer jederzeit zur freien VerfĂŒgung. Da er nur als Hilfsmittel benutzt wird, findet er bei dem Netz keine Verwendung.
Nachdem nun alles erklĂ€rt ist, kann das eigentliche Programmieren beginnen. Nehmen wir also an, das Modul ist als ASCII-File fertig. Es muĂ nur noch kompiliert werden. Ist auch dieses geschehen, kann man bei Bedarf die Endung .O löschen. Es wird so der Eindruck erweckt, es lĂ€ge eine echte Library vor. Die auf diese Weise entstandene Datei wird unter âLinkeroptionenâ als zusĂ€tzlich zu linkende Datei eingetragen, womit alle Vorbereitungen abgeschlossen sein sollten.
Jetzt gehtâs an die Entwicklung eines Programmes. Zu beachten ist, daĂ neben den Include-Dateien fĂŒr die GEM-Funktionen (GEM/CONST/TYPE/SUBS.INC) auch die Include-Datei fĂŒr NETZLIB (NETZ.INC) nach der program-Zeile aufgefĂŒhrt wird. Dank einer Ănderung in ST Pascal Plus ist es ja jetzt möglich, Konstanten-, Typen-, Variablen-, Label- und Routinendeklarationen in einer Include-Datei zusammenzufassen.
FĂŒr die Anwendung von NETZLIB sind noch vier kleine Beispiele angefĂŒhrt. Beispiel 1 entwirft nur eine Graphik, gibt sie aber nicht an den Monitor weiter, sondern speichert sie lediglich ab. Beispiel 2 liest nur eine Datei und zeichnet sie auf den Bildschirm. Das Programm lĂ€Ăt sich am besten nutzen, wenn man eine Anwendung anmeldet. Dies geschieht auf dem Desktop unter dem MenĂŒpunkt âAnwendung anmeldenâ. Hier wird die benutzte Endung der NETZGRAPHIK-Dateien eingetragen, beispielsweise .DAT oder .NTZ. Möchte man nun eine Graphik sehen, so braucht man nur die Datei anzuklicken, und das Programm wird automatisch aufgerufen. Der Dateiname wird aus der Kommandozeile gelesen. Ebensogut lĂ€Ăt sich auch ein Command-Line-Interpreter verwenden. Notfalls kann man sogar den Dateinamen direkt eingeben.
Die beiden letzten Beispielprogramme zeigen, wie man Netz oder Funktion auswechseln kann.
Mir bleibt nur, Ihnen viel Freude mit dem Modul zu wĂŒnschen. Es möge die Programmiererei hilfreich unterstĂŒtzen.
 |
init_netz |
init_function |
init_matrix |
ausg_netz |
ausg_function |
sfile_netz |
lfile_netz |
kennung |
|
|
|
|
|
B |
V |
maxxlinks |
V |
|
|
B |
|
B |
V |
maxxrechts |
V |
|
|
B |
|
B |
V |
maxyoben |
V |
|
|
B |
|
B |
V |
maxyunten |
V |
|
|
B |
|
B |
V |
breite |
B |
|
|
|
|
B |
V |
hoehe |
B |
|
|
|
|
B |
V |
phi |
B |
|
|
|
|
B |
V |
psi |
B |
|
|
|
|
B |
V |
x0 |
B |
|
|
|
|
B |
V |
y0 |
B |
|
|
|
|
B |
V |
pkte_hor |
B |
B |
V |
B |
B |
B |
V |
pkte_ver |
B |
B |
V |
B |
B |
B |
V |
koord |
V |
|
|
B |
|
B |
V |
fkt_werte |
|
V |
V |
B |
B |
B |
V |
verst |
|
V |
V |
B |
|
B |
V |
versch |
|
V |
V |
|
B |
B |
V |
f_max |
|
V |
V |
|
B |
B |
V |
f_min |
|
V |
V |
|
B |
B |
V |
x_max |
|
B |
V |
|
B |
B |
V |
x_min |
|
B |
V |
|
B |
B |
V |
y_max |
|
B |
V |
|
B |
B |
V |
y_min |
|
B |
V |
|
B |
B |
V |
(Bezeichnungen: B = benötigt, V = verÀndert)
Tabelle 1
{* Deklarationen NETZGRAPHIK *}
{ (c) 1987 by D. Rabich, DĂŒlmen.
Entw. mit ST Pascal+ V2.0 (CCD, Eltville) }
{-<<<<< Typendeklarationen NETZGRAPHIK >>>>>-}
type horizontal = 0..639;
vertikal = 0..399;
winkel = -89..89;
hor_pkte = 1..100;
ver_pkte = 1..60;
punkte = record
x : short_integer;
y : short_integer;
end;
netzdaten = record
kennung : string[80];
maxxlinks,maxxrechts : short_integer;
maxyoben,maxyunten : short_integer;
breite : horizontal;
hoehe : vertikal;
phi,psi : winkel;
x0 : horizontal;
y0 : vertikal;
pkte_hor : hor_pkte;
pkte_ver : ver_pkte;
koord : array [hor_pkte,ver_pkte] of punkte;
fkt_werte : array [hor_pkte,ver_pkte] of real;
verst : real;
versch : short_integer;
f_max,f_min : real;
x_max,x_min : real;
y_max,y_min : real;
end;
matrix = array [1..50,1..50] of real;
{-<<<<< Prozedurdeklarationen NETZGRAPHIK >>>>>-}
procedure init_netz(var netz : netzdaten);
EXTERNAL;
procedure init_function(function f(x,y : real) : real; var netz : netzdaten);
EXTERNAL;
procedure init_matrix(a : matrix; m,n : short_integer; var netz : netzdaten);
EXTERNAL;
procedure ausg_netz(netz : netzdaten; ausf boolean);
EXTERNAL;
procedure ausg_function(netz : netzdaten);
EXTERNAL;
procedure sfile_netz(netz : netzdaten; name : string);
EXTERNAL;
procedure lfile_netz(var netz : netzdaten; name : string);
EXTERNAL;
Listing: NETZINC
{-<<<<< Programm - Modul: NETZGRAPHIK >>>>>-}
{$M+,D-,P-,R-}
PROGRAM netzgraphik;
{ (c) 1987 by Dietmar Rabich, Dövelingsweg 2, 4408 DĂŒlmen }
{ Datum : 24. Oktober 1987 }
{ Version : 1.0 }
{ Entwickelt mit ST Pascal Plus Version 2.0 }
{----***** Konstanten und Typen *****------}
CONST pi = 3.141592653589; (* globale Definition *;
{$I \INCLUDE\GEMCONST.INC } (* fĂŒr GEM *)
TYPE ($I \INCLUDE\GEMTYPE.INC )
horizontal = 0..639;
vertikal = 0..399;
winkel = -89..89;
hor_pkte = 1..100;
ver_pkte = 1..60;
punkte = RECORD
x : short_integer;
y : short_integer;
END;
netzdaten = RECORD
kennung : string[80];
maxxlinks,maxxrechts : short_integer;
maxyoben,maxyunten : short_integer;
breite : horizontal;
hoehe : vertikal;
phi,psi : winkel;
x0 : horizontal;
y0 : vertikal;
pkte_hor : hor_pkte;
pkte_ver : ver_pkte;
koord : ARRAY [hor_pkte,ver_pkte] OF punkte;
fkt_werte : ARRAY [hor_pkte,ver_pkte] OF real;
verst : real;
versch : short_integer;
f_max,f_min : real;
x_max,x_min : real;
y_max,y_min : real;
END;
matrix = ARRAY [1..50,1..50] OF real;
{â--***** Prozeduren und Funktionen *****â--}
{$I \INCLUDE\GEMSUBS.INC } (* fĂŒr GEM *)
{$E+}
(* Netz - Initialisierung *)
PROCEDURE init_netz(VAR netz : netzdaten);
VAR mdx1,mdx2,mdy1,mdy2 : real;
dx1,dx2,dy1,dy2 : real;
xs,ys,xs2,ys2 : real;
i,j,dummy : short_integer;
(* Umrechnung Grad -> Bogen *)
FUNCTION bogen(x : real) : real;
BEGIN
bogen:=x*pi/180;
END;
(* notwendige Zwischenwerte *)
PROCEDURE zwischenwerte;
BEGIN
WITH netz DO
BEGIN
mdx1:=breite*cos(bogen(phi));
mdx2:=-hoehe*sin(bogen(psi));
mdy1:=breite*sin(bogen(phi));
mdy2:=hoehe*cos(bogen(psi));
dx1:=mdx1/pkte_hor;
dx2:=mdx2/pkte_ver;
dy1:=mdy1/pkte_hor;
dy2:=mdy2/pkte_ver;
END;
END;
(* AusmaĂ des Graphen *)
PROCEDURE ausmass;
BEGIN
WITH netz DO
BEGIN
IF psi>=0 THEN
BEGIN
maxxlinks :=x0+round(mdx2);
maxxrechts:=x0+round(mdx1);
END
ELSE
BEGIN
maxxlinks :=x0;
maxxrechts:=x0+round(mdx1+mdx2);
END;
IF phi>=0 THEN
BEGIN
maxyunten :=y0+round(mdy1+mdy2)+50;
maxyoben :=y0-50;
END
ELSE
BEGIN
maxyunten :=y0+round(mdy2)+50;
maxyoben :=y0+round(mdy1)-50;
END;
END;
END;
BEGIN
WITH netz DO
(* Abbruch bei zu dichter Punktwahl! *)
IF (breite/pkte_hor<3) OR (hoehe/pkte_ver<3) THEN
dummy:=do_alert('[3][ Zu viele | Punkte !][ABBRUCH]',1)
ELSE
BEGIN
zwischenwerte;
i:=1;
xs:=x0;
ys:=y0;
REPEAT
j:=1;
xs2:=xs;
ys2:=ys;
REPEAT
koord[i,j].x:=round(xs2);
koord[i,j].y:=round(ys2);
xs2:=xs2+dx1;
ys2:=ys2+dy1;
j:=j+1;
UNTIL j>pkte_hor;
xs:=xs+dx2;
ys:=ys+dy2;
i:=i+l;
UNTIL i>pkte_ver;
ausmass;
END;
END;
(* Funktion - Initialisierung *)
PROCEDURE init_function (FUNCTION f(x,y : real) : real; VAR netz : netzdaten);
VAR i,j : short_integer;
schritt_x, schritt_y : real;
xs,ys : real;
BEGIN
WITH netz DO
BEGIN
schritt_x:=abs(x_max-x_min)/(pkte_hor-1);
schritt_y:=abs(y_max-y_min)/(pkte_ver-1);
f_max:=f(x_min,y_max);
f_min:=f(x_min,y_max);
i:=1;
ys:=y_max;
REPEAT
j:=1;
xs:=x_min;
REPEAT
fkt_werte[i,j]:=f(xs,ys);
IF fkt_werte[i,j]>f_max THEN f_max:=fkt_werte[i,j];
IF fkt_werte[i,j]<f_min THEN f_min:=fkt_werte[i,j];
j:=j+i;
xs:=xs+schritt_x;
UNTIL j>pkte_hor;
i:=i+1;
ys:=ys-schritt_y;
UNTIL i>pkte_ver;
IF f_max<>f_min THEN
verst:=100/abs(f_max-f_min)
ELSE
verst:=0;
versch:=round(verst*(f_max+f_min)/2);
END;
END;
(* Matrix - Initialisierung *)
PROCEDURE init_matrix(a : matrix; m,n : short_integer; VAR netz : netzdaten);
VAR i,j : short_integer;
BEGIN
WITH netz DO
BEGIN
x_min:=1;
x_max:=n;
y_min:=1;
y_max:=m;
pkte_hor:=n;
pkte_ver:=m;
f_max:=a[1,1];
f_min:=a[1,1];
i:=1;
REPEAT
j:=1;
REPEAT
fkt_werte[i,j]:=a[i,j];
IF fkt_werte[i,j]>f_max THEN f_max:=fkt_werte[i,j];
IF fkt_werte[i,j]<f_min THEN f_min:=fkt_werte[i,j];
j:=j+1;
UNTIL j>pkte_hor;
i:=i+1;
UNTIL i>pkte_ver;
IF f_max<>f_min THEN
verst:=100/abs(f_max-f_min)
ELSE
verst:=0;
versch:=round(verst*(f_max+f_min)/2);
END;
END;
(* Ausgabe - Netzgraphik (Bildschirm) *)
PROCEDURE ausg_netz(netz : netzdaten; ausf : boolean);
VAR i,j : short_integer;
control : ctrl_parms;
int_in : int_in_parms;
int_out : int_out_parms;
pts_in : pts_in_parms;
pts_out : pts_out_parms;
dummy : short_integer;
(* UnregelmĂ€Ăiges Viereck VDI-Funktion FILLED AREA *)
PROCEDURE Viereck(x0,y0,x1,y1,x2,y2,x3,y3 : short_integer);
BEGIN
pts_in[0]:=x0; pts_in[1]:=y0;
pts_in[2]:=x1; pts_in[3]:=y1;
pts_in[4]:=x2; pts_in[5]:=y2;
pts_in[6]:=x3; pts_in[7]:=y3;
pts_in[8]:=x0; pts_in[9]:=y0;
vdi_call(9,0,0,5,control,int_in,int_out,pts_in,pts_out,false);
END;
(* Ausgabe mit Löschen verdeckter Teile *)
PROCEDURE ausg_m;
VAR i,j : short_integer;
BEGIN
WITH netz DO
BEGIN
paint_color(white);
paint_style(0);
FOR i:=1 TO pkte_ver DO
BEGIN
FOR j:=1 TO pkte_hor-1 DO
BEGIN
viereck(koord[i,j].x,
koord[i,j].y-round (verte[i,j]1)+versch,
koord[i,j+1].x,
koord[i,j+1].y-round (verst*fkt_werte[i,j+1]1)+versch,
koord[i,j+1].x,
maxyunten,
koord[i,j].x,
maxyunten);
pline(koord[i,j].x,
koord[i,j].y-round(verst*fkt_werte[i,j])+versch,
koord[i,j+1].x,
koord[i,j+1].y-round (verst*fkt_werte[i,j+1])+versch);
END;
IF i<pkte_ver THEN
FOR j:=1 TO pkte_hor DO
BEGIN
viereck(koord[i,j].x,
koord[i,j].y-round (verst*fkt_werte[i,j]-1)+versch,
koord[i+1,j].x,
koord[i+1,j].y-round (verst*fkt_werte[i+1,j]1)+versch,
koord[i+1,j].x,
maxyunten,
koord[i,j].x,
maxyunten);
pline(koord[i,j].x,
koord[i,j].y-round (verst*fkt_werte[i,j])+versch,
koord[i+1,j].x,
koord[i+1,j].y-round (verst*fkt_werte[i+1,j])+versch);
END;
END;
END;
END;
(* Ausgabe ohne Löschen verdeckter Teile *)
PROCEDURE ausg_o;
VAR i, j : short_integer;
BEGIN
WITH netz DO
FOR i:=1 TO pkte_ver DO
BEGIN
FOR j:=1 TO pkte_hor-1 DO
pline(koord[i,j].x,
koord[i,j].y-round (verst*fkt_werte[i,j])+versch,
koord[i,j+1].x,
koord[i,j+1].y-round (verst*fkt_werte[i,j+1])+versch);
IF i<pkte_ver THEN
FOR j:=1 TO pkte_hor DO
pline(koord[i,j].x,
koord[i,j].y-round (verst*fkt_werte[i,j])+versch,
koord[i+1,j].x,
koord[i+1,j].y-round (verst*fkt_werte[i+1,j])+versch);
END;
END;
BEGIN
WITH netz DO
(* PlausibilitĂ€tsprĂŒfung *)
IF (maxxlinks<0) OR (maxxrechts>639) OR (maxyoben<0) OR (maxyunten>399) THEN
dummy:=do_alert('[3][Koordinaten falsch!][ABBRUCH]',1)
ELSE
IF ausf THEN
ausg_m
ELSE
ausg_o;
END;
(* Ausgabe - Funktion (Datei OUTPUT.DAT) *)
PROCEDURE ausg_function(netz : netzdaten);
VAR i,j : short_integer;
schritt_x, schritt_y : real;
xs,ys : real;
ausgabe : text;
BEGIN
WITH netz DO
BEGIN
rewrite(ausgabe,'output.dat');
schritt_x:=abs(x_max-x_min)/(pkte_hor-1);
schritt_y:=abs(y_max-y_min)/(pkte_ver-1);
writeln(ausgabe,'x_min=',x_min);
writeln(ausgabe,'x_max=',x_max);
writeln(ausgabe,'y_min=',y_min);
writeln(ausgabe,'y_max=',y_max);
writeln(ausgabe,'f_min=',f_min);
writeln(ausgabe,'f_max=',f_max);
writeln(ausgabe);
i:=1;
ys:=y_max;
REPEAT
j:=1;
xs:=x_min;
REPEAT
writeln(ausgabe,'f(',xs,',',ys,')=',fkt_werte[i,j]);
j:=j+1;
xs:=xs+schritt_x;
UNTIL j>pkte_hor;
i:=i+1;
ys:=ys-schritt_y;
UNTIL i>pkte_ver;
close(ausgabe);
END;
END;
(* Speicher - Funktion (schreiben) *)
PROCEDURE sfile_netz(netz : netzdaten; name : string);
TYPE ausgabe = FILE OF netzdaten;
VAR datei : ausgabe;
BEGIN
rewrite(datei,name);
write(datei,netz);
close(datei);
END;
(* Speicher - Funktion (lesen) *)
PROCEDURE lfile_netz(VAR netz : netzdaten; name : string);
TYPE ausgabe = FILE OF netzdaten;
VAR datei : ausgabe;
BEGIN
reset(datei,name);
read(datei,netz);
close(datei);
END;
{â***** Hauptprogramm *****â}
BEGIN END.
Listing 2: NETZLIB
{ - Eingabeprogramm fĂŒr NETZGRAPHIK - )
program eingabe_netz;
{(c) 1987 by Dietmar Rabich.
Entw. mit ST Pascal+ 2.0. }
const {$I \INCLUDE\GEMCONST.INC }
type {$I \INCLUDE\GEMTYPE.INC }
{$I NETZ.INC }
var netz : netzdaten;
aplid : short_integer;
dummy : short_integer;
{$I \INCLUDE\GEMSUBS.INC }
function f(x,y:real):real;
begin
f:=cos(x+y)*sin(x*y);
end;
begin
aplid:=init_gem;
if aplid>=0 then
begin
(* Meldung, die Beginn kennzeichnet *)
dummy:=do_alert(concat('[0]
[Eingabeprogramm NETZGRAPHIK|',
'~~~~~~~~~~~~~~~~~~~~~~~~~~~|',
' Entwickelt mit |',
' ST Pascal Plus V 2.0.][Los geht',
chr(39),'s!]'),1);
(* Netz - Daten *)
netz.breite :=400;
netz.hoehe :=180;
netz.phi := 5;
netz.psi := 10;
netz.x0 :=100;
netz.y0 :=100;
netz.pkte_hor := 30;
netz.pkte_ver := 20;
netz.x_min := -3;
netz.x_max := 3;
netz.y_min := -3;
netz.y_max := 3;
netz.kennung :='Graph der Funktion f(x,y)=cos(x+y)*sin(x*y).';
(* Netzinitialisierung *)
init_netz(netz);
(* Funktionsinitialisierung *)
init_function(f,netz);
(* Daten in File schreiben *)
sfile_netz(netz,'netz.dat');
(* Ende kennzeichnen *)
dummy:=do_alert(concat('[0][File erstellt.|',
'--------------|',
'Ausgabedatei: |',
' NETZ.DAT ][Alles klar]'),1);
exit_gem;
end;
end.
Listing 3: Eingabeprogramm fĂŒr Netzgraphik
{ - Ausgabeprogramm fĂŒr NETZGRAPHIK - }
program ausgabe_netz;
{(c) 1987 by Dietmar Rabich.
Entw. mit ST Pascalt 2.0. }
const {$I \INCLUDE\GEMCONST.INC )
type {$I \INCLUDE\GEMTYPE.INC }
{$I NETZ.INC }
var netz : netzdaten;
aplid : short_integer;
datei : string;
{$I \INCLUDE\GEMSUBS.INC }
function conin(dev:short_integer):char;
BIOS (2);
procedure eingabe_datei;
var name : string;
begin
(* Argument aus Command-Line lesen *)
cmd_getarg(1,name);
if name<>'' then
datei:=name
else
begin
writeln(chr(27),'E *** Ausgabe NETZGRAPHIK***');
writeln('(Entwickelt mit ST Pascal Plus V 2.0)');
write('Bitte Dateinamen eingeben:');
readln(datei);
end;
end;
begin
aplid:=init_gem;
if aplid>=0 then
begin
init_mouse;
hide_mouse;
eingabe_datei;
(* Netz - Daten aus File lesen *)
lfile_netz(netz,datei);
clear_screen;
(* Kennung des Netzes als Text ausgeben *)
draw_string(0,13,netz.kennung);
(* Netz ausgeben, m.Löschen verdeckter Teile *)
ausg_netz(netz,true);
repeat until conin(2)=' ';
(* Netz ausgeben, o.Löschen verdeckter Teile *)
ausg_netz(netz,false);
repeat until conin(2)=' ';
show_mouse;
end;
exit_gem;
end.
Listing 4: Ausgabeprogramm fĂŒr Netzgraphik
{ - Ausgabeprogramm fĂŒr NETZGRAPHIK - }
program netz_1;
{(c) 1987 by Dietmar Rabich.
Entw. mit ST Pascal* 2.0. }
const {$I \INCLUDE\GEMCONST.INC }
type {$I \INCLUDE\GEMTYPE.INC }
{$I NETZ.INC }
var netz : netzdaten;
aplid : short_integer;
{$I \INCLUDE\GEMSUBS.INC }
function conin(dev:short_integer):char;
BIOS (2);
function f(x,y:real):real;
begin
f:=sin(abs(x*y)/3);
end;
begin
aplid:=init_gem;
if aplid>=0 then
begin
init_mouse;
hide_mouse;
clear_screen;
(* Netz - Daten *)
netz.breite :=400;
netz.hoehe :=200;
netz.phi := 0;
netz.psi := 0;
netz.x0 :=100;
netz.y0 :=100;
netz.pkte_hor := 30;
netz.pkte_ver := 20;
netz.x_min := -5;
netz.x_max := 5;
netz.y_min := -5;
netz.y_max := 5;
(* Initialisierung *)
init_netz(netz);
init_function(f,netz);
(* Ausgabe *)
ausg_netz(netz,false);
repeat until conin(2)=' ';
clear_screen;
(* Ănderung des Netzes *)
netz.breite :=200;
netz.hoehe :=100;
netz.phi :=-10;
netz.psi := 0;
netz.x0 :=150;
netz.y0 :=150;
(* Neuinitialisierung *)
init_netz(netz);
(* Neuausgabe *)
ausg_netz(netz,false);
repeat until conin(2)=' ';
show_mouse;
exit_gem;
end;
end.
Listing 5: Ausgabeprogramm fĂŒr Netzgraphik/program netz_l
{ - Ausgabeprogramm fĂŒr NETZGRAPHIK - }
program netz_2;
{(c) 1987 by Dietmar Rabich.
Entw. mit ST Pascal+ 2.0. }
const {$I \INCLUDE\GEMCONST.INC }
type {$I \INCLUDE\GEMTYPE.INC }
{$I NETZ.INC }
var netz,netz_alt : netzdaten;
aplid : short_integer;
{$I \INCLUDE\GEMSUBS.INC }
function conin(dev:short_integer):char;
BIOS(2);
function f(x,y:real):real;
begin f:=cos(abs(x*y)/3); end;
function g(x,y:real):real;
begin g:=exp(abs(x*y)/2); end;
begin
aplid:=init_gem;
if aplid>=0 then
begin
init_mouse;
hide_mouse;
clear_screen;
(* Netz - Daten *)
netz.breite :=400;
netz.hoehe :=200;
netz.phi := 5;
netz.psi := 5;
netz.x0 :=100;
netz.y0 :=100;
netz.pkte_hor := 30;
netz.pkte_ver := 20;
netz.x_min := -5;
netz.x_max := 5;
netz.y_min := -5;
netz.y_max := 5;
(* Initialisierung *)
init_netz(netz);
init_function(f,netz);
(* Ausgabe des Netzes *)
ausg_netz(netz,true);
repeat until conin(2)=' ';
clear_screen;
netz_alt:=netz; (* fĂŒr evtl.spĂ€tere Verwendung *)
(* Ănderung der Funktion *)
netz.x_min := -2;
netz.x_max := 2;
netz.y_min := -1;
netz.y_max := 1;
(* Neuinitialisierung der Funktion *)
init_function(g,netz);
(* Neuausgabe *)
ausg_netz(netz,true);
repeat until conin(2)=' ';
show_mouse;
exit_gem;
end;
end.
Listing 6: Ausgabeprogramm fĂŒr Netzgraphik/program netz_2