/******************************************************************************
* CagdEdit.c - Editing tools of surfaces and Curves.			      *
*******************************************************************************
* Written by Gershon Elber, Sep. 91.					      *
******************************************************************************/

#include "cagd_loc.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
* Provides the way to modify/get a single control point into/from the curve. M
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:        Curve to be modified/query.                                  M
*   CtlPt:      New control point to be substituted into Crv. Must carry the M
*               same PType as Crv if to be written to Crv.                   M
*   Index:      In curve CRV's control polygon to substitute/query CtlPt.    M
*   Write:      If TRUE CtlPt is copied into Crv, if FALSE the point is      M
*               copied from Crv to CtlPt.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *: If Write is TRUE, the new modified curve, if WRITE is   M
*                    FALSE, NULL.                                            M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdEditSingleCrvPt, curve editing                                       M
*****************************************************************************/
CagdCrvStruct *CagdEditSingleCrvPt(CagdCrvStruct *Crv,
				   CagdCtlPtStruct *CtlPt,
				   int Index,
				   CagdBType Write)
{
    CagdBType
	IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
    int i,
	Length = Crv -> Length,
	MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
    CagdCrvStruct
	*NewCrv = Write ? CagdCrvCopy(Crv) : NULL;
    CagdRType
	**Points = Write ? NewCrv -> Points : Crv -> Points;

    if (Index < 0 || Index >= Length)
	CAGD_FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);

    if (Write) {
	if (Crv -> PType != CtlPt -> PtType)
	    CAGD_FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH);

	for (i = IsNotRational; i <= MaxCoord; i++)
	    Points[i][Index] = CtlPt -> Coords[i];
    }
    else {
        CtlPt -> PtType = Crv -> PType;

	for (i = IsNotRational; i <= MaxCoord; i++)
	    CtlPt -> Coords[i] = Points[i][Index];
    }

    return NewCrv;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
* Provides the way to modify/get a single control point into/from a surface. M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:        Surface to be modified/query.                                M
*   CtlPt:      New control point to be substituted into Srf. Must carry the M
*               same PType as Srf if to be written to Srf.                   M
*   UIndex, VIndex: In surface Srf's control mesh to substitute/query CtlPt. M
*   Write:      If TRUE CtlPt is copied into Srf, if FALSE the point is      M
*               copied from Srf to CtlPt.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *: If Write is TRUE, the new modified curve, if WRITE is   M
*                    FALSE, NULL.                                            M
*                                                                            *
* KEYWORDS:                                                                  M
*   CagdEditSingleSrfPt, surface editing                                     M
*****************************************************************************/
CagdSrfStruct *CagdEditSingleSrfPt(CagdSrfStruct *Srf,
				   CagdCtlPtStruct *CtlPt,
				   int UIndex,
				   int VIndex,
				   CagdBType Write)
{
    CagdBType
	IsNotRational = !CAGD_IS_RATIONAL_SRF(Srf);
    int i,
	ULength = Srf -> ULength,
	VLength = Srf -> VLength,
	MaxCoord = CAGD_NUM_OF_PT_COORD(Srf -> PType);
    CagdSrfStruct
	*NewSrf = Write ? CagdSrfCopy(Srf) : NULL;
    CagdRType
	**Points = Write ? NewSrf -> Points : Srf -> Points;

    if (UIndex < 0 || UIndex >= ULength ||
	VIndex < 0 || VIndex >= VLength)
	CAGD_FATAL_ERROR(CAGD_ERR_INDEX_NOT_IN_MESH);

    if (Write) {
	if (Srf -> PType != CtlPt -> PtType)
	    CAGD_FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH);

	for (i = IsNotRational; i <= MaxCoord; i++)
	    Points[i][CAGD_MESH_UV(NewSrf, UIndex, VIndex)] =
		CtlPt -> Coords[i];
    }
    else {
        CtlPt -> PtType = Srf -> PType;

	for (i = IsNotRational; i <= MaxCoord; i++)
	    CtlPt -> Coords[i] =
		Points[i][CAGD_MESH_UV(Srf, UIndex, VIndex)];
    }

    return NewSrf;
}
