658 lines
12 KiB
C++
658 lines
12 KiB
C++
//-----------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : CPloygon.cpp
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: 类的定义
|
|
// = Maintainers:
|
|
//
|
|
//-----------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "CPloygon.h"
|
|
#include "XPoint.h"
|
|
#include "XGlobalFunc.h"
|
|
#include "XPrivateGlobalFunc.h"
|
|
|
|
CPloygon::CPloygon()
|
|
{
|
|
m_bPlaned = 0;
|
|
}
|
|
|
|
CPloygon::CPloygon(const CPloyLine& bline):CPloyLine(bline)
|
|
{
|
|
m_bPlaned = 0;
|
|
m_bClosed = 1;
|
|
}
|
|
|
|
#if ARX > 17
|
|
CPloygon::CPloygon(const CPloygon& bline)
|
|
{
|
|
ReleaseBasLst();
|
|
POSITION pos = bline.m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* pNode = bline.m_BNodeList.GetNext(pos);
|
|
CBNode* pNodeNew = new CBNode;
|
|
*pNodeNew = *pNode;
|
|
m_BNodeList.AddTail(pNodeNew);
|
|
|
|
}
|
|
|
|
m_bClosed = bline.m_bClosed;
|
|
m_plane = bline.m_plane;
|
|
m_bPlaned = bline.m_bPlaned;
|
|
}
|
|
#endif
|
|
|
|
CPloygon::~CPloygon()
|
|
{
|
|
POSITION pos = m_childSRList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CPloygon* pNode = m_childSRList.GetNext(pos);
|
|
delete pNode;
|
|
}
|
|
m_childSRList.RemoveAll();
|
|
}
|
|
|
|
void CPloygon::ReleaseRgnLst(TBPolygonList& sRgnList)
|
|
{
|
|
POSITION pos = sRgnList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CPloygon* pNode = sRgnList.GetNext(pos);
|
|
delete pNode;
|
|
}
|
|
sRgnList.RemoveAll();
|
|
}
|
|
|
|
BOOL CPloygon::IsSurrounded(CPloyLine* 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 CPloygon::CreatAcGePlane()
|
|
{
|
|
if (m_BNodeList.GetCount() < 4)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int n = 0;
|
|
AcGePoint3d pt[3];
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL && n < 3)
|
|
{
|
|
CBNode* 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 CPloygon::TransformBy(AcGeMatrix3d& mat)
|
|
{
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* pNode = m_BNodeList.GetNext(pos);
|
|
pNode->m_pt.transformBy(mat);
|
|
}
|
|
}
|
|
|
|
AcGeMatrix3d CPloygon::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 CPloygon::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 CPloygon::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;
|
|
}
|
|
|
|
CBNode* CPloygon::GetNextNode2(CBNode* pNode)
|
|
{
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* 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;
|
|
}
|
|
|
|
CBNode* CPloygon::GetNextNode(CBNode* pNode)
|
|
{
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* pNodeCur = m_BNodeList.GetNext(pos);
|
|
if (pNodeCur == pNode)
|
|
{
|
|
if (pos == NULL)
|
|
{
|
|
return m_BNodeList.GetHead();
|
|
}
|
|
return m_BNodeList.GetAt(pos);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
CBNode* CPloygon::GetPreNode(CBNode* pNode)
|
|
{
|
|
POSITION pos = m_BNodeList.GetTailPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* 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 CPloygon::ConvertToTriangle(DList<XTriangle> &lstRes)
|
|
{
|
|
if (m_BNodeList.GetCount() < 4)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (m_BNodeList.GetCount() == 4)
|
|
{
|
|
XTriangle* p3dface = ConvertToTriangle();
|
|
if (p3dface != NULL)
|
|
{
|
|
lstRes.Append(p3dface);
|
|
}
|
|
return 1;
|
|
}
|
|
TBPolygonList sRgnList;
|
|
if (!TrianglizePolygon(sRgnList))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
POSITION pos = sRgnList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CPloygon* pNode = sRgnList.GetNext(pos);
|
|
XTriangle* p3dface = pNode->ConvertToTriangle();
|
|
if (p3dface != NULL)
|
|
{
|
|
lstRes.Append(p3dface);
|
|
}
|
|
}
|
|
ReleaseRgnLst(sRgnList); //释放内存
|
|
return 1;
|
|
}
|
|
|
|
BOOL CPloygon::ConvertTo3DFaces(C3DFaceList& face3DList)
|
|
{
|
|
if (m_BNodeList.GetCount() < 4)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (m_BNodeList.GetCount() == 4)
|
|
{
|
|
AcDbFace* p3dface = ConvertTo3dFace();
|
|
C3DFace* pC3DFace = new C3DFace(p3dface);
|
|
face3DList.AddTail(pC3DFace);
|
|
return 1;
|
|
}
|
|
TBPolygonList sRgnList;
|
|
if (!TrianglizePolygon(sRgnList))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
POSITION pos = sRgnList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CPloygon* pNode = sRgnList.GetNext(pos);
|
|
AcDbFace* p3dface = pNode->ConvertTo3dFace();
|
|
C3DFace* pC3DFace = new C3DFace(p3dface);
|
|
face3DList.AddTail(pC3DFace);
|
|
}
|
|
ReleaseRgnLst(sRgnList); //释放内存
|
|
return 1;
|
|
}
|
|
|
|
BOOL CPloygon::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)
|
|
{
|
|
CPloygon* pRgn = sRgnList.GetPrev(pos);
|
|
pRgn->TransformBy(mat);
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
BOOL CPloygon::IsASuitableDivLine(CBNode* pNode1,CBNode* pNode2)
|
|
{//判断线段pNode1-pNode2是否能够恰当地将区域剖分开
|
|
if (IsPtInsideRgn(pNode1,pNode2)&&
|
|
IsPtInsideRgn(pNode2,pNode1)&&
|
|
!IsCrossOtherEdges(pNode1,pNode2))
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void CPloygon::CutDown(TBPolygonList& sRgnList)
|
|
{
|
|
if (m_BNodeList.GetCount() <= 4)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CBNode* pHead = m_BNodeList.GetHead();
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* pNode = m_BNodeList.GetNext(pos);
|
|
CBNode* pNodeNext = GetNextNode2(pNode); //其后第二个结点
|
|
while (pNodeNext != NULL && pNodeNext != pHead)
|
|
{
|
|
if (IsASuitableDivLine(pNode,pNodeNext))
|
|
{
|
|
CPloygon* pRgn1 = NULL;
|
|
CPloygon* pRgn2 = NULL;
|
|
DivideTo2Polygon(pNode,pNodeNext,pRgn1,pRgn2);
|
|
|
|
if (pRgn1 != NULL && pRgn2 != NULL)
|
|
{
|
|
INT_PTR 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 CPloygon::DivideTo2Polygon(CBNode* pNode1,CBNode* pNode2,CPloygon*& pRgn1,CPloygon*& pRgn2)
|
|
{
|
|
pRgn1 = new CPloygon;
|
|
pRgn2 = new CPloygon;
|
|
//构造pRgn1
|
|
CBNode* pNode = pNode1;
|
|
while (pNode != pNode2)
|
|
{
|
|
CBNode* pNodeNew = new CBNode;
|
|
*pNodeNew = *pNode;
|
|
pRgn1->m_BNodeList.AddTail(pNodeNew);
|
|
pNode = GetNextNode(pNode);
|
|
}
|
|
|
|
CBNode* pNodeNew2 = new CBNode;
|
|
*pNodeNew2 = *pNode2;
|
|
pRgn1->m_BNodeList.AddTail(pNodeNew2);
|
|
|
|
CBNode* pNodeNew1 = new CBNode;
|
|
*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)
|
|
{
|
|
CBNode* pNodeNew = new CBNode;
|
|
*pNodeNew = *pNode;
|
|
pRgn2->m_BNodeList.AddTail(pNodeNew);
|
|
pNode = GetNextNode(pNode);
|
|
}
|
|
|
|
pNodeNew1 = new CBNode;
|
|
*pNodeNew1 = *pNode1;
|
|
pRgn2->m_BNodeList.AddTail(pNodeNew1);
|
|
|
|
pNodeNew2 = new CBNode;
|
|
*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 CPloygon::IsPtInsideRgn(CBNode* pNode,CBNode* pTestNode)
|
|
{
|
|
if (pNode == NULL||pTestNode == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
CBNode* pNodePrev = GetPreNode(pNode);
|
|
CBNode* 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 CPloygon::IsCrossOtherEdges(CBNode* pNode1,CBNode* pNode2)
|
|
{
|
|
if (pNode1 == NULL || pNode2 == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
AcGeLineSeg3d lineSeg1(pNode1->m_pt,pNode2->m_pt);
|
|
CBNode* pNodePrev = NULL;
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
CBNode* 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;
|
|
}
|
|
|
|
XTriangle* CPloygon::ConvertToTriangle()
|
|
{
|
|
XTriangle* p3dFace = new XTriangle(XPoint(),XPoint(),XPoint());
|
|
p3dFace->m_nFlag = 0x7;
|
|
int i = 0;
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL && i < 3)
|
|
{
|
|
CBNode* 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* CPloygon::ConvertTo3dFace()
|
|
{
|
|
AcDbFace* p3dFace = new AcDbFace;
|
|
int i = 0;
|
|
POSITION pos = m_BNodeList.GetHeadPosition();
|
|
while (pos != NULL && i < 4)
|
|
{
|
|
CBNode* 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 CPloygon::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;
|
|
}
|
|
}
|