private void CreateOutOfBoundsFreePoint(FreePoint freePoint) {
            // For an out of bounds (OOB) point, we'll link one edge from it to the inbounds edge if it's
            // out of bounds in only one direction; if in two, we'll add a bend. Currently we don't need
            // to do any more because multiple waypoints are processed as multiple subpaths.
            var oobLocation = freePoint.Point;
            Point inboundsLocation = graphGenerator.MakeInBoundsLocation(oobLocation);
            Directions dirFromGraph = PointComparer.GetDirections(inboundsLocation, oobLocation);
            freePoint.OutOfBoundsDirectionFromGraph = dirFromGraph;
            if (!PointComparer.IsPureDirection(dirFromGraph)) {
                // It's OOB in two directions so will need a bend, but we know inboundsLocation
                // is a graph corner so it has a vertex already and we don't need to look up sides.
                StaticGraphUtility.Assert(null != VisGraph.FindVertex(inboundsLocation), "graph corner vertex not found", ObstacleTree, VisGraph);
                freePoint.AddOobEdgesFromGraphCorner(TransUtil, inboundsLocation);
                return;
            }

            // We know inboundsLocation is on the nearest graphBox border ScanSegment, so this won't return a
            // null edge, and we'll just do normal join-to-one-edge handling, extending in the direction to the graph.
            var inboundsVertex = this.VisGraph.FindVertex(inboundsLocation);
            var dirToGraph = CompassVector.OppositeDir(dirFromGraph);
            if (null != inboundsVertex) {
                freePoint.AddToAdjacentVertex(this.TransUtil, inboundsVertex, dirToGraph, this.portSpliceLimitRectangle);
            }
            else {
                var edge = this.FindorCreateNearestPerpEdge(oobLocation, inboundsLocation, dirFromGraph, ScanSegment.NormalWeight);
                if (null != edge) {
                    inboundsVertex = freePoint.AddEdgeToAdjacentEdge(this.TransUtil, edge, dirToGraph, this.portSpliceLimitRectangle);
                }
            }

            // This may be an oob waypoint, in which case we want to add additional edges so we can
            // go outside graph, cross the waypoint, and come back in.  Shortest-paths will do the
            // work of determining the optimal path, to avoid backtracking.
            var inboundsLeftVertex = StaticGraphUtility.FindNextVertex(inboundsVertex, CompassVector.RotateLeft(dirToGraph));
            if (inboundsLeftVertex != null) {
                this.TransUtil.ConnectVertexToTargetVertex(freePoint.Vertex, inboundsLeftVertex, dirToGraph, ScanSegment.NormalWeight);
            }
            var inboundsRightVertex = StaticGraphUtility.FindNextVertex(inboundsVertex, CompassVector.RotateRight(dirToGraph));
            if (inboundsRightVertex != null) {
                this.TransUtil.ConnectVertexToTargetVertex(freePoint.Vertex, inboundsRightVertex, dirToGraph, ScanSegment.NormalWeight);
            }
        }
 private FreePoint FindOrCreateFreePoint(Point location) {
     FreePoint freePoint;
     if (!this.freePointMap.TryGetValue(location, out freePoint)) {
         freePoint = new FreePoint(TransUtil, location);
         this.freePointMap[location] = freePoint;
     } else {
         freePoint.GetVertex(TransUtil, location);
     }
     freePointsInGraph.Insert(freePoint);
     freePointLocationsUsedByRouteEdges.Insert(location);
     return freePoint;
 }
        private void ConnectOobWaypointToEndpointVisibilityAtGraphBoundary(FreePoint oobWaypoint, Port port) {
            if ((oobWaypoint == null) || !oobWaypoint.IsOutOfBounds) {
                return;
            }

            // Connect to the graphbox side at points collinear with the vertices.  The waypoint may be
            // OOB in two directions so call once for each axis.
            var endpointVertices = this.FindVertices(port);
            var dirFromGraph = oobWaypoint.OutOfBoundsDirectionFromGraph & (Directions.North | Directions.South);
            ConnectToGraphAtPointsCollinearWithVertices(oobWaypoint, dirFromGraph, endpointVertices);
            dirFromGraph = oobWaypoint.OutOfBoundsDirectionFromGraph & (Directions.East | Directions.West);
            ConnectToGraphAtPointsCollinearWithVertices(oobWaypoint, dirFromGraph, endpointVertices);
        }
 private void ConnectToGraphAtPointsCollinearWithVertices(FreePoint oobWaypoint, Directions dirFromGraph,
             List<VisibilityVertex> endpointVertices) {
     if (Directions. None == dirFromGraph) {
         // Not out of bounds on this axis.
         return;
     }
     var dirToGraph = CompassVector.OppositeDir(dirFromGraph);
     foreach (var vertex in endpointVertices) {
         var graphBorderLocation = this.InBoundsGraphBoxIntersect(vertex.Point, dirFromGraph);
         var graphBorderVertex = this.VisGraph.FindVertex(graphBorderLocation);
         if (graphBorderVertex != null) {
             this.TransUtil.ConnectVertexToTargetVertex(oobWaypoint.Vertex, graphBorderVertex, dirToGraph, ScanSegment.NormalWeight);
         }
     }
 }
        private void ConnectFreePointToLateralEdge(FreePoint freePoint, Directions lateralDir) {
            // Turn on pivot vertex to either side to find the next edge to connect to.  If the freepoint is
            // overlapped (inside an obstacle), just find the closest ScanSegment outside the obstacle and 
            // start extending from there; otherwise, we can have the FreePoint calculate its max visibility.
            var end = freePoint.IsOverlapped ? this.InBoundsGraphBoxIntersect(freePoint.Point, lateralDir)
                                             : freePoint.MaxVisibilityInDirectionForNonOverlappedFreePoint(lateralDir, this.TransUtil);
            var lateralEdge = this.FindorCreateNearestPerpEdge(end, freePoint.Point, lateralDir, freePoint.InitialWeight);

            // There may be no VisibilityEdge between the current point and any adjoining obstacle in that direction.
            if (null != lateralEdge) {
                freePoint.AddEdgeToAdjacentEdge(TransUtil, lateralEdge, lateralDir, this.portSpliceLimitRectangle);
            }
        }