home *** CD-ROM | disk | FTP | other *** search
- /* TURTLE - Modul mit Funktionen zur Ausführung sog. 'Turtle'-Grafik (turtle
- * = Schildkröte). Turtle-Grafik ist ein Modell zum Bestimmen relativer
- * Bewegungen eines vorgestellten Zeigers, dessen Richtung, Farbe,
- * Sichtbarkeit und andere Attribute über Turtle-Funktionen mit Vorgabe-
- * werten versehen werden. Um das Turtle-Modul zu verwenden, schließt man in
- * das betreffende Programm die Einfügdatei TURTLE.H mit ein. Folgende
- * Funktionen (viele davon als Makros definiert) sind global:
- *
- * InitTurtle - Turtle-Grafik anfangen
- * Home - Turtle-Vorgabewerte rücksetzen
- * StiftStatus - Stift-Sichtbarkeit einrichten
- * AusFuellung - Füllstatus einrichten
- * StiftFarbe - Stift-Farbindex einrichten
- * RandFarbe - Rand-Farbindex einrichten
- * Schwenken - Von gegenwärtiger Richtung schwenken
- * Richtung - Absolute Richtung einrichten
- * Bewege - In gegenwärtige Richtung bewegen
- * GeheZu - Zu Absoluter Position gehen
- * Poly - Polygon zeichnen
- * Kreis - Kreis zeichnen mit Mitte an gegenwärtiger Position
- * Ellipse - Ellipse zeichnen mit Mitte an gegenwärtiger Position
- * Rechteck - Rechteck zeichnen mit Mitte an gegenwärtiger Position
- * BildGroesse - Größe des Rechtecks mit Ausgangspunkt links-oben
- * BildHolen - Rechteckiges Bild holen mit Ausgangspunkt links-oben
- * BildPos - Rechteckiges Bild anlegen, Ausgangspunkt links-oben
- * Fuellen - Von gegenwärtiger Position bis Rand füllen
- * FarbIndexWeiter - Zum nächsten Farbindex weiter
- * FarbWertWeiter - Zum nächsten Farbwert weiter
- * AufBildsch - Feststellen: ist gegenwärtige Position auf Bildschirm
- * RGB - Rot-, Grün-, Blau-Elemente von Farbwerten kombinieren
- *
- * Die Struktur TURTLE structure, die Globalvariable "tc" (des Typs TURTLE)
- * und die Variable "vlColors" sind definiert. Sie werden jedoch
- * normalerweise nicht direkt vom Programmiere benutzt.
- */
-
- #include <graph.h>
- #include <math.h>
- #include <string.h>
- #include "turtle.h"
-
- #define PI 3.141593
-
- long cvlColors[256]; /* Datenfeld von Farbwerten des Typs long */
-
- TURTLE tc = { 1.39 }; /* Ursprüngliches Verhältnis - auf benutzten
- * Bildschirm anpassen
- */
-
- /* InitTurtle - Initialisiert alle Turtle-Vorgabewerte. Diese Funktion
- * sollte mindestens einmal aufgerufen werden (nach _setvideomode und
- * _getvideoconfig) und wieder nach jedem Wechsel auf einen neuen
- * Grafikmodus.
- *
- * Parameter: vc - Zeiger zur Struktur videoconfig
- *
- * Ergebnis: 0 bei Versagen, sonst 1
- *
- * Benutzt: Strukturvariable tc, Datenfeld cvlColors
- */
- short InitTurtle( struct videoconfig *vc )
- {
- int i;
- unsigned cvuInc, cvuRot, cvuGruen, cvuBlau; /* 'Unsigned' Teile der */
- static int mode = -1; /* Farbwerte */
-
- /* Falls kein Grafikmodus, abbrechen. */
- if( !vc->numxpixels )
- return 0;
-
- /* Nach Moduswechsel Fensterkoordinaten neu einrichten. */
- if( mode != vc->mode )
- {
- mode = vc->mode;
- tc.xsLinks = tc.ysOben = 0;
- tc.xsRechts = vc->numxpixels - 1;
- tc.ysUnten = vc->numypixels - 1;
- }
-
- /* Palettenkennung einrichten. */
- switch( vc->adapter )
- {
- case _MDPA:
- case _CGA:
- case _OCGA:
- case _HGC:
- tc.fPalette = FALSCH;
- break;
- default:
- tc.fPalette = WAHR;
- break;
- }
-
- /* Paletten-Vorgabewerte einrichten. */
- switch( vc->mode )
- {
- case _HRESBW:
- case _HERCMONO:
- case _ERESNOCOLOR:
- case _ORESCOLOR:
- case _VRES2COLOR:
- tc.afw = 0;
- tc.afi = 2;
- return Home();
- case _MRES256COLOR: /* Aktive Bits in dieser Reihenfolge: */
- cvuInc = 12;
- tc.afw = tc.afi = 125; /* ???????? ??bbbbbb ??gggggg ??rrrrrr */
- break;
- case _ERESCOLOR:
- if( vc->memory == 64 )
- {
- cvuInc = 32;
- tc.afw = 16; /* ???????? ??????Bb ??????Gg ??????Rr */
- tc.afi = 4;
- break;
- } /* Sonst Rest überspringen */
- case _VRES16COLOR:
- cvuInc = 16;
- tc.afw = 64; /* ???????? ??????bb ??????gg ??????rr */
- tc.afi = 16;
- break;
- case _MRES4COLOR:
- case _MRESNOCOLOR:
- cvuInc = 32;
- tc.afw = 16; /* ???????? ??????Bb ??????Gg ??????Rr */
- tc.afi = 4;
- break;
- case _MRES16COLOR:
- case _HRES16COLOR:
- cvuInc = 32;
- tc.afi = tc.afw = 16; /* ???????? ??????Bb ??????Gg ??????Rr */
- break;
- }
-
- /* Paletten-Datenfelder füllen. */
- for( i = 0, cvuBlau = 0; cvuBlau < 64; cvuBlau += cvuInc )
- for( cvuGruen = 0; cvuGruen < 64; cvuGruen += cvuInc )
- for( cvuRot = 0; cvuRot < 64; cvuRot += cvuInc )
- {
- cvlColors[i] = RGB( cvuRot, cvuGruen, cvuBlau );
- /* Special case of 6 bits for 16 Farbes (RGBI).
- * If both bits are on for any Farbe, intensity is set.
- * If one bit is set for a Farbe, that Farbe is on.
- */
- if( cvuInc == 32 )
- cvlColors[i + 8] = cvlColors[i] | (cvlColors[i] >>
- 1);
- i++;
- }
- cvlColors[tc.afw - 1] = _BRIGHTWHITE;
- FarbWertWeiter( VORGABE );
- return Home();
- }
-
- /* Home - Zum Rücksetzen der Turtle-Vorgabewerte. Diese Funktion kann
- * aufgerufen werden, solang der Videomodus nicht geändert wurde, doch die
- * Schildkröte ('Turtle') zur Mitte des Fensters zurückgestellt und alle
- * Vorgabewerte rückgesetzt werden sollen. Wenn man beispielsweise die
- * Absolutwerte für das Fenster ändert kann man danach Home aufrufen und
- * damit ein neues Turtle-Fenster einrichten.
- *
- * Parameter: Keine
- *
- * Ergebnis: 0 bei Versagen, sonst 1
- *
- * Benutzt: tc
- */
- short Home()
- {
- struct _wxycoord xy1, xy2;
-
- _setviewport( tc.xsLinks, tc.ysOben, tc.xsRechts, tc.ysUnten );
-
- /* Fenster einrichten nach Bildschirmhöhe 1000 und -breite nach
- * Seitenverhältnis.
- */
- tc.yMax = 500.0;
- tc.xMax = tc.yMax * tc.yxSeitenvh;
- if( !_setwindow( FALSCH, -tc.xMax, -tc.yMax, tc.xMax, tc.yMax ) )
- return 0;
-
- /* Über Y-Achse die Größe eines Bildpunkts berechnen. */
- xy1 = _getwindowcoord( 1, 1 );
- xy2 = _getwindowcoord( 1, 2 );
- tc.yEinheit = xy2.wy - xy1.wy;
-
- /* Vorgabewerte für gegenwärtigen Bildpunkt, Richtung, Stift-Status
- * und Füll-Status einrichten.
- */
- tc.xGgw = tc.yGgw = 0.0;
- _moveto_w( tc.xGgw, tc.yGgw );
- Richtung( 0 );
- StiftStatus( WAHR );
- AusFuellung( FALSCH );
-
- /* Weiß zum letzten Farbindex machen; Stift u. Rand darauf einstellen. */
- _remappalette( WEISS, _BRIGHTWHITE );
- RandFarbe( WEISS );
- StiftFarbe( WEISS );
- _setbkcolor( _BLACK );
- return 1;
- }
-
- /* StiftStatus - Bestimmt die Sichtbarkeit des von Bewege und GeheZu
- * benutzten Stifts. Dieser Status kann WAHR (sichtbar), FALSCH (unsichtbar)
- * oder VORGABE (gegenwärtige Einstellung unverändert).
- *
- * Parameter: fStiftStatus
- *
- * Ergebnis: gegenwärtiger Stift-Status
- *
- * Benutzt: tc
- */
- int StiftStatus( int fStiftStatus )
- {
- switch( fStiftStatus )
- {
- case VORGABE:
- break;
- case FALSCH:
- tc.fStiftStatus = FALSCH;
- break;
- default:
- tc.fStiftStatus = WAHR;
- break;
- }
- return tc.fStiftStatus;
- }
-
- /* AusFuellung - Bestimmt die Ausfüllweise für Formen, wie z.B. Rechtecke,
- und zwar entweder als WAHR (ganz ausfüllen), FALSCH (nur Rand) oder VORGABE
- (gegenwärtige Einstellung unverändert).
- *
- * Parameter: fFuell
- *
- * Ergebnis: Gegenwärtiger Füllstatus
- *
- * Benutzt: tc
- */
- short AusFuellung( short fFuell )
- {
- switch( fFuell )
- {
- case VORGABE:
- break;
- case _GBORDER:
- case FALSCH:
- tc.fFuell = _GBORDER;
- break;
- default:
- tc.fFuell = _GFILLINTERIOR;
- break;
- }
- return tc.fFuell;
- }
-
- /* StiftFarbe - Bestimmt den Farbindex des Stiftes.
- *
- * Parameter: fiGgw - beliebiger VORGABE-Farbindex für unverändertes
- * Ergebnis
- *
- * Ergebnis: gegenwärtiger Stift-Farbindex
- *
- * Benutzt: tc
- */
- short StiftFarbe( short fiGgw )
- {
- if( fiGgw != VORGABE )
- _setcolor( tc.fiGgw = fiGgw );
- return tc.fiGgw;
- }
-
- /* RandFarbe - Bestimmt den Farbindex für den Rand zur Berücksichtigung
- * durch Füllanweisungen.
- *
- * Parameter: fiRand - beliebiger VORGABE-Farbindex für Ergebnis
- * ohne Veränderung
- *
- * Ergebnis: gegenwärtiger Rand-Farbindex
- *
- * Benutzt: tc
- */
- short RandFarbe( short rand )
- {
- if( rand != VORGABE )
- tc.fiRand = rand;
- return tc.fiRand;
- }
-
- /* Schwenken - Bestimmt neue Richtung relativ zur gegenwärtigen Richtung.
- *
- *
- * Parameter: wklGgw - ein Gradwert für Schwenkwinkel, wobei ein positiver
- * Wert Rechts-, ein negativer Wert eine Linksdrehung bedeutet.
- *
- * Ergebnis: neuer gegenwärtiger Absolutwert für Richtung
- *
- * Benutzt: tc
- */
- short Schwenken( short wklGgw )
- {
- return( tc.wklGgw = ((tc.wklGgw + wklGgw) % CIRCUMFERENCE) );
- }
-
- /* Richtung - Sets a new absolute Richtung.
- *
- * Parameter: wklGgw - ein Gradwert für Schwenkwinkel, wobei ein positiver
- * Wert Rechts-, ein negativer Wert eine Linksdrehung bedeutet.
- * (0 deutet genau nach 'Norden' bzw. 12:00 Uhr.)
-
- * Ergebnis: neuer gegenwärtiger Absolutwert für Richtung
- *
- * Benutzt: tc
- */
- short Richtung( short wklGgw )
- {
- if( wklGgw < 0 )
- return( tc.wklGgw = 360 - (wklGgw % CIRCUMFERENCE) );
- else
- return( tc.wklGgw = wklGgw % CIRCUMFERENCE );
- }
-
- /* Bewege - Geht von der gegenwärtigen Position eine bestimmte Strecke
- * in der gegenwärtigen Richtung. Ist Stiftstatus WAHR, wird dabei ein
- * Strich gezeichnet. Die neue Position wird zur gegenwärtigen Position.
- *
- * Parameter: dxy - Unterschied zwischen gegenwärtigem xy und neuem xy
- *
- * Ergebnis: 0 wenn neue Position außerhalb des Bildschirms liegt, sonst
- * einen Wert ungleich Null.
- *
- * Benutzt: tc
- */
- short Bewege( double dxy )
- {
- double dx, dy; /* Unterschied zwischen X und Y */
- double angT;
-
- /* Neue X- und Y-Positionen berechnen. */
- angT = (tc.wklGgw - 90) * (PI / HALFCIRCUMFERENCE);
- dx = dxy * cos( angT );
- dy = dxy * sin( angT );
-
- /* Bewegen - dabei zeichnen, wenn Stift WAHR; neue Position einnehmen */
- if( tc.fStiftStatus )
- _lineto_w( tc.xGgw + dx, tc.yGgw + dy );
- else
- _moveto_w( tc.xGgw + dx, tc.yGgw + dy );
- tc.xGgw += dx;
- tc.yGgw += dy;
- return AufBildsch();
- }
-
- /* GeheZu - Geht von der gegenwärtigen Position zu einer bestimmten
- * Position. Ist Stiftstatus WAHR, wird dabei ein Strich
- * gezeichnet. Die neue Position wird zur gegenwärtigen Position.
- * Die gegenwärtige Richtung ändert sich dabei nicht.
- *
- * Parameter: x und y - Koordinaten der neuen Position
- *
- * Ergebnis: 0 wenn neue Position außerhalb des Bildschirms liegt, sonst
- * einen Wert ungleich Null.
- *
- * Benutzt: tc
- */
- short GeheZu( double x, double y )
- {
- if( tc.fStiftStatus )
- _lineto_w( x, y );
- else
- _moveto_w( x, y );
- tc.xGgw = x;
- tc.yGgw = y;
- return AufBildsch();
- }
-
- /* Poly - Zeichnet ein Polygon.
- *
- * Parameter: cSide - Seitenanzahl des Polygons
- * dxySide - Abstand einer jeden Seite
- *
- * Ergebnis: 0 wenn irgend ein Teil des Polygons außerhalb des Bildschirms
- * liegt, sonst einen Wert ungleich Null.
- */
- short Poly( int cSide, double dxySide )
- {
- short i, angT, fPen, ret = WAHR;
-
- /* Sicherstellen, daß Stift aktiv (WAHR) ist (danach wieder rücksetzen). */
- fPen = StiftStatus( WAHR );
-
- /* Richtung (Winkel) berechnen, dann jede Seite zeichnen. */
- angT = 360 / cSide;
- for( i = 1; i <= cSide; i++ )
- {
- ret = Bewege( dxySide ) && ret;
- Schwenken( angT );
- }
- StiftStatus( fPen );
- return ret;
- }
-
- /* FarbIndexWeiter - Zum nächsten Farbindex weiterrotieren. Das erste
- * Attribut (meist der Hintergund) und das letzte (weiß) werden ausgelassen.
- *
- * Parameter: fiGgw - Mit VORGABE den Farbindex vom letzten Aufruf benutzen
- * oder eine neue Farbe als Ausgangspunlkt bestimmen.
- *
- * Ergebnis: Der weiterrotierte Farbindex
- *
- * Benutzt: tc
- */
- short FarbIndexWeiter( short fiGgw )
- {
- static short fiPrev = 0; /* Statisch, damit der Index zwischen
- * Aufrufen beibehalten wird
- */
- /* Neuen gegenwärtigen Index zuweisen, falls gegeben. */
- if( fiGgw != VORGABE )
- fiPrev = fiGgw;
-
- /* Für zweifarbiges Video umschalten, für mehrfarbiges rotieren. */
- if( tc.afi == 2 )
- return( fiPrev = !fiPrev );
- else
- return( fiPrev = (++fiPrev % (tc.afi - 1)) );
- }
-
- /* FarbWertWeiter - Zum nächsten Farbwert weiterrotieren für Adapter (EGA
- * und höher), die mit umkonfigurierbaren Paletten funktionieren.
- *
- * Parameter: fAktion - VORGABE (alle weiterdrehen) oder LIMITED (nur
- * die ersten 14)
- *
- * Ergebnis: Keines
- *
- * Benutzt: tc
- */
- void FarbWertWeiter( int fAktion )
- {
- static int icvGgw = 1; /* Gegenwärtiger Index zum Farbwert-Datenfeld */
- static int fiGgw = 1; /* Gegenwärtiger Farbindex */
- int icvT; /* Vorläufiger Index zu Farbwerten */
- int i;
-
- /* Betriebsarten ohne Palettenwerte ignorieren. */
- if( !tc.fPalette || !tc.afw )
- return;
-
- /* Farbwert-Index erhöhen und weiterrotieren. */
- icvT = (++icvGgw % (tc.afw - 2)) + 1;
-
-
- /* VORGABE - Alle Farbindeces in Gruppen von je 14 weiterrotieren. Für
- * die meisten Betriebsarten sund dies schon alle Indeces mit Ausnahme
- * des ersten und letzten. Bei 256-Farbmodus würde das Rotieren aller
- * verfügbaren Indeces zu lange dauern.
- */
- if( fAktion == VORGABE )
- for( i = 1; i <= 14; i++ )
- _remappalette( (fiGgw++ % (tc.afi - 2)) + 1,
- cvlColors[(icvT++ % (tc.afw - 2)) + 1] );
-
- /* LIMITED - Nur die ersten 14 Farbindeces rotieren. */
- else
- for( i = 1; i <= 14; i++ )
- _remappalette( i, cvlColors[(icvT++ % (tc.afw - 1)) + 1] );
- }
-