565 lines
9.6 KiB
C++
565 lines
9.6 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TGMCurve2D 类
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TGMCurve2D 定义
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TGMCurve2D.h"
|
|
#include "TGPoint2D.h"
|
|
#include "TSPTable.h"
|
|
#include "TGMLine2D.h"
|
|
|
|
IMPLEMENT_RUN_TIME_CLASS1(TGMCurve2D,"TGMCurve2D",TPGeCurve2D)
|
|
|
|
TGMCurve2D::TGMCurve2D()
|
|
{
|
|
|
|
}
|
|
|
|
TGMCurve2D::TGMCurve2D(const TPGeCurve2D&curve)
|
|
{
|
|
AddTail((TPGeCurve2D*)(curve.Clone()));
|
|
}
|
|
|
|
TGMCurve2D::~TGMCurve2D()
|
|
{
|
|
|
|
}
|
|
|
|
TGPoint TGMCurve2D::GetSamplePoint() const
|
|
{
|
|
return GetAt(0)->GetSamplePoint();
|
|
}
|
|
|
|
double TGMCurve2D::GetElev() const
|
|
{
|
|
return GetAt(0)->GetElev();
|
|
}
|
|
|
|
TGObject* TGMCurve2D::Clone() const
|
|
{
|
|
return new TGMCurve2D(*this);
|
|
}
|
|
|
|
long TGMCurve2D::GetSegNum() const
|
|
{
|
|
return GetLength();
|
|
}
|
|
|
|
TGMCurve2D::TGMCurve2D(const TGMCurve2D&curve)
|
|
{
|
|
for (TPGeCurve2D*const* p = curve.GetFirst();p != NULL;p = curve.GetNext(p))
|
|
{
|
|
AddTail((TPGeCurve2D*)((*p)->Clone()));
|
|
}
|
|
}
|
|
|
|
bool TGMCurve2D::IsValid() const
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const TPGeCurve2D* pSeg0 = GetAt(0);
|
|
if (pSeg0 == NULL || !pSeg0->IsValid())
|
|
{
|
|
return false;
|
|
}
|
|
for (long i = 1;i<GetSegNum();i++)
|
|
{
|
|
const TPGeCurve2D*pSeg = GetAt(i);
|
|
if (pSeg == NULL || !pSeg->IsValid())
|
|
{
|
|
return false;
|
|
}
|
|
if (!pSeg0->IsConnect(*pSeg))
|
|
{
|
|
return false;
|
|
}
|
|
pSeg0 = pSeg;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGMCurve2D::IsClosed() const
|
|
{
|
|
if (IsCurveSeg())
|
|
{
|
|
return TPGeCurve2D::IsClosed();
|
|
}
|
|
else if (GetSegNum() == 1)
|
|
{
|
|
return GetAt(0)->IsClosed();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool TGMCurve2D::IsFinite(bool bStart) const
|
|
{
|
|
if (bStart)
|
|
{
|
|
return GetAt(0)->IsFinite(true);
|
|
}
|
|
else
|
|
{
|
|
return GetAt(GetLastIndex())->IsFinite(false);
|
|
}
|
|
}
|
|
|
|
bool TGMCurve2D::IsSelfCross() const
|
|
{
|
|
if (GetLength() == 1)
|
|
{
|
|
return GetAt(0)->IsSelfCross();
|
|
}
|
|
|
|
TArray<TPGeCurve2D*> segs(GetSegNum());
|
|
long i = 0;
|
|
for (TPGeCurve2D*const*p = GetFirst();p != NULL;p = GetNext(p),i++)
|
|
{
|
|
if ((*p)->IsClosed() || (*p)->IsSelfCross())
|
|
{
|
|
return true;
|
|
}
|
|
segs[i] = (*p);
|
|
}
|
|
|
|
bool bClosed = IsClosed();
|
|
for (i = 0;i<GetLength();i++)
|
|
{
|
|
TPGeCurve2D*pSegi = segs[i];
|
|
for (long j = i+1;j<GetLength();j++)
|
|
{
|
|
TPGeCurve2D*pSegj = segs[j];
|
|
TGObjectList oList;
|
|
if (pSegi->Intersect(*pSegj,oList))
|
|
{
|
|
for (oList.MoveToFirst();!oList.IsOut();oList.MoveToNext())
|
|
{
|
|
if (!IS_TYPE(oList.GetCurData(),TGPoint2D))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
if (oList.GetLength()>2)
|
|
{
|
|
return true;
|
|
}
|
|
else if (oList.GetLength() == 2)
|
|
{
|
|
if (!(GetLength() == 2 && bClosed))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(j == i+1 || (i == 0 && j == GetLastIndex() && bClosed)))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
long TGMCurve2D::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* TGMCurve2D::GetSubCurve(double pa0,double pa1) const
|
|
{
|
|
if (GetSegNum() == 1)
|
|
{
|
|
return GetAt(0)->GetSubCurve(pa0,pa1);
|
|
}
|
|
|
|
TGMCurve2D *pMC = new TGMCurve2D;
|
|
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 = GetAt(iSeg0),*pSeg1 = GetAt(iSeg1);
|
|
if (iSeg0 == iSeg1)
|
|
{
|
|
pMC->AddTail(pSeg0->GetSubCurve(pa0,pa1));
|
|
}
|
|
else
|
|
{
|
|
if (DOWN_ZERO(pa0-1))
|
|
{
|
|
pMC->AddTail(pSeg0->GetSubCurve(pa0,1));
|
|
}
|
|
for (long i = iSeg0+1;i<iSeg1;i++)
|
|
{
|
|
pMC->AddTail((TPGeCurve2D*)(GetAt(i)->Clone()));
|
|
}
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
pMC->AddTail(pSeg1->GetSubCurve(0,pa1));
|
|
}
|
|
}
|
|
}
|
|
else if (DOWN_ZERO(pa1-pa0))
|
|
{
|
|
long iSeg0 = Pa2Seg(pa0),iSeg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D *pSeg0 = GetAt(iSeg0),*pSeg1 = GetAt(iSeg1);
|
|
if (DOWN_ZERO(pa0-1))
|
|
{
|
|
pMC->AddTail(pSeg0->GetSubCurve(pa0,1));
|
|
}
|
|
for (long i = iSeg0+1;i<GetSegNum();i++)
|
|
{
|
|
pMC->AddTail((TPGeCurve2D*)(GetAt(i)->Clone()));
|
|
}
|
|
for (i = 0;i<iSeg1;i++)
|
|
{
|
|
pMC->AddTail((TPGeCurve2D*)(GetAt(i)->Clone()));
|
|
}
|
|
if (UP_ZERO(pa1))
|
|
{
|
|
pMC->AddTail(pSeg1->GetSubCurve(0,pa1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
long iSeg = Pa2Seg(pa0);
|
|
TPGeCurve2D* pSeg = GetAt(iSeg);
|
|
if (DOWN_ZERO(pa0-1))
|
|
{
|
|
pMC->AddTail(pSeg->GetSubCurve(pa0,1));
|
|
}
|
|
for (long i = iSeg+1;i<GetSegNum();i++)
|
|
{
|
|
pMC->AddTail((TPGeCurve2D*)(GetAt(i)->Clone()));
|
|
}
|
|
for (i = 0;i<iSeg;i++)
|
|
{
|
|
pMC->AddTail((TPGeCurve2D*)(GetAt(i)->Clone()));
|
|
}
|
|
if (UP_ZERO(pa0))
|
|
{
|
|
pMC->AddTail(pSeg->GetSubCurve(0,pa0));
|
|
}
|
|
}
|
|
|
|
if (pMC->GetSegNum() == 1)
|
|
{
|
|
TPGeCurve2D *pSeg = pMC->Fetch(0);
|
|
delete pMC;
|
|
return pSeg;
|
|
}
|
|
else
|
|
{
|
|
return pMC;
|
|
}
|
|
}
|
|
|
|
void TGMCurve2D::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);
|
|
GetAt(i)->Pa2Pt(pa,pt);
|
|
}
|
|
}
|
|
|
|
void TGMCurve2D::GetStartPoint(TGPoint&pt) const
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetAt(0)->GetStartPoint(pt);
|
|
}
|
|
|
|
void TGMCurve2D::GetEndPoint(TGPoint &pt) const
|
|
{
|
|
if (IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
GetAt(GetLastIndex())->GetEndPoint(pt);
|
|
}
|
|
|
|
void TGMCurve2D::Pt2Pa(const TGPoint&pt,double&pa) const
|
|
{
|
|
pa = -1;
|
|
long i = 0;
|
|
for (TPGeCurve2D*const*p = GetFirst();p != NULL;p = GetNext(p),i++)
|
|
{
|
|
if ((*p)->HitTest(pt).Is(GR_IN))
|
|
{
|
|
(*p)->Pt2Pa(pt,pa);
|
|
pa = (pa+i)/GetSegNum();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TGMCurve2D::GetTangent(double pa,TPGeLine2D&line) const
|
|
{
|
|
long i = Pa2Seg(pa);
|
|
GetAt(i)->GetTangent(pa,line);
|
|
}
|
|
|
|
void TGMCurve2D::Reverse()
|
|
{
|
|
for (MoveToFirst();!IsOut();MoveToNext())
|
|
{
|
|
GetCurData()->Reverse();
|
|
}
|
|
ReverseList();
|
|
}
|
|
|
|
double TGMCurve2D::Integration(double pa0,double pa1) const
|
|
{
|
|
double d = pa0-pa1;
|
|
if (DOWN_ZERO(d))
|
|
{
|
|
long seg0 = Pa2Seg(pa0),seg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D*pSeg = GetAt(seg0);
|
|
if (seg0 == seg1)
|
|
{
|
|
return pSeg->Integration(pa0,pa1);
|
|
}
|
|
|
|
double r = pSeg->Integration(pa0,1);
|
|
pSeg = GetAt(seg1);
|
|
r += pSeg->Integration(0,pa1);
|
|
for (long i = seg0+1;i<seg1;i++)
|
|
{
|
|
pSeg = GetAt(i);
|
|
r += pSeg->AllIntegration();
|
|
}
|
|
return r;
|
|
}
|
|
else if (UP_ZERO(d))
|
|
{
|
|
TchPrivate::Exchange(pa0,pa1);
|
|
long seg0 = Pa2Seg(pa0),seg1 = Pa2Seg(pa1);
|
|
TPGeCurve2D*pSeg = GetAt(seg0);
|
|
if (seg0 == seg1)
|
|
{
|
|
return -pSeg->Integration(pa0,pa1);
|
|
}
|
|
|
|
double r = pSeg->Integration(pa0,1);
|
|
pSeg = GetAt(seg1);
|
|
r += pSeg->Integration(0,pa1);
|
|
for (long i = seg0+1;i<seg1;i++)
|
|
{
|
|
pSeg = GetAt(i);
|
|
r += pSeg->AllIntegration();
|
|
}
|
|
return -r;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
TGMLine2D* TGMCurve2D::MLinearize(double paDist) const
|
|
{
|
|
if (!TPGeCurve2D::IsFinite())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
TList<TGPoint> ptList;
|
|
TGMLine2D* pML;
|
|
long i;
|
|
for (TPGeCurve2D*const*p = GetFirst();p != NULL;p = GetNext(p))
|
|
{
|
|
pML = (*p)->MLinearize(paDist);
|
|
long num = pML->GetSegNum();
|
|
for (i = 0;i<num;i++)
|
|
{
|
|
ptList<<(*pML)[i];
|
|
}
|
|
delete pML;
|
|
}
|
|
bool bClosed = IsClosed();
|
|
if (!bClosed)
|
|
{
|
|
TGPoint2D pt;
|
|
GetAt(GetLastIndex())->GetEndPoint(pt);
|
|
ptList<<pt;
|
|
}
|
|
return new TGMLine2D(ptList,bClosed);
|
|
}
|
|
|
|
TGMLine2D* TGMCurve2D::PLinearize(double paDist) const
|
|
{
|
|
if (!TPGeCurve2D::IsFinite())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
TSPTable<TGMLine2D> plines(GetSegNum());
|
|
long count = 0;
|
|
bool bArcExist = false;
|
|
for (TPGeCurve2D*const* p = GetFirst();p != NULL;p = GetNext(p))
|
|
{
|
|
TGMLine2D* pMLine = (*p)->PLinearize(paDist);
|
|
if (pMLine == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
count += pMLine->GetSegNum();
|
|
if (IS_CLASS(pMLine,TGPLine2D))
|
|
{
|
|
bArcExist = true;
|
|
}
|
|
plines.AddTail(pMLine);
|
|
}
|
|
bool bClosed = IsClosed();
|
|
if (!bClosed)
|
|
{
|
|
count++;
|
|
}
|
|
|
|
if (bArcExist)
|
|
{
|
|
TGPLine2D *pRes = new TGPLine2D(count,bClosed);
|
|
count = 0;
|
|
for (long i = 0;i<plines.GetLength();i++)
|
|
{
|
|
TGMLine2D*pLine = plines[i];
|
|
if (IS_CLASS(pLine,TGPLine2D))
|
|
{
|
|
TGPLine2D *pLine1 = (TGPLine2D*)pLine;
|
|
for (long j = 0;j<pLine1->GetSegNum();j++)
|
|
{
|
|
(*pRes)[count] = (*pLine1)[j];
|
|
(*pRes)(count++) = (*pLine1)(j);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (long j = 0;j<pLine->GetSegNum();j++)
|
|
{
|
|
(*pRes)[count++] = (*pLine)[j];
|
|
}
|
|
}
|
|
}
|
|
if (!bClosed)
|
|
{
|
|
GetEndPoint((*pRes)[count]);
|
|
}
|
|
return pRes;
|
|
}
|
|
else
|
|
{
|
|
TGMLine2D *pRes = new TGMLine2D(count,bClosed);
|
|
count = 0;
|
|
for (long i = 0;i<plines.GetLength();i++)
|
|
{
|
|
TGMLine2D*pLine = plines[i];
|
|
|
|
for (long j = 0;j<pLine->GetSegNum();j++)
|
|
{
|
|
(*pRes)[count++] = (*pLine)[j];
|
|
}
|
|
}
|
|
if (!bClosed)
|
|
{
|
|
GetEndPoint((*pRes)[count]);
|
|
}
|
|
return pRes;
|
|
}
|
|
}
|
|
|
|
void TGMCurve2D::SetElev(double elev)
|
|
{
|
|
for (MoveToFirst();!IsOut();MoveToNext())
|
|
{
|
|
GetCurData()->SetElev(elev);
|
|
}
|
|
}
|
|
|
|
void TGMCurve2D::TransformBy(const TGMatrix&matrix)
|
|
{
|
|
for (MoveToFirst();!IsOut();MoveToNext())
|
|
{
|
|
GetCurData()->TransformBy(matrix);
|
|
}
|
|
}
|
|
|
|
bool TGMCurve2D::Explode(TGObjectList&res) const
|
|
{
|
|
for (TPGeCurve2D*const* p = GetFirst();p != NULL;p = GetNext(p))
|
|
{
|
|
res << (*p)->Clone();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TGMCurve2D::IsInclude(const TGObject&obj) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLine2D:
|
|
case CID_GLineRay2D:
|
|
return false;
|
|
case CID_GLineSeg2D:
|
|
{
|
|
const TPGeGLineSeg2D&seg = (const TPGeGLineSeg2D&)obj;
|
|
TGObjectList oList,oList1;
|
|
ExplodeEx(oList);
|
|
seg.SubtractBy(oList,oList1);
|
|
return oList1.IsEmpty();
|
|
}
|
|
case CID_GCircle2D:
|
|
case CID_GArc2D:
|
|
return false;
|
|
default:
|
|
return TPGeCurve2D::IsInclude(obj);
|
|
}
|
|
}
|
|
|
|
bool TGMCurve2D::Offset(double offset)
|
|
{
|
|
return false;
|
|
} |