home *** CD-ROM | disk | FTP | other *** search
- PROGRAM Funktionsplotter;
- (* Umsetzung von Plot3D.PAS aus TOOLBOX 03/89 für Plotter mit HPGL *)
- (* angepasst wurden : PRC InitGraf
- PRC PlotPoint
- neue Konstante : XOffset, YOffset zur Positionierung des Plots *)
- (* erfordert die UNIT HPGL *)
- (* Compiler : Turbo-Pascal 5.0
- Pgm.Vers.: 1.0.a
- Stand : 21.03.89 *)
-
- (*$R+*)
-
- USES Crt, Graph, HPGL; (* Turbo 4.0 Units *)
-
- { Für IBM VGA-Grafik und für den Plotter }
- CONST
- xmin_res = 0;
- xmax_res = 639;
- ymin_res = 0;
- ymax_res = 479;
- PenCol = 1;
- BackgCol = 15;
-
- (* Für den Plotter *)
- CONST XOffset = 75;
- YOffset = 500;
- (* im oberen Drittel eines DIN A4-Blattes *)
-
- TYPE KoorPoint = ^PointRec;
- PointRec = RECORD
- KoorX, KoorY : INTEGER;
- PNext : KoorPoint
- END;
-
- VAR KYmin, KYmax : ARRAY[xmin_res..xmax_res]
- OF INTEGER;
- First : BOOLEAN;
- Xmin, Xmax, Ymin,
- Ymax, Dx, Dy, fi,
- csfi, snfi, Xeinheit,
- Yeinheit, Zeinheit : REAL;
- Xnull, Ynull, PenX,
- PenY : INTEGER;
- DynPoint : KoorPoint;
- AktColor : INTEGER;
-
- {---------------------------------------------------------
- SYSTEMABHÄNGIGE PROZEDUREN
- Sie muessen diese Prozeduren vor der Compilierung auf
- Ihren Computer und das benutzte Grafiksystem anpassen.
- ---------------------------------------------------------}
-
- PROCEDURE InitGraf;
-
- VAR card,mode : INTEGER; {Var. für Turbo Pascal BGI}
-
- BEGIN
- {Turbo Pascal BGI-Routinen}
- DetectGraph(card,mode);
- InitGraph(card,mode,'');
- SetBkColor(BackgCol);
- { hier wird sonst die Routine eingefuegt, die die
- Grafikroutinen initialisiert }
-
- (* PLOTTER INITIALISIEREN *)
- OpenGraphik ('PRN'); (* oder z.B.: 'C:Test.Dat' *)
- PFaktor := 10;
- (* da in CRT-Pixels und nicht in cm gezeichnet wird, wird der
- Faktor für die Schrittweite von 40 auf 10 reduziert !
- Die einzelnen Punkte liegen sonst zu weit auseinander ! *)
- P_SetColor (2);
- P_Rectangle (XOffset, YOffset, XOffset + xmax_res, YOffset + ymax_Res);
- END;
-
-
- PROCEDURE Clear;
- BEGIN
- {Turbo Pascal BGI-Routinen}
- ClearDevice;
- { Grafikbildschirm loeschen }
- END;
-
-
- PROCEDURE TextMode;
- BEGIN
- {Turbo Pascal BGI-Routinen}
- CloseGraph;
- { 80 Zeichen Textbildschirm einschalten }
- END;
-
-
- PROCEDURE PenColor(Col : INTEGER {ggf. Farbtyp eintragen});
- BEGIN
- AktColor := Col;
- { auf angegebene Farbe schalten }
- END;
-
-
- PROCEDURE PlotPoint(X, Y: INTEGER);
-
-
- BEGIN
-
- {Turbo Pascal BGI-Routinen}
- PutPixel(X,Y,AktColor);
- { einen Punkt in der eingeschalteten Farbe an der
- Stelle x, y setzen }
-
- (* Plotterpunkt setzen *)
- P_PutPixel (XOffset + X, YOffset + ymax_res - Y, AktColor );
- (* für y : der Plotter hat den Ursprung links unten ! *)
-
- END;
-
- {---------------------------------------------------------
- ENDE SYSTEMABHÄNGIGE PROZEDUREN
- Ab hier ist das Programm auf Turbo-Pascal
- rechnerunabhaengig lauffaehig.
- ---------------------------------------------------------}
-
- {ControlXY:
- - testet ob ein Punkt von bereits vorhandenen Punkten
- verdeckt wird und ob er auf den Bildschirm passt.
- - aktualisiert die Vergleichsarrays.
- - Funktionswert ist der Wahrheitswert, der bestimmt
- ob der Punkt gesetzt werden darf:
- TRUE = setzen
- FALSE = nicht setzen
- }
- FUNCTION ControlXY (VAR X, Y : INTEGER) : BOOLEAN;
-
- VAR al, bl : BOOLEAN;
-
- BEGIN
- (* write (lst, x, '!', y); *)
- bl := (X <= xmax_res) AND (X >= xmin_res);
- al := bl;
- bl := bl AND (Y <= ymax_res) AND (Y >= ymin_res);
- IF First THEN BEGIN {wird gerade erste Linie gezeichnet?}
- KYmin[X] := Y; {wenn ja: Vergleichsarray aufbauen }
- KYmax[X] := Y
- END;
- IF al AND (NOT(First)) THEN
- IF Y > KYmax[X] THEN KYmax[X] := Y
- ELSE IF Y < KYmin[X] THEN
- KYmin[X] := Y
- ELSE bl := FALSE; {Punkt wird verdeckt}
- ControlXY := bl
- END;
-
- {---------------------------------------------------------}
- {DotXY:
- - setzt Bildschirmpunkt, falls er nicht verdeckt wird }
-
- PROCEDURE dotXY(X, Y: INTEGER);
- BEGIN
- IF ControlXY(X, Y) THEN PlotPoint(X, Y)
- END;
-
- {---------------------------------------------------------}
- {Do_Line:
- - zieht eine Linie von Punkt x1, y1 nach Punkt x2, y2.
- - geht tatsaechlich von P(x1, y1) aus, fuehrt also kein
- Koordinatentausch aus.
- - ist eine Modifikation der in PASCAL 4/'87
- veroeffentlichten Prozedur. }
-
- PROCEDURE do_line (x1, y1, x2, y2: INTEGER);
-
- VAR Dx, Dy, dA, Zaehler, X, Y, i : INTEGER;
-
- BEGIN
- dA := 0;
- i := 1;
- Dx := x2 - x1;
- Dy := y2 - y1;
- IF Dy < 0 THEN BEGIN
- i := -1;
- Dy := -Dy;
- Dx := -Dx
- END;
- dotXY(x1, y1);
- X := x1;
- Y := y1;
- IF Dx >= 0 THEN
- IF Dx < Dy THEN
- FOR Zaehler := 1 TO Pred(Dy) DO
- IF dA < 0 THEN BEGIN
- X := X + i;
- Y := Y + i;
- dotXY(X, Y);
- dA := dA + Dy - Dx
- END
- ELSE BEGIN
- Y := Y + i;
- dotXY(X, Y);
- dA := dA - Dx
- END
- ELSE
- FOR Zaehler := 1 TO Pred(Dx) DO
- IF dA <= 0 THEN BEGIN
- X := X + i;
- dotXY(X, Y);
- dA := dA + Dy
- END
- ELSE BEGIN
- X := X + i;
- Y := Y + i;
- dotXY(X, Y);
- dA := dA + Dy - Dx
- END
- ELSE IF abs(Dx) >= Dy THEN
- FOR Zaehler := 1 TO Pred(abs(Dx)) DO
- IF dA <= 0 THEN BEGIN
- X := X - i;
- dotXY(X, Y);
- dA := dA + Dy
- END
- ELSE BEGIN
- X := X - i;
- Y := Y + i;
- dotXY(X, Y);
- dA := dA + Dx + Dy
- END
- ELSE FOR Zaehler := 1 TO Pred(Dy) DO
- IF dA < 0 THEN BEGIN
- X := X - i;
- Y := Y + i;
- dotXY(X, Y);
- dA := dA + Dx + Dy
- END
- ELSE BEGIN
- Y := Y + i;
- dotXY(X, Y);
- dA := dA + Dx
- END;
- dotXY(x2, y2)
- END;
-
- {--------------------------------------------------------}
- {SetPos: -
- setzt den Anfangspunkt einer relativ gezeichneten Linie.
- LineTo: -
- zieht Linie vom letzten Linienpunkt zum angegebenen. }
-
- PROCEDURE SetPos(X, Y : INTEGER);
- BEGIN
- PenX := X; PenY := Y
- END;
-
- PROCEDURE Lineto(x2, y2 : INTEGER);
- BEGIN
- do_line(PenX, PenY, x2, y2);
- SetPos(x2, y2)
- END;
-
- {---------------------------------------------------------}
- {fkt: -
- hier tragen Sie die Funktion ein, die sie berechnen
- lassen wollen. }
-
- FUNCTION fkt(X, Y : REAL) : REAL;
- BEGIN
- fkt := (X*X*X + X*X - 2*X) * (Y*Y*Y - Y*Y - 2*Y);
- { x(x-1)(x+2) = y(y-2)(y+1) }
- {fkt := x*y; }
- END;
-
- {---------------------------------------------------------}
- {BildPos: -
- errechnet aus den Koordinaten des 3D-Koordinatensystems
- die Bildschirmkoordinaten. }
-
- PROCEDURE BildPos(tx, ty, tz : REAL; VAR ix, iy : INTEGER);
-
- VAR ey : REAL;
-
- BEGIN
- ey := ty * Yeinheit;
- ix := Xnull + Round(tx * Xeinheit + ey * csfi);
- iy := Ynull + Round(tz * Zeinheit + ey * snfi)
- END;
-
- {---------------------------------------------------------}
- {FirstLine:
- - zeichnet die erste Linie des Netzes
- - baut eine einfach verkettete Liste fuer die zuletzt
- berechneten Bildschirmkoordinaten auf (fuer die
- Netzverbindungen in Richtung der y-Achse).
- - baut mit Hilfe von ControlXY die Vergleichsarrays auf}
-
- PROCEDURE FirstLine;
-
- VAR tx, ty : REAL;
- x1, y1 : INTEGER;
- pnt, merk : KoorPoint;
-
- BEGIN
- First := TRUE;
- BildPos(Xmax, Ymin, fkt(Xmax, Ymin), x1, y1);
- SetPos(x1, y1); New(DynPoint); DynPoint^.KoorX := x1;
- DynPoint^.KoorY := y1; New(DynPoint^.PNext);
- pnt := DynPoint^.PNext;
- ty := Ymin;
- tx := Xmax - Dx;
- WHILE tx >= Xmin DO BEGIN
- BildPos(tx, ty, fkt(tx, ty), x1, y1);
- Lineto(x1, y1); pnt^.KoorX := x1;
- pnt^.KoorY := y1; New(pnt^.PNext);
- merk := pnt; pnt := pnt^.PNext;
- tx := tx - Dx
- END;
- First := FALSE; merk^.PNext := NIL
- END;
-
- {---------------------------------------------------------}
- {DoGraph:
- - zeichnet das Netz, dessen "Woelbungen" durch den Wert
- der Funktion fkt angegeben werden.
- - fuer die Netzverbindungen "in den Bildschirm hinein"
- (Y-Richtung) werden die Koordinaten der Netzpunkte
- der vorherigen "Schicht" in einer einfach verketteten
- Liste abgespeichert. }
-
- PROCEDURE DoGraph;
-
- VAR tx, ty, f : REAL;
- x1, y1, x2, y2 : INTEGER;
- pnt : KoorPoint;
-
- BEGIN
- FirstLine;
- ty := Ymin + Dy;
- WHILE ty < Ymax DO BEGIN
- x1 := DynPoint^.KoorX; y1 := DynPoint^.KoorY;
- SetPos(x1, y1);
- BildPos(Xmax, ty, fkt(Xmax, ty), x1, y1);
- Lineto(x1, y1);
- DynPoint^.KoorX := x1; DynPoint^.KoorY := y1;
- pnt := DynPoint^.PNext;
- tx := Xmax - Dx;
- WHILE tx >= Xmin DO BEGIN
- x1 := pnt^.KoorX; y1 := pnt^.KoorY;
- BildPos(tx, ty, fkt(tx, ty), x2, y2);
- do_line(x1, y1, x2, y2);
- pnt^.KoorX := x2; pnt^.KoorY := y2;
- pnt := pnt^.PNext;
- Lineto(x2, y2);
- tx := tx - Dx
- END;
- ty := ty + Dy
- END
- END;
-
- {---------------------------------------------------------}
- {Hier beginnt das Hauptprogramm (Parametereingabe). }
-
- BEGIN
- ClrScr;
- { Default-Einstellungen }
- Xmin := -3; Xmax := 2; Dx := 1.0/8;
- Ymin := -2; Ymax := 3; Dy := 1.0/8;
- Xnull := xmax_res DIV 2; Ynull := ymax_res DIV 2;
- fi := 70;
- snfi := sin(pi * fi / 180);
- csfi := cos(pi * fi / 180);
-
- Xeinheit := 100; Yeinheit := 25; Zeinheit := 1.5;
-
- (* { oder manuelle Eingabe }
- writeln('3D-Zeichnung der Funktion:');
- writeln('f(x, y) = x(x-1)(x+2) * y(y+1)(y-2)');
- writeln;
- write(' kleinstes x-Argument (xMin):');
- readln(xmin);
- write(' groesstes x-Argument (xMax):');
- readln(xmax);
- write('Netzpunkte in x-Richtung (deltaX):');
- readln(dx);
- Dx := (Xmax - Xmin) / Dx;
- writeln;
- write(' kleinstes y-Argument (yMin):');
- readln(ymin);
- write(' groesstes y-Argument (yMax):');
- readln(ymax);
- write('Netzpunkte in y-Richtung (deltaY):');
- readln(dy);
- Dy := (Ymax - Ymin) / Dy;
- writeln;
- write('Bildschirmkoordinate (x) des Ursprung(0/0/0):');
- readln(xNull);
- write('Bildschirmkoordinate (y) des Ursprung(0/0/0):');
- readln(yNull);
- writeln;
- write('Winkel zwischen x- und y-Achse ([Deg]):');
- readln(fi);
- snfi := sin(pi * fi / 180);
- csfi := cos(pi * fi / 180);
- writeln;
- writeln('Anzahl Punkte pro ganzem Funktionswert');
- write('Einheit der x-Achse:'); readln(xEinheit);
- write('Einheit der y-Achse:'); readln(yEinheit);
- write('Einheit der z-Achse:'); readln(zEinheit);
- *)
-
- InitGraf; Clear;
- PenColor(PenCol);
- DoGraph; ReadLn; TextMode
- END.