#pragma once
#include "McDbCurve.h"

class McDbSplineImp;
// -------------------------------------------------------------------------
// Summary:
// 		样条线类型
// Remarks:
// 		例如:创建一个样条线代码
// 		<code>
// 			CDrawSplineJig::CDrawSplineJig(void)
// 			{
// 				m_pSpline		= NULL;
// 				m_degree		= 3;
// 				m_fitTolerance	= AcGeContext::gTol.equalVector(); 
// 				m_periodic      = Adesk::kFalse;
// 			}
// 
// 			CDrawSplineJig::~CDrawSplineJig(void)
// 			{
// 				ASSERT(m_pSpline == NULL);
// 			}
// 
// 
// 			AcEdJig::DragStatus 
// 			CDrawSplineJig::sampler()
// 			{
// 
// 				AcGePoint3d point;
// 				AcEdJig::DragStatus ret = acquirePoint(point);
// 				if(ret == AcEdJig::kNormal)
// 				{
// 					McGePoint3dArray tmpFitPoint;
// 					tmpFitPoint = m_aryFitPoint;
// 					tmpFitPoint.append(point);
// 
// 
// 					m_getPt = point;
// 					if(tmpFitPoint.length() > 1 && m_pSpline != NULL)
// 					{
// 						m_pSpline->setFitData(tmpFitPoint,m_degree,m_fitTolerance,
// 							m_startTangent,m_endTangent,m_periodic);
// 					}
// 				}
// 				return ret;
// 			}
// 
// 			Adesk::Boolean CDrawSplineJig::update()
// 			{
// 				return Adesk::kTrue;
// 			}
// 
// 			AcDbEntity* CDrawSplineJig::entity() const
// 			{
// 				return m_pSpline;
// 			}
// 
// 			bool    CDrawSplineJig::DoIt()
// 			{
// 
// 
// 				ads_point pt;
// 				if(acedGetPoint(NULL,_T("\n 指定第一个点："),pt) != RTNORM)
// 				{
// 					return false;
// 				}
// 
// 				m_aryFitPoint.append(McGePoint3d(pt[X],pt[Y],pt[Z]) );
// 
// 				m_pSpline = new AcDbSpline;
// 
// 				// 取每一个点。
// 				bool isSuc = false;
// 				while(true)
// 				{
// 					acutPrintf(_T("\n 指定下一个点 <回车退出>:") );
// 					if(drag() != AcEdJig::kNormal)
// 					{
// 						break;
// 					}
// 					m_aryFitPoint.append(m_getPt);
// 					isSuc = true;
// 				}
// 				delete m_pSpline;
// 				m_pSpline = NULL;
// 
// 				if(isSuc)
// 				{
// 					AcDbSpline* m_pAddSpline = new AcDbSpline;
// 					m_pAddSpline->setFitData(m_aryFitPoint,m_degree,m_fitTolerance,
// 						m_startTangent,m_endTangent,m_periodic);
// 
// 					MrxDbgUtils::addToCurrentSpaceAndClose(m_pAddSpline);
// 				}
// 
// 
// 				return isSuc;
// 			}
// 		</code>
//		离散曲线的代码
// 		<code>
// 			void CSampleCurveJig::DoIt()
// 			{
// 				ads_name entName;
// 				ads_point pt;
// 				if(acedEntSel(_T("\n 选择需要离散的实体:"),entName,pt) != RTNORM)
// 				{
// 					return;
// 				}
// 				AcDbObjectId objId;
// 				if(acdbGetObjectId(objId,entName) != Acad::eOk)
// 					return;
// 
// 				AcDbObjectPointer<AcDbCurve> spCurve(objId,AcDb::kForRead);
// 				if(spCurve.openStatus() != Acad::eOk)
// 				{
// 					acutPrintf(_T("\n 请选择曲线实体"));
// 					return ;
// 				}
// 
// 				if(AcDbSpline::cast(spCurve.object() ) != NULL
// 					|| AcDbArc::cast(spCurve.object() ) != NULL
// 					|| AcDbCircle::cast(spCurve.object() ) != NULL 
// 					|| AcDbEllipse::cast(spCurve.object() ) != NULL 
// 					|| AcDbPolyline::cast(spCurve.object() ) != NULL 
// 					)
// 				{
// 					double approxEps	= 0.1;			// 离散后的最小弧的弧高。
// 					AcGePoint3dArray pointArray;		// 返离后的点数组。
// 					AcGeDoubleArray  paramArray;
// 
// 					spCurve->InnerGetSamplePoints(approxEps,pointArray,paramArray);
// 
// 					if(pointArray.isEmpty() )
// 					{
// 						acutPrintf(_T("\n 离散失败"));
// 					}
// 					else
// 					{
// 						AcGePoint3d tmpBt(pt[0],pt[1],pt[2]);
// 						// 报离散后的点，开始拖放，定位。
// 						m_pEnt = new CSampleCurveEnt(pointArray,tmpBt);
// 
// 						if(drag() == AcEdJig::kNormal)
// 						{
// 							AcGePoint3dArray aryPt;
// 							m_pEnt->GetNewPosAryPt(aryPt);
// 
// 							for(int i = 1; i < aryPt.length();i++)
// 							{
// 								AcDbLine* pLine = new AcDbLine(aryPt[i -1],aryPt[i]);
// 								CTestCommands::AddToModelSpace(pLine,acdbCurDwg() );
// 								pLine->close();
// 
// 							}
// 
// 						}
// 
// 						delete m_pEnt;
// 						m_pEnt = NULL;
// 
// 					}
// 				}
// 				else
// 				{
// 					acutPrintf(_T("\n 请选择样条线实体"));
// 				}
// 
// 			}
// 		</code>
// -------------------------------------------------------------------------
class ARXDLL McDbSpline : public  McDbCurve
{
public:
	// -------------------------------------------------------------------------
	// Summary:
	// 		申明类型信息
	// -------------------------------------------------------------------------
	MCDB_DECLARE_MEMBERS(McDbSpline);

