home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * *
- * Filename : D3L2.c *
- * *
- *****************************************************************
- * *
- * Comment : Dieses File unterstützt alle Level 2 Funktionen *
- * welche für die 3 dimensionale Darstellung *
- * benötigt werden. *
- * *
- * Funktionen *
- * ========== *
- * *
- * ClearCidden() löscht Hiddentabelle *
- * InitHidden() alloziert Hiddentabelle *
- * FreeHidden() gibt Speicher von Hiddentabelle frei *
- * InitRotation() initialisiert Rotationsfaktoren *
- * Trans3d() Transformiert 3D-Werte *
- * CalcScale3d() berechnet die Skalierung *
- * DrawGLine3d() zeichnet eine Gitterlinie *
- * DrawGrid3d() zeichnet die Koordinatenachsen *
- * HiddenLine() berechnet Sichtbarkeit einer Linie *
- * SortFct0() Sortierfunktion 1 *
- * SortFct2() Sortierfunktion 2 *
- * Draw3dCurve() zeichnet die Kurve *
- * DoClipp3D() 3D Clipping *
- * CheckClipp3D() Clipping Hilfsfunktion *
- * Draw3d() Hauptfunktion für 3D-Darstellung *
- * D3Lines() Unterfunktion für Draw3D() *
- * *
- * Rev : V1.0 *
- * *
- * History : V1.0 erstellen dieses Files 26/01/90 *
- * *
- * Doc : Plotlibrary User's Guide *
- * *
- * Bugs : keine bekannten *
- * *
- * Autor : Oesch Silvano *
- * *
- * Datum : 26/01/90 *
- * *
- ****************************************************************/
-
- /****************************************************************
- * *
- * allgemeine Includedateien *
- * *
- ****************************************************************/
-
- #include <math.h>
-
- /****************************************************************
- * *
- * Plotlibrary Includedateien *
- * *
- ****************************************************************/
-
- #include "Plot.h"
- #include "PlotL2.h"
- #include "SuppL2.h"
- #include "GfxL3.h"
- #include "DispL2.h"
- #include "D3L2.h"
-
- /****************************************************************
- * *
- * externe Variablen *
- * *
- ****************************************************************/
-
- extern struct Plot *plot;
- extern int plerr;
-
- extern DATA (*xexpfct)(), /* 10^ oder e^ bzw. ln oder */
- (*xlogfct)(), /* log Funktion für X-Achse */
- (*yexpfct)(), /* 10^ oder e^ bzw. ln oder */
- (*ylogfct)(), /* log Funktion für Y-Achse */
- (*zexpfct)(), /* 10^ oder e^ bzw. ln oder */
- (*zlogfct)(); /* log Funktion für Z-Achse */
-
- /****************************************************************
- * *
- * Globale statische Variablen *
- * *
- ****************************************************************/
-
- static DATA xr1,xr2,xr3, /* Rotationsfaktoren */
- yr1,yr2,yr3, /* für alle drei Achsen */
- zr1,zr2,zr3;
-
- static DATA xoffset, /* Bildverschiebung auf der */
- yoffset, /* Projektionsebene */
- fxscale, /* Einheitsskalierung für */
- fyscale, /* alle Achsen */
- fzscale,
- xscale, /* Skalierung in der Pro- */
- yscale; /* jektionsebene */
-
- static GPT *tv, /* oberer Horizont */
- *bv; /* unterer Horizont */
-
- /****************************************************************
- * *
- * Function : draw3d() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : int allg. Rückgabewert *
- * != FALSE alle klar *
- * == FALSE Fehler *
- * *
- *****************************************************************
- * *
- * Comment : Draw3D() ist die Hauptfunktion der 3D-Darstellung. *
- * Sie ruft die einzelnen Unterfunktionen auf, welche *
- * das System initialisieren und danach werden die *
- * Zeichnungsfunktionen aufgerufen, welche die *
- * Graphik zeichnen. *
- * *
- ****************************************************************/
-
- int draw3d()
- {
- int returnset = TRUE; /* allg. Rückgabewert */
-
- plot->phix = 30; /* feste Rotationswinkel */
- plot->phiy = 40; /* für alle Achsen */
- plot->phiz = 0;
-
- getxsize2d(); /* verfügbare Zeichengrösse */
- getysize2d(); /* verfügbare Zeichengrösse */
-
- if (plot->d3opt & HIDDEN) /* Initialisiere Hiddenline */
- setreturn(inithidden()); /* wenn benötigt */
- if (returnset != FALSE) /* weiter wenn kein Fehler */
- {
- initfunction(); /* log Funktionen init. */
- initrotation(); /* rot. Funktion init. */
- calcstep(&plot->xmin,plot->xmes);
- calcstep(&plot->ymin,plot->ymes);
- calcstep(&plot->zmin,plot->zmes);
- calcscale3d(); /* Skalierung berechnen */
- ClearGraphics(); /* Graphik löschen */
- drawgrid3d(); /* Gitter zeichnen */
- draw3dcurves(); /* 3D Kurve zeichnen */
- }
- if (plot->d3opt & HIDDEN) /* Hiddenline freigeben */
- freehidden(); /* wenn vorhanden */
- return(returnset); /* und zurück */
- }
-
- /****************************************************************
- * *
- * Function : Draw3dCurves() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Draw3DCurves() zeichnet und beschriftet eine drei- *
- * dimensionale Kurve. Die eingestellten Dar- *
- * stellungsoptionen HiddenLine und Crosshatching *
- * werden dabei berücksichtigt. Alle Daten im *
- * Speicher werden zuerst nach ihrer Z-Komponente *
- * sortiert und danach werden gleiche Z-Werte anhand *
- * der X-Werte sortiert. Dadurch wird die ganze *
- * in Schnitte unterteilt in Richtung der Z-Achse. *
- * Die Linien können danach vmo kleineren X-Wert zum *
- * grösseren X-Wert gezeichnet werden. *
- * Beim Crosshatching werden einfach die Sortier- *
- * komponenten vertauscht. Es kann beim Aufzeichen *
- * mit Crosshatching zu Darstellungsfehleren kommen, *
- * da der Hiddenline Algorithmus die Daten in einer *
- * bestimmten Reihenfolge benötigt. Siehe *
- * HiddenLine(). *
- * *
- ****************************************************************/
-
- static void draw3dcurves()
- {
-
- struct Curve *curve=plot->first; /* Kurvenzeiger */
-
- calccolor(curve->color); /* Farbe setzten */
- d3lines(sfct2,sfct0); /* 1 Linienzug */
- if (plot->d3opt & CROSH) /* mit Crosshatching */
- { /* Ja */
- clearhidden(); /* Hidden init. */
- d3lines(sfct0,sfct2); /* 2 Linienzug */
- }
- SetFgColor(TEXTCOL); /* für Text */
- if (curve->titel) /* Wenn Namen */
- printtextabs(curve->titel, /* und schreibe Namen */
- (plot->xpic1+plot->xpic2)/2,
- plot->ysize,T_CX|T_B);
-
- }
-
- /****************************************************************
- * *
- * Function : trans3d() *
- * *
- *****************************************************************
- * *
- * Input : xo,yo,zo,xn,yn *
- * DATA *xo transformierender X-Wert *
- * *yo transformierender Y-Wert *
- * *zo transformierender Z-Wert *
- * int *xn transformierter X-Wert *
- * *yn transformierter Y-Wert *
- * *
- * Output : returnset Rüchgabewert *
- * int returnset *
- * == TRUE gültige Transformation *
- * & XTRANS ungültige X Transformation *
- * & YTRANS ungültige Y Transformation *
- * & ZTRANS ungültige Z Transformation *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion transformiert einen Koordinaten- *
- * punkt in die Bildschirmkoordinaten. Die math. *
- * Beschreibung dieser Funktion ist in der Diplom- *
- * arbeit zu finden. *
- * *
- ****************************************************************/
-
- int trans3d(xo,yo,zo,xn,yn)
- DATA *xo,
- *yo,
- *zo;
- int *xn,
- *yn;
- {
- int returnset = TRUE; /* allg Rückgabewert */
- DATA x,y,z, /* Speicher für die */
- x1,y1,z1, /* Koordinaten */
- divs; /* Projektionsdivisor */
-
- /****************************************************************
- * *
- * Werte Transformation *
- * *
- ****************************************************************/
-
- if (plot->xmes != LIN) /* log Transformation */
- if (*xo > 0.0) /* bereichscheck */
- x = xlogfct(*xo); /* transformieren */
- else /* sonst */
- returnset |=XTRANS; /* Fehler */
- else /* also lineare Trans. */
- x = *xo; /* Wert zuweisen */
-
- if (plot->ymes != LIN) /* log Transformation */
- if (*yo > 0.0) /* bereichscheck */
- y = ylogfct(*yo); /* transformieren */
- else /* sonst */
- returnset |=YTRANS; /* Fehler */
- else /* also lineare Trans. */
- y = *yo; /* Wert zuweisen */
-
- if (plot->zmes != LIN) /* log Transformation */
- if (*zo > 0.0) /* bereichscheck */
- z = zlogfct(*zo); /* transformieren */
- else /* sonst */
- returnset |=ZTRANS; /* Fehler */
- else /* also lineare Trans. */
- z = *zo; /* Wert zuweisen */
-
- if (returnset != TRUE) /* Fehler bei Werttransf. */
- return(returnset); /* mit Fehler zurück */
-
- x = x*fxscale; /* Einheitsskalierung */
- y = y*fyscale; /* alle Achsen haben danach */
- z = z*fzscale; /* einen Range von 10000 */
-
- /****************************************************************
- * *
- * Rotation um x-, y- und z-Achse in dieser Reihenfolge *
- * *
- ****************************************************************/
-
- x1 = x*xr1 + y*xr2 + z*xr3; /* Rotationswerte wurden */
- y1 = x*yr1 + y*yr2 + z*yr3; /* in InitRotation() schon */
- z1 = x*zr1 + y*zr2 + z*zr3; /* berechnet */
-
- /****************************************************************
- * *
- * Projektion auf die Bildschirmebene *
- * *
- ****************************************************************/
-
- divs = z1-plot->zcenter;
- x = (z1*plot->xcenter-x1*plot->zcenter)/divs;
- y = (z1*plot->ycenter-y1*plot->zcenter)/divs;
-
- /****************************************************************
- * *
- * Spiegelung, Skalierung und Rückverschiebung *
- * *
- ****************************************************************/
-
- *xn = (int)(x*xscale)+xoffset; /* X-Achse */
- *yn = (int)(-y*yscale)+yoffset; /* Y-Achse */
-
- return(returnset); /* und zurück */
- }
-
- /****************************************************************
- * *
- * Function : drawgline3d() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : DrawGLine3D() zeichnet eine Gerade mit den ein- *
- * gestellten Transformationswerten. Es werden keine *
- * Kontrollen auf Sichtbarkeit und transformier- *
- * geführt. *
- * *
- ****************************************************************/
-
- void drawgline3d(xs,ys,zs,xe,ye,ze)
- DATA *xs,*ys,*zs,*xe,*ye,*ze;
- {
- int xsn,ysn,xen,yen; /* trans. Werte */
-
- trans3d(xs,ys,zs,&xsn,&ysn); /* Werte transformieren */
- trans3d(xe,ye,ze,&xen,¥);
-
- DrawLine(xsn,ysn,xen,yen); /* Linie Zeichnen */
- }
-
- /****************************************************************
- * *
- * Function : D3Lines() *
- * *
- *****************************************************************
- * *
- * Input : sort1,sort2,opt *
- * int *sort1() Hauptsortierfunktion *
- * int *sort2() Untersortierfunktion *
- * int opt Crosshatchoption *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Unterfunktion von Draw3dCurves. Kommentar siehe *
- * dort. *
- * *
- ****************************************************************/
-
- static void d3lines(sort1,sort2)
- int (*sort1)(DATA *,DATA *),
- (*sort2)(DATA *,DATA *);
- {
- int counter, /* Unterelementzähler */
- ct, /* Elememntzähler */
- datasize, /* Grösse eines Elementes */
- xi1,yi1, /* Startpunkt Bildschirm */
- xi2,yi2, /* Endpunkt Bildschirm */
- i, /* Schleifenzähler */
- set, /* Setindikator */
- clipp; /* clipping Status */
- struct Curve *curve; /* Kurvenzeiger */
- register DATA *val, /* letztes Datenelement */
- *first; /* erstes Element */
- DATA x1,y1,z1, /* Startpunkt real */
- x2,y2,z2; /* Endpunkt real */
-
- curve = plot->first; /* Kurvenzeiger init. */
- datasize = valsize()*sizeof(DATA);
- val = curve->val; /* Datenzeiger init. */
- qsort((void *)curve->val,curve->count,datasize,sort1);
- /* sortiere ganzes Feld */
- ct = 0; /* counter löschen */
- while(ct < curve->count) /* solange Daten vorhanden */
- {
- first = val; /* Startelement */
- counter = 0; /* kein Element */
- do /* suche alle Elemente die */
- { /* gleich sind wie das */
- val +=3; /* Startelement und zähle */
- counter++; /* sie */
- }
- while(!sort1(first,val)); /* Feldvergleich */
-
- if (counter >=2) /* min. Start- und Endpunkt */
- {
- qsort((void *)first,counter,datasize,sort2);
- /* sortieren */
- set = FALSE; /* 1 Element nicht gesetzt */
- clipp = FALSE; /* clipping Status */
- for (i=0;i<counter;i++) /* für alle Punkte */
- {
- x2 = first[0]; /* Endpunkt zuweisen */
- y2 = first[1];
- z2 = first[2];
- if (set) /* Startpunkt gesetzt */
- { /* Ja */
- if (plot->clipp == CLIPP) /* clippen falls notwendig */
- clipp = doclipp3d(&x1,&y1,&z1,&x2,&y2,&z2);
- if (!clipp) /* nur wenn guter Status */
- { /* transformieren */
- if ((trans3d(&x1,&y1,&z1,&xi1,&yi1) == TRUE) and
- (trans3d(&x2,&y2,&z2,&xi2,&yi2) == TRUE))
- { /* nur wenn trans. ok */
-
- /****************************************************************
- * *
- * Wenn HiddenLine erwünscht ist, muss bei CrossHatching der *
- * Startpunkt mit dem Endpunkt vertauscht werden. *
- * *
- ****************************************************************/
-
- if (plot->d3opt & HIDDEN)
- {
- if (sort1 == sfct2)
- hiddenline(xi1,yi1,xi2,yi2);
- else
- hiddenline(xi2,yi2,xi1,yi1);
- }
- else
- DrawLine(xi1,yi1,xi2,yi2);
- }
- }
- }
- x1 = first[0]; /* Startpunkt von letztem */
- y1 = first[1]; /* Punkt nehmen */
- z1 = first[2];
- set = TRUE; /* Startpunkt gesetzt */
- first +=3; /* Nächtes Datenelement */
- }
- }
- ct += counter; /* gezeichnete Punkte add. */
- }
- }
-
- /****************************************************************
- * *
- * Function : drawgrid3d() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : DrawGrid() zeichnet das Gitter auf den Bildschirm *
- * für die 2 dimensionale Darstellung. *
- * *
- ****************************************************************/
-
- static void drawgrid3d()
- {
- int i, /* Schleifenzähler */
- slen, /* Textlänge */
- len, /* Beschriftungslänge Y */
- htsize, /* Zeilenhöhe */
- x1,y1; /* Bildschirmkoordinaten */
-
- char sbuf[] = " "; /* Textpuffer */
-
-
- drawxaxis(); /* Alle drei Achsen auf */
- len = drawyaxis(); /* den Bildschirm zeichnen */
- drawzaxis();
-
- /****************************************************************
- * *
- * Sichtbare Achsenlinien zeichnen *
- * *
- ****************************************************************/
-
- drawgline3d(&plot->xgridmin,&plot->ygridmax,&plot->zgridmax,
- &plot->xgridmin,&plot->ygridmin,&plot->zgridmax);
-
- drawgline3d(&plot->xgridmin,&plot->ygridmin,&plot->zgridmin,
- &plot->xgridmax,&plot->ygridmin,&plot->zgridmin);
-
- drawgline3d(&plot->xgridmin,&plot->ygridmin,&plot->zgridmax,
- &plot->xgridmin,&plot->ygridmin,&plot->zgridmin);
-
- if (plot->titel) /* Titel der Graphik */
- printtextabs(plot->titel, /* schreiben wenn vorhanden */
- (plot->xpic1+plot->xpic2)/2,
- plot->ypic1-plot->yle,T_CX|T_B);
-
- trans3d(&plot->xgridmin,&plot->ygridmin,&plot->zgridmin,
- &x1,&y1);
-
- if (plot->xname) /* X-Achsenname */
- printtextabs(plot->xname, /* schreiben wenn vorhanden */
- (plot->xpic2+x1)/2,
- y1,T_CX|T_T);
-
- if (plot->xunit) /* X-Achseneinheit */
- printtextabs(plot->xunit, /* schreiben wenn vorhanden */
- plot->xpic2,
- y1,T_L|T_T);
-
- if (plot->zname) /* Z-Achsenname */
- printtextabs(plot->zname, /* schreiben wenn vorhanden */
- (plot->xpic1+x1)/2,
- y1,T_CX|T_T);
-
- if (plot->zunit) /* Z-Achseneinheit */
- printtextabs(plot->zunit, /* schreiben wenn vorhanden */
- plot->xpic1,
- y1,T_R|T_T);
-
- if (plot->yname) /* Y-Achsenname */
- { /* schreiben wenn vorhanden */
- slen = strlen(plot->yname); /* Länge des Namens */
- len ++; /* Abstand zur Y-Achse */
- htsize = 5*plot->ytext/4;
- y1 = (plot->ypic2+plot->ypic1-(slen-1)*htsize)/2;
- x1 = plot->xpic1-len*plot->xtext;
- for (i=0;i<slen;i++) /* jedes Zeichen ausgeben */
- {
- sbuf[0] = plot->yname[i];
- printtextabs( sbuf,
- x1,
- y1+i*htsize,
- T_L|T_CY);
- }
- }
-
- trans3d(&plot->xgridmin,&plot->ygridmax,&plot->zgridmax,
- &x1,&y1);
-
- if (plot->yunit) /* Y-Achseneinheit */
- printtextabs(plot->yunit, /* schreiben wenn vorhanden */
- x1,
- y1-plot->yle,
- T_L|T_B);
- }
-
- /****************************************************************
- * *
- * Function : HiddenLine() *
- * *
- *****************************************************************
- * *
- * Input : x,y,x1,y1 *
- * int x Startpunkt der Linie *
- * int y *
- * int x1 Endpunkt der Linie *
- * int y1 *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion kontrolliert eine Linie auf ihre *
- * auf ihre Sichtbarkeit. Die Funktionsweise dieses *
- * ist schnell erklärt. *
- * Es werden zwei Horizonte definiert mit der Länge *
- * der Bildschirmauflösung. Diese beiden Horizonte *
- * werden am Anfang mit ihren gegenüberliegenden *
- * Werten inittialisiert. Die einzelnen Punkte einer *
- * Linie werden nun mit diesen beiden Horizonten *
- * vergliechen. *
- * Wenn sie über bzw. unter dem Horizont liegen, so *
- * werden sie gezeichnet und die Horizonte werden auf *
- * dieses Nivau angehoben. Wenn die Punkte zwischen *
- * den Horizonten liegt, dann wird keine Linie *
- * gezeichnet. *
- * Dieser sehr schnell und kleine Algorithmus hat *
- * jedoch auch seine Nachteile. Die Linien müssen *
- * auf dem Bildschirm von vorne nach hinten *
- * gezeichnet werden. *
- * Da dies beim Crosshatching nicht immer erfüllt *
- * wird, kann man dort kleinere Fehler erkennen. *
- * *
- ****************************************************************/
-
- static void hiddenline(x,y,x1,y1)
- int x,y,x1,y1;
- {
-
- int dx, /* horiz. Länge in Punkten */
- i, /* Schleifenzähler */
- mx,my, /* Startpunkt der Linie */
- top,bot, /* Boolean für Horizont */
- hid, /* Hiddenboolean */
- yai, /* aktuelle Y-Wert */
- yvi; /* vorhergehender Y-Wert */
- DATA yaf, /* aktueller Floathorizont */
- m; /* Steigung */
-
- dx = x1-x; /* berechne länge */
- if (dx==0) /* wenn keine Differenz */
- {
- dx = 1; /* generieren einer */
- x = x1-1; /* künst. Differenz */
- }
- m = (DATA)(y1-y)/abs(dx); /* Steigung der Linie */
- yaf = (DATA)y; /* Startpunkt speichern */
- yai = y; /* Y-Wert setzten */
- yvi = y;
-
- hid=TRUE; /* Linie nicht sichtbar */
- mx = x; /* Startpunkt der Linie */
- my = y; /* setzten */
- for (i=x;i<=x1;i++) /* für ganze Länge */
- {
- top = (yai <= tv[i]); /* Punkt über Top setzte 1 */
- bot = (yai >= bv[i]); /* Punkt unter Bottom 1 */
-
- if (top) tv[i] = yai; /* neuer Horizont setzten */
- if (bot) bv[i] = yai; /* wenn nötig */
- if ((!hid)and(!((top)or(bot)))) /* Zeichne Linie wenn 1 */
- { /* Status sich verändert */
- hid=TRUE; /* Linie versteckt */
- DrawLine(mx,my,i-1,yvi);
- }
- if ((hid)and((top)or(bot))) /* alles Sichtbar dann */
- { /* setzte hidden und lege */
- hid=FALSE; /* den Startpinkt der Linie */
- mx = i; /* fest */
- my = yai;
- }
- yaf = yaf+m; /* nächster Punkt berechnen */
- yvi = yai; /* und vorhergehender */
- yai = round(yaf); /* setzten */
- }
- if (!hid) /* zeichne Linie, wenn */
- DrawLine(mx,my,x1,y1); /* Daten vorhanden */
- }
-
-
- /****************************************************************
- * *
- * Function : sfct0() *
- * *
- *****************************************************************
- * *
- * Input : x,x1 *
- * DATA *x erstes Element *
- * DATA *1x zweites Element *
- * *
- * Output : int *
- * > 0 x > x1 *
- * == 0 x == x1 *
- * < 0 x < x1 *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion wird von dem Sortieralgorithmus *
- * benötigt. Die Datentabelle wird nach dem ersten *
- * Element ( x-Wert ) sortiert. *
- * *
- ****************************************************************/
-
- static int sfct0(x,x1)
- DATA *x,
- *x1;
- {
- if (*x < *x1) return(-1); /* Vergleichsoperation mit */
- else if (*x > *x1) return(1); /* den verschiedenen Rück- */
- else return(0); /* gabewerten */
- }
-
- /****************************************************************
- * *
- * Function : sfct2() *
- * *
- *****************************************************************
- * *
- * Input : x,x1 *
- * DATA *x erstes Element *
- * DATA *1x zweites Element *
- * *
- * Output : int *
- * > 0 x > x1 *
- * == 0 x == x1 *
- * < 0 x < x1 *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion wird von dem Sortieralgorithmus *
- * benötigt. Die Datentabelle wird nach dem dritten *
- * Element ( z-Wert ) sortiert. *
- * *
- ****************************************************************/
-
- static int sfct2(x,x1)
- DATA *x,
- *x1;
- {
- register DATA *u,*v; /* Datenzeiger */
-
- u = x+2; /* zuweisen der Daten- */
- v = x1+2; /* elemente */
-
- if (*u < *v) return(-1); /* Vergleichsoperation mit */
- else if (*u > *v) return(1); /* den verschiedenen Rück- */
- else return(0); /* gabewerten */
- }
-
- /****************************************************************
- * *
- * Function : checkclipp3d() *
- * *
- *****************************************************************
- * *
- * Input : x,y,z,c *
- * DATA *x x Koordinate *
- * DATA *y y Koordinate *
- * DATA *z z Koordinate *
- * char *c Status *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion kontrolliert die Koordinaten *
- * mittels der Gittergrenzen auf ihre Lage. Der *
- * Status wird mit den folgenden defines gesetzt. *
- * *
- * X_MN -> Clipping XMin *
- * X_MX -> Clipping XMax *
- * Y_MN -> Clipping YMin *
- * Y_MX -> Clipping YMax *
- * Z_MN -> Clipping ZMin *
- * Z_MX -> Clipping ZMax *
- * *
- * Wenn das Clipping eingeschaltet ist, wird *
- * mindestens diese Funktion aufgerufen und durch- *
- * geführt. *
- * *
- ****************************************************************/
-
- static void checkclipp3d(x,y,z,c)
- DATA *x,
- *y,
- *z;
- char *c;
- {
- *c=0; /* status initialisieren */
- if (*x<plot->xgridmin) /* links von min ? */
- *c |= X_MN; /* Ja */
- else if (*x>plot->xgridmax) /* Nein, rechts von max */
- *c |= X_MX; /* Ja */
-
- if (*y<plot->ygridmin) /* links von min ? */
- *c |= Y_MN; /* Ja */
- else if (*y>plot->ygridmax) /* Nein, rechts von max */
- *c |= Y_MX; /* Ja */
-
- if (*z<plot->zgridmin) /* links von min ? */
- *c |= Z_MN; /* Ja */
- else if (*z>plot->zgridmax) /* Nein, rechts von max */
- *c |= Z_MX; /* Ja */
- }
-
- /****************************************************************
- * *
- * Function : doclipp3d() *
- * *
- *****************************************************************
- * *
- * Input : x1,y1,z1,x2,y2,z2 *
- * DATA *x1 x Start *
- * DATA *y1 y Start *
- * DATA *z1 z Start *
- * DATA *x2 x Ende *
- * DATA *y2 y Ende *
- * DATA *z2 z Ende *
- * *
- * Output : char Status *
- * != 0 trivial reject *
- * == 0 Draw *
- * *
- *****************************************************************
- * *
- * Comment : Der Cohen-Sutherland Clipping Algorithmus welcher *
- * hier verwendet wird, ist eine logische Weiter- *
- * entwicklung aus dem 2D-Bereich. Er liefert einen *
- * Status über das Zeichnen der Linie. *
- * Wenn dieser Status == 0 ist, kann die Linie *
- * gezeichnet werden. *
- * Eine nähere Beschreibung dieses Algorithums *
- * befindet sich in der Diplomarbeit. *
- * *
- ****************************************************************/
-
- static char doclipp3d(x1,y1,z1,x2,y2,z2)
- DATA *x1,
- *y1,
- *z1,
- *x2,
- *y2,
- *z2;
- {
- DATA x,y,z, /* geclippte Koordinaten */
- fac; /* Verhältnisfaktor */
- char c1,c2,c; /* Status Variablen */
-
- checkclipp3d(x1,y1,z1,&c1); /* Kontrolliere Startpunkt */
- checkclipp3d(x2,y2,z2,&c2); /* kontrolliere Endpunkt */
-
- /****************************************************************
- * *
- * Der folgende Vergleich bestimmt das Clipping. *
- * *
- * ((c1!=0) || (c2!=0)) Wenn c1 == 0 und c2 == 0 dann trivial *
- * accept also die Linie liegt vollständig im Fenster. *
- * *
- * ((c1 & c2)!=0) Wenn beide Statusvariablen gleich sind spricht *
- * man von trivial reject. *
- * *
- * Wenn eine dieser Bedingungen erfüllt ist, dann muss keine *
- * Berechnung durchgeführt werden. Der Status wird entsprechend *
- * gesetzt. *
- * *
- ****************************************************************/
-
- while(((c1!=0) || (c2!=0)) && ((c1 & c2)==0))
- {
- if (c1) /* Startpunkt clippen */
- c=c1; /* dann Status zuweisen */
- else /* sonst */
- c=c2; /* Endpunkt zuweisen */
-
- if (c & X_MN) /* Punkt kleiner xmin ? */
- { /* Ja */
- x=plot->xgridmin; /* x gleich xmingrid */
- fac=(x-*x1)/(*x2-*x1); /* Faktor berechnen */
- y=*y1+(*y2-*y1)*fac; /* Schnittpunkt Y Koord. */
- z=*z1+(*z2-*z1)*fac; /* Schnittpunkt Z Koord. */
- }
- else if (c & X_MX) /* Punkt kleiner xmax ? */
- { /* Ja */
- x=plot->xgridmax; /* x gleich xmaxgrid */
- fac = (x-*x1)/(*x2-*x1); /* Faktor berechnen */
- y= *y1+(*y2-*y1)*fac; /* Schnittpunkt Y Koord. */
- z= *z1+(*z2-*z1)*fac; /* Schnittpunkt Z Koord. */
- }
-
- if (c & Y_MN) /* Punkt kleiner ymin ? */
- { /* Ja */
- y=plot->ygridmin; /* y gleich ymingrid */
- fac = (y-*y1)/(*y2-*y1); /* Faktor berechnen */
- x= *x1+(*x2-*x1)*fac; /* Schnittpunkt X Koord. */
- z= *z1+(*z2-*z1)*fac; /* Schnittpunkt Z Koord. */
- }
- else if (c & Y_MX) /* Punkt kleiner ymax ? */
- { /* Ja */
- y=plot->ygridmax; /* y gleich ymaxgrid */
- fac = (y-*y1)/(*y2-*y1); /* Faktor berechnen */
- x= *x1+(*x2-*x1)*fac; /* Schnittpunkt X Koord. */
- z= *z1+(*z2-*z1)*fac; /* Schnittpunkt Z Koord. */
- }
-
- if (c & Z_MN) /* Punkt kleiner zmin ? */
- { /* Ja */
- z=plot->zgridmin; /* z gleich zmingrid */
- fac = (z-*z1)/(*z2-*z1); /* Faktor berechnen */
- x= *x1+(*x2-*x1)*fac; /* Schnittpunkt X Koord. */
- y= *y1+(*y2-*y1)*fac; /* Schnittpunkt Y Koord. */
- }
- else if (c & Z_MX) /* Punkt kleiner zmax ? */
- { /* Ja */
- z=plot->zgridmax; /* z gleich zmaxgrid */
- fac = (z-*z1)/(*z2-*z1); /* Faktor berechnen */
- x= *x1+(*x2-*x1)*fac; /* Schnittpunkt X Koord. */
- y= *y1+(*y2-*y1)*fac; /* Schnittpunkt Y Koord. */
- }
-
- if (c==c1) /* Startpunkt bearbeitet ? */
- { /* Ja */
- *x1=x; /* geclippte Werte zu- */
- *y1=y; /* weisen */
- *z1=z;
- checkclipp3d(x1,y1,z1,&c1); /* und kontrollieren */
- }
- else /* also Endpunkt */
- {
- *x2=x; /* geclippte Werte zu- */
- *y2=y; /* weisen */
- *z2=z;
- checkclipp3d(x2,y2,z2,&c2); /* und kontrollieren */
- }
- }
- return(c1); /* zurück mit Status */
- }
-
- /****************************************************************
- * *
- * Function : calcscale() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : CalcScale berechnet die automatische Skalierung *
- * für alle 3D Darstellungen auf dem Bildschirm. *
- * Diese Funktion berechnet die Werte für die *
- * Transformationsmatrix. Es wird der max. verfügbare *
- * Pixelbereich dividiert durch die Grösse des *
- * Gitters. Dadurch erhalten wir für jeden Pixel *
- * einen bestimmten virtuellen Wert. *
- * *
- ****************************************************************/
-
- static void calcscale3d()
- {
- int i; /* allg Schleifenvariable */
-
- int pt[8][3] = /* Kanten der Koordinaten- */
- { /* grenzen. Indexierung in */
- 0,2,5, /* vt[] (ValueTable). */
- 1,2,5,
- 1,3,5,
- 0,3,5,
- 0,2,4,
- 1,2,4,
- 1,3,4,
- 0,3,4
- };
-
- DATA u,v, /* X- und Y-Projektion */
- ul,ur, /* X-Projektions Werte */
- vl,vr, /* Y-Projektions Werte */
- divs, /* Divisor */
- x,y,z, /* temp. Koordinatenpunkt */
- vt[6]; /* Eckpunkttabelle */
-
- /****************************************************************
- * *
- * Werte Konvertierung für alle Grenzwerte *
- * *
- ****************************************************************/
-
- if (plot->xmes != LIN) /* log. Transformation */
- {
- vt[0] = xlogfct(plot->xgridmin);
- vt[1] = xlogfct(plot->xgridmax);
- }
- else /* lineare Transformation */
- {
- vt[0] = plot->xgridmin;
- vt[1] = plot->xgridmax;
- }
-
- if (plot->ymes != LIN) /* log. Transformation */
- {
- vt[2] = ylogfct(plot->ygridmin);
- vt[3] = ylogfct(plot->ygridmax);
- }
- else /* lineare Transformation */
- {
- vt[2] = plot->ygridmin;
- vt[3] = plot->ygridmax;
- }
-
- if (plot->zmes != LIN) /* log. Transformation */
- {
- vt[4] = zlogfct(plot->zgridmin);
- vt[5] = zlogfct(plot->zgridmax);
- }
- else /* lineare Transformation */
- {
- vt[4] = plot->zgridmin;
- vt[5] = plot->zgridmax;
- }
-
- /****************************************************************
- * *
- * Berechnen der Einheitsskalierung. Bei einer multiplikation *
- * von f?scale mit den Grenzen der Achsen überstreichen alle *
- * Achsen den gleichen Bereich. Sie werden dadurch im 3D-Bereich *
- * gleich lang dargestellt. *
- * *
- ****************************************************************/
-
- fxscale = 10000/(vt[1]-vt[0]); /* X-Achse */
- fyscale = 10000/(vt[3]-vt[2]); /* Y-Achse */
- fzscale = 10000/(vt[5]-vt[4]); /* Z-Achse */
-
- /****************************************************************
- * *
- * Transformation auf die Einheitsskalierung *
- * *
- ****************************************************************/
-
- vt[0] = vt[0]*fxscale; /* X-Achse minimum */
- vt[1] = vt[1]*fxscale; /* X-Achse maximum */
- vt[2] = vt[2]*fyscale; /* Y-Achse minimum */
- vt[3] = vt[3]*fyscale; /* Y-Achse maximum */
- vt[4] = vt[4]*fzscale; /* Z-Achse minimum */
- vt[5] = vt[5]*fzscale; /* Z-Achse maximum */
-
- /****************************************************************
- * *
- * Initialisieren der projezierten Koordinaten *
- * *
- ****************************************************************/
-
- ul = 1e30; /* X-Achse 2D */
- ur = -ul; /* X-Achse 2D */
- vl = 1e30; /* Y-Achse 2D */
- vr = -vl; /* Y-Achse 2D */
-
- /****************************************************************
- * *
- * Festlegung des Betrachtungspunktes *
- * *
- ****************************************************************/
-
- plot->xcenter = (vt[0]+vt[1])/2; /* X-Achsenmitte */
- plot->ycenter = (vt[2]+vt[3])/2; /* Z-Achsenmitte */
- plot->zcenter = 1e30; /* Z-Achse weit weit hinten */
-
- /****************************************************************
- * *
- * Berechnen der Grenzwerte auf der Bildschirmebene *
- * *
- * Alle Eckpunkte des Koordinatenwürfels werden transformiert *
- * und die max. Projektionswerte werden festgehalten. Diese *
- * Werte müssen danach so skaliert werden, dass sie auf dem *
- * Bildschirmbereich liegen. *
- * *
- ****************************************************************/
-
- for (i=0;i<8;i++)
- {
-
- /****************************************************************
- * *
- * Rotation um x-, y- und z-Achse in dieser Reihenfolge *
- * *
- ****************************************************************/
-
- x = vt[pt[i][0]]*xr1 + vt[pt[i][1]]*xr2 + vt[pt[i][2]]*xr3;
- y = vt[pt[i][0]]*yr1 + vt[pt[i][1]]*yr2 + vt[pt[i][2]]*yr3;
- z = vt[pt[i][0]]*zr1 + vt[pt[i][1]]*zr2 + vt[pt[i][2]]*zr3;
-
- /****************************************************************
- * *
- * Projektion auf die Bildschirmebene *
- * *
- ****************************************************************/
-
- divs = z-plot->zcenter;
- u = (z*plot->xcenter-x*plot->zcenter)/divs;
- v = (z*plot->ycenter-y*plot->zcenter)/divs;
-
- if (u<ul) ul = u; /* max. Werte nach Pro- */
- if (u>ur) ur = u; /* jektion zuweisen für */
- if (v<vl) vl = v; /* beide Achsen */
- if (v>vr) vr = v;
- }
-
- /****************************************************************
- * *
- * Berechnung der Skalierung mit den max. Werten *
- * *
- ****************************************************************/
-
- xscale = (plot->xpic2-plot->xpic1)/(ur-ul);
- yscale = (plot->ypic2-plot->ypic1)/(vr-vl);
-
- /****************************************************************
- * *
- * Berechnung der Verschiebung mit den max. Werten *
- * *
- ****************************************************************/
-
- xoffset = (plot->xpic1*ur-plot->xpic2*ul)/(ur-ul);
- yoffset = (plot->ypic2*vr-plot->ypic1*vl)/(vr-vl);
-
- }
-
- /****************************************************************
- * *
- * Function : ClearHidden() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion initialisiert die beiden Horizonte *
- * auf die min. bzw. max. Werte. Danach kann der *
- * Hiddenlinealgorithmus neu gestartet werden. *
- * *
- ****************************************************************/
-
- static void clearhidden()
- {
- register i;
- register GPT *tv1,*bv1, /* Arrayzeiger */
- min,max; /* Init. -werte */
-
- min = (GPT)plot->ypic2; /* Zuweisen der Init.- */
- max = (GPT)plot->ypic1; /* werte */
-
- tv1 = tv; /* Adressen zuweisen der */
- bv1 = bv; /* beiden Horizonte */
- for (i=0;i<=plot->xpic2;i++) /* alle Felder init. */
- {
- *tv1++ = min; /* top mit bottom init. */
- *bv1++ = max; /* bot mit top init. */
- }
- }
-
- /****************************************************************
- * *
- * Function : InitHidden() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : int allg. Rückgabewert *
- * != FALSE alle klar *
- * == FALSE Fehler *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion alloziert den notwendigen Speicher *
- * für den Hiddenline Algorithmus. *
- * *
- ****************************************************************/
-
- static int inithidden()
- {
- tv = malloc((plot->xpic2+2)*sizeof(GPT));
- bv = malloc((plot->xpic2+2)*sizeof(GPT));
- if ((tv)and(bv)) /* Wenn Speicher bekommen */
- {
- clearhidden(); /* diesen initialisieren */
- return(TRUE); /* alles klar */
- }
- else /* sonst mit Fehler zurück */
- {
- seterror(HIDDENMEM);
- return(FALSE);
- }
- }
-
- /****************************************************************
- * *
- * Function : FreeHidden() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Diese Funktion gibt den allozierten Speicher für *
- * den Hiddenlinealgorithmus an das System zurück. *
- * *
- ****************************************************************/
-
- static void freehidden()
- {
- if (tv) free(tv); /* Tophorizont */
- if (bv) free(bv); /* Bottomhorizont */
- }
-
- /****************************************************************
- * *
- * Function : initrotation() *
- * *
- *****************************************************************
- * *
- * Input : void *
- * *
- * Output : void *
- * *
- *****************************************************************
- * *
- * Comment : Initialisiert die global statischen Rotations- *
- * variablen xr1,xr2 .. zr3. *
- * Die Rotation erfolgt zuerst mit der X-Achse, *
- * danach folgt die Y-Achse und amm Schluss wird noch *
- * um die Z-Achse rotiert. *
- * *
- * Die Herleitung dieser Funktionen ist in der *
- * Diplomarbeit zu finden. *
- * *
- ****************************************************************/
-
- static void initrotation()
- {
-
- static DATA rad = 0.01745329; /* Umrechnungsfaktor */
-
- DATA px,py,pz; /* Rotationswinkel in Rad. */
-
- px = plot->phix*rad; /* Umrechnen der Rotations- */
- py = plot->phiy*rad; /* winkel von Grad nach */
- pz = plot->phiz*rad; /* Radiant */
-
- xr1 = cos(py)*cos(pz); /* Berechnen der Rotations- */
- xr2 = cos(py)*sin(pz); /* faktoren für die ver- */
- xr3 = -sin(py); /* schiedenen Achsen */
-
- yr1 = sin(px)*cos(py)*cos(pz)-cos(px)*sin(pz);
- yr2 = sin(px)*sin(py)*sin(pz)+cos(px)*cos(pz);
- yr3 = sin(px)*cos(py);
-
- zr1 = cos(px)*sin(py)*cos(pz)+sin(px)*sin(pz);
- zr2 = cos(px)*sin(py)*sin(pz)-sin(px)*cos(pz);
- zr3 = cos(px)*cos(py);
-
- }
-
-