home *** CD-ROM | disk | FTP | other *** search
- {
- ┌───────────────────────────────────────────────────────────────────────────┐
- │ │
- │ Algorithmen zur grafischen Darstellung einer Funktion z = F(x,y). │
- │ │
- │ Version 1.0 │
- │ │
- ├───────────────────────────────────────────────────────────────────────────┤
- │ Copyright (C) 1991, Hans-Jürgen Herrler und Dieter Sosna │
- └───────────────────────────────────────────────────────────────────────────┘
- }
-
- { Soll in der Routine AlphaPunktSetzen geprüft werden, ob 0 <= x <= GetMaxX
- und 0 <= y <= GetMaxY ist, muß die folgende Compilerdirektive entfernt
- werden: }
-
- {$DEFINE ALPHA-}
-
- {$A+,F+,R-,S-}
-
- UNIT Plot;
-
- INTERFACE
-
- USES Graph;
-
- CONST
- { Maximalzahl von Gitterlinien in x- bzw. y-Richtung: }
- MaxGitter = 100;
-
- TYPE
- Float = {$IFOPT N+} Single; { falls 80x87 vorhanden ist;
- es ist auch Double möglich}
- {$ELSE} Real;
- {$ENDIF}
-
- FloatPointer = ^Float;
-
- { Beschreibung der Matrix, die die Werte der darzustellenden Funktion
- enthält: }
- MatrixParameter = Record
- XGitter, { Zahl der Gitterlinien bzw. Stützstellen }
- YGitter : Word; { der Funktion in X- bzw. Y-Richtung, die
- Zählung beginnt jeweils bei 1! }
- ZMin, ZMax : Float { kleinster und größter Funktionswert }
- END;
-
- Projektionsart = (ZentralProjektion, ParallelProjektion);
-
- { Beschreibung des erzeugten Bildes: }
- BildParameter = Record
- SchirmLinks, { Bildschirm-Ausschnitt, in dem die }
- SchirmRechts, { Darstellung erfolgt. Angegeben als }
- SchirmOben, { als Bruchteil von GetMaxX, GetMaxY }
- SchirmUnten : Float;
- { Farben: }
- ColorLine, { Linienfarbe }
- ColorFrame, { Bildrahmen }
- { Folgende Farben nur für Volumenperspektive: }
- ColorFillO, { Füllfarbe Oberseite }
- ColorFillU, { Füllfarbe Unterseite }
- ColorFillX, { Füllfarbe Seitenflächen parallel X}
- ColorFillY : Byte; { Füllfarbe Seitenflächen parallel Y}
- Alpha, { horizontaler Betrachtungswinkel }
- Gamma : Integer; { vertikaler Betrachtungswinkel }
- Case
- Projekt : Projektionsart {hier gewünschte Projektion angeben }
- Of
- ZentralProjektion:
- (Abstand, { Betrachtungsabstand }
- Brennweite : Word); { Brennweite }
- ParallelProjektion:
- (BrennweiteZuAbstand: Float) { Beeinflußt Größe bei Parallel-
- projektion }
- END;
-
- { ------------------------------------------------------------------------- }
-
- PROCEDURE VolumenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
- BildParm: BildParameter; UseHeap: Boolean);
- PROCEDURE AlphaScheibenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
- BildParm: BildParameter);
- PROCEDURE GitterFlaechenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
- BildParm: BildParameter; UseHeap: Boolean);
-
- FUNCTION Element(P: Pointer; i, j, SpaltenLen: Word): FloatPointer;
- { Liefert Zeiger auf das Matrixelement(i, j) zurück. }
-
- { ========================================================================= }
-
- IMPLEMENTATION
-
- TYPE
- GitterPktRec = Record
- XNr, YNr: Word; { Indizes des Gitterpunktes }
- ZPtr : FloatPointer; { Zeiger auf Z-Wert }
- END;
-
- { Konstanten für die Transformation in Gerätekoordinaten und zur
- Bilderzeugung: }
- TransformationsParameter = Record
- D1, D2, D3, D4, D5, { Transformationskonstanten, }
- D6, D7, D8, { beschreiben die resultierende }
- T1, T2, T3, { Matrix aller Transformationen }
- GTX, GTY : Float;
- ZSockel : Float;
- iKrit, jKrit : Integer; { "kritische" Gitterlinien, abhängig
- von der Lage des Augpunktes }
- VonUntenSichtbar : Boolean;
- Richtung : 'X'..'Y'; { Richtung bei Scheibenperspektive }
- XGitter,
- YGitter : Word;
- Case
- Projekt : Projektionsart Of
- ParallelProjektion:
- (BrennweiteZuAbstand: Float) { Beeinflußt Größe bei Parallel-
- projektion }
- END;
-
- TempArray = Array[1..MaxGitter*MaxGitter] Of PointType;
- TempArrayPtr= ^TempArray;
-
- VAR
- TrfParm : TransformationsParameter;
- SizeOfFloat : Word;
-
- { ------------------------------------------------------------------------- }
- FUNCTION Minimum(a, b: Integer): Integer;
- BEGIN
- IF a < b THEN Minimum := a ELSE Minimum := b
- END;
- { ------------------------------------------------------------------------- }
- FUNCTION Maximum(a, b: Integer): Integer;
- BEGIN
- IF a > b THEN Maximum := a ELSE Maximum := b
- END;
- { ------------------------------------------------------------------------- }
- {$L ZEIGER.OBJ}
- FUNCTION Element(P: Pointer; i, j, SpaltenLen: Word): FloatPointer;
- External;
- { Liefert Zeiger auf das Matrixelement(i, j) zurück. }
- { ------------------------------------------------------------------------- }
- PROCEDURE IncPtr(Var P: FloatPointer);
- External;
- { Rückt den bereits normalisierten(!) Zeiger auf das folgende Matrixelement.}
- { ------------------------------------------------------------------------- }
- PROCEDURE Transformation(MatrixParm: MatrixParameter;
- BildParm: BildParameter);
- { Berechnet Transformationskonstanten entsprechend der gewünschten
- Darstellung. Aufruf darf erst nach InitGraph erfolgen! }
-
- CONST
- { Folgende Konstanten charakterisieren die Transformation der Funktion:
- Abzubildender Quader in Weltkoordinaten (Funktion nach der Skalierung) }
- XWMin = -100; XWMax = +100;
- YWMin = -100; YWMax = +100;
- ZWMin = -50; ZWMax = +50;
- { Fenster in Weltkoordinaten ("Mattscheibe" in der Fotografie) }
- UMin = -18; UMax = +18;
- VMin = -12; VMax = +12;
-
- Sockel = 0.2; { Sockelhöhe als Bruchteil von ZMax-ZMin }
-
- VAR
- AlphaBogen, GammaBogen, { Betrachtungswinkel im Bogenmaß }
- SA, SG, CA, CG, { Sinus und Cosinus von Alpha bzw Gamma }
- SFX, STX, SFY, STY, { Konstanten der Skalierungs-Transformation }
- SFZ, STZ,
- GFX, GFY : Float; { Konstanten der Geräte-Transformation }
- { Zur Bezeichnung:
- S = Skalierungs-Transformation: reale Funktion -> Weltkoordinaten
- G = Geräte-Transformation:
- Fenster in Weltkoord. -> Ausschnitt in Gerätekoordinaten
- F = Faktor T = Translation }
- SchirmL, SchirmR, { Bildschirm-Ausschnitt in }
- SchirmO, SchirmU : Integer; { Geräte-Koordinaten }
- AX, AY : Float; { Weltkoordinaten des Augpunktes }
- a, b : Float; { Hilfsvariable }
- Sektor : 0..7; { zur Klassifikation von Alpha }
-
- BEGIN
- WITH TrfParm DO BEGIN
- Projekt := BildParm.Projekt;
- IF Projekt = ParallelProjektion THEN
- BrennweiteZuAbstand := BildParm.BrennweiteZuAbstand;
- XGitter := MatrixParm.XGitter;
- YGitter := MatrixParm.YGitter;
-
- { ViewPort festlegen, Rahmen zeichnen }
- WITH BildParm DO BEGIN
- SchirmL := Round(GetMaxX * SchirmLinks);
- SchirmR := Round(GetMaxX * SchirmRechts);
- SchirmO := Round(GetMaxY * SchirmOben);
- SchirmU := Round(GetMaxY * SchirmUnten);
- SetColor(ColorFrame);
- Rectangle(SchirmL, SchirmO, SchirmR, SchirmU);
- SetViewPort(Succ(SchirmL), Succ(SchirmO),
- Pred(SchirmR), Pred(SchirmU), ClipOn);
-
- { Berechnung von Transformationskonstanten }
- AlphaBogen := Alpha * Pi / 180; GammaBogen := Gamma * Pi/ 180;
- SA := Sin(AlphaBogen); SG := Sin(GammaBogen);
- CA := Cos(AlphaBogen); CG := Cos(GammaBogen);
- END;
-
- WITH MatrixParm DO BEGIN
- IF ZMax = ZMin THEN ZMax := Abs(ZMin) * 2 + 1;
- ZSockel := ZMin - (ZMax - ZMin) * Sockel;
- SFX := (XWMax - XWMin)/Pred(XGitter); STX := XWMin - SFX;
- SFY := (YWMax - YWMin)/Pred(YGitter); STY := YWMin - SFY;
- SFZ := (ZWMax - ZWMin)/(ZMax-ZSockel); STZ := ZWMin - SFZ * ZSockel
- END;
-
- GFX := (SchirmR - SchirmL)/(UMax - UMin);
- GTX := - GFX * UMin;
- GFY := (SchirmO - SchirmU)/(VMax - VMin);
- GTY := SchirmU - GFY * VMin - SchirmO;
- { Eigentlich: GTX := SchirmL - GFX * UMin
- GTY := SchirmU - GFY * VMin ,
- durch das eingestellte Grafikfenster ergeben sich aber Verschiebungen! }
- D1 := GFX * SFX * CA; D2 := GFX * SFY * SA;
- D3 := -GFY * SFX * SA * SG; D4 := GFY * SFY * CA * SG;
- D5 := GFY * SFZ * CG;
- T1 := GFX *(STX * CA + STY * SA);
- T2 := GFY *(-STX * SA * SG + STY * CA * SG + STZ * CG);
-
- WITH BildParm DO IF Projekt = ZentralProjektion THEN BEGIN
- D6 := -SFX * SA * CG / Brennweite;
- D7 := SFY * CA * CG / Brennweite;
- D8 := -SFZ * SG / Brennweite;
- T3 := (-STX * SA * CG + STY * CA * CG - STZ * SG + Abstand)/Brennweite
- END;
-
- { Richtung der Projektionsstrahlen bzw. Lage des Auges: }
- WITH BildParm DO IF Projekt = ParallelProjektion THEN BEGIN
- Sektor := ((Alpha + 180) Div 45) Mod 8;
- CASE Sektor OF
- 0,1,2,3 : jKrit := -1;
- 4,5,6,7 : jKrit := XGitter+2
- END;
- CASE Sektor OF
- 2,3,4,5 : iKrit := -1;
- 0,1,6,7 : iKrit := YGitter+2
- END;
- CASE Sektor OF { Vorzugsrichtung bei ScheibenPerspektive }
- 0,3,4,7 : Richtung := 'X';
- 1,2,5,6 : Richtung := 'Y'
- END;
- IF Gamma < 0 THEN VonUntenSichtbar := True
- ELSE VonUntenSichtbar := False;
- END
-
- ELSE BEGIN { ZentralProjektion }
- AX := Abstand * CG * SA; AY := - Abstand * CG * CA;
- a := (XGitter - 1) / (XWMax - XWMin);
- b := 1 - a * XWMin;
- jKrit := Trunc(a * AX + b);
- a := (YGitter - 1) / (YWMax - YWMin);
- b := 1 - a * YWMin;
- iKrit := Trunc(a * AY + b);
- IF Abstand * SG < ZWMin THEN VonUntenSichtbar := True
- ELSE VonUntenSichtbar := False
- END
- END
- END; { Transformation }
- { ------------------------------------------------------------------------- }
- PROCEDURE Projektion(RaumPkt: GitterPktRec; Var BildPkt: PointType);
- { Transformation in Gerätekoordinaten }
- VAR
- FT : Float;
- BEGIN
- WITH TrfParm DO WITH RaumPkt DO BEGIN
- IF Projekt = ZentralProjektion THEN
- FT := 1 / (D6 * XNr + D7 * YNr + D8 * ZPtr^ + T3)
- ELSE { ParallelProjektion }
- FT := BrennweiteZuAbstand;
- BildPkt.X := Round((D1 * XNr + D2 * YNr + T1)* FT + GTX);
- BildPkt.Y := Round((D3 * XNr + D4 * YNr + D5 * ZPtr^ + T2)* FT + GTY)
- END
- END; { Projektion }
- { ------------------------------------------------------------------------- }
- FUNCTION VorabProjektion(VAR Matrix; VAR TrfMatrix: TempArrayPtr): Boolean;
- { Projiziert die gesamte Matrix vorab auf Gerätekoordinaten, falls temporär
- genug Platz auf dem Heap vorhanden ist. }
- VAR
- Size : LongInt;
- i, j : Word;
- GP : GitterPktRec;
- BEGIN
- WITH TrfParm DO BEGIN
- Size := XGitter * YGitter * SizeOf(PointType);
- IF MaxAvail >= Size THEN BEGIN
- VorabProjektion := True;
- GetMem(TrfMatrix, Size);
- WITH GP DO FOR i := 1 TO YGitter DO BEGIN
- YNr := i;
- XNr := 1;
- ZPtr := Element(@Matrix, YNr, XNr, XGitter);
- Projektion(GP, TempArray(TrfMatrix^)[Pred(i)*XGitter+1]);
- FOR j := 2 TO XGitter DO BEGIN
- Inc(XNr);
- IncPtr(ZPtr);
- Projektion(GP, TempArray(TrfMatrix^)[Pred(i)*XGitter+j])
- END
- END
- END
- ELSE VorabProjektion := False
- END
- END;
-
- { ======= VolumenPerspektive ============================================== }
-
- PROCEDURE VolumenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
- BildParm: BildParameter; UseHeap: Boolean);
- VAR
- Vorab : Boolean;
- TrfMatrix : TempArrayPtr;
- { ......................................................................... }
- PROCEDURE Prisma(i, j: Integer);
- { Zeichnet Prisma unter Berücksichtigung der Sichtbarkeit }
- TYPE
- EckpunktNr = 1..8; { 8 Eckpunkte eines Prismas werden nummeriert }
- FlaechenType = Array[1..4] of EckpunktNr;
- CONST
- { Charakterisieren jedes Eckpunktes des Prismas. }
- Index : Array[EckpunktNr,1..2] of Byte =
- ((0, 0), (1, 0), (1, 1), (0, 1),
- (0, 0), (1, 0), (1, 1), (0, 1));
- { Charakterisieren der 6 Flächen des Prismas durch ihre Eckpunktnummern: }
- Oben : FlaechenType = (5, 6, 7, 8);
- Unten : FlaechenType = (1, 2, 3, 4);
- LinksX : FlaechenType = (1, 4, 8, 5);
- RechtsX : FlaechenType = (2, 3, 7, 6);
- LinksY : FlaechenType = (1, 2, 6, 5);
- RechtsY : FlaechenType = (4, 3, 7, 8);
- { ......................................................................... }
- PROCEDURE Viereck(Flaeche: FlaechenType);
- { Angegebene Fläche zeichnen (Inneres dabei löschen) }
- VAR
- k : 1..4;
- Ecke : EckPunktNr;
- GP : GitterPktRec;
- Polygon : Array[1..4] Of PointType;
- BEGIN
- WITH GP DO FOR k := 1 TO 4 DO BEGIN
- Ecke := Flaeche[k];
- XNr := j + Index[Ecke, 1];
- YNr := i + Index[Ecke, 2];
- IF Ecke < 5 THEN ZPtr := @TrfParm.ZSockel
- ELSE ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[k])
- END;
- FillPoly(4, Polygon)
- END; { Viereck }
- { ......................................................................... }
- PROCEDURE ViereckOben;
- { Entspricht dem Prozeduraufruf Viereck(Oben), ist aber optimiert! }
- VAR
- GP : GitterPktRec;
- Polygon : Array[1..4] Of PointType;
- BEGIN
- IF Vorab THEN WITH TrfParm DO BEGIN
- Polygon[1] := TempArray(TrfMatrix^)[Pred(i)*XGitter + j];
- Polygon[2] := TempArray(TrfMatrix^)[Pred(i)*XGitter + Succ(j)];
- Polygon[3] := TempArray(TrfMatrix^)[i*XGitter + Succ(j)];
- Polygon[4] := TempArray(TrfMatrix^)[i*XGitter + j]
- END
- ELSE WITH GP DO BEGIN
- XNr := j; YNr := i;
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[1]);
- Inc(XNr);
- IncPtr(ZPtr);
- Projektion(GP, Polygon[2]);
- Dec(XNr); Inc(YNr);
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[4]);
- Inc(XNr);
- IncPtr(ZPtr);
- Projektion(GP, Polygon[3])
- END;
- FillPoly(4, Polygon)
- END; { ViereckOben }
- { ......................................................................... }
- BEGIN { Prisma }
- SetFillStyle(SolidFill, BildParm.ColorFillO);
- ViereckOben;
- WITH TrfParm DO BEGIN
- { Nur wirklich sichtbare Seitenflächen zeichnen: }
- IF (j=1) and (j>jKrit) THEN BEGIN
- SetFillStyle(SolidFill, BildParm.ColorFillY);
- Viereck(LinksX)
- END;
- IF (j=pred(XGitter)) and (j<jKrit) THEN BEGIN
- SetFillStyle(SolidFill, BildParm.ColorFillY);
- Viereck(RechtsX)
- END;
- IF (i=1) and (i>iKrit) THEN BEGIN
- SetFillStyle(SolidFill, BildParm.ColorFillX);
- Viereck(LinksY)
- END;
- IF (i=pred(YGitter)) and (i<iKrit) THEN BEGIN
- SetFillStyle(SolidFill, BildParm.ColorFillX);
- Viereck(RechtsY)
- END;
- IF VonUntenSichtbar THEN BEGIN
- SetFillStyle(SolidFill, BildParm.ColorFillU);
- Viereck(Unten)
- END
- END
- END; { Prisma }
- { ......................................................................... }
- VAR
- i, j : Integer;
-
- BEGIN { VolumenPerspektive }
- Transformation(MatrixParm, BildParm);
- Vorab := False;
- IF UseHeap THEN Vorab := VorabProjektion(Matrix, TrfMatrix);
- SetColor(BildParm.ColorLine);
-
- WITH TrfParm DO BEGIN
-
- FOR i := 1 TO Pred(Minimum(iKrit, YGitter)) DO
- FOR j := 1 TO Pred(Minimum(jKrit, XGitter)) DO Prisma(i, j);
-
- FOR j := Pred(XGitter) DOWNTO Maximum(jKrit, 1) DO
- FOR i := 1 TO Pred(Minimum(iKrit, YGitter)) DO Prisma(i, j);
-
- FOR j := 1 TO Pred(Minimum(jKrit, XGitter)) DO
- FOR i := Pred(YGitter) DOWNTO Maximum(iKrit, 1) DO Prisma(i, j);
-
- FOR i := Pred(YGitter) DOWNTO Maximum(iKrit, 1) DO
- FOR j := Pred(XGitter) DOWNTO Maximum(jKrit, 1) DO Prisma(i, j);
-
- IF Vorab THEN FreeMem(TrfMatrix, XGitter*YGitter*SizeOf(PointType))
- END;
-
- SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn)
- END; { VolumenPerspektive }
-
- { ======= Modifizierter Alpha-Puffer-Algorithmus ========================== }
-
- TYPE
- PointArrayType = Array[1..MaxGitter+3] Of PointType;
- VAR
- maxTemp, minTemp,
- AlphaMax, AlphaMin : Array[0..719] of Integer;
- { ausreichend für CGA, HGC, EGA }
- AlphaColor : Byte;
-
- {$IFDEF ALPHA-} {$L ALPHA-.OBJ}
- {$ELSE} {$L ALPHA.OBJ}
- {$ENDIF}
-
- PROCEDURE AlphaLine(P1, P2: PointType); External;
- {Zeichnet eine Linie von P1 nach P2 gemäß modifiziertem α-Puffer-Algorithmus}
-
- PROCEDURE InitAlphaPuffer; External;
-
- PROCEDURE AlphaPufferAktualisieren; External;
-
- { ------------------------------------------------------------------------- }
- PROCEDURE AlphaPolyLine(NumPoints: Word; PolyPoints: PointArrayType);
- VAR
- i : Word;
- BEGIN
- FOR i := 1 TO Pred(NumPoints) DO
- AlphaLine(PolyPoints[i], PolyPoints[Succ(i)])
- END;
-
- { ======= AlphaScheibenPerspektive ======================================== }
-
- VAR
- Polygon : PointArrayType;
-
- PROCEDURE AlphaScheibenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
- BildParm: BildParameter);
- { ......................................................................... }
- PROCEDURE AlphaScheibeX(i: integer); { eine Scheibe parallel X-Achse }
- VAR
- k : Word;
- GP : GitterPktRec;
- BEGIN
- WITH GP DO BEGIN
- XNr := 1;
- YNr := i;
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[1]);
- FOR k := 2 TO TrfParm.XGitter DO BEGIN
- Inc(XNr);
- IncPtr(ZPtr);
- Projektion(GP, Polygon[k])
- END;
- ZPtr := @TrfParm.ZSockel;
- Projektion(GP, Polygon[Succ(TrfParm.Xgitter)]);
- XNr := 1;
- Projektion(GP, Polygon[TrfParm.Xgitter+2]);
- Polygon[TrfParm.XGitter+3] := Polygon[1];
- END;
- AlphaPolyLine(TrfParm.XGitter+3, Polygon);
- AlphaPufferAktualisieren
- END; { AlphaScheibeX }
- { ......................................................................... }
- PROCEDURE AlphaScheibeY(j: integer); { eine Scheibe parallel Y-Achse }
- VAR
- k : Word;
- GP : GitterPktRec;
- BEGIN
- WITH GP DO BEGIN
- XNr := j;
- YNr := 1;
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[1]);
- FOR k := 2 TO TrfParm.YGitter DO BEGIN
- Inc(YNr);
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[k])
- END;
- ZPtr := @TrfParm.ZSockel;
- Projektion(GP, Polygon[Succ(TrfParm.Ygitter)]);
- YNr := 1;
- Projektion(GP, Polygon[TrfParm.Ygitter+2]);
- Polygon[TrfParm.YGitter+3] := Polygon[1];
- END;
- AlphaPolyLine(TrfParm.YGitter+3, Polygon);
- AlphaPufferAktualisieren
- END; { AlphaScheibeY }
- { ......................................................................... }
- VAR
- i, j : Integer;
- BEGIN { AlphaScheibenPerspektive }
- Transformation(MatrixParm, BildParm);
- InitAlphaPuffer;
- AlphaColor := BildParm.ColorLine;
-
- WITH TrfParm DO
- IF Richtung = 'X' THEN BEGIN { Scheiben parallel X-Achse }
- FOR i := Maximum(Succ(iKrit), 1) TO YGitter DO AlphaScheibeX(i);
- FOR i := Minimum(iKrit, YGitter) DOWNTO 1 DO AlphaScheibeX(i)
- END
- ELSE BEGIN { Richtung = 'Y' , d.h. Scheiben parallel Y-Achse }
- FOR j := Maximum(Succ(jKrit), 1) TO XGitter DO AlphaScheibeY(j);
- FOR j := Minimum(jKrit, XGitter) DOWNTO 1 DO AlphaScheibeY(j)
- END;
-
- SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn)
- END; { AlphaScheibenPerspektive }
-
- { ======= GitterFlächenPerspektive ======================================== }
-
- PROCEDURE GitterFlaechenPerspektive(VAR Matrix; MatrixParm: MatrixParameter;
- BildParm: BildParameter; UseHeap: Boolean);
- VAR
- Vorab : Boolean;
- { Wurde die ganze Matrix vorab auf Gerätekoordinaten transformiert? }
- TrfMatrix : TempArrayPtr;
-
- { ......................................................................... }
- PROCEDURE Feld(i, j: Integer); { Zeichnet ein Elementarfeld }
- VAR
- GP : GitterPktRec;
- Polygon : Array[1..4] Of PointType;
- BEGIN
- IF Vorab THEN WITH TrfParm DO BEGIN
- Polygon[1] := TempArray(TrfMatrix^)[Pred(i)*XGitter + j];
- Polygon[2] := TempArray(TrfMatrix^)[Pred(i)*XGitter + Succ(j)];
- Polygon[3] := TempArray(TrfMatrix^)[i*XGitter + Succ(j)];
- Polygon[4] := TempArray(TrfMatrix^)[i*XGitter + j]
- END
- ELSE WITH GP DO BEGIN
- XNr := j; YNr := i;
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[1]);
- Inc(XNr);
- IncPtr(ZPtr);
- Projektion(GP, Polygon[2]);
- Dec(XNr); Inc(YNr);
- ZPtr := Element(@Matrix, YNr, XNr, TrfParm.XGitter);
- Projektion(GP, Polygon[4]);
- Inc(XNr);
- IncPtr(ZPtr);
- Projektion(GP, Polygon[3])
- END;
-
- WITH TrfParm DO BEGIN
- IF (i <= iKrit) or (i = 1) THEN AlphaLine(Polygon[1], Polygon[2]);
- IF (j >= jKrit) or (j = Pred(XGitter)) THEN
- AlphaLine(Polygon[2], Polygon[3]);
- IF (i >= iKrit) or (i = Pred(YGitter)) THEN
- AlphaLine(Polygon[3], Polygon[4]);
- IF (j <= jKrit) or (j = 1) THEN AlphaLine(Polygon[4], Polygon[1])
- END;
-
- AlphaPufferAktualisieren
- END; { Feld }
- { ......................................................................... }
- VAR
- i, j : Integer;
-
- BEGIN { GitterFlaechenPerspektive }
- Transformation(MatrixParm, BildParm);
- Vorab := False;
- IF UseHeap THEN Vorab := VorabProjektion(Matrix, TrfMatrix);
- AlphaColor := BildParm.ColorLine;
- InitAlphaPuffer;
-
- WITH TrfParm DO BEGIN
- FOR i := Maximum(iKrit, 1) TO Pred(YGitter) DO
- FOR j := Minimum(jKrit, Pred(XGitter)) DOWNTO 1 DO Feld(i, j);
-
- FOR j := Maximum(succ(jKrit), 1) TO Pred(XGitter) DO
- FOR i := Maximum(iKrit, 1) TO Pred(YGitter) DO Feld(i, j);
-
- FOR i := Pred(Minimum(iKrit, YGitter)) DOWNTO 1 DO
- FOR j := Maximum(jKrit, 1) TO Pred(XGitter) DO Feld(i, j);
-
- FOR j := Pred(Minimum(jKrit, XGitter)) DOWNTO 1 DO
- FOR i := Pred(Minimum(iKrit, YGitter)) DOWNTO 1 DO Feld(i, j);
-
- IF Vorab THEN FreeMem(TrfMatrix, XGitter * YGitter * SizeOf(PointType))
- END;
-
- SetViewPort(0, 0, GetMaxX, GetMaxY, ClipOn)
- END; { GitterFlaechenPerspektive }
-
- { ======= Initialisierungen =============================================== }
-
- BEGIN
- SizeOfFloat := SizeOf(Float)
- END.