	// -------------------------------------------------------------------------
	// Summary:
	// 		构造函数
	// -------------------------------------------------------------------------
	McDbSpline(void);

	// -------------------------------------------------------------------------
	// Summary:
	// 		析构函数
	// -------------------------------------------------------------------------
	virtual ~McDbSpline(void);


	//:Ignore

	Mcad::ErrorStatus getNurbsData(
		int&              degree,
		Mdesk::Boolean&   rational,
		Mdesk::Boolean&   closed,
		Mdesk::Boolean&   periodic,
		McGePoint3dArray& controlPoints,
		McGeDoubleArray&  knots,
		McGeDoubleArray&  weights,
		double&           controlPtTol,
		double&           knotTol) const;


	Mcad::ErrorStatus setNurbsData(
		int                  degree,
		Mdesk::Boolean       rational,
		Mdesk::Boolean       closed,
		Mdesk::Boolean       periodic,
		const McGePoint3dArray& controlPoints,
		const McGeDoubleArray& knots,
		const McGeDoubleArray& weights,
		double               controlPtTol,
		double               knotTol);

	//:End Ignore

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回样条线的拟合数据
	// Parameters:
	//		fitPoints		-		返回样条线拟合点数组
	//		degree          -		暂没有使用
	//		tangentsExist   -		暂没有使用
	//		startTangent    -		样条线开始位置处的切线向量
	//		endTangent      -		样条线结束位置处的切线向量
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus getFitData(
		McGePoint3dArray&  fitPoints,
		int&               degree,
		double&            fitTolerance,
		Mdesk::Boolean&    tangentsExist,
		McGeVector3d&      startTangent,
		McGeVector3d&      endTangent) const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置样条线的拟合数据
	// Parameters:
	//		fitPoints		-	    样条线拟合点数组
	//		degree          -		暂没有使用
	//		tangentsExist   -		暂没有使用
	//		startTangent    -		样条线开始位置处的切线向量
	//		endTangent      -		样条线结束位置处的切线向量
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus setFitData(
		const McGePoint3dArray&  fitPoints, 
		int                   degree =  3, 
		mxreal                fitTolerance = McGeContext::gTol.equalVector(), 
		const McGeVector3d&   startTangent = McGeVector3d::kIdentity, 
		const McGeVector3d&   endTangent = McGeVector3d::kIdentity,
		Mdesk::Boolean       periodic = Mdesk::kFalse,
		bool isReCalcControlPoint = true);


