301 lines
5.6 KiB
C++
301 lines
5.6 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TGNPolygon2D 类
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TGNPolygon2D 定义
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TGNPolygon2D.h"
|
|
#include "TGTriangle2D.h"
|
|
#include "TPtList.h"
|
|
|
|
TGNPolygon2D::TGNPolygon2D(long vertexNum)
|
|
: TGPolygon2D(vertexNum)
|
|
{
|
|
|
|
}
|
|
|
|
TGNPolygon2D::TGNPolygon2D(const TGMLine2D&ml,bool bCheck)
|
|
: TGPolygon2D(ml,bCheck)
|
|
{
|
|
|
|
}
|
|
|
|
TGNPolygon2D::TGNPolygon2D(const TGPolygon2D&poly)
|
|
: TGPolygon2D(poly)
|
|
{
|
|
|
|
}
|
|
|
|
TGNPolygon2D::~TGNPolygon2D()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
TGObject* TGNPolygon2D::Clone() const
|
|
{
|
|
return new TGNPolygon2D(*this);
|
|
}
|
|
|
|
bool TGNPolygon2D::IsValid() const
|
|
{
|
|
return TGPolygon2D::IsValid() && !IsConcave();
|
|
}
|
|
|
|
bool TGNPolygon2D::Explode(TGObjectList&res) const
|
|
{
|
|
if(mLine.GetVertexNum() < 9)
|
|
{
|
|
if(mLine.GetVertexNum() == 3)
|
|
{
|
|
res << new TGTriangle2D(mLine.GetVertex(0),mLine.GetVertex(1),mLine.GetVertex(2),false);
|
|
}
|
|
else
|
|
{
|
|
const TGPoint&pt = mLine.GetVertex(0);
|
|
long num = mLine.GetVertexNum()-1;
|
|
for(long i = 1;i < num;i++)
|
|
{
|
|
TGTriangle2D *pT = new TGTriangle2D(pt,mLine.GetVertex(i),mLine.GetVertex(i+1),false);
|
|
if(pT->Outline().IsLinear())
|
|
{
|
|
delete pT;
|
|
}
|
|
else
|
|
{
|
|
res << pT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const TGPoint&pt = Center();
|
|
long num = mLine.GetVertexNum()-1;
|
|
for(long i = 0;i<num;i++)
|
|
{
|
|
res << new TGTriangle2D(pt,mLine.GetVertex(i),mLine.GetVertex(i+1),false);
|
|
}
|
|
res << new TGTriangle2D(pt,mLine.GetVertex(i),mLine.GetVertex(0),false);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
GRelation TGNPolygon2D::HitTest(const TGPoint&pt) const
|
|
{
|
|
long last = mLine.GetVertexNum()-1;
|
|
bool bUnclock;
|
|
TGVector2D vt0(pt,mLine.GetVertex(last));
|
|
TGVector2D vt1(pt,mLine.GetVertex(0));
|
|
|
|
TPGeGLineSeg2D seg;
|
|
mLine.GetSegment(last,seg);
|
|
if(seg.HitTest(pt).Is(GR_IN))
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
|
|
double s = vt0 * vt1;
|
|
if(UP_ZERO(s))
|
|
{
|
|
bUnclock = true;
|
|
}
|
|
else if(DOWN_ZERO(s))
|
|
{
|
|
bUnclock = false;
|
|
}
|
|
else
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
if(bUnclock)
|
|
{
|
|
for(long i = 0;i<last;i++)
|
|
{
|
|
mLine.GetSegment(i,seg);
|
|
if(seg.HitTest(pt).Is(GR_IN))
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
|
|
vt0 = vt1;
|
|
vt1 = mLine.GetVertex(i+1);
|
|
vt1 -= mLine.GetVertex(i);
|
|
s = vt0*vt1;
|
|
if(UP_ZERO(s))
|
|
{
|
|
continue;
|
|
}
|
|
else if(DOWN_ZERO(s))
|
|
{
|
|
return GR_OUT;
|
|
}
|
|
else
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(long i = 0;i<last;i++)
|
|
{
|
|
mLine.GetSegment(i,seg);
|
|
if(seg.HitTest(pt).Is(GR_IN))
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
|
|
vt0 = vt1;
|
|
vt1 = mLine.GetVertex(i+1);
|
|
vt1 -= mLine.GetVertex(i);
|
|
s = vt0*vt1;
|
|
if(UP_ZERO(s))
|
|
{
|
|
return GR_OUT;
|
|
}
|
|
else if(DOWN_ZERO(s))
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
return GR_IN|GR_EDGE;
|
|
}
|
|
}
|
|
}
|
|
return GR_IN;
|
|
}
|
|
|
|
bool TGNPolygon2D::IsInclude(const TGObject&obj) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLineSeg2D:
|
|
{
|
|
const TPGeGLineSeg2D &seg = (const TPGeGLineSeg2D&)obj;
|
|
return HitTest(seg.GetStartPoint()).Is(GR_IN) && HitTest(seg.GetEndPoint()).Is(GR_IN);
|
|
}
|
|
case CID_GMLine2D:
|
|
{
|
|
const TGMLine2D &mLine = (const TGMLine2D&)obj;
|
|
for(long i = 0;i<mLine.GetVertexNum();i++)
|
|
{
|
|
if(HitTest(mLine.GetVertex(i)).IsNot(GR_IN))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
case CID_GPolygon2D:
|
|
case CID_GPolygonEx2D:
|
|
{
|
|
const TGPolygon2D&poly = (const TGPolygon2D&)obj;
|
|
const TGMLine2D& mLine = poly.Outline();
|
|
for(long i = 0;i<mLine.GetVertexNum();i++)
|
|
{
|
|
if(HitTest(mLine.GetVertex(i)).IsNot(GR_IN))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
default:
|
|
return TGPolygon2D::IsInclude(obj);
|
|
}
|
|
}
|
|
|
|
void TGNPolygon2D::CutBy(const TPGeCurve2D&curve,TGObjectList&left,TGObjectList&right) const
|
|
{
|
|
if(IS_TYPE(&curve,TPGeGLine2D))
|
|
{
|
|
const TPGeGLine2D&line = (const TPGeGLine2D&)curve;
|
|
long num = mLine.GetSegNum();
|
|
TPGeLine2D seg;
|
|
double paA,paB;
|
|
double paA1,paB1;
|
|
int iSeg1;
|
|
int ptCount = 0;
|
|
for(long i = 0;i<num;i++)
|
|
{
|
|
mLine.GetSegment(i,seg);
|
|
int r = seg.Intersect(line,paA,paB);
|
|
if(r == INT_NULL)
|
|
{
|
|
continue;
|
|
}
|
|
else if(r == INT_1PT && UPEQUAL_ZERO(paA) && DOWNEQUAL_ZERO(paA-1))
|
|
{
|
|
if(ptCount == 0)
|
|
{
|
|
ptCount++;
|
|
paA1 = paA;
|
|
paB1 = paB;
|
|
iSeg1 = i;
|
|
}
|
|
else if(!EQUAL_ZERO(paB-paB1))
|
|
{
|
|
TPtList lPt;
|
|
double pa0 = (iSeg1+paA1)/mLine.GetSegNum(),pa1 = (i+paA)/mLine.GetSegNum();
|
|
TGMLine2D *pSeg1 = (TGMLine2D*)mLine.GetSubCurve(pa0,pa1);
|
|
TGMLine2D *pSeg2 = (TGMLine2D*)mLine.GetSubCurve(pa1,pa0);
|
|
pSeg1->SetClosed();
|
|
pSeg2->SetClosed();
|
|
|
|
GRelation r = line.HitTest(pSeg1->GetSamplePoint());
|
|
if(r.Is(GR_LEFT))
|
|
{
|
|
left << new TGNPolygon2D(*pSeg1,false);
|
|
}
|
|
else if(r.Is(GR_RIGHT))
|
|
{
|
|
right << new TGNPolygon2D(*pSeg1,false);
|
|
}
|
|
|
|
r = line.HitTest(pSeg2->GetSamplePoint());
|
|
if(r.Is(GR_LEFT))
|
|
{
|
|
left << new TGNPolygon2D(*pSeg2,false);
|
|
}
|
|
else if(r.Is(GR_RIGHT))
|
|
{
|
|
right << new TGNPolygon2D(*pSeg2,false);
|
|
}
|
|
|
|
delete pSeg1;
|
|
delete pSeg2;
|
|
return;
|
|
}
|
|
}
|
|
else if(r == INT_LINE)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
GRelation r = GR_IN;
|
|
for(i = 0;r.Is(GR_IN);i++)
|
|
{
|
|
r = line.HitTest(mLine.GetVertex(i));
|
|
}
|
|
if(r.Is(GR_LEFT))
|
|
{
|
|
left << Clone();
|
|
}
|
|
else
|
|
{
|
|
right << Clone();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TGRegion2D::CutBy(curve,left,right);
|
|
}
|
|
} |