Files
envi-code/SourceCode/Code2026/tg_shs/shs_subgeLib/TPGeArc2D.cpp
T
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

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);
}