diff --git a/Executable/Program.cs b/Executable/Program.cs index 84c50c0..dd9b08e 100644 --- a/Executable/Program.cs +++ b/Executable/Program.cs @@ -61,7 +61,7 @@ if (arguments.TryGetValue(pathArg, out string[]? pathValue)) converter.SplitOsmExportIntoRegionFiles(pathValue[0]); } -Route route = Astar.FindPath(startLat, startLon, endLat, endLon, regionSize, true, importFolderPath: importPath, logger: logger); +Route route = new Astar().FindPath(startLat, startLon, endLat, endLon, regionSize, true, importFolderPath: importPath, logger: logger); if(route.RouteFound) Console.WriteLine(route); else diff --git a/astar/Astar.cs b/astar/Astar.cs index 2d31ca6..be6c23c 100644 --- a/astar/Astar.cs +++ b/astar/Astar.cs @@ -6,11 +6,13 @@ using OSM_Regions; namespace astar { - public class Astar + public class Astar(ValueTuple? optimizingWeights = null, int? explorationDistance = null) { private static readonly ValueTuple DefaultPriorityWeights = new(1, 1.4f, 0, 0); - private static readonly ValueTuple OptimizingWeights = new(1, 0, 0, 0.5f); - public static Route FindPath(float startLat, float startLon, float endLat, float endLon, float regionSize, bool car = true, PathMeasure pathing = PathMeasure.Distance, float additionalExploration = 3, string? importFolderPath = null, ILogger? logger = null) + private readonly ValueTuple OptimizingWeights = optimizingWeights ?? new(1, 0, -0.2f, 0); + private int ExplorationDistanceFromRoute = explorationDistance ?? 200; + + public Route FindPath(float startLat, float startLon, float endLat, float endLon, float regionSize, bool car = true, PathMeasure pathing = PathMeasure.Distance, float additionalExploration = 3, string? importFolderPath = null, ILogger? logger = null) { RegionLoader rl = new(regionSize, importFolderPath, logger: logger); Graph graph = Spiral(rl, startLat, startLon, regionSize); @@ -64,9 +66,15 @@ namespace astar if(meetingEnds is null) return new Route(graph, Array.Empty().ToList(), false); - PriorityQueue combinedQueue = toVisitStart; - while(toVisitEnd.TryDequeue(out ulong id, out int prio)) - combinedQueue.Enqueue(id, prio); + List routeNodes = PathFound(graph, meetingEnds.Value.Item1, meetingEnds.Value.Item2, car).Steps.Select(s => s.Node1).ToList(); + Dictionary routeQueue = toVisitStart.UnorderedItems.Select(l => l.Element).Union(toVisitEnd.UnorderedItems.Select(l => l.Element)).Where(id => + { + Node p = graph.Nodes[id]; + return routeNodes.Any(route => route.DistanceTo(p) < ExplorationDistanceFromRoute); + }).ToDictionary(id => id, _ => int.MinValue); + PriorityQueue combinedQueue = new(); + foreach ((ulong key, int value) in routeQueue) + combinedQueue.Enqueue(key, value); ValueTuple? newMeetingEnds = Optimize(additionalExploration, graph, combinedQueue, car, rl, priorityHelper, pathing, startNode.Value, endNode.Value, logger); meetingEnds = newMeetingEnds ?? meetingEnds; @@ -123,10 +131,10 @@ namespace astar return null; } - private static ValueTuple? Optimize(float additionalExploration, Graph graph, PriorityQueue combinedQueue, bool car, RegionLoader rl, PriorityHelper priorityHelper, PathMeasure pathing, Node startNode, Node goalNode, ILogger? logger = null) + private ValueTuple? Optimize(float additionalExploration, Graph graph, PriorityQueue combinedQueue, bool car, RegionLoader rl, PriorityHelper priorityHelper, PathMeasure pathing, Node startNode, Node goalNode, ILogger? logger = null) { int currentPathLength = graph.Nodes.Values.Count(node => node.PreviousNodeId is not null); - int optimizeAfterFound = (int)(currentPathLength * additionalExploration); //Check another x% of unexplored Paths. + int optimizeAfterFound = (int)(combinedQueue.Count * additionalExploration); //Check another x% of unexplored Paths. logger?.LogInformation($"Path found (explored {currentPathLength} Nodes). Optimizing route. (exploring {optimizeAfterFound} additional Nodes)"); ValueTuple? newMeetingEnds = null; while (optimizeAfterFound-- > 0 && combinedQueue.Count > 0)