Tekplot Grafikprogrammierung

Inhaltsverzeichnis

. . Einleitung
. . . Überblick
. . . Grundfunktionen
. . . Programme linken
. . . . UNIX, Amiga
. . . . VAX/ALPHA
. . . Versionen
. . Definition des Tekplotstandards
. . . Globale Variablen
. . . Funktionen
. . . . Grundfunktionen
. . . . Farben setzen
. . . . Figuren zeichnen
. . . . Funktionen zum Zeichnen in Gerätekoordinaten
. . . . Koordinatenumrechnungen
. . . . Eingabefunktionen
. . . . Grafikeingabe mit Maus
. . . . Manipulation der Fenstergrösse
. . . . Menüs
. . . . Synchronisation
. . . . Bilder anzeigen
. . . . Bilder speichern/laden
. . . . Beschriftungen
. . . . Tastaturabfrage
. . . . diverse weitere Funktionen
. . . . alte Funktionen
. . . Tekplot2 Funktionen (noch provisorisch)
. . . . Doublebuffering
. . . . MultiWindows
. . . . Farbsystem ändern


Einleitung

Überblick

Tekplot stellt eine Sammlung von Funktionen (Unterprogramme) dar, die dem Programmierer die Grafikprogrammierung erleichtern. Alle systemspezifischen Dinge werden in diesen Unterprogrammen gemacht. Mit nur 13 Grundfunktionen lassen sich schon viele Anwendungen realisieren.
Unter Verwendung der in Tekplot definierten Funktionen lassen sich somit auf einfachste Weise Grakifprogramme schreiben die auf jedem beliebigen Computer laufen.
Die bevorzugte Sprache ist C++, aber auch aus anderen Programmiersprachen wie Pascal oder Fortran lassen sich die Tekplotfunktionen aufrufen.
Es gibt folgende Grundfunktionen: Die vollständigen Definitionen sind im Kapitel 2.2 zu finden.

Grundfunktionen

Ein einfaches Beispiel in C:

/************************** Beispiel 1 **************************/
#include <stdio.h>
#include <xtekplot1.h>
static int exitflag=0;
void menu_exit() {exitflag=1;}

main()
{
 double xmin= -0.1, ymin=0.0, xmax=1.1, ymax=1.0;
 setmenu(1,"File");
 setmenu(1,"Exit",&menu_exit);
 inital(xmin,ymin,xmax,ymax); /* Grafikfenster oeffnen */
 plot(0.,0.,PENUP);
 plot(1.,1.,PENDOWN); /* eine Linie zeichnen */
 term_refresh();
 while(exitflag==0 && waitmenu(1)==0)
            ;/* auf Benutzereingaben warten */
 term_exit();
}
/************************** Beispiel 1 **************************/

Mit dem ersten setmenu wird eine Menüleiste definiert. Mit dem ersten Parameter wird dabei die Anzahl definiert, danach folgen entsprechend viele Namen für die Überschrift. Die folgenden Aufrufe von setmenu definieren die einzelnen Menüpunkte.
Mit inital wird ein Grafikfenster geöffnet und der benutzbare Zeichenbereich den angegebenen Werten (Benutzerkoordinaten) zugeordnet. Dabei ist es für das Programm egal wie gross das Fenster tatsächlich ist, die Funktion inital kümmert sich vollständig um die Umrechnungsfaktoren.
Mit plot wird der imaginäre Zeichenstift bewegt und zeichnet dabei, falls er mit PENDOWN abgesenkt ist, jeweils eine gerade Linie. Im Prinzip lassen sich damit alle Zeichnungen realisieren, aber es gibt noch einige weitere Funktionen, die schneller sind oder einfach komfortabler zu verwenden (z.B. Kreise, Vierecke, Linienzüge).
Mit term_refresh wird die Zeichnung beendet. Wird danach das Fenster in den Hintergrund verlegt und dann wieder hervorgeholt, so wird das Bild automatisch neu gezeichnet (Refresh). Mit term_exit hingegen wird das Fenster geschlossen.
Mit waitmenu kann man auf eine Aktion des Benutzers warten (Menü auswählen oder in Schliesssymbol des Fensters klicken). Wurde das Schliesssymbol angeklickt, wird 1 andernfalls 0 zurückgegeben.


Es sollten sich alle Funktionen auch von Fortran aufrufen lassen. Hier nochmals das gleiche Beispiel geschrieben für ALPHA/VAX.

/************************* Beispiel 1f **************************/
C Beispiel1f.for
C Uebersetzen:
C;ALPHA> FOR beispiel1f
C;ALPHA> BLINK beispiel1f,[PFISTER.OBJ]XTEKPLOT1
        EXTERNAL MENU_EXIT
        INTEGER exitflag,PENUP,PENDOWN,waitmenu
        REAL*4  xmin,ymin,xmax,ymax
        DATA PENUP,PENDOWN/3,2/
        DATA xmin,ymin,xmax,ymax/-0.1,0.0,1.1,1.0/
        BYTE NAMFILE(5),NAMEXIT(5)
        DATA NAMFILE/'F','i','l','e',0/
        DATA NAMEXIT/'E','x','i','t',0/
        COMMON /FLAGS/ exitflag
        exitflag=0
        CALL setmenu(%VAL(1),NAMFILE)
        CALL setmenu(%VAL(1),NAMEXIT,MENU_EXIT)
        CALL INITAL(xmin,ymin,xmax,ymax) ! Grafikfenster oeffnen
        CALL PLOT(0.,0.,PENUP)
        CALL PLOT(1.,1.,PENDOWN)         ! eine Linie zeichnen
        CALL term_refresh
        DO WHILE(exitflag.EQ.0 .AND. waitmenu(%VAL(1)).EQ.0)
        CONTINUE                         ! auf Benutzereingaben warten
        END DO
        CALL term_exit
        STOP
        END
        SUBROUTINE MENU_EXIT
        COMMON /FLAGS/ exitflag
        exitflag=1
        RETURN
        END
