home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 460.lha / 3DPlot_v2.0 / sources / plot15.c < prev    next >
C/C++ Source or Header  |  1991-01-04  |  26KB  |  1,077 lines

  1. /*----------------  INCLUDE FILES  ----------------*/
  2.  
  3. #include "common.h"
  4.  
  5.  
  6. /*----------------  External Variables    ---------------*/
  7.  
  8. extern struct GfxBase *GfxBase;
  9. extern struct Window *win;
  10. extern struct RastPort *rastport;
  11. extern struct ViewPort *viewport;
  12. extern AllPlotData *apd;
  13.  
  14. extern DOUBLE Evaluate(DOUBLE, DOUBLE);
  15.  
  16.  
  17. /*----------------  Global User Parameters  ------------*/
  18.  
  19. LONG   plottype;       /* How to plot graph, see menuselect.h */
  20.  
  21. static
  22. LONG   xcenter = 160,
  23.        ycenter = 100,       /* Center of screen */
  24.  
  25.        xp, yp,
  26.        vp, zplane,
  27.  
  28.        xp1, xp2, xp3, xp4, yp1, yp2, yp3, yp4; /* for hidden and filled */
  29.  
  30. static
  31. DOUBLE aspectratio = .927,     /* to correct y-axis */
  32.  
  33.        fartherest, nextfartherest,
  34.        xbegin, xend, ybegin, yend,
  35.        xspc, xinc,
  36.        yspc, yinc,
  37.        xminymin, xminymax, xmaxymin, xmaxymax,
  38.        xyminmax[4],
  39.  
  40.        dtoplane,
  41.        dmin, dmax,
  42.        colorspread,
  43.  
  44.        RotMatrix[3][3],
  45.        TempMatrix[3][3];
  46.  
  47. static
  48. BOOL   plottinggraph,
  49.        onscreen,
  50.        backflag;
  51.  
  52.  
  53. /*------------    Global Color Palette Parameters  -------------*/
  54.  
  55. LONG numcolors = 24,
  56.      pennumbase = 4,
  57.      pennummax = 27,
  58.  
  59.      bkgpen  = 0,
  60.      borderpen = 1,
  61.      axespen = 2,
  62.      textpen = 3,
  63.      highlightpen1 = 30,
  64.      highlightpen2 = 31,
  65.  
  66.      bkgred = 0,
  67.      bkggreen = 0,
  68.      bkgblue = 0,      /* Black background */
  69.      axesred = 8,
  70.      axesgreen = 0,
  71.      axesblue = 0,      /* Red axes */
  72.      borderred = 10,
  73.      bordergreen = 10,
  74.      borderblue = 10,      /* Medium gray border */
  75.      textred = 8,
  76.      textgreen = 0,
  77.      textblue = 8,      /* Purple text */
  78.      graphfarred = 0,
  79.      graphfargreen = 0,
  80.      graphfarblue = 7,     /* Blue graph far color */
  81.      graphnearred = 15,
  82.      graphneargreen = 15,
  83.      graphnearblue = 15;  /* White graph near color */
  84.  
  85.  
  86. /*--------------  Temp Raster Global Parameters  ------------*/
  87.  
  88. static struct TmpRas tmpras;
  89. static struct AreaInfo areainfo;
  90. static PLANEPTR myplane;
  91. static UWORD areabuffer[15];
  92.  
  93.  
  94. /*------------    IsStopPlot Function  ---------------*/
  95.  
  96. BOOL IsStopPlot(message)
  97.   struct IntuiMessage *message;
  98. {
  99.   ULONG mclass;
  100.   UWORD menunum;
  101.  
  102.   mclass = message->Class;
  103.   menunum = message->Code;
  104.   ReplyMsg((struct Message *)message);
  105.  
  106.   if(mclass == MENUPICK) {
  107.      if( (MENUNUM(menunum) == MENUFUNCTION) &&
  108.      (ITEMNUM(menunum) == FUNCTIONSTOPPLOT) )
  109.        return TRUE;
  110.   } /* if */
  111.  
  112.   return FALSE;
  113.  
  114. } /* IsStopPlot */
  115.  
  116.  
  117. /*------------    SetScreenColors Function  --------------*/
  118.  
  119. VOID SetScreenColors()
  120. {
  121. SetRGB4(viewport,bkgpen,bkgred,bkggreen,bkgblue);
  122. SetRGB4(viewport,borderpen,borderred,bordergreen,borderblue);
  123. SetRGB4(viewport,axespen,axesred,axesgreen,axesblue);
  124. SetRGB4(viewport,textpen,textred,textgreen,textblue);
  125. SetRGB4(viewport,highlightpen1,0,4,5);
  126. SetRGB4(viewport,highlightpen2,12,12,0);
  127.  
  128. }  /* SetScreenColors */
  129.  
  130.  
  131. /*------------    SetGraphColors Function  --------------*/
  132.  
  133. VOID SetGraphColors()
  134. {
  135.   LONG num,
  136.        redvalue,
  137.        greenvalue,
  138.        bluevalue;
  139.  
  140.   for (num = pennumbase ; num <= pennummax ; ++num) {
  141.     redvalue = graphfarred + (num-pennumbase) * (graphnearred-graphfarred) / numcolors;
  142.     greenvalue = graphfargreen + (num-pennumbase) * (graphneargreen-graphfargreen) / numcolors;
  143.     bluevalue = graphfarblue + (num-pennumbase) * (graphnearblue-graphfarblue) / numcolors;
  144.     SetRGB4(viewport,num,redvalue,greenvalue,bluevalue);
  145.   }
  146. }   /* SetGraphColors */
  147.  
  148.  
  149. /*-------------  SetLoresColors Function  --------------*/
  150.  
  151. void SetLoresColors()
  152. {
  153.   SetScreenColors();
  154.  
  155.   /* Set fartherest colors as group */
  156.   numcolors = 8;
  157.   pennumbase = 4;
  158.   pennummax = 11;
  159.   graphfarred = 0;
  160.   graphfargreen = 0;
  161.   graphfarblue = 7;
  162.   graphnearred = 0;
  163.   graphneargreen = 0;
  164.   graphnearblue = 15;
  165.  
  166.   SetGraphColors();
  167.  
  168.   /* Set nearest colors as group */
  169.   numcolors = 16;
  170.   pennumbase = 12;
  171.   pennummax = 27;
  172.   graphfarred = 0;
  173.   graphfargreen = 0;
  174.   graphfarblue = 15;
  175.   graphnearred = 15;
  176.   graphneargreen = 15;
  177.   graphnearblue = 15;
  178.  
  179.   SetGraphColors();
  180.  
  181.   /* Set values to actual range for calculations */
  182.   numcolors = 24;
  183.   pennumbase = 4;
  184.  
  185. } /* SetLoresColors */
  186.  
  187.  
  188. /*-------------  SetHiresColors Function  --------------*/
  189.  
  190. void SetHiresColors()
  191. {
  192.   SetScreenColors();
  193.  
  194.   numcolors = 12;
  195.   pennumbase = 4;
  196.   pennummax = 15;
  197.   graphfarred = 0;
  198.   graphfargreen = 0;
  199.   graphfarblue = 15;
  200.   graphnearred = 15;
  201.   graphneargreen = 15;
  202.   graphnearblue = 15;
  203.  
  204.   SetGraphColors();
  205.  
  206. } /* SetHiresColors */
  207.  
  208.  
  209. /*-------------  ChangePlotParameters  Function  -------------*/
  210.  
  211. void ChangePlotParameters(scr)
  212.   struct Screen *scr;
  213. {
  214.   WORD scrW, scrH;
  215.  
  216.   Forbid();
  217.      scrW = scr->Width;
  218.      scrH = scr->Height;
  219.   Permit();
  220.  
  221.   if(scrW == 320) {
  222.      apd->dd.OriginX = xcenter = 160;
  223.  
  224.      if(scrH == 200) {
  225.     aspectratio = .927;
  226.     apd->dd.OriginY = ycenter = 100;
  227.      }
  228.      else {
  229.     aspectratio = 1.854;
  230.     apd->dd.OriginY = ycenter = 200;
  231.      }
  232.  
  233.      SetLoresColors();
  234.  
  235.   } /* if */
  236.  
  237.   else {  /* scrH == 640 */
  238.      apd->dd.OriginX = xcenter = 320;
  239.  
  240.      if(scrH == 200) {
  241.     aspectratio = .4635;
  242.     apd->dd.OriginY = ycenter = 100;
  243.      }
  244.      else {
  245.     aspectratio = .927;
  246.     apd->dd.OriginY = ycenter = 200;
  247.      }
  248.  
  249.      SetHiresColors();
  250.  
  251.   } /* else */
  252.  
  253. } /* ChangePlotParameters */
  254.  
  255.  
  256. /*-----------------  calc Function  ------------------*/
  257.  
  258. static DOUBLE calc(x,y)
  259.   DOUBLE x, y;
  260. {
  261.   return (Evaluate(x, y));
  262.  
  263. }    /* calc */
  264.  
  265.  
  266. /*----------------  xcalc, ycalc, zcalc Functions  ----------------*/
  267.  
  268. static DOUBLE xcalc(x,y,z)
  269.   DOUBLE x, y, z;
  270. {
  271.   return (RotMatrix[0][0] * x + RotMatrix[0][1] * y + RotMatrix[0][2] * z);
  272.  
  273. }  /* xcalc */
  274.  
  275.  
  276. static DOUBLE ycalc(x,y,z)
  277.   DOUBLE x, y, z;
  278. {
  279.   return (RotMatrix[1][0] * x + RotMatrix[1][1] * y + RotMatrix[1][2] * z);
  280.  
  281. }  /* ycalc */
  282.  
  283.  
  284. static DOUBLE zcalc(x,y,z)
  285.   DOUBLE x, y, z;
  286. {
  287.   return (RotMatrix[2][0] * x + RotMatrix[2][1] * y + RotMatrix[2][2] * z);
  288.  
  289. } /* zcalc */
  290.  
  291.  
  292. /*--------------------    Calculate Function  -------------------*/
  293.  
  294. static VOID Calculate(x, y, z)
  295.   DOUBLE x, y, z;
  296. {
  297.   DOUBLE xpixels, ypixels, zpixels,
  298.      zdiff;
  299.   DOUBLE tforline;
  300.  
  301.   xpixels = (xcalc(x,y,z) * apd->dd.Scale) + (DOUBLE)(apd->dd.OriginX - xcenter);
  302.   ypixels = (-ycalc(x,y,z) * apd->dd.Scale) + (DOUBLE)(apd->dd.OriginY - ycenter);
  303.   zpixels = (zcalc(x,y,z) * apd->dd.Scale);
  304.  
  305.   zdiff = (DOUBLE)(vp + zplane) - zpixels; /* negative if behind viewer */
  306.  
  307.   if (zdiff > 1) {
  308.     tforline = ((DOUBLE) vp) / zdiff;
  309.     xp = (LONG)(xpixels * tforline + .5) + xcenter;
  310.     yp = (LONG)(ypixels * tforline * aspectratio + .5) + ycenter;
  311.     onscreen = TRUE;
  312.   }
  313.   else {
  314.     xp = -1;
  315.     yp = -1;
  316.     onscreen = FALSE;
  317.   }
  318. }   /* Calculate */
  319.  
  320.  
  321. /*------------------  CalcAndPlot Function  ----------------*/
  322.  
  323. static VOID CalcAndPlot(x, y)
  324.   DOUBLE x, y;
  325. {
  326.   LONG     pennum;
  327.   DOUBLE z;
  328.  
  329.   z = calc(x,y);
  330.   Calculate(x, y, z);
  331.  
  332.   if (onscreen == TRUE) {
  333.     dtoplane = zcalc(x,y,z);
  334.     pennum = (LONG)((dtoplane - dmin)/colorspread) + pennumbase;
  335.     if (pennum > pennummax)  pennum = pennummax;
  336.     if (pennum < pennumbase)  pennum = pennumbase;
  337.  
  338.       SetAPen(rastport,pennum);
  339.  
  340.       if (backflag == TRUE) {
  341.     Move(rastport,xp,yp);
  342.     WritePixel(rastport,xp,yp);
  343.     backflag = FALSE;
  344.       }
  345.       else {
  346.     Draw(rastport,xp,yp);
  347.       }
  348.  
  349.   }  /* if */
  350. }   /* CalcAndPlot */
  351.  
  352.  
  353. /*------------------  CalcAndPlot2 Function  ----------------*/
  354.  
  355. static VOID CalcAndPlot2(x1, y1, flag)
  356.   DOUBLE x1, y1;
  357.   BOOL     flag;
  358. {
  359.   static LONG    pennum;
  360.   static DOUBLE x2, y2, z1;
  361.  
  362.   /* Assign last 2 points to first 2 points */
  363.   xp1 = xp4;
  364.   xp2 = xp3;
  365.   yp1 = yp4;
  366.   yp2 = yp3;
  367.  
  368.   x2 = x1 + xspc;  /* used if flag = FALSE, plot along Y-axis */
  369.   y2 = y1 + yspc;  /* used if flag = TRUE , plot along X-axis */
  370.  
  371.   if(flag)
  372.      Calculate(x1, y2, calc(x1, y2));
  373.   else
  374.      Calculate(x2, y1, calc(x2, y1));
  375.  
  376.   xp3 = xp;
  377.   yp3 = yp;
  378.  
  379.   z1 = calc(x1, y1);
  380.  
  381.   Calculate(x1, y1, z1);
  382.   xp4 = xp;
  383.   yp4 = yp;
  384.  
  385.   if (onscreen == TRUE) {
  386.     dtoplane = zcalc(x1, y1, z1);
  387.     pennum = (LONG)((dtoplane - dmin)/colorspread) + pennumbase;
  388.     if (pennum > pennummax)  pennum = pennummax;
  389.     if (pennum < pennumbase)  pennum = pennumbase;
  390.  
  391.       SetOPen(rastport,pennum);
  392.  
  393.       if(plottype == PLOTHIDDEN)
  394.     SetAPen(rastport, bkgpen);
  395.       else /* PLOTFILLED */
  396.     SetAPen(rastport, pennum);
  397.  
  398.       AreaMove(rastport, xp1, yp1);
  399.       AreaDraw(rastport, xp2, yp2);
  400.       AreaDraw(rastport, xp3, yp3);
  401.       AreaDraw(rastport, xp4, yp4);
  402.       AreaEnd(rastport);
  403.  
  404.   }  /* if */
  405. }   /* CalcAndPlot2 */
  406.  
  407.  
  408. /*------------------  AxesCalcAndPlot Function    ----------------*/
  409.  
  410. static VOID AxesCalcAndPlot(x, y, z)
  411.   DOUBLE x, y, z;
  412. {
  413.   LONG pixelcolor, potencolor;
  414.  
  415.   Calculate(x, y, z);
  416.  
  417.   if (onscreen == TRUE) {
  418.     pixelcolor = ReadPixel(rastport,xp,yp);
  419.     dtoplane = zcalc(x,y,z);
  420.     potencolor = (LONG)((dtoplane - dmin)/colorspread) + pennumbase;
  421.  
  422.     if (potencolor > pixelcolor) {
  423.       SetAPen(rastport,axespen);
  424.       WritePixel(rastport,xp,yp);
  425.     }
  426.   }
  427. }  /* AxesCalcAndPlot */
  428.  
  429.  
  430. /*-----------------  RotateAboutX Function  ----------------*/
  431.  
  432. void RotateAboutX(angle)
  433.   DOUBLE angle;
  434. {
  435.   DOUBLE sinx = sin(angle);
  436.   DOUBLE cosx = cos(angle);
  437.  
  438.   RotMatrix[0][0] = TempMatrix[0][0];
  439.   RotMatrix[0][1] = TempMatrix[0][1]*cosx+TempMatrix[0][2]*sinx;
  440.   RotMatrix[0][2] = TempMatrix[0][1]*(-sinx)+TempMatrix[0][2]*cosx;
  441.   RotMatrix[1][0] = TempMatrix[1][0];
  442.   RotMatrix[1][1] = TempMatrix[1][1]*cosx+TempMatrix[1][2]*sinx;
  443.   RotMatrix[1][2] = TempMatrix[1][1]*(-sinx)+TempMatrix[1][2]*cosx;
  444.   RotMatrix[2][0] = TempMatrix[2][0];
  445.   RotMatrix[2][1] = TempMatrix[2][1]*cosx+TempMatrix[2][2]*sinx;
  446.   RotMatrix[2][2] = TempMatrix[2][1]*(-sinx)+TempMatrix[2][2]*cosx;
  447. } /* RotateAboutX */
  448.  
  449.  
  450. /*-----------------  RotateAboutY Function  ----------------*/
  451.  
  452. void RotateAboutY(angle)
  453.   DOUBLE angle;
  454. {
  455.   DOUBLE siny = sin(angle);
  456.   DOUBLE cosy = cos(angle);
  457.  
  458.   RotMatrix[0][0] = TempMatrix[0][0]*cosy+TempMatrix[0][2]*(-siny);
  459.   RotMatrix[0][1] = TempMatrix[0][1];
  460.   RotMatrix[0][2] = TempMatrix[0][0]*siny+TempMatrix[0][2]*cosy;
  461.   RotMatrix[1][0] = TempMatrix[1][0]*cosy+TempMatrix[1][2]*(-siny);
  462.   RotMatrix[1][1] = TempMatrix[1][1];
  463.   RotMatrix[1][2] = TempMatrix[1][0]*siny+TempMatrix[1][2]*cosy;
  464.   RotMatrix[2][0] = TempMatrix[2][0]*cosy+TempMatrix[2][2]*(-siny);
  465.   RotMatrix[2][1] = TempMatrix[2][1];
  466.   RotMatrix[2][2] = TempMatrix[2][0]*siny+TempMatrix[2][2]*cosy;
  467. } /* RotateAboutY */
  468.  
  469.  
  470. /*-----------------  RotateAboutZ Function  ----------------*/
  471.  
  472. void RotateAboutZ(angle)
  473.   DOUBLE angle;
  474. {
  475.   DOUBLE sinz = sin(angle);
  476.   DOUBLE cosz = cos(angle);
  477.  
  478.   RotMatrix[0][0] = TempMatrix[0][0]*cosz+TempMatrix[0][1]*sinz;
  479.   RotMatrix[0][1] = TempMatrix[0][0]*(-sinz)+TempMatrix[0][1]*cosz;
  480.   RotMatrix[0][2] = TempMatrix[0][2];
  481.   RotMatrix[1][0] = TempMatrix[1][0]*cosz+TempMatrix[1][1]*sinz;
  482.   RotMatrix[1][1] = TempMatrix[1][0]*(-sinz)+TempMatrix[1][1]*cosz;
  483.   RotMatrix[1][2] = TempMatrix[1][2];
  484.   RotMatrix[2][0] = TempMatrix[2][0]*cosz+TempMatrix[2][1]*sinz;
  485.   RotMatrix[2][1] = TempMatrix[2][0]*(-sinz)+TempMatrix[2][1]*cosz;
  486.   RotMatrix[2][2] = TempMatrix[2][2];
  487. } /* RotateAboutZ */
  488.  
  489.  
  490. /*-----------------  CopyRotToTemp Function  ----------------*/
  491.  
  492. void CopyRotToTemp()
  493. {
  494.   LONG i, j;
  495.  
  496.   for(i=0 ; i<=2 ; i++) {
  497.      for(j=0 ; j<=2 ; j++) {
  498.     TempMatrix[i][j] = RotMatrix[i][j];
  499.      }
  500.   }
  501. }  /* CopytRotToTemp */
  502.  
  503.  
  504. /*-----------------  PutIdentityInTemp Function  ----------------*/
  505.  
  506. void PutIdentityInTemp()
  507. {
  508.   TempMatrix[0][0] = 1;
  509.   TempMatrix[0][1] = 0;
  510.   TempMatrix[0][2] = 0;
  511.   TempMatrix[1][0] = 0;
  512.   TempMatrix[1][1] = 1;
  513.   TempMatrix[1][2] = 0;
  514.   TempMatrix[2][0] = 0;
  515.   TempMatrix[2][1] = 0;
  516.   TempMatrix[2][2] = 1;
  517. }  /* PutIdentityInTemp */
  518.  
  519.  
  520. /*--------------------    DrawGraph Function  -----------------*/
  521.  
  522. VOID DrawGraph()
  523. {
  524.   struct IntuiMessage *message;
  525.  
  526.   DOUBLE calcspacex, calcspacey, calcincx, calcincy,
  527.      tx, ty, tz,
  528.      yminend, ymaxend, ybeginspc,
  529.      xminend, xmaxend, xbeginspc,
  530.      zradians, yradians, xradians;
  531.   BOOL     alongxflag,
  532.      alongyflag;
  533.  
  534.  
  535.   plottinggraph = TRUE;
  536.  
  537.   SetRast(rastport,0);
  538.  
  539.   /* Calculate Equation Parameter */
  540.  
  541.   vp = (LONG)(apd->dd.ViewDist * apd->dd.Scale); /* Viewer distance in pixels from projection plane */
  542.  
  543.   zplane = (LONG)(apd->dd.ProjPlane * apd->dd.Scale); /* Distance in pixels of projection plane from origin */
  544.  
  545.   calcspacex = apd->dd.LineSpacingX;
  546.   calcspacey = apd->dd.LineSpacingY;
  547.  
  548.   if(plottype == PLOTNORMAL) {
  549.      calcincx = 5*apd->dd.PlotPrecisionX;
  550.      calcincy = 5*apd->dd.PlotPrecisionY;
  551.   }
  552.   else {
  553.      calcincx = apd->dd.LineSpacingX;
  554.      calcincy = apd->dd.LineSpacingY;
  555.   }     /* Values to speed up min and max calcs to get colorspread */
  556.  
  557.   /* Calculate Equation Coefficients */
  558.  
  559.   zradians = ((DOUBLE) apd->dd.RotationZ) * PI / 180.;
  560.   yradians = ((DOUBLE) apd->dd.RotationY) * PI / 180.;
  561.   xradians = ((DOUBLE) apd->dd.RotationX) * PI / 180.;
  562.  
  563.   PutIdentityInTemp();
  564.   if((apd->pi.RotationOrder == ROTATEXYZ) || (apd->pi.RotationOrder == ROTATEXZY)) {
  565.      RotateAboutX(xradians);
  566.      CopyRotToTemp();
  567.      if(apd->pi.RotationOrder == ROTATEXYZ) {
  568.     RotateAboutY(yradians);
  569.     CopyRotToTemp();
  570.     RotateAboutZ(zradians);
  571.      }
  572.      else {
  573.     RotateAboutZ(zradians);
  574.     CopyRotToTemp();
  575.     RotateAboutY(yradians);
  576.      }
  577.   }
  578.   else if((apd->pi.RotationOrder == ROTATEYXZ) || (apd->pi.RotationOrder == ROTATEYZX)) {
  579.      RotateAboutY(yradians);
  580.      CopyRotToTemp();
  581.      if(apd->pi.RotationOrder == ROTATEYXZ) {
  582.     RotateAboutX(xradians);
  583.     CopyRotToTemp();
  584.     RotateAboutZ(zradians);
  585.      }
  586.      else {
  587.     RotateAboutZ(zradians);
  588.     CopyRotToTemp();
  589.     RotateAboutX(xradians);
  590.      }
  591.   }
  592.   else {
  593.      RotateAboutZ(zradians);
  594.      CopyRotToTemp();
  595.      if(apd->pi.RotationOrder == ROTATEZXY) {
  596.     RotateAboutX(xradians);
  597.     CopyRotToTemp();
  598.     RotateAboutY(yradians);
  599.      }
  600.      else {
  601.     RotateAboutY(yradians);
  602.     CopyRotToTemp();
  603.     RotateAboutX(xradians);
  604.      }
  605.   }
  606.  
  607.  
  608.   /* CALCULATE MINIMUM & MAXIMUM DISTANCES FROM USER */
  609.  
  610.   /* Initialize minimum & maximum */
  611.  
  612.   tz = calc(apd->dd.PlotXmin,apd->dd.PlotYmin);
  613.   dtoplane = zcalc(apd->dd.PlotXmin,apd->dd.PlotYmin,tz);
  614.   dmax = dtoplane;
  615.   dmin = dtoplane;
  616.  
  617.   /* Loop on X at constant Y's */
  618.  
  619.   if ( (apd->pi.Surface == XONLY) || (apd->pi.Surface == XANDY) ) {
  620.  
  621.     for (ty = apd->dd.PlotYmin ; ty <= apd->dd.PlotYmax ; ty += calcspacey) {
  622.  
  623.           /* Check for Stop Plot from user */
  624.       if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  625.     if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  626.       } /* if */
  627.  
  628.       for (tx = apd->dd.PlotXmin ; tx <= apd->dd.PlotXmax ; tx += calcincx) {
  629.     tz = calc(tx,ty);
  630.     dtoplane = zcalc(tx,ty,tz);
  631.     dmax = MAX(dmax,dtoplane);
  632.     dmin = MIN(dmin,dtoplane);
  633.       }
  634.     }
  635.  
  636.   }
  637.  
  638.   /* Loop on Y at constant X's */
  639.  
  640.   if ( (apd->pi.Surface == YONLY) || (apd->pi.Surface == XANDY) ) {
  641.  
  642.     for (tx = apd->dd.PlotXmin ; tx <= apd->dd.PlotXmax ; tx += calcspacex) {
  643.  
  644.          /* Check for Stop Plot from user */
  645.       if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  646.     if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  647.       } /* if */
  648.  
  649.       for (ty = apd->dd.PlotYmin ; ty <= apd->dd.PlotYmax ; ty += calcincy) {
  650.     tz = calc(tx,ty);
  651.     dtoplane = zcalc(tx,ty,tz);
  652.     dmax = MAX(dmax,dtoplane);
  653.     dmin = MIN(dmin,dtoplane);
  654.       }
  655.     }
  656.  
  657.   }
  658.  
  659.   /* Calculate depth of each color range */
  660.  
  661.   colorspread = (dmax - dmin)/numcolors;
  662.   if (colorspread == 0) colorspread = 1;  /* in case all points equidistant */
  663.  
  664.   /* Calculate two farthest corners from viewer */
  665.  
  666.   xyminmax[0] = xminymin = zcalc(apd->dd.PlotXmin, apd->dd.PlotYmin, 0);
  667.   xyminmax[1] = xminymax = zcalc(apd->dd.PlotXmin, apd->dd.PlotYmax, 0);
  668.   xyminmax[2] = xmaxymin = zcalc(apd->dd.PlotXmax, apd->dd.PlotYmin, 0);
  669.   xyminmax[3] = xmaxymax = zcalc(apd->dd.PlotXmax, apd->dd.PlotYmax, 0);
  670.  
  671.   dqsort(xyminmax, 4);       /* Sort the distances */
  672.   fartherest = xyminmax[0];
  673.   nextfartherest = xyminmax[1];
  674.  
  675.   /* Set plotting order along X-axis */
  676.  
  677.   if( (fartherest == xminymin) || (fartherest == xminymax) ) {
  678.      xbegin = apd->dd.PlotXmin;
  679.      xend = apd->dd.PlotXmax;
  680.      xspc = apd->dd.LineSpacingX;
  681.      xinc = apd->dd.PlotPrecisionX;
  682.  
  683.      if( (nextfartherest == xmaxymin) || (nextfartherest == xmaxymax) )
  684.     alongxflag = TRUE;
  685.      else
  686.     alongxflag = FALSE;
  687.  
  688.   }  /* if */
  689.  
  690.   else {
  691.      xbegin = apd->dd.PlotXmax;
  692.      xend = apd->dd.PlotXmin;
  693.      xspc = -apd->dd.LineSpacingX;
  694.      xinc = -apd->dd.PlotPrecisionX;
  695.  
  696.      if( (nextfartherest == xminymin) || (nextfartherest == xminymax) )
  697.     alongxflag = TRUE;
  698.      else
  699.     alongxflag = FALSE;
  700.  
  701.   }  /* else */
  702.  
  703.   /* Set plotting order along Y-axis */
  704.  
  705.   if( (fartherest == xminymin) || (fartherest == xmaxymin) ) {
  706.      ybegin = apd->dd.PlotYmin;
  707.      yend = apd->dd.PlotYmax;
  708.      yspc = apd->dd.LineSpacingY;
  709.      yinc = apd->dd.PlotPrecisionY;
  710.   }
  711.   else {
  712.      ybegin = apd->dd.PlotYmax;
  713.      yend = apd->dd.PlotYmin;
  714.      yspc = -apd->dd.LineSpacingY;
  715.      yinc = -apd->dd.PlotPrecisionY;
  716.   }
  717.  
  718.   /* PLOT THE GRAPH */
  719.  
  720.   switch(plottype) {
  721.  
  722.      case PLOTNORMAL:
  723.  
  724.      /* Plot X's at constant Y's for specified range of Y */
  725.  
  726.   if (apd->pi.Surface == XONLY) {   /* Only if user specified */
  727.     for (ty = ybegin ; (ty <= apd->dd.PlotYmax) && (ty >= apd->dd.PlotYmin) ; ty += yspc) {
  728.  
  729.         /* Check for Stop Plot from user */
  730.       if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  731.     if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  732.       } /* if */
  733.  
  734.       backflag = TRUE;    /* Prevent last point from connecting with the next first point */
  735.  
  736.       for (tx = xbegin ; (tx <= apd->dd.PlotXmax) && (tx >= apd->dd.PlotXmin) ; tx += xinc)
  737.      CalcAndPlot(tx, ty);
  738.     } /* for */
  739.   }  /* if */
  740.  
  741.        /* Plot Y's at constant X for specified range of X */
  742.  
  743.   else if (apd->pi.Surface == YONLY) {      /* Do only if user specified */
  744.     for (tx = xbegin ; (tx <= apd->dd.PlotXmax) && (tx >= apd->dd.PlotXmin) ; tx += xspc) {
  745.  
  746.            /* Check for Stop Plot from user */
  747.       if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  748.     if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  749.       } /* if */
  750.  
  751.       backflag = TRUE;    /* Prevent last point from connecting with the next first point */
  752.  
  753.       for (ty = ybegin ; (ty <= apd->dd.PlotYmax) && (ty >= apd->dd.PlotYmin) ; ty += yinc)
  754.      CalcAndPlot(tx, ty);
  755.     } /* for */
  756.   }  /* else if */
  757.  
  758.   else {   /* Plot crosshatched */
  759.      DOUBLE ty2 = ybegin,
  760.         tx2 = xbegin;
  761.  
  762.      alongxflag = TRUE;
  763.      alongyflag = TRUE;
  764.  
  765.      do {
  766.     if(alongxflag) {
  767.        backflag = TRUE;
  768.        for(tx = xbegin ; (tx <= apd->dd.PlotXmax) && (tx >= apd->dd.PlotXmin) ; tx += xinc)
  769.           CalcAndPlot(tx, ty2);
  770.  
  771.        ty2 += yspc;
  772.  
  773.        if( (ty2 < apd->dd.PlotYmin) || (ty2 > apd->dd.PlotYmax) ) alongxflag = FALSE;
  774.  
  775.            /* Check for Stop Plot from user */
  776.        if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  777.           if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  778.        } /* if */
  779.  
  780.     } /* if */
  781.  
  782.     if(alongyflag) {
  783.        backflag = TRUE;
  784.        for(ty = ybegin ; (ty <= apd->dd.PlotYmax) && (ty >= apd->dd.PlotYmin) ; ty += yinc)
  785.           CalcAndPlot(tx2, ty);
  786.  
  787.        tx2 += xspc;
  788.  
  789.        if( (tx2 < apd->dd.PlotXmin) || (tx2 > apd->dd.PlotXmax) ) alongyflag = FALSE;
  790.  
  791.              /* Check for Stop Plot from user */
  792.        if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  793.           if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  794.        } /* if */
  795.  
  796.     } /* if */
  797.  
  798.      } while (alongxflag || alongyflag);
  799.  
  800.   } /* else */
  801.  
  802.   break;
  803.  
  804.      case PLOTHIDDEN:
  805.      case PLOTFILLED:
  806.  
  807. #if DEBUG
  808.   printf("Pre-InitArea\n");
  809. #endif
  810.  
  811.     InitArea(&areainfo, &areabuffer[0], 6);
  812.  
  813. #if DEBUG
  814.   printf("InitArea\n");
  815. #endif
  816.  
  817.     rastport->AreaInfo = &areainfo;
  818.  
  819. #if DEBUG
  820.   printf("rastport->AreaInfo\n");
  821. #endif
  822.  
  823.     myplane = (PLANEPTR)AllocRaster(320,200);
  824.  
  825. #if DEBUG
  826.   printf("AllocRaster\n");
  827. #endif
  828.  
  829.     if(myplane == NULL) break;
  830.  
  831. #if DEBUG
  832.   printf("myplane == NULL\n");
  833. #endif
  834.  
  835.     rastport->TmpRas = (struct TmpRas *)InitTmpRas(&tmpras, myplane, RASSIZE(320,200));
  836.  
  837. #if DEBUG
  838.   printf("Allocated tmpras\n");
  839. #endif
  840.  
  841.      if(alongxflag) {  /* Plot along X-axis */
  842.     yminend = apd->dd.PlotYmin;
  843.     ymaxend = apd->dd.PlotYmax;
  844.  
  845.         /* Prevent going one yspc to far at end of plot */
  846.     if(ybegin < yend)
  847.        ymaxend = apd->dd.PlotYmax - yspc;
  848.     else
  849.        yminend = apd->dd.PlotYmin - yspc;
  850.  
  851.     for(ty = ybegin ; (ty <= ymaxend) && (ty >= yminend) ; ty += yspc) {
  852.  
  853.             /* Check for Stop Plot from user */
  854.        if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  855.           if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  856.        } /* if */
  857.  
  858.        /* Initialize starting plot points */
  859.  
  860.        ybeginspc = ty + yspc;
  861.  
  862.        Calculate(xbegin, ty, calc(xbegin, ty));
  863.           xp4 = xp;
  864.           yp4 = yp;
  865.  
  866.        Calculate(xbegin, ybeginspc, calc(xbegin, ybeginspc));
  867.           xp3 = xp;
  868.           yp3 = yp;
  869.  
  870.        /* Plot along X-axis */
  871.  
  872.        for(tx = xbegin + xspc ; (tx <= apd->dd.PlotXmax) && (tx >= apd->dd.PlotXmin) ; tx += xspc)
  873.           CalcAndPlot2(tx, ty, alongxflag);
  874.  
  875.     } /* for */
  876.      } /* if */
  877.  
  878.      else {  /* Plot along Y-axis */
  879.     xminend = apd->dd.PlotXmin;
  880.     xmaxend = apd->dd.PlotXmax;
  881.  
  882.         /* Prevent going one xspc to far at end of plot */
  883.     if(xbegin < xend)
  884.        xmaxend = apd->dd.PlotXmax - xspc;
  885.     else
  886.        xminend = apd->dd.PlotXmin - xspc;
  887.  
  888.     for(tx = xbegin ; (tx <= xmaxend) && (tx >= xminend) ; tx += xspc) {
  889.  
  890.             /* Check for Stop Plot from user */
  891.        if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  892.           if(IsStopPlot(message) == TRUE) goto EndDrawGraph;
  893.        } /* if */
  894.  
  895.        /* Initialize starting plot points */
  896.  
  897.        xbeginspc = tx + xspc;
  898.  
  899.        Calculate(tx, ybegin, calc(tx, ybegin));
  900.           xp4 = xp;
  901.           yp4 = yp;
  902.  
  903.        Calculate(xbeginspc, ybegin, calc(xbeginspc, ybegin));
  904.           xp3 = xp;
  905.           yp3 = yp;
  906.  
  907.        /* Plot along X-axis */
  908.  
  909.        for(ty = ybegin + yspc ; (ty <= apd->dd.PlotYmax) && (ty >= apd->dd.PlotYmin) ; ty += yspc)
  910.           CalcAndPlot2(tx, ty, alongxflag);
  911.  
  912.     } /* for */
  913.      } /* else */
  914.  
  915.     FreeRaster(myplane, 320, 200);
  916.  
  917.     break;
  918.  
  919.      default:
  920.     break;
  921.   }  /* switch */
  922.  
  923.  
  924.   /* DRAW AXES */
  925.  
  926.   switch(apd->pi.AxesType) {
  927.  
  928.      case AXESTYPENONE:
  929.     break;
  930.  
  931.      case AXESTYPESTAR:
  932.  
  933.   /* X-axis */
  934.  
  935.   if (apd->ad.AxesXmax > apd->ad.AxesXmin) {   /* Do not plot if equal */
  936.     ty = 0;
  937.     tz = 0;
  938.     for (tx = apd->ad.AxesXmin ; tx <= apd->ad.AxesXmax ; tx += apd->ad.AxesPrecision)  AxesCalcAndPlot(tx, ty, tz);
  939.   }
  940.  
  941.   /* Y-axis */
  942.  
  943.   if (apd->ad.AxesYmax > apd->ad.AxesYmin) {
  944.     tx = 0;
  945.     tz = 0;
  946.     for (ty = apd->ad.AxesYmin ; ty <= apd->ad.AxesYmax ; ty += apd->ad.AxesPrecision)  AxesCalcAndPlot(tx, ty, tz);
  947.   }
  948.  
  949.   /* Z-axis */
  950.  
  951.   if (apd->ad.AxesZmax > apd->ad.AxesZmin) {
  952.     tx = 0;
  953.     ty = 0;
  954.     for (tz = apd->ad.AxesZmin ; tz <= apd->ad.AxesZmax ; tz += apd->ad.AxesPrecision)  AxesCalcAndPlot(tx, ty, tz);
  955.   }
  956.  
  957.   break;
  958.  
  959.      case AXESTYPEBOX:
  960.  
  961.   /* X-axis */
  962.  
  963.   if (apd->ad.AxesXmax > apd->ad.AxesXmin) {   /* Do not plot if equal */
  964.     for (tx = apd->ad.AxesXmin ; tx <= apd->ad.AxesXmax ; tx += apd->ad.AxesPrecision) {
  965.        AxesCalcAndPlot(tx, apd->ad.AxesYmin, apd->ad.AxesZmin);
  966.        AxesCalcAndPlot(tx, apd->ad.AxesYmin, apd->ad.AxesZmax);
  967.        AxesCalcAndPlot(tx, apd->ad.AxesYmax, apd->ad.AxesZmin);
  968.        AxesCalcAndPlot(tx, apd->ad.AxesYmax, apd->ad.AxesZmax);
  969.     } /* for */
  970.   }   /* if */
  971.  
  972.   /* Y-axis */
  973.  
  974.   if (apd->ad.AxesYmax > apd->ad.AxesYmin) {
  975.     for (ty = apd->ad.AxesYmin ; ty <= apd->ad.AxesYmax ; ty += apd->ad.AxesPrecision) {
  976.        AxesCalcAndPlot(apd->ad.AxesXmin, ty, apd->ad.AxesZmin);
  977.        AxesCalcAndPlot(apd->ad.AxesXmin, ty, apd->ad.AxesZmax);
  978.        AxesCalcAndPlot(apd->ad.AxesXmax, ty, apd->ad.AxesZmin);
  979.        AxesCalcAndPlot(apd->ad.AxesXmax, ty, apd->ad.AxesZmax);
  980.     } /* for */
  981.   }  /* if */
  982.  
  983.   /* Z-axis */
  984.  
  985.   if (apd->ad.AxesZmax > apd->ad.AxesZmin) {
  986.     for (tz = apd->ad.AxesZmin ; tz <= apd->ad.AxesZmax ; tz += apd->ad.AxesPrecision) {
  987.        AxesCalcAndPlot(apd->ad.AxesXmin, apd->ad.AxesYmin, tz);
  988.        AxesCalcAndPlot(apd->ad.AxesXmin, apd->ad.AxesYmax, tz);
  989.        AxesCalcAndPlot(apd->ad.AxesXmax, apd->ad.AxesYmin, tz);
  990.        AxesCalcAndPlot(apd->ad.AxesXmax, apd->ad.AxesYmax, tz);
  991.     } /* for */
  992.   }   /* if */
  993.  
  994.   break;
  995.  
  996.      default:
  997.     break;
  998.  
  999.   } /* switch */
  1000.  
  1001. EndDrawGraph:
  1002.    plottinggraph = FALSE;
  1003.  
  1004. }  /* DrawGraph */
  1005.  
  1006.  
  1007. VOID DrawContour(VOID)
  1008. {
  1009.    struct IntuiMessage *message;
  1010.    WORD lowX, lowY;
  1011.    WORD highX, highY;
  1012.    LONG   pennum;
  1013.    DOUBLE tx, ty, tz;
  1014.    DOUBLE stepvalX, stepvalY;
  1015.    DOUBLE calcspacex, calcspacey;
  1016.  
  1017.    plottinggraph = TRUE;
  1018.  
  1019.    /* Set up ranges */
  1020.    lowX = 0;
  1021.    lowY = 0;
  1022.    highX = win->Width - 1;
  1023.    highY = win->Height - 1;
  1024.    stepvalX = (apd->dd.PlotXmax - apd->dd.PlotXmin) / highX;
  1025.    stepvalY = (apd->dd.PlotYmax - apd->dd.PlotYmin) / highY;
  1026.    calcspacex = apd->dd.LineSpacingX;
  1027.    calcspacey = apd->dd.LineSpacingY;
  1028.  
  1029.    /* CALCULATE MINIMUM & MAXIMUM DISTANCES FROM USER */
  1030.  
  1031.    /* Initialize minimum & maximum */
  1032.    tz = calc(apd->dd.PlotXmin,apd->dd.PlotYmin);
  1033.    dmax = tz;
  1034.    dmin = tz;
  1035.  
  1036.    /* Loop over entire screen */
  1037.    for (ty = apd->dd.PlotYmin ; ty <= apd->dd.PlotYmax ; ty += calcspacey) {
  1038.           /* Check for Stop Plot from user */
  1039.       if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  1040.     if(IsStopPlot(message) == TRUE) goto EndDrawContour;
  1041.       } /* if */
  1042.       for (tx = apd->dd.PlotXmin ; tx <= apd->dd.PlotXmax ; tx += calcspacex) {
  1043.     tz = calc(tx,ty);
  1044.     dmax = MAX(dmax,tz);
  1045.     dmin = MIN(dmin,tz);
  1046.       } /* for */
  1047.    } /* for */
  1048.  
  1049.    /* Calculate depth of each color range */
  1050.    colorspread = (dmax - dmin)/numcolors;
  1051.    if (colorspread == 0) colorspread = 1;  /* in case all points equidistant */
  1052.  
  1053.    /* Plot over entire screen */
  1054.    for (ty = apd->dd.PlotYmax, yp = lowY ;
  1055.     yp <= highY ; ty -= stepvalY, yp += 1) {
  1056.           /* Check for Stop Plot from user */
  1057.       if(message = (struct IntuiMessage *) GetMsg(win->UserPort)) {
  1058.     if(IsStopPlot(message) == TRUE) goto EndDrawContour;
  1059.       } /* if */
  1060.  
  1061.       for (tx = apd->dd.PlotXmin, xp = lowX ;
  1062.        xp <= highX ; tx += stepvalX, xp += 1)    {
  1063.      tz = calc(tx,ty);
  1064.      pennum = (LONG)((tz - dmin)/colorspread) + pennumbase;
  1065.      if (pennum > pennummax)  pennum = pennummax;
  1066.      if (pennum < pennumbase)  pennum = pennumbase;
  1067.      SetAPen(rastport,pennum);
  1068.      WritePixel(rastport,xp,yp);
  1069.       } /* for */
  1070.    } /* for */
  1071.  
  1072. EndDrawContour:
  1073.    plottinggraph = FALSE;
  1074.  
  1075. } /* DrawContour */
  1076.  
  1077.