home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / grafik / tiff / graf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-12  |  31.2 KB  |  937 lines

  1. /***************************************************************
  2. *                                                              *
  3. *  Alles hier ist in Turbo C 1.0 für den ATARI ST geschrieben. *
  4. *  Dieses C ist voll nach ANSI definiert, auf jede nichtkom-   *
  5. *  patible Erweiterung wurde bewußt verzichtet, ist aber auch  *
  6. *  unter Turbo C 1.1 getestet.                                 *
  7. *                                                              *
  8. *  Es wurden nur sehr wenige Grafikbefehle aus dem GEM-VDI     *
  9. *  benutzt: Linien ziehen, Beschriften, Schrifthöhe wählen,    *
  10. *  Linienart wählen, Farbe wählen. Diese Befehle lassen sich   *
  11. *  durch entsprechende Grafikbefehle anderer Computer oder     *
  12. *       Sprachen bzw. Compiler einfach ersetzen.               *
  13. *                                                              *
  14. *  Auf alle besonderen C-Tricks wurde verzichtet, inbesondere  *
  15. *  auf Seiteneffekte. Das Bitfeld 'malen' läßt sich problem-   *
  16. *  los durch ein array aus integer ersetzen, somit ist diese   *
  17. *  Routine auch in andere Programmiersprachen übersetzbar.     *
  18. *                                                              *
  19. ***************************************************************/
  20.  
  21. /******* Der ATARI ST und TURBO C brauchen so ihre Definitionen */
  22.  
  23. #include <math.h>
  24. #include <stdio.h>
  25. #include <tos.h>     /* Betriebssystem-include */
  26. #include <stdlib.h>
  27. #include <string.h>
  28.  
  29. #include <aes.h>     /* Nur für die Grafik nötig, nicht nach ANSI */
  30. #include <vdi.h>
  31.  
  32. #define  TRUE     !0
  33. #define  FALSE    0
  34. #define  FAILURE  !0
  35. #define  SUCCESS  0
  36.  
  37. #define  PI             3.14159265358979323846
  38.  
  39. /******** Typendefinitionen, Funktionsprototypen **************/
  40.  
  41. typedef struct
  42. {
  43.   double real;
  44.   double imag;
  45. } COMPLEX;
  46.  
  47. typedef struct
  48. {
  49.    unsigned raster: 1;
  50.    unsigned transp: 1;
  51.    unsigned extrem: 1;
  52.    unsigned nullin: 1;
  53.    unsigned achsen: 1;
  54.    unsigned verlin: 1;
  55.    unsigned marker: 3;
  56.    unsigned normen: 1;
  57.    unsigned zahlen: 1;
  58.    unsigned       : 6;
  59. } MALFLAGS;
  60.  
  61. double diabat(double x),frac(double x);
  62.  
  63. int diagramm(int art, MALFLAGS malen, long xwerte, long ywerte,
  64.              long n, char typ, int x, int y, int w, int h);
  65. void marker_malen(int b, int xmin, int xmax, int ymin, int ymax,
  66.                   int pixoff, double pixfak, double *step,
  67.                   double *stepsum, double *stepmk,
  68.                   char dir, MALFLAGS malen, int flag);
  69. void polmarker_malen(int xpixoff, int ypixoff, 
  70.                      double pixfak, double *step, double *stepsum,
  71.                      double *stepmk, MALFLAGS malen);
  72.  
  73. double diabat(double arg);
  74. double frac(double x);
  75.  
  76. /*** Rest der Definitionen für's Demoprogramm ***/
  77.  
  78. int handle, gem_handle, ap_id, dummy;
  79. int contrl[12], intin[128], intout[128], ptsin[128], ptsout[128];
  80. int work_in[11], work_out[57];
  81. void hauptprg(void);
  82. int prog_init(void);
  83. void prog_exit(int art);
  84.  
  85. /*** Demoprogramm ***/
  86.  
  87. int main(void)
  88. {  int erfolg;
  89.  
  90.    erfolg = prog_init();
  91.    if(erfolg==1) hauptprg();
  92.    prog_exit(erfolg);
  93.    return(0);
  94. }
  95.  
  96. void hauptprg()
  97. {  long i,n=256L; double *x,*y,yh; MALFLAGS wahl;
  98.         int xw,yw,hw,ww,art,pxy[10];
  99.  
  100.    x = (double*)malloc((n+1)*sizeof(double));
  101.    y = (double*)malloc((n+1)*sizeof(double));
  102.    
  103.    v_clrwk(handle);
  104.    printf("Art des Diagramms (0 bis 6)    : ");
  105.    scanf("%d",&art); art %= 7;
  106.    printf("X,Y der oberen linken Bildecke : ");
  107.    scanf("%d,%d",&xw,&yw); xw %=640; yw %=400;
  108.    printf("Weite und Höhe des Diagramms   : ");
  109.    scanf("%d,%d",&ww,&hw); 
  110.    if(ww+xw>639) ww = 639-xw;
  111.    if(hw+yw>399) hw = 399-yw;
  112.    
  113.    for(i=0;i<n;i++)
  114.    {  *(x+i) = (double)(i+1)/(double)n*6.;
  115.       yh = (double)i/(double)n*6.-3.;
  116.       *(y+i) = exp(-yh*yh)*.995;
  117.    }
  118.    v_clrwk(handle);
  119.    pxy[0] = xw; pxy[1] = yw; pxy[2] = xw+ww; pxy[3] = yw;
  120.    pxy[4] = xw+ww; pxy[5] = yw+hw; pxy[6] = xw; pxy[7] = yw+hw;
  121.    pxy[8] = xw; pxy[9] = yw;
  122.    v_pline(handle,5,pxy);
  123.    
  124.    wahl.raster=1;
  125.    diagramm(art,wahl,(long)x,(long)y,n,'d',xw,yw,ww,hw);
  126.  
  127.    Bconin(2);
  128. }
  129.  
  130. int prog_init(void)
  131.  
  132. {  int i;
  133.  
  134.    ap_id = appl_init();
  135.    if (ap_id == -1) return(3);
  136.  
  137.    for(i=0;i<10;work_in[i++]=1); work_in[10] = 2;
  138.    gem_handle = graf_handle(&dummy,&dummy,&dummy,&dummy);
  139.    handle = gem_handle;
  140.    v_opnvwk(work_in,&handle,work_out);
  141.    if (handle == FALSE) return(2);
  142.    return(1);
  143. }
  144.  
  145. void prog_exit(int art)
  146.  
  147. {
  148.    switch(art)
  149.    {
  150.       case 1       : v_clsvwk(handle);
  151.       case 2       : appl_exit();
  152.       case 3       : break;
  153.    }
  154. }
  155.  
  156. /**************************************************************** 
  157. *                                                               *
  158. *   Universelle Diagrammroutine für beliebige Bildschirmmaße    *
  159. *                                                               *
  160. *   Version 1.2 vom 16.11.1989 geschrieben von DITTELSOFT       *
  161. *                                                               *
  162. *   Autor: Georg Ditti, Salierallee 37, 5100 Aachen            *
  163. *          Tel.: 0241 / 80 53 90 tags, 0241 / 60 24 87 privat   *
  164. *                                                               *
  165. *   art = 0 : lineare Darstellung          (int)                *
  166. *   art = 1 : y-logarithmische Darstellung                      *
  167. *   art = 2 : x-logarithmische Darstellung                      *
  168. *   art = 3 : doppelt logarythmische Darstellung                *
  169. *   art = 4 : Polardiagramm                                     *
  170. *   art = 5 : diabatische Darstellung                           *
  171. *   art = 6 : diabatisch-logarithmische Darstellung             *
  172. *   art = 7 : komplexe Ebene                                    *
  173. *   art = 8 : Darstellung komplexer Zahlen im Polardiagramm     *
  174. *                                                               *
  175. *   malen, Bit 0  : Raster(selbstskalierend)   (MALFLAGS)       *
  176. *   malen, Bit 1  : neues Diagramm über altes zeichnen          *
  177. *   malen, Bit 2  : Extrema markieren                           *
  178. *   malen, Bit 3  : Nullinien erzwingen                         *
  179. *   malen, Bit 4  : keine Achsenmarkierungen                    *
  180. *   malen, Bit 5  : keine Verbindungslinien                     *
  181. *   malen, Bit 6,Bit 7 und Bit 8: Alle Punkte markieren         *
  182. *   malen, Bit 9  : Maximum auf 1 normieren                     *
  183. *   malen, Bit 10 : Y-Werte werden numeriert (ohne X-Werte)     *
  184. *   malbits 6,7,8 : 0 => keine Punktmarkierung                  *
  185. *               1 => gerade Kreuzchen                           *
  186. *               2 => schräge Kreuzchen                          *
  187. *               3 => Quadrate                                   *
  188. *               4 => Rauten                                     *
  189. *               5 => Dreiecke nach oben                         *
  190. *               6 => Dreiecke nach unten                        *
  191. *                                                               *
  192. *   xwerte ist Zeiger auf Feld mit X-Werten                     *
  193. *                     oder Anfang des COMPLEX-Arrays            *
  194. *   ywerte ist Zeiger auf Feld mit Y-werten                     *
  195. *                                                               *
  196. *   n ist die Anzahl der darzustellenden Werte  (long)          *
  197. *                                                               *
  198. *   typ (char) gibt datentyp an                                 *
  199. *               'c' => char                                     *
  200. *               'u' => unsigned char                            *
  201. *               's,i' => short und int                          *
  202. *               'l' => long                                     *
  203. *               'f' => float                                    *
  204. *               'd' => double                                   *
  205. *               'x' => COMPLEX                                  *
  206. *                                                               *
  207. *   (geht auch mit Zeiger auf void, gibt's aber nicht in        *
  208. *    jedem C-Dialekt, erst recht nicht in anderen Sprachen)     *
  209. *                                                               *
  210. *   x,y,w,h sind die Maße des auszumalenden Fensters  (int)     *
  211. *   (x,y = Position der oberen, linken Ecke in Pixeln           *                    *
  212. *    w,h = Breite und Höhe des Zeichenbereichs in Pixel)        *
  213. *                                                               *
  214. ****************************************************************/
  215.  
  216. int diagramm(int art, MALFLAGS malen, long xwerte, long ywerte,
  217.              long n, char typ, int x, int y, int w, int h)
  218. {
  219.   /* Allgemeine Betriebsvariablen */
  220.  
  221.   long i,s,ptrx,ptry;
  222.   int pxy[10],mxy[10];
  223.   double xmin,xmax,ymin,ymax,maxpos,minpos,xw,yw,xh,yh,nymax;
  224.   double initxstepsum,initystepsum,initxstep,initystep,
  225.          initxstepmk,initystepmk;
  226.  
  227.   /* Erklärung der einzelnen Variablen :
  228.  
  229.     long i,s   = Zählvariablen
  230.     long ptrx,ptry = Pointer auf die X- bzw. Y-Werte der Tabelle
  231.     int pxy[10],mxy[10] = Felder, die Anfangs- und Endkoordinaten
  232.                           zum Zeichnen enthalten (m wie merk)
  233.     int flag = Allgemeine Flagvariable, öfters gebraucht
  234.     double xmin,xmax     = Minimum und Maximum der X-Werte
  235.     double ymin,ymax     = Minimum und Maximum der Y-Werte
  236.     double maxpos,minpos = Position der Extrema auf der X-Achse
  237.     double xw,yw,xh,yh   = Zwischenergebnisse
  238.     double nymax         = Maximum der Funktionswerte
  239.     double initxstepsum,initystepsum = Anfang der Skalierung
  240.     double initxstep,initystep = anfängliche Skalierungsweite 
  241.     double initxstepmk,initystepmk = anfängliche Markierungsweite
  242.   */
  243.  
  244.   /* Statische Fenster- und Maßstabsparameter für mehrere Kurven */
  245.  
  246.   static double xskamin,xskamax,xpixfak,ypixfak,yskamin,yskamax;
  247.   static double xstepsum,ystepsum,xstep,ystep,xstepmk,ystepmk;
  248.   static int xpixoff,ypixoff,ix0,iy0,ixmin,iymin,ixmax,iymax;
  249.  
  250.   /* Erklärung der einzelnen Variablen :
  251.     static double xskamin,xskamax = Skalenextrema > Extrema !
  252.     static double xpixfak,ypixfak = Pixel pro Skaleneinheit
  253.     static double yskamin,yskamax = siehe oben
  254.     static double xstepsum,ystepsum = aktueller Skalenmarker
  255.     static double xstep,ystep       = aktuelle Schrittweite
  256.     static double xstepmk,ystepmk   = aktuelle Schriftweite
  257.     static int xpixoff,ypixoff    = Zeichenoffset in Pixeln
  258.     static int ix0,iy0,ixmin,iymin,ixmax,iymax = Hilfsvariablen
  259.   */
  260.  
  261.   /*  Pointer initialisieren  */
  262.  
  263.   ptrx = xwerte; ptry = ywerte; if(malen.zahlen==1) ptrx = ptry;
  264.   
  265.   /* Maximal 1000 Punkte zeichnen, sonst sieht man nix mehr */
  266.  
  267.   s = 1; while((n/s)>1000L) s*=2;   
  268.  
  269.   switch(typ)
  270.   {
  271.   case 'c':
  272.     xmin = (double)*((char*)ptrx);
  273.     ymin = (double)*((char*)ptry); break; 
  274.   case 'u':
  275.     xmin = (double)*((unsigned char*)ptrx); 
  276.     ymin = (double)*((unsigned char*)ptry); break; 
  277.   case 's': case 'i':
  278.     xmin = (double)*((int*)ptrx); 
  279.     ymin = (double)*((int*)ptry); break; 
  280.   case 'l':
  281.     xmin = (double)*((long*)ptrx); 
  282.     ymin = (double)*((long*)ptry); break; 
  283.   case 'f':
  284.     xmin = (double)*((float*)ptrx); 
  285.     ymin = (double)*((float*)ptry); break; 
  286.   case 'd':
  287.     xmin = *((double*)ptrx); 
  288.     ymin = *((double*)ptry); break;
  289.   case 'x':
  290.     xmin = ((COMPLEX*)ptrx)->real; 
  291.     ymin = ((COMPLEX*)ptrx)->imag; break;
  292.   }
  293.   if(malen.zahlen==1) xmin=0.;
  294.   xmax = xmin; ymax = ymin;
  295.   maxpos = xmin; minpos = xmin;
  296.  
  297.   /*  Rasterlinien werden aus Folgen von 3 weißen Punkten 
  298.       und 1 schwarzem Punkt gezeichnet */
  299.  
  300.   vsl_udsty(handle,0x8888);
  301.  
  302.   /*  Extrema finden */
  303.  
  304.   for(i=1;i<n;i+=s)    
  305.   { switch(typ)
  306.     {
  307.     case 'c':
  308.       xw = (double)*((char*)ptrx+i); 
  309.       yw = (double)*((char*)ptry+i); break; 
  310.     case 'u':
  311.       xw = (double)*((unsigned char*)ptrx+i); 
  312.       yw = (double)*((unsigned char*)ptry+i); break; 
  313.     case 's': case 'i':
  314.       xw = (double)*((int*)ptrx+i); 
  315.       yw = (double)*((int*)ptry+i); break; 
  316.     case 'l':
  317.       xw = (double)*((long*)ptrx+i); 
  318.       yw = (double)*((long*)ptry+i); break; 
  319.     case 'f':
  320.       xw = (double)*((float*)ptrx+i); 
  321.       yw = (double)*((float*)ptry+i); break; 
  322.     case 'd':
  323.       xw = *((double*)ptrx+i); 
  324.       yw = *((double*)ptry+i); break; 
  325.     case 'x':
  326.       xw = ((COMPLEX*)ptrx+i)->real; 
  327.       yw = ((COMPLEX*)ptrx+i)->imag; break;
  328.     }
  329.     if(malen.zahlen==1) xw = (double)i;
  330.     if(art==8)
  331.     { xh = atan2(xw,yw); 
  332.       yh = sqrt(xw*xw+yw*yw);
  333.       xw = xh; yw = yh;
  334.     }
  335.     if(xmin>=xw) {xmin=xw;}
  336.     if(xw>=xmax) {xmax=xw;}
  337.     if(ymin>=yw) {ymin=yw; minpos=xw;}
  338.     if(yw>=ymax) {ymax=yw; maxpos=xw;}
  339.   }
  340.  
  341.   if(malen.normen==1)
  342.   { nymax = ymax; ymin /= nymax; ymax = 1.;}
  343.  
  344.   /*  Diagrammparameter nur erstes mal bestimmen  */
  345.  
  346.   if(malen.transp==0)
  347.   {
  348.     /* Wertebereichsprüfung, Skalierungsfaktor, 
  349.     Fensternullpunkt zum Zeichnen */
  350.  
  351.     /* Zuerst in X-Richtung */
  352.  
  353.     xpixfak = (double)(w-60); 
  354.     ypixfak = (double)(h-25);
  355.  
  356.     switch(art)
  357.     {
  358.     case 2: case 3: case 6:
  359.     { if(malen.nullin&&xmin>=1.)
  360.         xmin = 1.;
  361.       if(malen.nullin&&xmax<=1.) 
  362.         xmax = 1.;
  363.       if(0.>=xmin)
  364.         return(FAILURE);
  365.       xskamin = xmin*.8; xskamax = xmax*1.1;
  366.       xpixfak /= (log10(xskamax)-log10(xskamin));
  367.       xpixoff = x+60-(int)(log10(xskamin)*xpixfak);
  368.       initxstepsum = 1.; initxstep = .1; initxstepmk = .5;
  369.       if(xpixfak*initxstep>=100.)
  370.         {initxstep = .02; initxstepmk = .1;}
  371.       else if(xpixfak*initxstep<2.)
  372.         {initxstep = .9; initxstepmk = 1.;}
  373.       else if(xpixfak*initxstep<10.)
  374.         {initxstep =.3; initxstepmk=1.;}
  375.     } break;
  376.     case 4: case 8:
  377.       break;
  378.     default: 
  379.     { if(malen.nullin&&xmin>=0.) xskamin = 0.;
  380.       if(malen.nullin&&xmax<=0.) xskamax = 0.;
  381.       xskamin = xmin-.05*fabs(xmax-xmin);
  382.       xskamax = xmax+.05*fabs(xmax-xmin);
  383.       xpixfak /= (xskamax-xskamin);
  384.       xpixoff = x+60-(int)(xskamin*xpixfak);
  385.       initxstepsum = 0.; initxstep = 1.; initxstepmk = 5.;
  386.       while(xpixfak*initxstep>=100.)
  387.         {initxstep /= 10.; initxstepmk /= 10.;}
  388.       while(xpixfak*initxstep<10.)
  389.         {initxstep *= 10.; initxstepmk *= 10.;}
  390.       if(xpixfak*initxstep>=50.)
  391.         {initxstep /= 5.; initxstepmk /= 5.;}
  392.       else if(xpixfak*initxstep>=20.)
  393.         {initxstep /= 2.; initxstepmk /= 2.;}
  394.     } break;
  395.     }
  396.  
  397.     /* Dann in Y-Richtung */
  398.  
  399.     switch(art)
  400.     {
  401.     case 1: case 3: 
  402.     { if(malen.nullin&&ymin>=1.) ymin = 1.;
  403.       if(malen.nullin&&ymax<=1.) ymax = 1.;
  404.       if(0.>=ymin) return(FAILURE);
  405.       yskamin = ymin*.9; yskamax = ymax*1.1;
  406.       ypixfak /= (log10(yskamax)-log10(yskamin));
  407.       ypixoff = y+h-25+(int)(log10(yskamin)*ypixfak);
  408.       initystepsum = 1.; initystep = .1; initystepmk = .5;
  409.       if(ypixfak*initystep>=100.)
  410.         {initystep = .02; initystepmk = .1;}
  411.       else if(ypixfak*initystep<2.)
  412.         {initystep = .9; initystepmk = 1.;}
  413.       else if(ypixfak*initystep<10.)
  414.         {initystep = .3; initystepmk = 1.;}
  415.     } break;
  416.     case 5: case 6:
  417.     { if(0.>ymin||0.>ymax||ymin>1.||ymax>1.) return(FAILURE);
  418.       yskamin = 1e-9; yskamax = 1.-(1.-ymax)/2.;
  419.       if(yskamax>=1.-1e-10) yskamax=1.-1e-10;
  420.       ypixfak /= (diabat(yskamax)-diabat(yskamin));
  421.       ypixoff = y+h-25+(int)(diabat(1e-9)*ypixfak);
  422.       initystepsum = .5; initystep = .1; initystepmk = .5;
  423.     } break;
  424.     case 4: case 8:
  425.     { yskamax = fabs(ymax)*1.05; yskamin = -yskamax;
  426.       xskamax = yskamax;   xskamin = -xskamax;
  427.       ypixfak /= (yskamax*2.); xpixfak /= (xskamax*2.);
  428.       if(w<h) ypixfak = xpixfak; else xpixfak = ypixfak;
  429.       ypixoff = y+h/2; xpixoff = x+w/2;
  430.       initystepsum = 0.; initystep = .2; initystepmk = 1.;
  431.       while(ypixfak*initystep>=100.)
  432.         {initystep /= 10.; initystepmk /= 10.;}
  433.       while(ypixfak*initystep<10.)
  434.         {initystep *= 10.; initystepmk *= 10.;}
  435.       if(ypixfak*initystep>=50.)
  436.         {initystep /= 5.; initystepmk /= 5.;}
  437.       if(ypixfak*initystep>=20.)
  438.         {initystep /= 2.; initystepmk /= 2.;}
  439.     } break;
  440.     default: 
  441.     { if(malen.nullin&&ymin>=0.) ymin = 0.;
  442.       if(malen.nullin&&ymax<=0.) ymax = 0.;
  443.       yskamin = ymin-.05*fabs(ymax-ymin);
  444.       yskamax = ymax+.05*fabs(ymax-ymin);
  445.       ypixfak /= (yskamax-yskamin);
  446.       ypixoff = y+h-25+(int)(yskamin*ypixfak);
  447.       initystepsum = 0.; initystep = 1.; initystepmk = 5.;
  448.       while(ypixfak*initystep>=100.)
  449.         {initystep /= 10.; initystepmk /= 10.;}
  450.       while(ypixfak*initystep<10.)
  451.         {initystep *= 10.; initystepmk *= 10.;}
  452.       if(ypixfak*initystep>=50.)
  453.         {initystep /= 5.; initystepmk /= 5.;}
  454.       else if(ypixfak*initystep>=20.)
  455.         {initystep /= 2.; initystepmk /= 2.;}
  456.     } break;
  457.     }
  458.  
  459.     /*  Diverse Einstellungen des GEM-VDI von Digital Research  */
  460.  
  461.     vsl_color(handle,1);    /* Linien schwarz auf weißem Grund */
  462.     vswr_mode(handle,2);    /* Durchsichtige Buchstaben */
  463.     vsf_interior(handle,2); /* Alle Figuren durchsichtig */
  464.     vsf_style(handle,4);
  465.  
  466.     /*  Zeichnen der X-Achse  */
  467.  
  468.     pxy[0] = x;
  469.     pxy[1] = ypixoff; 
  470.     if(y+12>ypixoff||ypixoff>y+h-25) 
  471.     { switch(art)
  472.       {
  473.       case 1: case 3:
  474.         pxy[1] = ypixoff-(int)(log10(yskamin)*ypixfak); break;
  475.       default: 
  476.         pxy[1] = ypixoff-(int)(yskamin*ypixfak); break;
  477.       }
  478.     }
  479.     pxy[2] = x+w;
  480.     pxy[3] = pxy[1];
  481.     ix0 = pxy[1]; ixmin = x; ixmax = x+w;
  482.     v_pline(handle,2,pxy);                
  483.  
  484.     /*  Zeichnen der Y-Achse  */
  485.  
  486.     pxy[0] = xpixoff; 
  487.     if(x>xpixoff+60||xpixoff>x+w-5)
  488.     { switch(art)
  489.       {
  490.       case 2: case 3: case 6:
  491.         pxy[0] = xpixoff+(int)(log10(xskamin)*xpixfak); break;
  492.       default: 
  493.         pxy[0] = xpixoff+(int)(xskamin*xpixfak); break;
  494.       }
  495.     }
  496.     pxy[1] = y; 
  497.     pxy[2] = pxy[0];
  498.     pxy[3] = y+h;
  499.     iy0 = pxy[0]; iymin = y; iymax = y+h;
  500.     v_pline(handle,2,pxy);
  501.  
  502.     /* Zeichnen der X-Achsenmarkierer 
  503.     von einem 'runden' Startpunkt aus */
  504.  
  505.     switch(art)
  506.     {
  507.     case 2: case 3: case 6:      /*  Logarythmische Skalierung  */
  508.     { xstepsum = initxstepsum; 
  509.       xstep = initxstep; 
  510.       xstepmk = initxstepmk;
  511.       while(xskamax>=xstepsum)
  512.       { marker_malen(ix0,ixmin,ixmax,iymin,iymax,xpixoff,xpixfak,
  513.                      &xstep,&xstepsum,&xstepmk,'x',malen,2);
  514.       }
  515.       xstepsum = initxstepsum; 
  516.       xstep = initxstep; 
  517.       xstepmk = initxstepmk;
  518.       while(xstepsum>=xskamin)
  519.       { marker_malen(ix0,ixmin,ixmax,iymin,iymax,xpixoff,xpixfak,
  520.                      &xstep,&xstepsum,&xstepmk,'x',malen,-2);
  521.       }                                                        
  522.     } break;
  523.     case 4: case 8:
  524.       break;
  525.     default:           /*  Lineare Skalierung  */
  526.     { xstepsum = initxstepsum; 
  527.       xstep = initxstep; 
  528.       xstepmk = initxstepmk;
  529.       while(xskamax>=xstepsum)
  530.       { marker_malen(ix0,ixmin,ixmax,iymin,iymax,xpixoff,xpixfak,
  531.         &xstep,&xstepsum,&xstepmk,'x',malen,1);
  532.       }
  533.       xstepsum = initxstepsum; 
  534.       xstep = initxstep; 
  535.       xstepmk = initxstepmk;
  536.       while(xstepsum>=xskamin)
  537.       { marker_malen(ix0,ixmin,ixmax,iymin,iymax,xpixoff,xpixfak,
  538.                      &xstep,&xstepsum,&xstepmk,'x',malen,-1);
  539.       }
  540.     } break;
  541.     } /* end of switch */
  542.  
  543.     /* Zeichnen der Y-Achsenmarkierer von 
  544.     einem definierten Startpunkt aus */
  545.  
  546.     switch(art)
  547.     {
  548.     case 1: case 3:      /*  Logarythmische Skalierung  */
  549.     { ystepsum = initystepsum; 
  550.       ystep = initystep; 
  551.       ystepmk = initystepmk;
  552.       while(yskamax>=ystepsum)
  553.       { marker_malen(iy0,ixmin,ixmax,iymin,iymax,ypixoff,ypixfak,
  554.                      &ystep,&ystepsum,&ystepmk,'y',malen,2);
  555.       }
  556.       ystepsum = initystepsum; 
  557.       ystep = initystep; 
  558.       ystepmk = initystepmk;
  559.       while(ystepsum>=yskamin)
  560.       { marker_malen(iy0,ixmin,ixmax,iymin,iymax,ypixoff,ypixfak,
  561.                      &ystep,&ystepsum,&ystepmk,'y',malen,-2);
  562.       }
  563.     } break;
  564.     case 4: case 8:     /*  Polare Skalierung  */
  565.     { ystepsum = initystepsum;
  566.       ystep = initystep;
  567.       ystepmk = initystepmk;
  568.       while(yskamax>=ystepsum+ystep)
  569.       { polmarker_malen(xpixoff,ypixoff,ypixfak,&ystep,&ystepsum,
  570.                         &ystepmk,malen);
  571.       }
  572.     } break;
  573.     case 5: case 6:     /*  Diabatische Skalierung  */
  574.     { ystepsum = initystepsum;
  575.       ystep = initystep;
  576.       ystepmk = initystepmk;
  577.       while(yskamax>=ystepsum)
  578.       { marker_malen(iy0,ixmin,ixmax,iymin,iymax,ypixoff,ypixfak,
  579.                      &ystep,&ystepsum,&ystepmk,'y',malen,3);
  580.       }
  581.       ystepsum = initystepsum;
  582.       ystep = initystep;
  583.       ystepmk = initystepmk;
  584.       while(ystepsum>=yskamin)
  585.       { marker_malen(iy0,ixmin,ixmax,iymin,iymax,ypixoff,ypixfak,
  586.                      &ystep,&ystepsum,&ystepmk,'y',malen,-3);
  587.       }
  588.     } break;
  589.     default :         /*  Lineare Skalierung  */
  590.     { ystepsum = initystepsum;
  591.       ystep = initystep;
  592.       ystepmk = initystepmk;
  593.       while(yskamax>=ystepsum)
  594.       { marker_malen(iy0,ixmin,ixmax,iymin,iymax,ypixoff,ypixfak,
  595.                      &ystep,&ystepsum,&ystepmk,'y',malen,1);
  596.       }
  597.       ystepsum = initystepsum;
  598.       ystep = initystep;
  599.       ystepmk = initystepmk;
  600.       while(ystepsum>=yskamin)
  601.       { marker_malen(iy0,ixmin,ixmax,iymin,iymax,ypixoff,ypixfak,
  602.                      &ystep,&ystepsum,&ystepmk,'y',malen,-1);
  603.       }
  604.     } break;
  605.     } /* end of switch */
  606.   } /* end of 'neumalen'-if */
  607.  
  608.   /* Ab hier wird das Wertefeld in das Diagramm eingezeichnet */
  609.  
  610.   for(i=0;i<n;i+=s)
  611.   { switch(typ)
  612.     {
  613.     case 'c':
  614.       xw = (double)*((char*)ptrx+i);
  615.       yw = (double)*((char*)ptry+i); break; 
  616.     case 'u':
  617.       xw = (double)*((unsigned char*)ptrx+i);
  618.       yw = (double)*((unsigned char*)ptry+i); break; 
  619.     case 's': case 'i':
  620.       xw = (double)*((int*)ptrx+i);
  621.       yw = (double)*((int*)ptry+i); break; 
  622.     case 'l':
  623.       xw = (double)*((long*)ptrx+i);
  624.       yw = (double)*((long*)ptry+i); break; 
  625.     case 'f':
  626.       xw = (double)*((float*)ptrx+i);
  627.       yw = (double)*((float*)ptry+i); break; 
  628.     case 'd':
  629.       xw = *((double*)ptrx+i);
  630.       yw = *((double*)ptry+i); break; 
  631.     case 'x':
  632.       xw = ((COMPLEX*)ptrx+i)->real;
  633.       yw = ((COMPLEX*)ptrx+i)->imag; break;
  634.     }
  635.     if(malen.zahlen==1) xw = (double)i;
  636.     if(art==8)
  637.     { xh = atan2(xw,yw); 
  638.       yh = sqrt(xw*xw+yw*yw);
  639.       xw = xh; yw = yh;
  640.     }
  641.  
  642.     if(malen.normen==1) yw /= nymax;
  643.  
  644.     switch(art)
  645.     {                                  
  646.     case 2: case 3: case 6:
  647.       pxy[2] = xpixoff+(int)(xpixfak*log10(xw)); break;
  648.     case 4: case 8:
  649.       pxy[2] = xpixoff+(int)(xpixfak*(cos(xw)*yw)); break;
  650.     default: 
  651.       pxy[2] = xpixoff+(int)(xpixfak*xw); break;
  652.     }
  653.     switch(art)
  654.     {
  655.     case 1: case 3:
  656.       pxy[3] = ypixoff-(int)(ypixfak*log10(yw)); break;
  657.     case 4: case 8:
  658.       pxy[3] = ypixoff-(int)(ypixfak*(sin(xw)*yw)); break;
  659.     case 5: case 6:
  660.       pxy[3] = ypixoff-(int)(ypixfak*diabat(yw)); break;
  661.     default: 
  662.       pxy[3] = ypixoff-(int)(ypixfak*yw); break;
  663.     }
  664.  
  665.     /* Verbindungslinien ziehen */
  666.  
  667.     if(i>0&&malen.verlin==0) v_pline(handle,2,pxy);
  668.  
  669.     /* großes Kreuz bei den Extrema */
  670.  
  671.     if(malen.extrem==1&&(xw==minpos||xw==maxpos))
  672.     { mxy[0]=pxy[2]-20; mxy[1]=pxy[3];
  673.       mxy[2]=pxy[2]+20; mxy[3]=pxy[3]; v_pline(handle,2,mxy);
  674.       mxy[0]=pxy[2]; mxy[1]=pxy[3]-20;
  675.       mxy[2]=pxy[2]; mxy[3]=pxy[3]+20; v_pline(handle,2,mxy);
  676.     }
  677.  
  678.     switch(malen.marker)
  679.     {
  680.     case 1: /* gerade Kreuzchen */
  681.     { mxy[0]=pxy[2]-3; mxy[1]=pxy[3]; 
  682.       mxy[2]=pxy[2]+3; mxy[3]=pxy[3]; v_pline(handle,2,mxy);
  683.       mxy[0]=pxy[2]; mxy[1]=pxy[3]-3; 
  684.       mxy[2]=pxy[2]; mxy[3]=pxy[3]+3; v_pline(handle,2,mxy);
  685.     } break;
  686.     case 2: /* schräge Kreuzchen */
  687.     { mxy[0]=pxy[2]-3; mxy[1]=pxy[3]-3; 
  688.       mxy[2]=pxy[2]+3; mxy[3]=pxy[3]+3; v_pline(handle,2,mxy);
  689.       mxy[0]=pxy[2]+3; mxy[1]=pxy[3]-3; 
  690.       mxy[2]=pxy[2]-3; mxy[3]=pxy[3]+3; v_pline(handle,2,mxy);
  691.     } break;
  692.     case 3: /* Kästchen */
  693.     { mxy[0]=pxy[2]-3; mxy[1]=pxy[3]-3; 
  694.       mxy[2]=pxy[2]+3; mxy[3]=pxy[3]-3; 
  695.       mxy[4]=pxy[2]+3; mxy[5]=pxy[3]+3; 
  696.       mxy[6]=pxy[2]-3; mxy[7]=pxy[3]+3;
  697.       mxy[8]=pxy[2]-3; mxy[9]=pxy[3]-3; v_pline(handle,5,mxy);
  698.     } break;
  699.     case 4: /* Rauten */
  700.     { mxy[0]=pxy[2]-3; mxy[1]=pxy[3]; 
  701.       mxy[2]=pxy[2]; mxy[3]=pxy[3]-3; 
  702.       mxy[4]=pxy[2]+3; mxy[5]=pxy[3]; 
  703.       mxy[6]=pxy[2]; mxy[7]=pxy[3]+3;
  704.       mxy[8]=pxy[2]-3; mxy[9]=pxy[3]; v_pline(handle,5,mxy);
  705.     } break;
  706.     case 5: /* Dreieck oben */
  707.     { mxy[0]=pxy[2]-3; mxy[1]=pxy[3]-2; 
  708.       mxy[2]=pxy[2]; mxy[3]=pxy[3]+3; 
  709.       mxy[4]=pxy[2]+3; mxy[5]=pxy[3]-2; 
  710.       mxy[6]=pxy[2]-3; mxy[7]=pxy[3]-2; v_pline(handle,4,mxy);
  711.     } break;
  712.     case 6: /* Dreieck unten */
  713.     { mxy[0]=pxy[2]-3; mxy[1]=pxy[3]+2; 
  714.       mxy[2]=pxy[2]; mxy[3]=pxy[3]-3; 
  715.       mxy[4]=pxy[2]+3; mxy[5]=pxy[3]+2; 
  716.       mxy[6]=pxy[2]-3; mxy[7]=pxy[3]+2; v_pline(handle,4,mxy);
  717.     } break;
  718.     }
  719.     pxy[0] = pxy[2]; pxy[1] = pxy[3];
  720.   }
  721.   return(SUCCESS);
  722. }
  723.  
  724. /* marker_malen zeichnet und beschriftet die Skalenachsen,
  725.    wird für jeden einzelnen Schritt neu aufgerufen,
  726.    schaltet bei nichtlinearen Diagrammen Schrittweite um
  727.    
  728.    ACHTUNG : Benutzer des Turbo C 1.1 müssen das Ausgabeformat
  729.    für Beschriftung im Exponentiellen Modus vergrößern, da der
  730.    neue Compiler den Exponenten dummerweise immer mit 4 Stellen
  731.    ausgibt.
  732. */
  733.  
  734. void marker_malen(int b, int xmin, int xmax, int ymin, int ymax,
  735.             int pixoff, double pixfak, double *step,
  736.             double *stepsum, double *stepmk,
  737.             char dir, MALFLAGS malen, int flag)
  738.  
  739. { int pxy[4],toff,dummy; double absstepsum; char mk[20];
  740.   char mark[9];
  741.  
  742.   vst_height(handle,6,&dummy,&dummy,&dummy,&dummy);
  743.   absstepsum = fabs(*stepsum);
  744.  
  745.   if(dir=='x') /* X-Achse markieren */
  746.   { switch(flag)
  747.     {
  748.     case 2: case -2:
  749.       pxy[0] = pixoff+(int)(pixfak*log10(*stepsum)); break;
  750.     default:
  751.       pxy[0] = pixoff+(int)(pixfak*(*stepsum)); break;
  752.     }
  753.  
  754.     pxy[2] = pxy[0];
  755.  
  756.     if(.1>frac(absstepsum/(*stepmk)+.001))    
  757.     { pxy[1] = b; pxy[3] = b+8;
  758.       strcpy(mark,"     ");
  759.       if(absstepsum==0.||absstepsum<100000.&&absstepsum>=.001)
  760.       { sprintf(mk,"%04.3lf\0",(*stepsum)); toff = 16;
  761.         strncpy(mark,mk,5);
  762.       }
  763.       else
  764.       { sprintf(mk,"%2.1e\0",(*stepsum));
  765.         strncpy(mark,mk,8); toff=34;}
  766.     /*  strncpy(mark,mk,9); toff=34;}  f. Turbo C 1.1 */
  767.         if(malen.achsen==0)
  768.         v_gtext(handle,(pxy[2]-toff),(pxy[3]+9),mark);
  769.     }
  770.     else
  771.     { pxy[1] = b; pxy[3] = b+4;}
  772.  
  773.     if(pxy[0]>xmin&&xmax>pxy[0])
  774.     { if(malen.achsen==0) 
  775.       { v_pline(handle,2,pxy);}
  776.       if(malen.raster==1)
  777.       { vsl_type(handle,7);
  778.         pxy[1] = ymin; pxy[3] = ymax; v_pline(handle,2,pxy);
  779.         vsl_type(handle,1);
  780.       }
  781.     }
  782.   }
  783.  
  784.   else if(dir=='y') /* Y-Achse markieren */
  785.   { switch(flag)
  786.     {
  787.     case 2: case -2:
  788.       pxy[1] = pixoff-(int)(pixfak*log10(*stepsum)); break;
  789.     case 3: case -3:
  790.       pxy[1] = pixoff-(int)(pixfak*diabat(*stepsum)); break;
  791.     default:
  792.       pxy[1] = pixoff-(int)(pixfak*(*stepsum)); break;
  793.     }
  794.  
  795.     pxy[3] = pxy[1];
  796.  
  797.     if(.1>frac(absstepsum/(*stepmk)+.001))
  798.     { pxy[0] = b; pxy[2] = b-8;
  799.       strcpy(mark,"     ");
  800.       if(absstepsum==0.||absstepsum<100000.&&absstepsum>=.001)
  801.       { sprintf(mk,"%04.3lf\0",(*stepsum)); toff = 42;
  802.         strncpy(mark,mk,5);
  803.       }
  804.       else
  805.       { sprintf(mk,"%2.1e\0",(*stepsum));
  806.         strncpy(mark,mk,8); toff=66;} 
  807.      /* strncpy(mark,mk,9); toff=66;}  f. Turbo C 1.1 */  
  808.       if(malen.achsen==0)
  809.         v_gtext(handle,pxy[2]-toff,pxy[3]+3,mark);
  810.     }
  811.     else
  812.     { pxy[0] = b; pxy[2] = b-4;}
  813.  
  814.     if(pxy[1]>ymin&&ymax>pxy[1])
  815.     { if(malen.achsen==0) 
  816.       { v_pline(handle,2,pxy);}
  817.       if(malen.raster==1)
  818.       { vsl_type(handle,7);
  819.         pxy[0] = xmin; pxy[2] = xmax; v_pline(handle,2,pxy);
  820.         vsl_type(handle,1);
  821.       }
  822.     }
  823.   }
  824.   vst_height(handle,13,&dummy,&dummy,&dummy,&dummy);
  825.  
  826.   switch(flag) /* Schrittweite neu einstellen */
  827.   {
  828.   case  1:     /* linear ab 0 aufwärts */
  829.     *stepsum += *step; break;
  830.   case -1:     /* linear ab 0 abwärts */ 
  831.     *stepsum -= *step; break;
  832.   case  2:     /* logarithmisch ab 1 aufwärts */ 
  833.   { if(.01>=fabs(frac(log10(*stepsum)+.001)))
  834.     { *step *= 10.; *stepmk *= 10.;}
  835.     *stepsum += *step;
  836.   } break;
  837.   case -2:     /* logarithmisch ab 1 abwärts */ 
  838.   { *stepsum -= *step;
  839.     if(.01>=fabs(frac(log10(*stepsum)-.001)))
  840.     { *step /= 10.; *stepmk /= 10.;}
  841.     } break;
  842.   case  3:     /* diabatisch ab 0.5 aufwärts */ 
  843.   { *stepsum += *step;
  844.     if(.01>=frac(fabs(log10(1.-*stepsum))+.001))
  845.     { *step /= 10.; *stepmk /= 10.;}
  846.   } break;
  847.   case -3:     /* diabatisch ab 0.5 abwärts */
  848.   { *stepsum -= *step;
  849.     if((*stepsum)<.1999&&(*stepsum)>.9e-3)
  850.     { *stepmk /= 10.; *step = (*stepsum)*.9;}
  851.     if((*stepsum)<.9e-3)
  852.     { *stepmk /= 100.; *step = (*stepsum)*.99;}
  853.   } break;
  854.   }
  855. }
  856.  
  857. /* polmarker_malen zeichnet und beschriftet die
  858.    Skalenmarkierungen für das Polardiagramm,
  859.    wird für jeden einzelnen Schritt neu aufgerufen
  860. */
  861.  
  862. void polmarker_malen(int xpixoff, int ypixoff, 
  863.               double pixfak, double *step, double *stepsum,
  864.               double *stepmk, MALFLAGS malen)
  865.  
  866. { int pxy[6],i,h1,h2,dummy; double w; char mk[20]; char mark[7];
  867.  
  868.   *stepsum += *step;
  869.   vst_height(handle,6,&dummy,&dummy,&dummy,&dummy);
  870.  
  871.   pxy[0] = xpixoff+(int)(*stepsum*pixfak); pxy[2] = pxy[0];
  872.   if(.1>frac((*stepsum)/(*stepmk)+.001))
  873.   { pxy[1] = ypixoff-6; pxy[3] = ypixoff+6;
  874.     h1 = xpixoff-6; h2 = xpixoff+6;
  875.     strcpy(mark,"     ");
  876.     if((*stepsum)==0.||(*stepsum)<10000.&&(*stepsum)>.001)
  877.     { sprintf(mk,"%04.3lf\0",(*stepsum)); 
  878.       if(mk[4]!='0') strncpy(mark,mk,5); else strncpy(mark,mk,4);
  879.     }
  880.     else
  881.     { sprintf(mk,"%2.1e\0",(*stepsum)); strncpy(mark,mk,6);}
  882.     if(malen.achsen==0)v_gtext(handle,pxy[2]-12,pxy[3]+9,mark);
  883.   }
  884.   else
  885.   { pxy[1] = ypixoff-3; pxy[3] = ypixoff+3;
  886.     h1 = xpixoff-3; h2 = xpixoff+3;
  887.   }
  888.   if(malen.achsen==0)
  889.   { v_pline(handle,2,pxy);
  890.     pxy[0] = xpixoff-(int)(*stepsum*pixfak); pxy[2] = pxy[0];
  891.     v_pline(handle,2,pxy);
  892.     pxy[0] = h1; pxy[2] = h2;
  893.     pxy[1] = ypixoff-(int)(*stepsum*pixfak); pxy[3] = pxy[1];
  894.     v_pline(handle,2,pxy);
  895.     pxy[1] = ypixoff+(int)(*stepsum*pixfak); pxy[3] = pxy[1];
  896.     v_pline(handle,2,pxy);
  897.   }
  898.  
  899.   if(malen.raster)
  900.   { vsl_type(handle,7);
  901.     for(w=0.,i=0;i<=36;w+=PI/18.,i++)
  902.     { pxy[2] = xpixoff+(int)(pixfak*(*stepsum*cos(w)));
  903.       pxy[3] = ypixoff+(int)(pixfak*(*stepsum*sin(w)));
  904.       if(i!=0) v_pline(handle,2,pxy);
  905.       pxy[0] = pxy[2]; pxy[1] = pxy[3];
  906.       if(i%3==0&&*stepsum>*step)
  907.       { pxy[4] = xpixoff+(int)(pixfak*((*stepsum-*step)*cos(w)));
  908.         pxy[5] = ypixoff+(int)(pixfak*((*stepsum-*step)*sin(w)));
  909.         v_pline(handle,2,pxy+2);
  910.       }
  911.     }
  912.     vsl_type(handle,1);
  913.   }
  914.  
  915.   vst_height(handle,13,&dummy,&dummy,&dummy,&dummy);
  916. }
  917.  
  918. /* Diabatische Funktion, Quelle: SCHOTT-Glasfilterkatalog */
  919.  
  920. double diabat(double arg)
  921.  
  922. {
  923.   if(arg>=1.-1e-10) arg = 1.-1e-10;
  924.   if(arg<=1.e-10) arg = 1.e-10;
  925.   return(1.-log10(log10(1./arg)));
  926. }
  927.  
  928. /*   Vorzeichenrichtiger Kommaanteil einer Zahl   */
  929.  
  930. double frac(double x)
  931. { long int i;
  932.  
  933.   if(x==0.) return(0.);
  934.   i = (long int)x;
  935.   return(x-(double)i);
  936. }
  937.