/************************* Beispiel 1f **************************/


Um farbige Linien zu zeichnen kann man mit color(Nummer) eine Farbe einstellen. Zuvor sollte der Nummer mit setcolor(Nummer,rot,gruen,blau) eine Farbe zugeteilt werden. Voreingestellt sind (bei mindestens 3 Bitplanes) folgende Farben:
Nummer Rot Grün Blau Farbe
0 0 0 0 schwarz (Hintergrundfarbe)
1 255 255 255 weiss (Vordergrundfarbe)
2 255 0 0 rot
3 0 255 0 grün
4 0 0 255 blau
5 255 0 255 violet
6 255 255 0 gelb
7 127 127 127 grau
Es sind also 8 Bits pro Farbkomponente vorgesehen oder total 24 Bit womit 16777216 Farben dargestellt werden können. Je nach Hardware werden aber nicht alle Bits verwendet. Auf einem älteren Amiga-Modell zum Beispiel nur jeweils die oberen 4 Bits pro Farbkomponente (total 4096 Farben).
Um die Verwendung der Farben zu illustrieren noch ein Beispiel:
/************************** Beispiel 2 **************************/
#include <stdio.h>
#include <xtekplot1.h>
double zufallszahl();
static int exitflag=0; void menu_exit() {exitflag=1;}

main()
{
 double xmin= -0.5, ymin= -1.5, xmax=30, ymax=1.5;
 double x,x1,dx=0.5, y,y1,y2,yglatt,yg1;
 int i;
 setmenu(1,"File"); setmenu(1,"Exit",&menu_exit);
 inital(xmin,ymin,xmax,ymax); /* Grafikfenster oeffnen */
 plot(xmin,0.,PENUP); plot(xmax,0.,PENDOWN); /* Koordinaten weiss zeichnen */
 plot(0.,ymin,PENUP); plot(0.,ymax,PENDOWN); /* also voreingestellte Farbe */
 color(4); /* voreingestellte Farbnummer 4 waehlen (blau) */
 plot(xmin,ymin,PENUP); plot(xmin,ymax,PENDOWN);  /* Rahmen blau zeichnen */
 plot(xmax,ymax,PENDOWN); plot(xmax,ymin,PENDOWN); plot(xmin,ymin,PENDOWN);
 setcolor(1,0,255,0); /* Farbe 1 soll gruen sein */
 setcolor(2,255,0,0); /* Farbe 2 soll rot sein */
 x1=xmin; yg1=y1=y2=zufallszahl();
 for(x=xmin+dx,i=1; x<=xmax; x+=dx,i++)
        {y=zufallszahl();
         color(1); /* Rohdaten gruen zeichnen */
         plot(x1,y1,PENUP); plot(x,y,PENDOWN);
         color(2); /* geglaettete Daten rot zeichnen */
         yglatt=(y+y1+y2)/3.;
         plot(x1,yg1,PENUP); plot(x,yglatt,PENDOWN);
         x1=x; y2=y1; y1=y; yg1=yglatt;
        }
 term_refresh();
 while(exitflag==0 && waitmenu(1)==0)
            ;/* auf Benutzereingaben warten */
 term_exit();
}
double zufall()  /* liefert Zufallszahl zwischen 0.0 und 1.0 */
{
 static double x=1.7,y;
 x=(100.+x)/(100.*(x-(long)(x))+0.7); y=10.*x;
 return (y-(long)(y));
}
double zufallszahl() {return zufall()*2.-1.;}
/************************** Beispiel 2 **************************/

Je nach System werden zur Farbdarstellung unterschiedliche Strategien benutzt. Das folgende Beispiel 3 erzielt je nach verwendeter Farbstrategie eine andere Wirkung. Bei PseudoColor scheint sich das Rad zu drehen, bei TrueColor hingegen nicht.

/************************** Beispiel 3 **************************/
#include <stdio.h>
#include <math.h>
#include <xtekplot1.h>
#define NS 16 /* Anzahl 'Speichen' des Rades */
#define PI 3.14159265358979
static int exitflag=0; void menu_exit() {exitflag=1;}

main()
{
 double xmin= -1.3, ymin= -1., xmax=1.3,ymax=1., bigrad=0.7,radius=0.15,w;
 int i,j,j0=0,r[NS],g[NS],b[NS],step,gstep,rot,gruen,blau,ticks;
 setmenu(1,"File"); setmenu(1,"Exit",&menu_exit);
 inital(xmin,ymin,xmax,ymax); /* Grafikfenster oeffnen */
 step=255/NS; gstep=2*step; rot=255; gruen=0; blau=0;
 for(i=0;i<NS;i++)
  {r[i]=rot; if((rot-=step)<0) rot=0;
   g[i]=gruen; if((gruen+=gstep)>=255) {gruen=255; gstep= -step;}
               else if(gruen<0) gruen=0;
   b[i]=blau; blau+=step;
   setcolor(i+2,r[i],g[i],b[i]);
  }
 for(i=0,w=0.;i<NS;i++,w+=2*PI/NS) /* 'Speichen' zeichnen */
  {color(i+2); fillcircle(bigrad*sin(w),bigrad*cos(w),radius,radius);}
 term_refresh();
 ticks=50/NS; /* Wartezeit fuer 1 Umdrehung pro Sekunde */
 if(ticks==0) ticks=1;
 while(exitflag==0 && waitmenu(0)==0)
  {for(i=0,j=j0;i<NS;i++)              /* Aendern der Farbzuordnungen */
        {setcolor(i+2,r[j],g[j],b[j]); /* hat nur mit PseudoColor die */
         if(++j==NS) j=0;              /* gewuenschte Wirkung.        */
        }
   if(++j0==NS) j0=0;
   Delay(ticks); /* soviele 1/50 Sekunden warten */
  }
 term_exit();
}
/************************** Beispiel 3 **************************/

