529 lines
10 KiB
C++
529 lines
10 KiB
C++
//-------------------------------------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
|
|
// = FileName : TPGeArc2D 类
|
|
// = Version : ver2.0
|
|
// = Author : wlw
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: TPGeArc2D 定义
|
|
// = Maintainers:
|
|
//
|
|
//-------------------------------------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "TPGeArc2D.h"
|
|
// #include "TchGeLib.h"
|
|
#include "TGPoint2D.h"
|
|
#include "TWPushVar.h"
|
|
|
|
IMPLEMENT_RUN_TIME_CLASS1(TPGeArc2D,"TPGeArc2D",TPGeCurve2D)
|
|
|
|
TPGeArc2D::TPGeArc2D()
|
|
{
|
|
|
|
}
|
|
|
|
TPGeArc2D::TPGeArc2D(const TGPoint&pt,double radius,double sA,double cA,bool bUnClockWise):
|
|
circle(pt,radius,bUnClockWise),startAngle(sA),centralAngle(cA)
|
|
{
|
|
|
|
}
|
|
|
|
TPGeArc2D::TPGeArc2D(const TGPoint&sPt,const TGPoint&ePt,double angle)
|
|
{
|
|
Init(sPt,ePt,angle);
|
|
}
|
|
|
|
TPGeArc2D::TPGeArc2D(const TGPoint&pt0,const TGPoint&pt1,const TGPoint&pt2)
|
|
{
|
|
Init(pt0,pt1,pt2);
|
|
}
|
|
|
|
TPGeArc2D::TPGeArc2D(const TPGeCircle2D& c):circle(c)
|
|
{
|
|
|
|
}
|
|
|
|
TPGeCurve2D* TPGeArc2D::GetExtendCurve() const
|
|
{
|
|
return new TPGeCircle2D(circle);
|
|
}
|
|
|
|
bool TPGeArc2D::IsValid() const
|
|
{
|
|
return circle.IsValid() && UP_ZEROA(centralAngle) && DOWNEQUAL_ZEROA(centralAngle - PI2);
|
|
}
|
|
|
|
GRelation TPGeArc2D::HitTest(const TGPoint&pt) const
|
|
{
|
|
GRelation r = circle.HitTest(pt);
|
|
if(r.Is(GR_IN))
|
|
{
|
|
double pa;
|
|
Pt2Pa(pt,pa);
|
|
|
|
if(!IsParaInSeg(pa,GetParaPrecFromLength(Length()))
|
|
&& UP_ZEROD(Distance2D(GetStartPoint(),pt))
|
|
&& UP_ZEROD(Distance2D(GetEndPoint(),pt)))
|
|
{
|
|
return GR_OUT;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void TPGeArc2D::Reverse()
|
|
{
|
|
circle.Reverse();
|
|
startAngle = RA(GetEndAngle());
|
|
}
|
|
|
|
void TPGeArc2D::GetStartPoint(TGPoint&pt) const
|
|
{
|
|
circle.Pa2Pt(startAngle,pt);
|
|
}
|
|
|
|
void TPGeArc2D::GetEndPoint(TGPoint&pt) const
|
|
{
|
|
circle.Pa2Pt(startAngle+centralAngle,pt);
|
|
}
|
|
|
|
void TPGeArc2D::Pt2Pa(const TGPoint&pt,double&pa) const
|
|
{
|
|
circle.Pt2Pa(pt,pa);
|
|
pa = ALEN(startAngle,pa) / centralAngle;
|
|
}
|
|
|
|
void TPGeArc2D::Pa2Pt(double pa,TGPoint&pt) const
|
|
{
|
|
if(EQUAL_ZERO(pa))
|
|
{
|
|
GetStartPoint(pt);
|
|
}
|
|
else if(EQUAL_ZERO(pa-1))
|
|
{
|
|
GetEndPoint(pt);
|
|
}
|
|
else
|
|
{
|
|
circle.Pa2Pt(startAngle+pa*centralAngle,pt);
|
|
}
|
|
}
|
|
|
|
double TPGeArc2D::Integration(double pa0,double pa1) const
|
|
{
|
|
return circle.Integration(pa0 * centralAngle + startAngle, pa1 * centralAngle + startAngle);
|
|
}
|
|
|
|
void TPGeArc2D::GetTangent(double pa,TPGeLine2D&line) const
|
|
{
|
|
circle.GetTangent(startAngle + pa * centralAngle, line);
|
|
}
|
|
|
|
bool TPGeArc2D::IsClosed() const
|
|
{
|
|
double d = PI2 - centralAngle;
|
|
return EQUAL_ZEROA(d);
|
|
}
|
|
|
|
bool TPGeArc2D::Intersect(const TGObject&obj,TGObjectList&res) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLine2D:
|
|
case CID_GLineRay2D:
|
|
case CID_GLineSeg2D:
|
|
{
|
|
TGObjectList buf;
|
|
if(circle.Intersect(obj,buf))
|
|
{
|
|
double pa;
|
|
double paraPrec = GetParaPrecFromLength(Length());
|
|
for(buf.MoveToFirst();!buf.IsOut();buf.MoveToNext())
|
|
{
|
|
Pt2Pa((const TGPoint2D&)(buf.GetCurPData()),pa);
|
|
if(!IsParaInSeg(pa,paraPrec))
|
|
{
|
|
buf.DelCur();
|
|
}
|
|
}
|
|
if(!buf.IsEmpty())
|
|
{
|
|
res.Conbine(buf);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
case CID_GCircle2D:
|
|
{
|
|
TGObjectList buf;
|
|
if(circle.Intersect(obj,buf))
|
|
{
|
|
if(IS_TYPE(buf[0],TPGeCircle2D))
|
|
{
|
|
res<<new TPGeArc2D(*this);
|
|
return true;
|
|
}
|
|
|
|
double paraPrec = GetParaPrecFromLength(Length());
|
|
double pa;
|
|
for(buf.MoveToFirst();!buf.IsOut();buf.MoveToNext())
|
|
{
|
|
Pt2Pa((const TGPoint2D&)(buf.GetCurPData()),pa);
|
|
if(!IsParaInSeg(pa,paraPrec))
|
|
{
|
|
buf.DelCur();
|
|
}
|
|
}
|
|
if(!buf.IsEmpty())
|
|
{
|
|
res.Conbine(buf);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
case CID_GArc2D:
|
|
{
|
|
TGObjectList buf;
|
|
if(((const TPGeArc2D&)obj).Intersect(circle,buf))
|
|
{
|
|
if(IS_TYPE(buf[0],TPGeArc2D))
|
|
{
|
|
TWPushVar<double> vTemp(g_angleZero,GetAnglePrecFromRadius(circle.r));
|
|
|
|
if(((TPGeArc2D&)obj).IsClosed())
|
|
{
|
|
res<<new TPGeArc2D(*this);
|
|
}
|
|
else if(IsClosed())
|
|
{
|
|
res.Conbine(buf);
|
|
}
|
|
else
|
|
{
|
|
TPGeArc2D *pArc = (TPGeArc2D*)buf[0];
|
|
if((circle.Is(CLOCKWISE_CURVE) && pArc->circle.IsNot(CLOCKWISE_CURVE)) ||
|
|
(circle.IsNot(CLOCKWISE_CURVE) && pArc->circle.Is(CLOCKWISE_CURVE)))
|
|
{
|
|
pArc->Reverse();
|
|
}
|
|
double sA = ALEN(startAngle,pArc->startAngle);
|
|
double eA = ALEN(startAngle,pArc->GetEndAngle());
|
|
|
|
if(sA < eA)
|
|
{
|
|
double da = sA-centralAngle;
|
|
if(UP_ZEROA(da))
|
|
{
|
|
return false;
|
|
}
|
|
else if(DOWN_ZEROA(da))
|
|
{
|
|
if(UP_ZEROA(eA - centralAngle))
|
|
{
|
|
pArc->centralAngle = -da;
|
|
}
|
|
res.Conbine(buf);
|
|
}
|
|
else
|
|
{
|
|
res<<new TGPoint2D(GetEndPoint());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
double da = eA-centralAngle;
|
|
if(UPEQUAL_ZEROA(da))
|
|
{
|
|
res<<new TPGeArc2D(*this);
|
|
}
|
|
else
|
|
{
|
|
if(UP_ZEROA(eA))
|
|
{
|
|
TPGeArc2D *pArc1 = new TPGeArc2D(*this);
|
|
pArc1->centralAngle = eA;
|
|
res<<pArc1;
|
|
}
|
|
else
|
|
{
|
|
res<<new TGPoint2D(GetStartPoint());
|
|
}
|
|
|
|
double da0 = sA-centralAngle;
|
|
if(DOWN_ZEROA(da0))
|
|
{
|
|
pArc->centralAngle = -da0;
|
|
res.Conbine(buf);
|
|
}
|
|
else if(EQUAL_ZEROA(da0))
|
|
{
|
|
res<<new TGPoint2D(GetEndPoint());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
double paraPrec = GetParaPrecFromLength(Length());
|
|
double pa;
|
|
for(buf.MoveToFirst();!buf.IsOut();buf.MoveToNext())
|
|
{
|
|
Pt2Pa((const TGPoint2D&)(buf.GetCurPData()),pa);
|
|
if(!IsParaInSeg(pa,paraPrec))
|
|
{
|
|
buf.DelCur();
|
|
}
|
|
}
|
|
if(!buf.IsEmpty())
|
|
{
|
|
res.Conbine(buf);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
default:
|
|
return obj.Intersect(*this, res);
|
|
}
|
|
}
|
|
|
|
bool TPGeArc2D::IsInclude(const TGObject&obj) const
|
|
{
|
|
switch(obj.GetClassID())
|
|
{
|
|
case CID_GLine2D:
|
|
case CID_GLineRay2D:
|
|
case CID_GLineSeg2D:
|
|
return false;
|
|
case CID_GCircle2D:
|
|
return IsClosed() && circle.IsSameCircle((const TPGeCircle2D&)obj);
|
|
case CID_GArc2D:
|
|
{
|
|
const TPGeArc2D &arc = (const TPGeArc2D&)obj;
|
|
if(!circle.IsSameCircle(arc.circle))
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
double d = centralAngle - arc.centralAngle;
|
|
if(DOWN_ZEROA(d))
|
|
{
|
|
return false;
|
|
}
|
|
if((circle.Is(CLOCKWISE_CURVE) && arc.circle.IsNot(CLOCKWISE_CURVE)) ||
|
|
(circle.IsNot(CLOCKWISE_CURVE) && arc.circle.Is(CLOCKWISE_CURVE)))
|
|
{
|
|
d -= ALEN(startAngle,RA(arc.GetEndAngle()))+ALEN(RA(arc.startAngle),GetEndAngle());
|
|
}
|
|
else
|
|
{
|
|
d -= ALEN(startAngle,arc.startAngle)+ALEN(arc.GetEndAngle(),GetEndAngle());
|
|
}
|
|
return EQUAL_ZEROA(d);
|
|
}
|
|
}
|
|
default:
|
|
return TPGeCurve2D::IsInclude(obj);
|
|
}
|
|
}
|
|
|
|
bool TPGeArc2D::GetExtend2D(TPGeExtend2D& ext) const
|
|
{
|
|
TGPoint2D pt = GetStartPoint();
|
|
pt.GetExtend2D(ext);
|
|
pt = GetEndPoint();
|
|
ext += TPGeExtend2D(pt.x,pt.x,pt.y,pt.y);
|
|
|
|
double r = circle.r;
|
|
double x0 = circle.center.x, y0 = circle.center.y;
|
|
double x1,y1;
|
|
if(circle.Is(CLOCKWISE_CURVE))
|
|
{
|
|
if(AIN(0,startAngle,centralAngle))
|
|
{
|
|
x1 = x0 + r;
|
|
ext += TPGeExtend2D(x1,x1,y0,y0);
|
|
}
|
|
if(AIN(PI / 2,startAngle,centralAngle))
|
|
{
|
|
y1 = y0 - r;
|
|
ext += TPGeExtend2D(x0,x0,y1,y1);
|
|
}
|
|
if(AIN(PI,startAngle,centralAngle))
|
|
{
|
|
x1 = x0 - r;
|
|
ext += TPGeExtend2D(x1,x1,y0,y0);
|
|
}
|
|
if(AIN(PI*1.5,startAngle,centralAngle))
|
|
{
|
|
y1 = y0 + r;
|
|
ext += TPGeExtend2D(x0,x0,y1,y1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(AIN(0,startAngle,centralAngle))
|
|
{
|
|
x1 = x0 + r;
|
|
ext += TPGeExtend2D(x1,x1,y0,y0);
|
|
}
|
|
if(AIN(PI / 2,startAngle,centralAngle))
|
|
{
|
|
y1 = y0 + r;
|
|
ext += TPGeExtend2D(x0,x0,y1,y1);
|
|
}
|
|
if(AIN(PI,startAngle,centralAngle))
|
|
{
|
|
x1 = x0 - r;
|
|
ext += TPGeExtend2D(x1,x1,y0,y0);
|
|
}
|
|
if(AIN(PI * 1.5,startAngle,centralAngle))
|
|
{
|
|
y1 = y0 - r;
|
|
ext += TPGeExtend2D(x0,x0,y1,y1);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
TPGeCurve2D* TPGeArc2D::GetSubCurve(double pa0,double pa1) const
|
|
{
|
|
return circle.GetSubCurve(pa0 * centralAngle + startAngle, pa1 * centralAngle + startAngle);
|
|
}
|
|
|
|
TGMLine2D* TPGeArc2D::PLinearize(double paDist) const
|
|
{
|
|
return new TGPLine2D(*this);
|
|
}
|
|
|
|
void TPGeArc2D::Init(const TGPoint&pt0,const TGPoint&pt1,const TGPoint&pt2)
|
|
{
|
|
circle.Init(pt0,pt1,pt2);
|
|
circle.Pt2Pa(pt0,startAngle);
|
|
double endAngle;
|
|
circle.Pt2Pa(pt2,endAngle);
|
|
centralAngle = ALEN(startAngle,endAngle);
|
|
}
|
|
|
|
void TPGeArc2D::Init(const TGPoint&pt0,const TGPoint&pt1,double angle)
|
|
{
|
|
circle.Init(pt0,pt1,angle);
|
|
circle.Pt2Pa(pt0,startAngle);
|
|
centralAngle = fabs(angle);
|
|
}
|
|
|
|
void TPGeArc2D::SetStartAngle(double angle)
|
|
{
|
|
startAngle = NA(angle);
|
|
}
|
|
|
|
bool TPGeArc2D::IsClockwise() const
|
|
{
|
|
return circle.Is(CLOCKWISE_CURVE);
|
|
}
|
|
|
|
|
|
double TPGeArc2D::Length() const
|
|
{
|
|
return centralAngle*circle.r;
|
|
}
|
|
|
|
double TPGeArc2D::Area() const
|
|
{
|
|
return circle.Area();
|
|
}
|
|
|
|
double TPGeArc2D::GetMLinePrec() const
|
|
{
|
|
return TPGeCircle2D::g_fMLinePreci/centralAngle;
|
|
}
|
|
|
|
bool TPGeArc2D::Offset(double offset)
|
|
{
|
|
return circle.Offset(offset);
|
|
}
|
|
|
|
void TPGeArc2D::SetElev(double elev)
|
|
{
|
|
circle.SetElev(elev);
|
|
}
|
|
|
|
double TPGeArc2D::GetElev() const
|
|
{
|
|
return circle.GetElev();
|
|
}
|
|
|
|
void TPGeArc2D::TransformBy(const TGMatrix&matrix)
|
|
{
|
|
circle.TransformBy(matrix);
|
|
}
|
|
|
|
TGObject * TPGeArc2D::Clone() const
|
|
{
|
|
return new TPGeArc2D(*this);
|
|
}
|
|
|
|
double TPGeArc2D::GetEndAngle() const
|
|
{
|
|
return startAngle+centralAngle;
|
|
}
|
|
|
|
TGPoint TPGeArc2D::GetStartPoint() const
|
|
{
|
|
TGPoint pt;
|
|
GetStartPoint(pt);
|
|
return pt;
|
|
}
|
|
|
|
TGPoint TPGeArc2D::GetEndPoint() const
|
|
{
|
|
TGPoint pt;
|
|
GetEndPoint(pt);
|
|
return pt;
|
|
}
|
|
|
|
TGPoint TPGeArc2D::GetMidPoint() const
|
|
{
|
|
TGPoint pt;
|
|
Pa2Pt(0.5,pt);
|
|
return pt;
|
|
}
|
|
|
|
double TPGeArc2D::GetAnglePrecFromRadius(double dradius)const
|
|
{
|
|
double newAngPrec = 2 * asin(0.5 * g_distZero / dradius);
|
|
if (newAngPrec > 0.1)
|
|
{
|
|
newAngPrec = 0.1;
|
|
}
|
|
else if (newAngPrec < 1E-18)
|
|
{
|
|
newAngPrec = 1E-18;
|
|
}
|
|
|
|
return newAngPrec;
|
|
}
|
|
|
|
double TPGeArc2D::GetParaPrecFromLength(double dlength)const
|
|
{
|
|
double newPrec = g_distZero / dlength;
|
|
if (newPrec > 0.1)
|
|
{
|
|
newPrec = 0.1;
|
|
}
|
|
else if (newPrec < 1E-18)
|
|
{
|
|
newPrec = 1E-18;
|
|
}
|
|
|
|
return newPrec;
|
|
}
|
|
|
|
bool TPGeArc2D::IsParaInSeg(double dpa,double dprec)const
|
|
{
|
|
TWPushVar<double> vTemp(g_fZero,dprec);
|
|
return UPEQUAL_ZERO(dpa) && DOWNEQUAL_ZERO(dpa - 1);
|
|
} |