Metropoli BBS
VIEWER: cagdcoer.c MODE: TEXT (ASCII)
/******************************************************************************
* CagdCoer.c - Handle point coercesions/conversions.			      *
*******************************************************************************
* Written by Gershon Elber, Aug. 90.					      *
******************************************************************************/

#include "cagd_loc.h"

/******************************************************************************
* Coerce Srf/Crv Point from index Index of Points array of Type PType to E2   *
* If however Index < 0 Points is considered single point.		      *
******************************************************************************/
void CagdCoerceToE2(CagdRType *E2Point, CagdRType *Points[CAGD_MAX_PT_SIZE],
					        int Index, CagdPointType PType)
{
    CagdBType
	IsRational = CAGD_IS_RATIONAL_PT(PType);
    int i,
        MaxCoord = CAGD_NUM_OF_PT_COORD(PType);
    CagdRType *Point;

    if (MaxCoord > 2) MaxCoord = 2;

    if (Index < 0) {			      /* Points is one single point. */
        Point = *Points;
	for (i = 1; i <= MaxCoord; i++)
	    *E2Point++ = IsRational ? Point[i] / Point[W] : Point[i];
    }
    else                         /* Points is a full arrays from Srf or Crv. */
	for (i = 1; i <= MaxCoord; i++)
	    *E2Point++ = IsRational ? Points[i][Index] / Points[W][Index] :
				      Points[i][Index];

    for (i = MaxCoord + 1; i <= 2; i++)
	*E2Point++ = 0.0;
}

/******************************************************************************
* Coerce Srf/Crv Point from index Index of Points array of Type PType to E3   *
* If however Index < 0 Points is considered single point.		      *
******************************************************************************/
void CagdCoerceToE3(CagdRType *E3Point, CagdRType *Points[CAGD_MAX_PT_SIZE],
						int Index, CagdPointType PType)
{
    CagdBType
	IsRational = CAGD_IS_RATIONAL_PT(PType);
    int i,
	MaxCoord = CAGD_NUM_OF_PT_COORD(PType);
    CagdRType *Point;

    if (MaxCoord > 3) MaxCoord = 3;

    if (Index < 0) {			      /* Points is one single point. */
	Point = *Points;
	for (i = 1; i <= MaxCoord; i++)
	    *E3Point++ = IsRational ? Point[i] / Point[W] : Point[i];
    }
    else                         /* Points is a full arrays from Srf or Crv. */
	for (i = 1; i <= MaxCoord; i++)
	    *E3Point++ = IsRational ? Points[i][Index] / Points[W][Index] :
				      Points[i][Index];

    for (i = MaxCoord + 1; i <= 3; i++)
	*E3Point++ = 0.0;
}

/******************************************************************************
* Coerce Srf/Crv Point from index Index of Points array of Type PType to P2   *
* If however Index < 0 Points is considered single point.		      *
******************************************************************************/
void CagdCoerceToP2(CagdRType *P2Point, CagdRType *Points[CAGD_MAX_PT_SIZE],
					        int Index, CagdPointType PType)
{
    CagdBType
	IsRational = CAGD_IS_RATIONAL_PT(PType);
    int i,
        MaxCoord = CAGD_NUM_OF_PT_COORD(PType);
    CagdRType *Point;

    if (MaxCoord > 2) MaxCoord = 2;

    if (Index < 0) {			      /* Points is one single point. */
        Point = *Points;
	*P2Point++ = IsRational ? Point[W] : 1.0;
	for (i = 1; i <= MaxCoord; i++)
	    *P2Point++ = Point[i];
    }
    else {                       /* Points is a full arrays from Srf or Crv. */
	*P2Point++ = IsRational ? Points[W][Index] : 1.0;
	for (i = 1; i <= MaxCoord; i++)
	    *P2Point++ = Points[i][Index];
    }

    for (i = MaxCoord + 1; i <= 2; i++)
	*P2Point++ = 0.0;
}