Um auch auf nicht PseudoColorfähigen Computern eine Bewegung zu erhalten könnte man die Schlaufe "Speichen zeichnen" in die while-Schlaufe vor die Wartefunktion Delay legen. Die heutigen Rechner sind aber nicht genügend schnell um so eine Zeichnung in deutlich weniger als 0.02 Sekunden zu machen.


Programme linken

UNIX, Amiga

Unter UNIX legt man sich eine Datei "makefile" an, die etwa so aussieht:
#********************** UNIX makefile ***************************
C=gcc
all: beispiel3
beispiel3: beispiel3.c
        $C -I$h beispiel3.c $h/xtekplot1.o -lm -lX11 -o beispiel3
#********************** UNIX makefile ***************************
Mit "make" oder auch "make all" wird dann übersetzt und gelinkt. Damit können auch mehrere Dateien zusammengelinkt werden, wobei automatisch nur die veränderten Dateien neu übersetzt werden. Man kann auch aus dem Editor heraus (emacs mit KED-Emulation) mit ^B das makefile aufrufen, wobei anschliessend jeweils mit ^N an die noch fehlerhaften Stellen im Programm gesprungen werden kann.
(hier bedeutet ^B dass die Tasten Ctrl und B gleichzeitig gedrückt werden)

VAX/ALPHA

Unter ALPHA/VAX/VMS legt man sich eine Datei "make.com" an, die etwa so aussieht:
!************************** make.com *****************************
$ cx beispiel
$ blink beispiel,[pfister.obj]xtekplot1
$ pur beispiel.*
!************************** make.com *****************************
Um cx und blink zu definieren, können im "login.com" (auf pcizuse) folgende Zeilen eingefügt werden:
$ @[PFISTER.COM]VAXC
$ @[PFISTER.COM]cplusplus
$ @[PFISTER.COM]linker
Statt der Datei "make.com" kann man auch in der Quelldatei entsprechende Kommentarzeilen einfügen und dann einfach mit "com beispiel" das Programm übersetzen und linken.
!********************* Teil von beispiel.c ***********************
/*
;AVAX> cx beispiel
;AVAX> blink beispiel,[pfister.obj]xtekplot1
;AVAX> pur beispiel.*
*/
!********************* Teil von beispiel.c ***********************

Versionen

tekplot.c alte Version (1.9)
tekplot1.cc diese Spezifikationen ohne MultiWindows, ohne alte Funktionen
tekplot2.cc Vollständige Version (noch nicht fertig programmiert)


Varianten für die verschiedenen Maschinen beginnen jeweils mit einer entsprechenden Abkürzung (z.B. MAC_tekplot.c, xtekplot1.cc, amitekplot1.cc).

Definition des Tekplotstandards

Globale Variablen

Alle globalen Variablen in Tekplot bestehen aus Kleinbuchstaben, Konstanten hingegen aus Grossbuchstaben. Die angegebenen Werte der Konstanten sind nur Richtwerte und können je nach System und Implementierung varieren.
Die Variablen sollten wenn möglich vom Anwendungsprogramm nicht direkt gelesen (und schon gar nicht verändert) werden. Es sind statt dessen die entsprechenden Funktionen zu verwenden (z.B. mausposition, getsize, set_tektitel).

aktuelle Fensterausmasse:

int tekplot_breite;  Breite in Pixel
int tekplot_hoehe;   Höhe in Pixel
int tekplot_tiefe;   Anzahl Bitplanes  (in getsize() verwendet)
aktuelle Mausdaten:
int tek_mausx,tek_mausy;  Koordinaten in Pixel von oben links gezählt
int maustasten_zustand;   enthält Bits die die Maustasten representieren.
 LIMAUS      0x040        linke Maustaste
 REMAUS      0x400        rechte Maustaste
 MIMAUS      0x100        mittlere Maustaste
 SCROLL_UP   0x800        Mausrad rauf
 SCROLL_DOWN 0x1000       Mausrad runter
 MAUSMASKE   0x540        alle vorhandenen Maustasten
 MAUSUP      1            Taste losgelassen
 MAUSDOWN    2            Taste gedrückt
 MAUSUDMASKE 3            Maske um nach loslassen/drücken zu prüfen
weitere Konstanten:
 PENUP     3              Angehobener Zeichenstift (in plot() gebraucht)
 PENDOWN   2              Abgesenkter Zeichenstift
 JAM1       1             normaler Zeichnungsmodus
 JAM2       2             spezieller Zeichnungsmodus
 COMPLEMENT 3             Farbumkehr-Zeichnungsmodus
 INVERSEVID 4             Zeichnungsmodus für inversen Text
Farbstrategie:
 STATICGRAY      0        nur fest eingestellte Grauwerte darstellbar
 GRAYSCALE       1        nur Grauwerte darstellbar
 STATICCOLOR     2        unveränderliche Farbtabelle
 PSEUDOCOLOR     3        Farbnummern werden in Tabelle nachgeschaut
 TRUECOLOR       4        Farben werden direkt als RGB-Werte behandelt
 DIRECTCOLOR     5        ähnlich TRUECOLOR
