#pragma once #ifndef AFX_EXT_CLASS #define AFX_EXT_CLASS Q_DECL_IMPORT #endif #include "Triangulation.h" #include namespace NVoronoi { class CVoronoi; //单个Voronoi图元 class AFX_EXT_CLASS CVoronoiUnit { public: CVoronoiUnit(CVoronoi* pParent); /** @brief判断该图元是否闭合 */ bool IsClosed(); /** @brief 添加边界,返回1表示添加成功 */ bool AddBorder(CMyCurve& border); /** @brief 添加断层,即由断层进行切割*/ bool ClipWithFlts(vector* pFlts, vector* pRects = 0); //获取多边形曲线 bool GetPolygon(CMyCurve& curve); //清除不含中心点的多边形曲线 void EraseOtherPgns(void); list& GetOtherPgns(void); int npt; //相关中心点序号 CPoint3D* ppt; //相关中心点指针 list m_nodPoints; //包含中心点的多边形 list m_otherPgns; //不含中心点的多边形曲线 private: /** @brief 找到中心点最小包围曲线,将点存入ptlist,如果存在其他不含井点的多边形,存入otherpgns*/ bool MinClosedCurve(CMyCurve& nodCur, CMyCurve& border,CPointList& ptlist, list& otherPgns); //父龟背图 CVoronoi* m_pParent; }; //vorono多边形 class CVoronoiPolygon { public: CVoronoiPolygon(); ~CVoronoiPolygon(); int GetWell(void){return m_iWellPt; } bool ContainWell(void) {return m_bWellInside;} CMyCurve* GetPolygon(void) {return m_pPolygon; } //判断两个多边形是否相邻 bool IsAdjacent(CVoronoiPolygon* pOther); int m_iWellPt; //相关井点序号 bool m_bWellInside; // 是否包含井点 CMyCurve* m_pPolygon; }; class AFX_EXT_CLASS CVoronoi : public CTriangulation { public: CVoronoi(void); virtual ~CVoronoi(void); public: /** @brief 设置相关的边界曲线:工区边界、断层等,pFlt为断层 pFltRects为断层对应矩形范围 */ int InitBoundary(CMyCurve* border = NULL, vector* pFlts = 0, vector* pFltRects = 0); /** @brief 生成Voronoi图,获得生成的曲线元素 */ int CreateVoronoiMap(TPtrList& curveVoronoiList); /** @brief 读取2D散点数据 */ virtual int ReadPoints(vector& X, vector& Y); virtual int ReadPoints(int num, double* X, double* Y); //标记需要图元劈分的中心点(井点)序号 void SetMarkedPoints(vector& markVec); //拆分所有标记龟背图元Polygon到相邻图元Polygon中 void SplitMarkedUnits(void); //由断层分割多个voronoi单元 分离出的部分由相邻单元瓜分,并更新 返回分割掉的原始vunit个数 int SplitVUnitWithFlts(void); //由断层分割龟背单元pScrVUnit生成多个voronoi多边形存入dstVUnits,若断层未分割,则v unit边界生成多边形 bool SplitVUnitWithFlts(CVoronoiUnit* pScrVUnit,list& dstVPgns, vector* pFlts); //由每口井的最大区域ctCurs,序号与点序号一一对应重新分配m_vPolygons & m_VUnitList //用于单晶储量运算 void ReassignWithConstraintRects( double width, double height ); //由给定的若干v多边形重新生成局部龟背图 /** @brief 清空类*/ virtual void ClearAll(); /** @brief 清空类成员*/ void ClearVoronoi(); //获取相邻多边形的组合边界 返回个数 int CreateUnitedBoundaries( vector& pgns, vector& borders ); //////////////////////////////////////////////////////////////////////// //图件生成之后的调用函数 // //获取Voronoi单元曲线 int GetVUnitCurves(vector& curs); //获取V多边形曲线 int GetVPolygonCurves(vector& curs); //获取水井劈分线曲线 int GetMWSplitterCurves(vector& curs); /** @brief 获得生成的所有图元多边形,curveVoronoiList存放生成的曲线(CCurveEx)结果*/ int GetUnitCurve(TPtrList& curveVoronoiList); /** @brief 获得生成的Voronoi图元多边形*/ int GetUnitCurve(int nIndex, CMyCurve& pCurve); /** @brief 获得生成的Voronoi图的区域线个数*/ int GetUnitCount() { return (int)m_VUnitList.size(); } /** @brief 返回voronoi单元*/ CVoronoiUnit* GetUnit(int index); /** @brief 将Voronoi图写入文件*/ void Write(char* filename); /** @brief 由边界条件生成Voronoi图*/ virtual int Create(); //查找位于断层内部的井点 void FindWellInFlts(void); list& GetSplitterSegments(void); private: //拆分指定的voronoi图元到相邻图元中 idx为中心点序号 void SplitMarkedUnit(int wellIndex); //dest合并subject相邻部分 void MergeAdjacentPart(CVoronoiPolygon* pSubjectUnit, CVoronoiPolygon* pDestUnit); /** @brief 求取两结点中点*/ bool MidPoint(int npt1, int npt2,CPoint3D& mpt); /** @brief 求取两结点中点*/ bool MidPoint(CPoint3D& pt1, CPoint3D& pt2,CPoint3D& mpt); /** @brief 由边界选择数据点,删除边界外的数据点*/ void SelectPointsByBorder(); /** @brief 生成单个龟背图元*/ bool CreateVoronoiUnit(int npt, int nTri, CVoronoiUnit& vunit); /** @brief 单方向追踪nTri相邻三角形中的Voronoi结点,addMode == 0为尾部添加点,1 为头部添加 */ virtual int DirectionalTrace(int& nTri, int& npt1, int& npt2, set& FDTriNos,list& nodlist, int addMode = 0); /**@brief 准备追踪,确定首点 m_LastPoint*/ int PrepareTrace(int nTri, int npt1, int bot0,int bot1,list& nodlist, int addMode); /**@brief 单方向追踪到边界 进行结束处理*/ int EndDirectionalTrace(int nTri, int nTop, int nBottom,list& nodlist, int addMode); /** @brief 追踪ntri三角形中的Voronoi结点,addMode == 0为尾部添加点,1 为头部添加 */ int GetVNodePoint(int nTri, int npt1, int npt2, int npt3,list& nodlist, int addMode ); /** @brief 曲线延伸到边界,求交点桩号*/ bool ExtendToBorder(list& nodlist, double& l0 , double extlen); /** @brief 生成包络曲线 */ bool CreateEnvelopeCurve(); /** @brief生成外心点数组*/ bool CreateCirCenterPoints(); /* @brief 判断向量(x1,y1)(x3,y3)在向量(x1,y1)(x2,y2)的右侧还是左侧,右侧返回0,左侧返回1,线上返回2 **/ int VectorSide(double x1, double y1, double x2, double y2, double x3, double y3); /**@brief 判断向量(pt0-pt2)在向量(pt0,pt1)的右侧还是左侧,右返回0 左返回1,线上返回2*/ int VectorSide(CPoint2D& pt0, CPoint2D& pt1,CPoint2D& pt2); //生成井点序号与龟背图对应关系 void MapPointVoronoiUnit(void); //生成井点序号与VPolygon的对应map void MapPointVoronoiPolygon(void); //点与多边形中的点是否有重合 bool IsAdjacent(CPoint3D& pt, list& polygon,CRect8* pRect ); //获取目标vector中所有点与polygon的邻接关系,将邻接点序号存入vecAdjacent中 返回邻接点个数 int GetAdjacentPoint(list& targetPts, list& polygon,set& adjResult); //将点添加到链表中 void AddPoint(list& nodlist, CPoint3D& pt, int addMode=0); //判断坐标数组是否共线 如果是 返回true 否 返回false bool IsCollinear(double prec); //当井点共线时,或只有一个井点时,生成voronoi单元, int CreateCollinearVoronoiMap(); //当井点共线时,生成voronoi单元,curveVoronoiList存放生成的曲线(CCurveEx)结果 int CreateCollinearVoronoiMap(TPtrList& curveVoronoiList); //获取V多边形相邻的多边形,相同井点的多边形除外,bCompareAllPgns= true 与图中所有井点区域比较,false= 只与关联井点比较 int GetAdjacentPolygons(CVoronoiPolygon* pscrPgn, list& dstpgns, bool bCompareAllPgns = false); //查找相邻Voronoi单元井点 int GetNeighborWells(int iWell, vector& neighborWells); //获取相邻多边形的大边界 CMyCurve* CreateBoundary( list& pgns ); //获取一组相邻多边形的大边界线段 void GetBoundarySegs( list& scrPgns, list& dstSegs ); //获取一组相邻多边形的大边界线段 void GetBoundarySegs( vector& scrPgns, list& dstSegs ); //连接两条有公共点的曲线 如公共点 返回0 CMyCurve* CreateBoundary(list& scrSegs); //生成子VORONOI图 bool CreateSubVoronoi(list& pgns, CMyCurve* pBoundary,CVoronoi& dstVrn, std::map& subwell2origwell,vector* pFlts); //由子voronoi图更新原图 void UpdateWithSubVoronoi(CVoronoi& dstVrn, std::map& subwell2origwell); //由vpolygon更新vunit void UpdateVUnitWithVPolygon(CVoronoiUnit* pDstUnit, CVoronoiPolygon* pScrPolygon); //清空vpolygons void ClearVPolygons(void); //根据坐标获取井点序号 int GetWellIndex(double x, double y); //两线段减去相同部分,得到不同部分的线段个数,若无相交(或仅有一点相交) 返回0 int SubtractSegment(VSegment& v1, VSegment& v2, vector& dstSegs); //设置在断层中的井点序号 set& GetWellInFlt(void); //获取矩形四边 etdLen 为每条边延伸长度,缺省-1 void GetRectLines(double x0, double y0, double w, double h,CMyCurve* lines, double etdLen = -0.1); private: /** @brief 三角形外心*/ vector m_CCPoints; /** @brief 所有龟背图元容器*/ vector m_VUnitList; /** @brief voronoi单元被断层分割后的多边形*/ list m_vPolygons; typedef list::iterator VPITER; /** @brief Voronoi图边界线 */ CMyCurve m_Border; /** @brief 网格包络线*/ CMyCurve m_OutlineCurve; vector* m_pFlts; vector m_fltRects; //标记中心点劈分/////////////////////// CPoint3D m_LastPoint; set m_markedPoints; //标记的井点序号 map m_mapPtVUnit; //点序号与voronoi unit序号的map map m_mapPtVPng; //点序号与对应VPolygon指针的map set m_wellinflt; //位于断层内部的井点序号 用于断层分割 CSize8* m_pConstrainSize; //用于分割的矩形长宽 list m_splitterSegments; //分割水井(标记井)的线段 }; }; //NTriangle