492 lines
9.2 KiB
C++
492 lines
9.2 KiB
C++
//-----------------------------------------------------------------------------+
|
|
// Copyright (C), 1998-2007, SH Software Co. Ltd.
|
|
// = FileName : XLine直线类
|
|
// = Version : ver2.0
|
|
// = Author : zjq
|
|
// = CreateDate : 2002-09-09
|
|
// = Description: XLine类定义
|
|
// = Maintainers:
|
|
//
|
|
//-----------------------------------------------------------------------------+
|
|
#include "StdAfx.h"
|
|
#include "XLine.h"
|
|
#include "XPoly.h"
|
|
#include "XDbObject.h"
|
|
#include "XPoint.h"
|
|
#include "PointList.h"
|
|
#include "XGlobalFunc.h"
|
|
#include "XGlobalCurveFunc.h"
|
|
#include "XPrivateGlobalFunc.h"
|
|
#include "XCurveInline.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 XPoint &pt1, const XPoint &pt2,
|
|
const XPoint &qt1, const XPoint &qt2, XPoint &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;
|
|
}
|
|
|
|
XLine::XLine(const ads_point p1, const ads_point p2, int nflag)
|
|
{
|
|
m_startPoint = p1;
|
|
m_endPoint = p2;
|
|
m_nFlag = nflag;
|
|
}
|
|
|
|
XLine::XLine(const Entity& entLine, int nflag , ads_matrix tranMat)
|
|
{
|
|
XDbObject 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
XLine::XLine(const XLine & src)
|
|
: m_startPoint(src.m_startPoint), m_endPoint(src.m_endPoint), m_nFlag(src.m_nFlag)
|
|
{
|
|
|
|
}
|
|
|
|
XLine::XLine(int nflag)
|
|
{
|
|
m_nFlag = nflag;
|
|
}
|
|
|
|
XLine::XLine(const XPoint &ptThrough, ads_real dDrt)
|
|
: m_startPoint(ptThrough), m_nFlag(LS_INFINITE)
|
|
{
|
|
ads_polar(m_startPoint, dDrt, 100.0, m_endPoint);
|
|
}
|
|
|
|
XLine::~XLine()
|
|
{
|
|
|
|
}
|
|
|
|
int XLine::OnWhichSide(const XPoint &ptsrc) const
|
|
{
|
|
XCurveSegment seg;
|
|
seg = *this;
|
|
return seg.OnWhichSide(ptsrc);
|
|
}
|
|
|
|
// 同两条线的特征有关
|
|
int XLine::Intersection(const XLine* pLine, ads_point ptrp) const
|
|
{
|
|
if (pLine != NULL)
|
|
{
|
|
XPoint ptGe;
|
|
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 XLine::Intersection(const XArc* pArc, ads_point ptrp1, ads_point ptrp2) const
|
|
{
|
|
if ( pArc != NULL)
|
|
{
|
|
//zjq 2009-08-31 采用AcGe算法
|
|
if (!IsEqual(1.0E-5, 3, pArc->GetCenterPt().z, m_startPoint.z, m_endPoint.z))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//zjq 2009-08-31 修改存取方式
|
|
AcGeLine3d lineT(m_startPoint.AsAcGePoint3d(),m_endPoint.AsAcGePoint3d());
|
|
AcGeCircArc3d cirO(pArc->m_ptCenter.AsAcGePoint3d(),AcGeVector3d::kZAxis,pArc->m_dRadius);
|
|
|
|
int nInt = 0;
|
|
XPoint 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 XLine::Intersection(const XCircle* 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;
|
|
XPoint 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 XLine::HitTest2d(const XPoint &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;
|
|
}
|
|
|
|
XVector3D vtTest = ptTest - m_startPoint;
|
|
XVector3D 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
|
|
{
|
|
XVector3D vtCross = (vtTest*vtThis);
|
|
if (vtCross.z > 0)
|
|
{
|
|
return POS_Rigth;
|
|
}
|
|
|
|
if (vtCross.z < 0)
|
|
{
|
|
return POS_Left;
|
|
}
|
|
}
|
|
|
|
return POS_Error;
|
|
}
|
|
|
|
int XLine::Intersection(XPoly* pPoly, PointList &pts) const
|
|
{
|
|
ASSERT(pPoly != NULL);
|
|
|
|
XLine aLine(LS_FINITE);
|
|
int nlen = pPoly->Length();
|
|
XPoint 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 XLine::Modify(const Entity* pEntity) const
|
|
{
|
|
ASSERT(pEntity != NULL);
|
|
Entity entLine = *pEntity;
|
|
if (!entLine.Is(_T("LINE")))
|
|
{
|
|
return RTERROR;
|
|
}
|
|
|
|
entLine.SetData(10, &m_startPoint);
|
|
entLine.SetData(11, &m_endPoint);
|
|
|
|
return entLine.Modify();
|
|
}
|
|
|
|
int XLine::MakeEntity(const Entity* pEntity) const
|
|
{
|
|
ASSERT(pEntity != NULL);
|
|
Entity ent = *pEntity;
|
|
Groups g(_T("*"));
|
|
RBList ebuf = ads_entgetx(ent, (resbuf *)&g);
|
|
ebuf.SetData(10, &m_startPoint);
|
|
ebuf.SetData(11, &m_endPoint);
|
|
|
|
return ads_entmake(ebuf);
|
|
}
|
|
|
|
int XLine::Make(const TCHAR *szlay) const
|
|
{
|
|
TCHAR szlayer[80] = _T("");
|
|
if (szlay)
|
|
{
|
|
_tcscpy(szlayer, szlay);
|
|
}
|
|
else
|
|
{
|
|
xg_getvar(_T("clayer"), szlayer);
|
|
}
|
|
|
|
return XExport::MakeEntity(RTDXF0, _T("LINE"), 10,
|
|
&m_startPoint.x,11,
|
|
&m_endPoint.x, 8, szlayer, NULL);
|
|
}
|
|
|
|
int XLine::OSnap(int nMode, XPoint &ptPick) const
|
|
{
|
|
XLine &ln = *(XLine *)this;
|
|
switch(nMode)
|
|
{
|
|
case OS_END:
|
|
ptPick = ln.NearPoint(ptPick);
|
|
return nMode;
|
|
case OS_MID:
|
|
ptPick = MidPoint();
|
|
return nMode;
|
|
case OS_NEA:
|
|
{
|
|
XPoint 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;
|
|
}
|
|
|
|
XLine XLine::Offset(ads_real ddist) const
|
|
{
|
|
XPoint spt, ept;
|
|
ads_real dang = CT_std_angle(Direction() - PI / 2.0);
|
|
|
|
ads_polar(m_startPoint, dang, ddist, spt);
|
|
ads_polar(m_endPoint, dang, ddist, ept);
|
|
|
|
return XLine(spt, ept);
|
|
}
|
|
|
|
int XLine::GetSubLine(const XPoint &ptLoc, ads_real ddist, XLine& 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;
|
|
}
|
|
|
|
|