/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each /// traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal /// should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start /// node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial /// segment (Incoming) or should be able to flow from the initial segment (Outgoing) or /// in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no /// segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitorFun">Specifies the stateful visitor that should be notified as soon as /// a traversable segment (which has not been traversed before) is found.</param> public static IEnumerable <ushort> Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitorFun) { ExtSegment initialSeg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[initialSegmentId]; if (!initialSeg.valid) { return(null); } // Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegmentId}"); if (!visitorFun( new SegmentVisitData( ref initialSeg, ref initialSeg, false, false, true))) { return(null); } HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ref NetSegment initialSegment = ref initialSegmentId.ToSegment();
/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each /// traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal /// should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start /// node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial /// segment (Incoming) or should be able to flow from the initial segment (Outgoing) or /// in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no /// segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitorFun">Specifies the stateful visitor that should be notified as soon as /// a traversable segment (which has not been traversed before) is found.</param> public static IEnumerable <ushort> Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitorFun) { ExtSegment initialSeg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[initialSegmentId]; if (!initialSeg.valid) { return(null); } // Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegmentId}"); if (!visitorFun( new SegmentVisitData( ref initialSeg, ref initialSeg, false, false, true))) { return(null); } HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ushort startNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, true); TraverseRec( ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, true)], ref startNodeId.ToNode(), true, direction, side, stopCrit, visitorFun, visitedSegmentIds); ushort endNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, false); TraverseRec( ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, false)], ref endNodeId.ToNode(), false, direction, side, stopCrit, visitorFun, visitedSegmentIds); // Log._Debug($"SegmentTraverser: Traversal finished."); return(visitedSegmentIds); }
public static void Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, LaneStopCriterion laneStopCrit, SegmentStopCriterion segStopCrit, NetInfo.LaneType?laneTypeFilter, VehicleInfo.VehicleType?vehicleTypeFilter, SegmentLaneVisitor laneVisitor) { IList <LanePos> initialSortedLanes = null; //------------------------------------- // Function applies via SegmentTraverser //------------------------------------- bool VisitorFun(SegmentVisitData segData) { bool isInitialSeg = segData.Initial; bool reverse = !isInitialSeg && segData.ViaStartNode == segData.ViaInitialStartNode; bool ret = false; //------------------------------------- // Function applies for each segment //------------------------------------- bool VisitorProcessFun(ushort segmentId, ref NetSegment segment) { // Log._Debug($"SegmentLaneTraverser: Reached segment {segmentId}: // isInitialSeg={isInitialSeg} viaStartNode={segData.viaStartNode} // viaInitialStartNode={segData.viaInitialStartNode} reverse={reverse}"); IList <LanePos> sortedLanes = Constants.ServiceFactory.NetService.GetSortedLanes( segmentId, ref segment, null, laneTypeFilter, vehicleTypeFilter, reverse); if (isInitialSeg) { initialSortedLanes = sortedLanes; } else if (initialSortedLanes == null) { throw new ApplicationException("Initial list of sorted lanes not set."); } else if (sortedLanes.Count != initialSortedLanes.Count && (laneStopCrit & LaneStopCriterion.LaneCount) != LaneStopCriterion.None) { // Log._Debug($"SegmentLaneTraverser: Stop criterion reached @ {segmentId}: // {sortedLanes.Count} current vs. {initialSortedLanes.Count} initial lanes"); return(false); } for (int i = 0; i < sortedLanes.Count; ++i) { // Log._Debug($"SegmentLaneTraverser: Traversing segment lane // {sortedLanes[i].laneIndex} @ {segmentId} (id {sortedLanes[i].laneId}, // pos {sortedLanes[i].position})"); if (!laneVisitor( new SegmentLaneVisitData( segData, i, sortedLanes[i], initialSortedLanes[i]))) { return(false); } } ret = true; return(true); } Constants.ServiceFactory.NetService.ProcessSegment( segData.CurSeg.segmentId, VisitorProcessFun); return(ret); } SegmentTraverser.Traverse(initialSegmentId, direction, side, segStopCrit, VisitorFun); }
/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial segment (Incoming) or should be able to flow from the initial segment (Outgoing) or in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitor">Specifies the stateful visitor that should be notified as soon as a traversable segment (which has not been traversed before) is found.</param> public static void Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitor) { SegmentGeometry initialSegGeometry = SegmentGeometry.Get(initialSegmentId); if (initialSegGeometry == null) { return; } Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegGeometry.SegmentId}"); if (visitor(new SegmentVisitData(initialSegGeometry, initialSegGeometry, false, false, true))) { HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); TraverseRec(initialSegGeometry, true, true, direction, side, stopCrit, visitor, visitedSegmentIds); TraverseRec(initialSegGeometry, false, false, direction, side, stopCrit, visitor, visitedSegmentIds); } Log._Debug($"SegmentTraverser: Traversal finished."); }
private static void TraverseRec(SegmentGeometry prevSegGeometry, bool exploreStartNode, bool viaInitialStartNode, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitor, HashSet <ushort> visitedSegmentIds) { Log._Debug($"SegmentTraverser: Traversing segment {prevSegGeometry.SegmentId}"); // collect next segment ids to traverse if (direction == TraverseDirection.None) { throw new ArgumentException($"Invalid direction {direction} given."); } if (side == TraverseSide.None) { throw new ArgumentException($"Invalid side {side} given."); } HashSet <ushort> nextSegmentIds = new HashSet <ushort>(); switch (direction) { case TraverseDirection.AnyDirection: default: if (side == TraverseSide.AnySide) { nextSegmentIds.UnionWith(prevSegGeometry.GetConnectedSegments(exploreStartNode)); } else { if ((side & TraverseSide.Left) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetLeftSegments(exploreStartNode)); } if ((side & TraverseSide.Straight) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetStraightSegments(exploreStartNode)); } if ((side & TraverseSide.Right) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetRightSegments(exploreStartNode)); } } break; case TraverseDirection.Incoming: if (side == TraverseSide.AnySide) { nextSegmentIds.UnionWith(prevSegGeometry.GetIncomingSegments(exploreStartNode)); } else { if ((side & TraverseSide.Left) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetIncomingLeftSegments(exploreStartNode)); } if ((side & TraverseSide.Straight) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetIncomingStraightSegments(exploreStartNode)); } if ((side & TraverseSide.Right) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetIncomingRightSegments(exploreStartNode)); } } break; case TraverseDirection.Outgoing: if (side == TraverseSide.AnySide) { nextSegmentIds.UnionWith(prevSegGeometry.GetOutgoingSegments(exploreStartNode)); } else { if ((side & TraverseSide.Left) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetOutgoingLeftSegments(exploreStartNode)); } if ((side & TraverseSide.Straight) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetOutgoingStraightSegments(exploreStartNode)); } if ((side & TraverseSide.Right) != TraverseSide.None) { nextSegmentIds.UnionWith(prevSegGeometry.GetOutgoingRightSegments(exploreStartNode)); } } break; } nextSegmentIds.Remove(0); Log._Debug($"SegmentTraverser: Fetched next segments to traverse: {nextSegmentIds.CollectionToString()}"); if (nextSegmentIds.Count >= 2 && (stopCrit & SegmentStopCriterion.Junction) != SegmentStopCriterion.None) { Log._Debug($"SegmentTraverser: Stop criterion reached @ {prevSegGeometry.SegmentId}: {nextSegmentIds.Count} connected segments"); return; } ushort prevNodeId = prevSegGeometry.GetNodeId(exploreStartNode); // explore next segments foreach (ushort nextSegmentId in nextSegmentIds) { if (nextSegmentId == 0 || visitedSegmentIds.Contains(nextSegmentId)) { continue; } visitedSegmentIds.Add(nextSegmentId); SegmentGeometry nextSegGeometry = SegmentGeometry.Get(nextSegmentId); if (nextSegGeometry != null) { Log._Debug($"SegmentTraverser: Traversing segment {nextSegGeometry.SegmentId}"); if (visitor(new SegmentVisitData(prevSegGeometry, nextSegGeometry, viaInitialStartNode, prevNodeId == nextSegGeometry.StartNodeId(), false))) { bool nextNodeIsStartNode = nextSegGeometry.StartNodeId() != prevNodeId; TraverseRec(nextSegGeometry, nextNodeIsStartNode, viaInitialStartNode, direction, side, stopCrit, visitor, visitedSegmentIds); } } } }
private static void TraverseRec(ref ExtSegment prevSeg, ref ExtSegmentEnd prevSegEnd, ref NetNode node, bool viaInitialStartNode, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitorFun, HashSet <ushort> visitedSegmentIds) { // Log._Debug($"SegmentTraverser: Traversing segment {prevSegEnd.segmentId}"); // collect next segment ids to traverse if (direction == TraverseDirection.None) { throw new ArgumentException($"Invalid direction {direction} given."); } if (side == TraverseSide.None) { throw new ArgumentException($"Invalid side {side} given."); } IExtSegmentManager extSegMan = Constants.ManagerFactory.ExtSegmentManager; IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; HashSet <ushort> nextSegmentIds = new HashSet <ushort>(); for (int i = 0; i < 8; ++i) { ushort nextSegmentId = node.GetSegment(i); if (nextSegmentId == 0 || nextSegmentId == prevSegEnd.segmentId) { continue; } bool nextIsStartNode = (bool)Constants.ServiceFactory.NetService.IsStartNode( nextSegmentId, prevSegEnd.nodeId); ExtSegmentEnd nextSegEnd = extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(nextSegmentId, nextIsStartNode)]; if (direction == TraverseDirection.AnyDirection || (direction == TraverseDirection.Incoming && nextSegEnd.incoming) || (direction == TraverseDirection.Outgoing && nextSegEnd.outgoing)) { if (side == TraverseSide.AnySide) { nextSegmentIds.Add(nextSegmentId); } else { ArrowDirection dir = extSegEndMan.GetDirection( ref prevSegEnd, nextSegmentId); if (((side & TraverseSide.Left) != TraverseSide.None && dir == ArrowDirection.Left) || ((side & TraverseSide.Straight) != TraverseSide.None && dir == ArrowDirection.Forward) || ((side & TraverseSide.Right) != TraverseSide.None && dir == ArrowDirection.Right)) { nextSegmentIds.Add(nextSegmentId); } } } } nextSegmentIds.Remove(0); // Log._Debug($"SegmentTraverser: Fetched next segments to traverse: // {nextSegmentIds.CollectionToString()}"); if (nextSegmentIds.Count >= 2 && (stopCrit & SegmentStopCriterion.Junction) != SegmentStopCriterion.None) { // Log._Debug($"SegmentTraverser: Stop criterion reached @ {prevSegEnd.segmentId}: // {nextSegmentIds.Count} connected segments"); return; } // explore next segments foreach (ushort nextSegmentId in nextSegmentIds) { if (visitedSegmentIds.Contains(nextSegmentId)) { continue; } visitedSegmentIds.Add(nextSegmentId); // Log._Debug($"SegmentTraverser: Traversing segment {nextSegmentId}"); ushort nextStartNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(nextSegmentId, true); if (!visitorFun( new SegmentVisitData( ref prevSeg, ref extSegMan.ExtSegments[nextSegmentId], viaInitialStartNode, prevSegEnd.nodeId == nextStartNodeId, false))) { continue; } bool nextNodeIsStartNode = nextStartNodeId != prevSegEnd.nodeId; ExtSegmentEnd nextSegEnd = extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(nextSegmentId, nextNodeIsStartNode)]; Constants.ServiceFactory.NetService.ProcessNode( nextSegEnd.nodeId, (ushort nId, ref NetNode nextNode) => { TraverseRec( ref extSegMan.ExtSegments[nextSegmentId], ref nextSegEnd, ref nextNode, viaInitialStartNode, direction, side, stopCrit, visitorFun, visitedSegmentIds); return(true); }); } // end foreach }
private static void TraverseRec(SegmentGeometry prevSegGeometry, bool exploreStartNode, bool viaInitialStartNode, TraverseDirection direction, SegmentStopCriterion stopCrit, SegmentVisitor visitor, HashSet <ushort> visitedSegmentIds) { // collect next segment ids to traverse ushort[] nextSegmentIds; int numConnectedSegments; switch (direction) { case TraverseDirection.Both: default: nextSegmentIds = prevSegGeometry.GetConnectedSegments(exploreStartNode); numConnectedSegments = prevSegGeometry.CountOtherSegments(exploreStartNode); break; case TraverseDirection.Incoming: nextSegmentIds = prevSegGeometry.GetIncomingSegments(exploreStartNode); numConnectedSegments = prevSegGeometry.CountIncomingSegments(exploreStartNode); break; case TraverseDirection.Outgoing: nextSegmentIds = prevSegGeometry.GetOutgoingSegments(exploreStartNode); numConnectedSegments = prevSegGeometry.CountOutgoingSegments(exploreStartNode); break; } if (numConnectedSegments >= 2 && (stopCrit & SegmentStopCriterion.Junction) != SegmentStopCriterion.None) { Log._Debug($"SegmentTraverser: Stop criterion reached @ {prevSegGeometry.SegmentId}: {numConnectedSegments} connected segments"); return; } ushort prevNodeId = prevSegGeometry.GetNodeId(exploreStartNode); // explore next segments foreach (ushort nextSegmentId in nextSegmentIds) { if (nextSegmentId == 0 || visitedSegmentIds.Contains(nextSegmentId)) { continue; } visitedSegmentIds.Add(nextSegmentId); SegmentGeometry nextSegGeometry = SegmentGeometry.Get(nextSegmentId); if (nextSegGeometry != null) { Log._Debug($"SegmentTraverser: Traversing segment {nextSegGeometry.SegmentId}"); if (visitor(new SegmentVisitData(prevSegGeometry, nextSegGeometry, viaInitialStartNode, prevNodeId == nextSegGeometry.StartNodeId(), false))) { bool nextNodeIsStartNode = nextSegGeometry.StartNodeId() != prevNodeId; TraverseRec(nextSegGeometry, nextNodeIsStartNode, viaInitialStartNode, direction, stopCrit, visitor, visitedSegmentIds); } } } }
/// <summary> /// Performs a Depth-First traversal over the cached segment geometry structure. At each traversed segment, the given `visitor` is notified. It then can update the current `state`. /// </summary> /// <param name="initialSegmentGeometry">Specifies the segment at which the traversal should start.</param> /// <param name="nextNodeIsStartNode">Specifies if the next node to traverse is the start node of the initial segment.</param> /// <param name="direction">Specifies if traffic should be able to flow towards the initial segment (Incoming) or should be able to flow from the initial segment (Outgoing) or in both directions (Both).</param> /// <param name="maximumDepth">Specifies the maximum depth to explore. At a depth of 0, no segment will be traversed (event the initial segment will be omitted).</param> /// <param name="visitor">Specifies the stateful visitor that should be notified as soon as a traversable segment (which has not been traversed before) is found.</param> public static void Traverse(ushort initialSegmentId, TraverseDirection direction, TraverseSide side, SegmentStopCriterion stopCrit, SegmentVisitor visitor) { ExtSegment initialSeg = Constants.ManagerFactory.ExtSegmentManager.ExtSegments[initialSegmentId]; if (!initialSeg.valid) { return; } //Log._Debug($"SegmentTraverser: Traversing initial segment {initialSegmentId}"); if (visitor(new SegmentVisitData(ref initialSeg, ref initialSeg, false, false, true))) { HashSet <ushort> visitedSegmentIds = new HashSet <ushort>(); visitedSegmentIds.Add(initialSegmentId); IExtSegmentEndManager extSegEndMan = Constants.ManagerFactory.ExtSegmentEndManager; ushort startNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, true); Constants.ServiceFactory.NetService.ProcessNode(startNodeId, delegate(ushort nId, ref NetNode node) { TraverseRec(ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, true)], ref node, true, direction, side, stopCrit, visitor, visitedSegmentIds); return(true); }); ushort endNodeId = Constants.ServiceFactory.NetService.GetSegmentNodeId(initialSegmentId, false); Constants.ServiceFactory.NetService.ProcessNode(endNodeId, delegate(ushort nId, ref NetNode node) { TraverseRec(ref initialSeg, ref extSegEndMan.ExtSegmentEnds[extSegEndMan.GetIndex(initialSegmentId, false)], ref node, false, direction, side, stopCrit, visitor, visitedSegmentIds); return(true); }); } //Log._Debug($"SegmentTraverser: Traversal finished."); }