#pragma once
#include "McDbCurve.h"
class McDbPolylineImp;

// -------------------------------------------------------------------------
// Summary:
// 		多段线类型
// Remarks:
// 		例如:MxDrawX.ocx中绘PL线的代码
// 		<code>
// 			McDbPolyline* MxDrawXDrawPath::MakePolyline(mxreal dW)
// 			{
// 				if(m_vecData.size() < 2)
// 					return NULL;
// 
// 				McDbPolyline* pPL = new McDbPolyline;
// 
// 				bool isHaveWidth = false;
// 				for(unsigned int i = 0; i < m_vecData.size();i++)
// 				{
// 
// 					pPL->addVertexAt(m_vecData[i].pt,
// 						m_vecData[i].dBulge,
// 						m_vecData[i].dStartWidth,
// 						m_vecData[i].dEndWidth
// 						);
// 					if((m_vecData[i].dStartWidth > 0 )
// 						|| (m_vecData[i].dEndWidth > 0)
// 						)
// 					{
// 						isHaveWidth = true;
// 					}
// 				}
// 
// 				if(m_isClosed)
// 					pPL->setClosed(Mdesk::kTrue);
// 
// 				if((!isHaveWidth) 
// 					&& (!MxT::IsZero(dW)) 
// 					)
// 				{
// 					pPL->setConstantWidth(dW);
// 				}
// 
// 				ClaerData();
// 
// 				return pPL;
// 			}
// 
// 			LONG CMxDrawXCtrl::DrawPathToPolyline(void)
// 			{
// 				AFX_MANAGE_STATE(AfxGetStaticModuleState());
// 
// 				// TODO: 在此添加调度处理程序代码
// 				McDbPolyline* pPolyline = m_pDrawPath->MakePolyline(m_dLineWidth);
// 				if(pPolyline == NULL)
// 					return 0;
// 
// 				std::unique_ptr<MxDrawXDrawFun> spDrawFun(DrawFun() );
// 				return spDrawFun->AddToCurrentSpace(pPolyline);
// 			}
// 		</code>
//		创建Pl线代码
// 		<code>
// 			AcDbPolyline* pPL = new AcDbPolyline;
// 			pPL->setConstantWidth(dLineWidth);
// 			pPL->addVertexAt(0,pt1.convert2d(AcGePlane::kXYPlane));
// 			pPL->addVertexAt(1,pt2.convert2d(AcGePlane::kXYPlane));
// 			return AddToModelSpace(pPL,pDatabase);
// 		</code>
// -------------------------------------------------------------------------
class ARXDLL McDbPolyline : public McDbCurve
{
public:
	enum  PolylineType
	{
		kLwPolyline = 0,
		k2dPolyline = 1,
		k3dPolyline = 2
	};

	// -------------------------------------------------------------------------
	// Summary:
	// 		申明类型信息
	// -------------------------------------------------------------------------
	MCDB_DECLARE_MEMBERS(McDbPolyline);

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

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

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多线段是否闭合
	// Parameters:
	// 		bClosed	-	是否闭合 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	void              setClosed       (Mdesk::Boolean bClosed);
	

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置多线段的固定宽度
	// Parameters:
	// 		dWdith	-	线段的固定宽度 
	// Returns:
	// 		如果成功返回Mcad::eOk，如果传递的数据非法则返回Mcad::eInvalidInput
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus setConstantWidth(mxreal dWdith);
	
	// -------------------------------------------------------------------------
	// Summary:
	// 		返回多线段是否闭合
	// -------------------------------------------------------------------------
	Mdesk::Boolean    isClosed        ()                        const;  

	

