home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / PLOT / PLOT3D_A.ZIP / PLOT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-24  |  10.1 KB  |  324 lines

  1. /*
  2.  
  3. Plot3d -- plot.c, the plotting code
  4.  
  5. By Adrian Mariano -- adrian@milton.u.washington.edu
  6.  
  7.  
  8. Copyright (c) 1991 by Adrian Mariano
  9.  
  10. You may use and distribute this program as much as you like so long as you do 
  11. not charge for this service.  I am not liable for failure of this program to 
  12. perform in any way.  
  13.  
  14. */
  15.  
  16.  
  17. #include "plot3d.h"
  18.  
  19. /******************************************************************/
  20. /*                                                                */
  21. /*                      Parameters to plot3d()                    */
  22.  
  23. float xmin=-3;     /* Dimensions of display area */
  24. float xmax=3;
  25. float ymin=-3;
  26. float ymax=3;
  27. float zmin=-3;
  28. float zmax=3;
  29.  
  30. float aspect=1.0;    /* Aspect ratio */
  31. float distance=3;    /* Perspective distance */
  32. float tip=-30.0;     /* Rotation around y axis */
  33. float spin=0.0;      /* Rotation around z axis */
  34.  
  35. float var1start;
  36. float var2start;
  37. float var1end;
  38. float var2end;
  39.  
  40. long var1stepcount=30; /* Number of steps over var 1 */
  41. long var2stepcount=30; /* Number of steps over var 2 */
  42.  
  43. /*                                                                */
  44. /******************************************************************/
  45.  
  46. #define TRUE 1
  47. #define FRONT 1
  48. #define FALSE 0
  49. #define BACK 0
  50. #define PI  3.14159265
  51.  
  52.  
  53. /*************************************
  54.         Internal variables
  55.         Global for convenience
  56. *************************************/
  57.  
  58. struct sectiontype {
  59.      int x1,y1,x2,y2,x3,y3,x4,y4;
  60.      float x;
  61. /*     char ferr;*/
  62.    };
  63.  
  64. float xrange,yrange,zrange,sinspin,cosspin,sintip,costip;
  65. float multx,multy,addx,addy;
  66.  
  67.  
  68. /* The main function */
  69. int plot3d(void (*transform)(float *,float *,float *,float,float,float));
  70.  
  71. /* Takes (x,y,z) and returns (x,y,z) in screen coordinates */
  72. void realscale(float *xx,float *yy,float *zz);
  73.  
  74. /* Compare to sections -- used by qsort */
  75. int sectioncmp(struct sectiontype *a,struct sectiontype *b);
  76.  
  77. /* plots the data contained the section */
  78. void plotsections(struct sectiontype *section,int count);
  79.  
  80. /* Get screen coordinates from float (x,y,z) */
  81. void scale(int *xint,int *yint,float x,float y,float z);
  82.  
  83. /* Draw 3d line */
  84. void line3d(float a,float b,float c,float d,float e,float f);
  85.  
  86. /* Initialize multx, multy, addx, and addy for use in scaling */
  87. void calcscale(float xmin,float ymin,float zmin,float xmax,float ymax,float zmax);
  88.  
  89. /* Draw the axes */
  90. void drawaxes(char flag);
  91.  
  92. /* Is this face (of the cube) visible ? */
  93. int visible(int i);
  94.  
  95.  
  96.  
  97. /* Function to be plotted */
  98.  
  99. #define FIX(flag,min,max) ( flag==1 ? max : min )
  100. #define round(x) floor((x)+0.5)
  101.  
  102. typedef int(*function)(const void *,const void *);
  103.  
  104. int plot3d(void (*transform)(float *,float *,float *,float,float,float))  /* transform points to transform to cartesian */
  105.  
  106. {
  107.    int i,edgecount,steps,steps2;         /* Counters */
  108.    float x,y,z;                         /* Cartesian coordinates */
  109.    float var1step,var2step,var1,var2;   /* Values for independent vars */
  110.    struct sectiontype *section;         /* Table of sections */
  111.  
  112.  
  113.    /* Get some memory */
  114.    section=farcalloc(var1stepcount+var2stepcount+3+(var1stepcount+1)*(var2stepcount+1),sizeof(struct sectiontype));
  115.    if (!section){
  116.       printf("Insufficient memory\n\n");
  117.       return 0;
  118.    }   
  119.    xrange=xmax-xmin;   /* Calculate widths for x, y, and z */
  120.    yrange=ymax-ymin;
  121.    zrange=zmax-zmin;
  122.    costip=cos(tip*PI/180);    /* Precalculate trig functions for angles */
  123.    sintip=sin(tip*PI/180);
  124.    sinspin=sin(spin*PI/180);
  125.    cosspin=cos(spin*PI/180);
  126.    calcscale(xmin,ymin,zmin,xmax,ymax,zmax);  /* Calculate scaling factors */
  127.    var1step=(var1end-var1start)/(var1stepcount);/* Set stepsizes for the  */
  128.    var2step=(var2end-var2start)/(var2stepcount);/* independent variables  */
  129.    i=0;
  130.    edgecount=0;
  131.    var1=var1start;     /* Initialize var1 */
  132.  
  133.    /* First make a partial table of needed boundary values.  These are given */
  134.    /* very large x distances so that they will get sorted to the end of the  */
  135.    /* section list.  A second counter, 'edgecount' is kept.  When the        */
  136.    /* sections are plotted, the this value will be subtracted from the       */
  137.    /* total counter so these edge sections won't be plotted                  */
  138.  
  139.    /* Create a table of the edge values along the "top" of the function */
  140.    for(var2=var2start,steps=var2stepcount+1; steps ;steps--, i++,edgecount++,var2+=var2step) {
  141.       (*transform)(&x,&y,&z,ff(var1,var2-var2step,0),var1,var2-var2step);
  142.       realscale(&x,&y,&z);
  143.       (section+i)->x4=round(addx+multx*x);  /* Bottom left point */
  144.       (section+i)->y4=round(addy+multy*y);
  145.       (section+i)->x=1e37;                  /* This section will get sorted to the end */
  146.  
  147.       (*transform)(&x,&y,&z,ff(var1,var2,0),var1,var2);
  148.       realscale(&x,&y,&z);
  149.       (section+i)->x3=round(addx+multx*x);  /* Bottom right point */
  150.       (section+i)->y3=round(addy+multy*y);
  151.    }
  152.  
  153.    /* Main loop, cycles through var 1 */
  154.    for (var1=var1start+var1step,steps2=var1stepcount; steps2 ;steps2--, var1+=var1step) {
  155.    
  156.       /* Calculate value for left edge of function */
  157.       var2=var2start;
  158.       (*transform)(&x,&y,&z,ff(var1,var2 ,0),var1,var2);
  159.       realscale(&x,&y,&z);
  160.       (section+i)->x3=round(addx+multx*x);  /* Bottom right point */
  161.       (section+i)->y3=round(addy+multy*y);
  162.       (section+i)->x=1e37;                  /* Will get sorted to the end */
  163.       (*transform)(&x,&y,&z,ff(var1-var1step,var2,0),var1-var1step,var2);
  164.       realscale(&x,&y,&z);
  165.       (section+i)->x2=round(addx+multx*x);  /* Top right point */
  166.       (section+i)->y2=round(addy+multy*y);
  167.       edgecount++;
  168.       i++;
  169.  
  170.       /* Main loop.  Calculate sections for one cycle of var 2 */
  171.       for(var2=var2start+var2step,steps=var2stepcount; steps ; i++ , steps--, var2+=var2step) {
  172.      (*transform)(&x,&y,&z,ff(var1,var2,0),var1,var2);
  173.      realscale(&x,&y,&z);
  174.      (section+i)->x3=round(addx+multx*x); /* Bottom right point */
  175.          (section+i)->y3=round(addy+multy*y);
  176.          (section+i)->x=z;
  177.  
  178.      /* These points have already been calculated */
  179.      (section+i)->x4=(section+i-1)->x3;   /* Bottom left point */
  180.          (section+i)->y4=(section+i-1)->y3;
  181.  
  182.      (section+i)->x2=(section+i-var2stepcount-1)->x3; /* Top right */
  183.      (section+i)->y2=(section+i-var2stepcount-1)->y3;
  184.  
  185.      (section+i)->x1=(section+i-var2stepcount-1)->x4; /* Top left */
  186.      (section+i)->y1=(section+i-var2stepcount-1)->y4;
  187.  
  188.       }
  189.       printf(".");  /* The it hasn't crashed indicator */
  190.    }
  191.    printf("\nSorting...");
  192.    qsort(section,i,sizeof(struct sectiontype),(function)sectioncmp);
  193.  
  194.    printf("\done");
  195.    entergraphics();
  196.    i-=edgecount;       /* Subtract the edges out */
  197.    drawaxes(BACK);     /* Draw back part of axes */
  198.    plotsections(section,i);
  199.    drawaxes(FRONT);             /* And plot those sections */
  200.    farfree(section);
  201.    return 1;
  202. }
  203.  
  204. void realscale(float *xx,float *yy,float *zz) {
  205.    float x,y,z,dist;
  206.  
  207.    x=(*xx/xrange)-xmin/xrange/2-xmax/xrange/2;
  208.    y=(*yy/yrange)-ymin/yrange/2-ymax/yrange/2;
  209.    z=(*zz/zrange)-zmin/zrange/2-zmax/zrange/2;
  210.    *zz=(x*cosspin-y*sinspin)*costip-z*sintip;
  211.    if (distance==0.0) dist=1;
  212.    else dist=distance+0.5-*zz;
  213.    *xx=(y*cosspin+x*sinspin)*aspect/dist;
  214.    *yy=(z*costip+(x*cosspin-y*sinspin)*sintip)/dist;
  215.    }
  216.  
  217.  
  218. /* Compare to sections for qsort() */
  219.  
  220. int sectioncmp(struct sectiontype *a,struct sectiontype *b)
  221. {
  222.  if (a->x < b->x) return(-1);
  223.  if (a->x == b->x) return(0);
  224.  return(1);
  225. }
  226.  
  227.  
  228. void plotsections(struct sectiontype *section,int count) /* Plot count sections */
  229. {
  230.  int i;
  231.  for(i=0;i<count;i++)
  232.    fill((section+i)->x1,(section+i)->y1,(section+i)->x2,(section+i)->y2,
  233.     (section+i)->x3,(section+i)->y3,(section+i)->x4,(section+i)->y4);
  234.  
  235. }
  236.  
  237. void scale(int *xint,int *yint,float x,float y,float z) {
  238.    realscale(&x,&y,&z);
  239.    *xint=round(addx+multx*x);
  240.    *yint=round(addy+multy*y);
  241.    }
  242.  
  243.  
  244. void line3d(float a,float b,float c,float d,float e,float f) {
  245.    int x1,y1,x2,y2;
  246.  
  247.    scale(&x1,&y1,a,b,c);
  248.    scale(&x2,&y2,d,e,f);
  249.    drawline(x1,y1,x2,y2);
  250.    }
  251.  
  252. /* Determine scaling constants */
  253.  
  254.  
  255. void calcscale(float xmin,float ymin,float zmin,float xmax,float ymax,float zmax)
  256. {
  257.    float xs[2],ys[2],zs[2],yb=-1e37,ym=1e37,xm=1e37,xb=-1e37;
  258.    char i,j,k;
  259.  
  260.    multx=1;
  261.    addx=0;
  262.    multy=1;
  263.    addy=0;
  264.    xs[0]=xmin;
  265.    xs[1]=xmax;
  266.    ys[0]=ymin;
  267.    ys[1]=ymax;
  268.    zs[0]=zmin;
  269.    zs[1]=zmax;
  270.    for(i=0;i<2;i++)
  271.       for(j=0;j<2;j++)
  272.      for(k=0;k<2;k++){
  273.             xmin=xs[i];
  274.             ymin=ys[j];
  275.             zmin=zs[k];
  276.             realscale(&xmin,&ymin,&zmin);
  277.             if (xmin>xb) xb=xmin;
  278.             else if (xmin<xm) xm=xmin;
  279.             if (ymin>yb) yb=ymin;
  280.             else if (ymin<ym) ym=ymin;
  281.      }
  282.    multx=((float)maxx)/(xb-xm);
  283.    multy=((float)maxy)/(yb-ym);
  284.    if (multx>multy) multx=multy; else multy=multx;
  285.    multy=-multy;
  286.    addx=-xm*multx+((float)maxx-multx*(xb-xm))/2;
  287.    addy=(float)maxy-ym*multy-((float)maxy+multy*(yb-ym))/2;
  288. }
  289.  
  290.  
  291. static int faces[6][3]={{0,0,-1},{-1,0,0},{0,1,0},{1,0,0},{0,-1,0},{0,0,1}};
  292. static int edges[12][8]={
  293.                  {0,1,-1,-1,-1,-1,1,-1},
  294.                  {0,2,-1,1,-1,1,1,-1},
  295.                  {0,3,1,-1,-1,1,1,-1},
  296.                  {0,4,-1,-1,-1,1,-1,-1},
  297.                  {4,1,-1,-1,-1,-1,-1,1},
  298.                  {1,2,-1,1,-1,-1,1,1},
  299.                  {2,3,1,1,-1,1,1,1},
  300.                  {3,4,1,-1,-1,1,-1,1},
  301.                  {5,1,-1,-1,1,-1, 1,1},
  302.                  {5,2,-1, 1,1, 1, 1,1},
  303.                  {5,3, 1,-1,1, 1, 1,1},
  304.                  {5,4,-1,-1,1, 1,-1,1}};
  305.  
  306.  
  307. void drawaxes(char flag)   /* Draw the axes */
  308. {
  309.    int i;
  310.    for(i=0;i<12;i++)
  311.      if ((visible(edges[i][0]) && visible(edges[i][1]))==flag)
  312.         line3d(FIX(edges[i][2],xmin,xmax), FIX(edges[i][3],ymin,ymax),
  313.                FIX(edges[i][4],zmin,zmax), FIX(edges[i][5],xmin,xmax),
  314.                FIX(edges[i][6],ymin,ymax), FIX(edges[i][7],zmin,zmax));
  315. }
  316.  
  317.  
  318. int visible(int i)   /* determine if a face of the coordinate cube is visible */
  319. {
  320.    return(faces[i][2] * sintip-(faces[i][0]*cosspin-faces[i][1]*sinspin)*costip<0);
  321. }
  322.  
  323.  
  324.