459 lines
8.4 KiB
C++
459 lines
8.4 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TPGeCircle2D 类
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TPGeCircle2D 定义
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TPGeCircle2D.h"
|
|
#include "TGPoint2D.h"
|
|
#include "TPGeGLine2D.h"
|
|
#include "TPGeGLineRay2D.h"
|
|
// #include "TchGeLib.h"
|
|
|
|
double TPGeCircle2D::g_fMLinePreci = 0.1;
|
|
IMPLEMENT_RUN_TIME_CLASS1(TPGeCircle2D,"TPGeCircle2D",TPGeCurve2D)
|
|
|
|
TPGeCircle2D::TPGeCircle2D(bool bUnclock/* = true*/)
|
|
{
|
|
if (!bUnclock)
|
|
{
|
|
AddFlag(CLOCKWISE_CURVE);
|
|
}
|
|
}
|
|
|
|
TPGeCircle2D::TPGeCircle2D(const TGPoint& pt,double r,bool bUnclock/* = true*/):TPGeCircle(pt,r)
|
|
{
|
|
if (!bUnclock)
|
|
{
|
|
AddFlag(CLOCKWISE_CURVE);
|
|
}
|
|
}
|
|
|
|
TPGeCircle2D::TPGeCircle2D(const TPGeCircle& circle,bool bUnclock/* = true*/):TPGeCircle(circle)
|
|
{
|
|
if (!bUnclock)
|
|
{
|
|
AddFlag(CLOCKWISE_CURVE);
|
|
}
|
|
|
|
}
|
|
|
|
TPGeCircle2D::TPGeCircle2D(const TGPoint& pt0,const TGPoint& pt1,const TGPoint& pt2)
|
|
{
|
|
Init(pt0,pt1,pt2);
|
|
}
|
|
|
|
TPGeCircle2D::TPGeCircle2D(const TGPoint& pt0,const TGPoint& pt1,double angle)
|
|
{
|
|
Init(pt0,pt1,angle);
|
|
}
|
|
|
|
TPGeCircle2D::~TPGeCircle2D()
|
|
{
|
|
|
|
}
|
|
|
|
void TPGeCircle2D::GetTangent(double pa,TPGeLine2D&line) const
|
|
{
|
|
if (Is(CLOCKWISE_CURVE))
|
|
{
|
|
TPGeCircle::GetTangent(PI2 - pa,line);
|
|
line.Reverse();
|
|
}
|
|
else
|
|
{
|
|
TPGeCircle::GetTangent(pa,line);
|
|
}
|
|
}
|
|
|
|
void TPGeCircle2D::Pt2Pa(const TGPoint& pt,double&pa) const
|
|
{
|
|
TPGeCircle::Pt2Pa(pt,pa);
|
|
if (Is(CLOCKWISE_CURVE))
|
|
{
|
|
pa = PI2 - pa;
|
|
}
|
|
}
|
|
|
|
void TPGeCircle2D::Pa2Pt(double pa,TGPoint& pt) const
|
|
{
|
|
if (Is(CLOCKWISE_CURVE))
|
|
{
|
|
TPGeCircle::Pa2Pt(PI2-pa,pt);
|
|
}
|
|
else
|
|
{
|
|
TPGeCircle::Pa2Pt(pa,pt);
|
|
}
|
|
}
|
|
|
|
void TPGeCircle2D::SetMLinePreci(double preci)
|
|
{
|
|
g_fMLinePreci = preci;
|
|
}
|
|
|
|
void TPGeCircle2D::Reverse()
|
|
{
|
|
if (Is(CLOCKWISE_CURVE))
|
|
{
|
|
RemoveFlag(CLOCKWISE_CURVE);
|
|
}
|
|
else
|
|
{
|
|
AddFlag(CLOCKWISE_CURVE);
|
|
}
|
|
}
|
|
|
|
bool TPGeCircle2D::IsClosed() const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool TPGeCircle2D::IsFinite(bool bStart) const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool TPGeCircle2D::IsClockwise() const
|
|
{
|
|
return Is(CLOCKWISE_CURVE);
|
|
}
|
|
|
|
double TPGeCircle2D::Area() const
|
|
{
|
|
return TPGeCircle::Area();
|
|
}
|
|
|
|
double TPGeCircle2D::Length() const
|
|
{
|
|
return TPGeCircle::Length();
|
|
}
|
|
|
|
double TPGeCircle2D::GetMLinePrec() const
|
|
{
|
|
return g_fMLinePreci;
|
|
}
|
|
|
|
bool TPGeCircle2D::Offset(double offset)
|
|
{
|
|
if (IsClockwise())
|
|
{
|
|
offset = -offset;
|
|
}
|
|
return TPGeCircle::Offset(offset);
|
|
}
|
|
|
|
void TPGeCircle2D::SetElev(double elev)
|
|
{
|
|
center.z = elev;
|
|
}
|
|
|
|
double TPGeCircle2D::GetElev() const
|
|
{
|
|
return center.z;
|
|
}
|
|
|
|
bool TPGeCircle2D::IsValid() const
|
|
{
|
|
return TPGeCircle::IsValid();
|
|
}
|
|
|
|
void TPGeCircle2D::TransformBy(const TGMatrix&matrix)
|
|
{
|
|
matrix.Transform2D(center);
|
|
}
|
|
|
|
TGObject * TPGeCircle2D::Clone() const
|
|
{
|
|
return new TPGeCircle2D(*this);
|
|
}
|
|
|
|
GRelation TPGeCircle2D::HitTest(const TGPoint& pt) const
|
|
{
|
|
return TPGeCircle::HitTest(pt);
|
|
}
|
|
|
|
double TPGeCircle2D::Integration(double pa0,double pa1) const
|
|
{
|
|
if (Is(CLOCKWISE_CURVE))
|
|
{
|
|
return TPGeCircle::Integration(PI2 - pa0, PI2 - pa1);
|
|
}
|
|
else
|
|
{
|
|
return TPGeCircle::Integration(pa0, pa1);
|
|
}
|
|
}
|
|
|
|
bool TPGeCircle2D::Intersect(const TGObject& obj, TGObjectList& res) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLine2D:
|
|
{
|
|
TGPoint2D* pPt1 = new TGPoint2D, *pPt2 = new TGPoint2D;
|
|
int ret = TPGeCircle::Intersect((const TPGeGLine2D&)obj,*pPt1,*pPt2);
|
|
if (ret == INT_NULL)
|
|
{
|
|
delete pPt1;
|
|
delete pPt2;
|
|
return false;
|
|
}
|
|
else if (ret == INT_2PT)
|
|
{
|
|
res << pPt1 << pPt2;
|
|
}
|
|
else
|
|
{
|
|
res << pPt1;
|
|
delete pPt2;
|
|
}
|
|
return true;
|
|
}
|
|
case CID_GLineRay2D:
|
|
{
|
|
double pa1,pa2;
|
|
const TPGeGLineRay2D& ray = (const TPGeGLineRay2D&)obj;
|
|
const TPGeLine2D& line = ray;
|
|
|
|
int ret = line.Intersect(this,pa1,pa2);
|
|
if (ret == INT_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
else if (ret == INT_2PT)
|
|
{
|
|
bool result = false;
|
|
if (UPEQUAL_ZERO(pa1))
|
|
{
|
|
TGPoint2D* pPt = new TGPoint2D;
|
|
ray.Pa2Pt(pa1,*pPt);
|
|
res << pPt;
|
|
result = true;
|
|
}
|
|
if (UPEQUAL_ZERO(pa2))
|
|
{
|
|
TGPoint2D* pPt = new TGPoint2D;
|
|
ray.Pa2Pt(pa2,*pPt);
|
|
res << pPt;
|
|
result = true;
|
|
}
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
if (UPEQUAL_ZERO(pa1))
|
|
{
|
|
TGPoint2D* pPt = new TGPoint2D;
|
|
ray.Pa2Pt(pa1,*pPt);
|
|
res << pPt;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
case CID_GLineSeg2D:
|
|
{
|
|
double pa1,pa2;
|
|
const TPGeGLineSeg2D& seg = (const TPGeGLineSeg2D&)obj;
|
|
const TPGeLine2D& line = seg;
|
|
int ret = line.Intersect(this,pa1,pa2);
|
|
if (ret == INT_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
else if (ret == INT_2PT)
|
|
{
|
|
bool result = false;
|
|
if (UPEQUAL_ZERO(pa1) && DOWNEQUAL_ZERO(pa1 - 1))
|
|
{
|
|
TGPoint2D* pPt = new TGPoint2D;
|
|
seg.Pa2Pt(pa1,*pPt);
|
|
res << pPt;
|
|
result = true;
|
|
}
|
|
if (UPEQUAL_ZERO(pa2) && DOWNEQUAL_ZERO(pa2 - 1))
|
|
{
|
|
TGPoint2D* pPt = new TGPoint2D;
|
|
seg.Pa2Pt(pa2,*pPt);
|
|
res << pPt;
|
|
result = true;
|
|
}
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
if (UPEQUAL_ZERO(pa1) && DOWNEQUAL_ZERO(pa1 - 1))
|
|
{
|
|
TGPoint2D* pPt = new TGPoint2D;
|
|
seg.Pa2Pt(pa1,*pPt);
|
|
res << pPt;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
case CID_GCircle2D:
|
|
{
|
|
TGPoint2D* pPt1 = new TGPoint2D,*pPt2 = new TGPoint2D;
|
|
int ret = TPGeCircle::Intersect((const TPGeCircle2D&)obj,*pPt1,*pPt2);
|
|
if (ret == INT_NULL)
|
|
{
|
|
delete pPt1;
|
|
delete pPt2;
|
|
return false;
|
|
}
|
|
else if (ret == INT_2PT)
|
|
{
|
|
res << pPt1 << pPt2;
|
|
}
|
|
else if (ret == INT_1PT)
|
|
{
|
|
res << pPt1;
|
|
delete pPt2;
|
|
}
|
|
else
|
|
{
|
|
delete pPt1;
|
|
delete pPt2;
|
|
res << new TPGeCircle2D(*this);
|
|
}
|
|
return true;
|
|
}
|
|
default:
|
|
return obj.Intersect(*this,res);
|
|
}
|
|
}
|
|
|
|
bool TPGeCircle2D::IsInclude(const TGObject& obj) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLine2D:
|
|
case CID_GLineRay2D:
|
|
case CID_GLineSeg2D:
|
|
return false;
|
|
case CID_GArc2D:
|
|
return IsSameCircle(((const TPGeArc2D&)obj).circle);
|
|
case CID_GCircle2D:
|
|
return IsSameCircle((const TPGeCircle2D&)obj);
|
|
default:
|
|
return TPGeCurve2D::IsInclude(obj);
|
|
}
|
|
}
|
|
|
|
bool TPGeCircle2D::GetExtend2D(TPGeExtend2D&ext) const
|
|
{
|
|
ext.SetRange(center.x - r,center.x + r, center.y - r, center.y + r);
|
|
return true;
|
|
}
|
|
|
|
TPGeCurve2D* TPGeCircle2D::GetSubCurve(double pa0,double pa1) const
|
|
{
|
|
TPGeArc2D* pArc = new TPGeArc2D(*this);
|
|
pArc->SetStartAngle(pa0);
|
|
pArc->centralAngle = NA(pa1 - pa0);
|
|
if (DOWNEQUAL_ZEROA(pArc->centralAngle))
|
|
{
|
|
pArc->centralAngle = PI2;
|
|
}
|
|
return pArc;
|
|
}
|
|
|
|
TGMLine2D* TPGeCircle2D::PLinearize(double paDist) const
|
|
{
|
|
return new TGPLine2D(*this);
|
|
}
|
|
|
|
void TPGeCircle2D::Split(const TTable<double>& paTable, TGObjectList& res) const
|
|
{
|
|
if (paTable.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
if (paTable.GetLength() == 1)
|
|
{
|
|
res << GetSubCurve(paTable.GetAt(0),paTable.GetAt(0));
|
|
}
|
|
else
|
|
{
|
|
for (long i = 1; i < paTable.GetLength(); i++)
|
|
{
|
|
if (DOWN_ZEROA(paTable.GetAt(i - 1) - paTable.GetAt(i)))
|
|
{
|
|
res << GetSubCurve(paTable.GetAt(i - 1), paTable.GetAt(i));
|
|
}
|
|
}
|
|
double last = paTable.GetAt(i - 1);
|
|
if (DOWN_ZEROA(last - PI2) || UP_ZEROA(paTable.GetAt(0)))
|
|
{
|
|
res << GetSubCurve(last,paTable.GetAt(0));
|
|
}
|
|
}
|
|
}
|
|
|
|
TGMLine2D* TPGeCircle2D::MLinearize(double paDist) const
|
|
{
|
|
if (paDist < 1E-9)
|
|
{
|
|
paDist = GetMLinePrec();
|
|
}
|
|
|
|
long num = (long)(PI2 / paDist + 0.999999);
|
|
if (num < 2)
|
|
{
|
|
return NULL;
|
|
}
|
|
paDist = PI2 / num;
|
|
TGMLine2D *pMLine = new TGMLine2D(num,true);
|
|
double pa = 0;
|
|
for (long i = 0; i < num; i++, pa += paDist)
|
|
{
|
|
Pa2Pt(pa,(*pMLine)[i]);
|
|
}
|
|
return pMLine;
|
|
}
|
|
|
|
void TPGeCircle2D::Init(const TGPoint& pt0,const TGPoint& pt1,const TGPoint& pt2)
|
|
{
|
|
TPGeCircle::Init(pt0,pt1,pt2);
|
|
if (TGVector2D(pt0,pt1).IsVectorRight(TGVector2D(pt1,pt2)))
|
|
{
|
|
AddFlag(CLOCKWISE_CURVE);
|
|
}
|
|
else
|
|
{
|
|
RemoveFlag(CLOCKWISE_CURVE);
|
|
}
|
|
}
|
|
|
|
void TPGeCircle2D::Init(const TGPoint& pt0,const TGPoint& pt1,double angle)
|
|
{
|
|
TPGeCircle::Init(pt0,pt1,angle);
|
|
if (angle < 0)
|
|
{
|
|
AddFlag(CLOCKWISE_CURVE);
|
|
}
|
|
else
|
|
{
|
|
RemoveFlag(CLOCKWISE_CURVE);
|
|
}
|
|
}
|
|
|
|
bool TPGeCircle2D::IsSameCircle(const TPGeCircle2D& cir, bool bSameDirection) const
|
|
{
|
|
if (TPGeCircle::operator == (cir))
|
|
{
|
|
if (bSameDirection)
|
|
{
|
|
return (Is(CLOCKWISE_CURVE) && cir.Is(CLOCKWISE_CURVE)) || (IsNot(CLOCKWISE_CURVE) && cir.IsNot(CLOCKWISE_CURVE));
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
} |