/******************************************************************************
* Coerce Srf/Crv Point from index Index of Points array of Type PType to P3   *
* If however Index < 0 Points is considered single point.		      *
******************************************************************************/
void CagdCoerceToP3(CagdRType *P3Point, CagdRType *Points[CAGD_MAX_PT_SIZE],
						int Index, CagdPointType PType)
{
    CagdBType
	IsRational = CAGD_IS_RATIONAL_PT(PType);
    int i,
	MaxCoord = CAGD_NUM_OF_PT_COORD(PType);
    CagdRType *Point;

    if (MaxCoord > 3) MaxCoord = 3;

    if (Index < 0) {			      /* Points is one single point. */
	Point = *Points;
	*P3Point++ = IsRational ? Point[W] : 1.0;
	for (i = 1; i <= MaxCoord; i++)
	    *P3Point++ = Point[i];
    }
    else {                       /* Points is a full arrays from Srf or Crv. */
	*P3Point++ = IsRational ? Points[W][Index] : 1.0;
	for (i = 1; i <= MaxCoord; i++)
	    *P3Point++ = Points[i][Index];
    }

    for (i = MaxCoord + 1; i <= 3; i++)
	*P3Point++ = 0.0;
}

/******************************************************************************
* Coerce Points array of point type OldPType to point type NewPType, in place *
******************************************************************************/
void CagdCoercePointsTo(CagdRType *Points[], int Len,
			CagdPointType OldPType, CagdPointType NewPType)
{
    int i, j,
	OldIsRational = CAGD_IS_RATIONAL_PT(OldPType),
	OldNumOfCoords = CAGD_NUM_OF_PT_COORD(OldPType),
	NewIsRational = CAGD_IS_RATIONAL_PT(NewPType),
	NewNumOfCoords = CAGD_NUM_OF_PT_COORD(NewPType);
    CagdRType *NewPoints[CAGD_MAX_PT_SIZE], Pt[CAGD_MAX_PT_SIZE];
	

    for (i = !NewIsRational; i <= NewNumOfCoords; i++)
	NewPoints[i] = (CagdRType *) CagdMalloc(sizeof(CagdRType) * Len);

    for (i = 0; i < Len; i++) {
	switch (NewPType) {
	    case CAGD_PT_E2_TYPE:
	        CagdCoerceToE2(Pt, Points, i, OldPType);
	        break;
	    case CAGD_PT_E3_TYPE:
	        CagdCoerceToE3(Pt, Points, i, OldPType);
	        break;
	    case CAGD_PT_P2_TYPE:
	        CagdCoerceToP2(Pt, Points, i, OldPType);
	        break;
	    case CAGD_PT_P3_TYPE:
	        CagdCoerceToP3(Pt, Points, i, OldPType);
	        break;
	    default:
		FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
		break;
	}

	if (NewIsRational)
	    for (j = 0; j <= NewNumOfCoords; j++) NewPoints[j][i] = Pt[j];
	else
	    for (j = 1; j <= NewNumOfCoords; j++) NewPoints[j][i] = Pt[j - 1];
    }

    /* Replace old rep. with new. */
    for (i = !OldIsRational; i <= OldNumOfCoords; i++)
	CagdFree((VoidPtr) Points[i]);
    for (i = !NewIsRational; i <= NewNumOfCoords; i++)
	Points[i] = NewPoints[i];
    for (; i <= CAGD_MAX_PT_COORD; i++)
	Points[i] = NULL;
}

/******************************************************************************
* Coerce Crv to point type PType.					      *
******************************************************************************/
CagdCrvStruct *CagdCoerceCrvTo(CagdCrvStruct *Crv, CagdPointType PType)
{
    Crv = CagdCrvCopy(Crv);
    CagdCoercePointsTo(Crv -> Points, Crv -> Length, Crv -> PType, PType);
    Crv -> PType = PType;
    return Crv;
}

/******************************************************************************
* Coerce Srf to point type PType.					      *
******************************************************************************/
CagdSrfStruct *CagdCoerceSrfTo(CagdSrfStruct *Srf, CagdPointType PType)
{
    Srf = CagdSrfCopy(Srf);
    CagdCoercePointsTo(Srf -> Points, Srf -> ULength * Srf -> VLength,
		       Srf -> PType, PType);
    Srf -> PType = PType;
    return Srf;
}

/******************************************************************************
* Returns the point which includes the two provided.			      *
******************************************************************************/
CagdPointType CagdMergePointType(CagdPointType PType1, CagdPointType PType2)
{
    CagdBType
	IsRational = CAGD_IS_RATIONAL_PT(PType1) || CAGD_IS_RATIONAL_PT(PType2);
    int NumCoords = MAX(CAGD_NUM_OF_PT_COORD(PType1),
		        CAGD_NUM_OF_PT_COORD(PType2));

    return CAGD_MAKE_PT_TYPE(IsRational, NumCoords);
}
[ RETURN TO DIRECTORY ]