1361 lines
26 KiB
C++
1361 lines
26 KiB
C++
//-----------------------------------------------------------------------------+
|
||
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
||
// = FileName : CHole.cpp
|
||
// = Version : ver2.0
|
||
// = Author : zjq
|
||
// = CreateDate : 2002-09-09
|
||
// = Description: 类的定义
|
||
// = 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;
|
||
}
|
||
|
||
//out放到表首,后面不再判断最外边界,
|
||
//仅判断边界边界是否相交和洞中是否有洞
|
||
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;
|
||
|
||
//out放到表首,后面不再判断最外边界,
|
||
//仅判断边界边界是否相交和洞中是否有洞
|
||
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;
|
||
|
||
//out放到表首,后面不再判断最外边界,
|
||
//仅判断边界边界是否相交和洞中是否有洞
|
||
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::FormatEdgeList()
|
||
{
|
||
//判断各封闭多义线是否相交,并找出外边界,放到表首
|
||
POSITION pos1 = m_RegionLst.GetHeadPosition();
|
||
CPloygon* pSurround = NULL;
|
||
int nSrdTot = 0; //总包含次数
|
||
while (pos1 != NULL)
|
||
{
|
||
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
|
||
POSITION pos2 = m_RegionLst.GetHeadPosition();
|
||
int nSrd = 0; //pPolygon1与其他多边形的包含次数
|
||
while (pos2 != NULL)
|
||
{
|
||
CPloygon* pPolygon2=m_RegionLst.GetNext(pos2);
|
||
if (pPolygon1 != pPolygon2)
|
||
{
|
||
CPloygon* plgTemp = NULL;
|
||
int ret = pPolygon1->IsSurrounded(pPolygon2);
|
||
if (ret == 0)
|
||
{//AfxMessageBox(_T("有边界线相交,无法构造孔板!"));
|
||
return 0;
|
||
}
|
||
else if (ret == 1)
|
||
{//包含pPolygon,
|
||
nSrd++;
|
||
nSrdTot++;
|
||
plgTemp = pPolygon1;
|
||
if (nSrdTot == 1)
|
||
{
|
||
pSurround=plgTemp;
|
||
}
|
||
}
|
||
else if (ret == 2)
|
||
{//被pPolygon包含
|
||
nSrd++;
|
||
nSrdTot++;
|
||
plgTemp = pPolygon2;
|
||
if (nSrdTot == 1)
|
||
{
|
||
pSurround=plgTemp;
|
||
}
|
||
}
|
||
|
||
if (nSrdTot > 1 && plgTemp != NULL && pSurround != plgTemp)
|
||
{//AfxMessageBox(_T("孔中包含有孔,不合理!"));
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
if (nSrd == 0)
|
||
{//AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
|
||
return 0;
|
||
}
|
||
}
|
||
if (nSrdTot == 0)
|
||
{//AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
|
||
return Acad::eNotImplementedYet;
|
||
}
|
||
if (pSurround != NULL)
|
||
{
|
||
POSITION posSrd = m_RegionLst.Find(pSurround);
|
||
m_RegionLst.RemoveAt(posSrd);
|
||
m_RegionLst.AddHead(pSurround);
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
//改变方向,外边界逆时针,内边界顺时针
|
||
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;
|
||
}
|
||
|
||
//处理边链表(已经指定外边界,不再判断)
|
||
BOOL CHole::FormatEdgeListAuto()
|
||
{
|
||
BOOL bRet = FALSE;
|
||
int nRet = -1;
|
||
//判断所有各封闭多义线是否相交,判断洞中是否有洞
|
||
POSITION pos1 = m_RegionLst.GetHeadPosition();
|
||
if(pos1 == NULL)
|
||
{
|
||
return FALSE;
|
||
}
|
||
CPloygon* pSurround = m_RegionLst.GetNext(pos1);
|
||
|
||
while (pos1 != NULL)
|
||
{//是否与最外边界相交
|
||
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
|
||
if(pPolygon1 != pSurround)
|
||
{
|
||
nRet = pSurround->IsSurrounded(pPolygon1);
|
||
// 最外边界不包括此洞
|
||
if (nRet != 1)
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
//洞与洞之间的关系
|
||
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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//改变方向,外边界逆时针,内边界顺时针
|
||
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];
|
||
prompts[0]=_T("\n请选择边界线,(<Enter>结束):");
|
||
prompts[1]=_T("\n请选择要剔除的边界线:");
|
||
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)
|
||
{
|
||
AfxMessageBox(_T("所选图形有非闭合区域!"));
|
||
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;
|
||
}
|
||
//平移
|
||
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)
|
||
{//平移
|
||
CPloygon* pRgn = m_RegionLst.GetNext(pos);
|
||
pRgn->MoveTo(disp);
|
||
}
|
||
|
||
if (m_RegionLst.GetCount() == 1)
|
||
{
|
||
return 1;
|
||
}
|
||
//判断各封闭多义线是否相交,并找出外边界,放到表首
|
||
POSITION pos1 = m_RegionLst.GetHeadPosition();
|
||
CPloygon* pSurround = NULL;
|
||
int nSrdTot = 0; //总包含次数
|
||
while (pos1 != NULL)
|
||
{
|
||
CPloygon* pPolygon1 = m_RegionLst.GetNext(pos1);
|
||
POSITION pos2 = m_RegionLst.GetHeadPosition();
|
||
int nSrd = 0; //pPolygon1与其他多边形的包含次数
|
||
while (pos2 != NULL)
|
||
{
|
||
CPloygon* pPolygon2 = m_RegionLst.GetNext(pos2);
|
||
if (pPolygon1 != pPolygon2)
|
||
{
|
||
CPloygon* plgTemp = NULL;
|
||
int ret = pPolygon1->IsSurrounded(pPolygon2);
|
||
if (ret == 0)
|
||
{
|
||
AfxMessageBox(_T("有边界线相交,无法构造孔板!"));
|
||
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)
|
||
{
|
||
AfxMessageBox(_T("孔中包含有孔,不合理!"));
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
if (nSrd == 0)
|
||
{
|
||
AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
|
||
return 0;
|
||
}
|
||
}
|
||
if (nSrdTot == 0)
|
||
{
|
||
AfxMessageBox(_T("你选择了没有外边界的孔,请重选!"));
|
||
return Acad::eNotImplementedYet;
|
||
}
|
||
if (pSurround != NULL)
|
||
{
|
||
POSITION posSrd = m_RegionLst.Find(pSurround);
|
||
m_RegionLst.RemoveAt(posSrd);
|
||
m_RegionLst.AddHead(pSurround);
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
//改变方向,外边界逆时针,内边界顺时针
|
||
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;
|
||
}
|
||
}
|
||
//直线段化
|
||
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;
|
||
}
|
||
//复制一个新链表
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
//三角化
|
||
CPloygon rgn = CPloygon(*pHead);
|
||
rgn.ConvertToTriangle(lstRes);
|
||
//***** 释放内存
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
//三角化
|
||
CPloygon rgn = CPloygon(*pHead);
|
||
rgn.ConvertTo3DFaces(face3DList);
|
||
//***** 释放内存
|
||
pos = RegionLst.GetHeadPosition();
|
||
while (pos != NULL)
|
||
{
|
||
CPloygon* pPolygon = RegionLst.GetNext(pos);
|
||
delete pPolygon;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
CBNode* CHole::GetADivideNode(CPloygon* pEdge,CPloygon* pEdge1,CBNode* pNode)
|
||
{
|
||
//pEdge:外边界
|
||
//pEdge1:内边界(孔)
|
||
//pNode:内边界上最左边的节点
|
||
if (pEdge == NULL || pNode == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
|
||
pEdge->ReCalcSValue();
|
||
double limitX = pNode->m_pt.x;//内边界最左边节点的X坐标
|
||
CBNode* pTemp = NULL;
|
||
POSITION pos = pEdge->m_BNodeList.GetHeadPosition();
|
||
while (pos != NULL)
|
||
{
|
||
CBNode* pNode0 = pEdge->m_BNodeList.GetNext(pos);
|
||
|
||
//修改: modified on 2003.9.3
|
||
//if (pNode0->m_pt.x<=limitX)
|
||
if (pNode0->m_pt.x < limitX || fabs(pNode0->m_pt.x - limitX) < fTOL)
|
||
{//在外边界上选择X坐标小于或等于内边界上最左边节点的点
|
||
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;
|
||
//如果pNode0的后一个节点在有向线段pPrev->pNode0的右侧
|
||
if (n == 2)
|
||
{//则只要pNode位于pPrev->pNode0的左侧或者pNode0->pNext的左侧,包括边界上,pNode0都是一个合适的节点
|
||
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
|
||
{ //如果pNode0的后一个节点在有向线段pPrev->pNode0的左侧或线上
|
||
//则pNode要同时位于pPrev->pNode0和pNode0->pNext的左侧,
|
||
//包括边界上,pNode0才是一个合适的节点
|
||
|
||
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)
|
||
{//同时,线段pNode0->pNode不与外边界上位于X=limitX左侧的边界相交
|
||
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;
|
||
}
|
||
//外边界
|
||
CPloygon* pHead = m_RegionLst.GetHead();
|
||
if (!(pHead->IsClosed()))
|
||
{
|
||
return 0;
|
||
}
|
||
CBNode* pLeft = pHead->GetMostLeftNode();
|
||
if (pLeft == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
//将最左边的点设为头
|
||
pHead->ResetHead(pLeft);
|
||
|
||
if (pHead->GetClockwise() == 1)
|
||
{//保证逆时针
|
||
pHead->Reverse();
|
||
}
|
||
|
||
//处理内边界
|
||
POSITION pos = m_RegionLst.GetHeadPosition();
|
||
while (pos != NULL)
|
||
{
|
||
CPloygon* pPolygon = m_RegionLst.GetNext(pos);
|
||
if (pPolygon != pHead)
|
||
{
|
||
CBNode* pLeft = pPolygon->GetMostLeftNode();
|
||
if (pLeft != NULL)
|
||
{//将最左边的点设为头
|
||
|
||
pPolygon->ResetHead(pLeft);
|
||
if (pPolygon->GetClockwise() == 2)
|
||
{ //保证顺时针
|
||
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;
|
||
}
|
||
|