//-----------------------------------------------------------------------------+ // 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 &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; } }