2026-10-04 00:04:20 +08:00
|
|
|
//-------------------------------------------------------------------------------------------------------+
|
2026-09-28 15:28:50 +08:00
|
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
2026-10-04 00:04:20 +08:00
|
|
|
// = FileName : TPGeCurveMesh 类
|
2026-09-28 15:28:50 +08:00
|
|
|
// = Version : ver2.0
|
|
|
|
|
// = Author : wlw
|
|
|
|
|
// = CreateDate : 2002-09-09
|
2026-10-04 00:04:20 +08:00
|
|
|
// = Description: TPGeCurveMesh 定义
|
2026-09-28 15:28:50 +08:00
|
|
|
// = Maintainers:
|
|
|
|
|
//
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
|
|
|
#include "StdAfx.h"
|
|
|
|
|
#include "TPGeCurveMesh.h"
|
|
|
|
|
#include "TGMeshNode.h"
|
|
|
|
|
#include "TGMeshEdge.h"
|
|
|
|
|
#include "TListQuene.h"
|
|
|
|
|
#include "TGRegion2D.h"
|
|
|
|
|
#include "TGRegionEx2D.h"
|
|
|
|
|
|
|
|
|
|
TPGeCurveMesh::TPGeCurveMesh()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TPGeCurveMesh::~TPGeCurveMesh()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TPGeCurveMesh::operator > (const TPGeCurveMesh&) const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TPGeCurveMesh::operator < (const TPGeCurveMesh&) const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TGMeshNode* TPGeCurveMesh::FindOrAddNode(const TGPoint&pt)
|
|
|
|
|
{
|
|
|
|
|
TGMeshNode*pNode = new TGMeshNode(pt);
|
|
|
|
|
if(!m_allNode.SortIn(pNode))
|
|
|
|
|
{
|
|
|
|
|
delete pNode;
|
|
|
|
|
}
|
|
|
|
|
return m_allNode.GetCurData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPGeCurveMesh::AppendCurve(const TPGeCurve2D*pCurve)
|
|
|
|
|
{
|
|
|
|
|
if((!pCurve->IsFinite(true) && !pCurve->IsFinite(false)) || pCurve->IsClosed())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TGPoint pt1,pt2;
|
|
|
|
|
pCurve->GetStartPoint(pt1);
|
|
|
|
|
pCurve->GetEndPoint(pt2);
|
|
|
|
|
if(pt1.Equal2D(pt2))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_allEdge.AddTail(new TGMeshEdge(pCurve,pCurve->IsFinite(true) ? FindOrAddNode(pt1) : NULL,
|
|
|
|
|
pCurve->IsFinite(false) ? FindOrAddNode(pt2) : NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPGeCurveMesh::RemoveOpenEdge()
|
|
|
|
|
{
|
|
|
|
|
TListQuene<TGMeshNode*> quene;
|
|
|
|
|
for(m_allNode.MoveToFirst(); !m_allNode.IsOut(); m_allNode.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
if(m_allNode.GetCurData()->IsEndNode())
|
|
|
|
|
{
|
|
|
|
|
quene.EnQuene(m_allNode.GetCurData());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while(!quene.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
TGMeshNode*pNode;
|
|
|
|
|
quene.DeQuene(pNode);
|
|
|
|
|
TGMeshEdge*pEdge = pNode->GetOnlyEdge();
|
|
|
|
|
if(pEdge == NULL)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pNode->Clear();
|
|
|
|
|
pNode = pEdge->GetNextNode(pNode);
|
|
|
|
|
if(pNode != NULL)
|
|
|
|
|
{
|
|
|
|
|
pNode->RemoveEdge(pEdge);
|
|
|
|
|
if(pNode->IsEndNode())
|
|
|
|
|
{
|
|
|
|
|
quene.EnQuene(pNode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pEdge->AddFlag(INVALID_EDGE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(m_allEdge.MoveToFirst();!m_allEdge.IsOut();m_allEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
if(m_allEdge.GetCurData()->Is(INVALID_EDGE))
|
|
|
|
|
{
|
|
|
|
|
m_allEdge.DelCur();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TPGeCurveMesh::TPGeCurveMesh(const TGObjectList&buf,bool bOnlyClose)
|
|
|
|
|
{
|
|
|
|
|
for(TGObject*const*p = buf.GetFirst();p != NULL;p = buf.GetNext(p))
|
|
|
|
|
{
|
|
|
|
|
AppendCurve((const TPGeCurve2D*)(*p));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(m_allNode.MoveToFirst();!m_allNode.IsOut();m_allNode.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
m_allNode.GetCurData()->Arrange();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(m_allEdge.MoveToFirst();!m_allEdge.IsOut();m_allEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
if(m_allEdge.GetCurData()->Is(DUP_EDGE))
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge *pEdge = m_allEdge.GetCurData();
|
|
|
|
|
TGMeshNode* pNode1 = (TGMeshNode*)pEdge->GetNode(1),*pNode2 = (TGMeshNode*)pEdge->GetNode(2);
|
|
|
|
|
if(pNode1 != NULL)
|
|
|
|
|
{
|
|
|
|
|
pNode1->RemoveEdge(pEdge);
|
|
|
|
|
}
|
|
|
|
|
if(pNode2 != NULL)
|
|
|
|
|
{
|
|
|
|
|
pNode2->RemoveEdge(pEdge);
|
|
|
|
|
}
|
|
|
|
|
m_allEdge.DelCur();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(bOnlyClose)
|
|
|
|
|
{
|
|
|
|
|
RemoveOpenEdge();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPGeCurveMesh::FindAllMesh()
|
|
|
|
|
{
|
|
|
|
|
for(m_allEdge.MoveToFirst();!m_allEdge.IsOut();m_allEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge* pEdge = m_allEdge.GetCurData();
|
|
|
|
|
if(pEdge->IsNot(VISITED12))
|
|
|
|
|
{
|
|
|
|
|
TGMesh* pMesh = pEdge->FindMesh(1);
|
|
|
|
|
if(pMesh != NULL)
|
|
|
|
|
{
|
|
|
|
|
pMesh->ExplodeSelfCross(m_allMesh);
|
|
|
|
|
m_allMesh << pMesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(pEdge->IsNot(VISITED21))
|
|
|
|
|
{
|
|
|
|
|
TGMesh* pMesh = pEdge->FindMesh(2);
|
|
|
|
|
if(pMesh != NULL)
|
|
|
|
|
{
|
|
|
|
|
pMesh->ExplodeSelfCross(m_allMesh);
|
|
|
|
|
m_allMesh << pMesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPGeCurveMesh::FindAllSDMesh()
|
|
|
|
|
{
|
|
|
|
|
for(m_allEdge.MoveToFirst();!m_allEdge.IsOut();m_allEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge* pEdge = m_allEdge.GetCurData();
|
|
|
|
|
if(pEdge->IsNot(VISITED12))
|
|
|
|
|
{
|
|
|
|
|
TGMesh* pMesh = pEdge->FindSDMesh();
|
|
|
|
|
if(pMesh != NULL)
|
|
|
|
|
{
|
|
|
|
|
pMesh->ExplodeSelfCross(m_allMesh);
|
|
|
|
|
m_allMesh << pMesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPGeCurveMesh::Explode(TPDList<TPGeCurveMesh> &lstChildMesh)
|
|
|
|
|
{
|
|
|
|
|
for(m_allEdge.MoveToFirst();!m_allEdge.IsOut();m_allEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge *pEdge = m_allEdge.GetCurData();
|
|
|
|
|
if(pEdge->IsNot(VISITED))
|
|
|
|
|
{
|
|
|
|
|
TPGeCurveMesh *pChild = new TPGeCurveMesh;
|
|
|
|
|
TListQuene<TGMeshEdge*> quene;
|
|
|
|
|
pEdge->AddFlag(VISITED);
|
|
|
|
|
quene.EnQuene(pEdge);
|
|
|
|
|
|
|
|
|
|
while(!quene.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
quene.DeQuene(pEdge);
|
|
|
|
|
pChild->m_allEdge << pEdge;
|
|
|
|
|
if(pEdge->m_pNode1 != NULL)
|
|
|
|
|
{
|
|
|
|
|
pChild->m_allNode.SortIn(pEdge->m_pNode1);
|
|
|
|
|
}
|
|
|
|
|
if(pEdge->m_pNode2 != NULL)
|
|
|
|
|
{
|
|
|
|
|
pChild->m_allNode.SortIn(pEdge->m_pNode2);
|
|
|
|
|
}
|
|
|
|
|
if(pEdge->m_pMesh1 != NULL)
|
|
|
|
|
{
|
|
|
|
|
pChild->m_allMesh.FindOrAddTail(pEdge->m_pMesh1);
|
|
|
|
|
}
|
|
|
|
|
if(pEdge->m_pMesh2 != NULL)
|
|
|
|
|
{
|
|
|
|
|
pChild->m_allMesh.FindOrAddTail(pEdge->m_pMesh2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TGMeshNode *pNode = pEdge->m_pNode1;
|
|
|
|
|
if(pNode != NULL)
|
|
|
|
|
{
|
|
|
|
|
for(pNode->m_lstEdge.MoveToFirst();!pNode->m_lstEdge.IsOut();pNode->m_lstEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge *pEdge1 = pNode->m_lstEdge.GetCurData();
|
|
|
|
|
if(pEdge1->IsNot(VISITED))
|
|
|
|
|
{
|
|
|
|
|
pEdge1->AddFlag(VISITED);
|
|
|
|
|
quene.EnQuene(pEdge1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pNode = pEdge->m_pNode2;
|
|
|
|
|
if(pNode != NULL)
|
|
|
|
|
{
|
|
|
|
|
for(pNode->m_lstEdge.MoveToFirst();!pNode->m_lstEdge.IsOut();pNode->m_lstEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge *pEdge1 = pNode->m_lstEdge.GetCurData();
|
|
|
|
|
if(pEdge1->IsNot(VISITED))
|
|
|
|
|
{
|
|
|
|
|
pEdge1->AddFlag(VISITED);
|
|
|
|
|
quene.EnQuene(pEdge1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lstChildMesh << pChild;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(m_allEdge.MoveToFirst();!m_allEdge.IsOut();m_allEdge.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TGMeshEdge *pEdge = m_allEdge.GetCurData();
|
|
|
|
|
pEdge->RemoveFlag(VISITED);
|
|
|
|
|
m_allEdge.SetCurData(NULL);
|
|
|
|
|
}
|
|
|
|
|
m_allEdge.Clear();
|
|
|
|
|
|
|
|
|
|
for(m_allNode.MoveToFirst();!m_allNode.IsOut();m_allNode.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
if(m_allNode.GetCurData()->m_lstEdge.GetLength() > 0)
|
|
|
|
|
{
|
|
|
|
|
m_allNode.FetchCur();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(m_allMesh.MoveToFirst();!m_allMesh.IsOut();m_allMesh.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
m_allMesh.SetCurData(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_allMesh.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TPGeCurveMesh::CreateRegion(TGObjectList& lstRegion,TGObjectList&lstHole)
|
|
|
|
|
{
|
|
|
|
|
TGObjectList oListCCW,oListCW;
|
|
|
|
|
for(m_allMesh.MoveToFirst();!m_allMesh.IsOut();m_allMesh.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
TPGeCurve2D *pCurve = m_allMesh.GetCurData()->CreateCurve();
|
|
|
|
|
if(pCurve != NULL)
|
|
|
|
|
{
|
|
|
|
|
if(pCurve->IsClosed())
|
|
|
|
|
{
|
|
|
|
|
if(pCurve->IsClockwise())
|
|
|
|
|
{
|
|
|
|
|
pCurve->Reverse();
|
|
|
|
|
oListCW << pCurve;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
oListCCW << pCurve;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
delete pCurve;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(oListCCW.GetLength() == 1)
|
|
|
|
|
{
|
|
|
|
|
TGObjectList oList;
|
|
|
|
|
oList.Conbine(oListCCW);
|
|
|
|
|
oList.Conbine(oListCW);
|
|
|
|
|
|
|
|
|
|
TGRegion2D *pRegion = new TGRegionEx2D(oList,false);
|
|
|
|
|
if(!pRegion->IsValid())
|
|
|
|
|
{
|
|
|
|
|
delete pRegion;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lstRegion << pRegion;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for(oListCCW.MoveToFirst();!oListCCW.IsOut();oListCCW.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
lstRegion << new TGRegionEx2D(oListCCW.GetCurCurve2D(),false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(oListCW.MoveToFirst();!oListCW.IsOut();oListCW.MoveToNext())
|
|
|
|
|
{
|
|
|
|
|
lstHole << new TGRegionEx2D(oListCW.GetCurCurve2D(),false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|