public AStarShortestPathFinder(RouteGraph routeGraph) { this.graph = routeGraph; }
public static RouteGraph InitializeVertices(IEnumerable<IRect> nodes, IEnumerable<IEdge> edges) { var graph = new RouteGraph(); // add vertices for node corners foreach (var node in nodes) { graph.Boxes.Add(node); foreach (var vertex in GetRectCorners(node, boxPadding)) { graph.Vertices.Add(vertex); } } // add vertices for egde endpoints foreach (var multiEdgeGroup in edges.GroupBy(edge => GetStartEnd(edge))) { int multiEdgeCount = multiEdgeGroup.Count(); IRect fromRect = multiEdgeGroup.First().From; IRect toRect = multiEdgeGroup.First().To; var sourceCenter = GeomUtils.RectCenter(fromRect); var targetCenter = GeomUtils.RectCenter(toRect); if (Math.Abs(sourceCenter.X - targetCenter.X) > Math.Abs(sourceCenter.Y - targetCenter.Y) || (fromRect == toRect)) { // the line is horizontal double multiEdgeSpanSource = GetMultiEdgeSpan(fromRect.Height, multiEdgeCount, multiEdgeGap); double multiEdgeSpanTarget = GetMultiEdgeSpan(toRect.Height, multiEdgeCount, multiEdgeGap); double originSourceCurrentY = sourceCenter.Y - multiEdgeSpanSource / 2; double originTargetCurrentY = targetCenter.Y - multiEdgeSpanTarget / 2; foreach (var edge in multiEdgeGroup.OrderBy(edge => edge.From == edge.To)) { Point2D sourceOrigin = new Point2D(sourceCenter.X, originSourceCurrentY); Point2D targetOrigin = new Point2D(targetCenter.X, originTargetCurrentY); // Here user could provide custom edgeStart and edgeEnd // inflate boxes a little so that edgeStart and edgeEnd are a little outside of the box (to prevent floating point errors) if (edge.From == edge.To) { var edgeStart = new Point2D(fromRect.Left + fromRect.Width + 0.01, originSourceCurrentY); var edgeEnd = new Point2D(fromRect.Left + fromRect.Width / 2, fromRect.Top); graph.AddEdgeEndpointVertices(edge, edgeStart, edgeEnd); } else { var edgeStart = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.From.Inflated(1e-3)); var edgeEnd = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.To.Inflated(1e-3)); graph.AddEdgeEndpointVertices(edge, edgeStart, edgeEnd); } originSourceCurrentY += multiEdgeSpanSource / (multiEdgeCount - 1); originTargetCurrentY += multiEdgeSpanTarget / (multiEdgeCount - 1); } } else { // the line is vertical double multiEdgeSpanSource = GetMultiEdgeSpan(fromRect.Width, multiEdgeCount, multiEdgeGap); double multiEdgeSpanTarget = GetMultiEdgeSpan(toRect.Width, multiEdgeCount, multiEdgeGap); double originSourceCurrentX = sourceCenter.X - multiEdgeSpanSource / 2; double originTargetCurrentX = targetCenter.X - multiEdgeSpanTarget / 2; foreach (var edge in multiEdgeGroup.OrderBy(edge => edge.From == edge.To)) { Point2D sourceOrigin = new Point2D(originSourceCurrentX, sourceCenter.Y); Point2D targetOrigin = new Point2D(originTargetCurrentX, targetCenter.Y); // Here user could provide custom edgeStart and edgeEnd // inflate boxes a little so that edgeStart and edgeEnd are a little outside of the box (to prevent floating point errors) var edgeStart = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.From.Inflated(1e-3)); var edgeEnd = GeomUtils.LineRectIntersection(sourceOrigin, targetOrigin, edge.To.Inflated(1e-3)); graph.AddEdgeEndpointVertices(edge, edgeStart, edgeEnd); originSourceCurrentX += multiEdgeSpanSource / (multiEdgeCount - 1); originTargetCurrentX += multiEdgeSpanTarget / (multiEdgeCount - 1); } } } return graph; }