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

733 lines
14 KiB
C++

#include "StdAfx.h"
#include "GeLine.h"
#include "globalfunc.h"
#include "GePoly.h"
#include "AcDbObjectPtr.h"
#include "ADSGePoint3d.h"
#include "PointList.h"
#include "GeCurveInline.h"
enum HitTestPos
{
POS_Error = 0, //错误
POS_Left = 1, //左边
POS_Rigth = 2, //右边
POS_Start = 3, //起始点
POS_End = 4, //终止点
POS_InLine = 5, //线内
POS_StartLineEx = 6, //起始侧延长线
POS_EndLineEx = 7 //终止侧延长线
};
// 仅处理z坐标相同的线
static int Inters(const ADSGePoint3d &pt1, const ADSGePoint3d &pt2,
const ADSGePoint3d &qt1, const ADSGePoint3d &qt2, ADSGePoint3d &ptInter)
{
if (fabs(pt1.z - pt2.z) > g_Option::instance()._DIST_SNAP)
{
return RTERROR;
}
// Ax+ By+ C = 0;
ads_real A1 = pt2.y - pt1.y,
B1 = pt1.x - pt2.x,
C1 = pt1.y * pt2.x - pt1.x * pt2.y;
ads_real A2 = qt2.y - qt1.y,
B2 = qt1.x - qt2.x,
C2 = qt1.y * qt2.x - qt1.x * qt2.y;
ads_real E = A1 * B2 - A2 * B1;
if (fabs(E) < g_Option::instance()._DIST_SNAP * g_Option::instance()._DIST_SNAP) //重合或平行
{
return RTERROR;
}
ptInter.x = (B1 * C2 - B2 * C1) / E;
ptInter.y = (C1 * A2 - C2 * A1) / E;
ptInter.z = pt1.z;
return RTNORM;
}
GeLine::GeLine(const ads_point p1, const ads_point p2, int nflag)
{
m_startPoint = p1;
m_endPoint = p2;
m_nFlag = nflag;
}
GeLine::GeLine(const EntitySet& entLine, int nflag , ads_matrix tranMat)
{
AcDbObjectPtr obj(entLine.name, AcDb::kForRead, Adesk::kTrue);
if (!obj)
{
return;
}
if (obj.m_pObject->isKindOf(AcDbLine::desc()))
{
AcDbLine *pLine = (AcDbLine *)obj.m_pObject;
(AcGePoint3d &)m_startPoint = pLine->startPoint();
(AcGePoint3d &)m_endPoint = pLine->endPoint();
if (tranMat)
{
m_startPoint.TransformBy(tranMat);
m_endPoint.TransformBy(tranMat);
}
}
}
GeLine::GeLine(const GeLine & src)
: m_startPoint(src.m_startPoint), m_endPoint(src.m_endPoint), m_nFlag(src.m_nFlag)
{
}
GeLine::GeLine(int nflag)
{
m_nFlag = nflag;
}
GeLine::GeLine(const ADSGePoint3d &ptThrough, ads_real dDrt)
: m_startPoint(ptThrough), m_nFlag(LS_INFINITE)
{
ads_polar(m_startPoint, dDrt, 100.0, m_endPoint);
}
GeLine::~GeLine()
{
}
int GeLine::OnWhichSide(const ADSGePoint3d &ptsrc) const
{
GeCurveSegment seg;
seg = *this;
return seg.OnWhichSide(ptsrc);
}
// 同两条线的特征有关
int GeLine::Intersection(const GeLine* pLine, ads_point ptrp) const
{
if (pLine != NULL)
{
// modify by xlc 100613 取消AcGe算法,速度慢
// modify by xlc on 110503 大坐标采用AcGe算法,保证精度
ADSGePoint3d ptGe;
if (fabs(m_startPoint.x) > 1.e8 || fabs(m_startPoint.y) > 1.e8
||fabs(m_endPoint.x) > 1.e8 || fabs(m_endPoint.y) > 1.e8)//大坐标
{
AcGeLine3d lineT,lineO;
lineT.set(m_startPoint.AsAcGePoint3d(),
m_endPoint.AsAcGePoint3d());
lineO.set(pLine->m_startPoint.AsAcGePoint3d(),
pLine->m_endPoint.AsAcGePoint3d());
AcGePoint3d ptGeP;
Adesk::Boolean bInt = lineT.intersectWith(lineO,ptGeP);
if (!bInt)
{
return 0;
}
ptGe = ptGeP;
}
else
{
if (Inters(m_startPoint, m_endPoint, pLine->m_startPoint, pLine->m_endPoint, ptGe) != RTNORM)
{
return 0;
}
}
if (m_nFlag == LS_INFINITE
&& pLine->m_nFlag == LS_INFINITE)
{
ptrp[X] = ptGe.x;
ptrp[Y] = ptGe.y;
ptrp[Z] = ptGe.z;
return 1;
}
int tag1 = ptGe & (*this);
int tag2 = ptGe & (*pLine);
if (tag1 == PR_OUTSIDE || tag2 == PR_OUTSIDE)
{
return 0;
}
if ((m_nFlag & LS_FINITE) && (tag1 == PR_EXTEND))
{
return 0;
}
if ((pLine->m_nFlag & LS_FINITE) && (tag2 == PR_EXTEND))
{
return 0;
}
ptrp[X] = ptGe.x;
ptrp[Y] = ptGe.y;
ptrp[Z] = ptGe.z;
return 1;
}
return FALSE;
}
int GeLine::Intersection(const GeArc* pArc, ads_point ptrp1, ads_point ptrp2) const
{
if ( pArc != NULL)
{
//lfy 2010-08-31 采用AcGe算法
if (!GlobalFunc::IsEqual(1.0E-5, 3, pArc->GetCenterPt().z, m_startPoint.z, m_endPoint.z))
{
return 0;
}
//lfy 2010-08-31 修改存取方式
AcGeLine3d lineT(m_startPoint.AsAcGePoint3d(),m_endPoint.AsAcGePoint3d());
AcGeCircArc3d cirO(pArc->m_ptCenter.AsAcGePoint3d(),AcGeVector3d::kZAxis,pArc->m_dRadius);
int nInt = 0;
ADSGePoint3d pt1, pt2;
cirO.intersectWith(lineT,nInt,pt1,pt2);
//无交点
if (nInt == 0)
{
return 0;
}
int nt1 = ((pt1 & (*pArc)) != PR_OUTSIDE);
int nt2 = ((pt2 & (*pArc)) != PR_OUTSIDE);
if (m_nFlag == LS_FINITE)
{
if (nt1)
{
int npr1 = pt1 & (*this);
nt1 = (npr1 == PR_ONPT1) || (npr1 == PR_ONPT2) || (npr1 == PR_INSIDE);
}
if (nt2)
{
int npr2 = pt2 & (*this);
nt2 = (npr2 == PR_ONPT1) || (npr2 == PR_ONPT2) || (npr2 == PR_INSIDE);
}
}
//保存点
if (ptrp1)
{
if (nt1)
{
pt1 > ptrp1;
}
if (!nt1 && nt2)
{
pt2 > ptrp1;
}
}
if (ptrp2)
{
if (nt2 && nt1)
{
pt2 > ptrp2;
}
}
if (nt2 + nt1 == 2)
{
if (pt1.AsAcGePoint3d().distanceTo(pt2.AsAcGePoint3d()) < g_Option::instance()._DIST_SNAP)
{
nt2 = 0;
}
}
return nt1 + nt2;
}
return FALSE;
}
int GeLine::Intersection(const GeCircle* pCircle, ads_point ptrp1, ads_point ptrp2) const
{
if (pCircle != NULL)
{
if (!GlobalFunc::IsEqual(1.0E-5, 3, pCircle->m_ptCenter.z, m_startPoint.z, m_endPoint.z))
{
return 0;
}
AcGeLine3d lineT(m_startPoint.AsAcGePoint3d(), m_endPoint.AsAcGePoint3d());
AcGeCircArc3d cirO(pCircle->m_ptCenter.AsAcGePoint3d(),AcGeVector3d::kZAxis,pCircle->m_dRadius);
int nInt = 0;
ADSGePoint3d pt1, pt2;
cirO.intersectWith(lineT,nInt,pt1,pt2);
//无交点
if (nInt == 0)
{
return 0;
}
int nt1 = 1, nt2 = 1;
if (m_nFlag == LS_FINITE)
{
int npr1 = pt1 & (*this);
nt1 = (npr1 == PR_ONPT1) || (npr1 == PR_ONPT2) || (npr1 == PR_INSIDE);
int npr2 = pt2 & (*this);
nt2 = (npr2 == PR_ONPT1) || (npr2 == PR_ONPT2) || (npr2 == PR_INSIDE);
}
if (ptrp1)
{
if (nt1)
{
pt1 > ptrp1;
}
if (!nt1 && nt2)
{
pt2 > ptrp1;
}
if (ptrp2)
{
if (nt2 && nt1)
{
pt2 > ptrp2;
}
}
if (nt1 + nt2 == 2)
{
if (asPnt3d(ptrp1).distanceTo(asPnt3d(ptrp2)) < g_Option::instance()._DIST_SNAP)
{
nt2 = 0;
}
}
}
return nt1 + nt2;
}
return FALSE;
}
int GeLine::HitTest2d(const ADSGePoint3d &ptTest) const
{
double dLineLen = m_startPoint.Distance2d(m_endPoint);
if (dLineLen < g_Option::instance()._DIST_SNAP)
{
return POS_Error;
}
double dDist2Start = m_startPoint.Distance2d(ptTest);
if (dDist2Start < g_Option::instance()._DIST_SNAP)
{
return POS_Start;
}
double dDist2End = m_endPoint.Distance2d(ptTest);
if (dDist2End < g_Option::instance()._DIST_SNAP)
{
return POS_End;
}
TVector3D vtTest = ptTest - m_startPoint;
TVector3D vtThis = m_endPoint - m_startPoint;
vtThis /= dLineLen;
using namespace GlobalFunc;
double dDot = (vtTest & vtThis);
if (fabs(fabs(dDot) - dDist2Start) < g_Option::instance()._DIST_SNAP)
{
if (dDot < 0.0)
{
return POS_StartLineEx;
}
if (dDot < dLineLen)
{
return POS_InLine;
}
return POS_EndLineEx;
}
else
{
TVector3D vtCross = (vtTest*vtThis);
if (vtCross.z > 0)
{
return POS_Rigth;
}
if (vtCross.z < 0)
{
return POS_Left;
}
}
return POS_Error;
}
int GeLine::Intersection(GePoly* pPoly, PointList &pts) const
{
ASSERT(pPoly != NULL);
GeLine aLine(LS_FINITE);
int nlen = pPoly->Length();
ADSGePoint3d pt;
for (int i = 0; i < nlen; i++)
{
pPoly->NthLine(i, aLine);
if (Intersection(&aLine, pt))
{
if ((pt & (*this)) == PR_INSIDE)
{
pts.Insert(pt);
}
}
}
return pts.Length() - 2;
}
int GeLine::Modify(const EntitySet* pEntity) const
{
ASSERT(pEntity != NULL);
EntitySet entLine = *pEntity;
if (!entLine.Is(_T("LINE")))
{
return RTERROR;
}
entLine.SetData(10, &m_startPoint);
entLine.SetData(11, &m_endPoint);
return entLine.Modify();
}
int GeLine::MakeEntity(const EntitySet* pEntity) const
{
ASSERT(pEntity != NULL);
EntitySet ent = *pEntity;
RBGroups g(_T("*"));
RBList ebuf = ads_entgetx(ent, (resbuf *)&g);
ebuf.SetData(10, &m_startPoint);
ebuf.SetData(11, &m_endPoint);
return ads_entmake(ebuf);
}
int GeLine::Make(const TCHAR *szlay) const
{
TCHAR szlayer[80] = _T("");
if (szlay)
{
_tcscpy(szlayer, szlay);
}
else
{
GlobalFunc::TGGetVar(_T("clayer"), szlayer);
}
return GlobalFunc::MakeEntity(RTDXF0, _T("LINE"), 10,
&m_startPoint.x,11,
&m_endPoint.x, 8, szlayer, NULL);
}
int GeLine::OSnap(int nMode, ADSGePoint3d &ptPick) const
{
GeLine &ln = *(GeLine *)this;
switch(nMode)
{
case OS_END:
ptPick = ln.NearPoint(ptPick);
return nMode;
case OS_MID:
ptPick = MidPoint();
return nMode;
case OS_NEA:
{
ADSGePoint3d ptSrc = ptPick;
AcGeLine3d lineT(m_startPoint.AsAcGePoint3d(),
m_endPoint.AsAcGePoint3d());
AcGePointOnCurve3d ptOnCrv;
lineT.getClosestPointTo(ptPick.AsAcGePoint3d(),ptOnCrv);
ptPick = ptOnCrv.point3d();
return nMode;
}
break;
}
return OS_NON;
}
GeLine GeLine::Offset(ads_real ddist) const
{
ADSGePoint3d spt, ept;
ads_real dang = GlobalFunc::AngleRangeTo2PI(Direction() - PI / 2.0);
ads_polar(m_startPoint, dang, ddist, spt);
ads_polar(m_endPoint, dang, ddist, ept);
return GeLine(spt, ept);
}
int GeLine::GetSubLine(const ADSGePoint3d &ptLoc, ads_real ddist, GeLine& res) const
{
ads_polar(ptLoc, Direction() - PI, ddist / 2.0, res.m_startPoint);
ads_polar(ptLoc, Direction(), ddist / 2.0,res.m_endPoint);
int nflg1 = res.m_startPoint & (*this);
int nflg2 = res.m_endPoint & (*this);
if ((nflg1 == PR_ONPT1 || nflg1 == PR_ONPT2 || nflg1 == PR_INSIDE) &&
(nflg2 == PR_ONPT1 || nflg2 == PR_ONPT2 || nflg2 == PR_INSIDE))
{
return RTNORM;
}
else if (m_nFlag == LS_INFINITE && nflg1 == PR_EXTEND && nflg2 == PR_EXTEND)
{
return RTNORM;
}
return RTERROR;
}
int GeLine::operator != (const GeLine& aLine) const
{
return !((*this) == aLine);
}
void GeLine::SetStartPoint(ADSGePoint3d ptStart)
{
m_startPoint = ptStart;
}
void GeLine::GetStartPoint(ADSGePoint3d& ptStart)
{
ptStart = m_startPoint;
}
ADSGePoint3d GeLine::GetStartPoint() const
{
return m_startPoint;
}
void GeLine::SetEndPoint(ADSGePoint3d ptEnd)
{
m_endPoint = ptEnd;
}
void GeLine::GetEndPoint(ADSGePoint3d& ptEnd)
{
ptEnd = m_endPoint;
}
ADSGePoint3d GeLine::GetEndPoint() const
{
return m_endPoint;
}
ADSGePoint3d& GeLine::StartPoint()
{
return m_startPoint;
}
ADSGePoint3d& GeLine::EndPoint()
{
return m_endPoint;
}
ADSGePoint3d& GeLine::StartPoint() const
{
return (ADSGePoint3d&)m_startPoint;
}
ADSGePoint3d& GeLine::EndPoint() const
{
return (ADSGePoint3d&)m_endPoint;
}
void GeLine::SetLineFlag(int nFlag)
{
m_nFlag = nFlag;
}
int GeLine::GetLineFlag() const
{
return m_nFlag;
}
void GeLine::SetPoints(const ADSGePoint3d& pt1, const ADSGePoint3d& pt2)
{
m_startPoint = pt1;
m_endPoint = pt2;
}
void GeLine::SetElevation(ads_real delev)
{
m_startPoint.z = delev;
m_endPoint.z = delev;
}
void GeLine::Reverse()
{
ADSGePoint3d pttmp = m_startPoint;
m_startPoint = m_endPoint;
m_endPoint = pttmp;
}
ads_real* GeLine::NearPoint(const ads_point pt0)
{
if (ads_distance((ads_real *)pt0, (ads_real *)m_startPoint)
< ads_distance((ads_real *)pt0, (ads_real *)m_endPoint))
{
return &m_startPoint.x;
}
return &m_endPoint.x;
}
ads_real* GeLine::FarPoint(const ads_point pt0)
{
if (ads_distance((ads_real *)pt0, m_startPoint)
> ads_distance((ads_real *)pt0,m_endPoint))
{
return &m_startPoint.x;
}
return &m_endPoint.x;
}
ADSGePoint3d GeLine::MidPoint() const
{
ADSGePoint3d ptMid;
ptMid.x = (m_startPoint.x + m_endPoint.x) / 2.0;
ptMid.y = (m_startPoint.y + m_endPoint.y) / 2.0;
ptMid.z = (m_startPoint.z + m_endPoint.z) / 2.0;
return ptMid;
}
void GeLine::MidPoint(ADSGePoint3d& ptres) const
{
ptres.x = (m_startPoint.x + m_endPoint.x) / 2.0;
ptres.y = (m_startPoint.y + m_endPoint.y) / 2.0;
ptres.z = (m_startPoint.z + m_endPoint.z) / 2.0;
}
void GeLine::TransUCS(const resbuf *pfrom, const resbuf *pto)
{
ADSGePoint3d spt = m_startPoint, ept = m_endPoint;
ads_trans(spt, pfrom, pto, 0, m_startPoint);
ads_trans(ept, pfrom, pto, 0, m_endPoint);
}
void GeLine::TransformBy(ads_matrix mat)
{
m_startPoint.TransformBy(mat);
m_endPoint.TransformBy(mat);
}
bool GeLine::IsKindOf(GeEntity::TEntityId entType) const
{
switch(entType)
{
case GeEntity::eEntity:
case GeEntity::eCurve:
case GeEntity::eLinearEnt:
case GeEntity::eLine:
return true;
}
return false;
}
GeEntity::TEntityId GeLine::Type() const
{
return GeEntity::eLine;
}
int GeLine::GetExtend(ADSGePoint3d &ptlow, ADSGePoint3d &ptup) const
{
ADSGePoint3d ptStart = m_startPoint;
ADSGePoint3d ptEnd = m_endPoint;
ptlow = Min(ptStart, ptEnd);
ptup = Max(ptStart, ptEnd);
return RTNORM;
}
ads_real GeLine::GetLength() const
{
//return m_startPoint.AsAcGePoint3d().distanceTo(m_endPoint);
//return ads_distance(m_startPoint,m_endPoint);
double t1 = m_startPoint.x - m_endPoint.x;
double t2 = m_startPoint.y - m_endPoint.y;
double t3 = m_startPoint.z - m_endPoint.z;
return sqrt(t1 * t1 + t2 * t2 + t3 * t3);
}
ads_real GeLine::Direction() const
{
return ads_angle(m_startPoint,
m_endPoint);
}
TVector3D GeLine::Direction3d() const
{
ASSERT(GetLength() > g_Option::instance()._DIST_SNAP);
TVector3D vt = m_endPoint - m_startPoint;
vt.Normalize();
return vt;
}
ads_real GeLine::PathArea() const
{
ADSGePoint3d ptStart = m_startPoint;
ADSGePoint3d ptEnd = m_endPoint;
return (ptEnd.x - ptStart.x) * (ptStart.y + ptEnd.y) / 2.0;
}
int GeLine::operator !() const
{
return m_endPoint == m_startPoint;
}
bool GeLine::operator == (const GeLine& aLine) const
{
ADSGePoint3d ptStart = m_startPoint;
ADSGePoint3d ptEnd = m_endPoint;
int nFlag = m_nFlag;
ADSGePoint3d ptStartSrc = aLine.GetStartPoint();
ADSGePoint3d ptEndSrc = aLine.GetEndPoint();
int nFlagSrc = aLine.GetLineFlag();
return (nFlag == nFlagSrc
&& (ptStart == ptStartSrc && ptEnd == ptEndSrc)
|| (ptStart == ptEndSrc && ptEnd == ptStartSrc));
}
GeLine& GeLine::operator = (const GeLine& aLine)
{
if (this != &aLine)
{
m_startPoint = aLine.m_startPoint;
m_endPoint = aLine.m_endPoint;
m_nFlag = aLine.m_nFlag;
}
return *this;
}