1956 lines
37 KiB
C++
1956 lines
37 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TGPLine2D 类
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TGPLine2D 定义
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TGPLine2D.h"
|
|
#include "TGPa.h"
|
|
#include "TPDList.h"
|
|
#include "TGPoint2D.h"
|
|
#include "TSPTable.h"
|
|
|
|
IMPLEMENT_RUN_TIME_CLASS1(TGPLine2D,"TGPLine2D",TGMLine2D)
|
|
|
|
bool TGPLine2D::IsValid() const
|
|
{
|
|
if (!TGMLine2D::IsValid())
|
|
{
|
|
return false;
|
|
}
|
|
for (long i=0;i<bulges.GetLength();i++)
|
|
{
|
|
if (UPEQUAL_ZEROA(bulges.GetAt(i)-PI2) || DOWNEQUAL_ZEROA(bulges.GetAt(i)+PI2))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(long vertexNum,bool bClosed):TGMLine2D(vertexNum,bClosed)
|
|
{
|
|
bulges.Realloc(vertexNum);
|
|
bulges.SetAll(0);
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TArray<TGPoint>&vertexs,bool bClosed):TGMLine2D(vertexs,bClosed)
|
|
{
|
|
bulges.Realloc(vertexs.GetLength());
|
|
bulges.SetAll(0);
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TTable<TGPoint>&vertexs,bool bClosed):TGMLine2D(vertexs,bClosed)
|
|
{
|
|
bulges.Realloc(vertexs.GetLength());
|
|
bulges.SetAll(0);
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TArray<TGPoint>&vertexs,const TArray<double>&angles,bool bClosed):TGMLine2D(vertexs,bClosed),
|
|
bulges(angles)
|
|
{
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TTable<TGPoint>&vertexs,const TTable<double>&angles,bool bClosed):TGMLine2D(vertexs,bClosed),
|
|
bulges(angles)
|
|
{
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TGMLine2D&mLine):TGMLine2D(mLine)
|
|
{
|
|
bulges.Realloc(mLine.GetVertexNum());
|
|
bulges.SetAll(0);
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TPGeCircle2D&cir):TGMLine2D(2,true)
|
|
{
|
|
bulges.Realloc(2);
|
|
cir.Pa2Pt(0,(*this)[0]);
|
|
cir.Pa2Pt(PI,(*this)[1]);
|
|
if (cir.IsClockwise())
|
|
{
|
|
(*this)(0) = -PI;
|
|
(*this)(1) = -PI;
|
|
}
|
|
else
|
|
{
|
|
(*this)(0) = PI;
|
|
(*this)(1) = PI;
|
|
}
|
|
}
|
|
|
|
TGPLine2D::TGPLine2D(const TPGeArc2D&arc):TGMLine2D(2,false)
|
|
{
|
|
bulges.Realloc(2);
|
|
(*this)[0] = arc.GetStartPoint();
|
|
(*this)[1] = arc.GetEndPoint();
|
|
(*this)(0) = arc.IsClockwise()?-arc.centralAngle:arc.centralAngle;
|
|
(*this)(1) = 0;
|
|
}
|
|
|
|
TGPLine2D::~TGPLine2D()
|
|
{
|
|
|
|
}
|
|
|
|
double& TGPLine2D::operator ()(long i)
|
|
{
|
|
return bulges[i];
|
|
}
|
|
|
|
TGMLine2D* TGPLine2D::PLinearize(double paDist) const
|
|
{
|
|
return new TGPLine2D(*this);
|
|
}
|
|
|
|
TGObject * TGPLine2D::Clone() const
|
|
{
|
|
return new TGPLine2D(*this);
|
|
}
|
|
|
|
double TGPLine2D::GetBulge(long i) const
|
|
{
|
|
return bulges.GetAt(i);
|
|
}
|
|
|
|
bool TGPLine2D::IsArc(long i) const
|
|
{
|
|
return !EQUAL_ZEROA(bulges.GetAt(i));
|
|
}
|
|
|
|
void TGPLine2D::GetSegment(long i,TPGeLine2D& seg) const
|
|
{
|
|
TGMLine2D::GetSegment(i,seg);
|
|
}
|
|
|
|
bool TGPLine2D::IsArcExist() const
|
|
{
|
|
long num = GetSegNum();
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TGPLine2D::SetVertexNum(long num,bool bCopy)
|
|
{
|
|
points.Realloc(num,bCopy);
|
|
if (bCopy)
|
|
{
|
|
long oldNum = bulges.GetLength();
|
|
bulges.Realloc(num,true);
|
|
for (long i = oldNum;i<num;i++)
|
|
{
|
|
bulges[i] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bulges.Realloc(num,false);
|
|
bulges.SetAll(0);
|
|
}
|
|
}
|
|
|
|
bool TGPLine2D::RemoveDupPoint()
|
|
{
|
|
if (points.GetLength() < 2)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TList<TGPoint> ptList;
|
|
TList<double> aList;
|
|
ptList.AddTail(points.GetAt(0));
|
|
for (long i = 1;i<points.GetLength();i++)
|
|
{
|
|
if (ptList.GetCurData() != points.GetAt(i))
|
|
{
|
|
ptList.AddTail(points.GetAt(i));
|
|
aList.AddTail(bulges.GetAt(i-1));
|
|
}
|
|
}
|
|
|
|
aList.AddTail(bulges.GetAt(bulges.GetLastIndex()));
|
|
if (Is(CLOSED_CURVE) && ptList.GetLength()>1 && points.GetAt(0) == ptList.GetCurData())
|
|
{
|
|
ptList.DelCur();
|
|
aList.DelCur();
|
|
}
|
|
if (ptList.GetLength() < 2)
|
|
{
|
|
return false;
|
|
}
|
|
if (ptList.GetLength()<points.GetLength())
|
|
{
|
|
points = ptList;
|
|
bulges = aList;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGPLine2D::IsSelfCross() const
|
|
{
|
|
long num = GetSegNum();
|
|
if (num < 2)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool bClosed = IsClosed();
|
|
long num1 = num-1;;
|
|
for (long i = 0;i<num1;i++)
|
|
{
|
|
TGObjectList buf;
|
|
TPGeCurve2D *pSegi = GetSegment(i);
|
|
buf << pSegi;
|
|
for (long j = i+1;j<num;j++)
|
|
{
|
|
TPGeCurve2D *pSegj = GetSegment(j);
|
|
buf << pSegj;
|
|
|
|
TGObjectList oList;
|
|
if (pSegi->Intersect(*pSegj,oList))
|
|
{
|
|
if (oList[0]->GetClassID() != CID_GPoint2D)
|
|
{
|
|
return true;
|
|
}
|
|
else if (oList.GetLength() == 2)
|
|
{
|
|
if (!(num == 2 && bClosed))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (j != i+1 && (i != 0 || j != num1 || !bClosed))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TGPLine2D::Pa2Pt(double pa,TGPoint&pt) const
|
|
{
|
|
if (EQUAL_ZERO(pa))
|
|
{
|
|
GetStartPoint(pt);
|
|
}
|
|
else if (EQUAL_ZERO(pa-1))
|
|
{
|
|
GetEndPoint(pt);
|
|
}
|
|
else
|
|
{
|
|
long i = Pa2Seg(pa);
|
|
TPGeCurve2D* pSeg = GetSegment(i);
|
|
pSeg->Pa2Pt(pa,pt);
|
|
delete pSeg;
|
|
}
|
|
}
|
|
|
|
TPGeCurve2D* TGPLine2D::GetSubCurve(double pa0,double pa1) const
|
|
{
|
|
TList<TGPoint> ptList;
|
|
TList<double> paList;
|
|
TGPoint pt;
|
|
if (IsClosed())
|
|
{
|
|
if (EQUAL_ZERO(pa0-1))
|
|
{
|
|
pa0 = 0;
|
|
}
|
|
if (EQUAL_ZERO(pa1-1))
|
|
{
|
|
pa1 = 0;
|
|
}
|
|
}
|
|
if (UP_ZERO(pa1-pa0))
|
|
{
|
|
long iSeg0 = Pa2Seg(pa0),iSeg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D *pSeg0 = GetSegment(iSeg0),*pSeg1 = GetSegment(iSeg1);
|
|
|
|
if (DOWN_ZERO(pa0-1))
|
|
{
|
|
pSeg0->Pa2Pt(pa0,pt);
|
|
ptList.AddTail(pt);
|
|
if (iSeg0 == iSeg1)
|
|
{
|
|
paList.AddTail(GetBulge(iSeg0)*(pa1-pa0));
|
|
}
|
|
else
|
|
{
|
|
paList.AddTail(GetBulge(iSeg0)*(1-pa0));
|
|
}
|
|
}
|
|
|
|
for (long i = iSeg0+1;i<iSeg1;i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
paList.AddTail(GetBulge(i));
|
|
}
|
|
if (iSeg0 != iSeg1)
|
|
{
|
|
ptList.AddTail(GetVertex(iSeg1));
|
|
paList.AddTail(GetBulge(iSeg1)*pa1);
|
|
}
|
|
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
pSeg1->Pa2Pt(pa1,pt);
|
|
ptList.AddTail(pt);
|
|
paList.AddTail(0);
|
|
}
|
|
delete pSeg0;
|
|
delete pSeg1;
|
|
return new TGPLine2D(ptList,paList,false);
|
|
}
|
|
else if (DOWN_ZERO(pa1-pa0))
|
|
{
|
|
long iSeg0 = Pa2Seg(pa0),iSeg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D *pSeg0 = GetSegment(iSeg0),*pSeg1 = GetSegment(iSeg1);
|
|
|
|
if (DOWN_ZERO(pa0-1))
|
|
{
|
|
|
|
pSeg0->Pa2Pt(pa0,pt);
|
|
ptList.AddTail(pt);
|
|
paList.AddTail(GetBulge(iSeg0)*(1-pa0));
|
|
}
|
|
|
|
for (long i = iSeg0+1;i<GetVertexNum();i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
paList.AddTail(GetBulge(i));
|
|
}
|
|
|
|
for (i = 0;i<iSeg1;i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
paList.AddTail(GetBulge(i));
|
|
}
|
|
ptList.AddTail(GetVertex(iSeg1));
|
|
paList.AddTail(GetBulge(iSeg1)*pa1);
|
|
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
pSeg1->Pa2Pt(pa1,pt);
|
|
ptList.AddTail(pt);
|
|
paList.AddTail(0);
|
|
}
|
|
delete pSeg0;
|
|
delete pSeg1;
|
|
return new TGPLine2D(ptList,paList,false);
|
|
}
|
|
else
|
|
{
|
|
long iSeg = Pa2Seg(pa0);
|
|
TPGeCurve2D* pSeg = GetSegment(iSeg);
|
|
if (DOWN_ZERO(pa0-1))
|
|
{
|
|
pSeg->Pa2Pt(pa0,pt);
|
|
ptList.AddTail(pt);
|
|
paList.AddTail(GetBulge(iSeg)*(1-pa0));
|
|
}
|
|
|
|
for (long i = iSeg+1;i<GetVertexNum();i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
paList.AddTail(GetBulge(i));
|
|
}
|
|
for (i = 0;i<iSeg;i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
paList.AddTail(GetBulge(i));
|
|
}
|
|
if (UP_ZERO(pa0))
|
|
{
|
|
ptList.AddTail(GetVertex(iSeg));
|
|
paList.AddTail(GetBulge(iSeg)*pa0);
|
|
}
|
|
delete pSeg;
|
|
return new TGPLine2D(ptList,paList,true);
|
|
}
|
|
}
|
|
|
|
void TGPLine2D::Pt2Pa(const TGPoint&pt,double&pa) const
|
|
{
|
|
pa = -1;
|
|
TGObjectList buf;
|
|
for (long i = 0;i<GetSegNum();i++)
|
|
{
|
|
TPGeCurve2D* pSeg = GetSegment(i);
|
|
buf << pSeg;
|
|
if (pSeg->HitTest(pt).Is(GR_IN))
|
|
{
|
|
pSeg->Pt2Pa(pt,pa);
|
|
pa = (pa+i)/GetSegNum();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TGPLine2D::GetTangent(double pa,TPGeLine2D&line) const
|
|
{
|
|
long i = Pa2Seg(pa);
|
|
if (IsArc(i))
|
|
{
|
|
TPGeArc2D aSeg;
|
|
GetSegment(i,aSeg);
|
|
aSeg.GetTangent(pa,line);
|
|
}
|
|
else
|
|
{
|
|
GetSegment(i,line);
|
|
line.Normalize();
|
|
}
|
|
}
|
|
|
|
void TGPLine2D::Reverse()
|
|
{
|
|
if (Is(CLOSED_CURVE))
|
|
{
|
|
points.Reverse(1);
|
|
bulges.Reverse();
|
|
}
|
|
else
|
|
{
|
|
points.Reverse();
|
|
if (bulges.GetLength()>2)
|
|
{
|
|
bulges.Reverse(0,bulges.GetLength()-2);
|
|
}
|
|
}
|
|
for (long i = 0;i<bulges.GetLength();i++)
|
|
{
|
|
bulges[i] = -(bulges[i]);
|
|
}
|
|
}
|
|
|
|
double TGPLine2D::Integration(double pa0,double pa1) const
|
|
{
|
|
double d = pa0-pa1;
|
|
if (DOWN_ZERO(d))
|
|
{
|
|
long seg0 = Pa2Seg(pa0),seg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D*pSeg = GetSegment(seg0);
|
|
if (seg0 == seg1)
|
|
{
|
|
double r = pSeg->Integration(pa0,pa1);
|
|
delete pSeg;
|
|
return r;
|
|
}
|
|
|
|
double r = pSeg->Integration(pa0,1);
|
|
delete pSeg;
|
|
pSeg = GetSegment(seg1);
|
|
r += pSeg->Integration(0,pa1);
|
|
delete pSeg;
|
|
for (long i = seg0+1;i<seg1;i++)
|
|
{
|
|
pSeg = GetSegment(i);
|
|
r += pSeg->AllIntegration();
|
|
delete pSeg;
|
|
}
|
|
return r;
|
|
}
|
|
else if (UP_ZERO(d))
|
|
{
|
|
Exchange(pa0,pa1);
|
|
long seg0 = Pa2Seg(pa0),seg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D*pSeg = GetSegment(seg0);
|
|
if (seg0 == seg1)
|
|
{
|
|
double r = pSeg->Integration(pa0,pa1);
|
|
delete pSeg;
|
|
return -r;
|
|
}
|
|
|
|
double r = pSeg->Integration(pa0,1);
|
|
delete pSeg;
|
|
pSeg = GetSegment(seg1);
|
|
r += pSeg->Integration(0,pa1);
|
|
delete pSeg;
|
|
for (long i = seg0+1;i<seg1;i++)
|
|
{
|
|
pSeg = GetSegment(i);
|
|
r += pSeg->AllIntegration();
|
|
delete pSeg;
|
|
}
|
|
return -r;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool TGPLine2D::GetExtend2D(TPGeExtend2D&ext) const
|
|
{
|
|
return TGObject2D::GetExtend2D(ext);
|
|
}
|
|
|
|
GRelation TGPLine2D::HitTest(const TGPoint&pt) const
|
|
{
|
|
if (IsClosed())
|
|
{
|
|
//modify by xlc on 101123 解决搜索房间求布尔运算错误的问题
|
|
//TPGeGLineRay2D ray(TGVector2D(1,0),pt);
|
|
TPGeGLineRay2D ray(TGVector2D(cos(0.005*PI),sin(0.005*PI)),pt);
|
|
|
|
bool bOutside = true;
|
|
long segNum = GetSegNum();
|
|
TPGeGLineSeg2D lSeg;
|
|
TPGeArc2D aSeg;
|
|
for (long i = 0;i<segNum;i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
GetSegment(i,aSeg);
|
|
|
|
if (aSeg.HitTest(pt).Is(GR_IN))
|
|
{
|
|
return GR_IN;
|
|
}
|
|
|
|
TGObjectList oList;
|
|
if (aSeg.Intersect(ray,oList))
|
|
{
|
|
for (oList.MoveToFirst();!oList.IsOut();oList.MoveToNext())
|
|
{
|
|
const TGPoint2D &pt1 = (const TGPoint2D&)(oList.GetCurPData());
|
|
if (pt1 != pt)
|
|
{
|
|
if (pt1 != GetVertex(i))
|
|
{
|
|
if (pt1 != GetVertex((i+1)%segNum))
|
|
{
|
|
TGVector2D vt0(aSeg.circle.center,pt1),vt;
|
|
vt0.GetLVertVector(vt);
|
|
if (!vt.IsParallel(ray))
|
|
{
|
|
bOutside=!bOutside;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
bool bLeft1,bLeft2;
|
|
if (UP_ZERO(tan.y))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
|
|
else if (DOWN_ZERO(tan.y))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = aSeg.circle.center.y>pt.y;
|
|
}
|
|
|
|
int j = (i+1)%segNum;
|
|
while(true)
|
|
{
|
|
if (IsArc(j))
|
|
{
|
|
GetSegment(j,aSeg);
|
|
aSeg.GetTangent(0,tan);
|
|
if (UP_ZERO(tan.y))
|
|
{
|
|
bLeft2 = true;
|
|
}
|
|
else if (DOWN_ZERO(tan.y))
|
|
{
|
|
bLeft2 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft2 = aSeg.circle.center.y>pt.y;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
GetSegment(j,tan);
|
|
tan.Normalize();
|
|
if (EQUAL_ZERO(tan.y))
|
|
{
|
|
j = (j+1)%segNum;
|
|
}
|
|
else
|
|
{
|
|
bLeft2 = UP_ZERO(tan.y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ((bLeft1 && !bLeft2) || (!bLeft1 && bLeft2))
|
|
{
|
|
bOutside = !bOutside;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return GR_IN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetSegment(i,lSeg);
|
|
|
|
if (lSeg.HitTest(pt).Is(GR_IN))
|
|
return GR_IN;
|
|
|
|
double pa1,pa2;
|
|
int iRet = ray.GetGeLine().Intersect(lSeg,pa1,pa2);
|
|
double dpa2 = pa2-1;
|
|
if (iRet == INT_1PT && UPEQUAL_ZERO(pa1) &&
|
|
UPEQUAL_ZERO(pa2) && DOWNEQUAL_ZERO(dpa2))
|
|
{
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
if (UP_ZERO(pa2) && DOWN_ZERO(dpa2))
|
|
{
|
|
bOutside=!bOutside;
|
|
}
|
|
else if (EQUAL_ZERO(dpa2)) // 1E-9
|
|
// sg add 091109,替换为下面这句话,则可以解决某张图的搜索房间问题
|
|
// else if ((dpa2)>=-1E-10 && (dpa2)<=1E-10)
|
|
{
|
|
TPGeGLine2D tan;
|
|
bool bLeft1 = lSeg.GetStartPoint().y>pt.y,bLeft2;
|
|
|
|
|
|
int j = (i+1)%segNum;
|
|
while(true)
|
|
{
|
|
if (IsArc(j))
|
|
{
|
|
GetSegment(j,aSeg);
|
|
aSeg.GetTangent(0,tan);
|
|
if (UP_ZERO(tan.y))
|
|
{
|
|
bLeft2 = true;
|
|
}
|
|
else if (DOWN_ZERO(tan.y))
|
|
{
|
|
bLeft2 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft2 = aSeg.circle.center.y>pt.y;
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
GetSegment(j,tan);
|
|
tan.Normalize();
|
|
if (EQUAL_ZERO(tan.y))
|
|
{
|
|
j = (j+1)%segNum;
|
|
}
|
|
else
|
|
{
|
|
bLeft2 = UP_ZERO(tan.y);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if ((bLeft1 && !bLeft2) || (!bLeft1 && bLeft2))
|
|
{
|
|
bOutside = !bOutside;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return GR_IN;
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
lSeg.Pt2Pa(pt,pa1);
|
|
if (UPEQUAL_ZERO(pa1) && DOWNEQUAL_ZERO(pa1-1))
|
|
{
|
|
return GR_IN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return bOutside?GR_OUTSIDE:GR_INSIDE;
|
|
}
|
|
else
|
|
{
|
|
return TGObject::HitTest(pt);
|
|
}
|
|
}
|
|
|
|
void TGPLine2D::QuickCut(const TPGeGLine2D&line,TGObjectList&left,TGObjectList&right,TGObjectList&mid) const
|
|
{
|
|
long segNum = GetSegNum();
|
|
const TPGeLine2D &line0 = line;
|
|
TPGeGLine2D line1(line);
|
|
TPDList<TGPa> cutList;
|
|
double pa0,pa1;
|
|
TPGeGLineSeg2D lSeg;
|
|
TPGeArc2D aSeg;
|
|
GRelation r;
|
|
|
|
for (long i = 0;i<segNum;i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
GetSegment(i,aSeg);
|
|
TGObjectList oList;
|
|
if (aSeg.Intersect(line1,oList))
|
|
{
|
|
for (oList.MoveToFirst();!oList.IsOut();oList.MoveToNext())
|
|
{
|
|
const TGPoint2D&pt = (const TGPoint2D&)(oList.GetCurPData());
|
|
if (pt == GetVertex(i))
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
bool bLeft0,bLeft1;
|
|
TPGeGLine2D tan;
|
|
if (IsArc(j))
|
|
{
|
|
TPGeArc2D aSeg0;
|
|
GetSegment(j,aSeg0);
|
|
aSeg0.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg0.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
aSeg.GetTangent(0,tan);
|
|
s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bLeft0 = r.Is(GR_LEFT);
|
|
|
|
aSeg.GetTangent(0,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pt != GetVertex((i+1)%segNum))
|
|
{
|
|
TGVector2D tan;
|
|
TGVector2D(aSeg.circle.center,pt).GetLVertVector(tan);
|
|
if (!tan.IsParallel(line0))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetSegment(i,lSeg);
|
|
int iRet = line0.Intersect(lSeg,pa0,pa1);
|
|
if (iRet == INT_1PT)
|
|
{
|
|
if (UP_ZERO(pa1) && DOWN_ZERO(pa1-1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
else if (EQUAL_ZERO(pa1))
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
if (IsArc(j))
|
|
{
|
|
bool bLeft0,bLeft1 = line0.HitTest(lSeg.GetEndPoint()).Is(GR_LEFT);
|
|
|
|
GetSegment(j,aSeg);
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1 = line0.HitTest(lSeg.GetEndPoint()).Is(GR_LEFT);
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
bool bLeft0,bLeft1;
|
|
if (IsArc(j))
|
|
{
|
|
GetSegment(j,aSeg);
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
r.AddFlag(GR_IN);
|
|
for (j = (i+2)%segNum;r.Is(GR_IN);j = (j+1)%segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
|
|
line0.Pt2Pa(lSeg.GetStartPoint(),pa0);
|
|
line0.Pt2Pa(GetVertex((j-2+segNum)%segNum),pa1);
|
|
if (pa0>pa1)
|
|
{
|
|
Exchange(pa0,pa1);
|
|
}
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1);
|
|
}
|
|
else
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1,MID_PT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bLeft0 = r.Is(GR_LEFT),bLeft1;
|
|
|
|
r.AddFlag(GR_IN);
|
|
for (j = (i+2)%segNum;r.Is(GR_IN);j = (j+1)%segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
|
|
line0.Pt2Pa(lSeg.GetStartPoint(),pa0);
|
|
line0.Pt2Pa(GetVertex((j-2+segNum)%segNum),pa1);
|
|
if (pa0>pa1)
|
|
{
|
|
Exchange(pa0,pa1);
|
|
}
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1);
|
|
}
|
|
else
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1,MID_PT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (cutList.IsEmpty())
|
|
{
|
|
right << new TPGeGLine2D(line);
|
|
return;
|
|
}
|
|
cutList.Arrange();
|
|
|
|
bool bOut = true;
|
|
bool bMid = false;
|
|
TGPoint pt0,pt1;
|
|
cutList.MoveToFirst();
|
|
line0.Pa2Pt(cutList.GetCurPData().pa,pt0);
|
|
right << new TPGeGLineRay2D(TGVector2D(-line0),pt0);
|
|
if (cutList.GetCurPData().Is(MID_PT))
|
|
{
|
|
bMid = true;
|
|
}
|
|
else
|
|
{
|
|
bOut = false;
|
|
}
|
|
for (cutList.MoveToNext();!cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
const TGPa&pa = cutList.GetCurPData();
|
|
line0.Pa2Pt(pa.pa,pt1);
|
|
TPGeGLineSeg2D *pNewSeg = new TPGeGLineSeg2D(pt0,pt1);
|
|
if (bMid)
|
|
{
|
|
mid << pNewSeg;
|
|
}
|
|
else if (bOut)
|
|
{
|
|
right << pNewSeg;
|
|
}
|
|
else
|
|
{
|
|
left << pNewSeg;
|
|
}
|
|
|
|
pt0 = pt1;
|
|
if (pa.Is(MID_PT))
|
|
{
|
|
bMid = !bMid;
|
|
}
|
|
else
|
|
{
|
|
bOut = !bOut;
|
|
bMid = false;
|
|
}
|
|
}
|
|
right << new TPGeGLineRay2D(TGVector2D(line0),pt0);
|
|
}
|
|
|
|
void TGPLine2D::QuickCut(const TPGeGLineRay2D&line,TGObjectList&left,TGObjectList&right,TGObjectList&mid) const
|
|
{
|
|
long segNum = GetSegNum();
|
|
const TPGeLine2D &line0 = line;
|
|
TPGeGLine2D line1(line);
|
|
TPDList<TGPa> cutList;
|
|
double pa0,pa1;
|
|
TPGeGLineSeg2D lSeg;
|
|
TPGeArc2D aSeg;
|
|
GRelation r;
|
|
for (long i = 0;i<segNum;i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
GetSegment(i,aSeg);
|
|
TGObjectList oList;
|
|
if (aSeg.Intersect(line1,oList))
|
|
{
|
|
for (oList.MoveToFirst();!oList.IsOut();oList.MoveToNext())
|
|
{
|
|
const TGPoint2D&pt = (const TGPoint2D&)(oList.GetCurPData());
|
|
if (pt == GetVertex(i))
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
bool bLeft0,bLeft1;
|
|
TPGeGLine2D tan;
|
|
if (IsArc(j))
|
|
{
|
|
TPGeArc2D aSeg0;
|
|
GetSegment(j,aSeg0);
|
|
aSeg0.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg0.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
aSeg.GetTangent(0,tan);
|
|
s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bLeft0 = r.Is(GR_LEFT);
|
|
|
|
aSeg.GetTangent(0,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pt != GetVertex((i+1)%segNum))
|
|
{
|
|
TGVector2D tan;
|
|
TGVector2D(aSeg.circle.center,pt).GetLVertVector(tan);
|
|
if (!tan.IsParallel(line0))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetSegment(i,lSeg);
|
|
int iRet = line0.Intersect(lSeg,pa0,pa1);
|
|
if (iRet == INT_1PT)
|
|
{
|
|
if (UP_ZERO(pa1) && DOWN_ZERO(pa1-1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
else if (EQUAL_ZERO(pa1))
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
if (IsArc(j))
|
|
{
|
|
bool bLeft0,bLeft1 = line0.HitTest(lSeg.GetEndPoint()).Is(GR_LEFT);
|
|
|
|
GetSegment(j,aSeg);
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1 = line0.HitTest(lSeg.GetEndPoint()).Is(GR_LEFT);
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
bool bLeft0,bLeft1;
|
|
if (IsArc(j))
|
|
{
|
|
GetSegment(j,aSeg);
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
r.AddFlag(GR_IN);
|
|
for (j = (i+2)%segNum;r.Is(GR_IN);j = (j+1)%segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
|
|
line0.Pt2Pa(lSeg.GetStartPoint(),pa0);
|
|
line0.Pt2Pa(GetVertex((j-2+segNum)%segNum),pa1);
|
|
if (pa0>pa1)
|
|
{
|
|
Exchange(pa0,pa1);
|
|
}
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1);
|
|
}
|
|
else
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1,MID_PT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bLeft0 = r.Is(GR_LEFT),bLeft1;
|
|
|
|
r.AddFlag(GR_IN);
|
|
for (j = (i+2)%segNum;r.Is(GR_IN);j = (j+1)%segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
|
|
line0.Pt2Pa(lSeg.GetStartPoint(),pa0);
|
|
line0.Pt2Pa(GetVertex((j-2+segNum)%segNum),pa1);
|
|
if (pa0>pa1)
|
|
{
|
|
Exchange(pa0,pa1);
|
|
}
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1);
|
|
}
|
|
else
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1,MID_PT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (cutList.IsEmpty())
|
|
{
|
|
right << new TPGeGLineRay2D(line);
|
|
return;
|
|
}
|
|
|
|
cutList.Arrange();
|
|
bool bOut = true;
|
|
bool bMid = false;
|
|
for (cutList.MoveToFirst();!cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
const TGPa& pa = cutList.GetCurPData();
|
|
if (UP_ZERO(pa.pa))
|
|
{
|
|
break;
|
|
}
|
|
if (pa.Is(MID_PT))
|
|
{
|
|
bMid = !bMid;
|
|
}
|
|
else
|
|
{
|
|
bOut = !bOut;
|
|
bMid = false;
|
|
}
|
|
}
|
|
if (cutList.IsOut())
|
|
{
|
|
right << new TPGeGLineRay2D(line);
|
|
return;
|
|
}
|
|
|
|
TGPoint pt0(line0.basePoint),pt1;
|
|
for (;!cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
const TGPa&pa = cutList.GetCurPData();
|
|
line0.Pa2Pt(pa.pa,pt1);
|
|
TPGeGLineSeg2D *pNewSeg = new TPGeGLineSeg2D(pt0,pt1);
|
|
if (bMid)
|
|
{
|
|
mid << pNewSeg;
|
|
}
|
|
else if (bOut)
|
|
{
|
|
right << pNewSeg;
|
|
}
|
|
else
|
|
{
|
|
left << pNewSeg;
|
|
}
|
|
|
|
pt0 = pt1;
|
|
if (pa.Is(MID_PT))
|
|
{
|
|
bMid = !bMid;
|
|
}
|
|
else
|
|
{
|
|
bOut = !bOut;
|
|
bMid = false;
|
|
}
|
|
}
|
|
right << new TPGeGLineRay2D(TGVector2D(line0),pt0);
|
|
}
|
|
|
|
void TGPLine2D::QuickCut(const TPGeGLineSeg2D&line,TGObjectList&left,TGObjectList&right,TGObjectList&mid) const
|
|
{
|
|
long segNum = GetSegNum();
|
|
const TPGeLine2D &line0 = line;
|
|
TPGeGLine2D line1(line);
|
|
TPDList<TGPa> cutList;
|
|
double pa0,pa1;
|
|
TPGeGLineSeg2D lSeg;
|
|
TPGeArc2D aSeg;
|
|
GRelation r;
|
|
for (long i = 0;i<segNum;i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
GetSegment(i,aSeg);
|
|
TGObjectList oList;
|
|
if (aSeg.Intersect(line1,oList))
|
|
for (oList.MoveToFirst();!oList.IsOut();oList.MoveToNext())
|
|
{
|
|
const TGPoint2D&pt = (const TGPoint2D&)(oList.GetCurPData());
|
|
if (pt == GetVertex(i))
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
bool bLeft0,bLeft1;
|
|
TPGeGLine2D tan;
|
|
if (IsArc(j))
|
|
{
|
|
TPGeArc2D aSeg0;
|
|
GetSegment(j,aSeg0);
|
|
aSeg0.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg0.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
aSeg.GetTangent(0,tan);
|
|
s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bLeft0 = r.Is(GR_LEFT);
|
|
|
|
aSeg.GetTangent(0,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft1 = true;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft1 = false;
|
|
}
|
|
else
|
|
{
|
|
bLeft1 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pt != GetVertex((i+1)%segNum))
|
|
{
|
|
TGVector2D tan;
|
|
TGVector2D(aSeg.circle.center,pt).GetLVertVector(tan);
|
|
if (!tan.IsParallel(line0))
|
|
{
|
|
line0.Pt2Pa(pt,pa0);
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetSegment(i,lSeg);
|
|
int iRet = line0.Intersect(lSeg,pa0,pa1);
|
|
if (iRet == INT_1PT)
|
|
{
|
|
if (UP_ZERO(pa1) && DOWN_ZERO(pa1-1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
else if (EQUAL_ZERO(pa1))
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
if (IsArc(j))
|
|
{
|
|
bool bLeft0,bLeft1 = line0.HitTest(lSeg.GetEndPoint()).Is(GR_LEFT);
|
|
|
|
GetSegment(j,aSeg);
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1 = line0.HitTest(lSeg.GetEndPoint()).Is(GR_LEFT);
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
long j = (i-1+segNum)%segNum;
|
|
bool bLeft0,bLeft1;
|
|
if (IsArc(j))
|
|
{
|
|
GetSegment(j,aSeg);
|
|
TPGeGLine2D tan;
|
|
aSeg.GetTangent(1,tan);
|
|
double s = line0*tan;
|
|
if (UP_ZERO(s))
|
|
{
|
|
bLeft0 = false;
|
|
}
|
|
else if (DOWN_ZERO(s))
|
|
{
|
|
bLeft0 = true;
|
|
}
|
|
else
|
|
{
|
|
bLeft0 = line0.HitTest(aSeg.circle.center).Is(GR_LEFT);
|
|
}
|
|
|
|
r.AddFlag(GR_IN);
|
|
for (j = (i+2)%segNum;r.Is(GR_IN);j = (j+1)%segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
|
|
line0.Pt2Pa(lSeg.GetStartPoint(),pa0);
|
|
line0.Pt2Pa(GetVertex((j-2+segNum)%segNum),pa1);
|
|
if (pa0>pa1)
|
|
{
|
|
Exchange(pa0,pa1);
|
|
}
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1);
|
|
}
|
|
else
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1,MID_PT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bLeft0 = r.Is(GR_LEFT),bLeft1;
|
|
|
|
r.AddFlag(GR_IN);
|
|
for (j = (i+2)%segNum;r.Is(GR_IN);j = (j+1)%segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
|
|
line0.Pt2Pa(lSeg.GetStartPoint(),pa0);
|
|
line0.Pt2Pa(GetVertex((j-2+segNum)%segNum),pa1);
|
|
if (pa0>pa1)
|
|
{
|
|
Exchange(pa0,pa1);
|
|
}
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1);
|
|
}
|
|
else
|
|
{
|
|
cutList << new TGPa(pa0,MID_PT) << new TGPa(pa1,MID_PT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (cutList.IsEmpty())
|
|
{
|
|
right << new TPGeGLineSeg2D(line);
|
|
return;
|
|
}
|
|
|
|
cutList.Arrange();
|
|
bool bOut = true;
|
|
bool bMid = false;
|
|
for (cutList.MoveToFirst();!cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
const TGPa& pa = cutList.GetCurPData();
|
|
if (UP_ZERO(pa.pa))
|
|
{
|
|
break;
|
|
}
|
|
if (pa.Is(MID_PT))
|
|
{
|
|
bMid = !bMid;
|
|
}
|
|
else
|
|
{
|
|
bOut = !bOut;
|
|
bMid = false;
|
|
}
|
|
}
|
|
if (cutList.IsOut())
|
|
{
|
|
right << new TPGeGLineSeg2D(line);
|
|
return;
|
|
}
|
|
|
|
TGPoint pt0(line.GetStartPoint()),pt1;
|
|
TPGeGLineSeg2D *pNewSeg = NULL;
|
|
for (bool bContinue = true;bContinue && !cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
const TGPa&pa = cutList.GetCurPData();
|
|
if (UPEQUAL_ZERO(pa.pa-1))
|
|
{
|
|
pNewSeg = new TPGeGLineSeg2D(pt0,line.GetEndPoint());
|
|
bContinue = false;
|
|
}
|
|
else
|
|
{
|
|
line0.Pa2Pt(pa.pa,pt1);
|
|
pNewSeg = new TPGeGLineSeg2D(pt0,pt1);
|
|
}
|
|
if (bMid)
|
|
{
|
|
mid << pNewSeg;
|
|
}
|
|
else if (bOut)
|
|
{
|
|
right << pNewSeg;
|
|
}
|
|
else
|
|
{
|
|
left << pNewSeg;
|
|
}
|
|
|
|
pt0 = pt1;
|
|
if (pa.Is(MID_PT))
|
|
{
|
|
bMid = !bMid;
|
|
}
|
|
else
|
|
{
|
|
bOut = !bOut;
|
|
bMid = false;
|
|
}
|
|
}
|
|
|
|
if (bContinue)
|
|
{
|
|
right << new TPGeGLineSeg2D(pt0,line.GetEndPoint());
|
|
}
|
|
}
|
|
|
|
bool TGPLine2D::IsInclude(const TGObject&obj) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GArc2D:
|
|
case CID_GCircle2D:
|
|
return false;
|
|
default:
|
|
return TGMLine2D::IsInclude(obj);
|
|
}
|
|
}
|
|
|
|
bool TGPLine2D::Explode(TGObjectList&res) const
|
|
{
|
|
long num = GetSegNum();
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
res << GetSegment(i);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TGMLine2D* TGPLine2D::MLinearize(double paDist) const
|
|
{
|
|
bool bUseDefault = paDist<1E-9;
|
|
long num = GetSegNum();
|
|
TList<TGPoint> ptList;
|
|
long count = 0;
|
|
TPGeArc2D arc;
|
|
for (long i = 0;i<num;i++)
|
|
{
|
|
ptList[count++] = points.GetAt(i);
|
|
if (IsArc(i))
|
|
{
|
|
GetSegment(i,arc);
|
|
long num1;
|
|
if (bUseDefault)
|
|
{
|
|
num1 = (long)(1/arc.GetMLinePrec()+0.999999);
|
|
}
|
|
else
|
|
{
|
|
num1 = (long)(arc.centralAngle/paDist+0.999999);
|
|
}
|
|
if (num1<1)
|
|
{
|
|
continue;
|
|
}
|
|
double paDist1 = 1.0 / num1;
|
|
double pa = paDist1;
|
|
|
|
for (long j = 1; j < num1; j++,pa += paDist1)
|
|
{
|
|
arc.Pa2Pt(pa,ptList[count++]);
|
|
}
|
|
}
|
|
}
|
|
if (!IsClosed())
|
|
{
|
|
ptList[count] = points.GetAt(i);
|
|
}
|
|
return new TGMLine2D(ptList,IsClosed());
|
|
}
|
|
|
|
bool TGPLine2D::Offset(double offset)
|
|
{
|
|
TSPTable<TPGeCurve2D> curves(GetSegNum());
|
|
for (long i = 0;i<GetSegNum();i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
TPGeArc2D arc;
|
|
GetSegment(i,arc);
|
|
if (!arc.Offset(offset))
|
|
return false;
|
|
curves.AddTail(arc.GetExtendCurve());
|
|
}
|
|
else
|
|
{
|
|
TPGeGLine2D *pLine = new TPGeGLine2D;
|
|
GetSegment(i,*pLine);
|
|
pLine->Offset(offset);
|
|
curves.AddTail(pLine);
|
|
}
|
|
}
|
|
|
|
TArray<TGPoint> newPt(GetVertexNum());
|
|
for (i = 1;i<curves.GetLength();i++)
|
|
{
|
|
TPGeCurve2D*pCurve0 = curves[i-1],*pCurve1 = curves[i];
|
|
TGObjectList buf;
|
|
if (pCurve0->Intersect(*pCurve1,buf))
|
|
{
|
|
TPGeCurve2D*pSeg = GetSegment(i);
|
|
pSeg->Offset(offset);
|
|
if (IS_CLASS(buf[0],TPGeCurve2D))
|
|
{
|
|
pSeg->GetStartPoint(newPt[i]);
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt0 = (TGPoint2D&)(*buf[0]);
|
|
if (buf.GetLength() == 1)
|
|
{
|
|
newPt[i] = pt0;
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt1 = (TGPoint2D&)(*buf[1]),pt2;
|
|
pSeg->GetStartPoint(pt2);
|
|
double nDist0 = pt2.Distance(pt0),nDist1 = pt2.Distance(pt1);
|
|
newPt[i] = nDist0<nDist1?pt0:pt1;
|
|
}
|
|
}
|
|
delete pSeg;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (IsClosed())
|
|
{
|
|
TPGeCurve2D*pCurve0 = curves[i-1],*pCurve1 = curves[0];
|
|
TGObjectList buf;
|
|
if (pCurve0->Intersect(*pCurve1,buf))
|
|
{
|
|
TPGeCurve2D*pSeg = GetSegment(0);
|
|
pSeg->Offset(offset);
|
|
if (IS_CLASS(buf[0],TPGeCurve2D))
|
|
{
|
|
pSeg->GetStartPoint(newPt[0]);
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt0 = (TGPoint2D&)(*buf[0]);
|
|
if (buf.GetLength() == 1)
|
|
{
|
|
newPt[0] = pt0;
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt1 = (TGPoint2D&)(*buf[1]),pt2;
|
|
pSeg->GetStartPoint(pt2);
|
|
double nDist0 = pt2.Distance(pt0),nDist1 = pt2.Distance(pt1);
|
|
newPt[0] = nDist0<nDist1?pt0:pt1;
|
|
}
|
|
}
|
|
delete pSeg;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TPGeCurve2D *pSegFirst = GetSegment(0),*pSegLast = GetSegment(i-1);
|
|
pSegFirst->Offset(offset);
|
|
pSegLast->Offset(offset);
|
|
pSegFirst->GetStartPoint(newPt[0]);
|
|
pSegLast->GetEndPoint(newPt[newPt.GetLastIndex()]);
|
|
delete pSegFirst;
|
|
delete pSegLast;
|
|
}
|
|
|
|
points = newPt;
|
|
for (i = 0;i<GetSegNum();i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
double pa0,pa1;
|
|
curves[i]->Pt2Pa(newPt[i],pa0);
|
|
curves[i]->Pt2Pa(newPt[(i+1)%GetVertexNum()],pa1);
|
|
bulges[i] = curves[i]->IsClockwise()?-ALEN(pa0,pa1):ALEN(pa0,pa1);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGPLine2D::OffsetSeg(long iSeg,double offset)
|
|
{
|
|
TSPTable<TPGeCurve2D> curves(GetSegNum());
|
|
for (long i = 0;i<GetSegNum();i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
TPGeArc2D arc;
|
|
GetSegment(i,arc);
|
|
if (i == iSeg && !arc.Offset(offset))
|
|
{
|
|
return false;
|
|
}
|
|
curves.AddTail(arc.GetExtendCurve());
|
|
}
|
|
else
|
|
{
|
|
TPGeGLine2D *pLine = new TPGeGLine2D;
|
|
GetSegment(i,*pLine);
|
|
if (i == iSeg)
|
|
{
|
|
pLine->Offset(offset);
|
|
}
|
|
curves.AddTail(pLine);
|
|
}
|
|
}
|
|
|
|
TArray<TGPoint> newPt(points);
|
|
for (i = 1;i<curves.GetLength();i++)
|
|
{
|
|
if (i != iSeg && i != iSeg+1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
TPGeCurve2D*pCurve0 = curves[i-1],*pCurve1 = curves[i];
|
|
TGObjectList buf;
|
|
if (pCurve0->Intersect(*pCurve1,buf))
|
|
{
|
|
TPGeCurve2D*pSeg = GetSegment(i);
|
|
if (IS_CLASS(buf[0],TPGeCurve2D))
|
|
{
|
|
pSeg->GetStartPoint(newPt[i]);
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt0 = (TGPoint2D&)(*buf[0]);
|
|
if (buf.GetLength() == 1)
|
|
{
|
|
newPt[i] = pt0;
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt1 = (TGPoint2D&)(*buf[1]),pt2;
|
|
pSeg->GetStartPoint(pt2);
|
|
double nDist0 = pt2.Distance(pt0),nDist1 = pt2.Distance(pt1);
|
|
newPt[i] = nDist0<nDist1?pt0:pt1;
|
|
}
|
|
}
|
|
delete pSeg;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (IsClosed())
|
|
{
|
|
if (iSeg == 0 || iSeg == i-1)
|
|
{
|
|
TPGeCurve2D*pCurve0 = curves[i-1],*pCurve1 = curves[0];
|
|
TGObjectList buf;
|
|
if (pCurve0->Intersect(*pCurve1,buf))
|
|
{
|
|
TPGeCurve2D*pSeg = GetSegment(0);
|
|
if (IS_CLASS(buf[0],TPGeCurve2D))
|
|
{
|
|
pSeg->GetStartPoint(newPt[0]);
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt0 = (TGPoint2D&)(*buf[0]);
|
|
if (buf.GetLength() == 1)
|
|
{
|
|
newPt[0] = pt0;
|
|
}
|
|
else
|
|
{
|
|
TGPoint2D &pt1 = (TGPoint2D&)(*buf[1]),pt2;
|
|
pSeg->GetStartPoint(pt2);
|
|
double nDist0 = pt2.Distance(pt0),nDist1 = pt2.Distance(pt1);
|
|
newPt[0] = nDist0<nDist1?pt0:pt1;
|
|
}
|
|
}
|
|
delete pSeg;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else if (iSeg == 0)
|
|
{
|
|
TPGeCurve2D *pSegFirst = GetSegment(0);
|
|
pSegFirst->Offset(offset);
|
|
pSegFirst->GetStartPoint(newPt[0]);
|
|
delete pSegFirst;
|
|
}
|
|
else if (iSeg == i-1)
|
|
{
|
|
TPGeCurve2D *pSegLast=GetSegment(i-1);
|
|
pSegLast->Offset(offset);
|
|
pSegLast->GetEndPoint(newPt[newPt.GetLastIndex()]);
|
|
delete pSegLast;
|
|
}
|
|
|
|
points = newPt;
|
|
for (i = 0;i<GetSegNum();i++)
|
|
{
|
|
if (IsArc(i))
|
|
{
|
|
double pa0,pa1;
|
|
curves[i]->Pt2Pa(newPt[i],pa0);
|
|
curves[i]->Pt2Pa(newPt[(i+1)%GetVertexNum()],pa1);
|
|
bulges[i] = curves[i]->IsClockwise()?-ALEN(pa0,pa1):ALEN(pa0,pa1);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void TGPLine2D::SetClosed(bool bClosed,double angle)
|
|
{
|
|
if (bulges.GetLength() < 1 || bulges.GetLastIndex() < 0 || bulges.GetLastIndex() >= bulges.GetLength())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(bClosed)
|
|
{
|
|
AddFlag(CLOSED_CURVE);
|
|
bulges[bulges.GetLastIndex()]=angle;
|
|
}
|
|
else
|
|
{
|
|
RemoveFlag(CLOSED_CURVE);
|
|
bulges[bulges.GetLastIndex()]=0;
|
|
}
|
|
}
|