824 lines
16 KiB
C++
824 lines
16 KiB
C++
#include "StdAfx.h"
|
|
#include "globalfunc.h"
|
|
#include "GePolygonEx.h"
|
|
#include "GeCurveInline.h"
|
|
|
|
GePolygonEx::GePolygonEx(GePoly &src)
|
|
{
|
|
for (int i = 0; i < src.Length(); i++)
|
|
{
|
|
AppendNode(*src[i], 1);
|
|
}
|
|
}
|
|
|
|
GePolygonEx::GePolygonEx(EntitySet &ent)
|
|
{
|
|
int nFlag0 = 0;
|
|
ent.GetData(70, &nFlag0);
|
|
|
|
if (nFlag0 > 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GePoly2D poly(ent);
|
|
if (!poly)
|
|
{
|
|
return;
|
|
}
|
|
|
|
poly.MapToPolygon(*this);
|
|
|
|
if (!nFlag0)
|
|
{
|
|
ADSGePoint3d &ptStart = *(*this)[0];
|
|
ADSGePoint3d &ptEnd = *Tail();
|
|
if (ptStart == ptEnd)
|
|
{
|
|
int nTail = Length() - 1;
|
|
Remove(nTail);
|
|
|
|
if (!*this)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Reset();
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
m_lstVisibleFlag.Append(new int(1));
|
|
}
|
|
}
|
|
|
|
GePolygonEx::GePolygonEx()
|
|
{
|
|
|
|
}
|
|
|
|
GePolygonEx::GePolygonEx(const GePolygonEx &src)
|
|
{
|
|
*this = src;
|
|
}
|
|
|
|
GePolygonEx::~GePolygonEx()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void GePolygonEx::CopyFrom(const GeEntity* pSrc)
|
|
{
|
|
if (this != pSrc && pSrc->IsKindOf(GeEntity::ePolygonEx))
|
|
{
|
|
Reset();
|
|
m_lstVisibleFlag.Reset();
|
|
assert(((GePolygonEx*)pSrc)->Length() == m_lstVisibleFlag.Length());
|
|
|
|
ADSGePoint3d pt;
|
|
int nindex;
|
|
for (int i = 0; i < ((GePolygonEx*)pSrc)->Length(); i++)
|
|
{
|
|
pt = *(*(GePolygonEx*)pSrc)[i];
|
|
nindex = *((GePolygonEx*)pSrc)->m_lstVisibleFlag[i];
|
|
AppendNode(pt,nindex);
|
|
}
|
|
}
|
|
else if (this != pSrc && pSrc->IsKindOf(GeEntity::ePoly))
|
|
{
|
|
Reset();
|
|
for (int i = 0; i < ((GePoly*)pSrc)->Length(); i++)
|
|
{
|
|
Append(new ADSGePoint3d(*(*(GePoly*)pSrc)[i]));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
GePolygonEx & GePolygonEx::operator = (const GePolygonEx &src)
|
|
{
|
|
if (this != &src)
|
|
{
|
|
CopyFrom(&src);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
SHLoopList<int>& GePolygonEx::GetVisibleFlag()
|
|
{
|
|
return m_lstVisibleFlag;
|
|
}
|
|
|
|
// 求第 nIndex 个点, 支持循环
|
|
ADSGePoint3d * GePolygonEx::operator [](int nIndex)
|
|
{
|
|
int nLen = Length();
|
|
nIndex = GlobalFunc::LimitCycle(nIndex, nLen);
|
|
return GePoly::operator[](nIndex);
|
|
}
|
|
|
|
// 求第 nIndex 个点, 支持循环
|
|
const ADSGePoint3d & GePolygonEx::operator [](int nIndex) const
|
|
{
|
|
int nLen = Length();
|
|
nIndex = GlobalFunc::LimitCycle(nIndex, nLen);
|
|
const GePoly &rThis = *this;
|
|
return rThis[nIndex];
|
|
}
|
|
|
|
void GePolygonEx::RemoveNode(int nIndex)
|
|
{
|
|
int nEdge = Length();
|
|
nIndex = GlobalFunc::LimitCycle(nIndex, nEdge);
|
|
Remove(nIndex);
|
|
m_lstVisibleFlag.Remove(nIndex);
|
|
}
|
|
|
|
// 求法向量,用来作为坐标变换
|
|
int GePolygonEx::GetNormal(TVector3D &vtNormal) const
|
|
{
|
|
int nEdgeNum = Length();
|
|
if (nEdgeNum < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
ADSGePoint3d pt0 = GetVertex(0);
|
|
ADSGePoint3d pt1, pt2;
|
|
int nFlag = 0;
|
|
for (int i = 1; i < nEdgeNum; i++)
|
|
{
|
|
ADSGePoint3d pt = GetVertex(i);
|
|
if (pt0.Distance(pt) < g_Option::instance()._DIST_SNAP)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!nFlag)
|
|
{
|
|
pt1 = pt;
|
|
nFlag++;
|
|
}
|
|
else
|
|
{
|
|
GeLine ln(pt0, pt1);
|
|
if ((pt & ln) == PR_OUTSIDE)
|
|
{
|
|
pt2 = pt;
|
|
nFlag++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nFlag < 2)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
TVector3D vt1 = pt1 - pt0;
|
|
TVector3D vt2 = pt2 - pt0;
|
|
BOOL b1 = (vt1.Length() < 1.0E-6);
|
|
BOOL b2 = (vt2.Length() < 1.0E-6);
|
|
if (b1 || b2)
|
|
{
|
|
#ifndef NDEBUG
|
|
g_Option::instance().adsout << _T("\n不好的GePolygonEx!");
|
|
#endif
|
|
}
|
|
|
|
using namespace GlobalFunc;
|
|
vtNormal = vt1 * vt2;
|
|
((AcGeVector3d &)vtNormal).normalize();
|
|
|
|
// Add on 2002/10/11,上面的vtNormal可能与实际方向相反
|
|
//GePolygonExImp tmp(*this);
|
|
GePolygonEx tmp(*this);
|
|
tmp.Wcs2Ecs(vtNormal);
|
|
|
|
double nPathArea = tmp.PathArea();
|
|
//GePolygonExImp tmp1;
|
|
GePolygonEx tmp1;
|
|
tmp1.AppendNode(pt0);
|
|
tmp1.AppendNode(pt1);
|
|
tmp1.AppendNode(pt2);
|
|
tmp1.Wcs2Ecs(vtNormal);
|
|
|
|
double nPathArea1 = tmp1.PathArea();
|
|
if ((nPathArea > 0 && nPathArea1 < 0) || (nPathArea < 0 && nPathArea1 > 0))
|
|
{
|
|
vtNormal.Reverse();
|
|
}
|
|
|
|
return RTNORM;
|
|
}
|
|
|
|
void GePolygonEx::Ecs2Wcs(TVector3D vtEcs)
|
|
{
|
|
GePoly &poly = *this;
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
*poly[i] = GlobalFunc::Ecs2Wcs(*poly[i], vtEcs);
|
|
}
|
|
}
|
|
|
|
void GePolygonEx::Wcs2Ecs(TVector3D vtEcs)
|
|
{
|
|
GePoly &poly = *this;
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
*poly[i] = GlobalFunc::Wcs2Ecs(*poly[i], vtEcs);
|
|
}
|
|
}
|
|
|
|
int GePolygonEx::Trianglize(PtrList<GeTriangle> &lstTris, BOOL b2D) const
|
|
{
|
|
GePolygonEx polyEx(*this);
|
|
TVector3D vtNormal;
|
|
if (!b2D)
|
|
{
|
|
if (GetNormal(vtNormal) != RTNORM)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
polyEx.Wcs2Ecs(vtNormal);
|
|
}
|
|
|
|
if (polyEx.PathArea() > 1.0E-6)
|
|
{
|
|
polyEx.Reverse();
|
|
}
|
|
|
|
int nRet = polyEx.SubTrianglize(lstTris);
|
|
|
|
if (!b2D)
|
|
{
|
|
int num = lstTris.Length();
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
lstTris[i]->Ecs2Wcs(vtNormal);
|
|
}
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
int GePolygonEx::GetInsidePoint(ADSGePoint3d &ptRet, BOOL b2D) const
|
|
{
|
|
GePolygonEx polyEx(*this);
|
|
TVector3D vtNormal;
|
|
if (!b2D)
|
|
{
|
|
if (GetNormal(vtNormal) != RTNORM)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
polyEx.Wcs2Ecs(vtNormal);
|
|
}
|
|
|
|
if (polyEx.PathArea() > 1.0E-6)
|
|
{
|
|
polyEx.Reverse();
|
|
vtNormal.Reverse(); // 2003/2/27,修改以便正确解决ECS转化
|
|
}
|
|
|
|
int nRet = polyEx.SubGetInsidePoint(ptRet);
|
|
if (nRet == RTNORM && !b2D)
|
|
{
|
|
ptRet = GlobalFunc::Ecs2Wcs(ptRet, vtNormal);
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
// 求第i个顶点的夹角
|
|
double GePolygonEx::GetAngle(int idx) const
|
|
{
|
|
int nEdge = Length();
|
|
ASSERT(nEdge >= 3);
|
|
|
|
int nNext = -1;
|
|
int nPre = -1;
|
|
|
|
nNext = idx + 1;
|
|
nPre = idx - 1;
|
|
if (idx == 0)
|
|
{
|
|
nPre = nEdge - 1;
|
|
}
|
|
if (idx == nEdge - 1)
|
|
{
|
|
nNext = 0;
|
|
}
|
|
|
|
ADSGePoint3d ptCur = (*this)[idx];
|
|
ADSGePoint3d ptPrev = (*this)[nPre];
|
|
ADSGePoint3d ptNext = (*this)[nNext];
|
|
double nPrevAng = GlobalFunc::AngleRangeTo2PI(ads_angle(ptCur, ptPrev) - ads_angle(ptCur, ptNext));
|
|
return nPrevAng;
|
|
}
|
|
|
|
//是否为凸多边形,2D
|
|
BOOL GePolygonEx::IsConvex() const
|
|
{
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
if (nAng < g_DimOption::instance()._angSnap || nAng > PI - g_DimOption::instance()._angSnap)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#if ARX > 19
|
|
static int MakeCallBack(void* pData)
|
|
{
|
|
if( NULL == pData )
|
|
return 0 ;
|
|
|
|
resbuf *rb = (resbuf*)pData;
|
|
if( acedCmdCWasCancelled() )
|
|
{
|
|
acutRelRb(rb);
|
|
return 0 ;
|
|
}
|
|
|
|
resbuf *rbData = rb->rbnext;
|
|
rb->rbnext = NULL;
|
|
if( NULL == rbData )
|
|
acedCommandC(MakeCallBack, rbData , RT3DPOINT , rb->resval.rpoint, RTSTR , _T("C"), RTNONE);
|
|
else
|
|
acedCommandC(MakeCallBack, rbData , RT3DPOINT , rb->resval.rpoint, RTNONE );
|
|
acutRelRb(rb);
|
|
acedCallBackOnCancel();
|
|
|
|
return 1;
|
|
}
|
|
|
|
// 测试用
|
|
int GePolygonEx::Make(const TCHAR *szLay)
|
|
{
|
|
GlobalFunc::PushAcadVar<CString,true> clayer(_T("CLAYER"), szLay);
|
|
GlobalFunc::PushAcadVar<int> vOsMode(_T("OSMODE"), 0);
|
|
resbuf *resTep, *resData;
|
|
int iLen = Length();
|
|
if( iLen > 0 )
|
|
{
|
|
resTep = resData = acutNewRb(RT3DPOINT);
|
|
ads_point_set(*(*this)[0], resTep->resval.rpoint);
|
|
for( int i=1; i<iLen; ++i )
|
|
{
|
|
resTep = resTep->rbnext = acutNewRb(RT3DPOINT);
|
|
ads_point_set(*(*this)[i], resTep->resval.rpoint);
|
|
}
|
|
}
|
|
return acedCommandC(MakeCallBack, resData, RTSTR, _T(".PLINE"), RTNONE);
|
|
}
|
|
|
|
#else
|
|
|
|
int GePolygonEx::Make(const TCHAR *szLay)
|
|
{
|
|
GlobalFunc::PushAcadVar<CString,true> clayer(_T("CLAYER"), szLay);
|
|
GlobalFunc::PushAcadVar<int> vOsMode(_T("OSMODE"), 0);
|
|
ads_command(RTSTR, _T(".PLINE"), RTNONE);
|
|
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
ads_command(RT3DPOINT, (*this)[i], RTNONE);
|
|
}
|
|
|
|
return ads_command(RTSTR, _T("C"), RTNONE);
|
|
}
|
|
|
|
#endif
|
|
|
|
void GePolygonEx::Reverse()
|
|
{
|
|
GePoly::Reverse();
|
|
m_lstVisibleFlag.Reverse();
|
|
}
|
|
|
|
double GePolygonEx::GetEdgeLength(int idx) const
|
|
{
|
|
const ADSGePoint3d &pt = (*this)[idx];
|
|
//最后一点与第一个点求距离
|
|
if (idx == Length() - 1)
|
|
{
|
|
idx = -1;
|
|
}
|
|
const ADSGePoint3d &ptNext = (*this)[idx + 1];
|
|
|
|
return pt.Distance(ptNext);
|
|
}
|
|
|
|
BOOL GePolygonEx::IsVisible(int idx) const
|
|
{
|
|
return (m_lstVisibleFlag[idx]);
|
|
}
|
|
|
|
void GePolygonEx::SetVisible(int idx, BOOL bVis)
|
|
{
|
|
*(m_lstVisibleFlag[idx]) = bVis;
|
|
}
|
|
|
|
ADSGePoint3d GePolygonEx::GetVertex(int idx) const
|
|
{
|
|
return (*this)[idx];
|
|
}
|
|
|
|
void GePolygonEx::AppendNode(const ADSGePoint3d &pt, int nIndex/* = 1*/)
|
|
{
|
|
Append(new ADSGePoint3d(pt));
|
|
m_lstVisibleFlag.Append(new int(nIndex));
|
|
}
|
|
|
|
void GePolygonEx::Reset()
|
|
{
|
|
GePoly::Reset();
|
|
m_lstVisibleFlag.Reset();
|
|
}
|
|
|
|
int GePolygonEx::SubTrianglize(PtrList<GeTriangle> &lstTris)
|
|
{
|
|
LAB_START:
|
|
int nEdge = Length();
|
|
if (nEdge < 3)
|
|
{
|
|
return RTNORM;
|
|
}
|
|
|
|
// 消除长度为0的边
|
|
for (int i = 0; i < nEdge; i++)
|
|
{
|
|
if (GetEdgeLength(i) < g_Option::instance()._DIST_SNAP)
|
|
{
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// 消除0和PI的顶点,可能没有必要
|
|
for (i = 9; i < nEdge; i++)
|
|
{
|
|
if (nEdge < 3)
|
|
{
|
|
return RTNORM;
|
|
}
|
|
|
|
double nAng = GetAngle(i);
|
|
if (fabs(nAng) < g_DimOption::instance()._angSnap) //夹角为0
|
|
{
|
|
BOOL bVis = IsVisible(i - 1);
|
|
if (GetEdgeLength(i - 1) < GetEdgeLength(i))
|
|
{
|
|
bVis = IsVisible(i);
|
|
}
|
|
|
|
SetVisible(i - 1, bVis);
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
if (fabs(nAng) < g_DimOption::instance()._angSnap) //消除0度的夹角,可能导致边长为0
|
|
{
|
|
goto LAB_START;
|
|
}
|
|
}
|
|
else if (fabs(nAng - PI) < g_DimOption::instance()._angSnap) //夹角为PI
|
|
{
|
|
BOOL bVis1 = IsVisible(i - 1);
|
|
BOOL bVis2 = IsVisible(i);
|
|
|
|
if (bVis1 == bVis2) //可见性相同,可以消除
|
|
{
|
|
SetVisible(i - 1, bVis1);
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nEdge < 3)
|
|
{
|
|
return RTNORM;
|
|
}
|
|
|
|
if (nEdge == 3)
|
|
{
|
|
i = 0;
|
|
int nVisFlag = SIDE1_INVISIBLE * (!IsVisible(i - 1))
|
|
+ SIDE2_INVISIBLE * (!IsVisible(i))
|
|
+ SIDE3_INVISIBLE * (!IsVisible(i + 1));
|
|
|
|
lstTris.Append(new GeTriangle(GetVertex(i - 1), GetVertex(i), GetVertex(i + 1), nVisFlag));
|
|
Reset();
|
|
return RTNORM;
|
|
}
|
|
|
|
// 消除小于180的凸角
|
|
for (i = 0; i < nEdge; i++)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
if (nAng < PI - g_DimOption::instance()._angSnap)
|
|
{
|
|
int nVisFlag = SIDE1_INVISIBLE * (!IsVisible(i - 1))
|
|
+ SIDE2_INVISIBLE * (!IsVisible(i))
|
|
+ SIDE3_INVISIBLE;
|
|
|
|
GeTriangle tri(GetVertex(i - 1), GetVertex(i), GetVertex(i + 1), nVisFlag);
|
|
|
|
BOOL bAllow = TRUE;
|
|
// 其他顶点都在tri外部或第3边,则可以消除
|
|
for (int n = i + 2; n < i - 1 + nEdge; n++)
|
|
{
|
|
ADSGePoint3d ptTest = GetVertex(n);
|
|
int nHitFlag = tri.HitTest2d(ptTest);
|
|
int nFlag = 1; //第一个端点到末尾端点的路径(除首末点外)都需要重新测定
|
|
switch(nHitFlag)
|
|
{
|
|
case 0: //外部
|
|
break;
|
|
case 1: //第一点
|
|
break;
|
|
case 2: //第2点
|
|
nFlag = 2;
|
|
break;
|
|
case 3: //第3点
|
|
break;
|
|
case -1: //第1边
|
|
nFlag = 2;
|
|
break;
|
|
case -2: //第2边
|
|
nFlag = 2;
|
|
break;
|
|
case -3: //第3边
|
|
break;
|
|
case 4:
|
|
nFlag = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!nFlag)
|
|
{
|
|
bAllow = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (nFlag == 2) //测定ptTest的2边是否和tri的第三边有交点,且交点在线内
|
|
{
|
|
GeLine lnSect(tri.vertex3, tri.vertex1, LS_FINITE);
|
|
GeLine lnOut(ptTest, GetVertex(n + 1), LS_FINITE);
|
|
GeLine lnIn(GetVertex(n - 1), ptTest, LS_FINITE);
|
|
ADSGePoint3d ptInt1, ptInt2;
|
|
BOOL bInt1 = (lnSect.Intersection(&lnOut, ptInt1) > 0); //比ads_inters更加可靠
|
|
|
|
if (bInt1)
|
|
{
|
|
if (lnSect.GetStartPoint().Distance2d(ptInt1) > g_Option::instance()._DIST_SNAP
|
|
&& lnSect.GetEndPoint().Distance2d(ptInt1) > g_Option::instance()._DIST_SNAP)
|
|
{
|
|
bAllow = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL bInt2 = (lnSect.Intersection(&lnIn, ptInt2) > 0); //比ads_inters更加可靠
|
|
if (bInt2)
|
|
{
|
|
if (lnSect.GetStartPoint().Distance2d(ptInt2) > g_Option::instance()._DIST_SNAP
|
|
&& lnSect.GetEndPoint().Distance2d(ptInt2) > g_Option::instance()._DIST_SNAP)
|
|
{
|
|
bAllow = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bAllow)
|
|
{
|
|
lstTris.Append(new GeTriangle(tri));
|
|
SetVisible(i - 1, FALSE); //必须在顶点移除前更改可见性,否则如果首点被移除导致序号的变化
|
|
RemoveNode(i);
|
|
|
|
goto LAB_START;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
g_Option::instance().adsout << _T("\n警告:多边形三角化可能不合适, 还有") << Length() << _T("个边未三角化!");
|
|
Make(_T("1"));
|
|
#endif
|
|
|
|
return RTERROR;
|
|
}
|
|
|
|
int GePolygonEx::SubGetInsidePoint(ADSGePoint3d &ptRet)
|
|
{
|
|
LAB_START:
|
|
int nEdge = Length();
|
|
if (nEdge < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
// 消除长度为0的边
|
|
for (int i = 0; i < nEdge; i++)
|
|
{
|
|
if (GetEdgeLength(i) < g_Option::instance()._DIST_SNAP)
|
|
{
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// 消除0和PI的顶点
|
|
for (i = 0; i < nEdge; i++)
|
|
{
|
|
if (nEdge < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
double nAng = GetAngle(i);
|
|
if (fabs(nAng) < g_DimOption::instance()._angSnap) //夹角为0
|
|
{
|
|
BOOL bVis = IsVisible(i - 1);
|
|
if (GetEdgeLength(i - 1) < GetEdgeLength(i))
|
|
{
|
|
bVis = IsVisible(i);
|
|
}
|
|
|
|
SetVisible(i - 1, bVis);
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
|
|
if (fabs(nAng) < g_DimOption::instance()._angSnap) //消除0度的夹角,可能导致边长为0
|
|
{
|
|
goto LAB_START;
|
|
}
|
|
}
|
|
else if (fabs(nAng - PI) < g_DimOption::instance()._angSnap) //夹角为PI
|
|
{
|
|
BOOL bVis1 = IsVisible(i - 1);
|
|
BOOL bVis2 = IsVisible(i);
|
|
|
|
if (bVis1 == bVis2) //可见性相同,可以消除
|
|
{
|
|
SetVisible(i - 1, bVis1);
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nEdge < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
BOOL bAoJiao = FALSE;
|
|
double nPi = PI - 1.0E-6;
|
|
|
|
// 还没有优化,应当同时向前、向后消除
|
|
// 消除凹角, 向前
|
|
for (i = 0; i < nEdge; i++)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
double nAngNext = GetAngle(i+1);
|
|
if (!bAoJiao)
|
|
{
|
|
bAoJiao = (nAng > nPi);
|
|
}
|
|
|
|
if (nAng > nPi && nAngNext < nPi)
|
|
{
|
|
BOOL bCanCut = TRUE;
|
|
GeLine ln(GetVertex(i), GetVertex(i + 2), LS_FINITE);
|
|
|
|
//判断i+3到i-2是否的边是否有交点
|
|
for (int n = i + 3; n <= i - 2 + nEdge; n++)
|
|
{
|
|
ADSGePoint3d ptInt;
|
|
GeLine ln1(GetVertex(n), GetVertex(n + 1), LS_FINITE);
|
|
if (ln.Intersection(&ln1, ptInt))
|
|
{
|
|
int nFlag1 = (ptInt & ln);
|
|
int nFlag2 = (ptInt & ln1);
|
|
if (nFlag1 == PR_INSIDE && nFlag2 == PR_INSIDE)
|
|
{
|
|
bCanCut = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bCanCut)
|
|
{
|
|
ADSGePoint3d pt1 = GetVertex(i);
|
|
ADSGePoint3d pt2 = GetVertex(i + 1);
|
|
ADSGePoint3d pt3 = GetVertex(i + 2);
|
|
|
|
ptRet.x = (pt1.x + pt2.x + pt3.x) / 3.0;
|
|
ptRet.y = (pt1.y + pt2.y + pt3.y) / 3.0;
|
|
ptRet.z = (pt1.z + pt2.z + pt3.z) / 3.0;
|
|
|
|
return RTNORM;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bAoJiao)
|
|
{
|
|
// 消除凹角, 向后
|
|
for (i = nEdge - 1; i >= 0; i--)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
double nAngPrev = GetAngle(i - 1);
|
|
|
|
if (nAng > nPi && nAngPrev < nPi)
|
|
{
|
|
BOOL bCanCut = TRUE;
|
|
GeLine ln(GetVertex(i), GetVertex(i - 2), LS_FINITE); //消i-1
|
|
|
|
//判断i+1到i-4边是否有交点
|
|
for (int n = i + 1; n <= i - 4 + nEdge; n++)
|
|
{
|
|
ADSGePoint3d ptInt;
|
|
GeLine ln1(GetVertex(n), GetVertex(n + 1), LS_FINITE);
|
|
if (ln.Intersection(&ln1, ptInt))
|
|
{
|
|
int nFlag1 = (ptInt & ln);
|
|
int nFlag2 = (ptInt & ln1);
|
|
if (nFlag1 == PR_INSIDE && nFlag2 == PR_INSIDE)
|
|
{
|
|
bCanCut = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bCanCut)
|
|
{
|
|
ADSGePoint3d pt1 = GetVertex(i - 2);
|
|
ADSGePoint3d pt2 = GetVertex(i - 1);
|
|
ADSGePoint3d pt3 = GetVertex(i);
|
|
|
|
ptRet.x = (pt1.x + pt2.x + pt3.x) / 3.0;
|
|
ptRet.y = (pt1.y + pt2.y + pt3.y) / 3.0;
|
|
ptRet.z = (pt1.z + pt2.z + pt3.z) / 3.0;
|
|
|
|
return RTNORM;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ADSGePoint3d pt1 = GetVertex(0);
|
|
ADSGePoint3d pt2 = GetVertex(1);
|
|
ADSGePoint3d pt3 = GetVertex(2);
|
|
|
|
ptRet.x = (pt1.x + pt2.x + pt3.x) / 3.0;
|
|
ptRet.y = (pt1.y + pt2.y + pt3.y) / 3.0;
|
|
ptRet.z = (pt1.z + pt2.z + pt3.z) / 3.0;
|
|
|
|
return RTNORM;
|
|
}
|
|
|
|
bool GePolygonEx::IsKindOf(GeEntity::TEntityId entType) const
|
|
{
|
|
switch(entType)
|
|
{
|
|
case GeEntity::eEntity:
|
|
case GeEntity::eCurve:
|
|
case GeEntity::ePoly:
|
|
case GeEntity::eShape:
|
|
case GeEntity::ePolygonEx:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
GeEntity::TEntityId GePolygonEx::Type() const
|
|
{
|
|
return GeEntity::ePolygonEx;
|
|
}
|