787 lines
15 KiB
C++
787 lines
15 KiB
C++
//-----------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : XPolygonEx 类
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: XPolygonEx 类定义
|
|
// = Maintainers:
|
|
//
|
|
//-----------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "XPolygonEx.h"
|
|
#include "XPushVar.h"
|
|
#include "XGlobalFunc.h"
|
|
#include "XPrivateGlobalFunc.h"
|
|
#include "XGlobalCurveFunc.h"
|
|
#include "XCurveInline.h"
|
|
|
|
XPolygonEx::XPolygonEx(XPoly &src)
|
|
{
|
|
for (int i = 0; i < src.Length(); i++)
|
|
{
|
|
AppendNode(*src[i], 1);
|
|
}
|
|
}
|
|
|
|
XPolygonEx::XPolygonEx(Entity &ent)
|
|
{
|
|
int nFlag0 = 0;
|
|
ent.GetData(70, &nFlag0);
|
|
|
|
if (nFlag0 > 1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
XPoly2D poly(ent);
|
|
if (!poly)
|
|
{
|
|
return;
|
|
}
|
|
|
|
poly.MapToPolygon(*this);
|
|
|
|
if (!nFlag0)
|
|
{
|
|
XPoint &ptStart = *(*this)[0];
|
|
XPoint &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));
|
|
}
|
|
}
|
|
|
|
XPolygonEx::XPolygonEx()
|
|
{
|
|
|
|
}
|
|
|
|
XPolygonEx::XPolygonEx(const XPolygonEx &src)
|
|
{
|
|
*this = src;
|
|
}
|
|
|
|
XPolygonEx::~XPolygonEx()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
void XPolygonEx::CopyFrom(const XEntity* pSrc)
|
|
{
|
|
if (this != pSrc && pSrc->IsKindOf(XEntity::ePolygonEx))
|
|
{
|
|
Reset();
|
|
m_lstVisibleFlag.Reset();
|
|
assert(pSrc->GetLength() == m_lstVisibleFlag.Length());
|
|
XPoint pt;
|
|
int nindex;
|
|
for (int i = 0; i < ((XPolygonEx*)pSrc)->Length(); i++)
|
|
{
|
|
pt = *(*(XPolygonEx*)pSrc)[i];
|
|
nindex = *((XPolygonEx*)pSrc)->m_lstVisibleFlag[i];
|
|
AppendNode(pt,nindex);
|
|
}
|
|
}
|
|
else if (this != pSrc && pSrc->IsKindOf(XEntity::ePoly))
|
|
{
|
|
Reset();
|
|
for (int i = 0; i < ((XPoly*)pSrc)->Length(); i++)
|
|
{
|
|
Append(new XPoint(*(*(XPoly*)pSrc)[i]));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
XPolygonEx & XPolygonEx::operator = (const XPolygonEx &src)
|
|
{
|
|
if (this != &src)
|
|
{
|
|
CopyFrom(&src);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
LoopList<int>& XPolygonEx::GetVisibleFlag()
|
|
{
|
|
return m_lstVisibleFlag;
|
|
}
|
|
|
|
// 求第 nIndex 个点, 支持循环
|
|
XPoint * XPolygonEx::operator [](int nIndex)
|
|
{
|
|
int nLen = Length();
|
|
nIndex = LimitCycle(nIndex, nLen);
|
|
return XPoly::operator[](nIndex);
|
|
}
|
|
|
|
// 求第 nIndex 个点, 支持循环
|
|
const XPoint & XPolygonEx::operator [](int nIndex) const
|
|
{
|
|
int nLen = Length();
|
|
nIndex = LimitCycle(nIndex, nLen);
|
|
const XPoly &rThis = *this;
|
|
return rThis[nIndex];
|
|
}
|
|
|
|
void XPolygonEx::RemoveNode(int nIndex)
|
|
{
|
|
int nEdge = Length();
|
|
nIndex = LimitCycle(nIndex, nEdge);
|
|
Remove(nIndex);
|
|
m_lstVisibleFlag.Remove(nIndex);
|
|
}
|
|
|
|
// 求法向量,用来作为坐标变换
|
|
int XPolygonEx::GetNormal(XVector3D &vtNormal) const
|
|
{
|
|
int nEdgeNum = Length();
|
|
if (nEdgeNum < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
XPoint pt0 = GetVertex(0);
|
|
XPoint pt1, pt2;
|
|
int nFlag = 0;
|
|
for (int i = 1; i < nEdgeNum; i++)
|
|
{
|
|
XPoint pt = GetVertex(i);
|
|
if (pt0.Distance(pt) < _DIST_SNAP)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!nFlag)
|
|
{
|
|
pt1 = pt;
|
|
nFlag++;
|
|
}
|
|
else
|
|
{
|
|
XLine ln(pt0, pt1);
|
|
if ((pt & ln) == PR_OUTSIDE)
|
|
{
|
|
pt2 = pt;
|
|
nFlag++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nFlag < 2)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
XVector3D vt1 = pt1 - pt0;
|
|
XVector3D vt2 = pt2 - pt0;
|
|
BOOL b1 = (vt1.Length() < 1.0E-6);
|
|
BOOL b2 = (vt2.Length() < 1.0E-6);
|
|
if (b1 || b2)
|
|
{
|
|
#ifndef NDEBUG
|
|
XGeLib::adsout << _T("\n不好的XPolygonEx!");
|
|
#endif
|
|
}
|
|
|
|
vtNormal = vt1 * vt2;
|
|
((AcGeVector3d &)vtNormal).normalize();
|
|
|
|
// Add on 2002/10/11,上面的vtNormal可能与实际方向相反
|
|
//XPolygonExImp tmp(*this);
|
|
XPolygonEx tmp(*this);
|
|
tmp.Wcs2Ecs(vtNormal);
|
|
|
|
double nPathArea = tmp.PathArea();
|
|
//XPolygonExImp tmp1;
|
|
XPolygonEx 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 XPolygonEx::Ecs2Wcs(XVector3D vtEcs)
|
|
{
|
|
XPoly &poly = *this;
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
*poly[i] = XPrivate::Ecs2Wcs(*poly[i], vtEcs);
|
|
}
|
|
}
|
|
|
|
void XPolygonEx::Wcs2Ecs(XVector3D vtEcs)
|
|
{
|
|
XPoly &poly = *this;
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
*poly[i] = XPrivate::Wcs2Ecs(*poly[i], vtEcs);
|
|
}
|
|
}
|
|
|
|
int XPolygonEx::Trianglize(DList<XTriangle> &lstTris, BOOL b2D) const
|
|
{
|
|
XPolygonEx polyEx(*this);
|
|
XVector3D 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 XPolygonEx::GetInsidePoint(XPoint &ptRet, BOOL b2D) const
|
|
{
|
|
XPolygonEx polyEx(*this);
|
|
XVector3D 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 = XPrivate::Ecs2Wcs(ptRet, vtNormal);
|
|
}
|
|
|
|
return nRet;
|
|
}
|
|
|
|
// 求第i个顶点的夹角
|
|
double XPolygonEx::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;
|
|
}
|
|
|
|
XPoint ptCur = (*this)[idx];
|
|
XPoint ptPrev = (*this)[nPre];
|
|
XPoint ptNext = (*this)[nNext];
|
|
double nPrevAng = CT_std_angle(ads_angle(ptCur, ptPrev) - ads_angle(ptCur, ptNext));
|
|
return nPrevAng;
|
|
}
|
|
|
|
//是否为凸多边形,2D
|
|
BOOL XPolygonEx::IsConvex() const
|
|
{
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
if (nAng < _angSnap || nAng > PI - _angSnap)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// 测试用
|
|
int XPolygonEx::Make(const TCHAR *szLay)
|
|
{
|
|
XPushVarStr clayer(_T("CLAYER"), szLay);
|
|
XPushVar<int> vOsMode(_T("OSMODE"), 0);
|
|
SHads_command(RTSTR, _T(".PLINE"), RTNONE);
|
|
|
|
for (int i = 0; i < Length(); i++)
|
|
{
|
|
SHads_command(RT3DPOINT, (*this)[i], RTNONE);
|
|
}
|
|
|
|
return SHads_command(RTSTR, _T("C"), RTNONE);
|
|
}
|
|
|
|
void XPolygonEx::Reverse()
|
|
{
|
|
XPoly::Reverse();
|
|
m_lstVisibleFlag.Reverse();
|
|
}
|
|
|
|
double XPolygonEx::GetEdgeLength(int idx) const
|
|
{
|
|
const XPoint &pt = (*this)[idx];
|
|
//最后一点与第一个点求距离
|
|
if (idx == Length() - 1)
|
|
{
|
|
idx = -1;
|
|
}
|
|
const XPoint &ptNext = (*this)[idx + 1];
|
|
|
|
return pt.Distance(ptNext);
|
|
}
|
|
|
|
BOOL XPolygonEx::IsVisible(int idx) const
|
|
{
|
|
return (m_lstVisibleFlag[idx]);
|
|
}
|
|
|
|
void XPolygonEx::SetVisible(int idx, BOOL bVis)
|
|
{
|
|
*(m_lstVisibleFlag[idx]) = bVis;
|
|
}
|
|
|
|
XPoint XPolygonEx::GetVertex(int idx) const
|
|
{
|
|
return (*this)[idx];
|
|
}
|
|
|
|
void XPolygonEx::AppendNode(const XPoint &pt, int nIndex/* = 1*/)
|
|
{
|
|
Append(new XPoint(pt));
|
|
m_lstVisibleFlag.Append(new int(nIndex));
|
|
}
|
|
|
|
void XPolygonEx::Reset()
|
|
{
|
|
XPoly::Reset();
|
|
m_lstVisibleFlag.Reset();
|
|
}
|
|
|
|
int XPolygonEx::SubTrianglize(DList<XTriangle> &lstTris)
|
|
{
|
|
LAB_START:
|
|
int nEdge = Length();
|
|
if (nEdge < 3)
|
|
{
|
|
return RTNORM;
|
|
}
|
|
|
|
// 消除长度为0的边
|
|
for (int i = 0; i < nEdge; i++)
|
|
{
|
|
if (GetEdgeLength(i) < _DIST_SNAP)
|
|
{
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// 消除0和PI的顶点,可能没有必要
|
|
for (int i = 9; i < nEdge; i++)
|
|
{
|
|
if (nEdge < 3)
|
|
{
|
|
return RTNORM;
|
|
}
|
|
|
|
double nAng = GetAngle(i);
|
|
if (fabs(nAng) < _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) < _angSnap) //消除0度的夹角,可能导致边长为0
|
|
{
|
|
goto LAB_START;
|
|
}
|
|
}
|
|
else if (fabs(nAng - PI) < _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)
|
|
{
|
|
int i = 0;
|
|
int nVisFlag = SIDE1_INVISIBLE * (!IsVisible(i - 1))
|
|
+ SIDE2_INVISIBLE * (!IsVisible(i))
|
|
+ SIDE3_INVISIBLE * (!IsVisible(i + 1));
|
|
|
|
lstTris.Append(new XTriangle(GetVertex(i - 1), GetVertex(i), GetVertex(i + 1), nVisFlag));
|
|
Reset();
|
|
return RTNORM;
|
|
}
|
|
|
|
// 消除小于180的凸角
|
|
for (int i = 0; i < nEdge; i++)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
if (nAng < PI - _angSnap)
|
|
{
|
|
int nVisFlag = SIDE1_INVISIBLE * (!IsVisible(i - 1))
|
|
+ SIDE2_INVISIBLE * (!IsVisible(i))
|
|
+ SIDE3_INVISIBLE;
|
|
|
|
XTriangle 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++)
|
|
{
|
|
XPoint 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的第三边有交点,且交点在线内
|
|
{
|
|
XLine lnSect(tri.vertex3, tri.vertex1, LS_FINITE);
|
|
XLine lnOut(ptTest, GetVertex(n + 1), LS_FINITE);
|
|
XLine lnIn(GetVertex(n - 1), ptTest, LS_FINITE);
|
|
XPoint ptInt1, ptInt2;
|
|
BOOL bInt1 = (lnSect.Intersection(&lnOut, ptInt1) > 0); //比ads_inters更加可靠
|
|
|
|
if (bInt1)
|
|
{
|
|
if (lnSect.GetStartPoint().Distance2d(ptInt1) > _DIST_SNAP
|
|
&& lnSect.GetEndPoint().Distance2d(ptInt1) > _DIST_SNAP)
|
|
{
|
|
bAllow = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL bInt2 = (lnSect.Intersection(&lnIn, ptInt2) > 0); //比ads_inters更加可靠
|
|
if (bInt2)
|
|
{
|
|
if (lnSect.GetStartPoint().Distance2d(ptInt2) > _DIST_SNAP
|
|
&& lnSect.GetEndPoint().Distance2d(ptInt2) > _DIST_SNAP)
|
|
{
|
|
bAllow = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bAllow)
|
|
{
|
|
lstTris.Append(new XTriangle(tri));
|
|
SetVisible(i - 1, FALSE); //必须在顶点移除前更改可见性,否则如果首点被移除导致序号的变化
|
|
RemoveNode(i);
|
|
|
|
goto LAB_START;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
XGeLib::adsout << _T("\n警告:多边形三角化可能不合适, 还有") << Length() << _T("个边未三角化!");
|
|
Make(_T("1"));
|
|
#endif
|
|
|
|
return RTERROR;
|
|
}
|
|
|
|
int XPolygonEx::SubGetInsidePoint(XPoint &ptRet)
|
|
{
|
|
LAB_START:
|
|
int nEdge = Length();
|
|
if (nEdge < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
// 消除长度为0的边
|
|
for (int i = 0; i < nEdge; i++)
|
|
{
|
|
if (GetEdgeLength(i) < _DIST_SNAP)
|
|
{
|
|
RemoveNode(i);
|
|
nEdge--;
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// 消除0和PI的顶点
|
|
for (int i = 0; i < nEdge; i++)
|
|
{
|
|
if (nEdge < 3)
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
double nAng = GetAngle(i);
|
|
if (fabs(nAng) < _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) < _angSnap) //消除0度的夹角,可能导致边长为0
|
|
{
|
|
goto LAB_START;
|
|
}
|
|
}
|
|
else if (fabs(nAng - PI) < _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 (int 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;
|
|
XLine ln(GetVertex(i), GetVertex(i + 2), LS_FINITE);
|
|
|
|
//判断i+3到i-2是否的边是否有交点
|
|
for (int n = i + 3; n <= i - 2 + nEdge; n++)
|
|
{
|
|
XPoint ptInt;
|
|
XLine 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)
|
|
{
|
|
XPoint pt1 = GetVertex(i);
|
|
XPoint pt2 = GetVertex(i + 1);
|
|
XPoint 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 (int i = nEdge - 1; i >= 0; i--)
|
|
{
|
|
double nAng = GetAngle(i);
|
|
double nAngPrev = GetAngle(i - 1);
|
|
|
|
if (nAng > nPi && nAngPrev < nPi)
|
|
{
|
|
BOOL bCanCut = TRUE;
|
|
XLine ln(GetVertex(i), GetVertex(i - 2), LS_FINITE); //消i-1
|
|
|
|
//判断i+1到i-4边是否有交点
|
|
for (int n = i + 1; n <= i - 4 + nEdge; n++)
|
|
{
|
|
XPoint ptInt;
|
|
XLine 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)
|
|
{
|
|
XPoint pt1 = GetVertex(i - 2);
|
|
XPoint pt2 = GetVertex(i - 1);
|
|
XPoint 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
XPoint pt1 = GetVertex(0);
|
|
XPoint pt2 = GetVertex(1);
|
|
XPoint 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 XPolygonEx::IsKindOf(XEntity::TEntityId entType) const
|
|
{
|
|
switch(entType)
|
|
{
|
|
case XEntity::eEntity:
|
|
case XEntity::eCurve:
|
|
case XEntity::ePoly:
|
|
case XEntity::eShape:
|
|
case XEntity::ePolygonEx:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
XEntity::TEntityId XPolygonEx::Type() const
|
|
{
|
|
return XEntity::ePolygonEx;
|
|
}
|