Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

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);
}
}