/******************************************************************** 创建日期: 2011年12月22日<13:51:21> 文件名称: PDSAlgorithm.h 原始作者: 孙宇飞 文件描述: 该文件中提供算法类的函数 所有的函数都将使用输入,输出变量完成数据交换,一定不使用全局变量中的数据 各函数的变量说明一定要明确,尤其是与数学库中功能相似又有区别的函数,一定要将区别写清楚 修改记录: 版本号码 修改日期 作者 修改内容 *********************************************************************/ #ifndef PDSALGORITHM_H #define PDSALGORITHM_H #include //线段 // 该类将会在计算最大多边形的过程中使用,每一条点链都会记录所在曲线的索引值和方向 class CPDSSegment : public CObject { public: CList m_listPoint; //实际点链 int m_iCurveIndex; //this所属曲线的索引值 // 举例:在计算最大多边形的过程中,该变量记录this取自于哪一条点链(取名为list) BOOL m_bDirection; //=TRUE 方向相同, =FALSE 方向相反 // 举例:在计算最大多边形的过程中,该变量记录m_listPoint与list是否头尾点顺序相同, // 若=FALSE则表示m_listPoint从头到尾的方向是list从尾到头的方向 int m_iIndex; //this在整条链表(数组)中的索引值,可以根据实际情况酌情指定该变量的含义 CPDSSegment(void); CPDSSegment(CList& listPoint, int iCurveIndex, BOOL bDirection, int iIndex); CPDSSegment(CPDSSegment& rhs); CPDSSegment& operator=(CPDSSegment& rhs); BOOL operator==(CPDSSegment& rhs); BOOL operator!=(CPDSSegment& rhs); void Initial(void); }; //typedef CList CPDSSegmentList; class CPDSSegmentList : public CList { public: CPDSSegmentList& operator=(CPDSSegmentList& rhs); BOOL operator==(CPDSSegmentList& rhs); BOOL operator!=(CPDSSegmentList& rhs); CPDSSegment& operator[](int iIndex); }; //计算面积最大的多边形 //特别说明: // 本函数计算在给定的多条点链所形成的若干个多边形中,面积最大的那一个 //参数: // alCurve 点链数组,输入时要保证每条点链至少有2个点,如果是多边形还要求首尾点相同,并且相邻的点坐标不同 // listSegment [输出]线段链表,按照顺序将各线段中的点链连接起来就是一整条多边形,并且是逆时针的(在屏幕上看是顺时针) // CPDSSegment::m_iCurveIndex表示该元素是alCurve中的第几条,从0开始 // CPDSSegment::m_bDirection=TRUE表示与alCurve[]方向相同 // CPDSSegment::m_iIndex不使用 //返回值: // =TRUE 计算成功, =FALSE 计算失败,listSegment为空 BOOL CalculatePolygonWithMaxArea(CArray,CList >& alCurve, CPDSSegmentList& listSegment); //计算切割区域 //特别说明: // 在切割模板的时候,众多的开槽线纵横交错,需要把它们形成的最大多边形找到,直接将中间部分镂空即可,既加快速度又延长激光寿命; // 切角半径的作用是避免从一条模板切割到另一条模板时形成尖锐的夹角; //参数: // iDPMM 长度分辨率(一个内部单位即为1/iDPMM毫米) // alCurve 点链数组,输入时要保证每条点链至少有2个点,如果是多边形还要求首尾点相同,并且相邻的点坐标不同 // iRadius 切角半径,若=0表示不切角 // dMaxError 计算圆弧时的拟合误差 // alCutting [输出]点链数组,其中的每一条点链都是被切割的轨迹 //返回值: // alCutting.GetSize() int CalculateCuttingRegion(int iDPMM, CArray,CList >& alCurve, int iRadius, double dMaxError, CArray,CList >& alCutting); //计算listSegment中任意两条曲线的交点,并把交点插入到点链中 void DividePDSSegmentList(CPDSSegmentList& listSegment); //获取给定点的度数(如果某条线段的头点或者尾点等于给定点,那么度数加1) int GetPointDegree(CPoint ptPoint, CPDSSegmentList& listSegment); //移除孤立的曲线(如果曲线的头点或者尾点的度数为1,那么它就是孤立的,要被移除) void RemoveIsolateCurve(CPDSSegmentList& listSegment); //获取面积最大的多边形 //参数: // listSelectSegment [输入][输出]给定的全部点链,输出后会将listBorderSegment中的点链移除 // listBorderSegment [输出]能够形成边界的点链 void GetMaxBorder(CPDSSegmentList& listSelectSegment, CPDSSegmentList& listBorderSegment); //获取与给定点连接的点链 //参数: // listSelectSegment [输入][输出]给定的全部点链,一旦某条点链被添加到listConnectSegment中,则从该链表中移除 // ptPoint 给定点,查找与头点或者尾点等于该点的点链 // listConnectSegment [输出]与给定点相连接的点链 void GetConnectSegment(CPDSSegmentList& listSelectSegment, CPoint ptPoint, CPDSSegmentList& listConnectSegment); //向已有边线中添加一条点链 //参数: // listConnectSegment [输入][输出]与当前已有边线的尾点相连接的点链,输出时,哪条点链被添加到边线中,就把哪条点链移除 // listBorderSegment [输入][输出]输入时不能为空,本函数要使用其尾点的切线方向,输出时将会有一条点链被添加到尾部 void AddOneSegment(CPDSSegmentList& listConnectSegment, CPDSSegmentList& listBorderSegment); //添加一条点链 //参数: // ptLB 左下角点(left-bottom),世界坐标系下 // listConnectSegment [输入][输出]与当前已有边线的尾点相连接的点链,输出时,哪条点链被添加到边线中,就把哪条点链移除 // listBorderSegment [输出]输出时将会有一条点链被添加到尾部 void AddOneSegment(CPoint ptLB, CPDSSegmentList& listConnectSegment, CPDSSegmentList& listBorderSegment); //获取极限点 //参数: // ptCenter 旋转中心 // listPoint 点链 // bAntiClockwise =TRUE 逆时针旋转,世界坐标系下 //返回值: // 极限的那个点 //说明: // 如果要求逆时针旋转,那么要选择最左边的那个点;反之,要选择最右边的那个点 CPoint GetLimitPoint(CPoint ptCenter, CList& listPoint, BOOL bAntiClockwise); //获取左下角点 //参数: // listSegment 链表 //返回值: // 点,左下角点.单位:世界坐标系 //说明: // 此处的左下角点是指:y值最小的那个点,如果这样的点有多个,那么选择x值最小的那一个 CPoint GetLeftBottomPoint(CPDSSegmentList& listSegment); //计算圆弧切角的实际点链 //参数: // iDPMM 长度分辨率(一个内部单位即为1/iDPMM毫米) // listPoint1 第一条线 // listPoint2 第二条线,并且listPoint2.GetHead()==listPoint1.GetTail() // iRadius 圆角半径,不能为0 // dMaxError 拟合圆弧的最大误差,不能为0 // listArc [输出]圆弧实际点链 //返回值: // =TRUE 计算成功,listArc数据有效, =FALSE 计算失败,listArc为空 BOOL CalculateArcCorner(int iDPMM, CList& listPoint1, CList& listPoint2, int iRadius, double dMaxError, CList& listArc); //计算listSegment中任意两条曲线的交点,并把交点插入到点链中 void DividePDSSegmentList_New(CPDSSegmentList& listSegment); //将listSegment中的相同点关联起来 //特别说明: // 链表中的某些点可能坐标并不相等,但是非常接近,调用IsSamePoint()=true,那么应该把这样的点设置为相同的坐标 void ConnectPDSSegmentSamePoint(CPDSSegmentList& listSegment); //查找小于给定阈值的点,并返回该点位于哪条链表中 //特别说明: // (1)20160507,syf,添加该函数 // (2)该函数被CalculateCuttingRegion调用 //输入参数: // ptPoint 给定点 // listSegment 链表 // dMaxError 最大误差值 //返回值: // 索引值,从0开始,若为-1则搜索失败 int FindNearestPoint_WithDistance(CPoint ptPoint, CPDSSegmentList& listSegment, double dMaxError); //查找相同的线段 //特别说明: // (1)20160507,syf,添加该函数 // (2)该函数被CalculateCuttingRegion调用 // (3)实际上listSegment[].m_listPoint.GetCount()=2,全都是线段,这是由CalculateCuttingRegion函数中算法的特殊性决定的 // (4)在查找的过程中,忽略掉线段的方向,只要是端点相同即为相同 //输入参数: // ptPoint1 线段起点 // ptPoint2 线段终点 // listSegment 链表 //返回值: // 索引值,从0开始,若为-1则搜索失败 int FindSameSegment_2P(CPoint ptPoint1, CPoint ptPoint2, CPDSSegmentList& listSegment); //计算切线距离点 //特别说明: // (1)本函数被数据结构引用,也被工具引用,在V10版本发行后,一定要谨慎修改,以免造成已发行版本出错,切记!!!! // (2)只要listCurve.GetCount() >= 2,本函数都返回true // (3)计算切线时,根据宏定义F_MAX_TANGENT_ERROR截取长度,一旦宏定义被修改,本函数的计算结果就会改变 //输入参数: // iDPMM 分辨率 // listCurve 点链,至少有2个点,否则直接返回false;如果头尾点相同,那么按照多边形处理 // ptFrom 点,从该点开始计算切线;如果该点不在线上,则根据它的最近点计算切线方向,最终保证(ptFrom,ptTangency)就是切线方向 // bTangentPrev =true 指向前趋方向的切线,=false 指向后继方向的切线 // dLength 切线长度,不能为0,使用其绝对值 //输出参数: // ptFixPoint 最近点,距离ptFrom最近的点,一定在线上(未必在点链内部) // ptTangent 切点 //返回值: // =true 计算成功,=false 计算失败 BOOL CalculateTangentPD(int iDPMM, CList& listCurve, CPoint ptFrom, BOOL bTangentPrev, double dLength, CPoint& ptFixPoint, CPoint& ptTangent); #endif //PDSALGORITHM_H