internal void AddToAdjacentVertex(TransientGraphUtility transUtil , VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect) { if (!PointComparer.Equal(this.Point, targetVertex.Point)) { transUtil.FindOrAddEdge(this.Vertex, targetVertex, InitialWeight); } ExtendEdgeChain(transUtil, targetVertex, dirToExtend, limitRect); }
// Adds an edge from this.Vertex to a (possibly new) vertex at an intersection with an // existing Edge that adjoins the point. We take 'dir' as an input parameter for edge // extension because we may be on the edge so can't calculate the direction. internal VisibilityVertex AddEdgeToAdjacentEdge(TransientGraphUtility transUtil , VisibilityEdge targetEdge, Directions dirToExtend, Rectangle limitRect) { Point targetIntersect = StaticGraphUtility.SegmentIntersection(targetEdge, this.Point); VisibilityVertex targetVertex = transUtil.VisGraph.FindVertex(targetIntersect); if (null != targetVertex) { AddToAdjacentVertex(transUtil, targetVertex, dirToExtend, limitRect); } else { targetVertex = transUtil.AddEdgeToTargetEdge(this.Vertex, targetEdge, targetIntersect); } ExtendEdgeChain(transUtil, targetVertex, dirToExtend, limitRect); return targetVertex; }
internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex targetVertex, Directions dirToExtend, Rectangle limitRect) { // Extend the edge chain to the opposite side of the limit rectangle. StaticGraphUtility.Assert(PointComparer.Equal(this.Point, targetVertex.Point) || (PointComparer.GetPureDirection(this.Point, targetVertex.Point) == dirToExtend) , "input dir does not match with to-targetVertex direction", transUtil.ObstacleTree, transUtil.VisGraph); var extendOverlapped = IsOverlapped; if (extendOverlapped) { // The initial vertex we connected to may be on the border of the enclosing obstacle, // or of another also-overlapped obstacle. If the former, we turn off overlap now. extendOverlapped = transUtil.ObstacleTree.PointIsInsideAnObstacle(targetVertex.Point, dirToExtend); } // If we're inside an obstacle's boundaries we'll never extend past the end of the obstacle // due to encountering the boundary from the inside. So start the extension at targetVertex. SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.IsOverlapped ? targetVertex : this.Vertex, dirToExtend, transUtil); transUtil.ExtendEdgeChain(targetVertex, limitRect, segmentAndCrossings.Item1, segmentAndCrossings.Item2, extendOverlapped); }
internal void ExtendFromBorderVertex(TransientGraphUtility transUtil, VisibilityVertex borderVertex , Rectangle limitRect, bool routeToCenter) { ExtendEdgeChain(transUtil, borderVertex, borderVertex, limitRect, routeToCenter); }
internal void GetVertex(TransientGraphUtility transUtil, Point point) { this.Vertex = transUtil.FindOrAddVertex(point); }
internal void AddToAdjacentVertex(TransientGraphUtility transUtil, VisibilityVertex targetVertex , Rectangle limitRect, bool routeToCenter) { VisibilityVertex borderVertex = transUtil.VisGraph.FindVertex(this.VisibilityBorderIntersect); if (null != borderVertex) { ExtendFromBorderVertex(transUtil, borderVertex, limitRect, routeToCenter); return; } // There is no vertex at VisibilityBorderIntersect, so create it and link it to targetVertex. // Note: VisibilityBorderIntersect may == targetIntersect if that is on our border, *and* // targetIntersect may be on the border of a touching obstacle, in which case this will splice // into or across the adjacent obstacle, which is consistent with "touching is overlapped". // So we don't use UnpaddedBorderIntersect as prevPoint when calling ExtendEdgeChain. // VisibilityBorderIntersect may be rounded just one Curve.DistanceEpsilon beyond the ScanSegment's // perpendicular coordinate; e.g. our X may be targetIntersect.X + Curve.DistanceEpsilon, thereby // causing the direction from VisibilityBorderIntersect to targetIntersect to be W instead of E. // So use the targetIntersect if they are close enough; they will be equal for flat borders, and // otherwise the exact value we use only needs be "close enough" to the border. (We can't use // CenterVertex as the prevPoint because that could be an impure direction). // Update: With the change to carry MaxVisibilitySegment within the PortEntrance, PortManager finds // targetVertex between VisibilityBorderIntersect and MaxVisibilitySegment.End, so this should no longer // be able to happen. // See RectilinearTests.PaddedBorderIntersectMeetsIncomingScanSegment for an example of what happens // when VisibilityBorderIntersect is on the incoming ScanSegment (it jumps out above with borderVertex found). if (OutwardDirection == PointComparer.GetPureDirection(targetVertex.Point, this.VisibilityBorderIntersect)) { Debug.Assert(false, "Unexpected reversed direction between VisibilityBorderIntersect and targetVertex"); // ReSharper disable HeuristicUnreachableCode this.VisibilityBorderIntersect = targetVertex.Point; borderVertex = targetVertex; // ReSharper restore HeuristicUnreachableCode } else { borderVertex = transUtil.FindOrAddVertex(this.VisibilityBorderIntersect); transUtil.FindOrAddEdge(borderVertex, targetVertex, InitialWeight); } ExtendEdgeChain(transUtil, borderVertex, targetVertex, limitRect, routeToCenter); }
internal void AddOobEdgesFromGraphCorner(TransientGraphUtility transUtil, Point cornerPoint) { Directions dirs = PointComparer.GetDirections(cornerPoint, Vertex.Point); VisibilityVertex cornerVertex = transUtil.VisGraph.FindVertex(cornerPoint); // For waypoints we want to be able to enter in both directions. transUtil.ConnectVertexToTargetVertex(cornerVertex, this.Vertex, dirs & (Directions.North | Directions.South), ScanSegment.NormalWeight); transUtil.ConnectVertexToTargetVertex(cornerVertex, this.Vertex, dirs & (Directions.East | Directions.West), ScanSegment.NormalWeight); }
// Called if we must create the vertex. internal FreePoint(TransientGraphUtility transUtil, Point point) { OutOfBoundsDirectionFromGraph = Directions. None; this.GetVertex(transUtil, point); }
internal Point MaxVisibilityInDirectionForNonOverlappedFreePoint(Directions dirToExtend, TransientGraphUtility transUtil) { Debug.Assert(!this.IsOverlapped, "Do not precalculate overlapped obstacle visibility as we should extend from the outer target vertex instead"); SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.Vertex, dirToExtend, transUtil); return segmentAndCrossings.Item1.End; }
// Splits an existing Edge to splice in this.Vertex. internal void SpliceIntoEdge(TransientGraphUtility transUtil, VisibilityEdge edge) { transUtil.SplitEdge(edge, this.Vertex); }
// Called if we must create the vertex. internal FreePoint(TransientGraphUtility transUtil, Point point) { OutOfBoundsDirectionFromGraph = Directions.None; this.GetVertex(transUtil, point); }
internal Point MaxVisibilityInDirectionForNonOverlappedFreePoint(Directions dirToExtend, TransientGraphUtility transUtil) { Debug.Assert(!this.IsOverlapped, "Do not precalculate overlapped obstacle visibility as we should extend from the outer target vertex instead"); SegmentAndCrossings segmentAndCrossings = GetSegmentAndCrossings(this.Vertex, dirToExtend, transUtil); return(segmentAndCrossings.Item1.End); }
private SegmentAndCrossings GetSegmentAndCrossings(VisibilityVertex startVertex, Directions dirToExtend, TransientGraphUtility transUtil) { var dirIndex = CompassVector.ToIndex(dirToExtend); var segmentAndCrossings = this.maxVisibilitySegmentsAndCrossings[dirIndex]; if (null == segmentAndCrossings) { PointAndCrossingsList pacList; var maxVisibilitySegment = transUtil.ObstacleTree.CreateMaxVisibilitySegment(startVertex.Point, dirToExtend, out pacList); segmentAndCrossings = new SegmentAndCrossings(maxVisibilitySegment, pacList); this.maxVisibilitySegmentsAndCrossings[dirIndex] = segmentAndCrossings; } else { // For a waypoint this will be a target and then a source, so there may be a different lateral edge to // connect to. In that case make sure we are consistent in directions - back up the start point if needed. if (PointComparer.GetDirections(startVertex.Point, segmentAndCrossings.Item1.Start) == dirToExtend) { segmentAndCrossings.Item1.Start = startVertex.Point; } } return(segmentAndCrossings); }
internal void ExtendEdgeChain(TransientGraphUtility transUtil, VisibilityVertex paddedBorderVertex , VisibilityVertex targetVertex, Rectangle limitRect, bool routeToCenter) { // Extend the edge chain to the opposite side of the limit rectangle. transUtil.ExtendEdgeChain(targetVertex, limitRect, this.MaxVisibilitySegment, this.pointAndCrossingsList, this.IsOverlapped); // In order for Nudger to be able to map from the (near-) endpoint vertex to a PortEntry, we must // always connect a vertex at UnpaddedBorderIntersect to the paddedBorderVertex, even if routeToCenter. var unpaddedBorderVertex = transUtil.FindOrAddVertex(UnpaddedBorderIntersect); transUtil.FindOrAddEdge(unpaddedBorderVertex, paddedBorderVertex, this.unpaddedToPaddedBorderWeight); if (routeToCenter) { // Link the CenterVertex to the vertex at UnpaddedBorderIntersect. transUtil.ConnectVertexToTargetVertex(ObstaclePort.CenterVertex, unpaddedBorderVertex, OutwardDirection, InitialWeight); } }
private SegmentAndCrossings GetSegmentAndCrossings(VisibilityVertex startVertex, Directions dirToExtend, TransientGraphUtility transUtil) { var dirIndex = CompassVector.ToIndex(dirToExtend); var segmentAndCrossings = this.maxVisibilitySegmentsAndCrossings[dirIndex]; if (null == segmentAndCrossings) { PointAndCrossingsList pacList; var maxVisibilitySegment = transUtil.ObstacleTree.CreateMaxVisibilitySegment(startVertex.Point, dirToExtend, out pacList); segmentAndCrossings = new SegmentAndCrossings(maxVisibilitySegment, pacList); this.maxVisibilitySegmentsAndCrossings[dirIndex] = segmentAndCrossings; } else { // For a waypoint this will be a target and then a source, so there may be a different lateral edge to // connect to. In that case make sure we are consistent in directions - back up the start point if needed. if (PointComparer.GetDirections(startVertex.Point, segmentAndCrossings.Item1.Start) == dirToExtend) { segmentAndCrossings.Item1.Start = startVertex.Point; } } return segmentAndCrossings; }
internal void AddToGraph(TransientGraphUtility transUtil, bool routeToCenter) { // We use only border vertices if !routeToCenter. if (routeToCenter) { CenterVertex = transUtil.FindOrAddVertex(this.Location); } }