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