Für Requester-Beschriftungen:
 SPRACHE_DEUTSCH 1        für automatisch eingesetzten Text
 SPRACHE_ENGLISH 2        für automatisch eingesetzten Text
Diverses:
FILE * tekplot_fpbild;       Dateizeiger beim Speichern mit plotsave()
char * tekplot_fenstername;  FensterBeschriftung (in set_tektitel() verwendet)
MAX_DATEINAME_LAENGE 256
MAX_PFADNAME_LAENGE 1024

Funktionen

Grundfunktionen

void inital(double xmin,double ymin,double xmax,double ymax)
Ein Grafikfenster wird geöffnet und der sichtbare Bereich den Fliesskommawerten zugeordnet. Mit xmin, ymin wird die Ecke unten links und mit xmax, ymax die Ecke oben rechts definiert. Fortranversion: INITAL(REAL*4,...)

void term_refresh()
Der Zeichnungszugriff auf das Grafikfenster wird wieder ausgeschaltet. Das gibt dem Tekplotsystem die Möglichkeit das Bild für Refreshs zu speichern.

void term_exit()
Damit wird das Grafikfenster wieder geschlossen.

void inital_new(double xmin,double ymin,double xmax,double ymax)
Kann nach einem term_refresh() verwendet werden. Die Werte xmin...ymax müssen dabei nicht unbedingt die gleichen sein wie bei inital. Wenn sie gleich sein sollen kann man sie weglassen (in C++), oder alle auf 0.0 setzen.

void color(int farbnummer)
Aktuelle Farbe setzen (Fortranaufruf: COLOR(%VAL(nr))) Bei weniger als 24 Bit Farbtiefe: benutze setcolor() um die Farbe zu ändern, oder setzergbtabelle() um die Voreinstellung der Farbpalette zu ändern. Bei 24 Bit Farbtiefe: rgbcolor() benutzen, oder als Farbnummer direkt 0xRRGGBB benutzen.

void rgbcolor(int rot,int gruen,int blau)
Aktuelle RGB-Farbe setzen. Die Farbanteile sollten Zahlen im Bereich 0 bis 255 sein. Dies funktioniert aber nur bei 24 Bit Farbtiefe. Ansonsten setcolor() und color() verwenden.

void tek_pen(char* modus)
Stiftmodus zum Linien zeichnen setzen. Der Modus wird jeweils an den ersten 2 Zeichen im String modus erkannt. FETT oder BOLD für dicke Linien, PUNKT punktiert, LSTRICH lang gestrichelt, KSTRICH Kurz gestrichelt, PSTRICH PunktStrich, PPSTRICH PunktPunktStrich, LPSTRICH MSTRICH für weitere Strichelungsarten. NORM normale Linie. (Fortranaufruf: PEN('TEXT'))

void plot(double x,double y,int pen)
Für pen sind die Werte PENUP (gehobener Stift) und PENDOWN (abgesenkter Stift) zu verwenden. Fortranversion: PLOT(REAL*4,REAL*4,INTEGER*2)

void tek_line(int n,double* xfeld,double* yfeld)
Zeichnet einen Linienzug der durch n Stützpunkte definierter ist. Da der erste Punkt auch zählt muss n eins grösser sein als die Anzahl zu zeichnende Linien. Fortranversion: LINE(INTEGER*2,REAL*4,REAL*4)

void plotsave(char* string) in Kapitel "Bilder speichern/laden" erklärt.

void setmenu(int n,...)     in Kapitel "Menüs" erklärt.

int waitmenu(int waitflag)  in Kapitel "Menüs" erklärt.

void tek_grein(double*...)  in Kapitel "Grafikeingabe" erklärt.

Farben setzen

void setcolor(int farbnr,int rot,int gruen,int blau)
Die Farbe mit der Nummer farbnr neu definieren. Als Farbanteile sind Werte von 0 bis 255 gültig. 0 0 0 entspricht schwarz, 255 255 255 entspricht weiss. Siehe auch color() um aktuelle Farbe zu setzen. Bei 24 Bit Farbtiefe sollte besser rgbcolor() verwendet werden.

void setzergbtabelle(int n,UBYTE *tabelle[3])
Die ersten n Einträge der Voreingestellten Farbpalette setzen. Dies muss vor inital gemacht werden. tabelle wird in c so definiert: UBYTE tabelle[n][3]={{R,G,B},...};

void setmaxfarben(int n)
Maximale Anzahl Einträge der Farbtabelle setzen. Damit kann man verhindern, dass bei grosser Tiefe eine riesige Farbtabelle erstellt wird. Muss vor inital gemacht werden.

Figuren zeichnen

void tek_punkt(double x,double y,int farbnr)
Einen Punkt zeichnen

void drawbox(double x1,double y1,double x2,double y2)
Viereck zeichnen

void fillbox(double x1,double y1,double x2,double y2)
gefülltes Viereck zeichnen

void drawcircle(double x,double y,double r1,double r2)
Kreis oder Ellipse mit Mittelpunkt x y zeichnen. Der Radius r1 gilt in Richtung der x-Achse, r2 in Richtung der y-Achse. Um einen Kreis zu erhalten müssen die Seitenverhältnisse des Grafikfensters und die in inital gewählten Grenzen berücksichtigt werden.

void fillcircle(double x,double y,double r1,double r2)
gefüllter Kreis oder Ellipse zeichnen

void fillpolygon(int n,double *xf,double *yf)
gefülltes Vieleck zeichnen

Funktionen zum Zeichnen in Gerätekoordinaten

