515 lines
10 KiB
C++
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;
|
|
}
|
|
|
|
|