/******************************************************************************
* SrfCntr.c - contour a surface with a plane.				      *
*******************************************************************************
* (C) Gershon Elber, Technion, Israel Institute of Technology                 *
*******************************************************************************
* Written by Gershon Elber, June. 95.					      *
******************************************************************************/

#include "irit_sm.h"
#include "cagd_lib.h"
#include "symb_lib.h"
#include "iritprsr.h"
#include "ip_cnvrt.h"
#include "bool_lib.h"
#include "allocate.h"
#include "primitiv.h"
#include "geomat3d.h"
#include "user_loc.h"

/*****************************************************************************
* DESCRIPTION:                                                               M
*   Computes the intersection of a freeform surface and a plane by	     M
* approximating the surface by polygons and calling Boolean tools.	     M
*   If PSrfObj is a scalar surface then it is promoted first into a          M
* 3D Euclidean surface with UV as YZ coordinates (and X has scalar field).   M
*                                                                            *
* PARAMETERS:                                                                M
*   Srf:     To approximate its intersection with the given plane.           M
*   Plane:   To intersect with the given surface. If NULL the XY plane is    M
*	     used.							     M
*   Fineness:   Control of polygonal approximation of surface. See	     M
*	     IritSurface2Polygons function.				     M
*                                                                            *
* RETURN VALUE:                                                              M
*   IPPolygonStruct *:   A list of polylines approximating the contour.      M
*                                                                            *
* SEE ALSO:                                                                  M
*   UserCntrScalarFieldAndEval						     M
*                                                                            *
* KEYWORDS:                                                                  M
*   UserCntrSrfWithPlane, contouring                                         M
*****************************************************************************/
IPPolygonStruct *UserCntrSrfWithPlane(CagdSrfStruct *Srf,
				      PlaneType Plane,
				      RealType FineNess)
{
    int OldInterCurve;
    CagdRType Width, t;
    CagdPType SrfCenter, PlaneCenter, Size;
    CagdBBoxStruct BBox;
    CagdSrfStruct *Srf3Space;
    IPObjectStruct *PlaneObj, *SrfObj, *CntrObj;
    IPPolygonStruct *CntrPoly, *SrfPolys;

    switch (CAGD_NUM_OF_PT_COORD(Srf -> PType)) {
	case 1:
	case 2:
	    if (CAGD_IS_RATIONAL_SRF(Srf))
	        Srf3Space = CagdCoerceSrfTo(Srf, CAGD_PT_P3_TYPE);
	    else
	        Srf3Space = CagdCoerceSrfTo(Srf, CAGD_PT_E3_TYPE);
	    break;
	default:
	    Srf3Space = Srf;
	    break;
    }

    SrfPolys = IritSurface2Polygons(Srf3Space, TRUE, FineNess, FALSE, FALSE);
    
    /* Find location of surface so we can position the plane properly. */
    CagdSrfBBox(Srf3Space, &BBox);
    PT_BLEND(SrfCenter, BBox.Min, BBox.Max, 0.5);
    PT_SUB(Size, BBox.Max, BBox.Min);
    Width = MAX(MAX(Size[0], Size[1]), Size[2]);

    CGPointFromLinePlane(SrfCenter, Plane, Plane, PlaneCenter, &t);
    PlaneObj = PrimGenPOLYDISKObject(Plane, PlaneCenter, Width * 10.0);

    SrfObj = GenPOLYObject(SrfPolys);

    OldInterCurve = BoolSetOutputInterCurve(TRUE);

    CntrObj = BooleanAND(SrfObj, PlaneObj);

    IPFreeObject(SrfObj);
    IPFreeObject(PlaneObj);

    BoolSetOutputInterCurve(OldInterCurve);

    CntrPoly = CntrObj -> U.Pl;
    CntrObj -> U.Pl = NULL;
    IPFreeObject(CntrObj);

    if (Srf != Srf3Space)
        CagdSrfFree(Srf3Space);

    return IritPrsrMergePolylines(CntrPoly);
}
