home *** CD-ROM | disk | FTP | other *** search
/ Dream 41 / Amiga_Dream_41.iso / Amiga / Pro / 3d / ICoons1_0.lzh / icoons / source / spl_util.c < prev    next >
C/C++ Source or Header  |  1992-10-25  |  46KB  |  1,569 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_gfx.h"
  11. #include "spl_math.h"
  12. #include "spl_util.h"
  13.  
  14. void Splines_Init()
  15. /************************************************************************/
  16. /*                                                                      */
  17. /* Initialize the tables containing splines, knots and points.        */
  18. /*                                                                      */
  19. /************************************************************************/
  20. {
  21.     Spline_T     *Spline;
  22.     short    Point_Id;
  23.  
  24.     while (Splines != NULL) Spline_Free(Splines);
  25.  
  26.     for (Point_Id = 0; Point_Id < Max_Nbr_Points; Point_Id++)
  27.                     Points[Point_Id].Reference_Count = 0;
  28.  
  29.     Select_Knot        = NULL;
  30.     Select_Spline    = NULL;
  31.     Select_Point_Id    = -1;
  32.  
  33.     Group_Mode        = FALSE;
  34.     Points_Hidden    = FALSE;
  35.  
  36. } /* Splines_Init */
  37.  
  38. static
  39. Boolean_T Is_Segment_Selected(Spline_T *Spline, Knot_T *Knot)
  40. /************************************************************************/
  41. /*                                                                      */
  42. /* Return TRUE if the segment defined by Spline and Knot is selected.    */
  43. /*                                                                      */
  44. /* A segment is selected if BOTH endpoints are selected.        */
  45. /*                                                                      */
  46. /************************************************************************/
  47. {
  48.     Knot_T     *Next_Knot;
  49.     Boolean_T    Result;
  50.  
  51.     if (Spline == NULL || Knot == NULL) return(FALSE);
  52.  
  53.     Next_Knot = Knot->Next;
  54.     if (Next_Knot == NULL) return(FALSE);
  55.  
  56.     Result = 
  57.     Is_VSelected(Points[Knot->Point_Id]) &&
  58.     Is_VSelected(Points[Next_Knot->Point_Id]);
  59.  
  60.     return(Result);
  61.     
  62. } /* Is_Segment_Selected */
  63.  
  64. void Set_Origin(Vector_T New_Origin)
  65. /************************************************************************/
  66. /*                                                                      */
  67. /* Move origin.                                */
  68. /*                                                                      */
  69. /************************************************************************/
  70. {
  71.     short    i;
  72.     extern Vector_T     Offset;
  73.  
  74.     if (Grid_Snap_Active) Snap_To_Grid(New_Origin);
  75.  
  76.     for (i = 0; i < Max_Nbr_Points; i++) {
  77.  
  78.     if (Points[i].Reference_Count != 0) {
  79.  
  80.         Vec2Op(Points[i].Pos, +=, Origin);
  81.         Vec2Op(Points[i].Pos, -=, New_Origin);
  82.  
  83.        } /* if */
  84.  
  85.     } /* for */
  86.  
  87.     Vec2Op(Offset, +=, Origin);
  88.     Vec2Op(Offset, -=, New_Origin);
  89.  
  90. } /* Set_Origin */
  91.  
  92. Boolean_T Get_Bounding_Box(Vector_T Min_Pos, Vector_T Max_Pos)
  93. /************************************************************************/
  94. /*                                                                      */
  95. /* Find bounding box which contains all visible points.            */
  96. /* Return TRUE if no points were found.                    */
  97. /*                                                                      */
  98. /************************************************************************/
  99. {
  100.     short    i;
  101.  
  102.     Vec3Scalar(Min_Pos, = , 1e9, 1e9, 1e9);
  103.     Vec3Scalar(Max_Pos, = , -1e9, -1e9, -1e9);
  104.  
  105.     for (i = 0; i < Max_Nbr_Points; i++) 
  106.       if (Points[i].Reference_Count > 0 && !Is_Hidden(Points[i])) {
  107.     if (Min_Pos[0] > Points[i].Pos[0]) Min_Pos[0] = Points[i].Pos[0];
  108.     if (Min_Pos[1] > Points[i].Pos[1]) Min_Pos[1] = Points[i].Pos[1];
  109.     if (Min_Pos[2] > Points[i].Pos[2]) Min_Pos[2] = Points[i].Pos[2];
  110.     if (Max_Pos[0] < Points[i].Pos[0]) Max_Pos[0] = Points[i].Pos[0];
  111.     if (Max_Pos[1] < Points[i].Pos[1]) Max_Pos[1] = Points[i].Pos[1];
  112.     if (Max_Pos[2] < Points[i].Pos[2]) Max_Pos[2] = Points[i].Pos[2];
  113.     } /* if */
  114.  
  115.     if (Min_Pos[0] > Max_Pos[0]) return(TRUE);
  116.  
  117.     return(FALSE);
  118.  
  119. } /* Get_Bounding_Box */
  120.  
  121. Boolean_T Get_Select_Bounding_Box(Vector_T Min_Pos, Vector_T Max_Pos)
  122. /************************************************************************/
  123. /*                                                                      */
  124. /* Find bounding box which contains all selected points.        */
  125. /* Return TRUE if no points were found.                    */
  126. /*                                                                      */
  127. /************************************************************************/
  128. {
  129.     short    i;
  130.  
  131.     Vec3Scalar(Min_Pos, = , 1e9, 1e9, 1e9);
  132.     Vec3Scalar(Max_Pos, = , -1e9, -1e9, -1e9);
  133.  
  134.     for (i = 0; i < Max_Nbr_Points; i++) 
  135.       if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
  136.     if (Min_Pos[0] > Points[i].Pos[0]) Min_Pos[0] = Points[i].Pos[0];
  137.     if (Min_Pos[1] > Points[i].Pos[1]) Min_Pos[1] = Points[i].Pos[1];
  138.     if (Min_Pos[2] > Points[i].Pos[2]) Min_Pos[2] = Points[i].Pos[2];
  139.     if (Max_Pos[0] < Points[i].Pos[0]) Max_Pos[0] = Points[i].Pos[0];
  140.     if (Max_Pos[1] < Points[i].Pos[1]) Max_Pos[1] = Points[i].Pos[1];
  141.     if (Max_Pos[2] < Points[i].Pos[2]) Max_Pos[2] = Points[i].Pos[2];
  142.     } /* if */
  143.  
  144.     if (Min_Pos[0] > Max_Pos[0]) return(TRUE);
  145.  
  146.     return(FALSE);
  147.  
  148. } /* Get_Select_Bounding_Box */
  149.  
  150. void Points_Save()
  151. /************************************************************************/
  152. /*                                                                      */
  153. /* Save all points to Saved_Points table.                */
  154. /*                                                                      */
  155. /************************************************************************/
  156. {
  157.     short    i;
  158.  
  159.     for (i = 0; i < Max_Nbr_Points; i++) Saved_Points[i] = Points[i];
  160.  
  161. } /* Points_Save */
  162.  
  163. void Points_Restore()
  164. /************************************************************************/
  165. /*                                                                      */
  166. /* Restore all points from Saved_Points table.                */
  167. /*                                                                      */
  168. /************************************************************************/
  169. {
  170.     short    i;
  171.  
  172.     for (i = 0; i < Max_Nbr_Points; i++) Points[i] = Saved_Points[i];
  173.  
  174. } /* Points_Restore */
  175.  
  176. void Points_Move(Vector_T Distance)
  177. /************************************************************************/
  178. /*                                                                      */
  179. /* Move all selected points the distance 'Distance'.            */
  180. /*                                                                      */
  181. /************************************************************************/
  182. {
  183.     short    i;
  184.  
  185.     for (i = 0; i < Max_Nbr_Points; i++) {
  186.  
  187.     if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
  188.  
  189.         Vec3Op(Points[i].Pos, =, Saved_Points[i].Pos, +, Distance);
  190.  
  191.        } /* if */
  192.  
  193.     } /* for */
  194.  
  195. } /* Points_Move */
  196.  
  197. void Points_Scale(double Scale_Factor, 
  198.     Boolean_T Do_Scale_X, Boolean_T Do_Scale_Y, Boolean_T Do_Scale_Z)
  199. /************************************************************************/
  200. /*                                                                      */
  201. /* Scale all selected points.                        */
  202. /*                                                                      */
  203. /************************************************************************/
  204. {
  205.     short    i;
  206.  
  207.     for (i = 0; i < Max_Nbr_Points; i++) {
  208.  
  209.     if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
  210.  
  211.             if (Do_Scale_X) Points[i].Pos[0] = Origin[0] + 
  212.                 Scale_Factor * (Saved_Points[i].Pos[0] - Origin[0]);
  213.             if (Do_Scale_Y) Points[i].Pos[1] = Origin[1] + 
  214.                 Scale_Factor * (Saved_Points[i].Pos[1] - Origin[1]);
  215.             if (Do_Scale_Z) Points[i].Pos[2] = Origin[2] + 
  216.                 Scale_Factor * (Saved_Points[i].Pos[2] - Origin[2]);
  217.  
  218.        } /* if */
  219.  
  220.     } /* for */
  221.  
  222. } /* Points_Scale */
  223.  
  224. void Points_Rotate(double Angle, short Axis)
  225. /************************************************************************/
  226. /*                                                                      */
  227. /* Rotate all selected points 'Angle' degrees about 'Axis'.        */
  228. /*                                                                      */
  229. /************************************************************************/
  230. {
  231.     short    i;
  232.     Vector_T    R_Vector, P, RP;
  233.     Matrix_T    R_Matrix;
  234.  
  235.     if (Axis < 0 || Axis > 2) return;
  236.  
  237.     R_Vector[0] = R_Vector[1] = R_Vector[2] = 0.0;
  238.     R_Vector[Axis] = Angle;
  239.  
  240.     Compute_Rotation_Matrix(R_Matrix, R_Vector);
  241.  
  242.     for (i = 0; i < Max_Nbr_Points; i++) {
  243.  
  244.     if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
  245.  
  246.         Vec3Op(P, =, Saved_Points[i].Pos, -, Origin);
  247.  
  248.         Matrix_MultV(RP, R_Matrix, P);
  249.  
  250.         Vec3Op(Points[i].Pos, =, RP, +, Origin);
  251.  
  252.        } /* if */
  253.  
  254.     } /* for */
  255.  
  256. } /* Points_Scale */
  257.  
  258. void Points_Set_Tension(double Tension)
  259. /************************************************************************/
  260. /*                                                                      */
  261. /* Set tension for all selected points.                    */
  262. /*                                                                      */
  263. /************************************************************************/
  264. {
  265.     Spline_T     *Spline;
  266.     Knot_T    *Knot;
  267.     int        i;
  268.  
  269.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  270.  
  271.     for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  272.                     i++, Knot = Knot->Next) {
  273.     
  274.         if (Is_Segment_Selected(Spline, Knot))
  275.             Knot->Tension = Tension;
  276.  
  277.        } /* for */
  278.  
  279.     } /* for */
  280.  
  281. } /* Points_Set_Tension */
  282.  
  283. void Points_Set_Bias(double Bias)
  284. /************************************************************************/
  285. /*                                                                      */
  286. /* Set bias for all selected points.                    */
  287. /*                                                                      */
  288. /************************************************************************/
  289. {
  290.     Spline_T     *Spline;
  291.     Knot_T    *Knot;
  292.     int        i;
  293.  
  294.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  295.  
  296.     for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  297.                     i++, Knot = Knot->Next) {
  298.     
  299.         if (Is_Segment_Selected(Spline, Knot))
  300.             Knot->Bias = Bias;
  301.  
  302.        } /* for */
  303.  
  304.     } /* for */
  305.  
  306. } /* Points_Set_Bias */
  307.  
  308. void Points_Set_Continuity(double Continuity)
  309. /************************************************************************/
  310. /*                                                                      */
  311. /* Set continuity for all selected points.                */
  312. /*                                                                      */
  313. /************************************************************************/
  314. {
  315.     Spline_T     *Spline;
  316.     Knot_T    *Knot;
  317.     int        i;
  318.  
  319.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  320.  
  321.     for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  322.                     i++, Knot = Knot->Next) {
  323.     
  324.         if (Is_Segment_Selected(Spline, Knot))
  325.             Knot->Continuity = Continuity;
  326.  
  327.        } /* for */
  328.  
  329.     } /* for */
  330.  
  331. } /* Points_Set_Continuity */
  332.  
  333. short Point_New(Vector_T Pos)
  334. /************************************************************************/
  335. /*                                                                      */
  336. /* Allocate first free point in the point list, set its position to Pos.*/
  337. /* Return id of the point.                        */
  338. /*                                                                      */
  339. /************************************************************************/
  340. {
  341.     short    i;
  342.  
  343.     for (i = 0; i < Max_Nbr_Points && Points[i].Reference_Count != 0; i++) ;
  344.  
  345.     if (i >= Max_Nbr_Points) return(-1);
  346.  
  347.     Points[i].Reference_Count     = 1;
  348.     Points[i].Flags               = 0;
  349.     /* DON'T Initialize Points[i].Work it might be in use already! */
  350.  
  351.     Vec2Op(Points[i].Pos, =, Pos);
  352.  
  353.     return(i);
  354.  
  355. } /* Point_New */
  356.  
  357.  
  358. void Point_Move(short Point_Id, Vector_T Pos)
  359. /************************************************************************/
  360. /*                                                                      */
  361. /* Move point Point_Id to Pos.                        */
  362. /*                                                                      */
  363. /************************************************************************/
  364. {
  365.     if (!Is_Point_Id_Ok(Point_Id)) return;
  366.  
  367.     Vec2Op(Points[Point_Id].Pos, =, Pos);
  368.  
  369. } /* Point_Move */
  370.  
  371. short Point_Find(Vector_T Pos, short View_Id)
  372. /************************************************************************/
  373. /*                                                                      */
  374. /* Search for a point with  coordinates near Pos, in the view View_Id.    */
  375. /* Return its id, or -1 if not found.                    */
  376. /*                                                                      */
  377. /************************************************************************/
  378. {
  379.     int     i;
  380.     short    Found_Id;
  381.     double     D, Dist;
  382.  
  383.     Dist = 999999.0;
  384.     switch (View_Id) {        
  385.  
  386.     case V_X:                     /* Y - Z */
  387.         for (i = 0; i < Max_Nbr_Points; i++) {
  388.         if (Points[i].Reference_Count > 0 && Is_Visible(Points[i])) {
  389.               D = MAX(ABS(Pos[1] - Points[i].Pos[1]), ABS(Pos[2] - Points[i].Pos[2]));
  390.             if (D < Dist) {
  391.                 Dist = D;
  392.                 Found_Id = i;
  393.             } /* if */
  394.         } /* if */
  395.  
  396.         } /* for */
  397.     break;    
  398.     
  399.     case V_Y:                     /* X - Z */
  400.         for (i = 0; i < Max_Nbr_Points; i++) {
  401.         if (Points[i].Reference_Count > 0 && Is_Visible(Points[i])) {
  402.               D = MAX(ABS(Pos[0] - Points[i].Pos[0]), ABS(Pos[2] - Points[i].Pos[2]));
  403.             if (D < Dist) {
  404.                 Dist = D;
  405.                 Found_Id = i;
  406.             } /* if */
  407.         } /* if */
  408.  
  409.         } /* for */
  410.     break;
  411.  
  412.     case V_Z:                     /* X - Y */
  413.         for (i = 0; i < Max_Nbr_Points; i++) {
  414.         if (Points[i].Reference_Count > 0 && Is_Visible(Points[i])) {
  415.               D = MAX(ABS(Pos[0] - Points[i].Pos[0]), ABS(Pos[1] - Points[i].Pos[1]));
  416.             if (D < Dist) {
  417.                 Dist = D;
  418.                 Found_Id = i;
  419.             } /* if */
  420.         } /* if */
  421.         } /* for */
  422.     break;
  423.     
  424.     case V_P:                    /* Persp */
  425.     /* Not implemented yet */
  426.     break;
  427.  
  428.     } /* switch */
  429.  
  430.     if (Dist > Max_Dist) return(-1);
  431.  
  432.     return(Found_Id);
  433.  
  434. }  /* Point_Find */
  435.  
  436. void Knot_Insert(Spline_T *Spline, Knot_T *Knot, Knot_T *New_Knot)
  437. /************************************************************************/
  438. /*                                                                      */
  439. /* Insert New_Knot after the knot Knot to the the spline Spline.    */
  440. /* If Knot is NULL, then insert it first.                */
  441. /*                                                                      */
  442. /************************************************************************/
  443. {
  444.  
  445.     if (Knot == NULL) {        /* Insert first    */
  446.     
  447.         New_Knot->Next      = Spline->First;
  448.         New_Knot->Previous = NULL;
  449.  
  450.     if (New_Knot->Next != NULL) New_Knot->Next->Previous = New_Knot;
  451.         else                        Spline->Last             = New_Knot;
  452.  
  453.     Spline->First     = New_Knot;
  454.  
  455.      } else {
  456.     
  457.     New_Knot->Next = Knot->Next;
  458.     New_Knot->Previous = Knot;
  459.  
  460.     if (New_Knot->Next != NULL) New_Knot->Next->Previous = New_Knot;
  461.     else                        Spline->Last             = New_Knot;
  462.  
  463.     Knot->Next = New_Knot;
  464.  
  465.  
  466.     } /* if .. else .. */
  467.  
  468.         /* Check if Knot was last     */
  469.     if (Spline->Last == Knot) Spline->Last = New_Knot;
  470.  
  471.     if (Spline->Loop) {
  472.  
  473.     Spline->First->Previous = Spline->Last;
  474.     Spline->Last->Next      = Spline->First;
  475.  
  476.     } else {
  477.  
  478.     Spline->First->Previous = NULL;
  479.     Spline->Last->Next      = NULL;
  480.  
  481.     } /* if .. else .. */
  482.  
  483.     Spline->Nbr_Knots++;
  484.  
  485.  
  486. } /* Knot_Insert */
  487.  
  488. void Knot_Remove(Spline_T *Spline, Knot_T *Knot)
  489. /************************************************************************/
  490. /*                                                                      */
  491. /* Remove the knot Knot from the spline Spline.                */
  492. /*                                                                      */
  493. /************************************************************************/
  494. {
  495.     if (Spline == NULL || Knot == NULL) return;
  496.  
  497.     if (Spline->First == Spline->Last) {
  498.  
  499.     Spline->First = Spline->Last = NULL;
  500.  
  501.     } else {
  502.  
  503.         if (Spline->First == Knot) Spline->First = Knot->Next;
  504.         if (Spline->Last == Knot) Spline->Last = Knot->Previous;
  505.  
  506.     } /* if .. else .. */
  507.  
  508.     if (Knot->Previous != NULL) Knot->Previous->Next = Knot->Next; 
  509.     if (Knot->Next     != NULL) Knot->Next->Previous = Knot->Previous; 
  510.  
  511.     Spline->Nbr_Knots--;
  512.  
  513.     if (Spline->Nbr_Knots < 3) Spline_Loop(Spline, FALSE);
  514.  
  515. } /* Knot_Remove */
  516.  
  517. Knot_T *Knot_New(Spline_T *Spline, Knot_T *Knot)
  518. /************************************************************************/
  519. /*                                                                      */
  520. /* Add a new knot after the knot Knot to the the spline Spline.        */
  521. /*                                                                      */
  522. /* Return ptr to new knot, or NULL if it couldn't be created.        */
  523. /*                                                                      */
  524. /************************************************************************/
  525. {
  526.     Knot_T    *New_Knot;
  527.  
  528.     New_Knot = (Knot_T *) malloc(sizeof(Knot_T));
  529.     if (New_Knot == NULL) return(NULL);
  530.  
  531.     New_Knot->Point_Id      = -1;
  532.     New_Knot->Flags      = 0;
  533.     New_Knot->Tension      = 0.0;
  534.     New_Knot->Bias      = 0.0;
  535.     New_Knot->Continuity = 0.0;
  536.  
  537.     Knot_Insert(Spline, Knot, New_Knot);
  538.  
  539.     return(New_Knot);
  540.  
  541. } /* Knot_New */
  542.  
  543. void Knot_Free(Spline_T *Spline, Knot_T *Knot)
  544. /************************************************************************/
  545. /*                                                                      */
  546. /* Free the knot Knot from the spline Spline.                */
  547. /*                                                                      */
  548. /************************************************************************/
  549. {
  550.     if (Spline == NULL || Knot == NULL) return;
  551.  
  552.     Knot_Remove(Spline, Knot);
  553.  
  554.     if (Knot->Point_Id >= 0) Points[Knot->Point_Id].Reference_Count--;
  555.     free(Knot);
  556.  
  557. } /* Knot_Free */
  558.  
  559. Knot_T *Knot_Add(Spline_T *Spline, Knot_T *Knot, Vector_T Point_Pos)
  560. /************************************************************************/
  561. /*                                                                      */
  562. /* Add a new knot after the knot 'Knot' on spline 'Spline'.        */
  563. /* Place it at 'Point_Pos'.                        */
  564. /*                                                                      */
  565. /* Select it, and return ptr to new knot.                */
  566. /*                                                                      */
  567. /************************************************************************/
  568. {
  569.     int        i;
  570.     short    New_Point_Id;
  571.     Knot_T    *New_Knot;
  572.     short    Point_Id, Next_Point_Id;
  573.     Vector_T    V1, V2;
  574.     double    Dot_Product;
  575.     Boolean_T    Last_Knot;
  576.  
  577.  
  578.     if (Spline == NULL || Knot == NULL) return(NULL);
  579.  
  580.     /* Now try to decide wheter the new knot should be placed before or    */
  581.     /* after 'Knot'.                            */
  582.  
  583.     Point_Id = Knot->Point_Id;
  584.  
  585.     Last_Knot = FALSE;
  586.  
  587.     if (Spline->Last != Knot) {
  588.  
  589.     Next_Point_Id = Knot->Next->Point_Id;
  590.  
  591.     } else {
  592.  
  593.     /* This is the last knot    */
  594.     if (!Spline->Loop) {
  595.     
  596.          /* Special case:                         */
  597.         /* If last knot and not looping, then use previous point    */
  598.         /* and invert the test.                    */
  599.  
  600.         Last_Knot = TRUE;
  601.         Next_Point_Id = Knot->Previous->Point_Id;
  602.  
  603.         } else  Next_Point_Id = Spline->First->Point_Id;
  604.  
  605.     } /* if .. else .. */
  606.  
  607.     /* Vector from current point to next:                 */
  608.     Vec3Op(V1, =, Points[Next_Point_Id].Pos, -, Points[Point_Id].Pos);
  609.  
  610.     /* Vector from current point to new point:            */
  611.     Vec3Op(V2, =, Point_Pos, -, Points[Point_Id].Pos);
  612.  
  613.     Dot_Product = VecDot(V1, V2);
  614.  
  615.     if (Last_Knot) Dot_Product *= -1.0;
  616.  
  617.     /* If the two vectors are pointing in the same direction, ie.     */
  618.     /* the dot product > 0, then place new knot after current knot, */
  619.     /* otherwise before                        */
  620.  
  621.     if (Dot_Product < 0.0) Knot = Knot->Previous;    /* Before    */
  622.  
  623.     New_Point_Id = Point_New(Point_Pos);
  624.     if (New_Point_Id < 0) return(NULL);
  625.  
  626.     New_Knot = Knot_New(Spline, Knot);
  627.     if (New_Knot == NULL) {
  628.  
  629.     Points[New_Point_Id].Reference_Count--;
  630.     return(NULL);
  631.  
  632.     } /* if */
  633.  
  634.     New_Knot->Point_Id     = New_Point_Id;
  635.  
  636.     Compute_Spline(Spline);
  637.  
  638.     Select_Point(New_Point_Id);
  639.  
  640.     return(New_Knot);
  641.  
  642. } /* Knot_Add */
  643.  
  644. void Knot_Delete(Spline_T *Spline, Knot_T *Knot)
  645. /************************************************************************/
  646. /*                                                                      */
  647. /* Delete knot with id Knot_Id from the spline 'Spline'.        */
  648. /* If there's no more knots in the spline, then delete the spline.    */
  649. /*                                                                      */
  650. /************************************************************************/
  651. {
  652.     if (Spline == NULL || Knot == NULL) return;
  653.  
  654.     Knot_Free(Spline, Knot);
  655.  
  656.     if (Spline->Nbr_Knots <= 0) Spline_Free(Spline);
  657.  
  658. } /* Knot_Delete */
  659.  
  660. Spline_T *Spline_New()
  661. /************************************************************************/
  662. /*                                                                      */
  663. /* Add a new empty spline.                        */
  664. /*                                                                      */
  665. /* Return Id of new spline, or NULL if it couldn't be created.        */
  666. /************************************************************************/
  667. {
  668.     Spline_T     *Spline;
  669.  
  670.     Spline = (Spline_T *) malloc(sizeof(Spline_T));
  671.     if (Spline == NULL) return(NULL);
  672.  
  673.     Spline->Nbr_Knots    = 0;
  674.     Spline->First    = NULL;
  675.     Spline->Last    = NULL;
  676.     Spline->Loop    = FALSE;
  677.     Spline->Flags    = 0;
  678.  
  679.     Spline->Next = Splines;
  680.     Spline->Previous = NULL;
  681.  
  682.     if (Spline->Next != NULL) Spline->Next->Previous = Spline;
  683.     Splines = Spline;
  684.  
  685.     return(Spline);
  686.  
  687. } /* Spline_New */
  688.  
  689. void Spline_Free(Spline_T *Spline)
  690. /************************************************************************/
  691. /*                                                                      */
  692. /* Delete the spline Spline, DON'T change point reference counts.    */    
  693. /*                                                                      */
  694. /************************************************************************/
  695. {
  696.     Knot_T    *Knot, *Next_Knot;
  697.     int        i;
  698.  
  699.     if (Spline == NULL) return;
  700.  
  701.     if (Spline->Next != NULL) Spline->Next->Previous = Spline->Previous;
  702.  
  703.     if (Spline->Previous != NULL) Spline->Previous->Next = Spline->Next;
  704.     else                          Splines = Splines->Next;
  705.  
  706.     /* Free all knots in this spline.    */
  707.     for (i = 0, Knot = Spline->First;
  708.          i < Spline->Nbr_Knots && Knot != NULL; i++) {
  709.  
  710.     Next_Knot = Knot->Next;
  711.         if (Knot->Point_Id >= 0) Points[Knot->Point_Id].Reference_Count--;
  712.     free(Knot);
  713.     Knot = Next_Knot;
  714.  
  715.     } /* while */
  716.  
  717.     free(Spline);
  718.  
  719. } /* Spline_Free */
  720.  
  721. Spline_T *Spline_Add(Vector_T Pos)
  722. /************************************************************************/
  723. /*                                                                      */
  724. /* Add a new spline (with 2 knots) at position Pos. Select one endpoint */
  725. /* Return pointer to new spline (or NULL).                */
  726. /*                                                                      */
  727. /************************************************************************/
  728. {
  729.     int        i;
  730.     Spline_T    *Spline;
  731.     Knot_T    *Knot1, *Knot2;
  732.     short    Point_Id1, Point_Id2;
  733.  
  734.     Spline = Spline_New();
  735.     if (Spline == NULL) return(NULL);
  736.  
  737.     Point_Id1 = Point_New(Pos);
  738.     if (Point_Id1 < 0) return(NULL);
  739.  
  740.     Point_Id2 = Point_New(Pos);
  741.     if (Point_Id2 < 0) {
  742.     Points[Point_Id1].Reference_Count--;
  743.     return(NULL);
  744.     }
  745.  
  746.     Knot1 = Knot_New(Spline, NULL);
  747.     if (Knot1 == NULL) {
  748.     Points[Point_Id1].Reference_Count--;
  749.     Points[Point_Id2].Reference_Count--;
  750.     Spline_Free(Spline);
  751.     return(NULL);
  752.     }
  753.     Knot2 = Knot_New(Spline, Knot1);
  754.     if (Knot2 == NULL) {
  755.     Points[Point_Id1].Reference_Count--;
  756.     Points[Point_Id2].Reference_Count--;
  757.     Spline_Free(Spline);
  758.     return(NULL);
  759.     }
  760.     Knot1->Point_Id     = Point_Id1;
  761.     Knot2->Point_Id     = Point_Id2;
  762.  
  763.     Compute_Spline(Spline);
  764.  
  765.     Select_Point(Point_Id2);
  766.  
  767.     return(Spline);
  768.  
  769. } /* Spline_Add */
  770.  
  771. void Spline_Loop(Spline_T *Spline, Boolean_T Loop)
  772. /************************************************************************/
  773. /*                                                                      */
  774. /* 'Loop' or 'Unloop' a spline.                        */
  775. /*                                                                      */
  776. /************************************************************************/
  777. {
  778.     Spline->Loop = Loop;
  779.  
  780.     if (Spline->Last == NULL || Spline->First == NULL) return;
  781.  
  782.     if (Loop) {
  783.     
  784.     Spline->First->Previous = Spline->Last;
  785.     Spline->Last->Next      = Spline->First;
  786.  
  787.     } else {
  788.  
  789.     Spline->First->Previous = NULL;
  790.     Spline->Last->Next      = NULL;
  791.  
  792.     } /* if .. else .. */
  793.  
  794. } /* Spline_Loop */
  795.  
  796. Spline_T *Spline_Cut(Spline_T *Spline, Knot_T *Knot)
  797. /************************************************************************/
  798. /*                                                                      */
  799. /* Cut the spline 'Spline' at the knot 'Knot'.                */
  800. /*                                                                      */
  801. /* If the spline is looping, then the result will be one non looping     */
  802. /* spline. If the spline is non-looping, the result will be two splines.*/
  803. /*                                                                      */
  804. /* The knot 'Knot' will be deleted if the action is successfull.    */
  805. /*                                                                      */
  806. /* In case of error, return NULL, otherwise return ptr to newly created    */
  807. /* spline, or if no new spline was created, ptr to original spline.    */
  808. /*                                                                      */
  809. /************************************************************************/
  810. {
  811.     int        i,j;
  812.     int        Nbr_Knots;
  813.     short    Point_Id;
  814.     Spline_T    *Return_Value;
  815.     Spline_T    *New_Spline;
  816.     Knot_T    *Knot1, *Knot2;
  817.  
  818.     Return_Value = NULL;
  819.  
  820.     if (Spline == NULL || Knot == NULL) return(Return_Value);
  821.  
  822.     Nbr_Knots = Spline->Nbr_Knots;
  823.     Point_Id  = Knot->Point_Id;
  824.     
  825.     if (Spline->Loop) {
  826.     if (Nbr_Knots < 3) return(Return_Value);
  827.     
  828.     Knot1 = Knot->Previous;
  829.         Knot2 = Knot->Next;
  830.  
  831.     Knot_Free(Spline, Knot);
  832.  
  833.     Spline->Last = Knot1;
  834.     Spline->First = Knot2;
  835.  
  836.     Spline_Loop(Spline, FALSE);
  837.  
  838.         Return_Value = Spline;
  839.  
  840.     } else {
  841.  
  842.     /* It is only possible to cut at an inner knot!            */
  843.     if (Nbr_Knots < 5 || 
  844.         Knot->Previous == NULL || Knot->Previous->Previous == NULL ||
  845.         Knot->Next     == NULL || Knot->Next->Next         == NULL)
  846.                                  return(Return_Value);
  847.  
  848.         New_Spline = Spline_New();
  849.         if (New_Spline == NULL) return(NULL);
  850.     
  851.     Knot1 = NULL;        /* Insert point    */
  852.     Knot2 = Knot->Next;    /* Knot to remove/insert */
  853.     while (Knot2 != NULL) {
  854.  
  855.         Knot_Remove(Spline, Knot2);
  856.         Knot_Insert(New_Spline, Knot1, Knot2);
  857.  
  858.         Knot1 = Knot2; /* New insert point */
  859.         Knot2 = Knot->Next;    /* Knot to remove/insert */
  860.  
  861.         } /* while */
  862.  
  863.     Knot_Free(Spline, Knot);
  864.  
  865.        Return_Value = New_Spline;
  866.  
  867.     } /* if .. else .. */
  868.  
  869.     return(Return_Value);
  870.  
  871. } /* Spline_Cut */
  872.  
  873. void Spline_Reverse_Knots(Spline_T *Spline)
  874. /************************************************************************/
  875. /*                                                                      */
  876. /* Reverse the knots for Spline.                    */
  877. /*                                                                      */
  878. /************************************************************************/
  879. {
  880.     int        i;
  881.     Knot_T    *Knot, *Next_Knot, *Tmp_Knot;
  882.  
  883.     if (Spline == NULL) return;
  884.  
  885.     if (Spline->Nbr_Knots < 2) return;
  886.  
  887.     i = 0; 
  888.     Knot = Spline->First;
  889.     while (i < Spline->Nbr_Knots) {
  890.  
  891.     Next_Knot      = Knot->Next;
  892.  
  893.     /* switch Next & Previous */
  894.     Tmp_Knot       = Knot->Next;
  895.     Knot->Next     = Knot->Previous;
  896.     Knot->Previous = Tmp_Knot;
  897.  
  898.     Knot = Next_Knot;
  899.     i++;
  900.  
  901.     } /* while */
  902.  
  903.     /* Switch First & Last */
  904.     Tmp_Knot      = Spline->Last;
  905.     Spline->Last  = Spline->First;
  906.     Spline->First = Tmp_Knot;
  907.  
  908. } /* Spline_Reverse_Knots */
  909.  
  910. Boolean_T Splines_Connect(short View_Id, Spline_T *Spline, Knot_T *Knot)
  911. /************************************************************************/
  912. /*                                                                      */
  913. /* Try to connect the given spline/knot with another knot near it.    */
  914. /* Return TRUE if connection is made.                    */
  915. /*                                                                      */
  916. /************************************************************************/
  917. {
  918.     int     i;
  919.     short    Point_Id1;
  920.     short    Point_Id2;
  921.     double     D, Dist;
  922.     double    X, Y, Z;
  923.  
  924.     if (Spline == NULL || Knot == NULL) return(FALSE);
  925.  
  926.     Point_Id1 = Knot->Point_Id;
  927.  
  928.     X = Points[Point_Id1].Pos[0];
  929.     Y = Points[Point_Id1].Pos[1];
  930.     Z = Points[Point_Id1].Pos[2];
  931.  
  932.     Dist = 999999.0;
  933.  
  934.     switch (View_Id) {        
  935.     
  936.     case V_X:                     /* Y - Z */
  937.         for (i = 0; i < Max_Nbr_Points; i++) {
  938.         if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
  939.                 Is_Visible(Points[i])) {
  940.                 D = MAX(ABS(Y - Points[i].Pos[1]), ABS(Z - Points[i].Pos[2]));
  941.             if (D < Dist) {
  942.                 Dist = D;
  943.                 Point_Id2 = i;
  944.             } /* if */
  945.         } /* if */
  946.  
  947.         } /* for */
  948.     break;
  949.  
  950.     
  951.     case V_Y:                     /* X - Z */
  952.         for (i = 0; i < Max_Nbr_Points; i++) {
  953.         if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
  954.                 Is_Visible(Points[i])) {
  955.                 D = MAX(ABS(X - Points[i].Pos[0]), ABS(Z - Points[i].Pos[2]));
  956.             if (D < Dist) {
  957.                 Dist = D;
  958.                 Point_Id2 = i;
  959.             } /* if */
  960.         } /* if */
  961.  
  962.         } /* for */
  963.     break;
  964.     
  965.     case V_Z:                     /* X - Y */
  966.         for (i = 0; i < Max_Nbr_Points; i++) {
  967.         if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
  968.                 Is_Visible(Points[i])) {
  969.                 D = MAX(ABS(X - Points[i].Pos[0]), ABS(Y - Points[i].Pos[1]));
  970.             if (D < Dist) {
  971.                 Dist = D;
  972.                 Point_Id2 = i;
  973.             } /* if */
  974.         } /* if */
  975.         } /* for */
  976.     break;
  977.  
  978.     case V_P:                /* Persp */
  979.     break;
  980.  
  981.     } /* switch */
  982.  
  983.     if (Dist > Max_Dist) return(FALSE);
  984.  
  985.     /* We've found a point (Point_Id2) near the Point_Id1 */
  986.  
  987.     /* Now handle case where Point_Id1 is on start of spline and    */
  988.     /* Point_Id2 is on end of the same spline (or vice versa).     */
  989.     /* In this case we will remove the last knot loop the spline     */
  990.     /* instead.                            */
  991.  
  992.     if (!Spline->Loop) {
  993.  
  994.         if (Spline->First == Knot && 
  995.         Spline->Last->Point_Id == Point_Id2) {
  996.     
  997.             if (Spline->Nbr_Knots < 3) return(FALSE);
  998.  
  999.         Knot_Free(Spline, Spline->Last);
  1000.         Spline_Loop(Spline, TRUE);
  1001.             Deselect_All();
  1002.             Select_Point(Point_Id1);
  1003.         return(TRUE);
  1004.  
  1005.     }  else if (Spline->Last == Knot && 
  1006.                     Spline->First->Point_Id == Point_Id2) {
  1007.  
  1008.             if (Spline->Nbr_Knots < 3) return(FALSE);
  1009.         Knot_Free(Spline, Spline->Last);
  1010.         Spline_Loop(Spline, TRUE);
  1011.             Deselect_All();
  1012.             Select_Point(Point_Id2);
  1013.         return(TRUE);
  1014.  
  1015.     } /* if */
  1016.  
  1017.     } /* if */
  1018.  
  1019.     Points[Point_Id1].Reference_Count--;
  1020.     Knot->Point_Id = Point_Id2;
  1021.     Points[Point_Id2].Reference_Count++;
  1022.  
  1023.     Deselect_All();
  1024.     Select_Point(Point_Id2);
  1025.  
  1026.     return(TRUE);
  1027.  
  1028. } /* Splines_Connect */
  1029.  
  1030. Boolean_T Splines_Combine(short View_Id, Spline_T *Spline, Knot_T *Knot)
  1031. /************************************************************************/
  1032. /*                                                                      */
  1033. /* Try to combine the given spline/knot with another spline near it.    */
  1034. /* This will only work if we are looking at two endpoints, and none of    */
  1035. /* the splines are looping.                        */
  1036. /* Return TRUE if combination is made.                    */
  1037. /*                                                                      */
  1038. /************************************************************************/
  1039. {
  1040.     Boolean_T    Found;
  1041.     int     i;
  1042.     short    Point_Id1;
  1043.     short    Point_Id2;
  1044.     Spline_T    *S, *Spline2;
  1045.     Knot_T    *K, *Knot2;
  1046.     double     D, Dist;
  1047.     double    X, Y, Z;
  1048.  
  1049.     if (Spline == NULL || Knot == NULL) return(FALSE);
  1050.  
  1051.     if (Knot != Spline->First && Knot != Spline->Last) return(FALSE);
  1052.     if (Spline->Loop) return(FALSE);
  1053.     
  1054.     Point_Id1 = Knot->Point_Id;
  1055.  
  1056.     X = Points[Point_Id1].Pos[0];
  1057.     Y = Points[Point_Id1].Pos[1];
  1058.     Z = Points[Point_Id1].Pos[2];
  1059.  
  1060.     Dist = 999999.0;
  1061.  
  1062.     switch (View_Id) {        
  1063.     
  1064.     case V_X:                     /* Y - Z */
  1065.         for (i = 0; i < Max_Nbr_Points; i++) {
  1066.         if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
  1067.                 Is_Visible(Points[i])) {
  1068.                 D = MAX(ABS(Y - Points[i].Pos[1]), ABS(Z - Points[i].Pos[2]));
  1069.             if (D < Dist) {
  1070.                 Dist = D;
  1071.                 Point_Id2 = i;
  1072.             } /* if */
  1073.         } /* if */
  1074.  
  1075.         } /* for */
  1076.     break;
  1077.  
  1078.     
  1079.     case V_Y:                     /* X - Z */
  1080.         for (i = 0; i < Max_Nbr_Points; i++) {
  1081.         if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
  1082.                 Is_Visible(Points[i])) {
  1083.                 D = MAX(ABS(X - Points[i].Pos[0]), ABS(Z - Points[i].Pos[2]));
  1084.             if (D < Dist) {
  1085.                 Dist = D;
  1086.                 Point_Id2 = i;
  1087.             } /* if */
  1088.         } /* if */
  1089.  
  1090.         } /* for */
  1091.     break;
  1092.     
  1093.     case V_Z:                     /* X - Y */
  1094.         for (i = 0; i < Max_Nbr_Points; i++) {
  1095.         if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
  1096.                 Is_Visible(Points[i])) {
  1097.                 D = MAX(ABS(X - Points[i].Pos[0]), ABS(Y - Points[i].Pos[1]));
  1098.             if (D < Dist) {
  1099.                 Dist = D;
  1100.                 Point_Id2 = i;
  1101.             } /* if */
  1102.         } /* if */
  1103.         } /* for */
  1104.     break;
  1105.  
  1106.     case V_P:                /* Persp */
  1107.     break;
  1108.  
  1109.     } /* switch */
  1110.  
  1111.     if (Dist > Max_Dist) return(FALSE);
  1112.  
  1113.     /* We've found a point (Point_Id2) near the Point_Id1, find     */
  1114.     /* first knot using this point:                    */
  1115.  
  1116.     Found = FALSE;
  1117.     for (S = Splines; S != NULL && !Found; S = S->Next) {
  1118.  
  1119.         for (i = 0, K = S->First; i < S->Nbr_Knots && !Found; 
  1120.                             i++, K = K->Next) {
  1121.  
  1122.         if (Point_Id2 == K->Point_Id) {
  1123.  
  1124.         Spline2 = S;
  1125.         Knot2   = K;
  1126.         Found   = TRUE;
  1127.         } /* if */
  1128.  
  1129.     } /* for */
  1130.  
  1131.     } /* for */
  1132.  
  1133.     /* Spline2, Knot2 is on the second spline            */
  1134.  
  1135.     if (!Found) return(FALSE);    /* Should never happen!            */
  1136.     if (Spline2 == NULL || Knot2 == NULL) return(FALSE);
  1137.  
  1138.  
  1139.     if (Spline2 == Spline) return(FALSE);
  1140.     if (Knot2 != Spline2->First && Knot2 != Spline2->Last) return(FALSE);
  1141.     if (Spline2->Loop) return(FALSE);
  1142.  
  1143.     /* All conditions for combination is fulfilled, so do it*/    
  1144.  
  1145.     if (Knot  == Spline->First) Spline_Reverse_Knots(Spline);
  1146.     if (Knot2 == Spline2->Last) Spline_Reverse_Knots(Spline2); 
  1147.  
  1148.     /* Append spline 2 to spline 1:                    */
  1149.  
  1150.     Knot2 = Spline2->First->Next; /* Skip first knot    */
  1151.  
  1152.     while (Knot2 != NULL) {
  1153.  
  1154.     K = Knot2->Next;
  1155.  
  1156.     Knot_Remove(Spline2, Knot2);
  1157.     Knot_Insert(Spline, Spline->Last, Knot2);
  1158.  
  1159.     Knot2 = K;
  1160.  
  1161.     } /* while */
  1162.  
  1163.     Spline_Free(Spline2);
  1164.  
  1165.     return(TRUE);
  1166.  
  1167. } /* Splines_Combine */
  1168.  
  1169. void Splines_Disconnect(short Point_Id)
  1170. /************************************************************************/
  1171. /*                                                                      */
  1172. /* Disconnect all splines which meet at the point given by Point_Id.    */
  1173. /*                                                                      */
  1174. /************************************************************************/
  1175. {
  1176.     Spline_T    *Spline;
  1177.     Knot_T    *Knot;
  1178.     int        Point_Id2;
  1179.     int        i;
  1180.  
  1181.     if (!Is_Point_Id_Ok(Point_Id)) return;
  1182.  
  1183.     if (Points[Point_Id].Reference_Count < 2) return;
  1184.  
  1185.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  1186.  
  1187.         for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  1188.                         i++, Knot = Knot->Next) {
  1189.  
  1190.          if (Knot->Point_Id == Point_Id) {
  1191.  
  1192.         Point_Id2 = Point_New(Points[Point_Id].Pos);
  1193.         if (Point_Id2 < 0) return;
  1194.         Knot->Point_Id = Point_Id2;
  1195.  
  1196.         if (--Points[Point_Id].Reference_Count < 2) return;
  1197.  
  1198.         } /* if */
  1199.  
  1200.         } /* for */
  1201.  
  1202.     } /* for */
  1203.  
  1204.     Deselect_All();
  1205.     Select_Point(Point_Id);
  1206.  
  1207. } /* Splines_Disconnect */
  1208.  
  1209. #ifdef WORK_IN_PROGRESS
  1210. Boolean_T Splines_Copy()
  1211. {
  1212.     Spline_T    *Spline;
  1213.     Knot_T    *Knot, *First_Knot;
  1214.  
  1215.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  1216.     
  1217.     for (i = 0, First_Knot = NULL, Knot = Spline->First; 
  1218.          i < Spline->Nbr_Knots && First_Knot == NULL;
  1219.                         i++, Knot = Knot->Next) {
  1220.         if (Is_Segment_Selected(Spline, Knot) First_Knot = Knot;
  1221.     } /* for */
  1222.  
  1223.  
  1224.     } /* for */    
  1225. } /* Splines_Copy */
  1226.  
  1227. #endif
  1228.  
  1229. void Deselect_All()
  1230. /************************************************************************/
  1231. /*                                                                      */
  1232. /* DeSelect all points.                            */
  1233. /*                                                                      */
  1234. /************************************************************************/
  1235. {
  1236.     int    i;
  1237.  
  1238.  
  1239.     Select_Point_Id = -1;
  1240.     Select_Spline   = NULL;
  1241.     Select_Knot     = NULL;
  1242.  
  1243.     for (i = 0; i < Max_Nbr_Points; i++) Do_Deselect(Points[i]);
  1244.  
  1245.     Group_Mode          = FALSE;
  1246.  
  1247. } /* Deselect_All */
  1248.  
  1249. void Toggle_Select_All()
  1250. /************************************************************************/
  1251. /*                                                                      */
  1252. /* Toggle selection of all non-hidden points and enter group mode.    */
  1253. /*                                                                      */
  1254. /************************************************************************/
  1255. {
  1256.     int    P;
  1257.  
  1258.     for (P = 0; P < Max_Nbr_Points; P++) {
  1259.  
  1260.     if (Is_Visible(Points[P])) {
  1261.  
  1262.         if (Is_Selected(Points[P])) Do_Deselect(Points[P]);
  1263.             else                        Do_Select(Points[P]);
  1264.  
  1265.     } /* if */
  1266.  
  1267.     } /* for */
  1268.  
  1269.     /* Currently selected point isn't toggled! */
  1270.     if (Select_Point_Id >= 0) Do_Select(Points[Select_Point_Id]);
  1271.  
  1272.     Group_Mode = TRUE;
  1273.  
  1274. } /* Toggle_Select_All */
  1275.  
  1276. Boolean_T Select_Knot_From_Group()
  1277. /************************************************************************/
  1278. /*                                                                      */
  1279. /* Select any knot from the current group.                */
  1280. /* This is sometimes necessary, as some commands needs a selected knot    */
  1281. /* and not only a selected group.                     */
  1282. /* Just chose the first knot in the group.                */
  1283. /*                                                                      */
  1284. /* Return TRUE if we find a selectable knot.                */
  1285. /*                                                                      */
  1286. /************************************************************************/
  1287. {
  1288.     int        i;
  1289.     short     Point_Id;
  1290.     Spline_T     *Spline;
  1291.     Knot_T    *Knot;
  1292.  
  1293.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  1294.  
  1295.         for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  1296.                         i++, Knot = Knot->Next) {
  1297.  
  1298.         Point_Id = Knot->Point_Id;
  1299.  
  1300.             /* This knot is selected    */
  1301.         if (Is_Selected(Points[Point_Id])) {
  1302.  
  1303.         Select_Spline   = Spline;
  1304.         Select_Knot     = Knot;
  1305.         Select_Point_Id = Point_Id;
  1306.         return(TRUE);
  1307.  
  1308.         } /* if */
  1309.  
  1310.     } /* for */
  1311.  
  1312.     } /* for */
  1313.  
  1314.     return(FALSE);
  1315.  
  1316. } /* Select_Knot_From_Group */
  1317.  
  1318. void Select_Point(short Point_Id)
  1319. /************************************************************************/
  1320. /*                                                                      */
  1321. /* Select all knots which refer to the point 'Point_Id'.        */
  1322. /*                                                                      */
  1323. /* The first knot found will be the primary selected knot.        */
  1324. /*                                                                      */
  1325. /************************************************************************/
  1326. {
  1327.     int        i;
  1328.     Spline_T     *Spline;
  1329.     Knot_T    *Knot;
  1330.  
  1331.     if (!Is_Point_Id_Ok(Point_Id)) return;
  1332.  
  1333.     if (Points[Point_Id].Reference_Count <= 0) return;
  1334.  
  1335.     Select_Point_Id = Point_Id;
  1336.     Select_Spline   = NULL;
  1337.     Select_Knot     = NULL;
  1338.  
  1339.     Do_Select(Points[Select_Point_Id]);
  1340.  
  1341.     for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
  1342.  
  1343.         for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  1344.                         i++, Knot = Knot->Next) {
  1345.  
  1346.             /* This knot is selected    */
  1347.         if (Knot->Point_Id == Point_Id) {
  1348.  
  1349.         if (Select_Spline == NULL) {
  1350.  
  1351.             /* This is the first selected knot    */
  1352.             /* Make this knot the primary one.    */
  1353.  
  1354.             Select_Spline = Spline;
  1355.             Select_Knot   = Knot;
  1356.  
  1357.         } /* if */
  1358.  
  1359.         } /* if */
  1360.  
  1361.     } /* for */
  1362.  
  1363.     } /* for */
  1364.  
  1365. } /* Select_Point */
  1366.  
  1367. void Select_Next_Knot()
  1368. /************************************************************************/
  1369. /*                                                                      */
  1370. /* Select next knot at currently selected point.            */
  1371. /*                                                                      */
  1372. /************************************************************************/
  1373. {
  1374.     Spline_T     *Spline;
  1375.     Knot_T    *Knot;
  1376.  
  1377.     if (Select_Spline == NULL || Select_Knot == NULL) return;
  1378.  
  1379.  
  1380.     Spline  = Select_Spline;
  1381.     Knot    = Select_Knot;
  1382.  
  1383.     Select_Point_Id = Knot->Point_Id;
  1384.  
  1385.     do {
  1386.     Knot = Knot->Next;
  1387.         if (Knot == NULL || Knot->Previous == Spline->Last) {
  1388.  
  1389.         /* Loop back to first spline if necessary */
  1390.         Spline = Spline->Next;
  1391.         if (Spline == NULL) Spline = Splines;
  1392.             Knot = Spline->First;
  1393.  
  1394.     } /* if */
  1395.  
  1396.     } while (Knot->Point_Id != Select_Point_Id);
  1397.  
  1398.     Select_Knot   = Knot;
  1399.     Select_Spline = Spline;
  1400.  
  1401. } /* Select_Next_Knot */
  1402.  
  1403. void Toggle_Select_Spline(Spline_T *Spline)
  1404. /************************************************************************/
  1405. /*                                                                      */
  1406. /* Toggle selection of all knots on spline 'Spline'.            */
  1407. /*                                                                      */
  1408. /************************************************************************/
  1409. {
  1410.     int        i;
  1411.     Knot_T    *Knot;
  1412.     short    Point_Id;
  1413.  
  1414.     if (Spline == NULL) return;
  1415.  
  1416.     for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots; 
  1417.                         i++, Knot = Knot->Next) {
  1418.  
  1419.     Point_Id = Knot->Point_Id;
  1420.  
  1421.     if (Is_Visible(Points[Point_Id])) {
  1422.  
  1423.         if (Is_Selected(Points[Point_Id])) Do_Deselect(Points[Point_Id]);
  1424.             else                               Do_Select(Points[Point_Id]);
  1425.  
  1426.     } /* if */
  1427.  
  1428.     } /* for */
  1429.  
  1430.     /* Currently selected point isn't toggled! */
  1431.     if (Select_Point_Id >= 0) Do_Select(Points[Select_Point_Id]);
  1432.  
  1433.     Group_Mode = TRUE;
  1434.  
  1435. } /* Toggle_Select_Spline */
  1436.  
  1437. void Select_Area(short View_Id, Vector_T Pos1, Vector_T Pos2)
  1438. /************************************************************************/
  1439. /*                                                                      */
  1440. /* Toggle selection of all non hidden points in the area between Pos1     */
  1441. /* and Pos2 in the view given by View_Id.                    */
  1442. /*                                                                      */
  1443. /************************************************************************/
  1444. {
  1445.     int    i;
  1446.     double Tmp;
  1447.  
  1448.     switch (View_Id) {        
  1449.     
  1450.     case V_X:                     /* Y - Z */
  1451.         if (Pos1[2] > Pos2[2]) {Tmp=Pos1[2];Pos1[2]=Pos2[2];Pos2[2]=Tmp;};
  1452.         for (i = 0; i < Max_Nbr_Points; i++) {
  1453.         if (Points[i].Reference_Count > 0 && Is_Visible(Points[i]) &&
  1454.             Points[i].Pos[1] > Pos1[1] && Points[i].Pos[1] < Pos2[1] &&
  1455.             Points[i].Pos[2] > Pos1[2] && Points[i].Pos[2] < Pos2[2]) {
  1456.         
  1457.         if (Is_Selected(Points[i])) Do_Deselect(Points[i]);
  1458.         else                 Do_Select(Points[i]);
  1459.  
  1460.         } /* if */
  1461.         } /* for */
  1462.     break;
  1463.     
  1464.     case V_Y:                     /* X - Z */
  1465.         if (Pos1[2] > Pos2[2]) {Tmp=Pos1[2];Pos1[2]=Pos2[2];Pos2[2]=Tmp;};
  1466.         for (i = 0; i < Max_Nbr_Points; i++) {
  1467.         if (Points[i].Reference_Count > 0 && Is_Visible(Points[i]) &&
  1468.             Points[i].Pos[0] > Pos1[0] && Points[i].Pos[0] < Pos2[0] &&
  1469.             Points[i].Pos[2] > Pos1[2] && Points[i].Pos[2] < Pos2[2]) {
  1470.  
  1471.         if (Is_Selected(Points[i])) Do_Deselect(Points[i]);
  1472.         else                 Do_Select(Points[i]);
  1473.  
  1474.         } /* if */
  1475.         } /* for */
  1476.     break;
  1477.  
  1478.     case V_Z:                     /* X - Y */
  1479.         if (Pos1[1] > Pos2[1]) {Tmp=Pos1[1];Pos1[1]=Pos2[1];Pos2[1]=Tmp;};
  1480.         for (i = 0; i < Max_Nbr_Points; i++) {
  1481.         if (Points[i].Reference_Count > 0 && Is_Visible(Points[i]) &&
  1482.             Points[i].Pos[0] > Pos1[0] && Points[i].Pos[0] < Pos2[0] &&
  1483.             Points[i].Pos[1] > Pos1[1] && Points[i].Pos[1] < Pos2[1]) {
  1484.  
  1485.         if (Is_Selected(Points[i])) Do_Deselect(Points[i]);
  1486.         else                 Do_Select(Points[i]);
  1487.  
  1488.         } /* if */
  1489.         } /* for */
  1490.     break;
  1491.  
  1492.     case V_P:                    /* Persp */
  1493.     break;
  1494.  
  1495.     } /* switch */
  1496.  
  1497.     Group_Mode = TRUE;
  1498.  
  1499. } /* Select_Area */
  1500.  
  1501. void Hide_Selected_Points()
  1502. /************************************************************************/
  1503. /*                                                                      */
  1504. /* Hide all selected points and deselect them.                */
  1505. /*                                                                      */
  1506. /************************************************************************/
  1507. {
  1508.     int    i;
  1509.         
  1510.     for (i = 0; i < Max_Nbr_Points; i++) {
  1511.  
  1512.     if (Points[i].Reference_Count > 0 && Is_Selected(Points[i]) ) {
  1513.  
  1514.         Do_Hide(Points[i]);
  1515.         Points_Hidden = TRUE;
  1516.     } /* if */
  1517.  
  1518.     } /* for */
  1519.  
  1520.     Deselect_All();
  1521.     
  1522. } /* Hide_Selected_Points */
  1523.  
  1524. void Hide_Unselected_Points()
  1525. /************************************************************************/
  1526. /*                                                                      */
  1527. /* Hide all unselected points and deselect all.                */
  1528. /*                                                                      */
  1529. /************************************************************************/
  1530. {
  1531.     int    i;
  1532.         
  1533.     for (i = 0; i < Max_Nbr_Points; i++) {
  1534.  
  1535.     if (Points[i].Reference_Count > 0 && !Is_Selected(Points[i]) ) {
  1536.  
  1537.         Do_Hide(Points[i]);
  1538.         Points_Hidden = TRUE;
  1539.  
  1540.     } /* if */
  1541.  
  1542.     } /* for */
  1543.  
  1544.     Deselect_All();
  1545.     
  1546. } /* Hide_Unselected_Points */
  1547.  
  1548. void Show_All_Points()
  1549. /************************************************************************/
  1550. /*                                                                      */
  1551. /* Redisplay all hidden points.                        */
  1552. /*                                                                      */
  1553. /************************************************************************/
  1554. {
  1555.     int    i;
  1556.  
  1557.     for (i = 0; i < Max_Nbr_Points; i++) {
  1558.  
  1559.     if (Points[i].Reference_Count > 0 && Is_Hidden(Points[i]) ) {
  1560.  
  1561.         Do_Unhide(Points[i]);
  1562.  
  1563.     } /* if */
  1564.  
  1565.     } /* for */
  1566.     Points_Hidden = FALSE;
  1567.     
  1568. } /* Show_All_Points */
  1569.