Die Gerätekoordinaten beginnen im allgemeinen oben links mit
0 0 (erstes gezeichnetes Pixel) und enden unten rechts mit
tekplot_breite-1 tekplot_hoehe-1 (letztes gezeichnetes Pixel).
Dies muss aber nicht unbedingt so sein. Damit ein Programm sicher auf allen System läuft sollten nur Pixelkoordinaten verwendet werden, die aus Umrechnungen mit den in Tekplot vorhandenen Funktionen stammen (Abschnitt Koordinatenumrechnungen).

void moveto(int x,int y)
Aktuelle Stiftposition setzen.

void lineto(int x,int y)
Linie von aktueller zu neuer Stiftposition zeichnen.

void iline(int n,int* xfeld,int* yfeld)
durch n Stützpunkte definierter Linienzug zeichnen.

void ipunkt(int x,int y,int farbnr)
Einen Punkt zeichnen

void idrawbox(int x1,int y1,int x2,int y2)
Viereck zeichnen

void ifillbox(int x1,int y1,int x2,int y2)
gefülltes Viereck zeichnen

void idrawcircle(int x,int y,int r1,int r2)
Kreis oder Ellipse mit Mittelpunkt x y zeichnen. Bei einem Kreis und quadratischen Pixeln sind die Radien r1 und r2 identisch.

void ifillcircle(int x,int y,int r1,int r2)
gefüllter Kreis oder Ellipse zeichnen

void iviereck(int x1,int y1,int x2,int y2,int farbnr)
Gefülltes Viereck zeichnen. Dies entspricht dem Aufruf von color(farbnr) gefolgt von ifillbox(x1,y1,x2,y2).

void tek_flush()
Zeichnungspuffer leeren. Damit kann sichergestellt werden dass alles bisherige auch wirklich ausgeführt wurde. Sollte unbedingt verwendet werden wenn nach einem plot() direkt eine Funktion die in Pixelkoordinaten zeichnet verwendet werden soll. (plot() puffert in xtekplot seine Daten speziell um auch grosse Linienzüge sehr schnell zeichnen zu können.)

Koordinatenumrechnungen

Man beachte dass die y-Achse der Bildschirmkoordinaten (=Pixelkoordinaten) von oben nach unten, bei den Benutzerkoordinaten (=Userkoordinaten) jedoch wie gewohnt von unten nach oben zeigt.
Um wirklich Systemunabhängig zu programmieren sollten für Umrechnungen immer die entsprechenden Funktionen verwendet werden. Die Pixelkoordinaten müssen nicht unbedingt bei 0 beginnen (z.B. Offset durch Fensterrand oder Menüleiste).

void koorduser2pix(double x,double y,int *ix,int *iy)
von Benutzerkoordinaten in Bildschirmkoordinaten umrechnen

void koordpix2user(int ix,int iy,double *x,double *y)
von Bildschirmkoordinaten in Benutzerkoordinaten umrechnen

void deltakoorduser2pix(double x,double y,int *ix,int *iy)
Differenzen von Benutzerkoordinaten in Differenzen von Bildschirmkoordinaten umrechnen (z.B. Radius eines Kreises).

void deltakoordpix2user(int ix,int iy,double *x,double *y)
Differenzen von Bildschirmkoordinaten in Differenzen von Benutzerkoordinaten umrechnen.

Eingabefunktionen

int janeinrequester(char *text,char *jatext,char *neintext)
int janeinrequester_utf8(char *text,char *jatext,char *neintext)
Dem Benutzer wird in einem Eingabefenster eine Frage gestellt. Der Rückgabewert ist bei positiver Antwort ungleich 0 (Anklicken von jatext).

int requester_input(int n,char *text1,char *c1,char *c2,zeig1 ...)
Es wird in einem Eingabefenster nach n verschiedenen Variablen gefragt. text1 sollte den Namen der ersten Variablen enthalten; c1 ist der Kontrollstring zur Anzeige des aktuellen Inhalts, c2 der Kontrollstring zur Eingabe eines neuen Wertes und zeig1 der Zeiger auf die erste Variable. Für jede weitere Variable müssen jeweils weitere vier Parameter angegeben werden. Der Rückgabewert ist bei Anklicken von ok 1 sonst 0.

int nachfilenamefragen(char *str,char *name,int max,...)
Es wird nach einer Datei gefragt wobei eine entsprechende Dateiauswahlbox erscheint. In str sollte ein Text stehen der klarstellt wozu die auszuwählende Datei verwendet werden soll (z.B. "lade Textdatei"). In name kann ein voreingestellter Dateiname samt Pfad stehen. Der ausgewählte Name wird auch in dises Feld geschrieben (höchstens max Zeichen). Der Rückgabewert ist 1 wenn ok angeklickt wurde, sonst 0. Es können noch einige weitere Parameter angegeben werden: int flgs=0 (z.B. SPRACHE_DEUTSCH oder SPRACHE_ENGLISH), char *filter=NULL (Muster für sichtbare Dateien), char *oktext=NULL (Bei NULL wird automatisch "OK", "SAVE" oder "LOAD" gesetzt), char *canceltext=" CANCEL", char *parenttext=" Parent" (Schalter für übergeordnetes Verzeichnis), char *diskstext=" Disks" (Um auf anderes Wurzelverzeichnis zu wechseln).

Grafikeingabe mit Maus

void tek_grein(double* x,double* y)
Ein Fadenkreuz einschalten und auf Eingabe eines Grafikpunktes (Klick mit linker Maustaste) warten. Fortranversion: GREIN(REAL*4,REAL*4)

