home *** CD-ROM | disk | FTP | other *** search
- /* :ts=8 */
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "general.h"
- #include "globals.h"
- #include "intui.h"
- #include "spl_gfx.h"
- #include "spl_math.h"
- #include "spl_util.h"
-
- void Splines_Init()
- /************************************************************************/
- /* */
- /* Initialize the tables containing splines, knots and points. */
- /* */
- /************************************************************************/
- {
- Spline_T *Spline;
- short Point_Id;
-
- while (Splines != NULL) Spline_Free(Splines);
-
- for (Point_Id = 0; Point_Id < Max_Nbr_Points; Point_Id++)
- Points[Point_Id].Reference_Count = 0;
-
- Select_Knot = NULL;
- Select_Spline = NULL;
- Select_Point_Id = -1;
-
- Group_Mode = FALSE;
- Points_Hidden = FALSE;
-
- } /* Splines_Init */
-
- static
- Boolean_T Is_Segment_Selected(Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Return TRUE if the segment defined by Spline and Knot is selected. */
- /* */
- /* A segment is selected if BOTH endpoints are selected. */
- /* */
- /************************************************************************/
- {
- Knot_T *Next_Knot;
- Boolean_T Result;
-
- if (Spline == NULL || Knot == NULL) return(FALSE);
-
- Next_Knot = Knot->Next;
- if (Next_Knot == NULL) return(FALSE);
-
- Result =
- Is_VSelected(Points[Knot->Point_Id]) &&
- Is_VSelected(Points[Next_Knot->Point_Id]);
-
- return(Result);
-
- } /* Is_Segment_Selected */
-
- void Set_Origin(Vector_T New_Origin)
- /************************************************************************/
- /* */
- /* Move origin. */
- /* */
- /************************************************************************/
- {
- short i;
- extern Vector_T Offset;
-
- if (Grid_Snap_Active) Snap_To_Grid(New_Origin);
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count != 0) {
-
- Vec2Op(Points[i].Pos, +=, Origin);
- Vec2Op(Points[i].Pos, -=, New_Origin);
-
- } /* if */
-
- } /* for */
-
- Vec2Op(Offset, +=, Origin);
- Vec2Op(Offset, -=, New_Origin);
-
- } /* Set_Origin */
-
- Boolean_T Get_Bounding_Box(Vector_T Min_Pos, Vector_T Max_Pos)
- /************************************************************************/
- /* */
- /* Find bounding box which contains all visible points. */
- /* Return TRUE if no points were found. */
- /* */
- /************************************************************************/
- {
- short i;
-
- Vec3Scalar(Min_Pos, = , 1e9, 1e9, 1e9);
- Vec3Scalar(Max_Pos, = , -1e9, -1e9, -1e9);
-
- for (i = 0; i < Max_Nbr_Points; i++)
- if (Points[i].Reference_Count > 0 && !Is_Hidden(Points[i])) {
- if (Min_Pos[0] > Points[i].Pos[0]) Min_Pos[0] = Points[i].Pos[0];
- if (Min_Pos[1] > Points[i].Pos[1]) Min_Pos[1] = Points[i].Pos[1];
- if (Min_Pos[2] > Points[i].Pos[2]) Min_Pos[2] = Points[i].Pos[2];
- if (Max_Pos[0] < Points[i].Pos[0]) Max_Pos[0] = Points[i].Pos[0];
- if (Max_Pos[1] < Points[i].Pos[1]) Max_Pos[1] = Points[i].Pos[1];
- if (Max_Pos[2] < Points[i].Pos[2]) Max_Pos[2] = Points[i].Pos[2];
- } /* if */
-
- if (Min_Pos[0] > Max_Pos[0]) return(TRUE);
-
- return(FALSE);
-
- } /* Get_Bounding_Box */
-
- Boolean_T Get_Select_Bounding_Box(Vector_T Min_Pos, Vector_T Max_Pos)
- /************************************************************************/
- /* */
- /* Find bounding box which contains all selected points. */
- /* Return TRUE if no points were found. */
- /* */
- /************************************************************************/
- {
- short i;
-
- Vec3Scalar(Min_Pos, = , 1e9, 1e9, 1e9);
- Vec3Scalar(Max_Pos, = , -1e9, -1e9, -1e9);
-
- for (i = 0; i < Max_Nbr_Points; i++)
- if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
- if (Min_Pos[0] > Points[i].Pos[0]) Min_Pos[0] = Points[i].Pos[0];
- if (Min_Pos[1] > Points[i].Pos[1]) Min_Pos[1] = Points[i].Pos[1];
- if (Min_Pos[2] > Points[i].Pos[2]) Min_Pos[2] = Points[i].Pos[2];
- if (Max_Pos[0] < Points[i].Pos[0]) Max_Pos[0] = Points[i].Pos[0];
- if (Max_Pos[1] < Points[i].Pos[1]) Max_Pos[1] = Points[i].Pos[1];
- if (Max_Pos[2] < Points[i].Pos[2]) Max_Pos[2] = Points[i].Pos[2];
- } /* if */
-
- if (Min_Pos[0] > Max_Pos[0]) return(TRUE);
-
- return(FALSE);
-
- } /* Get_Select_Bounding_Box */
-
- void Points_Save()
- /************************************************************************/
- /* */
- /* Save all points to Saved_Points table. */
- /* */
- /************************************************************************/
- {
- short i;
-
- for (i = 0; i < Max_Nbr_Points; i++) Saved_Points[i] = Points[i];
-
- } /* Points_Save */
-
- void Points_Restore()
- /************************************************************************/
- /* */
- /* Restore all points from Saved_Points table. */
- /* */
- /************************************************************************/
- {
- short i;
-
- for (i = 0; i < Max_Nbr_Points; i++) Points[i] = Saved_Points[i];
-
- } /* Points_Restore */
-
- void Points_Move(Vector_T Distance)
- /************************************************************************/
- /* */
- /* Move all selected points the distance 'Distance'. */
- /* */
- /************************************************************************/
- {
- short i;
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
-
- Vec3Op(Points[i].Pos, =, Saved_Points[i].Pos, +, Distance);
-
- } /* if */
-
- } /* for */
-
- } /* Points_Move */
-
- void Points_Scale(double Scale_Factor,
- Boolean_T Do_Scale_X, Boolean_T Do_Scale_Y, Boolean_T Do_Scale_Z)
- /************************************************************************/
- /* */
- /* Scale all selected points. */
- /* */
- /************************************************************************/
- {
- short i;
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
-
- if (Do_Scale_X) Points[i].Pos[0] = Origin[0] +
- Scale_Factor * (Saved_Points[i].Pos[0] - Origin[0]);
- if (Do_Scale_Y) Points[i].Pos[1] = Origin[1] +
- Scale_Factor * (Saved_Points[i].Pos[1] - Origin[1]);
- if (Do_Scale_Z) Points[i].Pos[2] = Origin[2] +
- Scale_Factor * (Saved_Points[i].Pos[2] - Origin[2]);
-
- } /* if */
-
- } /* for */
-
- } /* Points_Scale */
-
- void Points_Rotate(double Angle, short Axis)
- /************************************************************************/
- /* */
- /* Rotate all selected points 'Angle' degrees about 'Axis'. */
- /* */
- /************************************************************************/
- {
- short i;
- Vector_T R_Vector, P, RP;
- Matrix_T R_Matrix;
-
- if (Axis < 0 || Axis > 2) return;
-
- R_Vector[0] = R_Vector[1] = R_Vector[2] = 0.0;
- R_Vector[Axis] = Angle;
-
- Compute_Rotation_Matrix(R_Matrix, R_Vector);
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count > 0 && Is_Selected(Points[i])) {
-
- Vec3Op(P, =, Saved_Points[i].Pos, -, Origin);
-
- Matrix_MultV(RP, R_Matrix, P);
-
- Vec3Op(Points[i].Pos, =, RP, +, Origin);
-
- } /* if */
-
- } /* for */
-
- } /* Points_Scale */
-
- void Points_Set_Tension(double Tension)
- /************************************************************************/
- /* */
- /* Set tension for all selected points. */
- /* */
- /************************************************************************/
- {
- Spline_T *Spline;
- Knot_T *Knot;
- int i;
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- if (Is_Segment_Selected(Spline, Knot))
- Knot->Tension = Tension;
-
- } /* for */
-
- } /* for */
-
- } /* Points_Set_Tension */
-
- void Points_Set_Bias(double Bias)
- /************************************************************************/
- /* */
- /* Set bias for all selected points. */
- /* */
- /************************************************************************/
- {
- Spline_T *Spline;
- Knot_T *Knot;
- int i;
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- if (Is_Segment_Selected(Spline, Knot))
- Knot->Bias = Bias;
-
- } /* for */
-
- } /* for */
-
- } /* Points_Set_Bias */
-
- void Points_Set_Continuity(double Continuity)
- /************************************************************************/
- /* */
- /* Set continuity for all selected points. */
- /* */
- /************************************************************************/
- {
- Spline_T *Spline;
- Knot_T *Knot;
- int i;
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- if (Is_Segment_Selected(Spline, Knot))
- Knot->Continuity = Continuity;
-
- } /* for */
-
- } /* for */
-
- } /* Points_Set_Continuity */
-
- short Point_New(Vector_T Pos)
- /************************************************************************/
- /* */
- /* Allocate first free point in the point list, set its position to Pos.*/
- /* Return id of the point. */
- /* */
- /************************************************************************/
- {
- short i;
-
- for (i = 0; i < Max_Nbr_Points && Points[i].Reference_Count != 0; i++) ;
-
- if (i >= Max_Nbr_Points) return(-1);
-
- Points[i].Reference_Count = 1;
- Points[i].Flags = 0;
- /* DON'T Initialize Points[i].Work it might be in use already! */
-
- Vec2Op(Points[i].Pos, =, Pos);
-
- return(i);
-
- } /* Point_New */
-
-
- void Point_Move(short Point_Id, Vector_T Pos)
- /************************************************************************/
- /* */
- /* Move point Point_Id to Pos. */
- /* */
- /************************************************************************/
- {
- if (!Is_Point_Id_Ok(Point_Id)) return;
-
- Vec2Op(Points[Point_Id].Pos, =, Pos);
-
- } /* Point_Move */
-
- short Point_Find(Vector_T Pos, short View_Id)
- /************************************************************************/
- /* */
- /* Search for a point with coordinates near Pos, in the view View_Id. */
- /* Return its id, or -1 if not found. */
- /* */
- /************************************************************************/
- {
- int i;
- short Found_Id;
- double D, Dist;
-
- Dist = 999999.0;
- switch (View_Id) {
-
- case V_X: /* Y - Z */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (Points[i].Reference_Count > 0 && Is_Visible(Points[i])) {
- D = MAX(ABS(Pos[1] - Points[i].Pos[1]), ABS(Pos[2] - Points[i].Pos[2]));
- if (D < Dist) {
- Dist = D;
- Found_Id = i;
- } /* if */
- } /* if */
-
- } /* for */
- break;
-
- case V_Y: /* X - Z */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (Points[i].Reference_Count > 0 && Is_Visible(Points[i])) {
- D = MAX(ABS(Pos[0] - Points[i].Pos[0]), ABS(Pos[2] - Points[i].Pos[2]));
- if (D < Dist) {
- Dist = D;
- Found_Id = i;
- } /* if */
- } /* if */
-
- } /* for */
- break;
-
- case V_Z: /* X - Y */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (Points[i].Reference_Count > 0 && Is_Visible(Points[i])) {
- D = MAX(ABS(Pos[0] - Points[i].Pos[0]), ABS(Pos[1] - Points[i].Pos[1]));
- if (D < Dist) {
- Dist = D;
- Found_Id = i;
- } /* if */
- } /* if */
- } /* for */
- break;
-
- case V_P: /* Persp */
- /* Not implemented yet */
- break;
-
- } /* switch */
-
- if (Dist > Max_Dist) return(-1);
-
- return(Found_Id);
-
- } /* Point_Find */
-
- void Knot_Insert(Spline_T *Spline, Knot_T *Knot, Knot_T *New_Knot)
- /************************************************************************/
- /* */
- /* Insert New_Knot after the knot Knot to the the spline Spline. */
- /* If Knot is NULL, then insert it first. */
- /* */
- /************************************************************************/
- {
-
- if (Knot == NULL) { /* Insert first */
-
- New_Knot->Next = Spline->First;
- New_Knot->Previous = NULL;
-
- if (New_Knot->Next != NULL) New_Knot->Next->Previous = New_Knot;
- else Spline->Last = New_Knot;
-
- Spline->First = New_Knot;
-
- } else {
-
- New_Knot->Next = Knot->Next;
- New_Knot->Previous = Knot;
-
- if (New_Knot->Next != NULL) New_Knot->Next->Previous = New_Knot;
- else Spline->Last = New_Knot;
-
- Knot->Next = New_Knot;
-
-
- } /* if .. else .. */
-
- /* Check if Knot was last */
- if (Spline->Last == Knot) Spline->Last = New_Knot;
-
- if (Spline->Loop) {
-
- Spline->First->Previous = Spline->Last;
- Spline->Last->Next = Spline->First;
-
- } else {
-
- Spline->First->Previous = NULL;
- Spline->Last->Next = NULL;
-
- } /* if .. else .. */
-
- Spline->Nbr_Knots++;
-
-
- } /* Knot_Insert */
-
- void Knot_Remove(Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Remove the knot Knot from the spline Spline. */
- /* */
- /************************************************************************/
- {
- if (Spline == NULL || Knot == NULL) return;
-
- if (Spline->First == Spline->Last) {
-
- Spline->First = Spline->Last = NULL;
-
- } else {
-
- if (Spline->First == Knot) Spline->First = Knot->Next;
- if (Spline->Last == Knot) Spline->Last = Knot->Previous;
-
- } /* if .. else .. */
-
- if (Knot->Previous != NULL) Knot->Previous->Next = Knot->Next;
- if (Knot->Next != NULL) Knot->Next->Previous = Knot->Previous;
-
- Spline->Nbr_Knots--;
-
- if (Spline->Nbr_Knots < 3) Spline_Loop(Spline, FALSE);
-
- } /* Knot_Remove */
-
- Knot_T *Knot_New(Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Add a new knot after the knot Knot to the the spline Spline. */
- /* */
- /* Return ptr to new knot, or NULL if it couldn't be created. */
- /* */
- /************************************************************************/
- {
- Knot_T *New_Knot;
-
- New_Knot = (Knot_T *) malloc(sizeof(Knot_T));
- if (New_Knot == NULL) return(NULL);
-
- New_Knot->Point_Id = -1;
- New_Knot->Flags = 0;
- New_Knot->Tension = 0.0;
- New_Knot->Bias = 0.0;
- New_Knot->Continuity = 0.0;
-
- Knot_Insert(Spline, Knot, New_Knot);
-
- return(New_Knot);
-
- } /* Knot_New */
-
- void Knot_Free(Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Free the knot Knot from the spline Spline. */
- /* */
- /************************************************************************/
- {
- if (Spline == NULL || Knot == NULL) return;
-
- Knot_Remove(Spline, Knot);
-
- if (Knot->Point_Id >= 0) Points[Knot->Point_Id].Reference_Count--;
- free(Knot);
-
- } /* Knot_Free */
-
- Knot_T *Knot_Add(Spline_T *Spline, Knot_T *Knot, Vector_T Point_Pos)
- /************************************************************************/
- /* */
- /* Add a new knot after the knot 'Knot' on spline 'Spline'. */
- /* Place it at 'Point_Pos'. */
- /* */
- /* Select it, and return ptr to new knot. */
- /* */
- /************************************************************************/
- {
- int i;
- short New_Point_Id;
- Knot_T *New_Knot;
- short Point_Id, Next_Point_Id;
- Vector_T V1, V2;
- double Dot_Product;
- Boolean_T Last_Knot;
-
-
- if (Spline == NULL || Knot == NULL) return(NULL);
-
- /* Now try to decide wheter the new knot should be placed before or */
- /* after 'Knot'. */
-
- Point_Id = Knot->Point_Id;
-
- Last_Knot = FALSE;
-
- if (Spline->Last != Knot) {
-
- Next_Point_Id = Knot->Next->Point_Id;
-
- } else {
-
- /* This is the last knot */
- if (!Spline->Loop) {
-
- /* Special case: */
- /* If last knot and not looping, then use previous point */
- /* and invert the test. */
-
- Last_Knot = TRUE;
- Next_Point_Id = Knot->Previous->Point_Id;
-
- } else Next_Point_Id = Spline->First->Point_Id;
-
- } /* if .. else .. */
-
- /* Vector from current point to next: */
- Vec3Op(V1, =, Points[Next_Point_Id].Pos, -, Points[Point_Id].Pos);
-
- /* Vector from current point to new point: */
- Vec3Op(V2, =, Point_Pos, -, Points[Point_Id].Pos);
-
- Dot_Product = VecDot(V1, V2);
-
- if (Last_Knot) Dot_Product *= -1.0;
-
- /* If the two vectors are pointing in the same direction, ie. */
- /* the dot product > 0, then place new knot after current knot, */
- /* otherwise before */
-
- if (Dot_Product < 0.0) Knot = Knot->Previous; /* Before */
-
- New_Point_Id = Point_New(Point_Pos);
- if (New_Point_Id < 0) return(NULL);
-
- New_Knot = Knot_New(Spline, Knot);
- if (New_Knot == NULL) {
-
- Points[New_Point_Id].Reference_Count--;
- return(NULL);
-
- } /* if */
-
- New_Knot->Point_Id = New_Point_Id;
-
- Compute_Spline(Spline);
-
- Select_Point(New_Point_Id);
-
- return(New_Knot);
-
- } /* Knot_Add */
-
- void Knot_Delete(Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Delete knot with id Knot_Id from the spline 'Spline'. */
- /* If there's no more knots in the spline, then delete the spline. */
- /* */
- /************************************************************************/
- {
- if (Spline == NULL || Knot == NULL) return;
-
- Knot_Free(Spline, Knot);
-
- if (Spline->Nbr_Knots <= 0) Spline_Free(Spline);
-
- } /* Knot_Delete */
-
- Spline_T *Spline_New()
- /************************************************************************/
- /* */
- /* Add a new empty spline. */
- /* */
- /* Return Id of new spline, or NULL if it couldn't be created. */
- /************************************************************************/
- {
- Spline_T *Spline;
-
- Spline = (Spline_T *) malloc(sizeof(Spline_T));
- if (Spline == NULL) return(NULL);
-
- Spline->Nbr_Knots = 0;
- Spline->First = NULL;
- Spline->Last = NULL;
- Spline->Loop = FALSE;
- Spline->Flags = 0;
-
- Spline->Next = Splines;
- Spline->Previous = NULL;
-
- if (Spline->Next != NULL) Spline->Next->Previous = Spline;
- Splines = Spline;
-
- return(Spline);
-
- } /* Spline_New */
-
- void Spline_Free(Spline_T *Spline)
- /************************************************************************/
- /* */
- /* Delete the spline Spline, DON'T change point reference counts. */
- /* */
- /************************************************************************/
- {
- Knot_T *Knot, *Next_Knot;
- int i;
-
- if (Spline == NULL) return;
-
- if (Spline->Next != NULL) Spline->Next->Previous = Spline->Previous;
-
- if (Spline->Previous != NULL) Spline->Previous->Next = Spline->Next;
- else Splines = Splines->Next;
-
- /* Free all knots in this spline. */
- for (i = 0, Knot = Spline->First;
- i < Spline->Nbr_Knots && Knot != NULL; i++) {
-
- Next_Knot = Knot->Next;
- if (Knot->Point_Id >= 0) Points[Knot->Point_Id].Reference_Count--;
- free(Knot);
- Knot = Next_Knot;
-
- } /* while */
-
- free(Spline);
-
- } /* Spline_Free */
-
- Spline_T *Spline_Add(Vector_T Pos)
- /************************************************************************/
- /* */
- /* Add a new spline (with 2 knots) at position Pos. Select one endpoint */
- /* Return pointer to new spline (or NULL). */
- /* */
- /************************************************************************/
- {
- int i;
- Spline_T *Spline;
- Knot_T *Knot1, *Knot2;
- short Point_Id1, Point_Id2;
-
- Spline = Spline_New();
- if (Spline == NULL) return(NULL);
-
- Point_Id1 = Point_New(Pos);
- if (Point_Id1 < 0) return(NULL);
-
- Point_Id2 = Point_New(Pos);
- if (Point_Id2 < 0) {
- Points[Point_Id1].Reference_Count--;
- return(NULL);
- }
-
- Knot1 = Knot_New(Spline, NULL);
- if (Knot1 == NULL) {
- Points[Point_Id1].Reference_Count--;
- Points[Point_Id2].Reference_Count--;
- Spline_Free(Spline);
- return(NULL);
- }
- Knot2 = Knot_New(Spline, Knot1);
- if (Knot2 == NULL) {
- Points[Point_Id1].Reference_Count--;
- Points[Point_Id2].Reference_Count--;
- Spline_Free(Spline);
- return(NULL);
- }
- Knot1->Point_Id = Point_Id1;
- Knot2->Point_Id = Point_Id2;
-
- Compute_Spline(Spline);
-
- Select_Point(Point_Id2);
-
- return(Spline);
-
- } /* Spline_Add */
-
- void Spline_Loop(Spline_T *Spline, Boolean_T Loop)
- /************************************************************************/
- /* */
- /* 'Loop' or 'Unloop' a spline. */
- /* */
- /************************************************************************/
- {
- Spline->Loop = Loop;
-
- if (Spline->Last == NULL || Spline->First == NULL) return;
-
- if (Loop) {
-
- Spline->First->Previous = Spline->Last;
- Spline->Last->Next = Spline->First;
-
- } else {
-
- Spline->First->Previous = NULL;
- Spline->Last->Next = NULL;
-
- } /* if .. else .. */
-
- } /* Spline_Loop */
-
- Spline_T *Spline_Cut(Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Cut the spline 'Spline' at the knot 'Knot'. */
- /* */
- /* If the spline is looping, then the result will be one non looping */
- /* spline. If the spline is non-looping, the result will be two splines.*/
- /* */
- /* The knot 'Knot' will be deleted if the action is successfull. */
- /* */
- /* In case of error, return NULL, otherwise return ptr to newly created */
- /* spline, or if no new spline was created, ptr to original spline. */
- /* */
- /************************************************************************/
- {
- int i,j;
- int Nbr_Knots;
- short Point_Id;
- Spline_T *Return_Value;
- Spline_T *New_Spline;
- Knot_T *Knot1, *Knot2;
-
- Return_Value = NULL;
-
- if (Spline == NULL || Knot == NULL) return(Return_Value);
-
- Nbr_Knots = Spline->Nbr_Knots;
- Point_Id = Knot->Point_Id;
-
- if (Spline->Loop) {
- if (Nbr_Knots < 3) return(Return_Value);
-
- Knot1 = Knot->Previous;
- Knot2 = Knot->Next;
-
- Knot_Free(Spline, Knot);
-
- Spline->Last = Knot1;
- Spline->First = Knot2;
-
- Spline_Loop(Spline, FALSE);
-
- Return_Value = Spline;
-
- } else {
-
- /* It is only possible to cut at an inner knot! */
- if (Nbr_Knots < 5 ||
- Knot->Previous == NULL || Knot->Previous->Previous == NULL ||
- Knot->Next == NULL || Knot->Next->Next == NULL)
- return(Return_Value);
-
- New_Spline = Spline_New();
- if (New_Spline == NULL) return(NULL);
-
- Knot1 = NULL; /* Insert point */
- Knot2 = Knot->Next; /* Knot to remove/insert */
- while (Knot2 != NULL) {
-
- Knot_Remove(Spline, Knot2);
- Knot_Insert(New_Spline, Knot1, Knot2);
-
- Knot1 = Knot2; /* New insert point */
- Knot2 = Knot->Next; /* Knot to remove/insert */
-
- } /* while */
-
- Knot_Free(Spline, Knot);
-
- Return_Value = New_Spline;
-
- } /* if .. else .. */
-
- return(Return_Value);
-
- } /* Spline_Cut */
-
- void Spline_Reverse_Knots(Spline_T *Spline)
- /************************************************************************/
- /* */
- /* Reverse the knots for Spline. */
- /* */
- /************************************************************************/
- {
- int i;
- Knot_T *Knot, *Next_Knot, *Tmp_Knot;
-
- if (Spline == NULL) return;
-
- if (Spline->Nbr_Knots < 2) return;
-
- i = 0;
- Knot = Spline->First;
- while (i < Spline->Nbr_Knots) {
-
- Next_Knot = Knot->Next;
-
- /* switch Next & Previous */
- Tmp_Knot = Knot->Next;
- Knot->Next = Knot->Previous;
- Knot->Previous = Tmp_Knot;
-
- Knot = Next_Knot;
- i++;
-
- } /* while */
-
- /* Switch First & Last */
- Tmp_Knot = Spline->Last;
- Spline->Last = Spline->First;
- Spline->First = Tmp_Knot;
-
- } /* Spline_Reverse_Knots */
-
- Boolean_T Splines_Connect(short View_Id, Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Try to connect the given spline/knot with another knot near it. */
- /* Return TRUE if connection is made. */
- /* */
- /************************************************************************/
- {
- int i;
- short Point_Id1;
- short Point_Id2;
- double D, Dist;
- double X, Y, Z;
-
- if (Spline == NULL || Knot == NULL) return(FALSE);
-
- Point_Id1 = Knot->Point_Id;
-
- X = Points[Point_Id1].Pos[0];
- Y = Points[Point_Id1].Pos[1];
- Z = Points[Point_Id1].Pos[2];
-
- Dist = 999999.0;
-
- switch (View_Id) {
-
- case V_X: /* Y - Z */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
- Is_Visible(Points[i])) {
- D = MAX(ABS(Y - Points[i].Pos[1]), ABS(Z - Points[i].Pos[2]));
- if (D < Dist) {
- Dist = D;
- Point_Id2 = i;
- } /* if */
- } /* if */
-
- } /* for */
- break;
-
-
- case V_Y: /* X - Z */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
- Is_Visible(Points[i])) {
- D = MAX(ABS(X - Points[i].Pos[0]), ABS(Z - Points[i].Pos[2]));
- if (D < Dist) {
- Dist = D;
- Point_Id2 = i;
- } /* if */
- } /* if */
-
- } /* for */
- break;
-
- case V_Z: /* X - Y */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
- Is_Visible(Points[i])) {
- D = MAX(ABS(X - Points[i].Pos[0]), ABS(Y - Points[i].Pos[1]));
- if (D < Dist) {
- Dist = D;
- Point_Id2 = i;
- } /* if */
- } /* if */
- } /* for */
- break;
-
- case V_P: /* Persp */
- break;
-
- } /* switch */
-
- if (Dist > Max_Dist) return(FALSE);
-
- /* We've found a point (Point_Id2) near the Point_Id1 */
-
- /* Now handle case where Point_Id1 is on start of spline and */
- /* Point_Id2 is on end of the same spline (or vice versa). */
- /* In this case we will remove the last knot loop the spline */
- /* instead. */
-
- if (!Spline->Loop) {
-
- if (Spline->First == Knot &&
- Spline->Last->Point_Id == Point_Id2) {
-
- if (Spline->Nbr_Knots < 3) return(FALSE);
-
- Knot_Free(Spline, Spline->Last);
- Spline_Loop(Spline, TRUE);
- Deselect_All();
- Select_Point(Point_Id1);
- return(TRUE);
-
- } else if (Spline->Last == Knot &&
- Spline->First->Point_Id == Point_Id2) {
-
- if (Spline->Nbr_Knots < 3) return(FALSE);
- Knot_Free(Spline, Spline->Last);
- Spline_Loop(Spline, TRUE);
- Deselect_All();
- Select_Point(Point_Id2);
- return(TRUE);
-
- } /* if */
-
- } /* if */
-
- Points[Point_Id1].Reference_Count--;
- Knot->Point_Id = Point_Id2;
- Points[Point_Id2].Reference_Count++;
-
- Deselect_All();
- Select_Point(Point_Id2);
-
- return(TRUE);
-
- } /* Splines_Connect */
-
- Boolean_T Splines_Combine(short View_Id, Spline_T *Spline, Knot_T *Knot)
- /************************************************************************/
- /* */
- /* Try to combine the given spline/knot with another spline near it. */
- /* This will only work if we are looking at two endpoints, and none of */
- /* the splines are looping. */
- /* Return TRUE if combination is made. */
- /* */
- /************************************************************************/
- {
- Boolean_T Found;
- int i;
- short Point_Id1;
- short Point_Id2;
- Spline_T *S, *Spline2;
- Knot_T *K, *Knot2;
- double D, Dist;
- double X, Y, Z;
-
- if (Spline == NULL || Knot == NULL) return(FALSE);
-
- if (Knot != Spline->First && Knot != Spline->Last) return(FALSE);
- if (Spline->Loop) return(FALSE);
-
- Point_Id1 = Knot->Point_Id;
-
- X = Points[Point_Id1].Pos[0];
- Y = Points[Point_Id1].Pos[1];
- Z = Points[Point_Id1].Pos[2];
-
- Dist = 999999.0;
-
- switch (View_Id) {
-
- case V_X: /* Y - Z */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
- Is_Visible(Points[i])) {
- D = MAX(ABS(Y - Points[i].Pos[1]), ABS(Z - Points[i].Pos[2]));
- if (D < Dist) {
- Dist = D;
- Point_Id2 = i;
- } /* if */
- } /* if */
-
- } /* for */
- break;
-
-
- case V_Y: /* X - Z */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
- Is_Visible(Points[i])) {
- D = MAX(ABS(X - Points[i].Pos[0]), ABS(Z - Points[i].Pos[2]));
- if (D < Dist) {
- Dist = D;
- Point_Id2 = i;
- } /* if */
- } /* if */
-
- } /* for */
- break;
-
- case V_Z: /* X - Y */
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (i != Point_Id1 && Points[i].Reference_Count > 0 &&
- Is_Visible(Points[i])) {
- D = MAX(ABS(X - Points[i].Pos[0]), ABS(Y - Points[i].Pos[1]));
- if (D < Dist) {
- Dist = D;
- Point_Id2 = i;
- } /* if */
- } /* if */
- } /* for */
- break;
-
- case V_P: /* Persp */
- break;
-
- } /* switch */
-
- if (Dist > Max_Dist) return(FALSE);
-
- /* We've found a point (Point_Id2) near the Point_Id1, find */
- /* first knot using this point: */
-
- Found = FALSE;
- for (S = Splines; S != NULL && !Found; S = S->Next) {
-
- for (i = 0, K = S->First; i < S->Nbr_Knots && !Found;
- i++, K = K->Next) {
-
- if (Point_Id2 == K->Point_Id) {
-
- Spline2 = S;
- Knot2 = K;
- Found = TRUE;
- } /* if */
-
- } /* for */
-
- } /* for */
-
- /* Spline2, Knot2 is on the second spline */
-
- if (!Found) return(FALSE); /* Should never happen! */
- if (Spline2 == NULL || Knot2 == NULL) return(FALSE);
-
-
- if (Spline2 == Spline) return(FALSE);
- if (Knot2 != Spline2->First && Knot2 != Spline2->Last) return(FALSE);
- if (Spline2->Loop) return(FALSE);
-
- /* All conditions for combination is fulfilled, so do it*/
-
- if (Knot == Spline->First) Spline_Reverse_Knots(Spline);
- if (Knot2 == Spline2->Last) Spline_Reverse_Knots(Spline2);
-
- /* Append spline 2 to spline 1: */
-
- Knot2 = Spline2->First->Next; /* Skip first knot */
-
- while (Knot2 != NULL) {
-
- K = Knot2->Next;
-
- Knot_Remove(Spline2, Knot2);
- Knot_Insert(Spline, Spline->Last, Knot2);
-
- Knot2 = K;
-
- } /* while */
-
- Spline_Free(Spline2);
-
- return(TRUE);
-
- } /* Splines_Combine */
-
- void Splines_Disconnect(short Point_Id)
- /************************************************************************/
- /* */
- /* Disconnect all splines which meet at the point given by Point_Id. */
- /* */
- /************************************************************************/
- {
- Spline_T *Spline;
- Knot_T *Knot;
- int Point_Id2;
- int i;
-
- if (!Is_Point_Id_Ok(Point_Id)) return;
-
- if (Points[Point_Id].Reference_Count < 2) return;
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- if (Knot->Point_Id == Point_Id) {
-
- Point_Id2 = Point_New(Points[Point_Id].Pos);
- if (Point_Id2 < 0) return;
- Knot->Point_Id = Point_Id2;
-
- if (--Points[Point_Id].Reference_Count < 2) return;
-
- } /* if */
-
- } /* for */
-
- } /* for */
-
- Deselect_All();
- Select_Point(Point_Id);
-
- } /* Splines_Disconnect */
-
- #ifdef WORK_IN_PROGRESS
- Boolean_T Splines_Copy()
- {
- Spline_T *Spline;
- Knot_T *Knot, *First_Knot;
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, First_Knot = NULL, Knot = Spline->First;
- i < Spline->Nbr_Knots && First_Knot == NULL;
- i++, Knot = Knot->Next) {
- if (Is_Segment_Selected(Spline, Knot) First_Knot = Knot;
- } /* for */
-
-
- } /* for */
- } /* Splines_Copy */
-
- #endif
-
- void Deselect_All()
- /************************************************************************/
- /* */
- /* DeSelect all points. */
- /* */
- /************************************************************************/
- {
- int i;
-
-
- Select_Point_Id = -1;
- Select_Spline = NULL;
- Select_Knot = NULL;
-
- for (i = 0; i < Max_Nbr_Points; i++) Do_Deselect(Points[i]);
-
- Group_Mode = FALSE;
-
- } /* Deselect_All */
-
- void Toggle_Select_All()
- /************************************************************************/
- /* */
- /* Toggle selection of all non-hidden points and enter group mode. */
- /* */
- /************************************************************************/
- {
- int P;
-
- for (P = 0; P < Max_Nbr_Points; P++) {
-
- if (Is_Visible(Points[P])) {
-
- if (Is_Selected(Points[P])) Do_Deselect(Points[P]);
- else Do_Select(Points[P]);
-
- } /* if */
-
- } /* for */
-
- /* Currently selected point isn't toggled! */
- if (Select_Point_Id >= 0) Do_Select(Points[Select_Point_Id]);
-
- Group_Mode = TRUE;
-
- } /* Toggle_Select_All */
-
- Boolean_T Select_Knot_From_Group()
- /************************************************************************/
- /* */
- /* Select any knot from the current group. */
- /* This is sometimes necessary, as some commands needs a selected knot */
- /* and not only a selected group. */
- /* Just chose the first knot in the group. */
- /* */
- /* Return TRUE if we find a selectable knot. */
- /* */
- /************************************************************************/
- {
- int i;
- short Point_Id;
- Spline_T *Spline;
- Knot_T *Knot;
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- Point_Id = Knot->Point_Id;
-
- /* This knot is selected */
- if (Is_Selected(Points[Point_Id])) {
-
- Select_Spline = Spline;
- Select_Knot = Knot;
- Select_Point_Id = Point_Id;
- return(TRUE);
-
- } /* if */
-
- } /* for */
-
- } /* for */
-
- return(FALSE);
-
- } /* Select_Knot_From_Group */
-
- void Select_Point(short Point_Id)
- /************************************************************************/
- /* */
- /* Select all knots which refer to the point 'Point_Id'. */
- /* */
- /* The first knot found will be the primary selected knot. */
- /* */
- /************************************************************************/
- {
- int i;
- Spline_T *Spline;
- Knot_T *Knot;
-
- if (!Is_Point_Id_Ok(Point_Id)) return;
-
- if (Points[Point_Id].Reference_Count <= 0) return;
-
- Select_Point_Id = Point_Id;
- Select_Spline = NULL;
- Select_Knot = NULL;
-
- Do_Select(Points[Select_Point_Id]);
-
- for (Spline = Splines; Spline != NULL; Spline = Spline->Next) {
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- /* This knot is selected */
- if (Knot->Point_Id == Point_Id) {
-
- if (Select_Spline == NULL) {
-
- /* This is the first selected knot */
- /* Make this knot the primary one. */
-
- Select_Spline = Spline;
- Select_Knot = Knot;
-
- } /* if */
-
- } /* if */
-
- } /* for */
-
- } /* for */
-
- } /* Select_Point */
-
- void Select_Next_Knot()
- /************************************************************************/
- /* */
- /* Select next knot at currently selected point. */
- /* */
- /************************************************************************/
- {
- Spline_T *Spline;
- Knot_T *Knot;
-
- if (Select_Spline == NULL || Select_Knot == NULL) return;
-
-
- Spline = Select_Spline;
- Knot = Select_Knot;
-
- Select_Point_Id = Knot->Point_Id;
-
- do {
- Knot = Knot->Next;
- if (Knot == NULL || Knot->Previous == Spline->Last) {
-
- /* Loop back to first spline if necessary */
- Spline = Spline->Next;
- if (Spline == NULL) Spline = Splines;
- Knot = Spline->First;
-
- } /* if */
-
- } while (Knot->Point_Id != Select_Point_Id);
-
- Select_Knot = Knot;
- Select_Spline = Spline;
-
- } /* Select_Next_Knot */
-
- void Toggle_Select_Spline(Spline_T *Spline)
- /************************************************************************/
- /* */
- /* Toggle selection of all knots on spline 'Spline'. */
- /* */
- /************************************************************************/
- {
- int i;
- Knot_T *Knot;
- short Point_Id;
-
- if (Spline == NULL) return;
-
- for (i = 0, Knot = Spline->First; i < Spline->Nbr_Knots;
- i++, Knot = Knot->Next) {
-
- Point_Id = Knot->Point_Id;
-
- if (Is_Visible(Points[Point_Id])) {
-
- if (Is_Selected(Points[Point_Id])) Do_Deselect(Points[Point_Id]);
- else Do_Select(Points[Point_Id]);
-
- } /* if */
-
- } /* for */
-
- /* Currently selected point isn't toggled! */
- if (Select_Point_Id >= 0) Do_Select(Points[Select_Point_Id]);
-
- Group_Mode = TRUE;
-
- } /* Toggle_Select_Spline */
-
- void Select_Area(short View_Id, Vector_T Pos1, Vector_T Pos2)
- /************************************************************************/
- /* */
- /* Toggle selection of all non hidden points in the area between Pos1 */
- /* and Pos2 in the view given by View_Id. */
- /* */
- /************************************************************************/
- {
- int i;
- double Tmp;
-
- switch (View_Id) {
-
- case V_X: /* Y - Z */
- if (Pos1[2] > Pos2[2]) {Tmp=Pos1[2];Pos1[2]=Pos2[2];Pos2[2]=Tmp;};
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (Points[i].Reference_Count > 0 && Is_Visible(Points[i]) &&
- Points[i].Pos[1] > Pos1[1] && Points[i].Pos[1] < Pos2[1] &&
- Points[i].Pos[2] > Pos1[2] && Points[i].Pos[2] < Pos2[2]) {
-
- if (Is_Selected(Points[i])) Do_Deselect(Points[i]);
- else Do_Select(Points[i]);
-
- } /* if */
- } /* for */
- break;
-
- case V_Y: /* X - Z */
- if (Pos1[2] > Pos2[2]) {Tmp=Pos1[2];Pos1[2]=Pos2[2];Pos2[2]=Tmp;};
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (Points[i].Reference_Count > 0 && Is_Visible(Points[i]) &&
- Points[i].Pos[0] > Pos1[0] && Points[i].Pos[0] < Pos2[0] &&
- Points[i].Pos[2] > Pos1[2] && Points[i].Pos[2] < Pos2[2]) {
-
- if (Is_Selected(Points[i])) Do_Deselect(Points[i]);
- else Do_Select(Points[i]);
-
- } /* if */
- } /* for */
- break;
-
- case V_Z: /* X - Y */
- if (Pos1[1] > Pos2[1]) {Tmp=Pos1[1];Pos1[1]=Pos2[1];Pos2[1]=Tmp;};
- for (i = 0; i < Max_Nbr_Points; i++) {
- if (Points[i].Reference_Count > 0 && Is_Visible(Points[i]) &&
- Points[i].Pos[0] > Pos1[0] && Points[i].Pos[0] < Pos2[0] &&
- Points[i].Pos[1] > Pos1[1] && Points[i].Pos[1] < Pos2[1]) {
-
- if (Is_Selected(Points[i])) Do_Deselect(Points[i]);
- else Do_Select(Points[i]);
-
- } /* if */
- } /* for */
- break;
-
- case V_P: /* Persp */
- break;
-
- } /* switch */
-
- Group_Mode = TRUE;
-
- } /* Select_Area */
-
- void Hide_Selected_Points()
- /************************************************************************/
- /* */
- /* Hide all selected points and deselect them. */
- /* */
- /************************************************************************/
- {
- int i;
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count > 0 && Is_Selected(Points[i]) ) {
-
- Do_Hide(Points[i]);
- Points_Hidden = TRUE;
- } /* if */
-
- } /* for */
-
- Deselect_All();
-
- } /* Hide_Selected_Points */
-
- void Hide_Unselected_Points()
- /************************************************************************/
- /* */
- /* Hide all unselected points and deselect all. */
- /* */
- /************************************************************************/
- {
- int i;
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count > 0 && !Is_Selected(Points[i]) ) {
-
- Do_Hide(Points[i]);
- Points_Hidden = TRUE;
-
- } /* if */
-
- } /* for */
-
- Deselect_All();
-
- } /* Hide_Unselected_Points */
-
- void Show_All_Points()
- /************************************************************************/
- /* */
- /* Redisplay all hidden points. */
- /* */
- /************************************************************************/
- {
- int i;
-
- for (i = 0; i < Max_Nbr_Points; i++) {
-
- if (Points[i].Reference_Count > 0 && Is_Hidden(Points[i]) ) {
-
- Do_Unhide(Points[i]);
-
- } /* if */
-
- } /* for */
- Points_Hidden = FALSE;
-
- } /* Show_All_Points */
-