You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

251 lines
9.0 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/************************************************************************/
/* 类名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; ///< 存储三角网格中的所有线段端点序号01代表第一条
list<int> m_SameLineTriNoLst; ///< 三个点线号相同的三角形序号list
LNOMAP m_lmp; ///<记录每条线起始点序号: key 线号, value 序号[2]
};
/** @brief 对线段进行加密加密后新生成的的点集存入CPoint3D容器中*/
int Infill(vector<CPoint3D* >& newPtVec,CPoint3D& pt1, CPoint3D& pt2,double step);