#include "stdafx.h" #include "commonRoad.h" #include "Road.h" AcGeTol CRoad::m_sGeTol; // 单件线段类,用来辅助执行该线上了点排序。 class __LineSingleton { public: static AcGeLineSeg2d & GetLine(); static void SetLine(const AcGeLineSeg2d &line); static void Release(); private: __LineSingleton (){} ~__LineSingleton(){} private: static AcGeLineSeg2d *m_pLine; }; // 单件弧线类,用来辅助执行该弧线上的点排序。 class __ArcSingleton { public: static AcGeCircArc2d & GetArc(); static void SetArc(const AcGeCircArc2d &arc); static void Release(); private: __ArcSingleton (){} ~__ArcSingleton(){} private: static AcGeCircArc2d *m_pArc; }; AcGeLineSeg2d *__LineSingleton::m_pLine = NULL; void __LineSingleton::SetLine(const AcGeLineSeg2d &line) { if (m_pLine == NULL) m_pLine = new AcGeLineSeg2d(line); else m_pLine->set(line.startPoint(), line.endPoint()); } AcGeLineSeg2d& __LineSingleton::GetLine() { ASSERT(m_pLine != NULL); return *m_pLine; } void __LineSingleton::Release() { delete m_pLine; m_pLine = NULL; } AcGeCircArc2d *__ArcSingleton::m_pArc = NULL; void __ArcSingleton::SetArc(const AcGeCircArc2d &arc) { if (m_pArc == NULL) m_pArc = new AcGeCircArc2d(arc); else *m_pArc = arc; } AcGeCircArc2d& __ArcSingleton::GetArc() { ASSERT(m_pArc != NULL); return *m_pArc; } void __ArcSingleton::Release() { delete m_pArc; m_pArc = NULL; } // 设置arInters最后两个参数为Attached。 void AttachEndInterStruct(AcAryInterStructPointer &arInters) { ASSERT(arInters.length() >= 2); CInterStruct *pInter1 = arInters[arInters.length() - 2]; CInterStruct *pInter2 = arInters.last(); ASSERT(pInter1 != NULL); ASSERT(pInter2 != NULL); pInter1->SetAttachedStruct(pInter2); pInter2->SetAttachedStruct(pInter1); } // 取中点,用于模板函数调用,不可删除 inline AcGePoint2d MidPoint(const AcGeCircArc2d &arc) { return MidPointOfArc(arc); } inline AcGePoint2d MidPoint(const AcGeLineSeg2d &lineseg) { return lineseg.midPoint(); } // 模板函数,为实现平台无关,设置为全局函数, template void CreateArInterStruct(const TSplit &edgeSplit, const TEdgeExt &leftEdgeExt, const TEdgeExt &rightEdgeExt, AcAryInterStructPointer &arLeftInterStruct, AcAryInterStructPointer &arRightInterStruct, AcAryInterStructPointer &arInterOri, TRoad &road, TCADEnt &ent, AcGeTol &tol, TInter&) { // 分别判断SplintEdge的 起点、终点、中点在垂直方向上相对于道路的位置。 EPointAtRoadPerp eAtRoadMidPoint = road.PointAtRoadPerp(MidPoint(edgeSplit)); EPointAtRoadPerp eAtRoadStartPt = road.PointAtRoadPerp(edgeSplit.startPoint()); EPointAtRoadPerp eAtRoadEndPt = road.PointAtRoadPerp(edgeSplit.endPoint()); AcAryInterStructPointer *pInterStruct = NULL; if (InRoadPerp(eAtRoadMidPoint) && InRoadPerp(eAtRoadStartPt) && InRoadPerp(eAtRoadEndPt)) { TInter* pInter = ConInterStructInRoad(edgeSplit, ent); // ent.AddInterStruct(pInter); arInterOri.append(pInter); return; // 排除边线在道路内部的情况 } // 分别判断splitEdge的起点和终点是否在道路左边线或者右边线上(包括延长线) // start和end代表splitline的起终,而left和right代表道路的左边,或者右边 bool bStartLeft = leftEdgeExt.isOn(edgeSplit.startPoint(), tol) == Adesk::kTrue; bool bStartRight = rightEdgeExt.isOn(edgeSplit.startPoint(), tol) == Adesk::kTrue; bool bEndLeft = leftEdgeExt.isOn(edgeSplit.endPoint(), tol) == Adesk::kTrue; bool bEndRight = rightEdgeExt.isOn(edgeSplit.endPoint(), tol) == Adesk::kTrue; if (!bStartLeft && !bStartRight && !bEndLeft && !bEndRight) return;// 排除跟道路不相交的情况,两端都不跟道路相交 bool bStart = false, bEnd = false, bComplexOut = false, bPara = false; EPointAtRoadInDir eComplexPos = eRoadStartOut; if (bStartLeft || bEndLeft) { pInterStruct = &arLeftInterStruct; AcGeVector2d dirAtStartOfSplit = road.LeftDirection(edgeSplit.startPoint()); AcGeVector2d dirAtEndOfSplit = road.LeftDirection(edgeSplit.endPoint()); EVecDirection eStartDir = road.SameDirection(dirAtStartOfSplit, edgeSplit, true); EVecDirection eEndDir = road.SameDirection(dirAtEndOfSplit, edgeSplit, false); bStart = (bStartLeft && (eStartDir == eSameDir)); bEnd = (bEndLeft && (eEndDir == eSameDir)); if ((bStartLeft && !bStart) || (bEndLeft && !bEnd)) { ASSERT(!(bStartLeft && bEndLeft)); // 不可能起点和终点都在道路的一条边上,而且还是跨交 bStart = bStartLeft; bEnd = bEndLeft; if ((eStartDir == ePerpDir) || (eEndDir == ePerpDir)) { bPara = true; } else { bComplexOut = true; pInterStruct = &arRightInterStruct; if (road.SameDirection(road.StartDirection(ChosePoint(edgeSplit, bStartLeft)), edgeSplit, bStartLeft) == eSameDir) eComplexPos = eRoadStartOut; else eComplexPos = eRoadEndOut; } } } else { pInterStruct = &arRightInterStruct; AcGeVector2d dirAtStartOfSplit = road.RightDirection(edgeSplit.startPoint()); AcGeVector2d dirAtEndOfSplit = road.RightDirection(edgeSplit.endPoint()); EVecDirection eStartDir = road.SameDirection(dirAtStartOfSplit, edgeSplit, true); EVecDirection eEndDir = road.SameDirection(dirAtEndOfSplit, edgeSplit, false); bStart = (bStartRight && (eStartDir == eSameDir)); bEnd = (bEndRight && (eEndDir == eSameDir)); if ((bStartRight && !bStart) || (bEndRight && !bEnd)) { ASSERT(!(bStartRight && bEndRight)); // 不可能起点和终点都在道路的一条边上,而且还是跨交 bStart = bStartRight; bEnd = bEndRight; if ((eStartDir == ePerpDir) || (eEndDir == ePerpDir)) { bPara = true; } else { bComplexOut = true; pInterStruct = &arLeftInterStruct; if (road.SameDirection(road.StartDirection(ChosePoint(edgeSplit, bStartRight)), edgeSplit, bStartRight) == eSameDir) eComplexPos = eRoadStartOut; else eComplexPos = eRoadEndOut; } } } if (!bStart && !bEnd) return; // edgeSplit if (bStart) { TInter *pInter = ConInterStruct(edgeSplit, true, road, ent, tol, bPara, FALSE, bComplexOut, eComplexPos); pInterStruct->append(pInter); // ent.AddInterStruct(pInter); arInterOri.append(pInter); } if (bEnd) { TInter *pInter = ConInterStruct(edgeSplit, false, road, ent, tol, bPara, FALSE, bComplexOut, eComplexPos); pInterStruct->append(pInter); // ent.AddInterStruct(pInter); arInterOri.append(pInter); } if (bStart && bEnd) AttachEndInterStruct(*pInterStruct); } template void CreateArInterStructForMid(const TSplit &midSplit, const TMidExt &midExt, AcAryInterStructPointer &arLeftInterStruct, AcAryInterStructPointer &arRightInterStruct, TRoad &road, TCADEnt &ent, AcGeTol &tol, TInter&) { bool bStartOn = midExt.isOn(midSplit.startPoint(), tol) == Adesk::kTrue; bool bEndOn = midExt.isOn(midSplit.endPoint(), tol) == Adesk::kTrue; if (!bStartOn && !bEndOn) return; // 排除了不相交的情况,这里开始判断splitMid是在左边还是在右边, AcAryInterStructPointer *pArDumpInter = NULL; EVecDirection eVecDir = road.SameDirection(road.LeftDirection(ChosePoint(midSplit, bStartOn)), midSplit, bStartOn); bool bPara = (eVecDir == ePerpDir); if ((eVecDir == eSameDir) || (eVecDir == ePerpDir)) pArDumpInter = &arLeftInterStruct; else pArDumpInter = &arRightInterStruct; // 直线道路跟圆弧中线的判定,可能会出现一端有两个端点的情况,这时添加的是两个Attach的结构体。 if (bStartOn) pArDumpInter->append(ConInterStruct(midSplit, true, road, ent, tol, bPara, TRUE)); if (bEndOn) pArDumpInter->append(ConInterStruct(midSplit, false, road, ent, tol, bPara,TRUE)); if (bStartOn && bEndOn) AttachEndInterStruct(*pArDumpInter); } int __PointCompareWithLine(const void *p1, const void* p2) { AcGeLineSeg2d lineSeg = __LineSingleton::GetLine(); const AcGePoint2d *pPt1 = (const AcGePoint2d*)p1, *pPt2 = (const AcGePoint2d*)p2; return PointSequence(lineSeg.direction(), *pPt1, *pPt2); } // 点排序 void SortPoint(const AcGeLineSeg2d &lineseg, AcArray &arPoint) { __LineSingleton::SetLine(lineseg); AcGePoint2d *pArPoint = arPoint.asArrayPtr(); qsort(pArPoint, arPoint.length(), sizeof(AcGePoint2d), __PointCompareWithLine); __LineSingleton::Release(); } int __PointCompareWithArc(const void *p1, const void *p2) { AcGeCircArc2d arc = __ArcSingleton::GetArc(); const AcGePoint2d *pPt1 = (const AcGePoint2d*)p1, *pPt2 = (const AcGePoint2d*)p2; return PointSequence(arc, *pPt1, *pPt2); } // 点排序, 排序起点是圆弧起始端所在半圆的起点,沿着圆弧的方向 void SortPoint(const AcGeCircArc2d &arc, AcArray &arPoint) { __ArcSingleton::SetArc(arc); AcGePoint2d *pArPoint = arPoint.asArrayPtr(); qsort(pArPoint, arPoint.length(), sizeof(AcGePoint2d), __PointCompareWithArc); __ArcSingleton::Release(); } // 在直线的方向上比较两个点的先后顺序,顺序返回true, 逆序返回false; bool IsPointInSequence(const AcGeLineSeg2d &lineseg, const AcGePoint2d &pt1, const AcGePoint2d &pt2) { return PointSequence(lineseg.direction(), pt1, pt2) == -1; } //在弧线的方向上比较两个点的先后顺序,顺序返回true, 逆序返回false; bool IsPointInSequence(const AcGeCircArc2d &cirArc, const AcGePoint2d &pt1, const AcGePoint2d &pt2) { return PointSequence(cirArc, pt1, pt2) == -1; } CRoad::CRoad(double dLeftWid, double dRightWid, BOOL bDrawMid, BOOL bDrawCorner, double dCornerRadius, EFilletStyle cornerType) : m_dLeftWid(dLeftWid), m_dRightWid(dRightWid), m_bDrawMid(bDrawMid), m_bCorner(bDrawCorner), m_dRaidus(dCornerRadius), m_eCornerType(cornerType) { m_sGeTol.setEqualPoint(1.0); m_sGeTol.setEqualVector(1.0); } CRoad::~CRoad(void) { } void CRoad::ToRegionSys(AcGePoint2d &ptLeftDown, AcGePoint2d &ptRightUp) const { ToRegion(ptLeftDown, ptRightUp); ptLeftDown = AsSysUnitPoint2d(ptLeftDown); ptRightUp = AsSysUnitPoint2d(ptRightUp); } EVecDirection CRoad::VecSameDirection(AcGeVector2d vec1, AcGeVector2d vec2, double dTol) { vec1.normalize(); vec2.normalize(); double dDot = vec1.dotProduct(vec2); if (fabs(dDot) < dTol) return ePerpDir; else if (dDot < 0.0) return eOppDir; else return eSameDir; } EVecDirection CRoad::SameDirection(const AcGeVector2d &vec, const AcGeCircArc2d &arcSplit, bool bStart) { AcGePoint2d ptInter = bStart ? arcSplit.startPoint() : arcSplit.endPoint(); AcGeVector2d vecArcSplit = bStart ? TanVecOfArcStartPoint(arcSplit) : TanVecOfArcEndPoint(arcSplit); return CRoad::VecSameDirection(vecArcSplit, vec, 1e-7); } EVecDirection CRoad::SameDirection(const AcGeVector2d &vec, const AcGeLineSeg2d &lineSplit, bool bStart) { AcGePoint2d ptInter = bStart ? lineSplit.startPoint() : lineSplit.endPoint(); AcGeVector2d vecArcSplit = (bStart ? lineSplit.direction() : -lineSplit.direction()); return CRoad::VecSameDirection(vecArcSplit, vec, 1e-7); } BOOL CRoad::IsInExtendRoad(CInterStruct *pInter) const { AcGePoint2d ptStart, ptEnd, ptMid; if (pInter->ToLineInter() != NULL) { CLineInterStruct *pLineInter = pInter->ToLineInter(); ptStart = pLineInter->InterLine().startPoint(); ptEnd = pLineInter->InterLine().endPoint(); ptMid = MidPoint(pLineInter->InterLine()); } else { CArcInterStruct *pArcInter = pInter->ToArcInter(); ptStart = pArcInter->InterArc().startPoint(); ptEnd = pArcInter->InterArc().endPoint(); ptMid = MidPoint(pArcInter->InterArc()); } EPointAtRoadPerp eppS = PointAtRoadPerp(ptStart); EPointAtRoadPerp eppE = PointAtRoadPerp(ptEnd); EPointAtRoadPerp eppM = PointAtRoadPerp(ptMid); if (!InRoadPerp(eppS) || !InRoadPerp(eppE) || !InRoadPerp(eppM)) { return FALSE; } EPointAtRoadInDir epiS = PointAtExtendRoadInDir(ptStart); EPointAtRoadInDir epiE = PointAtExtendRoadInDir(ptEnd); EPointAtRoadInDir epiM = PointAtExtendRoadInDir(ptMid); return (epiS == eInEdge && epiE == eInEdge && epiM == eInEdge); } // 过滤起点和终点外过多的点,起点外,或者终点外如果多个点,则只选取一个。 template void FilterSpareStartAndEndPoint(const TGeType &geSeg, AcArray &arInterPoint) { // 过滤一下:有多个点在起点外,或者终点外的情况 int nOutNum = 0; int nIndex = 0; while (arInterPoint.length() >= 2) // 有两个点的时候,才会确定是否需要比较。 { if (IsPointInSequence(geSeg, arInterPoint[nIndex], geSeg.startPoint())) nOutNum++; else break; if (nOutNum == 2) { arInterPoint.removeFirst(); nOutNum = 1; } nIndex = 1; } nIndex = (int)arInterPoint.length() - 1; // 定位到最后一个元素 nOutNum = 0; while (arInterPoint.length() >= 2) { if (IsPointInSequence(geSeg, geSeg.endPoint(), arInterPoint[nIndex])) { nOutNum++; } else break; if (nOutNum == 2) { arInterPoint.removeLast(); nOutNum = 1; } nIndex = (int)(arInterPoint.length() - 1); } } // 拆分单线(直线)道路 (给点) // lineseg 所给的单线, arInterPoint 拆分点数组(顺序), arLines:拆分之后的线段 void CRoad::SplitLineEdge(const AcGeLineSeg2d &lineseg, AcArray &arInterPoint, AcAryLineSeg2d &arLines) { if (arInterPoint.isEmpty()) return; // 过滤起点和终点外是否有超过两个点。 FilterSpareStartAndEndPoint(lineseg, arInterPoint); // 考虑起点和终点是否需要添加为拆分点 if (IsPointInSequence(lineseg, lineseg.startPoint(), arInterPoint[0])) arInterPoint.insertAt(0, lineseg.startPoint()); if (IsPointInSequence(lineseg, arInterPoint.last(), lineseg.endPoint())) arInterPoint.append(lineseg.endPoint()); // 拆分 for (int index = 1; index < (int)arInterPoint.length(); index++) { AcGePoint2d &ptPrev = arInterPoint[index-1]; AcGePoint2d &ptIndex = arInterPoint[index]; if (ptPrev.distanceTo(ptIndex) < 1.0) continue; // 认为是同一个点。 else arLines.append(AcGeLineSeg2d(ptPrev, ptIndex)); } } // 拆分圆弧道路: // arc:将要拆分的圆弧; arInterPioint,拆分点数组(顺序); arArcs:拆分之后的圆弧道路数组。 void CRoad::SplitArcEdge(const AcGeCircArc2d &arc, AcArray &arInterPoint, AcAryCircArc2d &arArcs) { if (arInterPoint.isEmpty()) return; FilterSpareStartAndEndPoint(arc, arInterPoint); if (IsPointInSequence(arc, arc.startPoint(), arInterPoint[0])) arInterPoint.insertAt(0, arc.startPoint()); if (IsPointInSequence(arc, arInterPoint.last(), arc.endPoint())) arInterPoint.append(arc.endPoint()); for (int index = 1; index < (int)arInterPoint.length(); index++) { AcGePoint2d &ptPrev = arInterPoint[index-1]; AcGePoint2d &ptIndex = arInterPoint[index]; if (ptPrev.distanceTo(ptIndex) < 1.0) continue; // 认为是同一个点。 else { arArcs.append(ConNewArc(arc, ptPrev, ptIndex)); } } } ////////////////////////////////////////////////////////////////////////// // CLineRoad AcGeLineSeg2d CLineRoad::LeftLine() const { return TRoadCommon::LeftLine(m_midLine, HalfWid()); } AcGeLineSeg2d CLineRoad::RightLine() const { return TRoadCommon::RightLine(m_midLine, HalfWid()); } AcGeLineSeg2d CLineRoad::MidLine() const { return m_midLine; } TGGeCurveSegment CLineRoad::ToCurveSeg(int nFlag) const // 0,中线;1,左边线;2,右边线 { TGGeCurveSegment curve; if (nFlag == 0) curve.SetLine(MidLine().startPoint(), MidLine().endPoint()); else if (nFlag == 1) curve.SetLine(LeftLine().startPoint(), LeftLine().endPoint()); else curve.SetLine(RightLine().startPoint(), RightLine().endPoint()); return curve; } EPointAtRoadPerp CLineRoad::PointAtRoadPerp(const AcGePoint2d &pt, double dTol) const { EPointToLine el = PointToLineSegPerp(LeftLine(), pt, dTol); EPointToLine er = PointToLineSegPerp(RightLine(), pt, dTol); if (el == eLeft) return eRoadLeftSide; else if (el == eOnLine) return eRoadLeftEdge; else { if (er == eLeft) return eInRoad; else if (er == eOnLine) return eRoadRightEdge; else return eRoadRightSide; } } EPointAtRoadInDir CLineRoad::PointAtRoadInDir(const AcGePoint2d &pt, double dTol ) const { switch (PointToLineSegDir(MidLine(), pt, dTol)) { case eStartOut: case eStartPoint: return eRoadStartOut; break; case eEndOut: case eEndPoint: return eRoadEndOut; break; default: return eInEdge; } } EPointAtRoadInDir CLineRoad::PointAtExtendRoadInDir(const AcGePoint2d &pt, double dTol /* = 1.0 */) const { // 去圆弧上的各点 switch (PointToLineSegDir(ExtendLine(MidLine(), TolForSplit(), TolForSplit()), pt, dTol)) { case eStartOut: return eRoadStartOut; break; case eEndOut: return eRoadEndOut; break; default: return eInEdge; } } void CLineRoad::ToRegion(AcGePoint2d &ptLeftDown, AcGePoint2d &ptRightUp) const { double dTol = TolForRegion(); AcGePoint2d ptls = LeftLine().startPoint(); AcGePoint2d ptle = LeftLine().endPoint(); AcGePoint2d ptrs = RightLine().startPoint(); AcGePoint2d ptre = RightLine().endPoint(); // 找四个点的最小值。 double xMin = MIN(MIN(ptls.x, ptle.x), MIN(ptrs.x, ptre.x)); double xMax = MAX(MAX(ptls.x, ptle.x), MAX(ptrs.x, ptre.x)); double yMin = MIN(MIN(ptls.y, ptle.y), MIN(ptrs.y, ptre.x)); double yMax = MAX(MAX(ptls.y, ptle.y), MAX(ptrs.y, ptre.y)); xMin -= dTol; xMax += dTol; yMin -= dTol; yMax += dTol; ptLeftDown.x = xMin; ptLeftDown.y = yMin; ptRightUp.x = xMax; ptRightUp.y = yMax; } CLineRoad::CLineRoad(double dLeftWid, double dRightWid, BOOL bDrawMid, BOOL bDrawCorner, double dCornerRadius, EFilletStyle cornerType, const AcGeLineSeg2d &midLine) : CRoad(dLeftWid, dRightWid, bDrawMid, bDrawCorner, dCornerRadius, cornerType), m_midLine(midLine) { } CLineRoad::~CLineRoad(){} // 直线道路的左右方向跟参数无关 AcGeVector2d CLineRoad::LeftDirection(const AcGePoint2d &point) const { return MidLine().direction().perpVector(); } AcGeVector2d CLineRoad::RightDirection(const AcGePoint2d &point) const { return -LeftDirection(point); } AcGeVector2d CLineRoad::StartDirection(const AcGePoint2d &point)const { return -EndDirection(point); } AcGeVector2d CLineRoad::EndDirection(const AcGePoint2d &point)const { return MidLine().direction(); } // 把直线道路识别为interStruct数组; // LineEdge: 直线路边,leftInters: 道路左侧interStruct数组, rightInters: 道路右侧interStruct数组 void CLineRoad::SplitEdge(const AcGeLineSeg2d &lineEdge, AcAryInterStructPointer &leftInters, AcAryInterStructPointer &rightInters, CLineCADEntEdgeAdapter &ent, AcAryInterStructPointer &arInterOri) const { double dTol = TolForSplit(); AcArray arInterPoint; // 交点数组 AcAryLineSeg2d arLines; // 拆分出来的线 AcGeLineSeg2d leftEdge = LeftLine(), rightEdge = RightLine(); AcGeLineSeg2d leftEdgeExt = ExtendLine(leftEdge, dTol, dTol), rightEdgeExt = ExtendLine(rightEdge, dTol, dTol); // 找交点 { AcGePoint2d ptInter; AcGeLineSeg2d lineEdgeExt = ExtendLine(lineEdge, dTol, dTol); if (lineEdgeExt.intersectWith(leftEdgeExt, ptInter) == Adesk::kTrue) { arInterPoint.append(ptInter); } if (lineEdgeExt.intersectWith(rightEdgeExt, ptInter) == Adesk::kTrue) { arInterPoint.append(ptInter); } } // 点排序, SortPoint(lineEdge, arInterPoint); // 拆分 SplitLineEdge(lineEdge, arInterPoint, arLines); // 遍历新拆出来的所有路段,并且构造interStruct结构体。 for (int index = 0; index < (int)arLines.length(); index++) { AcGeLineSeg2d &lineSplit = arLines[index]; MyLineSeg _lineSplit(lineSplit); MyLineSeg _leftEdge(leftEdge), _leftEdgeExt(leftEdgeExt), _rightEdge(rightEdge), _rightEdgeExt(rightEdgeExt); CLineInterStruct xx = CLineInterStruct::DumpStruct(); CreateArInterStruct(lineSplit, leftEdgeExt, rightEdgeExt, leftInters, rightInters, arInterOri, *this, ent, m_sGeTol, xx); } } // 把圆弧道路识别为interStruct数组; // ArcEdge: 直线路边,leftInters: 道路左侧interStruct数组, rightInters: 道路右侧interStruct数组 void CLineRoad::SplitEdge(const AcGeCircArc2d &arcEdge, AcAryInterStructPointer &leftInters, AcAryInterStructPointer &rightInters, CArcCADEntEdgeAdapter &ent, AcAryInterStructPointer &arInterOri) const { double dTol = TolForSplit(); AcArray arInterPoint; // 交点数组 AcAryCircArc2d arArcs; // 拆分出来的线 AcGeLineSeg2d leftEdge = LeftLine(), rightEdge = RightLine(); AcGeCircArc2d arcEdgeExt = ExtendArc(arcEdge, dTol, dTol); AcGeLineSeg2d leftEdgeExt = ExtendLine(leftEdge, dTol, dTol), rightEdgeExt = ExtendLine(rightEdge, dTol, dTol); // 找交点 { AcGePoint2d ptInter1, ptInter2; int nNum = -1; if (arcEdgeExt.intersectWith(leftEdgeExt, nNum, ptInter1, ptInter2) == Adesk::kTrue) { arInterPoint.append(ptInter1); if (nNum == 2) arInterPoint.append(ptInter2); } if (arcEdgeExt.intersectWith(rightEdgeExt, nNum, ptInter1, ptInter2) == Adesk::kTrue) { arInterPoint.append(ptInter1); if (nNum == 2) arInterPoint.append(ptInter2); } } // 点排序, SortPoint(arcEdge, arInterPoint); // 拆分 SplitArcEdge(arcEdge, arInterPoint, arArcs); // 遍历新拆出来的所有路段,并且构造interStruct结构体。 for (int index = 0; index < (int)arArcs.length(); index++) { AcGeCircArc2d &arcSplit = arArcs[index]; CArcInterStruct xx = CArcInterStruct::DumpStruct(); CreateArInterStruct(arcSplit, leftEdgeExt, rightEdgeExt, leftInters, rightInters, arInterOri, *this, ent, m_sGeTol, xx); } } void CLineRoad::SplitMid(const AcGeLineSeg2d &lineseg, AcAryInterStructPointer &arLeftDump, AcAryInterStructPointer &arRightDump, CLineCADEntEdgeAdapter &ent) const { ClearAcaryAll(arLeftDump); ClearAcaryAll(arRightDump); if (!IsDrawMid()) return; AcGeLineSeg2d linemid = MidLine(); double dTol = TolForSplit(); AcGeLineSeg2d lineMidExt = ExtendLine(linemid, dTol, dTol); AcGeLineSeg2d linesegExt = ExtendLine(lineseg, dTol, dTol); AcGePoint2d ptInter; if (lineMidExt.intersectWith(linesegExt, ptInter)) { AcArray arPtInter; arPtInter.append(ptInter); AcAryLineSeg2d arLines; SplitLineEdge(lineseg, arPtInter, arLines); for (int i = 0; i < (int)arLines.length(); i++) { AcGeLineSeg2d &lineSplit = arLines[i]; // 构造interStruct结构体,并且添加: bool bStartOn = lineMidExt.isOn(lineSplit.startPoint(), m_sGeTol) == Adesk::kTrue; bool bEndOn = lineMidExt.isOn(lineSplit.endPoint(), m_sGeTol) == Adesk::kTrue; if (!bStartOn && !bEndOn) continue; if (bStartOn && bEndOn) continue; // 排除了不相交的情况,这里开始判断splitMid是在左边还是在右边, AcAryInterStructPointer *pArDumpInter = NULL; AcGeVector2d vecRoadLeft = LeftDirection(bStartOn ? lineSplit.startPoint() : lineSplit.endPoint()); EVecDirection eVecDir = SameDirection(vecRoadLeft, lineSplit, bStartOn); bool bPara = (eVecDir == ePerpDir); if ((eVecDir == eSameDir) || (eVecDir == ePerpDir)) pArDumpInter = &arLeftDump; else pArDumpInter = &arRightDump; //注意:直线道路跟直线道路不可能存在连个交点,因此只能添加一个interStruct结构体 // 如果是其他情况:直线-圆弧,圆弧-圆弧,这时可能会产生了两个交点,此次,要添加两个interStruct,并且,设置这两个itnerStruct--BeAttached. pArDumpInter->append(ConInterStruct(lineSplit, bStartOn, *this, ent, m_sGeTol, bPara, TRUE)); } } } // 直线道路的中线对圆弧中心进行拆分,并且生成interStruct数组。 void CLineRoad::SplitMid(const AcGeCircArc2d &arc, AcAryInterStructPointer &arLeftDump, AcAryInterStructPointer &arRightDump, CArcCADEntEdgeAdapter &ent)const { ClearAcaryAll(arLeftDump); ClearAcaryAll(arRightDump); if (!IsDrawMid()) return; double dTol = TolForSplit(); AcGeLineSeg2d linemid = MidLine(); AcGeLineSeg2d lineMidExt = ExtendLine(linemid, dTol, dTol); AcGeCircArc2d arcExt = ExtendArc(arc, dTol, dTol); AcGePoint2d ptInter1, ptInter2; int nNum = -1; if (arcExt.intersectWith(lineMidExt, nNum, ptInter1, ptInter2)) { AcArray arPtInter; arPtInter.append(ptInter1); if (nNum == 2) arPtInter.append(ptInter2); if (arPtInter.length() == 2) SortPoint(arc, arPtInter); AcAryCircArc2d arArc; SplitArcEdge(arc, arPtInter, arArc); for (int i = 0; i < (int)arArc.length(); i++) { AcGeCircArc2d &arcSplit = arArc[i]; // 构造interStruct结构体,并且添加: CArcInterStruct xx = CArcInterStruct::DumpStruct(); CreateArInterStructForMid(arcSplit, lineMidExt, arLeftDump, arRightDump, *this, ent, m_sGeTol, xx); } } } ////////////////////////////////////////////////////////////////////////// // CArcRoad CArcRoad::CArcRoad(double dLeftWid, double dRightWid, BOOL bDrawMid, BOOL bDrawCorner, double dCornerRadius, EFilletStyle cornerType, const AcGeCircArc2d &midArc) : CRoad(dLeftWid, dRightWid, bDrawMid, bDrawCorner, dCornerRadius, cornerType), m_midArc(midArc) { } CArcRoad::~CArcRoad(){} AcGeVector2d CArcRoad::LeftDirection(const AcGePoint2d &point) const { if (MidArc().isClockWise()) { return point - MidArc().center(); } else return MidArc().center() - point; } AcGeVector2d CArcRoad::RightDirection(const AcGePoint2d &point) const { return -LeftDirection(point); } AcGeVector2d CArcRoad::StartDirection(const AcGePoint2d &point) const { return LeftDirection(point).perpVector(); } AcGeVector2d CArcRoad::EndDirection(const AcGePoint2d &point) const { return -StartDirection(point); } AcGeCircArc2d CArcRoad::LeftArc() const { return TRoadCommon::LeftArc(m_midArc, HalfWid()); } AcGeCircArc2d CArcRoad::RightArc() const { return TRoadCommon::RightArc(m_midArc, HalfWid()); } AcGeCircArc2d CArcRoad::MidArc() const { return m_midArc; } TGGeCurveSegment CArcRoad::ToCurveSeg(int nFlag) const // 0,中线;1,左边线;2,右边线 { // AcGeCircArc2d acgeArc; // if (nFlag == 0) // acgeArc = MidArc(); // else if (nFlag == 1) // acgeArc = LeftArc(); // else // acgeArc = RightArc(); // // // TGGeArc geArc(asDblArray(acgeArc.center()), // acgeArc.radius(), // (acgeArc.isClockWise() ? acgeArc.endAng() : acgeArc.startAng()), // (acgeArc.isClockWise() ? acgeArc.startAng() : acgeArc.endAng())); // // TGGeCurveSegment geCurve; // geCurve = geArc; // return geCurve; AcGeCircArc2d arc; if (nFlag == 0) arc = MidArc(); else if (nFlag == 1) arc = LeftArc(); else arc = RightArc(); return TGGeCurveSegment(arc.isClockWise() ? arc.endPoint() : arc.startPoint(), arc.isClockWise() ? arc.startPoint() : arc.endPoint(), NormalAngle(arc.endAng() - arc.startAng()) ); } EPointAtRoadPerp CArcRoad::PointAtRoadPerp(const AcGePoint2d &pt, double dTol) const { EPointToLine el = PointToArcPerp(LeftArc(), pt, dTol); EPointToLine er = PointToArcPerp(RightArc(), pt, dTol); if (el == eLeft) return eRoadLeftSide; else if (el == eOnLine) return eRoadLeftEdge; else { if (er == eLeft) return eInRoad; else if (er == eOnLine) return eRoadRightEdge; else return eRoadRightSide; } } // 点相对于圆弧的位置: // 算法:取midArc,取起始角度,终止角度,反向中间角度。计算pt相对于反向中间角度的夹角 EPointAtRoadInDir CArcRoad::PointAtRoadInDir(const AcGePoint2d &pt, double dTol ) const { // 去圆弧上的各点 switch (PointToArcDir(MidArc(), pt, dTol)) { case eStartOut: case eStartPoint: return eRoadStartOut; break; case eEndOut: case eEndPoint: return eRoadEndOut; break; default: return eInEdge; } } EPointAtRoadInDir CArcRoad::PointAtExtendRoadInDir(const AcGePoint2d &pt, double dTol /* = 1.0 */) const { // 去圆弧上的各点 switch (PointToArcDir(ExtendArc(MidArc(), TolForSplit(), TolForSplit()), pt, dTol)) { case eStartOut: return eRoadStartOut; break; case eEndOut: return eRoadEndOut; break; default: return eInEdge; } } void CArcRoad::ToRegion(AcGePoint2d &ptLeftDown, AcGePoint2d &ptRightUp) const { double dTol = TolForRegion(); AcGePoint2d ptCenter = MidArc().center(); double dRadius = MidArc().radius(); ptLeftDown.x = ptCenter.x - dRadius - dTol; ptLeftDown.y = ptCenter.y - dRadius - dTol; ptRightUp.x = ptCenter.x + dRadius + dTol; ptRightUp.y = ptCenter.y + dRadius + dTol; } ////////////////////////////////////////////////////////////////////////// // CArcRoad // 把直线道路识别为interStruct数组; // LineEdge: 直线路边,leftInters: 道路左侧interStruct数组, rightInters: 道路右侧interStruct数组 void CArcRoad::SplitEdge(const AcGeLineSeg2d &lineEdge, AcAryInterStructPointer &leftInters, AcAryInterStructPointer &rightInters, CLineCADEntEdgeAdapter &ent, AcAryInterStructPointer &arInterOri) const { // 定义数据: double dTol = TolForSplit(); AcArray arInterPoint; AcAryLineSeg2d arLines; AcGeCircArc2d leftEdge = LeftArc(), rightEdge = RightArc(); AcGeCircArc2d leftEdgeExt = ExtendArc(leftEdge, dTol, dTol), rightEdgeExt = ExtendArc(rightEdge, dTol, dTol); // 找交点 { AcGeLineSeg2d lineEdgeExt = ExtendLine(lineEdge, dTol, dTol); AcGePoint2d ptInterDump1, ptInterDump2; int nNum = 0; if (leftEdgeExt.intersectWith(lineEdgeExt, nNum, ptInterDump1, ptInterDump2)) { arInterPoint.append(ptInterDump1); if (nNum == 2) arInterPoint.append(ptInterDump2); } if (rightEdgeExt.intersectWith(lineEdgeExt, nNum, ptInterDump1, ptInterDump2)) { arInterPoint.append(ptInterDump1); if (nNum == 2) arInterPoint.append(ptInterDump2); } } // 点排序 SortPoint(lineEdge, arInterPoint); // 拆分 SplitLineEdge(lineEdge, arInterPoint, arLines); // 遍历,获取数据 for (int index = 0; index < (int)arLines.length(); index++) { AcGeLineSeg2d &lineSplit = arLines[index]; CLineInterStruct xx = CLineInterStruct::DumpStruct(); CreateArInterStruct(lineSplit, leftEdgeExt, rightEdgeExt, leftInters, rightInters, arInterOri, *this, ent, m_sGeTol, xx); } } // 把圆弧道路识别为interStruct数组; // ArcEdge: 直线路边,leftInters: 道路左侧interStruct数组, rightInters: 道路右侧interStruct数组 void CArcRoad::SplitEdge(const AcGeCircArc2d &arcEdge, AcAryInterStructPointer &leftInters, AcAryInterStructPointer &rightInters, CArcCADEntEdgeAdapter &ent, AcAryInterStructPointer &arInterOri) const { AcArray arInterPoint; AcAryCircArc2d arArcs; double dTol = TolForSplit(); AcGeCircArc2d leftEdge = LeftArc(), rightEdge = RightArc(); AcGeCircArc2d leftEdgeExt = ExtendArc(leftEdge, dTol, dTol), rightEdgeExt = ExtendArc(rightEdge, dTol, dTol); AcGeCircArc2d arcEdgeExt = ExtendArc(arcEdge, dTol, dTol); // 找交点 { AcGePoint2d ptInterDump1, ptInterDump2; int nNum = -1; if (arcEdgeExt.intersectWith(leftEdgeExt, nNum, ptInterDump1, ptInterDump2)) { arInterPoint.append(ptInterDump1); if (nNum == 2) arInterPoint.append(ptInterDump2); } if (arcEdgeExt.intersectWith(rightEdgeExt, nNum, ptInterDump1, ptInterDump2)) { arInterPoint.append(ptInterDump1); if (nNum == 2) arInterPoint.append(ptInterDump2); } } // 排序 SortPoint(arcEdge, arInterPoint); // 拆分 SplitArcEdge(arcEdge, arInterPoint, arArcs); // 遍历拆分结果,并且生成interStruct数据 for (int index = 0; index < (int)arArcs.length(); index++) { AcGeCircArc2d &arcSplit = arArcs[index]; CArcInterStruct xx = CArcInterStruct::DumpStruct(); CreateArInterStruct(arcSplit, leftEdgeExt, rightEdgeExt, leftInters, rightInters, arInterOri, *this, ent, m_sGeTol, xx); } } void CArcRoad::SplitMid(const AcGeLineSeg2d &lineseg, AcAryInterStructPointer &arLeftDump, AcAryInterStructPointer &arRightDump, CLineCADEntEdgeAdapter &ent) const { ClearAcaryAll(arLeftDump); ClearAcaryAll(arRightDump); if (!IsDrawMid()) return; double dTol = TolForSplit(); AcGeCircArc2d arcMid = MidArc(); AcGeCircArc2d arcMidExt = ExtendArc(arcMid, dTol, dTol); AcGeLineSeg2d lineExt = ExtendLine(lineseg, dTol, dTol); AcGePoint2d ptInter1, ptInter2; int nNum = -1; if (arcMidExt.intersectWith(lineExt, nNum, ptInter1, ptInter2)) { AcArray arPtInter; arPtInter.append(ptInter1); if (nNum == 2) arPtInter.append(ptInter2); if (arPtInter.length() == 2) SortPoint(lineseg, arPtInter); AcAryLineSeg2d arLine; SplitLineEdge(lineseg, arPtInter, arLine); for (int i = 0; i < (int)arLine.length(); i++) { AcGeLineSeg2d &lineSplit = arLine[i]; // 构造interStruct结构体,并且添加: CLineInterStruct xx = CLineInterStruct::DumpStruct(); CreateArInterStructForMid(lineSplit, arcMidExt, arLeftDump, arRightDump, *this, ent, m_sGeTol, xx); } } } void CArcRoad::SplitMid(const AcGeCircArc2d &arc, AcAryInterStructPointer &arLeftDump, AcAryInterStructPointer &arRightDump, CArcCADEntEdgeAdapter &ent) const { ClearAcaryAll(arLeftDump); ClearAcaryAll(arRightDump); if (!IsDrawMid()) return; double dTol = TolForSplit(); AcGeCircArc2d arcMid = MidArc(); AcGeCircArc2d arcMidExt = ExtendArc(arcMid, dTol, dTol); AcGeCircArc2d arcExt = ExtendArc(arc, dTol, dTol); AcGePoint2d ptInter1, ptInter2; int nNum = -1; if (arcMidExt.intersectWith(arcExt, nNum, ptInter1, ptInter2)) { AcArray arPtInter; arPtInter.append(ptInter1); if (nNum == 2) arPtInter.append(ptInter2); if (arPtInter.length() == 2) SortPoint(arc, arPtInter); AcAryCircArc2d arArc; SplitArcEdge(arc, arPtInter, arArc); for (int i = 0; i < (int)arArc.length(); i++) { AcGeCircArc2d &arcSplit = arArc[i]; // 构造interStruct结构体,并且添加: CLineInterStruct xx = CLineInterStruct::DumpStruct(); CreateArInterStructForMid(arcSplit, arcMidExt, arLeftDump, arRightDump, *this, ent, m_sGeTol, xx); } } }