#include "StdAfx.h" #include "GeLine.h" #include "globalfunc.h" #include "GePoly.h" #include "AcDbObjectPtr.h" #include "ADSGePoint3d.h" #include "PointList.h" #include "GeCurveInline.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 ADSGePoint3d &pt1, const ADSGePoint3d &pt2, const ADSGePoint3d &qt1, const ADSGePoint3d &qt2, ADSGePoint3d &ptInter) { if (fabs(pt1.z - pt2.z) > g_Option::instance()._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) < g_Option::instance()._DIST_SNAP * g_Option::instance()._DIST_SNAP) //重合或平行 { return RTERROR; } ptInter.x = (B1 * C2 - B2 * C1) / E; ptInter.y = (C1 * A2 - C2 * A1) / E; ptInter.z = pt1.z; return RTNORM; } GeLine::GeLine(const ads_point p1, const ads_point p2, int nflag) { m_startPoint = p1; m_endPoint = p2; m_nFlag = nflag; } GeLine::GeLine(const EntitySet& entLine, int nflag , ads_matrix tranMat) { AcDbObjectPtr 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); } } } GeLine::GeLine(const GeLine & src) : m_startPoint(src.m_startPoint), m_endPoint(src.m_endPoint), m_nFlag(src.m_nFlag) { } GeLine::GeLine(int nflag) { m_nFlag = nflag; } GeLine::GeLine(const ADSGePoint3d &ptThrough, ads_real dDrt) : m_startPoint(ptThrough), m_nFlag(LS_INFINITE) { ads_polar(m_startPoint, dDrt, 100.0, m_endPoint); } GeLine::~GeLine() { } int GeLine::OnWhichSide(const ADSGePoint3d &ptsrc) const { GeCurveSegment seg; seg = *this; return seg.OnWhichSide(ptsrc); } // 同两条线的特征有关 int GeLine::Intersection(const GeLine* pLine, ads_point ptrp) const { if (pLine != NULL) { // modify by xlc 100613 取消AcGe算法,速度慢 // modify by xlc on 110503 大坐标采用AcGe算法,保证精度 ADSGePoint3d 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 GeLine::Intersection(const GeArc* pArc, ads_point ptrp1, ads_point ptrp2) const { if ( pArc != NULL) { //lfy 2010-08-31 采用AcGe算法 if (!GlobalFunc::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; ADSGePoint3d 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()) < g_Option::instance()._DIST_SNAP) { nt2 = 0; } } return nt1 + nt2; } return FALSE; } int GeLine::Intersection(const GeCircle* pCircle, ads_point ptrp1, ads_point ptrp2) const { if (pCircle != NULL) { if (!GlobalFunc::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; ADSGePoint3d 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)) < g_Option::instance()._DIST_SNAP) { nt2 = 0; } } } return nt1 + nt2; } return FALSE; } int GeLine::HitTest2d(const ADSGePoint3d &ptTest) const { double dLineLen = m_startPoint.Distance2d(m_endPoint); if (dLineLen < g_Option::instance()._DIST_SNAP) { return POS_Error; } double dDist2Start = m_startPoint.Distance2d(ptTest); if (dDist2Start < g_Option::instance()._DIST_SNAP) { return POS_Start; } double dDist2End = m_endPoint.Distance2d(ptTest); if (dDist2End < g_Option::instance()._DIST_SNAP) { return POS_End; } TVector3D vtTest = ptTest - m_startPoint; TVector3D vtThis = m_endPoint - m_startPoint; vtThis /= dLineLen; using namespace GlobalFunc; double dDot = (vtTest & vtThis); if (fabs(fabs(dDot) - dDist2Start) < g_Option::instance()._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 GeLine::Intersection(GePoly* pPoly, PointList &pts) const { ASSERT(pPoly != NULL); GeLine aLine(LS_FINITE); int nlen = pPoly->Length(); ADSGePoint3d 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 GeLine::Modify(const EntitySet* pEntity) const { ASSERT(pEntity != NULL); EntitySet entLine = *pEntity; if (!entLine.Is(_T("LINE"))) { return RTERROR; } entLine.SetData(10, &m_startPoint); entLine.SetData(11, &m_endPoint); return entLine.Modify(); } int GeLine::MakeEntity(const EntitySet* pEntity) const { ASSERT(pEntity != NULL); EntitySet ent = *pEntity; RBGroups g(_T("*")); RBList ebuf = ads_entgetx(ent, (resbuf *)&g); ebuf.SetData(10, &m_startPoint); ebuf.SetData(11, &m_endPoint); return ads_entmake(ebuf); } int GeLine::Make(const TCHAR *szlay) const { TCHAR szlayer[80] = _T(""); if (szlay) { _tcscpy(szlayer, szlay); } else { GlobalFunc::TGGetVar(_T("clayer"), szlayer); } return GlobalFunc::MakeEntity(RTDXF0, _T("LINE"), 10, &m_startPoint.x,11, &m_endPoint.x, 8, szlayer, NULL); } int GeLine::OSnap(int nMode, ADSGePoint3d &ptPick) const { GeLine &ln = *(GeLine *)this; switch(nMode) { case OS_END: ptPick = ln.NearPoint(ptPick); return nMode; case OS_MID: ptPick = MidPoint(); return nMode; case OS_NEA: { ADSGePoint3d 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; } GeLine GeLine::Offset(ads_real ddist) const { ADSGePoint3d spt, ept; ads_real dang = GlobalFunc::AngleRangeTo2PI(Direction() - PI / 2.0); ads_polar(m_startPoint, dang, ddist, spt); ads_polar(m_endPoint, dang, ddist, ept); return GeLine(spt, ept); } int GeLine::GetSubLine(const ADSGePoint3d &ptLoc, ads_real ddist, GeLine& 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; } int GeLine::operator != (const GeLine& aLine) const { return !((*this) == aLine); } void GeLine::SetStartPoint(ADSGePoint3d ptStart) { m_startPoint = ptStart; } void GeLine::GetStartPoint(ADSGePoint3d& ptStart) { ptStart = m_startPoint; } ADSGePoint3d GeLine::GetStartPoint() const { return m_startPoint; } void GeLine::SetEndPoint(ADSGePoint3d ptEnd) { m_endPoint = ptEnd; } void GeLine::GetEndPoint(ADSGePoint3d& ptEnd) { ptEnd = m_endPoint; } ADSGePoint3d GeLine::GetEndPoint() const { return m_endPoint; } ADSGePoint3d& GeLine::StartPoint() { return m_startPoint; } ADSGePoint3d& GeLine::EndPoint() { return m_endPoint; } ADSGePoint3d& GeLine::StartPoint() const { return (ADSGePoint3d&)m_startPoint; } ADSGePoint3d& GeLine::EndPoint() const { return (ADSGePoint3d&)m_endPoint; } void GeLine::SetLineFlag(int nFlag) { m_nFlag = nFlag; } int GeLine::GetLineFlag() const { return m_nFlag; } void GeLine::SetPoints(const ADSGePoint3d& pt1, const ADSGePoint3d& pt2) { m_startPoint = pt1; m_endPoint = pt2; } void GeLine::SetElevation(ads_real delev) { m_startPoint.z = delev; m_endPoint.z = delev; } void GeLine::Reverse() { ADSGePoint3d pttmp = m_startPoint; m_startPoint = m_endPoint; m_endPoint = pttmp; } ads_real* GeLine::NearPoint(const ads_point pt0) { if (ads_distance((ads_real *)pt0, (ads_real *)m_startPoint) < ads_distance((ads_real *)pt0, (ads_real *)m_endPoint)) { return &m_startPoint.x; } return &m_endPoint.x; } ads_real* GeLine::FarPoint(const ads_point pt0) { if (ads_distance((ads_real *)pt0, m_startPoint) > ads_distance((ads_real *)pt0,m_endPoint)) { return &m_startPoint.x; } return &m_endPoint.x; } ADSGePoint3d GeLine::MidPoint() const { ADSGePoint3d ptMid; ptMid.x = (m_startPoint.x + m_endPoint.x) / 2.0; ptMid.y = (m_startPoint.y + m_endPoint.y) / 2.0; ptMid.z = (m_startPoint.z + m_endPoint.z) / 2.0; return ptMid; } void GeLine::MidPoint(ADSGePoint3d& ptres) const { ptres.x = (m_startPoint.x + m_endPoint.x) / 2.0; ptres.y = (m_startPoint.y + m_endPoint.y) / 2.0; ptres.z = (m_startPoint.z + m_endPoint.z) / 2.0; } void GeLine::TransUCS(const resbuf *pfrom, const resbuf *pto) { ADSGePoint3d spt = m_startPoint, ept = m_endPoint; ads_trans(spt, pfrom, pto, 0, m_startPoint); ads_trans(ept, pfrom, pto, 0, m_endPoint); } void GeLine::TransformBy(ads_matrix mat) { m_startPoint.TransformBy(mat); m_endPoint.TransformBy(mat); } bool GeLine::IsKindOf(GeEntity::TEntityId entType) const { switch(entType) { case GeEntity::eEntity: case GeEntity::eCurve: case GeEntity::eLinearEnt: case GeEntity::eLine: return true; } return false; } GeEntity::TEntityId GeLine::Type() const { return GeEntity::eLine; } int GeLine::GetExtend(ADSGePoint3d &ptlow, ADSGePoint3d &ptup) const { ADSGePoint3d ptStart = m_startPoint; ADSGePoint3d ptEnd = m_endPoint; ptlow = Min(ptStart, ptEnd); ptup = Max(ptStart, ptEnd); return RTNORM; } ads_real GeLine::GetLength() const { //return m_startPoint.AsAcGePoint3d().distanceTo(m_endPoint); //return ads_distance(m_startPoint,m_endPoint); double t1 = m_startPoint.x - m_endPoint.x; double t2 = m_startPoint.y - m_endPoint.y; double t3 = m_startPoint.z - m_endPoint.z; return sqrt(t1 * t1 + t2 * t2 + t3 * t3); } ads_real GeLine::Direction() const { return ads_angle(m_startPoint, m_endPoint); } TVector3D GeLine::Direction3d() const { ASSERT(GetLength() > g_Option::instance()._DIST_SNAP); TVector3D vt = m_endPoint - m_startPoint; vt.Normalize(); return vt; } ads_real GeLine::PathArea() const { ADSGePoint3d ptStart = m_startPoint; ADSGePoint3d ptEnd = m_endPoint; return (ptEnd.x - ptStart.x) * (ptStart.y + ptEnd.y) / 2.0; } int GeLine::operator !() const { return m_endPoint == m_startPoint; } bool GeLine::operator == (const GeLine& aLine) const { ADSGePoint3d ptStart = m_startPoint; ADSGePoint3d ptEnd = m_endPoint; int nFlag = m_nFlag; ADSGePoint3d ptStartSrc = aLine.GetStartPoint(); ADSGePoint3d ptEndSrc = aLine.GetEndPoint(); int nFlagSrc = aLine.GetLineFlag(); return (nFlag == nFlagSrc && (ptStart == ptStartSrc && ptEnd == ptEndSrc) || (ptStart == ptEndSrc && ptEnd == ptStartSrc)); } GeLine& GeLine::operator = (const GeLine& aLine) { if (this != &aLine) { m_startPoint = aLine.m_startPoint; m_endPoint = aLine.m_endPoint; m_nFlag = aLine.m_nFlag; } return *this; }