/******************************************************************************
* Orthotom.c - computation of k-orthotomics of curves and surfaces.	      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, February 97					      *
******************************************************************************/

#include "symb_loc.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Computes the K-orthotomic of a curve with respect to point P:            M
*       P + K < (C(t) - P), N(t) > N(t)                                      V
*   See "Fundamentals of Computer Aided Geometric Design", by J. Hoschek and M
* and D. Lasser.							     M
*                                                                            *
* PARAMETERS:                                                                M
*   Crv:     To compute its K-orthotomic                                     M
*   P:	     The points to which the K-orthotomic is computed for Crv for.   M
*   K:       The magnitude of the orthotomic function.                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdCrvStruct *:  The K-orthotomic                                       M
*                                                                            *
* SEE ALSO:                                                                  M
*   SymbSrfOrthotomic                                                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   SymbCrvOrthotomic                                                        M
*****************************************************************************/
CagdCrvStruct *SymbCrvOrthotomic(CagdCrvStruct *Crv,
				 CagdPType P,
				 CagdRType K)
{
    CagdPType PTmp;
    CagdCrvStruct *NCrv, *TCrv1, *TCrv2, *TCrv3, *Orthotomic;

    if (CAGD_NUM_OF_PT_COORD(Crv -> PType) != 2) {
        SYMB_FATAL_ERROR(SYMB_ERR_ONLY_2D);
	return NULL;
    }

    NCrv = SymbCrv2DUnnormNormal(Crv);

    PT_COPY(PTmp, P);
    PT_SCALE(PTmp, -1.0);

    TCrv2 = CagdCrvCopy(Crv);
    CagdCrvTransform(TCrv2, PTmp, 1.0);
    TCrv1 = SymbCrvDotProd(TCrv2, NCrv);
    CagdCrvFree(TCrv2);

    TCrv3 = SymbCrvMultScalar(NCrv, TCrv1);
    CagdCrvFree(TCrv1);
    
    TCrv1 = SymbCrvDotProd(NCrv, NCrv);
    if (CAGD_IS_RATIONAL_CRV(TCrv1)) {
	TCrv2 = SymbCrvInvert(TCrv1);

	Orthotomic = SymbCrvMultScalar(TCrv3, TCrv2);
	CagdCrvFree(TCrv2);
	CagdCrvFree(TCrv3);
    }
    else {
	CagdCrvStruct *CrvW, *CrvX, *CrvY, *CrvZ;

	SymbCrvSplitScalar(TCrv3, &CrvW, &CrvX, &CrvY, &CrvZ);

	CagdMakeCrvsCompatible(&TCrv1, &CrvX, TRUE, TRUE);
	CagdMakeCrvsCompatible(&TCrv1, &CrvY, TRUE, TRUE);
	CagdMakeCrvsCompatible(&CrvX,  &CrvY, TRUE, TRUE);

	Orthotomic = SymbCrvMergeScalar(TCrv1, CrvY, CrvX, NULL);
	CagdCrvFree(CrvX);
	CagdCrvFree(CrvY);
    }
    CagdCrvFree(TCrv1);

    PT_CLEAR(PTmp);
    CagdCrvTransform(Orthotomic, PTmp, K);
    CagdCrvTransform(Orthotomic, P, 1.0);

    return Orthotomic;
}

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Computes the K-orthotomic of a surface with respect to point P:          M
*       P + K < (S(u,v) - P), N(u,v) > N(u,v)                                V
*   See "Fundamentals of Computer Aided Geometric Design, by J. Hoschek and  M
* and D. Lasser.							     M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:     To compute its K-orthotomic                                     M
*   P:	     The points to which the K-orthotomic is computed for Srf for.   M
*   K:       The magnitude of the orthotomic function.                       M
*                                                                            *
* RETURN VALUE:                                                              M
*   CagdSrfStruct *:  The K-orthotomic                                       M
*                                                                            *
* SEE ALSO:                                                                  M
*   SymbCrvOrthotomic                                                        M
*                                                                            *
* KEYWORDS:                                                                  M
*   SymbSrfOrthotomic                                                        M
*****************************************************************************/
CagdSrfStruct *SymbSrfOrthotomic(CagdSrfStruct *Srf,
				 CagdPType P,
				 CagdRType K)
{
    CagdPType PTmp;
    CagdSrfStruct *NSrf, *TSrf1, *TSrf2, *TSrf3, *Orthotomic;

    NSrf = SymbSrfNormalSrf(Srf);

    PT_COPY(PTmp, P);
    PT_SCALE(PTmp, -1.0);

    TSrf2 = CagdSrfCopy(Srf);
    CagdSrfTransform(TSrf2, PTmp, 1.0);
    TSrf1 = SymbSrfDotProd(TSrf2, NSrf);
    CagdSrfFree(TSrf2);

    TSrf3 = SymbSrfMultScalar(NSrf, TSrf1);
    CagdSrfFree(TSrf1);
    
    TSrf1 = SymbSrfDotProd(NSrf, NSrf);
    if (CAGD_IS_RATIONAL_SRF(TSrf1)) {
	TSrf2 = SymbSrfInvert(TSrf1);

	Orthotomic = SymbSrfMultScalar(TSrf3, TSrf2);
	CagdSrfFree(TSrf2);
	CagdSrfFree(TSrf3);
    }
    else {
	CagdSrfStruct *SrfW, *SrfX, *SrfY, *SrfZ;

	SymbSrfSplitScalar(TSrf3, &SrfW, &SrfX, &SrfY, &SrfZ);

	CagdMakeSrfsCompatible(&TSrf1, &SrfX, TRUE, TRUE, TRUE, TRUE);
	CagdMakeSrfsCompatible(&TSrf1, &SrfY, TRUE, TRUE, TRUE, TRUE);
	CagdMakeSrfsCompatible(&SrfX,  &SrfY, TRUE, TRUE, TRUE, TRUE);

	Orthotomic = SymbSrfMergeScalar(TSrf1, SrfY, SrfX, SrfZ);
	CagdSrfFree(SrfX);
	CagdSrfFree(SrfY);
    }
    CagdSrfFree(TSrf1);

    PT_CLEAR(PTmp);
    CagdSrfTransform(Orthotomic, PTmp, K);
    CagdSrfTransform(Orthotomic, P, 1.0);

    return Orthotomic;
}

