#include "stdafx.h" #include "commonRoad.h" #include "RoolBackNew.h" #include "Road.h" #include #include "InterStruct.h" CInterStruct::CInterStruct(void) { m_dwFlag = 0; SetInEdge(TRUE); ClearFlag(eFlagComplexOut); SetShortFlag(false); SetDoneFlag(false); SetInRoadFlag(false); SetFlag(eFlagEdgeOrMid); ClearFlag(eFlagAttached);// 没有关联,初始设置无关联 SetAttachedStruct(NULL); SetPara(FALSE); // 不平行的 SetDrawed(FALSE); } CInterStruct::~CInterStruct(void) { } BOOL CInterStruct::IsMidofInterStruct(CInterStruct *pInter1, CInterStruct *pInter2) const { if (this->ToLineInter() != NULL) { return this->ToLineInter()->IsMidofInterStruct(pInter1->ToLineInter(), pInter2->ToLineInter()); } else { return this->ToArcInter()->IsMidofInterStruct(pInter1->ToArcInter(), pInter2->ToArcInter()); } } BOOL CInterStruct::IsNeedCreate(const CCADEntEdgeAdapter &entThis) const { if (IsErased()) return FALSE; if (IsAttached()) { // 两个都还没有绘制,才需要重新绘制。 return !IsDrawed() && !AttachedStruct()->IsDrawed();// } else // return IsDone(); return entThis.NeedReCreate() && !IsInRoad(); } ////////////////////////////////////////////////////////////////////////// // CLineInterStruct CLineInterStruct::CLineInterStruct(CLineCADEntEdgeAdapter &lineEnt) : m_lineEnt(lineEnt), CInterStruct() { lineEnt.AddInterStruct(this); } CLineInterStruct::~CLineInterStruct(void){} AcGeLineSeg2d CLineInterStruct::OriginLine() const { return m_lineEnt.Line(); } AcGeLineSeg2d CLineInterStruct::InterLine() const { return m_interLine; } void CLineInterStruct::SetInterLine(const AcGeLineSeg2d &line) { m_interLine = line; } CLineInterStruct* CLineInterStruct::ToLineInter() const { return (CLineInterStruct*)this; } // 需要检测自己的bAttach标志,并且假如成功创建后,别人的Attach标志。 void CLineInterStruct::CreateNew() { ASSERT(IsMidRoad()); // 如果设置了creatFlag, 或者 没有设置CreatFlag,但是对应的实体已经被删除了,都要重新建立该interStruct线 if (IsNeedCreate(m_lineEnt)) { // AcDbLine *pLine = NULL; if (m_pInterStructAttached != NULL) { CLineInterStruct* pLineInterAttached = (CLineInterStruct*)m_pInterStructAttached; AcGePoint2d ptStart = IsStart() ? m_interLine.startPoint() : pLineInterAttached->InterLine().startPoint(); AcGePoint2d ptEnd = !IsStart() ? InterLine().endPoint() : pLineInterAttached->InterLine().endPoint(); pLine = GeLineToDbLineSys(AcGeLineSeg2d(ptStart, ptEnd)); m_pInterStructAttached->BeAttached(); } else pLine = GeLineToDbLineSys(m_interLine); SetLayer(pLine, eRoadMidType); RoolBackAddNewData(pLine); SetDrawed(TRUE); } } void CLineInterStruct::EraseOldObject() { if (m_lineEnt.NeedReCreate()) m_lineEnt.RoolBackErase(); } double CLineInterStruct::Lenth() const { return m_interLine.startPoint().distanceTo(m_interLine.endPoint()); } double CLineInterStruct::DistanceTo(const AcGePoint2d &pt) const { return m_interLine.distanceTo(pt); } void CLineInterStruct::SetCreateFlag() { m_lineEnt.SetReCreateFlag(); SetDoneFlag(true); }; AcGeVector2d CLineInterStruct::Direction() const { if (IsStart()) { return InterLine().direction(); } else return -InterLine().direction(); } BOOL CLineInterStruct::CombinInterStrcutInSequence(CInterStruct *pInterNext) { ASSERT(pInterNext->ToLineInter() != NULL); CLineInterStruct *pLineNext = (CLineInterStruct*)pInterNext; ASSERT((&m_lineEnt) == (&(pLineNext->m_lineEnt))); if((this->InterLine().endPoint().distanceTo(pLineNext->InterLine().startPoint()) > 1.0)) return FALSE; AcGePoint2d ptStart = InterLine().startPoint() ; AcGePoint2d ptEnd = pLineNext->InterLine().endPoint() ; SetInterLine(AcGeLineSeg2d(ptStart, ptEnd)); return TRUE; } BOOL CLineInterStruct::CombinAttachInterStruct() { ASSERT(AttachedStruct() != NULL); CLineInterStruct *pLineAttached = (CLineInterStruct*)AttachedStruct(); CLineInterStruct *pLineInter1 = IsStart() ? this : pLineAttached; CLineInterStruct *pLineInter2 = IsStart() ? pLineAttached : this; AcGePoint2d ptStart, ptEnd; if (pLineInter1->IsDone() && pLineInter2->IsDone()) { ptStart = pLineInter1->InterLine().startPoint() ; ptEnd = pLineInter2->InterLine().endPoint(); SetInterLine(AcGeLineSeg2d(ptStart, ptEnd)); } else if (pLineInter1->IsDone() || pLineInter2->IsDone()) { ptStart = pLineInter1->IsDone() ? pLineInter1->InterLine().startPoint() : pLineInter1->OriginLine().startPoint(); ptEnd = pLineInter2->IsDone() ? pLineInter2->InterLine().endPoint() : pLineInter2->OriginLine().endPoint(); SetInterLine(AcGeLineSeg2d(ptStart, ptEnd)); this->SetDoneFlag(true); } else { // do nothing } return TRUE; } void CLineInterStruct::SimpleCreate() { AcDbLine *pLine = NULL; pLine = GeLineToDbLineSys(InterLine()); SetLayer(pLine, IsEdge() ? eRoadEdgeType : eRoadMidType); RoolBackAddNewData(pLine); } CLineInterStruct CLineInterStruct::DumpStruct() { CLineCADEntEdgeAdapter lineAdapter; CLineInterStruct lineInter(lineAdapter); return lineInter; } // 检测thisInterStruct是否位于pInter1和pInter2之间。 // 本函数用于检测所得到的线是否是两条道路的中线。 BOOL CLineInterStruct::IsMidofInterStruct(CLineInterStruct *pInter1, CLineInterStruct *pInter2) const { if ((pInter1 == NULL) || (pInter2 == NULL)) return FALSE; // 1、this.interPoint 在pInter1和pInter2之间。 // interPoint求向两条边的垂线,这两个向量的方向相反(点积<0) AcGeLine2d line1 = ToLine(pInter1->InterLine()); AcGeLine2d line2 = ToLine(pInter2->InterLine()); AcGePoint2d ptPerp1 = line1.closestPointTo(InterPoint()); AcGePoint2d ptperp2 = line2.closestPointTo(InterPoint()); AcGeVector2d vecToInter1 = InterPoint() - ptPerp1; AcGeVector2d vecToInter2 = InterPoint() - ptperp2; if (vecToInter1.dotProduct(vecToInter2) > 0) return FALSE; // 代表点不在两条道路中间 // 2、this Inter的方向跟pInter1,和pInter2的方向相同。 AcGeVector2d vecInter = this->Direction(); if ((vecInter.dotProduct(pInter1->Direction()) > 1e-6) && (vecInter.dotProduct(pInter2->Direction()) > 1e-6)) return TRUE; else return FALSE; } ////////////////////////////////////////////////////////////////////////// // CArcInterStruct CArcInterStruct::CArcInterStruct(CArcCADEntEdgeAdapter &arcEnt) : m_arcEnt(arcEnt), CInterStruct() { arcEnt.AddInterStruct(this); } CArcInterStruct::~CArcInterStruct(void){} AcGeCircArc2d CArcInterStruct::OriginArc() const { return m_arcEnt.Arc(); } AcGeCircArc2d CArcInterStruct::InterArc() const { return m_interArc; } void CArcInterStruct::SetInterArc(const AcGeCircArc2d &arc) { m_interArc = arc; } void CArcInterStruct::CreateNew() { ASSERT(IsMidRoad()); if (IsNeedCreate(m_arcEnt)) { // 开始创建 AcDbArc *pArc = new AcDbArc(); if (m_pInterStructAttached != NULL) { CArcInterStruct* pArcInterAttached = (CArcInterStruct*)m_pInterStructAttached; AcGePoint2d ptStart = IsStart() ? InterArc().startPoint() : pArcInterAttached->InterArc().startPoint(); AcGePoint2d ptEnd = !IsStart() ? InterArc().endPoint() : pArcInterAttached->InterArc().endPoint(); GeArcToDbSys(ConNewArc(m_interArc, ptStart, ptEnd), *pArc); m_pInterStructAttached->BeAttached(); } else GeArcToDbSys(m_interArc, *pArc); SetLayer(pArc, IsEdge() ? eRoadEdgeType : eRoadMidType); RoolBackAddNewData(pArc); SetDrawed(TRUE); } } void CArcInterStruct::EraseOldObject() { if (m_arcEnt.NeedReCreate()) m_arcEnt.RoolBackErase(); } void CArcInterStruct::SetCreateFlag() { m_arcEnt.SetReCreateFlag(); SetDoneFlag(true); } CArcInterStruct* CArcInterStruct::ToArcInter( ) const { return (CArcInterStruct*)this; } double CArcInterStruct::Lenth() const { return m_interArc.length(m_interArc.startAng(), m_interArc.endAng()); } double CArcInterStruct::DistanceTo(const AcGePoint2d &pt) const { return m_interArc.distanceTo(pt); } AcGeVector2d CArcInterStruct::Direction() const { return IsStart() ? TanVecOfArcStartPoint(InterArc()) : TanVecOfArcEndPoint(InterArc()); } BOOL CArcInterStruct::CombinInterStrcutInSequence(CInterStruct *pInterNext) { ASSERT(pInterNext->ToArcInter() != NULL); CArcInterStruct *pArcNext = pInterNext->ToArcInter(); ASSERT((&m_arcEnt) == (&(pArcNext->m_arcEnt))); if(this->InterArc().endPoint().distanceTo(pArcNext->InterArc().startPoint()) > 1.0) return FALSE; AcGePoint2d ptStart = InterArc().startPoint() ; AcGePoint2d ptEnd = pArcNext->InterArc().endPoint() ; SetInterArc(ConNewArc(InterArc(), ptStart, ptEnd)); return TRUE; } BOOL CArcInterStruct::CombinAttachInterStruct() { ASSERT(AttachedStruct() != NULL); CArcInterStruct *pArcAttached = AttachedStruct()->ToArcInter(); CArcInterStruct *pArcInter1 = IsStart() ? this : pArcAttached; CArcInterStruct *pArcInter2 = IsStart() ? pArcAttached : this; AcGePoint2d ptStart, ptEnd; if (pArcInter1->IsDone() && pArcInter2->IsDone()) { ptStart = pArcInter1->InterArc().startPoint() ; ptEnd = pArcInter2->InterArc().endPoint(); SetInterArc(ConNewArc(InterArc(), ptStart, ptEnd)); } else if (pArcInter1->IsDone() || pArcInter2->IsDone()) { ptStart = pArcInter1->IsDone() ? pArcInter1->InterArc().startPoint() : pArcInter1->OriginArc().startPoint(); ptEnd = pArcInter2->IsDone() ? pArcInter2->InterArc().endPoint() : pArcInter2->OriginArc().endPoint(); SetInterArc(ConNewArc(InterArc(), ptStart, ptEnd)); this->SetDoneFlag(true); } else { // do nothing } return TRUE; } void CArcInterStruct::SimpleCreate() { AcDbArc *pArc = new AcDbArc; GeArcToDbSys(InterArc(), *pArc); SetLayer(pArc, IsEdge() ? eRoadEdgeType : eRoadMidType); RoolBackAddNewData(pArc); } CArcInterStruct CArcInterStruct::DumpStruct() { CArcCADEntEdgeAdapter arcAdatper; CArcInterStruct arcInter(arcAdatper); return arcInter; } // 检测thisInterStruct是否位于pInter1和pInter2之间。 // 本函数用于检测本线(中线)是否是两条道路的中线。 BOOL CArcInterStruct::IsMidofInterStruct(CArcInterStruct *pInter1, CArcInterStruct *pInter2) const { if ((pInter1 == NULL) || (pInter2 == NULL)) return FALSE; // 算法: //1、通过圆弧的半径和圆心来筛选,即:中线半径在pInter1和pInter2之间,圆心相同 //2、通过交点处角度筛选:中线在该点处的切线方向在另外两个边之间。 AcGeCircArc2d thisArc = InterArc(); AcGeCircArc2d arc1 = pInter1->InterArc(); AcGeCircArc2d arc2 = pInter2->InterArc(); double dBigRadius = arc1.radius(); double dSamllRadius = arc2.radius(); if (dBigRadius < dSamllRadius) SWAP(dBigRadius, dSamllRadius); AcGeTol tol; tol.setEqualPoint(1.0); tol.setEqualVector(1.0); // 通过圆心和半径来筛选,要求:圆心相同,中线半径在两个pInter之间 if (!thisArc.center().isEqualTo(arc1.center(), tol) || !thisArc.center().isEqualTo(arc2.center(), tol)) return FALSE; if (thisArc.radius() > dBigRadius && thisArc.radius() < dSamllRadius) return FALSE; // 角度 double dAnglethis = this->Direction().angle(); double dangle1 = pInter1->Direction().angle(); double dangle2 = pInter2->Direction().angle(); // 角度近似相同 if (SameAngle(dAnglethis, dangle1, 0.1) || SameAngle(dAnglethis, dangle2, 0.1)) return TRUE; // CAD中的圆弧都是逆时针的 if (AngleInClock(false, dangle1, dangle2) > PI) SWAP(dangle1, dangle2); // 角度在二者之间。 if (AngleInClock(false, dangle1, dAnglethis) < AngleInClock(false, dangle1, dangle2)) return TRUE; else return FALSE; } // 构造CLineInterStruct。 CLineInterStruct* ConInterStruct(const AcGeLineSeg2d &lineEdge, bool bStart, const CRoad &road, CLineCADEntEdgeAdapter &ent, AcGeTol &geTol, BOOL bPara, BOOL bMid, BOOL bComplexOut, EPointAtRoadInDir eComplexPos) { CLineInterStruct *pLineInterStruct = new CLineInterStruct(ent); // ent构造 AcGePoint2d ptInter = bStart ? lineEdge.startPoint() : lineEdge.endPoint(); // 交点 pLineInterStruct->SetInterLine(lineEdge); // pLineInterStruct->SetStart(bStart); pLineInterStruct->SetInEdge(ent.Line().isOn(ptInter, geTol)); // 交点是否在原始边线上 if (!bComplexOut) pLineInterStruct->SetPostion(road.PointAtRoadInDir(ptInter)); else pLineInterStruct->SetPostion(eComplexPos); pLineInterStruct->SetInterPoint(ptInter); // 设置交点。 pLineInterStruct->SetAttachedStruct(NULL); if (bMid) pLineInterStruct->SetMidFlag(); // 中线标记 pLineInterStruct->SetPara(bPara); if (bComplexOut) pLineInterStruct->SetComplexOutFlag(); // 复杂外交线标记 return pLineInterStruct; } // 构造CArcInterStruct结构 CArcInterStruct* ConInterStruct(const AcGeCircArc2d &arcEdge, bool bStart, const CRoad &road, CArcCADEntEdgeAdapter &ent, AcGeTol &geTol, BOOL bPara, BOOL bMid, BOOL bComplexOut, EPointAtRoadInDir eComplexPos) { CArcInterStruct *pArcInterStruct = new CArcInterStruct(ent); AcGePoint2d ptInter = bStart ? arcEdge.startPoint() : arcEdge.endPoint(); pArcInterStruct->SetInterArc(arcEdge); // pArcInterStruct->SetStart(bStart); pArcInterStruct->SetInEdge(ent.Arc().isOn(ptInter, geTol)); if (!bComplexOut) pArcInterStruct->SetPostion(road.PointAtRoadInDir(ptInter)); else pArcInterStruct->SetPostion(eComplexPos); pArcInterStruct->SetInterPoint(ptInter); pArcInterStruct->SetAttachedStruct(NULL); if (bMid) pArcInterStruct->SetMidFlag(); pArcInterStruct->SetPara(bPara); if (bComplexOut) pArcInterStruct->SetComplexOutFlag(); return pArcInterStruct; } CLineInterStruct* ConInterStructInRoad(const AcGeLineSeg2d &lineEdge, CLineCADEntEdgeAdapter &ent) { CLineInterStruct *pLineInter = new CLineInterStruct(ent); pLineInter->SetInterLine(lineEdge); pLineInter->SetInRoadFlag(true); return pLineInter; } CArcInterStruct* ConInterStructInRoad(const AcGeCircArc2d &arcEdge, CArcCADEntEdgeAdapter &ent) { CArcInterStruct *pArcInter = new CArcInterStruct(ent); pArcInter->SetInterArc(arcEdge); pArcInter->SetInRoadFlag(true); return pArcInter; } void CLineInterStruct::SimpleCreateForLandScape() { AcDbLine *pLine = NULL; pLine = GeLineToDbLineSys(InterLine()); pLine->setVisibility(m_bIsVisible); AcDbObjectId idLayer = InitLayer(LAY_LSCP_ROAD); pLine->setLayer(idLayer); AcDbObjectId objectid = RoolBackAddNewData(pLine); if (m_GroupId.isValid()) { OPENOBJ_BEGIN(m_GroupId, AcDb::kForWrite, AcDbGroup, pGroup) if (pGroup) { pGroup->append(objectid); } OPENOBJ_END() } } void CArcInterStruct::SimpleCreateForLandScape() { AcDbArc *pArc = new AcDbArc; GeArcToDbSys(InterArc(), *pArc); pArc->setVisibility(m_bIsVisible); AcDbObjectId idLayer = InitLayer(LAY_LSCP_ROAD); pArc->setLayer(idLayer); AcDbObjectId objectid = RoolBackAddNewData(pArc); if (m_GroupId.isValid()) { OPENOBJ_BEGIN(m_GroupId, AcDb::kForWrite, AcDbGroup, pGroup) if (pGroup) { pGroup->append(objectid); } OPENOBJ_END() } }