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 >
Wrap
C/C++ Source or Header
|
1992-10-25
|
46KB
|
1,569 lines
/* :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 */