	//:Ignore

	virtual Mdesk::Boolean    worldDraw(McGiWorldDraw * wd);

	virtual Mcad::ErrorStatus dwgInFields(McDbDwgFiler* pFiler);

	virtual Mcad::ErrorStatus dwgOutFields(McDbDwgFiler* pFiler) const;

	virtual Mcad::ErrorStatus getGeomExtents(McDbExtents& extents, bool roughCalculation = true) const;

	virtual Mcad::ErrorStatus InnerGetSamplePoints(
		double approxEps, McGePoint3dArray& pointArray,
		McGeDoubleArray& paramArray) const;

	virtual Mcad::ErrorStatus getStartParam(double&) const;

	virtual Mcad::ErrorStatus getEndParam(double&) const;

	virtual Mcad::ErrorStatus getDistAtParam(double param, double& dist) const;

	virtual Mcad::ErrorStatus getClosestPointTo(const McGePoint3d& givenPnt,
		McGePoint3d& pointOnCurve,
		Mdesk::Boolean extend
		= Mdesk::kFalse) const;



	virtual Mcad::ErrorStatus   getOsnapPoints(
		McDb::OsnapMode     osnapMode,
		int                 gsSelectionMark,
		const McGePoint3d&  pickPoint,
		const McGePoint3d&  lastPoint,
		const McGeMatrix3d& viewXform,
		McGePoint3dArray&   snapPoints,
		McDbIntArray&       geomIds) const;

	virtual Mcad::ErrorStatus   transformBy(const McGeMatrix3d& xform);

	// 	virtual Mcad::ErrorStatus getOffsetCurves(double offsetDist,
	// 		McDbVoidPtrArray& offsetCurves) const;

	virtual Mcad::ErrorStatus getOffsetCurvesEx(double offsetDist,
		McDbVoidPtrArray& offsetCurves, McGePoint3d ptOffsetRef) const;

	virtual Mcad::ErrorStatus getSplitCurves(const McGeDoubleArray& params,
		McDbVoidPtrArray& curveSegments) const;

	virtual Mcad::ErrorStatus getSplitCurves(const McGePoint3dArray& points,
		McDbVoidPtrArray& curveSegments) const;

	virtual Mcad::ErrorStatus Mirror(McGePoint3d mirrorPt1, McGePoint3d mirrorPt2);

	virtual Mcad::ErrorStatus getFirstDeriv(double param,
		McGeVector3d& firstDeriv) const;

	virtual  Mcad::ErrorStatus intersectWith(const McDbEntity* pEnt,
		McDb::Intersect intType,
		McGePoint3dArray& points,
		int thisGsMarker = 0,
		int otherGsMarker = 0,
		int iExtendDirection = McDb::kExAll
	) const;

	virtual Mcad::ErrorStatus getFirstDeriv(const McGePoint3d& pt,
		McGeVector3d& firstDeriv) const;

	virtual Mcad::ErrorStatus   getGripPoints(
		McGePoint3dArray&  gripPoints,
		McGeIntArray&  osnapModes,
		McGeIntArray&  geomIds) const;

	virtual Mcad::ErrorStatus moveGripPointsAt(const McGeIntArray& indices,
		const McGeVector3d& offset);

	virtual Mcad::ErrorStatus getPointAtParam(double param, McGePoint3d& pt) const;


	virtual Mcad::ErrorStatus getParamAtPoint(const McGePoint3d& pt, double& param)const;



	virtual Mcad::ErrorStatus getStartPoint(McGePoint3d&) const;

	virtual Mcad::ErrorStatus getEndPoint(McGePoint3d&) const;

	virtual Mcad::ErrorStatus getDistAtPoint(const McGePoint3d&, double&)const;

	virtual Mcad::ErrorStatus getPointAtDist(double, McGePoint3d&) const;

	//:End Ignore

	inline McDbSplineImp* getMcDbSplineImp() const {
		return (McDbSplineImp*)m_pImp;
	}


};
