|
|
|
|
|
/************************************************************************/
|
|
|
/* 类名:CTriangulation */
|
|
|
/* 功能:对散点数据进行三角网格化及相关操作 */
|
|
|
/* 王昌伟 2011-10-9 */
|
|
|
/************************************************************************/
|
|
|
#pragma once
|
|
|
#include "stdafx.h"
|
|
|
#include "triangle.h"
|
|
|
#include <vector>
|
|
|
#include <list>
|
|
|
#include <iostream>
|
|
|
#include <sstream>
|
|
|
#include <fstream>
|
|
|
#include <string>
|
|
|
#include <set>
|
|
|
#include <map>
|
|
|
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<CPoint3D*>& 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]<npt[1]
|
|
|
};
|
|
|
|
|
|
//三角网格类
|
|
|
typedef map<int, int* > 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<double>& X, vector<double>& Y,vector<double>& Z);
|
|
|
virtual int ReadPoints(vector<double>& X, vector<double>& Y,vector<double>& Z, vector<int>& 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<int>& tNOLST,int ntri = -1);
|
|
|
/** @brief 删除与边界点相关的外围三角形 */
|
|
|
void DeleteOuterTriangles();
|
|
|
/** @brief 对三角网中三角形边线加密,加密步长为step,返回加密生成的新点数目 */
|
|
|
int InfillSegPoints(vector<CPoint3D*>& newPtVec, double step);
|
|
|
/** @brief 对三角网三角形内部(不含边界)加密,加密步长为step,返回生成的新点数目 */
|
|
|
int InfillInterPoints(vector<CPoint3D*>& newPtVec, double step);
|
|
|
/** @brief 判断数据点容器是否为空*/
|
|
|
bool IsPointVecEmpty();
|
|
|
/** @brief 判断三角容器是否为空*/
|
|
|
bool IsTriangleVecEmpty();
|
|
|
/** @brief 将三角网中所有线段存入容器 m_nTSegmentVec*/
|
|
|
int CreateAllSegments();
|
|
|
/** @brief 批量销毁多个三角形,将其指针指向NULL,并对m_TriangleList 做顺序上调整 */
|
|
|
bool DeleteMultiTriangles(list<int>& 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<int>& 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<CPoint3D*> m_PointVec;
|
|
|
/** @brief 单点属性个数*/
|
|
|
int m_NumofPointAttributes;
|
|
|
/** @brief 散点属性数组*/
|
|
|
vector<int> m_PointAttributeVec;
|
|
|
/** @brief 生成的三角平面指针数组*/
|
|
|
vector<CTriangle*> m_TriangleVec;
|
|
|
/** @brief 三角网各坐标极大极小值 */
|
|
|
double m_xMax,m_xMin,m_yMax,m_yMin,m_zMax,m_zMin;
|
|
|
/** @brief 三角网凸包上的数据点,首尾连接 */
|
|
|
vector<int> m_OutlinePoints;
|
|
|
//私有变量
|
|
|
private:
|
|
|
vector<int> m_nTSegmentVec; ///< 存储三角网格中的所有线段端点,序号0,1代表第一条
|
|
|
list<int> m_SameLineTriNoLst; ///< 三个点线号相同的三角形序号list
|
|
|
LNOMAP m_lmp; ///<记录每条线起始点序号: key 线号, value 序号[2]
|
|
|
};
|
|
|
|
|
|
/** @brief 对线段进行加密,加密后新生成的的点集存入CPoint3D容器中*/
|
|
|
int Infill(vector<CPoint3D* >& newPtVec,CPoint3D& pt1, CPoint3D& pt2,double step);
|
|
|
|
|
|
|