void imausklick(int taste,int *x,int *y)
Auf Mausklick warten. Im Parameter taste wird angegeben auf welchen Mausknopf gewartet werden soll. Wenn das Bit MAUSUP gesetzt ist wird gewartet bis alle angegebenen Knöpfe (LIMAUS MIMAUS REMAUS) losgelassen werden. Danach wird wenn MAUSDOWN gesetzt ist gewartet bis einer der angegebenen Knöpfe gedrückt wird. In x und y wird die Mausposition in Pixelkoordinaten zurückgegeben.

void mausklick(int taste,double *x,double *y)
Gleich wie imausklick, aber Mausposition wird in Userkoordinaten zurückgegeben.

int imausposition(int *x,int *y)
Momentane Mausposition in Pixelkoordinaten lesen. Der Funktionsrückgabewert enthält den Zustand der Maustasten (Bits LIMAUS MIMAUS REMAUS für gedrückte Tasten gesetzt, und SCROLL_UP SCROLL_DOWN für Mausrad).

int mausposition(double *x,double *y)
Momentane Mausposition in Userkoordinaten lesen. Der Funktionsrückgabewert enthält ebenfalls den Zustand der Maustasten (wie bei imausposition).

int maustasten()
Es wird das nächste Ereignis abgewartet, darauf reagiert und der Zustand der Maustasten zurückgegeben. Der Rückgabewerte enthält ebenfalls den Zustand der Maustasten (wie bei imausposition).

void set_funktions(funkzeig pre,funkzeig rel,funkzeig exp,funkzeig mot)
Setzen von Funktionen die bei Ereignissen aufgerufen werden sollen. pre() wird jeweils beim Drücken einer Maustaste, rel() beim Loslassen einer Maustaste, mot() beim Bewegen des Mauszeigers und exp() nach Verdeckungen des Tekplot-Fensters aufgerufen. Für nicht benötigte Funktionen wird NULL eingesetzt. set_funktions() sollte vor inital() aufgerufen werden.

Manipulation der Fenstergrösse

void setsize(int Breite,int Hoehe,int Tiefe)
Diese Funktion muss VOR inital() und falls vorhanden vor dem ersten setmenu aufgerufen werden! Damit kann angegeben werden wie breit und hoch in Pixeln das zu öffnende Grafikfenster werden soll. Tiefe gibt die Anzahl Bitplanes an. Es sind dann maximal 2 Tiefe Farben gleichzeitig darstellbar.

void getmaxsize(int* Breite,int* Hoehe,int* Tiefe,int* VisualKlasse)
Damit kann festgestellt werden welche maximalen Fenstergrössen auf dem aktuellen System benutzbar sind. Aus VisualKlasse lässt sich die vom System verwendete Farbstrategie erfahren. Kann vor inital aufgerufen werden.

void getsize(int* Breite,int* Hoehe,int* Tiefe,int* VisualKlasse)
Damit kann festgestellt werden welche aktuellen Fenstergrössen eingestellt sind. Aus VisualKlasse lässt sich die Farbstrategie erfahren. Darf erst nach inital aufgerufen werden.

void fullscreen_modus(int modus)
Damit kann ein Vollbildmodus eingestellt werden. 1=Vollbildmodus, 0=bisheriges Verhalten. Diese Funktion muss vor inital() und vor einem allfälligen getmaxsize() aufgerufen werden.

double getaspect()
Damit erhält man das Verhältnis von Breite zu Höhe eines Pixels. Dies ist nützlich um z.B. wirklich runde Kreise zu zeichnen (Verwendung von r2=getaspect()*r1 in idrawcircle).

void setaspect(double asp)
Damit kann das Verhältnis von Breite zu Höhe eines Pixels korrigiert werden. Dies kann nötig sein wenn das Betriebssystem die wirklichen Pixelgrössen des Bildschirms nicht kennt.

double getraspect()
Damit erhält man das Verhältnis von Höhe zu Breite eines runden Kreises in User-Koordinaten. Dies ist nützlich um z.B. wirklich runde Kreise zu zeichnen (Verwendung von r2=getraspect()*r1 in drawcircle).


Menüs

Die Funktionen setmenu und setsubmenu müssen vor inital aufgerufen werden.
Wenn ein Text in setmenu oder setsubmenu mit % beginnt so hat das folgende Zeichen eine spezielle Funktion:
q Der Menüpunkt hat ein Quadrat vorangestellt
Q ein ausgefülltes Quadrat
o einen Kreis
O ein ausgefüllter Kreis
r freier Platz für ein Markierungszeichen (erst ab Tekplot1)
R ein Markierungszeichen gesetzt (erst ab Tekplot1)
A das nächste Zeichen x ist ein "ShortCut" (erst ab Tekplot1)
~ Eine Trennzeile (es sollten einige weitere Tildezeichen folgen)
% das Prozentzeichen selbst


void setmenu(int n,char *text1,... ,prog1,...)
Menüs definieren. Beim ersten Aufruf werden n Texte übergeben, die als Überschriften im Menübalken zu verwenden sind. Bei den folgenden Aufrufen wird für jedes Menü ein Text (oder NULL falls ein Menü keine weiteren Einträge haben soll) angegeben, und die Adressen der aufzurufenden Funktionen (nur Funktionsnamen ohne Klammern) oder NULL falls keine aufgerufen werden soll.

void setsubmenu(int n,...)
Untermenüs definieren. Bei jedem Aufruf wird für jedes Menü ein Text (oder NULL falls für dieses Menü kein (weiterer) Untermenüeintrag erfolgen soll) angegeben, und die Adressen der aufzurufenden Funktionen oder NULL falls keine aufgerufen werden soll.