	// -------------------------------------------------------------------------
	// Summary:
	// 		得到多线段的固定宽度
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus getConstantWidth(mxreal&)                 const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		向Polyline增加新的一个端点
	// Parameters:
	//		index			-	新端点插入位置
	//		pt      		-	新增加的端点坐标
	//		bulge   		-	圆弧的凸度
	//		startWidth		-	该点位置的曲线的开始宽度
	//		endWidth	    -	该点位置的曲线的结束宽度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus addVertexAt(unsigned int index,
		const McGePoint2d& pt,
		mxreal bulge = 0.,
		mxreal startWidth = -1.,
		mxreal endWidth = -1);

	// -------------------------------------------------------------------------
	// Summary:
	// 		向Polyline增加新的一个端点
	// Parameters:
	//		index			-	新端点插入位置
	//		pt      		-	新增加的端点3d坐标
	//		bulge   		-	圆弧的凸度
	//		startWidth		-	该点位置的曲线的开始宽度
	//		endWidth	    -	该点位置的曲线的结束宽度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus addVertexAt(unsigned int index,
		const McGePoint3d& pt,
		mxreal bulge = 0.,
		mxreal startWidth = -1.,
		mxreal endWidth = -1);

	// -------------------------------------------------------------------------
	// Summary:
	// 		向Polyline增加新的一个端点
	// Parameters:
	//		pt      		-	新增加的端点坐标
	//		bulge   		-	圆弧的凸度
	//		startWidth		-	该点位置的曲线的开始宽度
	//		endWidth	    -	该点位置的曲线的结束宽度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus addVertexAt(const McGePoint2d& pt,
		mxreal bulge = 0.,
		mxreal startWidth = -1.,
		mxreal endWidth = -1);

	// -------------------------------------------------------------------------
	// Summary:
	// 		向Polyline增加新的一个端点
	// Parameters:
	//		pt      		-	新增加的端点3d坐标
	//		bulge   		-	圆弧的凸度
	//		startWidth		-	该点位置的曲线的开始宽度
	//		endWidth	    -	该点位置的曲线的结束宽度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus addVertexAt(const McGePoint3d& pt,
		mxreal bulge = 0.,
		mxreal startWidth = -1.,
		mxreal endWidth = -1);

	// -------------------------------------------------------------------------
	// Summary:
	// 		删除Polyline中的一个端点
	// Parameters:
	// 		index	-	端点的索引位置，从0开始计数
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus removeVertexAt  (unsigned int index);

	// -------------------------------------------------------------------------
	// Summary:
	// 		返回Polyline中的端点数目
	// -------------------------------------------------------------------------
	unsigned int      numVerts        () const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		得到Polyline的端点
	// Parameters:
	// 		index	-	端点的索引位置，从0开始计数
	//		pt		-	返回端点位置
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus getPointAt        (unsigned int index,
		McGePoint2d& pt)         const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		得到Polyline的3d端点
	// Parameters:
	// 		index	-	端点的索引位置，从0开始计数
	//		pt		-	返回端点位置
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus getPointAt        (unsigned int index,
		McGePoint3d& pt)         const;
	// -------------------------------------------------------------------------
	// Summary:
	// 		得到Polyline的凸度
	// Parameters:
	// 		index		-	端点的索引位置，从0开始计数
	//		bulge		-	返回的凸度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus getBulgeAt      (unsigned int index,
		mxreal&      bulge)      const;

	// -------------------------------------------------------------------------
	// Summary:
	// 		得到Polyline的端点的宽度参数
	// Parameters:
	// 		index		-	端点的索引位置，从0开始计数
	//		startWidth	-	返回开始宽度
	//		endWidth	-	返回结束宽度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus getWidthsAt     (unsigned int index,
		mxreal&      startWidth,
		mxreal&      endWidth)   const;


	// -------------------------------------------------------------------------
	// Summary:
	// 		设置端点坐标
	// Parameters:
	//		index		-	端点位置索引，从0开始计数
	//		pt			-	端点坐标
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus setPointAt      (unsigned int index,
		const McGePoint2d& pt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置端点3d坐标
	// Parameters:
	//		index		-	端点位置索引，从0开始计数
	//		pt			-	端点坐标
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus setPointAt      (unsigned int index,
		const McGePoint3d& pt);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置端点的凸度
	// Parameters:
	//		index    -	端点位置索引，从0开始计数
	//		bulge    -	凸度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus setBulgeAt      (unsigned int index,
		mxreal       bulge);

	// -------------------------------------------------------------------------
	// Summary:
	// 		设置Polyline的开始宽度和结束宽度
	// Parameters:
	// 		index    	-	端点位置索引，从0开始计数
	//		startWidth  -	开始宽度
	//		endWidth    -	结束宽度
	// Returns:
	// 		如果成功返回Mcad::eOk
	// -------------------------------------------------------------------------
	Mcad::ErrorStatus setWidthsAt     (unsigned int index,
		mxreal       startWidth,
		mxreal       endWidth);

	//:Ignore
	Mcad::ErrorStatus getGripPoints(McGePoint3dArray&    gripPoints,
		McGeIntArray& osnapMasks,
		McGeIntArray& geomIds) const;

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

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

	Mdesk::Boolean   worldDraw   (McGiWorldDraw* mode);

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

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


	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 getDistAtPoint (const McGePoint3d&, double&)const;
	virtual Mcad::ErrorStatus getPointAtDist (double, McGePoint3d&) const;
	virtual Mcad::ErrorStatus getSamplePoints(
		double approxEps, McGePoint3dArray& pointArray,
		McGeDoubleArray& paramArray) const;

	virtual Mcad::ErrorStatus getArea(double& dArea) const;

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

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


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

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

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



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

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

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


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

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


	virtual Mcad::ErrorStatus getParamAtDist(mxreal dist, mxreal& param) const;

	bool getAllData(std::vector<McGePoint3d>& aryPoint, std::vector<double>& aryBulge, std::vector<double>& arySW, std::vector<double>& aryEW);


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

	virtual Mcad::ErrorStatus   explode(McDbVoidPtrArray& entitySet) const;

	virtual void modified(const McDbObject* dbObj);


	Mcad::ErrorStatus sclaeWidth(double dScale);


	McDbPolyline::PolylineType getType() const;

	void setType(McDbPolyline::PolylineType type);


	void reverse();
	//:End Ignore

	inline McDbPolylineImp* getMcDbPolylineImp() const {
		return (McDbPolylineImp*)m_pImp;
	}

};



class McDbPolylineTempBufferImp;
class ARXDLL McDbPolylineCompute {
public:
	McDbPolylineCompute(McDbPolyline* pPL);
	~McDbPolylineCompute();

	unsigned int numVerts() const;
	Mcad::ErrorStatus getPointAt(unsigned int index, McGePoint3d& pt);
	Mcad::ErrorStatus setPointAt(unsigned int index, const McGePoint3d& pt);

	Mcad::ErrorStatus getWidthsAt(unsigned int index,
		mxreal&      startWidth,
		mxreal&      endWidth);

	Mcad::ErrorStatus setWidthsAt(long index, double startWidth, double endWidth);

	Mcad::ErrorStatus getBulgeAt(unsigned int index, mxreal&      bulge) ;

	void reInit();
protected:
	
private:
	McDbPolylineTempBufferImp* m_pImp;
	
};