Files
envi-code/SourceCode/Code2026/AdsXRx/CHole.cpp
T

1360 lines
27 KiB
C++
Raw Normal View History

2026-10-04 00:04:20 +08:00
//-----------------------------------------------------------------------------+
2026-09-28 15:28:50 +08:00
// Copyright (C), 1998-2007, SH Software Co. Ltd.
// = FileName : CHole.cpp
// = Version : ver2.0
// = Author : zjq
// = CreateDate : 2002-09-09
2026-10-04 00:04:20 +08:00
// = Description: 类的定义
2026-09-28 15:28:50 +08:00
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "CHole.h"
#include "XPrivateGlobalFunc.h"
CHole::CHole()
{
}
CHole::~CHole()
{
}
BOOL CHole::ConstructEdgeList(const DList<XPoly2D> &lstHole)
{
int nCount = lstHole.Length();
if(nCount <= 0)
{
return FALSE;
}
for(int i = 0; i < nCount; i++)
{
const XPoly2D &polyTemp = lstHole[i];
if(polyTemp.IsClosed())
{
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(polyTemp);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
}
}
}
}
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
if (m_RegionLst.GetCount() == 1)
{
return 1;
}
return FormatEdgeList();
}
BOOL CHole::ConstructEdgeList(const DList<XPolygonEx> &lstHole)
{
int nCount = lstHole.Length();
if(nCount <= 0)
{
return FALSE;
}
for(int i = 0; i < nCount; i++)
{
const XPolygonEx &polyTemp = lstHole[i];
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(polyTemp);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
}
}
}
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
if (m_RegionLst.GetCount() == 1)
{
return 1;
}
return FormatEdgeList();
}
BOOL CHole::ConstructEdgeList(const XPolygonEx &out, const DList<XPoly2D> &lstHole)
{
if(out.Length() <= 2)
{
return FALSE;
}
2026-10-04 00:04:20 +08:00
//out放到表首,后面不再判断最外边界,
//仅判断边界边界是否相交和洞中是否有洞
2026-09-28 15:28:50 +08:00
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(out);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
return FALSE;
}
}
else
{
return FALSE;
}
int nCount = lstHole.Length();
for(int i=0; i<nCount; i++)
{
const XPoly2D &polyTemp = lstHole[i];
if(polyTemp.IsClosed())
{
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(polyTemp);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
}
}
}
}
nCount = m_RegionLst.GetCount();
if (nCount == 0)
{
return 0;
}
if (nCount == 1)
{
return 1;
}
return FormatEdgeListAuto();
}
BOOL CHole::ConstructEdgeList(const XPolygonEx &out, const DList<XPolygonEx> &lstHole)
{
if(out.Length() <= 2)
return FALSE;
2026-10-04 00:04:20 +08:00
//out放到表首,后面不再判断最外边界,
//仅判断边界边界是否相交和洞中是否有洞
2026-09-28 15:28:50 +08:00
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(out);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
return FALSE;
}
}
else
{
return FALSE;
}
int nCount = lstHole.Length();
for(int i = 0; i < nCount; i++)
{
const XPolygonEx &polyTemp = lstHole[i];
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(polyTemp);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
}
}
}
nCount = m_RegionLst.GetCount();
if (nCount == 0)
{
return 0;
}
if (nCount == 1)
{
return 1;
}
return FormatEdgeListAuto();
}
BOOL CHole::ConstructEdgeList(const XPoly2D &out, const DList<XPoly2D> &lstHole)
{
if(out.Length() <= 2 && !out.IsClosed())
return FALSE;
2026-10-04 00:04:20 +08:00
//out放到表首,后面不再判断最外边界,
//仅判断边界边界是否相交和洞中是否有洞
2026-09-28 15:28:50 +08:00
CPloygon* pSideLine = NULL;
pSideLine = new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(out);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
return FALSE;
}
}
else
{
return FALSE;
}
int nCount = lstHole.Length();
for(int i=0; i<nCount; i++)
{
const XPoly2D &polyTemp = lstHole[i];
if(polyTemp.IsClosed())
{
CPloygon* pSideLine = NULL;
pSideLine=new CPloygon;
if(pSideLine != NULL)
{
pSideLine->Create(polyTemp);
if (pSideLine->m_bClosed && !pSideLine->IsEmpty())
{
m_RegionLst.AddTail(pSideLine);
}
else
{
delete pSideLine;
}
}
}
}
nCount = m_RegionLst.GetCount();
if (nCount == 0)
{
return 0;
}
if (nCount == 1)
{
return 1;
}
return FormatEdgeListAuto();
}
2026-10-04 00:04:20 +08:00
//处理边链表(未指定外边界)
2026-09-28 15:28:50 +08:00
BOOL CHole::FormatEdgeList()
{
2026-10-04 00:04:20 +08:00
//判断各封闭多义线是否相交,并找出外边界,放到表首
2026-09-28 15:28:50 +08:00
POSITION pos1 = m_RegionLst.GetHeadPosition();
CPloygon* pSurround = NULL;
2026-10-04 00:04:20 +08:00
int nSrdTot = 0; //总包含次数
2026-09-28 15:28:50 +08:00
while (pos1 != NULL)
{
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
POSITION pos2 = m_RegionLst.GetHeadPosition();
2026-10-04 00:04:20 +08:00
int nSrd = 0; //pPolygon1与其他多边形的包含次数
2026-09-28 15:28:50 +08:00
while (pos2 != NULL)
{
CPloygon* pPolygon2=m_RegionLst.GetNext(pos2);
if (pPolygon1 != pPolygon2)
{
CPloygon* plgTemp = NULL;
int ret = pPolygon1->IsSurrounded(pPolygon2);
if (ret == 0)
2026-10-04 00:04:20 +08:00
{//AfxMessageBox(_T("有边界线相交,无法构造孔板!"));
2026-09-28 15:28:50 +08:00
return 0;
}
else if (ret == 1)
2026-10-04 00:04:20 +08:00
{//包含pPolygon,
2026-09-28 15:28:50 +08:00
nSrd++;
nSrdTot++;
plgTemp = pPolygon1;
if (nSrdTot == 1)
{
pSurround=plgTemp;
}
}
else if (ret == 2)
2026-10-04 00:04:20 +08:00
{//被pPolygon包含
2026-09-28 15:28:50 +08:00
nSrd++;
nSrdTot++;
plgTemp = pPolygon2;
if (nSrdTot == 1)
{
pSurround=plgTemp;
}
}
if (nSrdTot > 1 && plgTemp != NULL && pSurround != plgTemp)
2026-10-04 00:04:20 +08:00
{//AfxMessageBox(_T("孔中包含有孔,不合理!"));
2026-09-28 15:28:50 +08:00
return 0;
}
}
}
if (nSrd == 0)
2026-10-04 00:04:20 +08:00
{//AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
2026-09-28 15:28:50 +08:00
return 0;
}
}
if (nSrdTot == 0)
2026-10-04 00:04:20 +08:00
{//AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
2026-09-28 15:28:50 +08:00
return Acad::eNotImplementedYet;
}
if (pSurround != NULL)
{
POSITION posSrd = m_RegionLst.Find(pSurround);
m_RegionLst.RemoveAt(posSrd);
m_RegionLst.AddHead(pSurround);
}
else
{
return 0;
}
2026-10-04 00:04:20 +08:00
//改变方向,外边界逆时针,内边界顺时针
2026-09-28 15:28:50 +08:00
POSITION pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
BOOL ret = pPolygon->GetClockwise();
if (pPolygon == pSurround&&ret == 1)
{
pPolygon->Reverse();
}
else if (ret == 2)
{
pPolygon->Reverse();
}
}
return TRUE;
}
2026-10-04 00:04:20 +08:00
//处理边链表(已经指定外边界,不再判断)
2026-09-28 15:28:50 +08:00
BOOL CHole::FormatEdgeListAuto()
{
BOOL bRet = FALSE;
int nRet = -1;
2026-10-04 00:04:20 +08:00
//判断所有各封闭多义线是否相交,判断洞中是否有洞
2026-09-28 15:28:50 +08:00
POSITION pos1 = m_RegionLst.GetHeadPosition();
if(pos1 == NULL)
{
return FALSE;
}
CPloygon* pSurround = m_RegionLst.GetNext(pos1);
while (pos1 != NULL)
2026-10-04 00:04:20 +08:00
{//是否与最外边界相交
2026-09-28 15:28:50 +08:00
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
if(pPolygon1 != pSurround)
{
nRet = pSurround->IsSurrounded(pPolygon1);
2026-10-04 00:04:20 +08:00
// 最外边界不包括此洞
2026-09-28 15:28:50 +08:00
if (nRet != 1)
{
return FALSE;
}
}
2026-10-04 00:04:20 +08:00
//洞与洞之间的关系
2026-09-28 15:28:50 +08:00
POSITION pos2 = pos1;
while (pos2 != NULL)
{
CPloygon* pPolygon2 = m_RegionLst.GetNext(pos2);
if (pPolygon1 != pPolygon2)
{
nRet = pPolygon1->IsSurrounded(pPolygon2);
if (nRet == 0 || nRet == 1 || nRet == 2)
{
return FALSE;
}
}
}
}
2026-10-04 00:04:20 +08:00
//改变方向,外边界逆时针,内边界顺时针
2026-09-28 15:28:50 +08:00
POSITION pos=m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
bRet = pPolygon->GetClockwise();
if (pPolygon == pSurround && bRet == 1)
{
pPolygon->Reverse();
}
else if (bRet == 2)
{
pPolygon->Reverse();
}
}
return TRUE;
}
BOOL CHole::ConstructEdgeList()
{
ads_name ssname;
struct resbuf* pCondition;
pCondition = acutBuildList(-4,_T("<OR"),RTDXF0,_T("CIRCLE"),RTDXF0,_T("LWPOLYLINE"),
RTDXF0,_T("POLYLINE"),-4,_T("OR>"),0);
const TCHAR* prompts[2];
2026-10-04 00:04:20 +08:00
prompts[0]=_T("\n请选择边界线,(<Enter>结束):");
prompts[1]=_T("\n请选择要剔除的边界线:");
2026-09-28 15:28:50 +08:00
if (acedSSGet(_T(":$"),prompts,NULL,pCondition,ssname) == RTCAN)
{
acedSSFree(ssname);
return 0;
}
acutRelRb(pCondition);
Adesk::Int32 nEnt;
if (acedSSLength(ssname,&nEnt) != RTNORM)
{
acedSSFree(ssname);
return 0;
}
for (long i = 0; i < nEnt; i++)
{
ads_name sEntName;
if (acedSSName(ssname,i,sEntName) != RTNORM)
{
acedSSFree(ssname);
return 0;
}
AcDbObjectId objId;
if (acdbGetObjectId(objId, sEntName) != Acad::eOk)
{
acedSSFree(ssname);
return 0;
}
if (objId == NULL)
{
acedSSFree(ssname);
return 0;
}
CPloygon* pSideLine = new CPloygon;
pSideLine->Create(objId);
if (!pSideLine->m_bClosed)
{
2026-10-04 00:04:20 +08:00
AfxMessageBox(_T("所选图形有非闭合区域!"));
2026-09-28 15:28:50 +08:00
acedSSFree(ssname);
return 0;
}
if (!(pSideLine->IsEmpty()))
{
CPloygon* pRgn=new CPloygon(*pSideLine);
m_RegionLst.AddTail(pRgn);
delete pSideLine;
}
}
acedSSFree(ssname);
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
2026-10-04 00:04:20 +08:00
//平移
2026-09-28 15:28:50 +08:00
CPloygon* pHead = m_RegionLst.GetHead();
CBNode* pNode = pHead->Head();
if (pNode != NULL)
{
m_insertPt = pNode->m_pt;
}
AcGeVector3d disp = AcGePoint3d(0,0,0) - m_insertPt;
POSITION pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
2026-10-04 00:04:20 +08:00
{//平移
2026-09-28 15:28:50 +08:00
CPloygon* pRgn = m_RegionLst.GetNext(pos);
pRgn->MoveTo(disp);
}
if (m_RegionLst.GetCount() == 1)
{
return 1;
}
2026-10-04 00:04:20 +08:00
//判断各封闭多义线是否相交,并找出外边界,放到表首
2026-09-28 15:28:50 +08:00
POSITION pos1 = m_RegionLst.GetHeadPosition();
CPloygon* pSurround = NULL;
2026-10-04 00:04:20 +08:00
int nSrdTot = 0; //总包含次数
2026-09-28 15:28:50 +08:00
while (pos1 != NULL)
{
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
POSITION pos2 = m_RegionLst.GetHeadPosition();
2026-10-04 00:04:20 +08:00
int nSrd = 0; //pPolygon1与其他多边形的包含次数
2026-09-28 15:28:50 +08:00
while (pos2 != NULL)
{
CPloygon* pPolygon2 = m_RegionLst.GetNext(pos2);
if (pPolygon1 != pPolygon2)
{
CPloygon* plgTemp = NULL;
int ret = pPolygon1->IsSurrounded(pPolygon2);
if (ret == 0)
{
2026-10-04 00:04:20 +08:00
AfxMessageBox(_T("有边界线相交,无法构造孔板!"));
2026-09-28 15:28:50 +08:00
return 0;
}
else if (ret == 1)
{
nSrd++;
nSrdTot++;
plgTemp=pPolygon1;
if (nSrdTot == 1)
{
pSurround = plgTemp;
}
}
else if (ret == 2)
{
nSrd++;
nSrdTot++;
plgTemp = pPolygon2;
if (nSrdTot == 1)
{
pSurround = plgTemp;
}
}
if (nSrdTot > 1 && plgTemp != NULL && pSurround != plgTemp)
{
2026-10-04 00:04:20 +08:00
AfxMessageBox(_T("孔中包含有孔,不合理!"));
2026-09-28 15:28:50 +08:00
return 0;
}
}
}
if (nSrd == 0)
{
2026-10-04 00:04:20 +08:00
AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
2026-09-28 15:28:50 +08:00
return 0;
}
}
if (nSrdTot == 0)
{
2026-10-04 00:04:20 +08:00
AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
2026-09-28 15:28:50 +08:00
return Acad::eNotImplementedYet;
}
if (pSurround != NULL)
{
POSITION posSrd = m_RegionLst.Find(pSurround);
m_RegionLst.RemoveAt(posSrd);
m_RegionLst.AddHead(pSurround);
}
else
{
return 0;
}
2026-10-04 00:04:20 +08:00
//改变方向,外边界逆时针,内边界顺时针
2026-09-28 15:28:50 +08:00
pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
BOOL ret = pPolygon->GetClockwise();
if (pPolygon == pSurround&&ret == 1)
{
pPolygon->Reverse();
}
else if (ret == 2)
{
pPolygon->Reverse();
}
}
return 1;
}
BOOL CHole::GetTriangles(DList<XTriangle> &lstRes)
{
return SimplifyToTriangle(lstRes);
}
void CHole::CreateHoles()
{
if(m_RegionLst.GetCount() == 0)
{
if (!ConstructEdgeList())
{
return;
}
}
2026-10-04 00:04:20 +08:00
//直线段化
2026-09-28 15:28:50 +08:00
POSITION pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pRgn = m_RegionLst.GetNext(pos);
pRgn->LinearizePLine(1);
}
C3DFaceList face3DList;
if (!SimplifyToFace(face3DList))
{
return;
}
if (m_RegionLst.GetCount() == 0)
{
return;
}
CString blockName_main = _T("Hole");
CEntityList entLst;
AcDbObjectId blockId;
C3DFaceList2EntityList(face3DList,entLst);
SetLayerOfEntities(entLst,_T("1"),1);
if (!CreateBlock(entLst,blockName_main,blockId,AcGePoint3d(0,0,0)))
{
return;
}
ReleaseCEntityList(entLst);
ReleaseC3DFaceList(face3DList);
AcGePoint3d org = m_insertPt;
org.z = 0;
if (!CreateReference(org,blockName_main,0))
{
return;
}
}
BOOL CHole::SimplifyToTriangle(DList<XTriangle> &lstRes)
{
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
if (!SortHolesInXY())
{
return 0;
}
if (!SortNodesAlongClockWise())
{
return 0;
}
2026-10-04 00:04:20 +08:00
//复制一个新链表
2026-09-28 15:28:50 +08:00
TBPolygonList RegionLst;
POSITION pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
CPloygon* pPolygonNew = new CPloygon(*pPolygon);
pPolygonNew->ClearUp();
RegionLst.AddTail(pPolygonNew);
}
CPloygon* pHead = RegionLst.GetHead();
pos = RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = RegionLst.GetNext(pos);
if (pPolygon != pHead)
{
CBNode* pNode = pPolygon->GetMostLeftNode();
CBNode* pNodeSuit = GetADivideNode(pHead,pPolygon,pNode);
if (pNodeSuit != NULL)
{
pHead->InsertBLineInto(pNodeSuit,pPolygon);
}
}
}
2026-10-04 00:04:20 +08:00
//三角化
2026-09-28 15:28:50 +08:00
CPloygon rgn = CPloygon(*pHead);
rgn.ConvertToTriangle(lstRes);
2026-10-04 00:04:20 +08:00
//***** 释放内存
2026-09-28 15:28:50 +08:00
pos = RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = RegionLst.GetNext(pos);
delete pPolygon;
}
return 1;
}
BOOL CHole::SimplifyToFace(C3DFaceList& face3DList)
{
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
if (!SortHolesInXY())
{
return 0;
}
if (!SortNodesAlongClockWise())
{
return 0;
}
TBPolygonList RegionLst;
POSITION pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
CPloygon* pPolygonNew = new CPloygon(*pPolygon);
pPolygonNew->ClearUp();
RegionLst.AddTail(pPolygonNew);
}
CPloygon* pHead = RegionLst.GetHead();
pos = RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = RegionLst.GetNext(pos);
if (pPolygon != pHead)
{
CBNode* pNode = pPolygon->GetMostLeftNode();
CBNode* pNodeSuit = GetADivideNode(pHead,pPolygon,pNode);
if (pNodeSuit != NULL)
{
pHead->InsertBLineInto(pNodeSuit,pPolygon);
}
}
}
2026-10-04 00:04:20 +08:00
//三角化
2026-09-28 15:28:50 +08:00
CPloygon rgn = CPloygon(*pHead);
rgn.ConvertTo3DFaces(face3DList);
2026-10-04 00:04:20 +08:00
//***** 释放内存
2026-09-28 15:28:50 +08:00
pos = RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = RegionLst.GetNext(pos);
delete pPolygon;
}
return 1;
}
CBNode* CHole::GetADivideNode(CPloygon* pEdge,CPloygon* pEdge1,CBNode* pNode)
{
2026-10-04 00:04:20 +08:00
//pEdge:外边界
//pEdge1:内边界(孔)
//pNode:内边界上最左边的节点
2026-09-28 15:28:50 +08:00
if (pEdge == NULL || pNode == NULL)
{
return NULL;
}
pEdge->ReCalcSValue();
2026-10-04 00:04:20 +08:00
double limitX = pNode->m_pt.x;//内边界最左边节点的X坐标
2026-09-28 15:28:50 +08:00
CBNode* pTemp = NULL;
POSITION pos = pEdge->m_BNodeList.GetHeadPosition();
while (pos != NULL)
{
CBNode* pNode0 = pEdge->m_BNodeList.GetNext(pos);
2026-10-04 00:04:20 +08:00
//修改: modified on 2003.9.3
2026-09-28 15:28:50 +08:00
//if (pNode0->m_pt.x<=limitX)
if (pNode0->m_pt.x < limitX || fabs(pNode0->m_pt.x - limitX) < fTOL)
2026-10-04 00:04:20 +08:00
{//在外边界上选择X坐标小于或等于内边界上最左边节点的点
2026-09-28 15:28:50 +08:00
CBNode* pPrev = pEdge->GetPreNode(pNode0);
CBNode* pNext = pEdge->GetNextNode(pNode0);
int n = PtAtWhichSide(pPrev->m_pt, pNode0->m_pt, pNext->m_pt);
BOOL bSuitable = 0;
2026-10-04 00:04:20 +08:00
//如果pNode0的后一个节点在有向线段pPrev->pNode0的右侧
2026-09-28 15:28:50 +08:00
if (n == 2)
2026-10-04 00:04:20 +08:00
{//则只要pNode位于pPrev->pNode0的左侧或者pNode0->pNext的左侧,包括边界上,pNode0都是一个合适的节点
2026-09-28 15:28:50 +08:00
if (PtAtWhichSide(pPrev->m_pt,pNode0->m_pt,pNode->m_pt) != 2
||PtAtWhichSide(pNode0->m_pt,pNext->m_pt,pNode->m_pt) != 2)
{
bSuitable = 1;
}
}
else
2026-10-04 00:04:20 +08:00
{ //如果pNode0的后一个节点在有向线段pPrev->pNode0的左侧或线上
//则pNode要同时位于pPrev->pNode0和pNode0->pNext的左侧,
//包括边界上,pNode0才是一个合适的节点
2026-09-28 15:28:50 +08:00
if (PtAtWhichSide(pPrev->m_pt,pNode0->m_pt,pNode->m_pt) != 2
&& PtAtWhichSide(pNode0->m_pt,pNext->m_pt,pNode->m_pt) != 2)
{
bSuitable = 1;
}
}
if (bSuitable)
2026-10-04 00:04:20 +08:00
{//同时,线段pNode0->pNode不与外边界上位于X=limitX左侧的边界相交
2026-09-28 15:28:50 +08:00
if (!(pEdge->IsIntersectWith(limitX,pNode0->m_pt,pNode->m_pt)))
{
return pNode0;
}
}
}
}
return NULL;
}
BOOL CHole::SortHolesInXY()
{
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
CPloygon* pHead = m_RegionLst.GetHead();
TBPolygonList tempList;
tempList.AddTail(pHead);
POSITION pos1 = m_RegionLst.GetHeadPosition();
while (pos1 != NULL)
{
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
if (pPolygon1 == pHead) continue;
CPloygon* pPolygon2 = tempList.GetTail();
double x1 = pPolygon1->GetMinX();
double x2 = pPolygon2->GetMinX();
if (x1 > x2)
{
tempList.AddTail(pPolygon1);
}
else if (fabs(x1 - x2) < fTOL)
{
if (pPolygon2 == pHead)
{
tempList.AddTail(pPolygon1);
}
else
{
double y1 = pPolygon1->GetMaxY();
double y2 = pPolygon2->GetMaxY();
POSITION pos2 = tempList.GetTailPosition();
if (y1 > y2)
{
tempList.AddTail(pPolygon1);
}
else
{
tempList.InsertBefore(pos2,pPolygon1);
}
}
}
else
{
POSITION pos2 = tempList.GetHeadPosition();
while (pos2 != NULL)
{
POSITION posTemp = pos2;
pPolygon2 = tempList.GetNext(pos2);
x2 = pPolygon2->GetMinX();
if (x1 < x2 && pPolygon1 != pHead)
{
tempList.InsertBefore(posTemp,pPolygon1);
break;
}
}
}
}
m_RegionLst.RemoveAll();
m_RegionLst.AddTail(&tempList);
return 1;
}
BOOL CHole::SortNodesAlongClockWise()
{
if (m_RegionLst.GetCount() == 0)
{
return 0;
}
2026-10-04 00:04:20 +08:00
//外边界
2026-09-28 15:28:50 +08:00
CPloygon* pHead = m_RegionLst.GetHead();
if (!(pHead->IsClosed()))
{
return 0;
}
CBNode* pLeft = pHead->GetMostLeftNode();
if (pLeft == NULL)
{
return 0;
}
2026-10-04 00:04:20 +08:00
//将最左边的点设为头
2026-09-28 15:28:50 +08:00
pHead->ResetHead(pLeft);
if (pHead->GetClockwise() == 1)
2026-10-04 00:04:20 +08:00
{//保证逆时针
2026-09-28 15:28:50 +08:00
pHead->Reverse();
}
2026-10-04 00:04:20 +08:00
//处理内边界
2026-09-28 15:28:50 +08:00
POSITION pos = m_RegionLst.GetHeadPosition();
while (pos != NULL)
{
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
if (pPolygon != pHead)
{
CBNode* pLeft = pPolygon->GetMostLeftNode();
if (pLeft != NULL)
2026-10-04 00:04:20 +08:00
{//将最左边的点设为头
2026-09-28 15:28:50 +08:00
pPolygon->ResetHead(pLeft);
if (pPolygon->GetClockwise() == 2)
2026-10-04 00:04:20 +08:00
{ //保证顺时针
2026-09-28 15:28:50 +08:00
pPolygon->Reverse();
}
}
}
}
return 1;
}
BOOL CHole::CreateReference(AcGePoint3d org,CString& BlockTableRecordName,double rotAng,CString layerName)
{
AcDbBlockReference* pNewBlkRef;
AcDbObjectId newEntId;
AcDbObjectId newBlockId;
AcDbBlockTable* pBlockTable;
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
Acad::ErrorStatus es = pBlockTable->getAt(BlockTableRecordName,newBlockId);
if (es != Acad::eOk)
{
pBlockTable->close();
return 0;
}
pBlockTable->close();
AcDbObjectId layerId = NULL;
if (layerName != _T(""))
{
if (!IsLayerExistInDb(layerName))
{
NewLayer(layerName);
}
SetLayerFrozen(layerName,false);
SetLayerOff(layerName,false);
layerId = GetLayerRecordId(layerName);
}
pNewBlkRef = new AcDbBlockReference;
AcGeVector3d normal = AcGeVector3d(0.0,0.0,1.0);
AcGePoint3d basePt = org;
UCS2WCS(basePt);
AcGeMatrix3d mat;
acdbUcsMatrix(mat);
AcGeMatrix3d mat1;
mat1(0,0) = cos(rotAng);
mat1(0,1) = -sin(rotAng);
mat1(1,0) = sin(rotAng);
mat1(1,1) = cos(rotAng);
mat = mat * mat1;
pNewBlkRef->setBlockTableRecord(newBlockId);
pNewBlkRef->setNormal(normal);
pNewBlkRef->setBlockTransform(mat);
pNewBlkRef->setPosition(basePt);
if (layerId != NULL)
{
pNewBlkRef->setLayer(layerId);
}
acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForRead);
AcDbBlockTableRecord* pBlockTableRec;
es = pBlockTable->getAt(ACDB_MODEL_SPACE,pBlockTableRec,AcDb::kForWrite);
if (es != Acad::eOk)
{
pBlockTable->close();
delete pNewBlkRef;
return 0;
}
pBlockTable->close();
es = pBlockTableRec->appendAcDbEntity(newEntId,pNewBlkRef);
if (es != Acad::eOk)
{
pBlockTableRec->close();
return 0;
}
pBlockTableRec->close();
pNewBlkRef->close();
return 1;
}
BOOL CHole::BlockName(CString& blockName)
{
static unsigned long Block_Num = 0;
CString temp;
Block_Num++;
temp.Format(_T("%ld"),Block_Num);
blockName = blockName + temp;
return 1;
}
BOOL CHole::CreateBlock(CEntityList& entLst,CString& blockName,AcDbObjectId& blockId,AcGePoint3d org)
{
if (!BlockName(blockName))
{
return 0;
}
AcDbBlockTable *pBlockTable = NULL;
Acad::ErrorStatus ret = acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pBlockTable, AcDb::kForWrite);
if (ret != Acad::eOk)
{
return 0;
}
AcDbBlockTableRecord *pBlockTableRecord = new AcDbBlockTableRecord;
pBlockTableRecord->setOrigin(org);
pBlockTableRecord->setName(blockName);
pBlockTable->add(blockId,pBlockTableRecord);
pBlockTable->close();
POSITION pos = entLst.GetHeadPosition();
while (pos != NULL)
{
CEntity* pEnt = entLst.GetNext(pos);
pBlockTableRecord->appendAcDbEntity(pEnt->m_pAcDbEnt);
pEnt->m_pAcDbEnt->close();
}
pBlockTableRecord->close();
return 1;
}
AcDbObjectId CHole::GetLayerRecordId(CString layerName)
{
layerName.TrimLeft();
layerName.TrimRight();
if (layerName == _T(""))
{
return NULL;
}
AcDbLayerTable *pLayerTable;
if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTable,AcDb::kForRead) != Acad::eOk)
{
return NULL;
}
AcDbObjectId recordId = NULL;
if (pLayerTable->getAt(layerName, recordId) != Acad::eOk)
{
pLayerTable->close();
return NULL;
}
pLayerTable->close();
return recordId;
}
void CHole::ReleaseC3DFaceList(C3DFaceList& c3dfaceLst)
{
POSITION pos = c3dfaceLst.GetHeadPosition();
while (pos != NULL)
{
C3DFace* pC3DFace = c3dfaceLst.GetNext(pos);
delete pC3DFace;
}
c3dfaceLst.RemoveAll();
}
void CHole::ReleaseCEntityList(CEntityList& centityLst)
{
POSITION pos = centityLst.GetHeadPosition();
while (pos != NULL)
{
CEntity* pEnt = centityLst.GetNext(pos);
delete pEnt;
}
centityLst.RemoveAll();
}
void CHole::SetLayerOfEntities(CEntityList& entLst,CString layerName, int colorNum)
{
SetLayer(layerName, colorNum);
POSITION pos = entLst.GetHeadPosition();
while (pos != NULL)
{
CEntity* pEnt = entLst.GetNext(pos);
pEnt->m_pAcDbEnt->setLayer(layerName);
pEnt->m_pAcDbEnt->setColorIndex(256);
}
}
BOOL CHole::IsLayerExistInDb(CString layerName)
{
layerName.TrimLeft();
layerName.TrimRight();
if (layerName == _T(""))
{
return 0;
}
AcDbLayerTable *pLayerTable;
if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTable,AcDb::kForRead) != Acad::eOk)
{
return 0;
}
BOOL ret = pLayerTable->has(layerName);
pLayerTable->close();
return ret;
}
BOOL CHole::SetLayer(CString layerName, int colorNum)
{
layerName.TrimLeft();
layerName.TrimRight();
if (layerName == _T(""))
{
layerName = _T("0");
}
if (IsLayerExistInDb(layerName))
{
AcDbLayerTable *pLayerTable;
if (acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTable, AcDb::kForRead) != Acad::eOk)
{
return 0;
}
AcDbLayerTableRecord* pLayerTableRecord;
if (pLayerTable->getAt(layerName, pLayerTableRecord,AcDb::kForWrite) == Acad::eOk)
{
pLayerTable->close();
if (pLayerTableRecord->isFrozen())
{
pLayerTableRecord->setIsFrozen(false);
}
if (pLayerTableRecord->isOff())
{
pLayerTableRecord->setIsOff(false);
}
if (colorNum > 0 && colorNum < 256)
{
AcCmColor color;
color.setColorIndex(colorNum);
pLayerTableRecord->setColor(color);
}
pLayerTableRecord->close();
return 1;
}
else
{
pLayerTable->close();
return 0;
}
}
return NewLayer(layerName, colorNum);
}
BOOL CHole::NewLayer(CString& layerName, int colorNum, BOOL bFreeze)
{
layerName.TrimLeft();
layerName.TrimRight();
if (layerName == _T(""))
{
layerName = _T("0");
return 0;
}
AcDbLayerTableRecord *pLayerTableRecord = new AcDbLayerTableRecord;
if (!pLayerTableRecord)
{
return 0;
}
pLayerTableRecord->setName(layerName);
if (colorNum > 0 && colorNum < 256)
{
AcCmColor color;
color.setColorIndex(colorNum);
pLayerTableRecord->setColor(color);
}
if (bFreeze)
{
pLayerTableRecord->setIsFrozen(1);
}
AcDbLayerTable *pLayerTable;
if (acdbHostApplicationServices()->workingDatabase()->getSymbolTable(pLayerTable,AcDb::kForWrite) != Acad::eOk)
{
delete pLayerTableRecord;
return 0;
}
AcDbObjectId recordId;
if (pLayerTable->add(recordId,pLayerTableRecord) != Acad::eOk)
{
pLayerTable->close();
delete pLayerTableRecord;
return 0;
}
pLayerTable->close();
pLayerTableRecord->close();
return 1;
}
void CHole::C3DFaceList2EntityList(C3DFaceList& c3dFaceLst,CEntityList& entLst)
{
POSITION pos = c3dFaceLst.GetTailPosition();
while (pos != NULL)
{
C3DFace* pNode = c3dFaceLst.GetPrev(pos);
CEntity* pCEnt = new CEntity(pNode->m_p3DFace);
entLst.AddTail(pCEnt);
}
}
BOOL CHole::SetLayerFrozen(CString layerName, bool bFreeze)
{
layerName.TrimLeft();
layerName.TrimRight();
if (layerName == _T(""))
{
return 0;
}
AcDbLayerTable *pLayerTable;
if (acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTable, AcDb::kForRead) != Acad::eOk)
{
return 0;
}
AcDbLayerTableRecord* pLayerTableRecord;
if (pLayerTable->getAt(layerName, pLayerTableRecord, AcDb::kForWrite) != Acad::eOk)
{
pLayerTable->close();
return 0;
}
pLayerTable->close();
if (bFreeze)
{
if (!pLayerTableRecord->isFrozen())
{
pLayerTableRecord->setIsFrozen(true);
}
}
else
{
if (pLayerTableRecord->isFrozen())
{
pLayerTableRecord->setIsFrozen(false);
}
}
pLayerTableRecord->close();
return 1;
}
BOOL CHole::SetLayerOff(CString layerName, bool bOff)
{
layerName.TrimLeft();
layerName.TrimRight();
if (layerName == _T(""))
{
return 0;
}
AcDbLayerTable *pLayerTable;
if (acdbHostApplicationServices()->workingDatabase()->getLayerTable(pLayerTable, AcDb::kForRead) != Acad::eOk)
{
return 0;
}
AcDbLayerTableRecord* pLayerTableRecord;
if (pLayerTable->getAt(layerName, pLayerTableRecord, AcDb::kForWrite) != Acad::eOk)
{
pLayerTable->close();
return 0;
}
pLayerTable->close();
if (bOff)
{
if (!pLayerTableRecord->isOff())
{
pLayerTableRecord->setIsOff(true);
}
}
else
{
if (pLayerTableRecord->isOff())
{
pLayerTableRecord->setIsOff(false);
}
}
pLayerTableRecord->close();
return 1;
}