int waitmenu(int waitflag)
Auf Benutzereingabe warten. Ist waitflag gesetzt so wird gewartet bis ein Ereignis eintrifft, wenn waitflag 0 ist wird falls kein Ereignis ansteht sofort zurückgekehrt. Wenn das Fenster geschlossen wurde wird 1, sonst 0 zurückgegeben.

void getmenuids(long idnr,long *idfeld,int max)
Identifikationsnummern der Menüs erhalten. Wird für idnr 0 angegeben so werden die Nummern aller Menupunkte im idfeld abgelegt. Die ersten n Nummern sind für die Einträge im Menübalken reserviert. Die folgenden Nummern entsprechen dann der Reihenfolge der Menüs als ob alle ausgeklappt wären. Ist idnr ungleich 0 werden die ID-Nummern der Untermenüs des entsprechenden Menüpunktes im idfeld abgelegt. max gibt an wieviele Nummern maximal ins idfeld geschrieben werden sollen.

void changemenu(long idnr,char *neuertext)
Text eines Menüs oder Untermenüs ändern. idnr ist eine Nummer die von getmenuids() erhalten wurde, oder einer Menüfunktion beim Aufrufen übergeben wurde. Da die id-Nummern systemabhängig sind darf man hier keinesfalls direkt eine Zahl eingeben!

int menu_switch(long id,long *ids,int k,int max,cha **text,int k1,int k2)
Verwaltet das Abhaken von Menupunkten in einem Submenu. id ist die aktuelle Nummer, ids ist das Feld aller Nummern des zugehoerigen Untermenus. max ist die Anzahl Menupunkte des Untermenus. k1 und k2 sind die Grenzen (0 bis max-1) und k der abzuhakende Menupunkt (k1 bis k2). text ist ein Feld der entsprechenden Menutexte (char *text[]=text1,text2...).

int get_menuleistenhoehe()
Höhe der Menüleiste in Pixel (sollte von Anwenderprogrammen nicht benötigt werden).

Synchronisation

Bei bewegten Bildern ist es wichtig dass nicht gezeichnet wird wenn der Rasterstrahl gerade den entsprechenden Bereich erneuert, sonst gibt es hässliche Flimmereffekte.
Wenn die nötigen Änderungen nicht zu umfangreich sind kann man in der Zeit die für den Zeilenrücksprung gebraucht wird zeichnen.
Bei grösseren Zeichnungen sollten zwei Bildspeicher verwendet werden (double buffering). Im gerade nicht dargestellten Speicher wird dann das neue Bild gezeichnet und beim Zeilenrücksprung die beiden Bildspeicher vertauscht (siehe changebuffer()).

void waitBOF()
Auf Beginn des Zeilenrücksprungs warten (Wait Bottom Of Frame).

void waitTOF()
Auf Ende des Zeilenrücksprungs warten (Wait Top Of Frame).

Bilder anzeigen

XImage* tek_xcreateimage(int xmax,int ymax)
Struktur fuer ein Bild reservieren. Die Bilddaten sind dann noch undefiniert. Mit XPutPixel(XImage *image,int x,int y,ULONG rgb) können dann die Bildpunkte gesetzt werden. Danach kann es mit der folgenden Funktion (tek_xputimage) verwendet werden. Schlussendlich sollte die Struktur dann wieder mit XDestroyImage(XImage*) freigegeben werden.
void tek_xputimage(XImage *image,int x0,int y0,int x1,int y1,int xbreite,int yhoehe)
Ein Bild an der Position x1,y1 (obere linke Ecke) zeichnen. Um das ganze Bild zu zeichnen werden x0=0, y0=0, xbreite=xmax und yhoehe=ymax gesetzt. Falls nur ein Ausschnitt vom image gezeichnet werden soll, können da entsprechend andere Werte gesetzt werden.

Bilder speichern/laden

void plotsave(char* string)
Speichern der Grafikoperationen ein/aus-schalten. Die Umgebungsvariable PLOTSAVE definiert dabei den Namen der Zieldatei. (Fortranaufruf: PLOTSAVE('STRING')) Mit string wird das zu speichernde Grafikformat angegeben:
POST Postscript
IFF IFF-VECT
AUS Speicherungsmodus ausschalten
OFF Speicherungsmodus ausschalten
iffbild_speichern(char *name)
Bild als IFF-ILBM (Pixelbild) speichern. Geht bisher nur auf dem Amiga.
iffbild_laden(char *name)
IFF-ILBM-Bild laden. Geht bisher nur auf dem Amiga.

Beschriftungen

void set_tektitel(char *text)
Setzen des Fenstertitels (Screentitel)

void ischrift(int x,int y,char *,double winkel=0.0)
void ischrift_utf8(int x,int y,char *,double winkel=0.0)
An der Position (Pixelkoordinaten) x y wird ein Text geschrieben. Die Richtung wird als Winkel in Grad angegeben. (Winkel geht (noch) nicht in unter XWindows, Speichern unter PostScript klappt aber)
Mit der _utf8 Version kann Text mit UTF8-Kodierung angezeigt werden. (Dazu wird die Funktion utf8_to_isolatin1() benutzt.)

int itextsize(int bx,int hy,char *font=NULL,int style=0)
Schriftgrösse setzen. Die Buchstaben sollen eine Breite von etwa bx und eine Höhe von etwa hy bekommen. Wenn möglich wird der angegebene Font gewählt. Gültige Schriftstile (style) sind: BOLD ITALIC und UNDERLINE, oder 0 für normale Schrift. Wird für font NULL angegeben so wird ein voreingestellter Font verwendet. Als Rückgabewert bekommt man die wirklich gesetzte Buchstabenhöhe.

void schrift(double x,double y,char *,double winkel=0.0)
void schrift_utf8(double x,double y,char *,double winkel=0.0)
Wie ischrift aber in Userkoordinaten

