//
//////////////////////////////////////////////////////////////////////////////
//
//  Copyright 2013 Autodesk, Inc.  All rights reserved.
//
//  Use of this software is subject to the terms of the Autodesk license 
//  agreement provided at the time of installation or download, or which 
//  otherwise accompanies this software in either electronic or hard copy form.   
//
//////////////////////////////////////////////////////////////////////////////
//
//
// DESCRIPTION:
//
// The AcDbNurbSurface class is the interface class for representing
// ASM NURBS surfaces inside AutoCAD.  

#pragma once

#include "dbsurf.h"
class AcGeKnotVector;
class AcGeNurbSurface;

#pragma pack(push, 8)

class ACDB_PORT AcDbNurbSurface: public AcDbSurface
{
public:

    AcDbNurbSurface();
    AcDbNurbSurface(int uDegree, int vDegree, bool rational,
                    int uNumControlPoints, int vNumControlPoints,
                    const AcGePoint3dArray& ctrlPts,
                    const AcGeDoubleArray& weights,
                    const AcGeKnotVector& uKnots, const AcGeKnotVector& vKnots );

    virtual ~AcDbNurbSurface();
    ACDB_DECLARE_MEMBERS(AcDbNurbSurface);

    //////////////////////////////////////////////////////////
    // NURBS surface methods
    //////////////////////////////////////////////////////////

    // get/set all data 
    Acad::ErrorStatus get (int& uDegree, int& vDegree, bool& rational,
                            int& uNumControlPoints, int& vNumControlPoints,
                            AcGePoint3dArray& ctrlPts, 
                            AcGeDoubleArray& weights,
                            AcGeKnotVector& uKnots, AcGeKnotVector& vKnots) const;
    Acad::ErrorStatus set (int uDegree, int vDegree, bool rational,
                            int uNumControlPoints, int vNumControlPoints,
                            const AcGePoint3dArray& ctrlPts,
                            const AcGeDoubleArray& weights,
                            const AcGeKnotVector& uKnots, const AcGeKnotVector& vKnots);    

    // get/set control points 
    Acad::ErrorStatus getControlPoints(int& uCount, int& vCount, AcGePoint3dArray& points) const;
    Acad::ErrorStatus setControlPoints(int uCount, int vCount, const AcGePoint3dArray& points);

    Acad::ErrorStatus getControlPointAt(int uIndex, int vIndex, AcGePoint3d& point) const;
    Acad::ErrorStatus setControlPointAt(int uIndex, int vIndex, const AcGePoint3d& point);

    // get the number of control points.
    Acad::ErrorStatus getNumberOfControlPointsInU(int& count) const;
    Acad::ErrorStatus getNumberOfControlPointsInV(int& count) const;

    // get knots
    Acad::ErrorStatus getUKnots(AcGeKnotVector& knots) const;
    Acad::ErrorStatus getVKnots(AcGeKnotVector& knots) const;

    // get the number of knots in u or v
    Acad::ErrorStatus getNumberOfKnotsInU(int& count) const;
    Acad::ErrorStatus getNumberOfKnotsInV(int& count) const;

    Acad::ErrorStatus getWeight(int uIndex, int vIndex, double& weight ) const;
    Acad::ErrorStatus setWeight(int uIndex, int vIndex, double weight );

    // Evaluate position, first and second derivatives
    Acad::ErrorStatus evaluate(double u, double v, AcGePoint3d& pos) const;
    Acad::ErrorStatus evaluate(double u, double v, AcGePoint3d& pos, AcGeVector3d& uDeriv, AcGeVector3d& vDeriv) const;
    Acad::ErrorStatus evaluate(double u, double v, AcGePoint3d& pos, AcGeVector3d& uDeriv, AcGeVector3d& vDeriv,
                                AcGeVector3d& uuDeriv, AcGeVector3d& uvDeriv, AcGeVector3d& vvDeriv) const;
    Acad::ErrorStatus evaluate(double u, double v, int derivDegree, AcGePoint3d& point, AcGeVector3dArray& derivatives) const;

    // get degree
    Acad::ErrorStatus getDegreeInU(int& degree) const;
    Acad::ErrorStatus getDegreeInV(int& degree) const;

    // is closed
    Acad::ErrorStatus isClosedInU(bool& isClosed) const;
    Acad::ErrorStatus isClosedInV(bool& isClosed) const;

    // is periodic
    Acad::ErrorStatus isPeriodicInU(bool& isPeriodic) const;
    Acad::ErrorStatus isPeriodicInV(bool& isPeriodic) const;

    // get period
    Acad::ErrorStatus getPeriodInU(double& period) const;
    Acad::ErrorStatus getPeriodInV(double& period) const;

    // test if rational 
    Acad::ErrorStatus isRational(bool& isRational) const;

    // test if planar
    Acad::ErrorStatus isPlanar(bool& isPlanar, AcGePoint3d& ptOnSurface, AcGeVector3d& normal) const;

    // test if a point is on the surface
    Acad::ErrorStatus isPointOnSurface(const AcGePoint3d& point, bool& onSurface) const;

    // get normal
    Acad::ErrorStatus getNormal(double u, double v, AcGeVector3d& normal) const;

    // get the simple patches in u v direction
    Acad::ErrorStatus getNumberOfSpansInU(int& span) const;
    Acad::ErrorStatus getNumberOfSpansInV(int& span) const;

    // get the u and v isolines.
    Acad::ErrorStatus getIsolineAtU(double u, AcArray<AcDbCurve*>& lineSegments) const;
    Acad::ErrorStatus getIsolineAtV(double v, AcArray<AcDbCurve*>& lineSegments) const;

    // knot insertion 
    Acad::ErrorStatus InsertKnotAtU(double u);
    Acad::ErrorStatus InsertKnotAtV(double v);

    // add / remove control points
    Acad::ErrorStatus InsertControlPointsAtU(double u, const AcGePoint3dArray& vCtrlPts, const AcGeDoubleArray& vWeights);
    Acad::ErrorStatus InsertControlPointsAtV(double v, const AcGePoint3dArray& uCtrlPts, const AcGeDoubleArray& uWeights);
    Acad::ErrorStatus RemoveControlPointsAtU(int uIndex);
    Acad::ErrorStatus RemoveControlPointsAtV(int vIndex);

    // rebuild
    Acad::ErrorStatus rebuild(int uDegree, int vDegree, int numUCtrlPts, int numVCtrlPts, bool bRestore = false);

    // adjust a point's location and tangent 
    Acad::ErrorStatus modifyPositionAndTangent(double u, double v, const AcGePoint3d& point,
                                 const AcGeVector3d* uDeriv = NULL, const AcGeVector3d* vDeriv = NULL);

    // get the u and v for a point
    Acad::ErrorStatus getParameterOfPoint(const AcGePoint3d& point, double& u, double& v) const;
   
    // Overridden methods from AcDbEntity
    void              dragStatus         (const AcDb::DragStat status);

    
protected:
    virtual Acad::ErrorStatus subGetClassID(CLSID* pClsid) const;
};

#pragma pack(pop)

