/************************************************************************/ /* 类名:CTriangulation */ /* 功能:对散点数据进行三角网格化及相关操作 */ /* 王昌伟 2011-10-9 */ /************************************************************************/ #pragma once #include "stdafx.h" #include "triangle.h" #include #include #include #include #include #include #include #include using namespace std; #define SCATTERPOINT_MODE 0 //散点模式 #define LINEARPOINT_MODE 1 //数据线模式 #define POLYGON_MODE 2 //多边形模式 //三角形平面类 class AFX_EXT_CLASS CTriangle { public: CTriangle(); ~CTriangle(); /** @brief计算得到平面系数A,B,C,D,生成三角平面*/ bool CreatePlane(); void Initial(); /** @brief判断三角形是否为空*/ bool IsEmpty(); /** @brief 求线段与三角平面的交点,若无交点,返回false*/ bool CrossPoint(CPoint3D& pt1, CPoint3D& pt2,CPoint3D& cspt); /** @brief 求取指定坐标点Z值,若坐标点在三角形外,返回false*/ bool GetZValue(double x, double y ,double& z); /** @brief 判断该z值是否在三角形上*/ bool IsZOnTriangle( double z ); /** @brief 计算三角形外心,即三边中垂线的交点 */ bool GetCircumCenter(CPoint3D& ccpt); /** @brief 计算三角形的重心,即三条中线的交点*/ bool GetGravityCenter(CPoint3D& gcpt); /** @brief 计算某一顶点在对边上的垂点*/ bool GetOrthoPoint(CPoint3D& rpt,int npt1,int npt2); /** @brief 判断曲线与三角形在2D平面上是否有交点*/ int IsCross2D(CCurve& curve); /** @brief 对三角形内部进行点加密, 加密步长step,返回加密的点个数*/ int InterInfill(vector& newPtVec, double step); private: /** @brief 判断两点与面的位置关系,1 为同侧, 0 为异侧, 11 为点1在面上,22为点2在平面上*/ int IsPtsOneSide(CPoint3D& pt1, CPoint3D& pt2); /** @brief 将坐标代入三角平面方程求值 */ double EquationValue(double x, double y, double z); double EquationValue(CPoint3D& pt); /** @brief 判断点是否位于平面上 */ bool IsPtOnPlane(CPoint3D& pt); /** @brief 判断点在XOY平面上的投影是否位于三角形在XOY面上投影的内部,返回2表示在边界线上*/ int IsPtInside2D(CPoint2D& pt); int IsPtInside2D(double x, double y); /** @brief 判断点是否在空间三角形内部*/ int IsPtInside3D(CPoint3D& pt); //辅助函数 public: /** @brief 判断两个三角形外接立方体是否无交汇 */ bool IsTriBodySeparated(CTriangle& tri); /** @brief 由已知两顶点序号查找第三个顶点序号,不存在 返回-1*/ int The3rdPoint(int nt1,int nt2); private: /** @brief 得到三角形各方向极值*/ bool GetExtremeValues(); /** @brief 快速排斥,判断点是否在三角外接立方体外部*/ bool IsPtOutTriBody(CPoint3D& pt); /** @brief 快速排斥,判断点是否在三角外接正方形外部*/ bool IsPtOutTriSquare(CPoint2D& pt); /** @brief 判断线段是否在三角形外接立方体外部 */ bool IsSegmentOutTriBody(CPoint3D& pt1, CPoint3D& pt2); /** @brief 判断线段是否在三角形外接矩形外部 */ bool IsSegmentOutTriSquare(double x1, double y1, double x2, double y2); //需赋值成员变量 public: int npt[3]; //顶点序号 CPoint3D* ppt[3]; //顶点指针 int neighbor[3]; //相邻三角形序号 public: double m_xMin, m_yMin,m_zMin,m_xMax,m_yMax,m_zMax; //三角形各坐标极值 double A,B,C,D; // 三角平面Ax+By+Cz+D = 0 的各项系数 其中,(A,B,C)为平面法向量 }; //三角线段类 class AFX_EXT_CLASS CTSegment { public: CTSegment(); /** @brief 由给定序号生成线段*/ bool Create(int np1,int np2); bool operator == ( const CTSegment& seg) const; bool operator < ( const CTSegment& seg) const; /** @brief 得到第n个点序号 */ int Pt(int n) const; private: int npt[2]; ///< 端点序号,npt[0] LNOMAP; ///< 记录每条数据线对应散点的起始位置 class AFX_EXT_CLASS CTriangulation { public: CTriangulation(); virtual ~CTriangulation(); /** @brief 清空类*/ virtual void ClearAll(); /** @brief 三角网内切 */ BOOL CutIn(CCurve& border); /** @brief 三角网外切*/ BOOL CutOut(CCurve& border); //读写 public: /** @brief 将Net按格式存储到dft文件中*/ bool WriteFile(char* filename, char* projectname = NULL); /** @brief 从dft文件中读取网格*/ bool ReadFile(char* filename); /** @brief 散点数据读取函数*/ virtual int ReadPoints(vector& X, vector& Y,vector& Z); virtual int ReadPoints(vector& X, vector& Y,vector& Z, vector& Attr,int attrnum = 1); int ReadPoints(int num, double* X, double* Y, double* Z); //操作 public: /** @brief 生成三角网,参数为0表示由散点生成网格,参数为1表示由点属性分组生成*/ virtual int Create(int createMode = SCATTERPOINT_MODE); /** @brief 将三角网中三角形以dfd格式存入文件*/ void WriteTriangles(char* filename); /** @brief 得到三角形总数目*/ int NumberofTriangles(); /** @brief 返回散点数目*/ int NumberofPoints(); /** @brief 求取指定坐标点Z值,若坐标点在三角网外,返回false*/ bool GetZValue(double x, double y ,double& z); /** @brief 线段上插值得到Z值点坐标 */ bool GetZPoint( double z,CPoint3D& pt1, CPoint3D& pt2, CPoint3D& pt); /** @brief 得到与第triNo个三角形相邻,且邻边为npt1,npt2的三角形序号*/ int GetNeighborTriangle(int triNo,int npt1, int npt2); /** @brief 得到所有以npt为顶点的三角形序号,存入容器,ntri 为初始三角形序号*/ int GetCommonPointTriangles(int npt,list& tNOLST,int ntri = -1); /** @brief 删除与边界点相关的外围三角形 */ void DeleteOuterTriangles(); /** @brief 对三角网中三角形边线加密,加密步长为step,返回加密生成的新点数目 */ int InfillSegPoints(vector& newPtVec, double step); /** @brief 对三角网三角形内部(不含边界)加密,加密步长为step,返回生成的新点数目 */ int InfillInterPoints(vector& newPtVec, double step); /** @brief 判断数据点容器是否为空*/ bool IsPointVecEmpty(); /** @brief 判断三角容器是否为空*/ bool IsTriangleVecEmpty(); /** @brief 将三角网中所有线段存入容器 m_nTSegmentVec*/ int CreateAllSegments(); /** @brief 批量销毁多个三角形,将其指针指向NULL,并对m_TriangleList 做顺序上调整 */ bool DeleteMultiTriangles(list& nolst); //相交部分 public: /** @brief 计算空间线段与三角网的交点 */ bool CrossPoint(CPoint3D& pt1, CPoint3D& pt2, CPoint3D& cspt); /** @brief 空间曲线与三角网的交点,无交点返回false */ bool CrossPoint(CCurve& curve, CPoint3D& cspt); /** @brief 两个三角网的交线,返回交点个数*/ int CrossCurve(CTriangulation& tNet, CCurve& crossCurve); /** @brief m_TriangleList容器中所有空指针,返回空指针个数 */ int DeleteAllNullTriangles(); private: /** @brief 由相邻线生成三角网,线号存在m_pointattributevec中*/ int CreateByLine(); /** &brief 在线号为lno的多边形内部生成三角网*/ int CreateInPolygon(int lno = 0); /** @brief 生成子网格, bno eno代表首尾数据点序号*/ int AddSubNet(int bno, int eno, int createMode ); /** @brief 将新生成的三角形与之前的三角网通过数据线lno建立相邻关系*/ int SetNeighbor(int btr, int etr,int lno); /** @brief 两个三角形之间建立相邻关系*/ int SetNeighbor(int ntr1, int ntr2); /** @brief 切除函数,CutMode为切除方式,0为外切,1为内切*/ BOOL CutNet(CCurve& border,int CutMode); /** @brief 判断点是否处在包络上*/ bool IsPtOnEnvelope(int ptNo); /** @brief 销毁三角网中单个三角形,将其指针指向NULL */ bool NullOneTriangle(int triNo); /** @brief 判断线段是否在三角网外接立方体之外,且不可能穿过*/ bool IsSegmentOutNetBody(CPoint3D& pt1, CPoint3D& pt2); /** @brief 判断三角形是否在网格立体空间外 */ bool IsTriOutNetBody(CTriangle& tri); /** @brief 删除散点数据*/ void DeletePointList(); /** @brief 删除三角数据*/ void DeleteTriangleList(); int GetExtremeValues(); /** @brief 判断两个三角网所处立体空间是否不想交 */ bool IsNetBodySeparated(CTriangulation& tNet); /** @brief 单向查找相交点,0为尾部添加,1为头部添加 */ virtual bool OneWayTrace(CTriangulation& tNet, int& bNo, int& npt1, int& npt2, CPointList& PointList, set& m_FDTriLib, int addMode = 0 ); /** @brief由线号精简三角网 */ void SimpleByLineNo(); /** @brief由线号精简部分三角网 */ void SimpleByLineNo(int btr, int etr); /** @brief 处理同序号三角形,和相邻三角形重新拆分*/ bool RebuildSameLineTriangles(); /** @brief 重新构建两个相邻三角形,交换对角线,npt1,npt2为相邻边*/ bool RebuildTwoTriangles(int ntr1, int ntr2, int npt1, int npt2); /** @brief 判断两个点是否共线号且相邻*/ bool IsLinearNeighbor(const int& npt1, const int& npt2); /** @brief 生成各条线起始序号查询map*/ bool CreateLineDataMap(); /** @brief 删除现有起始序号查询map*/ void DeleteLineDataMap(); //成员变量 public: /** @brief 散点坐标指针数组*/ vector m_PointVec; /** @brief 单点属性个数*/ int m_NumofPointAttributes; /** @brief 散点属性数组*/ vector m_PointAttributeVec; /** @brief 生成的三角平面指针数组*/ vector m_TriangleVec; /** @brief 三角网各坐标极大极小值 */ double m_xMax,m_xMin,m_yMax,m_yMin,m_zMax,m_zMin; /** @brief 三角网凸包上的数据点,首尾连接 */ vector m_OutlinePoints; //私有变量 private: vector m_nTSegmentVec; ///< 存储三角网格中的所有线段端点,序号0,1代表第一条 list m_SameLineTriNoLst; ///< 三个点线号相同的三角形序号list LNOMAP m_lmp; ///<记录每条线起始点序号: key 线号, value 序号[2] }; /** @brief 对线段进行加密,加密后新生成的的点集存入CPoint3D容器中*/ int Infill(vector& newPtVec,CPoint3D& pt1, CPoint3D& pt2,double step);