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