//-----------------------------------------------------------------------------+ // 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; }