home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / icoons / source / spl_gfx.c < prev    next >
C/C++ Source or Header  |  1992-10-20  |  43KB  |  1,422 lines

  1. /* :ts=8 */
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6.  
  7. #include "general.h"
  8. #include "globals.h"
  9. #include "intui.h"
  10. #include "spl_math.h"
  11. #include "spl_util.h"
  12. #include "spl_gfx.h"
  13.  
  14.  
  15.     /* Constants and macros used by the clipping routine:    */
  16. #define OutCode_Top    0x01
  17. #define OutCode_Bottom    0x02
  18. #define OutCode_Right    0x04
  19. #define OutCode_Left    0x08
  20.  
  21.     /* Compute 'OutCode' for position (X,Y) and return it in C    */
  22. #define Compute_OutCode(X, Y, C)                \
  23.     C = 0;                        \
  24.     if (Y > YMax)      C  = OutCode_Top;        \
  25.         else if (Y < YMin) C  = OutCode_Bottom;        \
  26.     if (X > XMax)      C |= OutCode_Right;        \
  27.         else if (X < XMin) C |= OutCode_Left
  28.     
  29.  
  30.     /* Clip and draw line (X0,Y0) - (X1,Y1) in view V.        */
  31. #define ViewClipDrawLine(V, X0, Y0, X1, Y1)        \
  32.     ClipDrawLine(X0, Y0, X1, Y1,             \
  33.         Views[V].X_Min, Views[V].X_Max,        \
  34.         Views[V].Y_Min, Views[V].Y_Max)
  35.  
  36. void ClipDrawLine(short X0, short Y0, short X1, short Y1, 
  37.            short XMin, short XMax, short YMin, short YMax)
  38. /************************************************************************/
  39. /*                                                                      */
  40. /* Clip and draw the line from (X0, Y0) - (X1, Y1) to the rectangle     */
  41. /* given by (XMin, YMin) - (XMax, YMax).                */
  42. /*                                                                      */
  43. /* This is the Cohen-Sutherland algorithm as described in         */
  44. /* Computer graphics p. 113 - 117.                    */
  45. /*                                                                      */
  46. /************************************************************************/
  47. {
  48.     Boolean_T     Accept, Done;
  49.     long    OutCode0, OutCode1, OutCodeOut;
  50.     int        X, Y;
  51.  
  52.     Accept = Done = FALSE;
  53.  
  54.     Compute_OutCode(X0, Y0, OutCode0);
  55.     Compute_OutCode(X1, Y1, OutCode1);
  56.  
  57.     do {
  58.  
  59.     if (OutCode0 == 0 && OutCode1 == 0) Accept = Done = TRUE;
  60.        else if ((OutCode0 & OutCode1) != 0) Done = TRUE;
  61.        else {
  62.  
  63.         /* Failed both tests, so calculate the line segment to     */
  64.         /* clip: from an outside point to an intersection with     */
  65.         /* clip edge.                        */
  66.  
  67.         /* At least one  endpoint is outside the clip rectangle,    */
  68.         /* pick it.                            */
  69.  
  70.         if (OutCode0 != 0) OutCodeOut = OutCode0;
  71.             else           OutCodeOut = OutCode1;
  72.  
  73.         /* Now find intersection point:                 */
  74.  
  75.         if (OutCodeOut & OutCode_Top) {
  76.  
  77.         /* Divide line at top of clip rectangle            */
  78.         if (Y0 == Y1) Done = TRUE;
  79.         else {
  80.             X = X0 + (X1 - X0) * (YMax - Y0) / (Y1 - Y0);
  81.             Y = YMax;
  82.         }
  83.         } else if (OutCodeOut & OutCode_Bottom) {
  84.  
  85.         /* Divide line at bottom of clip rectangle        */
  86.         if (Y0 == Y1) Done = TRUE;
  87.         else {
  88.             X = X0 + (X1 - X0) * (YMin - Y0) / (Y1 - Y0);
  89.             Y = YMin;
  90.         }
  91.  
  92.         } else if (OutCodeOut & OutCode_Right) {
  93.  
  94.         /* Divide line at right of clip rectangle        */
  95.         if (X0 == X1) Done = TRUE;
  96.         else {
  97.             X = XMax;
  98.             Y = Y0 + (Y1 - Y0) * (XMax - X0) / (X1 - X0);
  99.         }
  100.  
  101.         } else if (OutCodeOut & OutCode_Left) {
  102.  
  103.         /* Divide line at left of clip rectangle        */
  104.         if (X0 == X1) Done = TRUE;
  105.         else {
  106.             X = XMin;
  107.             Y = Y0 + (Y1 - Y0) * (XMin - X0) / (X1 - X0);
  108.         }
  109.         } /* if .. else .. */
  110.  
  111.         /* Now we move outside point to intersection point to clip,    */
  112.         /* and get ready for next pass.                */
  113.  
  114.         if (OutCodeOut == OutCode0) {
  115.  
  116.         X0 = X;
  117.         Y0 = Y;
  118.         Compute_OutCode(X0, Y0, OutCode0);
  119.  
  120.         } else {
  121.  
  122.         X1 = X;
  123.         Y1 = Y;
  124.         Compute_OutCode(X1, Y1, OutCode1);
  125.  
  126.          } /* if .. else .. */
  127.  
  128.     } /* if .. else .. */
  129.  
  130.     } while (!Done);
  131.  
  132.     if (Accept) {
  133.  
  134.     /* Draw from (X0, Y0) to (X1, Y1) */
  135.  
  136.         Move(Windows[Id_Active_Window].RastPort, X0, Y0);
  137.         Draw(Windows[Id_Active_Window].RastPort, X1, Y1);
  138.     
  139.     } /* if */
  140.  
  141. } /* ClipDrawLine */
  142.  
  143.  
  144. void Modify_Scale(double Factor)
  145. /************************************************************************/
  146. /*                                                                      */
  147. /* Modify the scale factor.                        */
  148. /*                                                                      */
  149. /************************************************************************/
  150. {
  151.     X_Scale_Factor *= Factor;
  152.     Y_Scale_Factor *= Factor;
  153.     Max_Dist = 5.0 / Y_Scale_Factor;
  154.  
  155. } /* Modify_Scale */
  156.  
  157. void Transformation_Init()
  158. /************************************************************************/
  159. /*                                                                      */
  160. /* Initialize all transformation parameters.                */
  161. /*                                                                      */
  162. /************************************************************************/
  163. {
  164.     Vector_T     Initial_Offset        = { 0.0, 0.0, 0.0 };
  165.  
  166.     Y_Scale_Factor    = 0.5;
  167.     X_Scale_Factor    = Aspect_Ratio * Y_Scale_Factor;
  168.     Modify_Scale(1.0);    
  169.  
  170.     Compute_Rotation_Matrix(M_Rotation, Rotation_Vector);
  171.     Set_Offset(Initial_Offset, -1);
  172.  
  173. } /* Transformation_Init */
  174.  
  175. void Set_Offset(Vector_T Pos, short View_Id)
  176. /************************************************************************/
  177. /*                                                                      */
  178. /* Set the offset to Pos. View_Id designates the view in which the     */
  179. /* offset is changed (-1 => all views).                    */
  180. /*                                                                      */
  181. /************************************************************************/
  182. {
  183.     switch (View_Id) {
  184.  
  185.     case -1:                 /* All views    */
  186.         Offset[0] = Pos[0]; 
  187.         Offset[1] = Pos[1]; 
  188.         Offset[2] = Pos[2]; 
  189.     break;
  190.  
  191.     case 0:                 /* Y - Z    */
  192.         Offset[1] = Pos[1]; 
  193.         Offset[2] = Pos[2]; 
  194.     break;
  195.  
  196.     case 1:                 /* X - Z    */
  197.         Offset[0] = Pos[0]; 
  198.         Offset[2] = Pos[2]; 
  199.     break;
  200.  
  201.     case 2:                 /* X - Y    */
  202.         Offset[0] = Pos[0]; 
  203.         Offset[1] = Pos[1]; 
  204.     break;  
  205.  
  206.     } /* switch */
  207.  
  208. } /* Set_Offset */
  209.  
  210. void Move_Offset(short Direction, short View_Id)
  211. /************************************************************************/
  212. /*                                                                      */
  213. /* Move offset in the view given by View_Id in the direction given by    */
  214. /* Direction (0: Up, 1: Down, 2: Right, 3: Left).            */
  215. /*                                                                      */
  216. /* The distance moved depends on the current scale factor.        */
  217. /*                                                                      */
  218. /************************************************************************/
  219. {
  220.     double     Delta;
  221.     Vector_T    New_Offset;
  222.  
  223.     Vec2Op(New_Offset, =, Offset);
  224.  
  225.     Delta = 100.0 / Y_Scale_Factor;
  226.  
  227.     switch (Direction) {
  228.     case 0:    /* Up */
  229.         switch (View_Id) {
  230.     case 0: New_Offset[2] = Offset[2] + Delta; break;
  231.     case 1: New_Offset[2] = Offset[2] + Delta; break;
  232.     case 2: New_Offset[1] = Offset[1] + Delta; break;
  233.     } /* switch */
  234.     break;
  235.  
  236.     case 1:    /* Down */
  237.         switch (View_Id) {
  238.     case 0: New_Offset[2] = Offset[2] - Delta; break;
  239.     case 1: New_Offset[2] = Offset[2] - Delta; break;
  240.     case 2: New_Offset[1] = Offset[1] - Delta; break;
  241.     } /* switch */
  242.     break;
  243.  
  244.     case 2:    /* Right */
  245.         switch (View_Id) {
  246.     case 0: New_Offset[1] = Offset[1] + Delta; break;
  247.     case 1: New_Offset[0] = Offset[0] + Delta; break;
  248.     case 2: New_Offset[0] = Offset[0] + Delta; break;
  249.     } /* switch */
  250.     break;
  251.  
  252.     case 3:    /* Left */
  253.         switch (View_Id) {
  254.     case 0: New_Offset[1] = Offset[1] - Delta; break;
  255.     case 1: New_Offset[0] = Offset[0] - Delta; break;
  256.     case 2: New_Offset[0] = Offset[0] - Delta; break;
  257.     } /* switch */
  258.     break;
  259.  
  260.     } /* Switch */
  261.  
  262.     Set_Offset(New_Offset, -1);
  263.  
  264. } /* Move_Offset */
  265.  
  266. void Snap_To_Grid(Vector_T Pos)
  267. /************************************************************************/
  268. /*                                                                      */
  269. /* Snap the point Pos to the grid.                    */
  270. /*                                                                      */
  271. /************************************************************************/
  272. {
  273.     double Size2;
  274.  
  275.     Size2 = Grid_Size / 2.0;
  276.  
  277.     Pos[0] = SGN(Pos[0]) * Grid_Size * ( (int)((ABS(Pos[0]) + Size2) / Grid_Size));
  278.     Pos[1] = SGN(Pos[1]) * Grid_Size * ( (int)((ABS(Pos[1]) + Size2) / Grid_Size));
  279.     Pos[2] = SGN(Pos[2]) * Grid_Size * ( (int)((ABS(Pos[2]) + Size2) / Grid_Size));
  280.  
  281. } /* Snap_To_Grid */
  282.  
  283. short Screen_To_World(int Screen_X, int Screen_Y, Vector_T Pos)
  284. /************************************************************************/
  285. /*                                                                      */
  286. /* Convert the screen coordinates (Screen_X, Screen_Y) to a world coor-    */
  287. /* dinate, and return id of the view where (Screen_X, Screen_Y) is.    */
  288. /*                                                                      */
  289. /* NOTICE: This function can only find two of the three world coordi-    */
  290. /*       nates. The third will not be modified by this routine.    */
  291. /*                                                                      */
  292. /************************************************************************/
  293. {
  294.     if ((What_Mask & What_X) &&
  295.     Screen_X >= Views[V_X].X_Min && 
  296.         Screen_X <= Views[V_X].X_Max &&
  297.         Screen_Y >= Views[V_X].Y_Min && 
  298.     Screen_Y <= Views[V_X].Y_Max) {      /* View X: Y-Z    */
  299.  
  300.     Pos[1] = (Screen_X - Views[V_X].X_Center) / X_Scale_Factor + 
  301.                                     Offset[1];
  302.     Pos[2] = (Views[V_X].Y_Center - Screen_Y) / Y_Scale_Factor + 
  303.                                     Offset[2];
  304.     return(V_X);
  305.  
  306.     } /* if */
  307.  
  308.     if ((What_Mask & What_Y) &&
  309.     Screen_X >= Views[V_Y].X_Min &&  
  310.         Screen_X <= Views[V_Y].X_Max &&
  311.     Screen_Y >= Views[V_Y].Y_Min && 
  312.     Screen_Y <= Views[V_Y].Y_Max) {     /* View Y: X-Z    */
  313.  
  314.     Pos[0] = (Screen_X - Views[V_Y].X_Center) / X_Scale_Factor + 
  315.                                     Offset[0];
  316.     Pos[2] = (Views[V_Y].Y_Center - Screen_Y) / Y_Scale_Factor + 
  317.                                     Offset[2];
  318.     return(V_Y);
  319.  
  320.     } /* if */
  321.  
  322.     if ((What_Mask & What_Z) &&
  323.     Screen_X >= Views[V_Z].X_Min &&  
  324.         Screen_X <= Views[V_Z].X_Max &&
  325.         Screen_Y >= Views[V_Z].Y_Min && 
  326.     Screen_Y <= Views[V_Z].Y_Max) {      /* View Z: X-Y    */
  327.  
  328.     Pos[0] = (Screen_X - Views[V_Z].X_Center) / X_Scale_Factor + 
  329.                                     Offset[0];
  330.     Pos[1] = (Views[V_Z].Y_Center - Screen_Y) / Y_Scale_Factor + 
  331.                                     Offset[1];
  332.     return(V_Z);
  333.  
  334.     } /* if */
  335.  
  336.     if ((What_Mask & What_P) &&
  337.      Screen_X >= Views[V_P].X_Min && 
  338.         Screen_X <= Views[V_P].X_Max &&
  339.     Screen_Y >= Views[V_P].Y_Min && 
  340.     Screen_Y <= Views[V_P].Y_Max) {      /* View P: Persp*/
  341.  
  342.     /* Points can't be selected in persp view (yet) */
  343.     return(-1);
  344.  
  345.     } /* if */
  346.  
  347.     return(-1);
  348.  
  349. } /* Screen_To_World */
  350.  
  351. void World_To_Screen(Vector_T Pos, short *X0, short *Y0, 
  352.                        short *X1, short *Y1, 
  353.                    short *X2, short *Y2)
  354. /************************************************************************/
  355. /*                                                                      */
  356. /* Convert the world coordinate in Pos to screen coordinates for the     */
  357. /* three 'flat' views.                            */
  358. /*                                                                      */
  359. /* This function is called all the time, so it is a good place for opti-*/
  360. /* mization.                                */
  361. /*                                                                      */
  362. /************************************************************************/
  363. {
  364.     Vector_T    P;
  365.  
  366.     Vec3Op(P, =, Pos, -, Offset);
  367.  
  368.     *X0 = Views[V_X].X_Center + P[1] * X_Scale_Factor;    /* X : Y - Z */
  369.     *Y0 = Views[V_X].Y_Center - P[2] * Y_Scale_Factor;
  370.  
  371.     *X1 = Views[V_Y].X_Center + P[0] * X_Scale_Factor;    /* Y : X - Z */
  372.     *Y1 = Views[V_Y].Y_Center - P[2] * Y_Scale_Factor;
  373.  
  374.     *X2 = Views[V_Z].X_Center + P[0] * X_Scale_Factor;    /* Z : X - Y */
  375.     *Y2 = Views[V_Z].Y_Center - P[1] * Y_Scale_Factor;
  376.  
  377. } /* World_To_Screen */
  378.  
  379. void World_To_Persp(Vector_T Pos, short *X, short *Y)
  380. /************************************************************************/
  381. /*                                                                      */
  382. /* Convert the world coordinate in Pos to screen coordinates for the     */
  383. /* perspective view.                            */
  384. /*                                                                      */
  385. /* This function is called all the time, so it is a good place for opti-*/
  386. /* mization.                                */
  387. /*                                                                      */
  388. /************************************************************************/
  389. {
  390.     Vector_T    P, RP;
  391.  
  392.     Vec3Op(P, =, Pos, -, Offset);
  393.  
  394.     Matrix_MultV(RP, M_Rotation, P);
  395.  
  396.     *X = Views[V_P].X_Center +  RP[0] * X_Scale_Factor;
  397.     *Y = Views[V_P].Y_Center -  RP[2] * Y_Scale_Factor;
  398.  
  399. } /* World_To_Persp */
  400.  
  401. void Unmark_All()
  402. /************************************************************************/
  403. /*                                                                      */
  404. /* Unmark all splines, knots and points.                */
  405. /*                                                                      */
  406. /************************************************************************/
  407. {
  408.     short    i;
  409.     short    Point_Id;
  410.     Spline_T *Spline;
  411.     Knot_T   *Knot;
  412.  
  413.  
  414.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  415.  
  416.     if (Spline->Nbr_Knots > 0) {
  417.  
  418.         Do_Unmark(*Spline);
  419.  
  420.         for (i = 0, Knot = Spline->First; 
  421.          i < Spline->Nbr_Knots; i++, Knot = Knot->Next) 
  422.                     Do_Unmark(*Knot);
  423.     } /* if */
  424.  
  425.     } /* for */
  426.  
  427.     for (Point_Id = 0; Point_Id < Max_Nbr_Points; Point_Id++) 
  428.                     Do_Unmark(Points[Point_Id]);
  429.  
  430. } /* Unmark_All */
  431.  
  432. void Mark_Selected_Segments()
  433. /************************************************************************/
  434. /*                                                                      */
  435. /* Mark the currently selected segments.                */
  436. /*                                                                      */
  437. /************************************************************************/
  438. {
  439.     Knot_T      *Knot, *Begin_Knot, *End_Knot;
  440.  
  441.     Unmark_All();
  442.  
  443.     if (Select_Spline == NULL || Select_Knot == NULL) return;
  444.  
  445.     if (Select_Spline->Nbr_Knots < 2) return;
  446.  
  447.     if (Select_Spline->Nbr_Knots < 5) {
  448.  
  449.     Begin_Knot = Select_Spline->First;
  450.     if (Select_Spline->Loop) 
  451.          End_Knot   = Select_Spline->Last->Next;
  452.     else End_Knot   = Select_Spline->Last;
  453.  
  454.     } else {
  455.  
  456.     Begin_Knot = Select_Knot;
  457.     if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
  458.     if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
  459.  
  460.     End_Knot = Select_Knot;
  461.     if (End_Knot->Next) End_Knot = End_Knot->Next;
  462.     End_Knot = End_Knot->Next;
  463.  
  464.     } /* if .. else .. */
  465.  
  466.         /* Loop from Begin_Knot to End_Knot (exclusive)    */
  467.  
  468.     Knot = Begin_Knot;
  469.     do {
  470.  
  471.     Do_Mark(*Knot);
  472.     Knot = Knot->Next;
  473.  
  474.     } while (Knot != End_Knot);
  475.  
  476. } /* Mark_Selected_Segments */
  477.  
  478. void Mark_Connected_Segments(short Point_Id)
  479. /************************************************************************/
  480. /*                                                                      */
  481. /* Mark segments connected to point Point_Id.                */
  482. /*                                                                      */
  483. /************************************************************************/
  484. {
  485.     Spline_T    *Spline;
  486.     Knot_T    *K, *Knot, *Begin_Knot, *End_Knot;
  487.     short    i;
  488.  
  489.     if (!Is_Point_Id_Ok(Point_Id)) return;
  490.  
  491.     Unmark_All();
  492.  
  493.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  494.  
  495.     if (Spline->Nbr_Knots < 2) continue;
  496.  
  497.     Knot = NULL;
  498.     for (i = 0, K = Spline->First; i < Spline->Nbr_Knots; 
  499.                         i++, K = K->Next)
  500.        if (K->Point_Id == Point_Id) Knot = K;
  501.  
  502.     if (Knot == NULL) continue;
  503.  
  504.  
  505.         if (Spline->Nbr_Knots < 5) {
  506.  
  507.         Begin_Knot = Spline->First;
  508.         if (Spline->Loop) End_Knot = Spline->Last->Next;
  509.         else            End_Knot = Spline->Last;
  510.  
  511.         } else {
  512.  
  513.         Begin_Knot = Knot;
  514.         if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
  515.         if (Begin_Knot->Previous) Begin_Knot = Begin_Knot->Previous;
  516.  
  517.         End_Knot = Knot;
  518.         if (End_Knot->Next) End_Knot = End_Knot->Next;
  519.         End_Knot = End_Knot->Next;
  520.  
  521.     } /* if .. else .. */
  522.  
  523.         /* Loop from Begin_Knot to End_Knot (exclusive)    */
  524.  
  525.         Knot = Begin_Knot;
  526.         do {
  527.  
  528.         Do_Mark(*Knot);
  529.         Knot = Knot->Next;
  530.  
  531.         } while (Knot != End_Knot);
  532.  
  533.     } /* for */
  534.  
  535. } /* Mark_Connected_Segments */
  536.  
  537. void Compute_Segment(Spline_T *Spline, Knot_T *Knot)
  538. /************************************************************************/
  539. /*                                                                      */
  540. /* Compute a spline segment.                        */
  541. /*                                                                      */
  542. /* This function is using a brute force iterative evaluation, it would    */
  543. /* be much better to use a forward difference method as described in    */
  544. /* Computer Graphics p. 511 - 514.                    */
  545. /* Oh well, maybe another time...                    */
  546. /*                                                                      */
  547. /************************************************************************/
  548. {
  549.     Matrix4_T    M_Precomp;
  550.     Vector4_T    Pos;
  551.     double     Step_T;
  552.     double     T;
  553.     Byte_T    NX, NY, NZ, NP;
  554.  
  555.     NX = NY = NZ = NP = 0;
  556.  
  557.     if (Spline->Nbr_Knots < 2) return;
  558.  
  559.     Step_T = 1.0 / Spline_Resolution;
  560.  
  561.     Precompute_Kochanek_Bartels(M_Precomp, Spline, Knot);
  562.  
  563.  
  564.     for (T = 0.0; T <= 1.0; T += Step_T) {
  565.  
  566.     Compute_Position(Pos, T, M_Precomp);
  567.  
  568.     World_To_Screen(Pos,&Knot->ViewX[NX][0],  &Knot->ViewX[NX][1],
  569.                 &Knot->ViewY[NY][0],  &Knot->ViewY[NY][1],
  570.                 &Knot->ViewZ[NZ][0],  &Knot->ViewZ[NZ][1]);
  571.  
  572.     World_To_Persp(Pos, &Knot->ViewP[NP][0], &Knot->ViewP[NP][1]);
  573.  
  574.         /* Simple clipping: The line must be entirely within the*/
  575.         /* views.                        */
  576.  
  577.     if (Views[V_X].X_Min < Knot->ViewX[NX][0] &&
  578.         Views[V_X].Y_Min < Knot->ViewX[NX][1] &&
  579.         Views[V_X].X_Max > Knot->ViewX[NX][0] &&
  580.         Views[V_X].Y_Max > Knot->ViewX[NX][1]) NX++;
  581.  
  582.     if (Views[V_Y].X_Min < Knot->ViewY[NY][0] &&
  583.         Views[V_Y].Y_Min < Knot->ViewY[NY][1] &&
  584.         Views[V_Y].X_Max > Knot->ViewY[NY][0] &&
  585.         Views[V_Y].Y_Max > Knot->ViewY[NY][1]) NY++;
  586.  
  587.     if (Views[V_Z].X_Min < Knot->ViewZ[NZ][0] &&
  588.         Views[V_Z].Y_Min < Knot->ViewZ[NZ][1] &&
  589.         Views[V_Z].X_Max > Knot->ViewZ[NZ][0] &&
  590.         Views[V_Z].Y_Max > Knot->ViewZ[NZ][1]) NZ++;
  591.  
  592.     if (Views[V_P].X_Min < Knot->ViewP[NP][0] &&
  593.         Views[V_P].Y_Min < Knot->ViewP[NP][1] &&
  594.         Views[V_P].X_Max > Knot->ViewP[NP][0] &&
  595.         Views[V_P].Y_Max > Knot->ViewP[NP][1]) NP++;
  596.  
  597.  
  598.     } /* for */
  599.  
  600.     Knot->NX = NX;
  601.     Knot->NY = NY;
  602.     Knot->NZ = NZ;
  603.     Knot->NP = NP;
  604.  
  605. } /* Compute_Segment */
  606.  
  607.  
  608. void Compute_Marked_Segments()
  609. /************************************************************************/
  610. /*                                                                      */
  611. /* Compute vectors for all marked segments.                */
  612. /*                                                                      */
  613. /************************************************************************/
  614. {
  615.     int        i;
  616.     Spline_T    *Spline;
  617.     Knot_T    *Knot;
  618.     int        Nbr_Knots;
  619.  
  620.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  621.  
  622.         if ((Nbr_Knots = Spline->Nbr_Knots) < 1) continue;
  623.  
  624.     for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  625.                         i++, Knot = Knot->Next) {
  626.     
  627.         if (Is_Marked(*Spline) || Is_Marked(*Knot) ) {
  628.  
  629.             Compute_Segment(Spline, Knot);
  630.  
  631.          } /* if */
  632.  
  633.     } /* for */
  634.  
  635.  
  636.     } /* for */
  637.  
  638. } /* Compute_Marked_Segments */
  639.  
  640.  
  641. void Compute_Spline(Spline_T *Spline)
  642. /************************************************************************/
  643. /*                                                                      */
  644. /* Compute vectors for a given spline.                    */
  645. /*                                                                      */
  646. /************************************************************************/
  647. {
  648.     Knot_T    *Knot;
  649.     int        i;
  650.     int          Nbr_Knots;
  651.  
  652.     if ((Nbr_Knots = Spline->Nbr_Knots) < 1) return;
  653.  
  654.  
  655.     for (i = 0, Knot = Spline->First; i < Nbr_Knots; i++, Knot = Knot->Next) {
  656.  
  657.     if (!Is_Hidden(Points[Knot->Point_Id]))
  658.             Compute_Segment(Spline, Knot);
  659.  
  660.     } /* for */
  661.  
  662. } /* Compute_Spline */
  663.  
  664.  
  665. void Compute_Splines()
  666. /************************************************************************/
  667. /*                                                                      */
  668. /* Compute vectors for all splines.                          */
  669. /*                                                                      */
  670. /************************************************************************/
  671. {
  672.     Spline_T *Spline;
  673.  
  674.     Set_Pointer(TRUE);
  675.  
  676.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  677.  
  678.     Compute_Spline(Spline);
  679.  
  680.     } /* for */
  681.  
  682.     Set_Pointer(FALSE);
  683.  
  684. } /* Compute_Splines */
  685.  
  686. void Draw_Segment(Spline_T *Spline, Knot_T *Knot, int Pen, long What)
  687. /************************************************************************/
  688. /*                                                                      */
  689. /* Draw a spline segment.                        */
  690. /*                                                                      */
  691. /* The segment must have been 'computed' before calling this function.    */
  692. /*                                                                      */
  693. /************************************************************************/
  694. {
  695.     Knot_T    *Next_Knot;
  696.  
  697.     What &= What_Mask;
  698.  
  699.     /* If either of the endpoints is hidden,         */
  700.     /* then don't draw the segment                 */
  701.  
  702.     Next_Knot = Knot->Next;
  703.     if (Next_Knot == NULL) return;
  704.  
  705.     if (Is_Hidden(Points[Next_Knot->Point_Id]) || 
  706.     Is_Hidden(Points[Knot->Point_Id]) ) return;
  707.  
  708.     SetAPen(Windows[Id_Active_Window].RastPort, Pen);
  709.  
  710.  
  711.     if ( (What & What_SX) && (Knot->NX > 1) ) {
  712.            Move(Windows[Id_Active_Window].RastPort, Knot->ViewX[0][0], 
  713.                        Knot->ViewX[0][1]);
  714.     PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NX-1, 
  715.                     &Knot->ViewX[1][0]);
  716.     } /* if */
  717.  
  718.     if ( (What & What_SY) && (Knot->NY > 1) ) {
  719.     Move(Windows[Id_Active_Window].RastPort, Knot->ViewY[0][0], 
  720.                        Knot->ViewY[0][1]);
  721.     PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NY-1, 
  722.                     &Knot->ViewY[1][0]);
  723.     } /* if */
  724.  
  725.     if ( (What & What_SZ) && (Knot->NZ > 1) ) {
  726.     Move(Windows[Id_Active_Window].RastPort, Knot->ViewZ[0][0], 
  727.                            Knot->ViewZ[0][1]);
  728.     PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NZ-1, 
  729.                     &Knot->ViewZ[1][0]);
  730.     } /* if */
  731.  
  732.     if ( (What & What_SP) && (Knot->NP > 1) ) {
  733.  
  734.            Move(Windows[Id_Active_Window].RastPort, Knot->ViewP[0][0], 
  735.                        Knot->ViewP[0][1]);
  736.     PolyDraw(Windows[Id_Active_Window].RastPort, Knot->NP-1, 
  737.                     &Knot->ViewP[1][0]);
  738.  
  739.     } /* if */
  740.  
  741. } /* Draw_Segment */
  742.  
  743. void Draw_Marked_Segments(Draw_Mode_T Mode, long What)
  744. /************************************************************************/
  745. /*                                                                      */
  746. /* Draw all marked segments.                        */
  747. /*                                                                      */
  748. /************************************************************************/
  749. {
  750.     Spline_T     *Spline;
  751.     Knot_T    *Knot;
  752.     int        i;
  753.     short    Nbr_Knots;
  754.     int        Pen;
  755.  
  756.     switch (Mode) {
  757.  
  758.     case DM_Normal: /* Normal draw */
  759.         Pen = Pen_Segment;
  760.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  761.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  762.         break;
  763.  
  764.     case DM_Erase: /* Delete       */
  765.         Pen = Pen_Background;
  766.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  767.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  768.         break;
  769.  
  770.     case DM_Plane: /* Draw in plane 3 */
  771.         Pen = Pen_Plane;
  772.         Windows[Id_Active_Window].RastPort->Mask    = 0x08;
  773.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  774.         break;
  775.  
  776.     } /* switch */
  777.  
  778.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  779.  
  780.     if ((Nbr_Knots = Spline->Nbr_Knots) < 2) continue;
  781.  
  782.     for (i = 0, Knot = Spline->First; 
  783.          i < Nbr_Knots && Knot->Next != NULL; i++, Knot = Knot->Next) {
  784.  
  785.         if (Is_Marked(*Spline) || Is_Marked(*Knot) ) {
  786.  
  787.             if (Mode == DM_Normal) {
  788.  
  789.                 Pen = Pen_Segment;
  790.  
  791.                 if (Select_Spline == Spline) {
  792.  
  793.                if (Select_Knot == Knot || 
  794.                            Select_Knot == Knot->Next) Pen = Pen_Segment_Selected;
  795.  
  796.                 } /* if */
  797.  
  798.             } /* if */
  799.             Draw_Segment(Spline, Knot, Pen, What);
  800.             Draw_Knot(Spline, Knot,  Mode, What);
  801.  
  802.         } /* if */
  803.  
  804.     } /* for */
  805.  
  806.     } /* for */
  807.  
  808.     Draw_Knot(Select_Spline, Select_Knot,  Mode, What);
  809.  
  810. } /* Draw_Marked_Segments */
  811.  
  812. void Draw_Spline(Spline_T *Spline , Draw_Mode_T Mode, long What)
  813. /************************************************************************/
  814. /*                                                                      */
  815. /* Draw a spline.                            */
  816. /*                                                                      */
  817. /************************************************************************/
  818. {
  819.     Knot_T    *Knot;
  820.     int        i;
  821.     short    Nbr_Knots;
  822.     int        Pen;
  823.  
  824.     if (Spline == NULL) return;
  825.     if ((Nbr_Knots = Spline->Nbr_Knots) < 1) return;
  826.  
  827.     switch (Mode) {
  828.  
  829.     case DM_Normal: /* Normal draw */
  830.         Pen = Pen_Segment;
  831.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  832.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  833.         break;
  834.  
  835.     case DM_Erase: /* Delete       */
  836.         Pen = Pen_Background;
  837.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  838.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  839.         break;
  840.  
  841.     case DM_Plane: /* Draw in plane 3 */
  842.         Pen = Pen_Plane;
  843.         Windows[Id_Active_Window].RastPort->Mask    = 0x08;
  844.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  845.         break;
  846.  
  847.     } /* switch */
  848.  
  849.  
  850.     for (i = 0, Knot = Spline->First; 
  851.      i < Nbr_Knots && Knot->Next != NULL; i++, Knot = Knot->Next) {
  852.  
  853.     if (Mode == DM_Normal) {
  854.  
  855.         Pen = Pen_Segment;
  856.  
  857.         if (Select_Spline == Spline) {
  858.  
  859.            if (Select_Knot == Knot || 
  860.                    Select_Knot == Knot->Next)  Pen = Pen_Segment_Selected;
  861.  
  862.         } /* if */
  863.  
  864.     } /* if */
  865.  
  866.     Draw_Segment(Spline, Knot, Pen, What);
  867.         Draw_Knot(Spline, Knot, Mode, What);
  868.  
  869.  
  870.     } /* for */
  871.  
  872.     Draw_Knot(Spline, Knot, Mode, What);
  873.  
  874. } /* Draw_Spline */
  875.  
  876.  
  877. void Draw_Splines(Draw_Mode_T Mode, long What)
  878. /************************************************************************/
  879. /*                                                                      */
  880. /* Draw all splines.                            */
  881. /*                                                                      */
  882. /************************************************************************/
  883. {
  884.     Spline_T *Spline;
  885.  
  886.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  887.  
  888.     Draw_Spline(Spline, Mode, What);
  889.  
  890.     } /* for */
  891.  
  892. } /* Draw_Splines */
  893.  
  894. void Draw_Origin(Draw_Mode_T Mode, long What)
  895. /************************************************************************/
  896. /*                                                                      */
  897. /* Draw the origin.                            */
  898. /*                                                                      */
  899. /************************************************************************/
  900. {
  901.     short     Xx0, Yx0, Xy0, Yy0, Xz0, Yz0, Xp0, Yp0;
  902.     short     Xx1, Yx1, Xy1, Yy1, Xz1, Yz1, Xp1, Yp1;
  903.     Vector_T    Vector;
  904.     double    Size;
  905.     int        Pen;
  906.  
  907.     What &= What_Mask;
  908.  
  909.     switch (Mode) {
  910.  
  911.     case DM_Normal:
  912.     Pen = Pen_Segment;
  913.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  914.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  915.     break;
  916.  
  917.     case DM_Erase:
  918.     Pen = Pen_Background;
  919.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
  920.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  921.     break;
  922.  
  923.     case DM_Plane:
  924.     Pen = Pen_Plane;
  925.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  926.         Windows[Id_Active_Window].RastPort->Mask    = 0x08;
  927.     break;
  928.  
  929.     } /* switch */
  930.  
  931.     World_To_Screen(Origin, &Xx0, &Yx0, &Xy0, &Yy0, &Xz0, &Yz0);
  932.     World_To_Persp(Origin,  &Xp0, &Yp0);
  933.  
  934.     Size = 10.0 / Y_Scale_Factor;
  935.  
  936.                         /* X - Axis    */
  937.     Vector[0] = Origin[0] + Size;
  938.     Vector[1] = Origin[1];
  939.     Vector[2] = Origin[2];
  940.  
  941.     World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
  942.     World_To_Persp(Vector,  &Xp1, &Yp1);
  943.  
  944.     if (Mode == DM_Normal) Pen = Pen_Axis_X;
  945.     SetAPen(Windows[Id_Active_Window].RastPort, Pen);
  946.     
  947.     if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
  948.     if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
  949.     if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
  950.     if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);
  951.  
  952.                         /* Y - Axis    */
  953.     Vector[0] = Origin[0];
  954.     Vector[1] = Origin[1] + Size;
  955.     Vector[2] = Origin[2];
  956.  
  957.     World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
  958.     World_To_Persp(Vector,  &Xp1, &Yp1);
  959.  
  960.     if (Mode == DM_Normal) Pen = Pen_Axis_Y;
  961.     SetAPen(Windows[Id_Active_Window].RastPort, Pen);
  962.  
  963.     if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
  964.     if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
  965.     if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
  966.     if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);
  967.  
  968.                         /* Z - Axis    */
  969.     Vector[0] = Origin[0];
  970.     Vector[1] = Origin[1];
  971.     Vector[2] = Origin[2] + Size;
  972.  
  973.     World_To_Screen(Vector, &Xx1, &Yx1, &Xy1, &Yy1, &Xz1, &Yz1);
  974.     World_To_Persp(Vector,  &Xp1, &Yp1);
  975.  
  976.     if (Mode == DM_Normal) Pen = Pen_Axis_Z;
  977.     SetAPen(Windows[Id_Active_Window].RastPort, Pen);
  978.  
  979.     if (What & What_X) ViewClipDrawLine(V_X, Xx0, Yx0, Xx1, Yx1);
  980.     if (What & What_Y) ViewClipDrawLine(V_Y, Xy0, Yy0, Xy1, Yy1);
  981.     if (What & What_Z) ViewClipDrawLine(V_Z, Xz0, Yz0, Xz1, Yz1);
  982.     if (What & What_P) ViewClipDrawLine(V_P, Xp0, Yp0, Xp1, Yp1);
  983.  
  984. } /* Draw_Origin */
  985.  
  986. void Draw_Grid(long What)
  987. /************************************************************************/
  988. /*                                                                      */
  989. /* Draw the grid if it is active.                    */
  990. /*                                                                      */
  991. /************************************************************************/
  992. {
  993.     Vector_T     Grid;
  994.     short    X0x, Y0x, X0y, Y0y, X0z, Y0z;    
  995.     short    X1x, Y1x, X1y, Y1y, X1z, Y1z;    
  996.     short    X, Y;
  997.     int        Dx, Dy;
  998.     long    i;
  999.  
  1000.     if (!Grid_Active) return;
  1001.  
  1002.     Vec2Op(Grid, =, Offset);
  1003.  
  1004.     Snap_To_Grid(Grid);
  1005.     World_To_Screen(Grid, &X0x, &Y0x, &X0y, &Y0y, &X0z, &Y0z);    
  1006.  
  1007.     Grid[0] = Offset[0] + Grid_Size;
  1008.     Grid[1] = Offset[1] + Grid_Size;
  1009.     Grid[2] = Offset[2] + Grid_Size;
  1010.     Snap_To_Grid(Grid);
  1011.     World_To_Screen(Grid, &X1x, &Y1x, &X1y, &Y1y, &X1z, &Y1z);    
  1012.  
  1013.     Dx = ABS(X1x - X0x);    /* Size of grid in screen coordinates */
  1014.     Dy = ABS(Y1x - Y0x);
  1015.  
  1016.     if (Dx < 5 || Dx > 100 || Dy < 5 || Dy > 100) return;
  1017.  
  1018.  
  1019.  
  1020.     i = (X0x - Views[V_X].X_Min) / Dx; X0x -= (i * Dx);
  1021.     i = (Y0x - Views[V_X].Y_Min) / Dy; Y0x -= (i * Dy);
  1022.  
  1023.     i = (X0y - Views[V_Y].X_Min) / Dx; X0y -= (i * Dx);
  1024.     i = (Y0y - Views[V_Y].Y_Min) / Dy; Y0y -= (i * Dy);
  1025.  
  1026.     i = (X0z - Views[V_Z].X_Min) / Dx; X0z -= (i * Dx);
  1027.     i = (Y0z - Views[V_Z].Y_Min) / Dy; Y0z -= (i * Dy);
  1028.  
  1029.     SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  1030.     Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  1031.     SetAPen(Windows[Id_Active_Window].RastPort, Pen_Grid);
  1032.  
  1033.     What &= What_Mask;
  1034.  
  1035.     if (What & What_X) {
  1036.  
  1037.     for (X = X0x; X < Views[V_X].X_Max; X += Dx) {
  1038.         for (Y = Y0x; Y < Views[V_X].Y_Max; Y += Dy) {
  1039.         WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
  1040.         }
  1041.     }
  1042.  
  1043.     } /* if */
  1044.  
  1045.     if (What & What_Y) {
  1046.  
  1047.     for (X = X0y; X < Views[V_Y].X_Max; X += Dx) {
  1048.         for (Y = Y0y; Y < Views[V_Y].Y_Max; Y += Dy) {
  1049.         WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
  1050.         }
  1051.     }
  1052.     } /* if */
  1053.  
  1054.     if (What & What_Z) {
  1055.  
  1056.     for (X = X0z; X < Views[V_Z].X_Max; X += Dx) {
  1057.         for (Y = Y0z; Y < Views[V_Z].Y_Max; Y += Dy) {
  1058.         WritePixel(Windows[Id_Active_Window].RastPort, X, Y);
  1059.         }
  1060.     }
  1061.     } /* if */
  1062.  
  1063. } /* Draw_Grid */
  1064.  
  1065. void Draw_Box(Vector_T Min_Pos, Vector_T Max_Pos, Vector_T R_Vector,
  1066.                     Draw_Mode_T Mode, long What)
  1067. /************************************************************************/
  1068. /*                                                                      */
  1069. /* Draw a box after it has been rotated as defined by R_Vector.        */
  1070. /* If R_Vector == NULL no rotation is performed.            */
  1071. /*                                                                      */
  1072. /************************************************************************/
  1073. {
  1074.     Matrix_T    R_Matrix;
  1075.     Vector_T    Tmp;
  1076.     Vector_T    Corners[8];
  1077.     short     X[8][4], Y[8][4];
  1078.     int        Pen;
  1079.     int        i;
  1080.  
  1081.  
  1082.     What &= What_Mask;
  1083.  
  1084.     switch (Mode) {
  1085.  
  1086.     case DM_Normal:
  1087.         Pen = Pen_Segment;
  1088.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  1089.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  1090.     break;
  1091.  
  1092.     case DM_Erase:
  1093.         Pen = Pen_Background;
  1094.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
  1095.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  1096.     break;
  1097.  
  1098.     case DM_Plane:
  1099.         Pen = Pen_Plane;
  1100.         Windows[Id_Active_Window].RastPort->Mask    = 0x08;
  1101.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  1102.     break;
  1103.  
  1104.     } /* switch */
  1105.  
  1106.     SetAPen(Windows[Id_Active_Window].RastPort, Pen);
  1107.  
  1108.  
  1109.     /* The eight corners:    */
  1110.     Vec3Scalar(Corners[0], = , Min_Pos[0], Min_Pos[1], Min_Pos[2]);
  1111.     Vec3Scalar(Corners[1], = , Max_Pos[0], Min_Pos[1], Min_Pos[2]);
  1112.     Vec3Scalar(Corners[2], = , Min_Pos[0], Max_Pos[1], Min_Pos[2]);
  1113.     Vec3Scalar(Corners[3], = , Max_Pos[0], Max_Pos[1], Min_Pos[2]);
  1114.     Vec3Scalar(Corners[4], = , Min_Pos[0], Min_Pos[1], Max_Pos[2]);
  1115.     Vec3Scalar(Corners[5], = , Max_Pos[0], Min_Pos[1], Max_Pos[2]);
  1116.     Vec3Scalar(Corners[6], = , Min_Pos[0], Max_Pos[1], Max_Pos[2]);
  1117.     Vec3Scalar(Corners[7], = , Max_Pos[0], Max_Pos[1], Max_Pos[2]);
  1118.  
  1119.     if (R_Vector != NULL) {
  1120.  
  1121.          Compute_Rotation_Matrix(R_Matrix, R_Vector);
  1122.  
  1123.     for (i = 0; i < 8; i++) {
  1124.  
  1125.         Vec3Op(Corners[i], =, Corners[i], -, Origin);
  1126.             Matrix_MultV(Tmp, R_Matrix, Corners[i]);
  1127.         Vec3Op(Corners[i], =, Tmp, +, Origin);
  1128.  
  1129.         } /* for */
  1130.  
  1131.     } /* if */
  1132.  
  1133.     if (What & What_K3)
  1134.     for (i = 0; i < 8; i++)
  1135.             World_To_Screen(Corners[i], &X[i][0], &Y[i][0], 
  1136.                     &X[i][1], &Y[i][1], 
  1137.                     &X[i][2], &Y[i][2]);
  1138.     if (What & What_KP)
  1139.     for (i = 0; i < 8; i++)
  1140.             World_To_Persp(Corners[i], &X[i][3], &Y[i][3]);
  1141.  
  1142.  
  1143.     if (What & What_KX) {
  1144.  
  1145.  
  1146.     ViewClipDrawLine(V_X, X[0][0], Y[0][0], X[1][0], Y[1][0]);
  1147.     ViewClipDrawLine(V_X, X[1][0], Y[1][0], X[3][0], Y[3][0]);
  1148.     ViewClipDrawLine(V_X, X[3][0], Y[3][0], X[2][0], Y[2][0]);
  1149.     ViewClipDrawLine(V_X, X[2][0], Y[2][0], X[0][0], Y[0][0]);
  1150.  
  1151.     ViewClipDrawLine(V_X, X[4][0], Y[4][0], X[5][0], Y[5][0]);
  1152.     ViewClipDrawLine(V_X, X[5][0], Y[5][0], X[7][0], Y[7][0]);
  1153.     ViewClipDrawLine(V_X, X[7][0], Y[7][0], X[6][0], Y[6][0]);
  1154.     ViewClipDrawLine(V_X, X[6][0], Y[6][0], X[4][0], Y[4][0]);
  1155.  
  1156.     ViewClipDrawLine(V_X, X[0][0], Y[0][0], X[4][0], Y[4][0]);
  1157.     ViewClipDrawLine(V_X, X[1][0], Y[1][0], X[5][0], Y[5][0]);
  1158.     ViewClipDrawLine(V_X, X[2][0], Y[2][0], X[6][0], Y[6][0]);
  1159.     ViewClipDrawLine(V_X, X[3][0], Y[3][0], X[7][0], Y[7][0]);
  1160.  
  1161.     } /* if */
  1162.  
  1163.     if (What & What_KY) {
  1164.  
  1165.     ViewClipDrawLine(V_Y, X[0][1], Y[0][1], X[1][1], Y[1][1]);
  1166.     ViewClipDrawLine(V_Y, X[1][1], Y[1][1], X[3][1], Y[3][1]);
  1167.     ViewClipDrawLine(V_Y, X[3][1], Y[3][1], X[2][1], Y[2][1]);
  1168.     ViewClipDrawLine(V_Y, X[2][1], Y[2][1], X[0][1], Y[0][1]);
  1169.  
  1170.     ViewClipDrawLine(V_Y, X[4][1], Y[4][1], X[5][1], Y[5][1]);
  1171.     ViewClipDrawLine(V_Y, X[5][1], Y[5][1], X[7][1], Y[7][1]);
  1172.     ViewClipDrawLine(V_Y, X[7][1], Y[7][1], X[6][1], Y[6][1]);
  1173.     ViewClipDrawLine(V_Y, X[6][1], Y[6][1], X[4][1], Y[4][1]);
  1174.  
  1175.     ViewClipDrawLine(V_Y, X[0][1], Y[0][1], X[4][1], Y[4][1]);
  1176.     ViewClipDrawLine(V_Y, X[1][1], Y[1][1], X[5][1], Y[5][1]);
  1177.     ViewClipDrawLine(V_Y, X[2][1], Y[2][1], X[6][1], Y[6][1]);
  1178.     ViewClipDrawLine(V_Y, X[3][1], Y[3][1], X[7][1], Y[7][1]);
  1179.  
  1180.     } /* if */
  1181.  
  1182.     if (What & What_KZ) {
  1183.  
  1184.     ViewClipDrawLine(V_Z, X[0][2], Y[0][2], X[1][2], Y[1][2]);
  1185.     ViewClipDrawLine(V_Z, X[1][2], Y[1][2], X[3][2], Y[3][2]);
  1186.     ViewClipDrawLine(V_Z, X[3][2], Y[3][2], X[2][2], Y[2][2]);
  1187.     ViewClipDrawLine(V_Z, X[2][2], Y[2][2], X[0][2], Y[0][2]);
  1188.  
  1189.     ViewClipDrawLine(V_Z, X[4][2], Y[4][2], X[5][2], Y[5][2]);
  1190.     ViewClipDrawLine(V_Z, X[5][2], Y[5][2], X[7][2], Y[7][2]);
  1191.     ViewClipDrawLine(V_Z, X[7][2], Y[7][2], X[6][2], Y[6][2]);
  1192.     ViewClipDrawLine(V_Z, X[6][2], Y[6][2], X[4][2], Y[4][2]);
  1193.  
  1194.     ViewClipDrawLine(V_Z, X[0][2], Y[0][2], X[4][2], Y[4][2]);
  1195.     ViewClipDrawLine(V_Z, X[1][2], Y[1][2], X[5][2], Y[5][2]);
  1196.     ViewClipDrawLine(V_Z, X[2][2], Y[2][2], X[6][2], Y[6][2]);
  1197.     ViewClipDrawLine(V_Z, X[3][2], Y[3][2], X[7][2], Y[7][2]);
  1198.  
  1199.     } /* if */
  1200.  
  1201.     if (What & What_KP) {
  1202.  
  1203.  
  1204.     ViewClipDrawLine(V_P, X[0][3], Y[0][3], X[1][3], Y[1][3]);
  1205.     ViewClipDrawLine(V_P, X[1][3], Y[1][3], X[3][3], Y[3][3]);
  1206.     ViewClipDrawLine(V_P, X[3][3], Y[3][3], X[2][3], Y[2][3]);
  1207.     ViewClipDrawLine(V_P, X[2][3], Y[2][3], X[0][3], Y[0][3]);
  1208.  
  1209.     ViewClipDrawLine(V_P, X[4][3], Y[4][3], X[5][3], Y[5][3]);
  1210.     ViewClipDrawLine(V_P, X[5][3], Y[5][3], X[7][3], Y[7][3]);
  1211.     ViewClipDrawLine(V_P, X[7][3], Y[7][3], X[6][3], Y[6][3]);
  1212.     ViewClipDrawLine(V_P, X[6][3], Y[6][3], X[4][3], Y[4][3]);
  1213.  
  1214.     ViewClipDrawLine(V_P, X[0][3], Y[0][3], X[4][3], Y[4][3]);
  1215.     ViewClipDrawLine(V_P, X[1][3], Y[1][3], X[5][3], Y[5][3]);
  1216.     ViewClipDrawLine(V_P, X[2][3], Y[2][3], X[6][3], Y[6][3]);
  1217.     ViewClipDrawLine(V_P, X[3][3], Y[3][3], X[7][3], Y[7][3]);
  1218.  
  1219.     } /* if */
  1220.  
  1221. } /* Draw_Box */
  1222.  
  1223. void Draw_Knot(Spline_T *Spline, Knot_T *Knot, Draw_Mode_T Mode, long What)
  1224. /************************************************************************/
  1225. /*                                                                      */
  1226. /* Draw a knot.                                */
  1227. /* Don't drow it in DM_Plane mode.                    */
  1228. /*                                                                      */
  1229. /************************************************************************/
  1230. {
  1231.     short     Xx, Yx, Xy, Yy, Xz, Yz, Xp, Yp;
  1232.     int         Point_Id;
  1233.     int        Pen;
  1234.  
  1235.     What &= What_Mask;
  1236.  
  1237.     if (Spline == NULL || Knot == NULL) return;
  1238.  
  1239.     Point_Id = Knot->Point_Id;
  1240.  
  1241.     if (Is_Hidden(Points[Point_Id])) return;
  1242.  
  1243.     switch (Mode) {
  1244.  
  1245.     case DM_Normal:
  1246.     if (Point_Id == Select_Point_Id)        Pen = Pen_Knot_Primary;
  1247.         else if (Is_Selected(Points[Point_Id])) Pen = Pen_Knot_Selected;
  1248.         else                               Pen = Pen_Knot;
  1249.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM1);
  1250.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  1251.     break;
  1252.  
  1253.     case DM_Erase:
  1254.         Pen = Pen_Background;
  1255.         SetDrMd(Windows[Id_Active_Window].RastPort, JAM2);
  1256.         Windows[Id_Active_Window].RastPort->Mask    = 0xff;
  1257.     break;
  1258.  
  1259.     case DM_Plane:
  1260.     return;
  1261.  
  1262.     } /* switch */
  1263.  
  1264.     SetAPen(Windows[Id_Active_Window].RastPort, Pen);
  1265.  
  1266.  
  1267.     if (What & What_K3)
  1268.         World_To_Screen(Points[Point_Id].Pos, &Xx, &Yx, &Xy, &Yy, &Xz, &Yz);
  1269.     if (What & What_KP)
  1270.         World_To_Persp(Points[Point_Id].Pos,  &Xp, &Yp);
  1271.  
  1272. #define DRAW_DOT
  1273. #ifdef DRAW_DOT
  1274.  
  1275.     /* Draw knots as dots    */
  1276.     if (What & What_KX) {
  1277.  
  1278.         /* Clipping */
  1279.     if (Views[V_X].X_Min < Xx && Views[V_X].Y_Min < Yx &&
  1280.         Views[V_X].X_Max > Xx && Views[V_X].Y_Max > Yx) {
  1281.  
  1282.  
  1283.         WritePixel(Windows[Id_Active_Window].RastPort, Xx, Yx);
  1284.  
  1285.     } /* if */
  1286.     } /* if */
  1287.  
  1288.     if (What & What_KY) {
  1289.     if (Views[V_Y].X_Min < Xy && Views[V_Y].Y_Min < Yy &&
  1290.         Views[V_Y].X_Max > Xy && Views[V_Y].Y_Max > Yy) {
  1291.  
  1292.         WritePixel(Windows[Id_Active_Window].RastPort, Xy, Yy);
  1293.  
  1294.     } /* if */
  1295.     } /* if */
  1296.  
  1297.     if (What & What_KZ) {
  1298.     if (Views[V_Z].X_Min < Xz && Views[V_Z].Y_Min < Yz &&
  1299.         Views[V_Z].X_Max > Xz && Views[V_Z].Y_Max > Yz) {
  1300.  
  1301.         WritePixel(Windows[Id_Active_Window].RastPort, Xz, Yz);
  1302.  
  1303.     } /* if */
  1304.  
  1305.     } /* if */
  1306.  
  1307.     if (What & What_KP) {
  1308.  
  1309.     if (Views[V_P].X_Min < Xp && Views[V_P].Y_Min < Yp &&
  1310.         Views[V_P].X_Max > Xp && Views[V_P].Y_Max > Yp) {
  1311.  
  1312.         WritePixel(Windows[Id_Active_Window].RastPort, Xp, Yp);
  1313.  
  1314.     } /* if */
  1315.  
  1316.     } /* if */
  1317.  
  1318. #else
  1319.  
  1320.     /* Draw knots as small crosses    */
  1321.     if (What & What_KX) {
  1322.  
  1323.  
  1324.         /* Clipping */
  1325.     if (Views[V_X].X_Min < Xx - 2 && Views[V_X].Y_Min < Yx - 2 &&
  1326.         Views[V_X].X_Max > Xx + 2 && Views[V_X].Y_Max > Yx + 2) {
  1327.  
  1328.         Move(Windows[Id_Active_Window].RastPort, Xx - 2, Yx);
  1329.         Draw(Windows[Id_Active_Window].RastPort, Xx + 2, Yx);
  1330.         Move(Windows[Id_Active_Window].RastPort, Xx    , Yx - 2);
  1331.         Draw(Windows[Id_Active_Window].RastPort, Xx    , Yx + 2);
  1332.  
  1333.     } /* if */
  1334.     } /* if */
  1335.  
  1336.     if (What & What_KY) {
  1337.     if (Views[V_Y].X_Min < Xy - 2 && Views[V_Y].Y_Min < Yy - 2 &&
  1338.         Views[V_Y].X_Max > Xy + 2 && Views[V_Y].Y_Max > Yy + 2) {
  1339.  
  1340.         Move(Windows[Id_Active_Window].RastPort, Xy - 2, Yy);
  1341.         Draw(Windows[Id_Active_Window].RastPort, Xy + 2, Yy);
  1342.         Move(Windows[Id_Active_Window].RastPort, Xy    , Yy - 2);
  1343.         Draw(Windows[Id_Active_Window].RastPort, Xy    , Yy + 2);
  1344.  
  1345.     } /* if */
  1346.     } /* if */
  1347.  
  1348.     if (What & What_KZ) {
  1349.     if (Views[V_Z].X_Min < Xz - 2 && Views[V_Z].Y_Min < Yz - 2 &&
  1350.         Views[V_Z].X_Max > Xz + 2 && Views[V_Z].Y_Max > Yz + 2) {
  1351.  
  1352.         Move(Windows[Id_Active_Window].RastPort, Xz - 2, Yz);
  1353.         Draw(Windows[Id_Active_Window].RastPort, Xz + 2, Yz);
  1354.         Move(Windows[Id_Active_Window].RastPort, Xz    , Yz - 2);
  1355.         Draw(Windows[Id_Active_Window].RastPort, Xz    , Yz + 2);
  1356.  
  1357.     } /* if */
  1358.  
  1359.     } /* if */
  1360.  
  1361.     if (What & What_KP) {
  1362.  
  1363.     if (Views[V_P].X_Min < Xp - 2 && Views[V_P].Y_Min < Yp - 2 &&
  1364.         Views[V_P].X_Max > Xp + 2 && Views[V_P].Y_Max > Yp + 2) {
  1365.  
  1366.         Move(Windows[Id_Active_Window].RastPort, Xp - 2, Yp);
  1367.         Draw(Windows[Id_Active_Window].RastPort, Xp + 2, Yp);
  1368.         Move(Windows[Id_Active_Window].RastPort, Xp    , Yp - 2);
  1369.         Draw(Windows[Id_Active_Window].RastPort, Xp    , Yp + 2);
  1370.  
  1371.     } /* if */
  1372.  
  1373.     } /* if */
  1374. #endif
  1375.  
  1376. } /* Draw_Knot */
  1377.  
  1378.  
  1379. void Draw_Knots(Draw_Mode_T Mode, long What)
  1380. /************************************************************************/
  1381. /*                                                                      */
  1382. /* Draw all knots.                            */
  1383. /*                                                                      */
  1384. /************************************************************************/
  1385. {
  1386.     int         i;
  1387.     Spline_T *Spline;
  1388.     Knot_T   *Knot;
  1389.  
  1390.     What &= What_Mask;
  1391.  
  1392.     if ( (What & What_K) == 0) return;
  1393.  
  1394.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  1395.  
  1396.         if (Spline->Nbr_Knots < 1) continue;
  1397.  
  1398.         for (i = 0, Knot = Spline->First; 
  1399.          i < Spline->Nbr_Knots; i++, Knot = Knot->Next) 
  1400.                 Draw_Knot(Spline, Knot, Mode, What);
  1401.  
  1402.     } /* for */
  1403.  
  1404. } /* Draw_Knots */
  1405.  
  1406. void Draw_All(long What)
  1407. /************************************************************************/
  1408. /*                                                                      */
  1409. /* Draw all splines, knots, grid and the origin.            */
  1410. /*                                                                      */
  1411. /************************************************************************/
  1412. {
  1413.     Set_Pointer(TRUE);
  1414.  
  1415.     Draw_Grid(What);
  1416.     Draw_Splines(DM_Normal, What);
  1417.     Draw_Origin(DM_Normal, What);
  1418.  
  1419.     Set_Pointer(FALSE);
  1420.  
  1421. } /* Draw_All */
  1422.