Files
envi-code/SourceCode/Code2026/tg_shs/shs_geLib/TGGeLine.cpp
T
2026-09-28 15:28:50 +08:00

515 lines
10 KiB
C++

//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TGGeLine直线类
// = Version : ver2.0
// = Author : wlw
// = CreateDate : 2002-09-09
// = Description: TGGeLine类定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TGGeLine.h"
#include "TGGePoly.h"
#include "TAcDbObjectPtr.h"
#include "TADSGePoint3d.h"
#include "TPointList.h"
#include "TchGlobalFunc.h"
#include "TchGlobalCurveFunc.h"
#include "TchPrivateGlobalFunc.h"
#include "TGGeCurveInline.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 TADSGePoint3d &pt1, const TADSGePoint3d &pt2,
const TADSGePoint3d &qt1, const TADSGePoint3d &qt2, TADSGePoint3d &ptInter)
{
if (fabs(pt1.z - pt2.z) > _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) < _DIST_SNAP * _DIST_SNAP) //重合或平行
{
return RTERROR;
}
ptInter.x = (B1 * C2 - B2 * C1) / E;
ptInter.y = (C1 * A2 - C2 * A1) / E;
ptInter.z = pt1.z;
return RTNORM;
}
TGGeLine::TGGeLine(const ads_point p1, const ads_point p2, int nflag)
{
m_startPoint = p1;
m_endPoint = p2;
m_nFlag = nflag;
}
TGGeLine::TGGeLine(const TEntitySet& entLine, int nflag , ads_matrix tranMat)
{
TAcDbObjectPtr 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);
}
}
}
TGGeLine::TGGeLine(const TGGeLine & src)
: m_startPoint(src.m_startPoint), m_endPoint(src.m_endPoint), m_nFlag(src.m_nFlag)
{
}
TGGeLine::TGGeLine(int nflag)
{
m_nFlag = nflag;
}
TGGeLine::TGGeLine(const TADSGePoint3d &ptThrough, ads_real dDrt)
: m_startPoint(ptThrough), m_nFlag(LS_INFINITE)
{
ads_polar(m_startPoint, dDrt, 100.0, m_endPoint);
}
TGGeLine::~TGGeLine()
{
}
int TGGeLine::OnWhichSide(const TADSGePoint3d &ptsrc) const
{
TGGeCurveSegment seg;
seg = *this;
return seg.OnWhichSide(ptsrc);
}
// 同两条线的特征有关
int TGGeLine::Intersection(const TGGeLine* pLine, ads_point ptrp) const
{
if (pLine != NULL)
{
// modify by xlc 100613 取消AcGe算法,速度慢
// modify by xlc on 110503 大坐标采用AcGe算法,保证精度
TADSGePoint3d 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 TGGeLine::Intersection(const TGGeArc* pArc, ads_point ptrp1, ads_point ptrp2) const
{
if ( pArc != NULL)
{
//lfy 2010-08-31 采用AcGe算法
if (!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;
TADSGePoint3d 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()) < _DIST_SNAP)
{
nt2 = 0;
}
}
return nt1 + nt2;
}
return FALSE;
}
int TGGeLine::Intersection(const TGGeCircle* pCircle, ads_point ptrp1, ads_point ptrp2) const
{
if (pCircle != NULL)
{
if (!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;
TADSGePoint3d 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)) < _DIST_SNAP)
{
nt2 = 0;
}
}
}
return nt1 + nt2;
}
return FALSE;
}
int TGGeLine::HitTest2d(const TADSGePoint3d &ptTest) const
{
double dLineLen = m_startPoint.Distance2d(m_endPoint);
if (dLineLen < _DIST_SNAP)
{
return POS_Error;
}
double dDist2Start = m_startPoint.Distance2d(ptTest);
if (dDist2Start < _DIST_SNAP)
{
return POS_Start;
}
double dDist2End = m_endPoint.Distance2d(ptTest);
if (dDist2End < _DIST_SNAP)
{
return POS_End;
}
TVector3D vtTest = ptTest - m_startPoint;
TVector3D vtThis = m_endPoint - m_startPoint;
vtThis /= dLineLen;
double dDot = (vtTest & vtThis);
if (fabs(fabs(dDot) - dDist2Start) < _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 TGGeLine::Intersection(TGGePoly* pPoly, TPointList &pts) const
{
ASSERT(pPoly != NULL);
TGGeLine aLine(LS_FINITE);
int nlen = pPoly->Length();
TADSGePoint3d 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 TGGeLine::Modify(const TEntitySet* pEntity) const
{
ASSERT(pEntity != NULL);
TEntitySet entLine = *pEntity;
if (!entLine.Is(_T("LINE")))
{
return RTERROR;
}
entLine.SetData(10, &m_startPoint);
entLine.SetData(11, &m_endPoint);
return entLine.Modify();
}
int TGGeLine::MakeEntity(const TEntitySet* pEntity) const
{
ASSERT(pEntity != NULL);
TEntitySet ent = *pEntity;
TGroups g(_T("*"));
TRBList ebuf = ads_entgetx(ent, (resbuf *)&g);
ebuf.SetData(10, &m_startPoint);
ebuf.SetData(11, &m_endPoint);
return ads_entmake(ebuf);
}
int TGGeLine::Make(const TCHAR *szlay) const
{
TCHAR szlayer[80] = _T("");
if (szlay)
{
_tcscpy(szlayer, szlay);
}
else
{
TGGetVar(_T("clayer"), szlayer);
}
return TchExport::MakeEntity(RTDXF0, _T("LINE"), 10,
&m_startPoint.x,11,
&m_endPoint.x, 8, szlayer, NULL);
}
int TGGeLine::OSnap(int nMode, TADSGePoint3d &ptPick) const
{
TGGeLine &ln = *(TGGeLine *)this;
switch(nMode)
{
case OS_END:
ptPick = ln.NearPoint(ptPick);
return nMode;
case OS_MID:
ptPick = MidPoint();
return nMode;
case OS_NEA:
{
TADSGePoint3d 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;
}
TGGeLine TGGeLine::Offset(ads_real ddist) const
{
TADSGePoint3d spt, ept;
ads_real dang = AngleRangeTo2PI(Direction() - PI / 2.0);
ads_polar(m_startPoint, dang, ddist, spt);
ads_polar(m_endPoint, dang, ddist, ept);
return TGGeLine(spt, ept);
}
int TGGeLine::GetSubLine(const TADSGePoint3d &ptLoc, ads_real ddist, TGGeLine& 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;
}