Files
envi-code/SourceCode/Code2026/tg_shs/shs_geLib/TBPloygon.cpp
T
2026-09-28 15:28:50 +08:00

658 lines
12 KiB
C++

//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TBPloygon.cpp
// = Version : ver2.0
// = Author : xlc
// = CreateDate : 2002-09-09
// = Description: 类的定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TBPloygon.h"
#include "TADSGePoint3d.h"
#include "TchGlobalFunc.h"
#include "TchPrivateGlobalFunc.h"
TBPloygon::TBPloygon()
{
m_bPlaned = 0;
}
TBPloygon::TBPloygon(const TBPloyLine& bline):TBPloyLine(bline)
{
m_bPlaned = 0;
m_bClosed = 1;
}
#if ADS > 16
TBPloygon::TBPloygon(const TBPloygon& bline)
{
ReleaseBasLst();
POSITION pos = bline.m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
TBNode* pNode = bline.m_BNodeList.GetNext(pos);
TBNode* pNodeNew = new TBNode;
*pNodeNew = *pNode;
m_BNodeList.AddTail(pNodeNew);
}
m_bClosed = bline.m_bClosed;
m_plane = bline.m_plane;
m_bPlaned = bline.m_bPlaned;
}
#endif
TBPloygon::~TBPloygon()
{
POSITION pos = m_childSRList.GetHeadPosition();
while (pos != NULL)
{
TBPloygon* pNode = m_childSRList.GetNext(pos);
delete pNode;
}
m_childSRList.RemoveAll();
}
void TBPloygon::ReleaseRgnLst(TBPolygonList& sRgnList)
{
POSITION pos = sRgnList.GetHeadPosition();
while (pos != NULL)
{
TBPloygon* pNode = sRgnList.GetNext(pos);
delete pNode;
}
sRgnList.RemoveAll();
}
BOOL TBPloygon::IsSurrounded(TBPloyLine* pPolygon)
{
if (!IsInXYPlane() || !pPolygon->IsInXYPlane())
{
return 0;
}
int n = IsWhere(pPolygon);
if (n == 3)
{
return 0;
}
else if (n == 1)
{
return 1;
}
else
{
int nn = pPolygon->IsWhere(this);
if (nn == 1)
{
return 2;
}
else
{
return 3;
}
}
}
BOOL TBPloygon::CreatAcGePlane()
{
if (m_BNodeList.GetCount() < 4)
{
return 0;
}
int n = 0;
AcGePoint3d pt[3];
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL && n < 3)
{
TBNode* pNode = m_BNodeList.GetNext(pos);
if (n == 0)
{
pt[n++] = pNode->m_pt;
}
else if (n > 0 && !IsEqual(pt[n-1], pNode->m_pt, TOL))
{
pt[n++] = pNode->m_pt;
}
}
if (n < 3)
{
return 0;
}
m_plane = AcGePlane(pt[0],pt[1],pt[2]);
m_bPlaned = 1;
return 1 ;
}
void TBPloygon::TransformBy(AcGeMatrix3d& mat)
{
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
TBNode* pNode = m_BNodeList.GetNext(pos);
pNode->m_pt.transformBy(mat);
}
}
AcGeMatrix3d TBPloygon::GetECSToUCSMat()
{
if (!m_bPlaned)
{
CreatAcGePlane();
}
AcGePoint3d origin;
AcGeVector3d axis1,axis2,axis3;
m_plane.getCoordSystem(origin,axis1,axis2);
axis3 = axis1.crossProduct(axis2);
AcGeMatrix3d mat;
mat.setToAlignCoordSys(AcGePoint3d(0,0,0), AcGeVector3d(-1,0,0), AcGeVector3d(0,1,0),
AcGeVector3d(0,0,1), origin, axis1, axis2, axis3);
return mat;
}
AcGeMatrix3d TBPloygon::GetUCSToECSMat()
{
if (!m_bPlaned)
{
CreatAcGePlane();
}
AcGePoint3d origin;
AcGeVector3d axis1,axis2,axis3;
m_plane.getCoordSystem(origin,axis1,axis2);
axis3 = axis1.crossProduct(axis2);
AcGeMatrix3d mat;
mat.setToAlignCoordSys(origin,axis1,axis2,axis3,AcGePoint3d(0,0,0),
AcGeVector3d(-1,0,0),AcGeVector3d(0,1,0),AcGeVector3d(0,0,1));
return mat;
}
BOOL TBPloygon::IsParallelToXY(double tol)
{
if (!m_bPlaned)
{
CreatAcGePlane();
}
if (!m_bPlaned)
{
return 0;
}
AcGePlane planeXY(AcGePoint3d(1,0,0),AcGePoint3d(0,1,0),AcGePoint3d(1,1,0));
AcGeTol tol1;
tol1.setEqualPoint(tol);
if (m_plane.isParallelTo(planeXY,tol1) == Adesk::kTrue)
{
return 1;
}
return 0;
}
TBNode* TBPloygon::GetNextNode2(TBNode* pNode)
{
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
TBNode* pNodeCur = m_BNodeList.GetNext(pos);
if (pNodeCur == pNode)
{
if (pos == NULL)
{
return NULL;
}
m_BNodeList.GetNext(pos);
if (pos == NULL)
{
return NULL;
}
return m_BNodeList.GetAt(pos);
}
}
return NULL;
}
TBNode* TBPloygon::GetNextNode(TBNode* pNode)
{
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
TBNode* pNodeCur = m_BNodeList.GetNext(pos);
if (pNodeCur == pNode)
{
if (pos == NULL)
{
return m_BNodeList.GetHead();
}
return m_BNodeList.GetAt(pos);
}
}
return NULL;
}
TBNode* TBPloygon::GetPreNode(TBNode* pNode)
{
POSITION pos = m_BNodeList.GetTailPosition();
while (pos != NULL)
{
TBNode* pNodeCur = m_BNodeList.GetPrev(pos);
if (pNodeCur == pNode)
{
if (pos == NULL)
{
POSITION pos1 = m_BNodeList.GetTailPosition();
m_BNodeList.GetPrev(pos1);
return m_BNodeList.GetAt(pos1);
}
return m_BNodeList.GetAt(pos);
}
}
return NULL;
}
BOOL TBPloygon::ConvertToTriangle(TDPtrList<TGGeTriangle> &lstRes)
{
if (m_BNodeList.GetCount() < 4)
{
return 0;
}
if (m_BNodeList.GetCount() == 4)
{
TGGeTriangle* p3dface = ConvertToTriangle();
if (p3dface != NULL)
{
lstRes.Append(p3dface);
}
return 1;
}
TBPolygonList sRgnList;
if (!TrianglizePolygon(sRgnList))
{
return 0;
}
POSITION pos = sRgnList.GetHeadPosition();
while (pos != NULL)
{
TBPloygon* pNode = sRgnList.GetNext(pos);
TGGeTriangle* p3dface = pNode->ConvertToTriangle();
if (p3dface != NULL)
{
lstRes.Append(p3dface);
}
}
ReleaseRgnLst(sRgnList); //释放内存
return 1;
}
BOOL TBPloygon::ConvertTo3DFaces(TAcDbFacePtrList& face3DList)
{
if (m_BNodeList.GetCount() < 4)
{
return 0;
}
if (m_BNodeList.GetCount() == 4)
{
AcDbFace* p3dface = ConvertTo3dFace();
TAcDbFacePtr* pC3DFace = new TAcDbFacePtr(p3dface);
face3DList.AddTail(pC3DFace);
return 1;
}
TBPolygonList sRgnList;
if (!TrianglizePolygon(sRgnList))
{
return 0;
}
POSITION pos = sRgnList.GetHeadPosition();
while (pos != NULL)
{
TBPloygon* pNode = sRgnList.GetNext(pos);
AcDbFace* p3dface = pNode->ConvertTo3dFace();
TAcDbFacePtr* pC3DFace = new TAcDbFacePtr(p3dface);
face3DList.AddTail(pC3DFace);
}
ReleaseRgnLst(sRgnList); //释放内存
return 1;
}
BOOL TBPloygon::TrianglizePolygon(TBPolygonList& sRgnList)
{
if (m_BNodeList.GetCount() < 4)
{
return 1;
}
if (!m_bClosed)
{
return 0;
}
BOOL bTransformed = 0;
AcGeMatrix3d mat;
if (!IsParallelToXY(TOL))
{
mat = GetUCSToECSMat();
TransformBy(mat);
bTransformed = 1;
}
int ret = GetClockwise();
if (ret == 1)
{
Reverse();
}
CutDown(sRgnList);
if (bTransformed)
{
mat = GetECSToUCSMat();
TransformBy(mat);
POSITION pos = sRgnList.GetTailPosition();
while (pos != NULL)
{
TBPloygon* pRgn = sRgnList.GetPrev(pos);
pRgn->TransformBy(mat);
}
}
return 1;
}
BOOL TBPloygon::IsASuitableDivLine(TBNode* pNode1,TBNode* pNode2)
{//判断线段pNode1-pNode2是否能够恰当地将区域剖分开
if (IsPtInsideRgn(pNode1,pNode2)&&
IsPtInsideRgn(pNode2,pNode1)&&
!IsCrossOtherEdges(pNode1,pNode2))
{
return 1;
}
else
{
return 0;
}
}
void TBPloygon::CutDown(TBPolygonList& sRgnList)
{
if (m_BNodeList.GetCount() <= 4)
{
return;
}
TBNode* pHead = m_BNodeList.GetHead();
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
TBNode* pNode = m_BNodeList.GetNext(pos);
TBNode* pNodeNext = GetNextNode2(pNode); //其后第二个结点
while (pNodeNext != NULL && pNodeNext != pHead)
{
if (IsASuitableDivLine(pNode,pNodeNext))
{
TBPloygon* pRgn1 = NULL;
TBPloygon* pRgn2 = NULL;
DivideTo2Polygon(pNode,pNodeNext,pRgn1,pRgn2);
if (pRgn1 != NULL && pRgn2 != NULL)
{
int num1 = pRgn1->m_BNodeList.GetCount();
if (num1 == 4)
{
sRgnList.AddTail(pRgn1);
}
else if (num1 > 4)
{
m_childSRList.AddTail(pRgn1);
pRgn1->CutDown(sRgnList);
}
int num2 = pRgn2->m_BNodeList.GetCount();
if (num2 == 4)
{
sRgnList.AddTail(pRgn2);
}
else if (num2 > 4)
{
m_childSRList.AddTail(pRgn2);
pRgn2->CutDown(sRgnList);
}
}
return;//如果找到剖分线,剖分后即结束此函数
}
pNodeNext = GetNextNode(pNodeNext);
}
}
}
void TBPloygon::DivideTo2Polygon(TBNode* pNode1,TBNode* pNode2,TBPloygon*& pRgn1,TBPloygon*& pRgn2)
{
pRgn1 = new TBPloygon;
pRgn2 = new TBPloygon;
//构造pRgn1
TBNode* pNode = pNode1;
while (pNode != pNode2)
{
TBNode* pNodeNew = new TBNode;
*pNodeNew = *pNode;
pRgn1->m_BNodeList.AddTail(pNodeNew);
pNode = GetNextNode(pNode);
}
TBNode* pNodeNew2 = new TBNode;
*pNodeNew2 = *pNode2;
pRgn1->m_BNodeList.AddTail(pNodeNew2);
TBNode* pNodeNew1 = new TBNode;
*pNodeNew1 = *pNode1;
pRgn1->m_BNodeList.AddTail(pNodeNew1);
pRgn1->m_bClosed = 1;
pRgn1->ClearUp();
pRgn1->ReCalcSValue();
//处理可见性
if (pRgn1->GetClockwise() == 1)
{
pRgn1->Reverse();
pNodeNew1->m_bVisible = 0;
}
else
{
pNodeNew2->m_bVisible = 0;
}
//构造pRgn2
pNode = pNode2;
while (pNode != pNode1)
{
TBNode* pNodeNew = new TBNode;
*pNodeNew = *pNode;
pRgn2->m_BNodeList.AddTail(pNodeNew);
pNode = GetNextNode(pNode);
}
pNodeNew1 = new TBNode;
*pNodeNew1 = *pNode1;
pRgn2->m_BNodeList.AddTail(pNodeNew1);
pNodeNew2 = new TBNode;
*pNodeNew2 = *pNode2;
pRgn2->m_BNodeList.AddTail(pNodeNew2);
pRgn2->m_bClosed = 1;
pRgn2->ClearUp();
pRgn2->ReCalcSValue();
//处理可见性
if (pRgn2->GetClockwise() == 1)
{
pRgn2->Reverse();
pNodeNew2->m_bVisible = 0;
}
else
{
pNodeNew1->m_bVisible = 0;
}
}
BOOL TBPloygon::IsPtInsideRgn(TBNode* pNode,TBNode* pTestNode)
{
if (pNode == NULL||pTestNode == NULL)
{
return 0;
}
TBNode* pNodePrev = GetPreNode(pNode);
TBNode* pNodeNext = GetNextNode(pNode);
//修改
if (!IsOverlap(pNodePrev->m_pt,pNode->m_pt,pNodeNext->m_pt,pNode->m_pt)&&
(!IsEqual(pTestNode->m_pt,pNode->m_pt)&&
!IsEqual(pTestNode->m_pt,pNodePrev->m_pt)&&
!IsEqual(pTestNode->m_pt,pNodeNext->m_pt))&&
(IsOnLineSeg(pNodePrev->m_pt,pNode->m_pt,pTestNode->m_pt)||
IsOnLineSeg(pNodeNext->m_pt,pNode->m_pt,pTestNode->m_pt)))
{
return 1;
}
int ret = PtAtWhichSide(pNodePrev->m_pt,pNode->m_pt,pNodeNext->m_pt);
int ret1 = PtAtWhichSide(pNodePrev->m_pt,pNode->m_pt,pTestNode->m_pt);
int ret2 = PtAtWhichSide(pNode->m_pt,pNodeNext->m_pt,pTestNode->m_pt);
//若pNodeNext在pNodePrev-pNode的左边,则pTestNode须同时在前后边的左边
if (ret == 1 && ret1 == 1 && ret2 == 1)
{
return 1;
}
//若在右边或共线,则pTestNode只须在前或后边的左边
else if (ret != 1 && (ret1 == 1 || ret2 == 1))
{
return 1;
}
return 0;
}
BOOL TBPloygon::IsCrossOtherEdges(TBNode* pNode1,TBNode* pNode2)
{
if (pNode1 == NULL || pNode2 == NULL)
{
return 0;
}
AcGeLineSeg3d lineSeg1(pNode1->m_pt,pNode2->m_pt);
TBNode* pNodePrev = NULL;
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
TBNode* pNode = m_BNodeList.GetNext(pos);
if (pNodePrev != NULL)
{
AcGePoint3d segPt;
AcGeLineSeg3d lineSeg2(pNodePrev->m_pt,pNode->m_pt);
if (lineSeg2.intersectWith(lineSeg1,segPt) == Adesk::kTrue &&
(!IsEqual(pNode1->m_pt,segPt) &&
!IsEqual(pNode2->m_pt,segPt)))
{
return 1;
}
}
pNodePrev = pNode;
}
return 0;
}
TGGeTriangle* TBPloygon::ConvertToTriangle()
{
TGGeTriangle* p3dFace = new TGGeTriangle(TADSGePoint3d(),TADSGePoint3d(),TADSGePoint3d());
p3dFace->m_nFlag = 0x7;
int i = 0;
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL && i < 3)
{
TBNode* pNode = m_BNodeList.GetNext(pos);
switch (i)
{
case 0:
p3dFace->vertex1 = pNode->m_pt;
if(pNode->m_bVisible)
{
p3dFace->m_nFlag &= ~SIDE1_INVISIBLE;
}
break;
case 1:
p3dFace->vertex2 = pNode->m_pt;
if(pNode->m_bVisible)
{
p3dFace->m_nFlag &= ~SIDE2_INVISIBLE;
}
break;
case 2:
p3dFace->vertex3 = pNode->m_pt;
if(pNode->m_bVisible)
{
p3dFace->m_nFlag &= ~SIDE3_INVISIBLE;
}
break;
}
i++;
}
if(i == 1)
{
p3dFace->vertex2 = p3dFace->vertex1;
p3dFace->vertex3 = p3dFace->vertex2;
}
else if(i == 2)
{
p3dFace->vertex3 = p3dFace->vertex2;
}
return p3dFace;
}
AcDbFace* TBPloygon::ConvertTo3dFace()
{
AcDbFace* p3dFace = new AcDbFace;
int i = 0;
POSITION pos = m_BNodeList.GetHeadPosition();
while (pos != NULL && i < 4)
{
TBNode* pNode = m_BNodeList.GetNext(pos);
AcGePoint3d pt = pNode->m_pt;
p3dFace->setVertexAt(i,pt);
if (pNode->m_bVisible)
{
p3dFace->makeEdgeVisibleAt(i);
}
else
{
p3dFace->makeEdgeInvisibleAt(i);
}
i++;
}
return p3dFace;
}
BOOL TBPloygon::IsOnLineSeg(AcGePoint3d pt11,AcGePoint3d pt12,AcGePoint3d pt,double tol)
{
AcGeTol tol1;
tol1.setEqualPoint(tol);
AcGeLineSeg3d line(pt11,pt12);
if (line.isOn(pt,tol1))
{
return 1;
}
else
{
return 0;
}
}