double textsize(double bx,double hy,char *font=NULL,int style=0)
Wie itextsize aber in Userkoordinaten

void bpencolor(int farbnr)
Hintergrundfarbe für Texte einstellen. Sollen die Texte ohne Hintergrund gezeichnet werden wird für farbnr -1 angegeben. Um inverse Texte zu zeichnen kann man den Zeichenmodus mit drawmode(INVERSEVID) setzen.

Tastaturabfrage

int keyget(int *n,int *asci,ULONG *rawcode)
Falls kein Tastendruck ansteht wird 0 zurückgegeben und die Parameter nicht verändert. Bei einer gedrückten Taste steht in rawcode ein Code der die Taste eindeutig identifiziert. Falls n gesetzt ist steht in asci der ASCII-Code der Taste. (Beispiele: n=1 asci=0x32 rawcode=0x32 ---> Taste 2 gedrückt, n=1 asci=0x32 rawcode=0xFFB2 ---> Taste 2 des Zifferblocks gedrückt.) Die Bedeutungen der rawcodes sind in X11:KEYSYMDEF.H beschrieben.

diverse weitere Funktionen

void screenclear(int farbnr=0)
Grafikfenster löschen. Es wird mit der Hintergrundfarbe (farbnr) gefüllt.

void drawmode(int mode)
Zeichnungsmodus setzen. Mit JAM1 werden die zu zeichnenden Pixel auf die gerade aktuelle Farbe gesetzt. JAM2 mischt mit der schon vorhandenen Farbe ? Mit COMPLEMENT wird das Negativ der im Pixel vorhandenen Farbe gesetzt (ExklusivOder Verknüpfung der Bits in den Bitplanes mit den Bits der aktuellen Farbnummer). INVERSEVID wird nur beim Zeichnen von Text gebraucht (erst ab Tekplot2).

void Delay(int n)
Es werden n 50stels Sekunden gewartet.

double rundezahl(double z1,double z2)
Runde Zahl zwischen z1 und z2 suchen.

Tekplot2 Funktionen (noch provisorisch)

Alle Funktionen von Tekplot1 sind auch hier enthalten. Zusätzlich gibt es aber noch Funktionen für:

Doublebuffering

Man vergleiche mit dem Abschnitt Synchronisation.
int changebuffer(int shownr,int drawnr)
Bildschirmspeicher vertauschen. Mit shownr wird der anzuzeigende Speicher, mit drawnr der zum Zeichnen zu benützende Speicher angegeben. Die Speicher werden mit Nummern angegeben, 0 für den schon mit inital reservierten 1 für einen weiteren (wird beim ersten Aufruf automatisch reserviert). Der Rückgabewert ist im Fehlerfall 0. Diese Funktion ist schon in xtekplot1 ab Version 2.82 realisiert.

MultiWindows

int changewindow(int nr)
Es wird auf das Fenster mit der Nummer nr gewechselt

Farbsystem ändern

TrueColor sollte sich auf jedem System simulieren lassen.
PseudoColor sollte auf folgenden Systemen auch gehen: ALPHA, MAC
int setcolorsystem(int VisualKlasse,int Tiefe,int breite, int Hoehe)
Wenn möglich entsprechende Grafikkarte verwenden. Der Rückgabewert ist die mit diesen Einstellungen maximal mögliche Tiefe, wenn Darstellung mit vorgegebener Breite und Höhe nicht möglich 0 und wenn diese VisualKlasse nicht möglich -1.


alte Funktionen

Die folgenden Funktionen sollten nach Möglichkeit in neuen Programmen nicht mehr verwendet werden. Es gibt dafür bessere oder schnellere Lösungen mit neueren Funktionen.


void iplot(int x,int y,int pen)
Für pen sind die Werte PENUP (gehobener Stift) und PENDOWN (abgesenkter Stift) zu verwenden. Für möglichst schnelle Programme sollten besser die Funktionen moveto und lineto verwendet werden.

void term()
Wie term_refresh() oder term_exit(), abhängig vom verwendeten System.

void grein(float* x,float* y)
Wie tek_grein aber mit Fliesszahlen kleinerer Genauigkeit.

void line(short* nz,float* xf,float* yf)
Wie tek_line() aber mit kleinerer Genauigkeit und nz auch als Zeiger (Fortran-Schnittstelle).

void qpunkt(float* x,float* y)
Punkt in aktueller Farbe zeichnen. In neuen Programmen tek_punkt verwenden.

void qgclear()
wie screenclear().

void q2esc(char* str)
Escapesequenz an Tektronik-Terminal schicken. Nur mit entsprechendem Terminal verwendbar.

void pen(char* x)
Wurde einst auch statt color() verwendet. Sonst aber wie tek_pen().

void iplotline(int x1,int y1,int x2,int y2,int farbe)
Linie ziehen. Besser moveto und lineto verwenden.

void setxsync(int modus)
XSync()-Aufrufe verwenden. Mit modus=1 werden in screenclear() ein XSync(dpy,0) aufgerufen, mit modus=2 auch noch beim Linien zeichnen. Es sollte nicht nötig sein diese Funktion zu verwenden, aber wenn ein älteres Programm nicht mehr korrekt geht (z.B. Ende eines Linienzugs nicht mehr zeichnet) kann man hiermit das xsync-Verhalten vor Version 2.8 simulieren.

Dieses Dokument wurde ursprünglich in LaTeX geschrieben, und dann nach HTML konvertiert.
Einige Aktualisierungen wurden erst nachträglich gemacht.
Letzte Updates: 7.5.2015, 26.10.2017, 2.12.2017 (R.Pfister)