1573 lines
29 KiB
C++
1573 lines
29 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TGMLine2D Àà
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TGMLine2D ¶¨Òå
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TGMLine2D.h"
|
|
#include "TGMatrix.h"
|
|
#include "TPGeGLineSeg2D.h"
|
|
#include "TGPa.h"
|
|
#include "TGPtPa.h"
|
|
#include "TPDList.h"
|
|
#include "TGPoint2D.h"
|
|
|
|
IMPLEMENT_RUN_TIME_CLASS1(TGMLine2D,"TGMLine2D",TPGeCurve2D)
|
|
|
|
TGMLine2D::TGMLine2D(long vertexNum,bool bClosed)
|
|
: points(vertexNum)
|
|
{
|
|
if (bClosed)
|
|
{
|
|
AddFlag(CLOSED_CURVE);
|
|
}
|
|
}
|
|
|
|
TGMLine2D::TGMLine2D(const TTable<TGPoint>&vertexs,bool bClosed):points(vertexs)
|
|
{
|
|
if (bClosed)
|
|
{
|
|
AddFlag(CLOSED_CURVE);
|
|
}
|
|
}
|
|
|
|
TGMLine2D::TGMLine2D(const TArray<TGPoint>&vertexs,bool bClosed):points(vertexs)
|
|
{
|
|
if (bClosed)
|
|
{
|
|
AddFlag(CLOSED_CURVE);
|
|
}
|
|
}
|
|
|
|
TGMLine2D::~TGMLine2D()
|
|
{
|
|
|
|
}
|
|
|
|
TGMLine2D& TGMLine2D::operator = (const TArray<TGPoint>&vertexs)
|
|
{
|
|
SetVertexNum(vertexs.GetLength());
|
|
points = vertexs;
|
|
return *this;
|
|
}
|
|
|
|
TGMLine2D& TGMLine2D::operator = (const TTable<TGPoint>&vertexs)
|
|
{
|
|
SetVertexNum(vertexs.GetLength());
|
|
points = vertexs;
|
|
return *this;
|
|
}
|
|
|
|
TGPoint& TGMLine2D::operator[](long i)
|
|
{
|
|
return points[i];
|
|
}
|
|
|
|
void TGMLine2D::SetClosed(bool bClosed/*=true*/)
|
|
{
|
|
if (bClosed)
|
|
{
|
|
AddFlag(CLOSED_CURVE);
|
|
}
|
|
else
|
|
{
|
|
RemoveFlag(CLOSED_CURVE);
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::SetVertexNum(long num,bool bCopy/*=false*/)
|
|
{
|
|
points.Realloc(num,bCopy);
|
|
}
|
|
|
|
long TGMLine2D::GetVertexNum() const
|
|
{
|
|
return points.GetLength();
|
|
}
|
|
|
|
const TGPoint& TGMLine2D::GetVertex(long i) const
|
|
{
|
|
return points.GetAt(i);
|
|
}
|
|
|
|
bool TGMLine2D::IsClosed() const
|
|
{
|
|
return Is(CLOSED_CURVE);
|
|
}
|
|
|
|
TGMLine2D* TGMLine2D::MLinearize(double paDist/*=0*/) const
|
|
{
|
|
return new TGMLine2D(*this);
|
|
}
|
|
|
|
TGPoint TGMLine2D::GetSamplePoint() const
|
|
{
|
|
TGPoint pt;
|
|
Pa2Pt(0.5 / GetSegNum(), pt);
|
|
return pt;
|
|
}
|
|
|
|
double TGMLine2D::GetElev() const
|
|
{
|
|
return points.GetAt(0).z;
|
|
}
|
|
|
|
TGObject * TGMLine2D::Clone() const
|
|
{
|
|
return new TGMLine2D(*this);
|
|
}
|
|
|
|
void TGMLine2D::GetStartPoint(TGPoint&pt) const
|
|
{
|
|
if (points.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
pt = points.GetAt(0);
|
|
}
|
|
|
|
void TGMLine2D::GetEndPoint(TGPoint&pt) const
|
|
{
|
|
if (IsClosed())
|
|
{
|
|
GetStartPoint(pt);
|
|
return;
|
|
}
|
|
|
|
if (points.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
pt = points.GetAt(points.GetLastIndex());
|
|
}
|
|
|
|
bool TGMLine2D::IsConcave() const
|
|
{
|
|
if (points.GetLength() <= 3)
|
|
{
|
|
return false;
|
|
}
|
|
TGVector2D vt1(points.GetAt(points.GetLastIndex()),points.GetAt(0));
|
|
bool bUp = false,bDown = false;
|
|
|
|
for (long i = 0;i < points.GetLength();i++)
|
|
{
|
|
TGVector2D vt2(points.GetAt(i), points.GetAt((i + 1) % points.GetLength()));
|
|
double temp = vt1 * vt2;
|
|
if (DOWN_ZERO(temp))
|
|
{
|
|
bDown = true;
|
|
}
|
|
else if (UP_ZERO(temp))
|
|
{
|
|
bUp = true;
|
|
}
|
|
if (bUp && bDown)
|
|
{
|
|
return true;
|
|
}
|
|
vt1 = vt2;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TGMLine2D::IsSelfCross() const
|
|
{
|
|
long num = GetSegNum();
|
|
if (num < 2)
|
|
{
|
|
return false;
|
|
}
|
|
TGObjectList oList;
|
|
TPGeGLineSeg2D iSeg,jSeg;
|
|
long num1 = num - 1;
|
|
for (long i = 0;i < num1;i++)
|
|
{
|
|
GetSegment(i,iSeg);
|
|
for (long j = i + 1; j < num;j++)
|
|
{
|
|
GetSegment(j,jSeg);
|
|
if (iSeg.Intersect(jSeg,oList))
|
|
{
|
|
if (oList[0]->GetClassID() == CID_GLineSeg2D)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (j == (i+1) || (i == 0 && j == num1 && IsClosed()))
|
|
{
|
|
oList.Clear();
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TGMLine2D::IsLinear() const
|
|
{
|
|
if (points.GetLength() <= 2)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
const TGPoint &pt0 = points.GetAt(0);
|
|
for (long i = 1;i < points.GetLength() && pt0 == points.GetAt(i);i++);
|
|
|
|
TGVector2D vt1(pt0,points.GetAt(i));
|
|
for (i += 1;i < points.GetLength();i++)
|
|
{
|
|
TGVector2D vt2(pt0,points.GetAt(i));
|
|
double temp = vt1 * vt2;
|
|
if (!EQUAL_ZERO(temp))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
long TGMLine2D::Pa2Seg(double&pa) const
|
|
{
|
|
pa *= GetSegNum();
|
|
long i = (long)pa;
|
|
if (i < 0)
|
|
{
|
|
i = 0;
|
|
}
|
|
else if (i >= GetSegNum())
|
|
{
|
|
i = GetSegNum() - 1;
|
|
}
|
|
pa -= i;
|
|
return i;
|
|
}
|
|
|
|
TPGeCurve2D* TGMLine2D::GetSubCurve(double pa0,double pa1) const
|
|
{
|
|
TList<TGPoint> ptList;
|
|
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);
|
|
TPGeGLineSeg2D seg0,seg1;
|
|
GetSegment(iSeg0,seg0);
|
|
GetSegment(iSeg1,seg1);
|
|
if (DOWN_ZERO(pa0 - 1))
|
|
{
|
|
seg0.Pa2Pt(pa0,pt);
|
|
ptList.AddTail(pt);
|
|
}
|
|
long iSeg2 = iSeg1 + 1;
|
|
for (long i = iSeg0 + 1; i < iSeg2; i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
}
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
seg1.Pa2Pt(pa1,pt);
|
|
ptList.AddTail(pt);
|
|
}
|
|
return new TGMLine2D(ptList,false);
|
|
}
|
|
else if (DOWN_ZERO(pa1 - pa0))
|
|
{
|
|
long iSeg0 = Pa2Seg(pa0),iSeg1 = Pa2Seg(pa1);
|
|
TPGeGLineSeg2D seg0,seg1;
|
|
GetSegment(iSeg0,seg0);
|
|
GetSegment(iSeg1,seg1);
|
|
if (DOWN_ZERO(pa0 - 1))
|
|
{
|
|
seg0.Pa2Pt(pa0,pt);
|
|
ptList.AddTail(pt);
|
|
}
|
|
for (long i = iSeg0 + 1;i < GetVertexNum();i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
}
|
|
|
|
long iSeg2 = iSeg1 + 1;
|
|
for (i = 0; i < iSeg2; i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
}
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
seg1.Pa2Pt(pa1,pt);
|
|
ptList.AddTail(pt);
|
|
}
|
|
return new TGMLine2D(ptList,false);
|
|
}
|
|
else
|
|
{
|
|
long iSeg = Pa2Seg(pa0);
|
|
TPGeGLineSeg2D seg;
|
|
GetSegment(iSeg,seg);
|
|
if (DOWN_ZERO(pa0 - 1))
|
|
{
|
|
seg.Pa2Pt(pa0,pt);
|
|
ptList.AddTail(pt);
|
|
}
|
|
for (long i = iSeg + 1;i < GetVertexNum();i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
}
|
|
for (i = 0;i < iSeg;i++)
|
|
{
|
|
ptList.AddTail(GetVertex(i));
|
|
}
|
|
if (UP_ZERO(pa0))
|
|
{
|
|
ptList.AddTail(seg.GetStartPoint());
|
|
}
|
|
return new TGMLine2D(ptList,true);
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::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);
|
|
TPGeGLineSeg2D seg;
|
|
GetSegment(i,seg);
|
|
seg.Pa2Pt(pa,pt);
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::Pt2Pa(const TGPoint&pt,double&pa) const
|
|
{
|
|
TPGeGLineSeg2D seg;
|
|
long num = GetSegNum();
|
|
pa = -1;
|
|
for (long i = 0;i < num;i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
if (seg.HitTest(pt).Is(GR_IN))
|
|
{
|
|
seg.Pt2Pa(pt,pa);
|
|
pa = (pa + i) / num;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::GetTangent(double pa,TPGeLine2D&line) const
|
|
{
|
|
GetSegment(Pa2Seg(pa),line);
|
|
line.Normalize();
|
|
}
|
|
|
|
void TGMLine2D::Reverse()
|
|
{
|
|
if (Is(CLOSED_CURVE))
|
|
{
|
|
points.Reverse(1);
|
|
}
|
|
else
|
|
{
|
|
points.Reverse();
|
|
}
|
|
}
|
|
|
|
double TGMLine2D::Integration(double pa0,double pa1) const
|
|
{
|
|
double d = pa0-pa1;
|
|
if (DOWN_ZERO(d))
|
|
{
|
|
long seg0 = Pa2Seg(pa0),seg1 = Pa2Seg(pa1);
|
|
TPGeGLineSeg2D seg;
|
|
GetSegment(seg0,seg);
|
|
if (seg0 == seg1)
|
|
{
|
|
return seg.Integration(pa0,pa1);
|
|
}
|
|
|
|
double r = seg.Integration(pa0,1);
|
|
GetSegment(seg1,seg);
|
|
r += seg.Integration(0,pa1);
|
|
for (long i = seg0 + 1; i < seg1; i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
r += seg.AllIntegration();
|
|
}
|
|
return r;
|
|
}
|
|
else if (UP_ZERO(d))
|
|
{
|
|
Exchange(pa0,pa1);
|
|
long seg0 = Pa2Seg(pa0),seg1 = Pa2Seg(pa1);
|
|
TPGeGLineSeg2D seg;
|
|
GetSegment(seg0,seg);
|
|
if (seg0 == seg1)
|
|
{
|
|
return -seg.Integration(pa0,pa1);
|
|
}
|
|
|
|
double r = seg.Integration(pa0,1);
|
|
GetSegment(seg1,seg);
|
|
r += seg.Integration(0,pa1);
|
|
for (long i = seg0 + 1; i < seg1; i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
r += seg.AllIntegration();
|
|
}
|
|
return -r;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
double TGMLine2D::Length() const
|
|
{
|
|
double len = 0;
|
|
long last = points.GetLastIndex();
|
|
for (long i = 0;i < last; i++)
|
|
{
|
|
len += Distance2D(points.GetAt(i),points.GetAt(i + 1));
|
|
}
|
|
if (Is(CLOSED_CURVE))
|
|
{
|
|
len += Distance2D(points.GetAt(last),points.GetAt(0));
|
|
}
|
|
return len;
|
|
}
|
|
|
|
void TGMLine2D::SetElev(double elev)
|
|
{
|
|
for (long i = 0;i < points.GetLength();i++)
|
|
{
|
|
points[i].z = elev;
|
|
}
|
|
}
|
|
|
|
bool TGMLine2D::GetExtend2D(TPGeExtend2D&ext) const
|
|
{
|
|
const TGPoint &pt0 = points.GetAt(0);
|
|
ext.SetRange(pt0.x,pt0.x,pt0.y,pt0.y);
|
|
for (long i = 1; i < points.GetLength(); i++)
|
|
{
|
|
const TGPoint &pt = points.GetAt(i);
|
|
ext += TPGeExtend2D(pt.x,pt.x,pt.y,pt.y);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
GRelation TGMLine2D::HitTest(const TGPoint&pt) const
|
|
{
|
|
if (IsClosed())
|
|
{
|
|
TPGeLine2D ray(TGVector2D(1,0),pt);
|
|
bool bOutside = true;
|
|
long segNum = GetSegNum();
|
|
TPGeGLineSeg2D seg;
|
|
double pa1,pa2;
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
|
|
if (seg.HitTest(pt).Is(GR_IN))
|
|
{
|
|
return GR_IN;
|
|
}
|
|
|
|
int iRet = ray.Intersect(seg,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))
|
|
{
|
|
int j = (i + 1) % segNum;
|
|
while(EQUAL_ZEROD(GetVertex(j).y-pt.y))
|
|
{
|
|
j = (j + 1) % segNum;
|
|
}
|
|
|
|
const TGPoint& pt0 = seg.GetStartPoint(), &pt1 = GetVertex(j);
|
|
if ((pt0.y > pt.y && pt1.y < pt.y) || (pt0.y < pt.y && pt1.y > pt.y))
|
|
{
|
|
bOutside = !bOutside;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return GR_IN;
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
seg.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 TGMLine2D::QuickCut(const TPGeGLine2D&line,TGObjectList&left,TGObjectList&right,TGObjectList&mid) const
|
|
{
|
|
long segNum = GetSegNum();
|
|
const TPGeLine2D &line0 = line;
|
|
TPDList<TGPa> cutList;
|
|
double pa0,pa1;
|
|
TPGeGLineSeg2D seg;
|
|
GRelation r;
|
|
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
int iRet = line0.Intersect(seg,pa0,pa1);
|
|
if (iRet == INT_1PT)
|
|
{
|
|
if (UP_ZERO(pa1) && DOWN_ZERO(pa1 - 1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
else if (EQUAL_ZERO(pa1))
|
|
{
|
|
r = line0.HitTest(GetVertex((i - 1 + segNum) % segNum));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1 = line0.HitTest(seg.GetEndPoint()).Is(GR_LEFT);
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
r = line0.HitTest(GetVertex((i - 1 + segNum) % segNum));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1;
|
|
r.AddFlag(GR_IN);
|
|
for (long j = (i + 2) % segNum; r.Is(GR_IN); j = (j + 1) % segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
line0.Pt2Pa(seg.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 TGMLine2D::QuickCut(const TPGeGLineRay2D&line,TGObjectList&left,TGObjectList&right,TGObjectList&mid) const
|
|
{
|
|
long segNum = GetSegNum();
|
|
const TPGeLine2D &line0 = line;
|
|
TPDList<TGPa> cutList;
|
|
double pa0,pa1;
|
|
TPGeGLineSeg2D seg;
|
|
GRelation r;
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
int iRet = line0.Intersect(seg,pa0,pa1);
|
|
if (iRet == INT_1PT)
|
|
{
|
|
if (UP_ZERO(pa1) && DOWN_ZERO(pa1 - 1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
else if (EQUAL_ZERO(pa1))
|
|
{
|
|
r = line0.HitTest(GetVertex((i - 1 + segNum) % segNum));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1 = line0.HitTest(seg.GetEndPoint()).Is(GR_LEFT);
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
r = line0.HitTest(GetVertex((i-1+segNum)%segNum));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1;
|
|
r.AddFlag(GR_IN);
|
|
for (long j = (i + 2) % segNum; r.Is(GR_IN); j = (j + 1) % segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
line0.Pt2Pa(seg.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 TGMLine2D::QuickCut(const TPGeGLineSeg2D&line,TGObjectList&left,TGObjectList&right,TGObjectList&mid) const
|
|
{
|
|
long segNum = GetSegNum();
|
|
const TPGeLine2D &line0 = line;
|
|
TPDList<TGPa> cutList;
|
|
double pa0,pa1;
|
|
TPGeGLineSeg2D seg;
|
|
GRelation r;
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
int iRet = line0.Intersect(seg,pa0,pa1);
|
|
if (iRet == INT_1PT)
|
|
{
|
|
if (UP_ZERO(pa1) && DOWN_ZERO(pa1 - 1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
else if (EQUAL_ZERO(pa1))
|
|
{
|
|
r = line0.HitTest(GetVertex((i - 1 + segNum) % segNum));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1 = line0.HitTest(seg.GetEndPoint()).Is(GR_LEFT);
|
|
if ((bLeft0 && !bLeft1) || (!bLeft0 && bLeft1))
|
|
{
|
|
cutList << new TGPa(pa0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_LINE)
|
|
{
|
|
r = line0.HitTest(GetVertex((i - 1 + segNum) % segNum));
|
|
if (r.IsNot(GR_IN))
|
|
{
|
|
bool bLeft0 = r.Is(GR_LEFT),bLeft1;
|
|
r.AddFlag(GR_IN);
|
|
for (long j = (i + 2) % segNum; r.Is(GR_IN); j = (j + 1) % segNum)
|
|
{
|
|
r = line0.HitTest(GetVertex(j));
|
|
}
|
|
bLeft1 = r.Is(GR_LEFT);
|
|
line0.Pt2Pa(seg.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());
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::QuickCut(const TPGeCircle2D&circle,TGObjectList&left,TGObjectList&right) const
|
|
{
|
|
TPDList<TGPtPa> cutList;
|
|
TGObjectList oList;
|
|
double pa[2],cpa;
|
|
TGPoint pt;
|
|
long segNum = GetSegNum();
|
|
TPGeLine2D seg;
|
|
for (long i = 0; i < segNum; i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
int iRet = seg.Intersect(&circle,pa[0],pa[1]);
|
|
if (iRet == INT_2PT)
|
|
{
|
|
for (int j = 0; j < 2; j++)
|
|
{
|
|
double dpa = pa[j] - 1;
|
|
if (UP_ZERO(pa[j]) && DOWN_ZERO(dpa))
|
|
{
|
|
seg.Pa2Pt(pa[j],pt);
|
|
circle.Pt2Pa(pt,cpa);
|
|
cutList << new TGPtPa(pt,cpa);
|
|
}
|
|
else if (EQUAL_ZERO(dpa))
|
|
{
|
|
seg.Pa2Pt(1,pt);
|
|
TGVector2D vt;
|
|
TGVector2D(circle.center,pt).GetLVertVector(vt);
|
|
TPGeLine2D line(vt,pt);
|
|
bool bLeft1 = line.HitTest(GetVertex(i)).Is(GR_LEFT);
|
|
bool bLeft2 = line.HitTest(GetVertex((i + 2) % segNum)).Is(GR_LEFT);
|
|
if ((bLeft1 && !bLeft2) || (!bLeft1 && bLeft2))
|
|
{
|
|
circle.Pt2Pa(pt,cpa);
|
|
cutList << new TGPtPa(pt,cpa);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_1PT)
|
|
{
|
|
double dpa = pa[0] - 1;
|
|
if (EQUAL_ZERO(dpa))
|
|
{
|
|
seg.Pa2Pt(1,pt);
|
|
TGVector2D vt;
|
|
TGVector2D(circle.center,pt).GetLVertVector(vt);
|
|
TPGeLine2D line(vt,pt);
|
|
if (line.HitTest(GetVertex((i + 2) % segNum)).Is(GR_LEFT))
|
|
{
|
|
circle.Pt2Pa(pt,cpa);
|
|
cutList << new TGPtPa(pt,cpa);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (cutList.IsEmpty())
|
|
{
|
|
if (HitTest(circle.center).Is(GR_INSIDE))
|
|
{
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GRelation r = circle.HitTest(GetVertex(i));
|
|
if (r.Is(GR_OUTSIDE))
|
|
{
|
|
left << new TPGeCircle2D(circle);
|
|
}
|
|
else if (r.Is(GR_INSIDE))
|
|
{
|
|
right << new TPGeCircle2D(circle);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
right << new TPGeCircle2D(circle);
|
|
return;
|
|
}
|
|
cutList.Arrange();
|
|
GRelation r = GR_IN;
|
|
double pa0 = cutList(cutList.GetLastIndex()).pa;
|
|
double aLen = ALEN(pa0,cutList(0).pa);
|
|
for (i = 2; i < 100000 && r.Is(GR_IN); i++)
|
|
{
|
|
circle.Pa2Pt(pa0 + aLen / i, pt);
|
|
r = HitTest(pt);
|
|
}
|
|
|
|
bool bOut = r.Is(GR_OUTSIDE);
|
|
cutList.MoveToFirst();
|
|
pa0 = cutList.GetCurPData().pa;
|
|
bOut = !bOut;
|
|
|
|
bool bUnclock = !circle.IsClockwise();
|
|
for (cutList.MoveToNext();!cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
double pa1 = cutList.GetCurPData().pa;
|
|
if (bOut)
|
|
{
|
|
right << new TPGeArc2D(circle.center, circle.r, pa0, pa1 - pa0, bUnclock);
|
|
}
|
|
else
|
|
{
|
|
left << new TPGeArc2D(circle.center, circle.r, pa0, pa1 - pa0, bUnclock);
|
|
}
|
|
pa0 = pa1;
|
|
bOut = !bOut;
|
|
}
|
|
cutList.MoveToFirst();
|
|
double pa1 = cutList.GetCurPData().pa;
|
|
if (bOut)
|
|
{
|
|
right << new TPGeArc2D(circle.center, circle.r, pa0, ALEN(pa0,pa1), bUnclock);
|
|
}
|
|
else
|
|
{
|
|
left << new TPGeArc2D(circle.center, circle.r, pa0, ALEN(pa0,pa1), bUnclock);
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::QuickCut(const TPGeArc2D&arc,TGObjectList&left,TGObjectList&right) const
|
|
{
|
|
TPDList<TGPtPa> cutList;
|
|
TGObjectList oList;
|
|
double pa[2],cpa;
|
|
TGPoint pt;
|
|
long segNum = GetSegNum();
|
|
TPGeLine2D seg;
|
|
const TPGeCircle2D &circle = arc.circle;
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GetSegment(i,seg);
|
|
int iRet = seg.Intersect(&circle,pa[0],pa[1]);
|
|
if (iRet == INT_2PT)
|
|
{
|
|
for (int j = 0;j < 2;j++)
|
|
{
|
|
double dpa = pa[j] - 1;
|
|
if (UP_ZERO(pa[j]) && DOWN_ZERO(dpa))
|
|
{
|
|
seg.Pa2Pt(pa[j],pt);
|
|
arc.Pt2Pa(pt,cpa);
|
|
cutList << new TGPtPa(pt,cpa);
|
|
}
|
|
else if (EQUAL_ZERO(dpa))
|
|
{
|
|
seg.Pa2Pt(1,pt);
|
|
TGVector2D vt;
|
|
TGVector2D(circle.center,pt).GetLVertVector(vt);
|
|
TPGeLine2D line(vt,pt);
|
|
bool bLeft1 = line.HitTest(GetVertex(i)).Is(GR_LEFT);
|
|
bool bLeft2 = line.HitTest(GetVertex((i + 2) % segNum)).Is(GR_LEFT);
|
|
if ((bLeft1 && !bLeft2) || (!bLeft1 && bLeft2))
|
|
{
|
|
arc.Pt2Pa(pt,cpa);
|
|
cutList << new TGPtPa(pt,cpa);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (iRet == INT_1PT)
|
|
{
|
|
double dpa = pa[0] - 1;
|
|
if (EQUAL_ZERO(dpa))
|
|
{
|
|
seg.Pa2Pt(1,pt);
|
|
TGVector2D vt;
|
|
TGVector2D(circle.center,pt).GetLVertVector(vt);
|
|
TPGeLine2D line(vt,pt);
|
|
if (line.HitTest(GetVertex((i + 2) % segNum)).Is(GR_LEFT))
|
|
{
|
|
arc.Pt2Pa(pt,cpa);
|
|
cutList << new TGPtPa(pt,cpa);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (cutList.IsEmpty())
|
|
{
|
|
if (HitTest(circle.center).Is(GR_INSIDE))
|
|
{
|
|
for (long i = 0;i < segNum;i++)
|
|
{
|
|
GRelation r = circle.HitTest(GetVertex(i));
|
|
if (r.Is(GR_OUTSIDE))
|
|
{
|
|
left << new TPGeArc2D(arc);
|
|
}
|
|
else if (r.Is(GR_INSIDE))
|
|
{
|
|
right << new TPGeArc2D(arc);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
right << new TPGeArc2D(arc);
|
|
return;
|
|
}
|
|
|
|
cutList.Arrange();
|
|
GRelation r = GR_IN;
|
|
double pa0 = cutList(cutList.GetLastIndex()).pa;
|
|
double aLen = pa0-cutList(0).pa;
|
|
for (i = 2;i < 100000 && r.Is(GR_IN);i++)
|
|
{
|
|
arc.Pa2Pt(pa0 + aLen / i, pt);
|
|
r = HitTest(pt);
|
|
}
|
|
|
|
bool bOut = r.Is(GR_OUTSIDE);
|
|
bool bUnclock = !circle.IsClockwise();
|
|
pa0 = 0;
|
|
cutList.MoveToFirst();
|
|
double pa1 = cutList.GetCurPData().pa;
|
|
|
|
if (EQUAL_ZERO(pa1))
|
|
{
|
|
bOut = !bOut;
|
|
cutList.MoveToNext();
|
|
}
|
|
for (bool bContinue = true;bContinue && !cutList.IsOut();cutList.MoveToNext())
|
|
{
|
|
pa1 = cutList.GetCurPData().pa;
|
|
if (UPEQUAL_ZERO(pa1-1))
|
|
{
|
|
pa1 = 1;
|
|
bContinue = false;
|
|
}
|
|
if (bOut)
|
|
{
|
|
right << new TPGeArc2D(circle.center, circle.r, NA(arc.startAngle + pa0 * arc.centralAngle),
|
|
(pa1 - pa0) * arc.centralAngle, bUnclock);
|
|
}
|
|
else
|
|
{
|
|
left << new TPGeArc2D(circle.center, circle.r, NA(arc.startAngle + pa0 * arc.centralAngle),
|
|
(pa1 - pa0) * arc.centralAngle, bUnclock);
|
|
}
|
|
pa0 = pa1;
|
|
bOut = !bOut;
|
|
}
|
|
if (bContinue)
|
|
{
|
|
pa1 = 1;
|
|
if (bOut)
|
|
{
|
|
right << new TPGeArc2D(circle.center, circle.r, NA(arc.startAngle + pa0 * arc.centralAngle),
|
|
ALEN(pa0 * arc.centralAngle, pa1 * arc.centralAngle), bUnclock);
|
|
}
|
|
else
|
|
{
|
|
left << new TPGeArc2D(circle.center, circle.r,NA(arc.startAngle + pa0 * arc.centralAngle),
|
|
ALEN(pa0 * arc.centralAngle, pa1 * arc.centralAngle), bUnclock);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TGMLine2D::TransformBy(const TGMatrix& pMatrix)
|
|
{
|
|
for (long i = 0; i < points.GetLength(); i++)
|
|
{
|
|
pMatrix.Transform2D(points[i]);
|
|
}
|
|
}
|
|
|
|
bool TGMLine2D::Explode(TGObjectList&res) const
|
|
{
|
|
long last = points.GetLastIndex();
|
|
for (long i = 0;i < last;i++)
|
|
{
|
|
res << new TPGeGLineSeg2D(points.GetAt(i),points.GetAt(i + 1));
|
|
}
|
|
if (Is(CLOSED_CURVE))
|
|
{
|
|
res << new TPGeGLineSeg2D(points.GetAt(last),points.GetAt(0));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGMLine2D::IsInclude(const TGObject&obj) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLine2D:
|
|
case CID_GLineRay2D:
|
|
case CID_GCircle2D:
|
|
case CID_GArc2D:
|
|
return false;
|
|
case CID_GLineSeg2D:
|
|
{
|
|
const TPGeGLineSeg2D&seg = (const TPGeGLineSeg2D&)obj;
|
|
TGObjectList oList,oList1;
|
|
Explode(oList);
|
|
seg.SubtractBy(oList,oList1);
|
|
return oList1.IsEmpty();
|
|
}
|
|
default:
|
|
return TPGeCurve2D::IsInclude(obj);
|
|
}
|
|
}
|
|
|
|
bool TGMLine2D::IsValid() const
|
|
{
|
|
if (points.GetLength() < 2)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
long last = points.GetLastIndex();
|
|
for (long i = 0;i < last;i++)
|
|
{
|
|
if (points.GetAt(i) == points.GetAt(i+1))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (Is(CLOSED_CURVE))
|
|
{
|
|
return points.GetAt(last) != points.GetAt(0);
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool TGMLine2D::RemoveDupPoint()
|
|
{
|
|
if (points.GetLength() < 2)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TList<TGPoint> ptList;
|
|
ptList.AddTail(points.GetAt(0));
|
|
|
|
for (long i = 1; i < points.GetLength(); i++)
|
|
{
|
|
if (ptList.GetCurData() != points.GetAt(i))
|
|
{
|
|
ptList.AddTail(points.GetAt(i));
|
|
}
|
|
}
|
|
if (Is(CLOSED_CURVE) && ptList.GetLength() > 1 && points.GetAt(0) == ptList.GetCurData())
|
|
{
|
|
ptList.DelCur();
|
|
}
|
|
if (ptList.GetLength() < 2)
|
|
{
|
|
return false;
|
|
}
|
|
if (ptList.GetLength()<points.GetLength())
|
|
{
|
|
points = ptList;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGMLine2D::ExplodeSelfcross(TGObjectList&oList) const
|
|
{
|
|
long num = GetSegNum();
|
|
if (num < 2)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
TGObjectList oList1;
|
|
TPGeGLineSeg2D iSeg,jSeg;
|
|
long num1 = num - 1;
|
|
for (long i = 0;i < num1;i++)
|
|
{
|
|
GetSegment(i,iSeg);
|
|
for (long j = i + 1; j < num; j++)
|
|
{
|
|
GetSegment(j,jSeg);
|
|
if (iSeg.Intersect(jSeg,oList1))
|
|
{
|
|
if (oList1[0]->GetClassID() == CID_GLineSeg2D)
|
|
{
|
|
if (num == 2)
|
|
{
|
|
oList << new TPGeGLineSeg2D(iSeg) << new TPGeGLineSeg2D(jSeg);
|
|
}
|
|
else
|
|
{
|
|
const TPGeGLineSeg2D& seg = (const TPGeGLineSeg2D&)(oList1.GetCurPData());
|
|
|
|
long jNum = j - i;
|
|
long iNum = GetVertexNum()-jNum;
|
|
if (iSeg.GetStartPoint() == jSeg.GetEndPoint())
|
|
{
|
|
iNum--;
|
|
}
|
|
|
|
TGMLine2D *pmli = new TGMLine2D(iNum,Is(CLOSED_CURVE));
|
|
TGMLine2D *pmlj = new TGMLine2D(jNum,true);
|
|
long iCount = 0,jCount = 0,count = 0;
|
|
|
|
if (iNum == 0)
|
|
{
|
|
count = 1;
|
|
}
|
|
else
|
|
{
|
|
while(count <= i)
|
|
{
|
|
(*pmli)[iCount++] = points.GetAt(count++);
|
|
}
|
|
}
|
|
|
|
while(count <= j)
|
|
{
|
|
(*pmlj)[jCount++] = points.GetAt(count++);
|
|
}
|
|
if (GetVertexNum()>iNum+jNum)
|
|
{
|
|
count++;
|
|
}
|
|
while(count<GetVertexNum())
|
|
{
|
|
(*pmli)[iCount++] = points.GetAt(count++);
|
|
}
|
|
|
|
if (iNum > 1 && !pmli->ExplodeSelfcross(oList))
|
|
{
|
|
oList << pmli;
|
|
}
|
|
else
|
|
{
|
|
delete pmli;
|
|
}
|
|
if (jNum > 1 && !pmlj->ExplodeSelfcross(oList))
|
|
{
|
|
oList << pmlj;
|
|
}
|
|
else
|
|
{
|
|
delete pmlj;
|
|
}
|
|
oList << new TPGeGLineSeg2D(iSeg) << new TPGeGLineSeg2D(jSeg);
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if (j == (i+1) || (i == 0 && j == num1 && Is(CLOSED_CURVE)))
|
|
{
|
|
oList1.Clear();
|
|
}
|
|
else
|
|
{
|
|
const TGPoint2D& pt = (const TGPoint2D&)(oList1.GetCurPData());
|
|
|
|
long jNum = j - i + 1;
|
|
long iNum = GetVertexNum() - jNum + 2;
|
|
bool bjEndPoint = (pt == jSeg.GetEndPoint());
|
|
bool biStartPoint = (pt == iSeg.GetStartPoint());
|
|
bool biEndPoint = (pt == iSeg.GetEndPoint());
|
|
if (bjEndPoint)
|
|
{
|
|
iNum--;
|
|
}
|
|
if (biStartPoint)
|
|
{
|
|
iNum--;
|
|
}
|
|
if (biEndPoint)
|
|
{
|
|
jNum--;
|
|
}
|
|
|
|
TGMLine2D *pmli = new TGMLine2D(iNum,Is(CLOSED_CURVE));
|
|
TGMLine2D *pmlj = new TGMLine2D(jNum,true);
|
|
long iCount = 0,jCount = 0,count = 0;
|
|
while(count <= i)
|
|
{
|
|
(*pmli)[iCount++] = points.GetAt(count++);
|
|
}
|
|
if (!biStartPoint)
|
|
{
|
|
(*pmli)[iCount++] = pt;
|
|
}
|
|
if (!biEndPoint)
|
|
{
|
|
(*pmlj)[jCount++] = pt;
|
|
}
|
|
while(count <= j)
|
|
{
|
|
(*pmlj)[jCount++] = points.GetAt(count++);
|
|
}
|
|
if (count<GetVertexNum())
|
|
{
|
|
if (!bjEndPoint)
|
|
{
|
|
(*pmli)[iCount++] = points.GetAt(count);
|
|
}
|
|
count++;
|
|
while(count<GetVertexNum())
|
|
{
|
|
(*pmli)[iCount++] = points.GetAt(count++);
|
|
}
|
|
}
|
|
|
|
if (iNum > 1 && !pmli->ExplodeSelfcross(oList))
|
|
{
|
|
oList << pmli;
|
|
}
|
|
else
|
|
{
|
|
delete pmli;
|
|
}
|
|
if (jNum > 1 && !pmlj->ExplodeSelfcross(oList))
|
|
{
|
|
oList << pmlj;
|
|
}
|
|
else
|
|
{
|
|
delete pmlj;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TGMLine2D::Offset(double offset)
|
|
{
|
|
TArray<TPGeLine2D> lines(GetSegNum());
|
|
for (long i = 0;i < lines.GetLength();i++)
|
|
{
|
|
GetSegment(i,lines[i]);
|
|
lines[i].Offset(offset);
|
|
}
|
|
|
|
TArray<TGPoint> newPt(GetVertexNum());
|
|
for (i = 1;i < lines.GetLength();i++)
|
|
{
|
|
TPGeLine2D& line0 = lines[i - 1];
|
|
TPGeLine2D& line1 = lines[i];
|
|
int iRet = line0.Intersect(line1,newPt[i]);
|
|
if (iRet == INT_LINE)
|
|
{
|
|
newPt[i] = line1.basePoint;
|
|
}
|
|
else if (iRet == INT_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (IsClosed())
|
|
{
|
|
int iRet = lines[i-1].Intersect(lines[0],newPt[0]);
|
|
if (iRet == INT_LINE)
|
|
{
|
|
newPt[0] = lines[0].basePoint;
|
|
}
|
|
else if (iRet == INT_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
newPt[0] = lines[0].basePoint;
|
|
newPt[newPt.GetLastIndex()] = lines[i - 1].basePoint + lines[i - 1];
|
|
}
|
|
points = newPt;
|
|
return true;
|
|
}
|
|
|
|
bool TGMLine2D::OffsetSeg(long iSeg,double offset)
|
|
{
|
|
TArray<TPGeLine2D> lines(GetSegNum());
|
|
for (long i = 0; i < lines.GetLength();i++)
|
|
{
|
|
GetSegment(i,lines[i]);
|
|
if (i == iSeg)
|
|
{
|
|
lines[i].Offset(offset);
|
|
}
|
|
}
|
|
|
|
TArray<TGPoint> newPt(points);
|
|
for (i = 1;i < lines.GetLength();i++)
|
|
{
|
|
if (i != iSeg && i != iSeg + 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
TPGeLine2D& line0 = lines[i - 1];
|
|
TPGeLine2D& line1 = lines[i];
|
|
int iRet = line0.Intersect(line1,newPt[i]);
|
|
if (iRet == INT_LINE)
|
|
{
|
|
newPt[i] = line1.basePoint;
|
|
}
|
|
else if (iRet == INT_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
if (IsClosed())
|
|
{
|
|
if (iSeg == i - 1 || iSeg == 0)
|
|
{
|
|
int iRet = lines[i-1].Intersect(lines[0],newPt[0]);
|
|
if (iRet == INT_LINE)
|
|
{
|
|
newPt[0]=lines[0].basePoint;
|
|
}
|
|
else if (iRet == INT_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
else if (iSeg == 0)
|
|
{
|
|
newPt[0] = lines[0].basePoint;
|
|
}
|
|
else if (iSeg == i - 1)
|
|
{
|
|
newPt[newPt.GetLastIndex()] = lines[i - 1].basePoint + lines[i - 1];
|
|
}
|
|
points = newPt;
|
|
return true;
|
|
} |