Splitting Pathfinding into separate files for each type of routing.

Removing timetracking again from routing-algos (not in scope)
This commit is contained in:
glax 2023-04-09 16:17:15 +02:00
parent fe0ccd0fca
commit 58d1031524
3 changed files with 85 additions and 73 deletions

View File

@ -18,9 +18,9 @@ var app = builder.Build();
app.MapGet("/getRoute", (float latStart, float lonStart, float latEnd, float lonEnd) => app.MapGet("/getRoute", (float latStart, float lonStart, float latEnd, float lonEnd) =>
{ {
ValueTuple<TimeSpan, List<PathNode>> result = Pathfinder.CustomAStar("D:/stuttgart-regbez-latest", new Coordinates(latStart, lonStart), new Coordinates(latEnd, lonEnd), DateTime startCalc = DateTime.Now;
Tag.SpeedType.car); List<PathNode> result = Pathfinder.AStarDistance("D:/stuttgart-regbez-latest", new Coordinates(latStart, lonStart), new Coordinates(latEnd, lonEnd));
PathResult pathResult = new PathResult(result.Item1, result.Item2); PathResult pathResult = new PathResult(startCalc - DateTime.Now, result);
return pathResult; return pathResult;
} }
); );
@ -28,7 +28,7 @@ app.MapGet("/getRoute", (float latStart, float lonStart, float latEnd, float lon
app.MapGet("/getClosestNode", (float lat, float lon) => app.MapGet("/getClosestNode", (float lat, float lon) =>
{ {
RegionManager regionManager = new RegionManager("D:/stuttgart-regbez-latest"); RegionManager regionManager = new RegionManager("D:/stuttgart-regbez-latest");
return Pathfinder.ClosestNodeToCoordinates(new Coordinates(lat, lon), Tag.SpeedType.car, ref regionManager); return Pathfinder.ClosestNodeToCoordinates(new Coordinates(lat, lon), Tag.SpeedType.car, regionManager);
}); });
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.

View File

@ -4,75 +4,23 @@ using OSMImporter;
namespace Pathfinding; namespace Pathfinding;
public static class Pathfinder public static partial class Pathfinder
{ {
public static ValueTuple<TimeSpan, List<PathNode>> CustomAStar(string workingDir, Coordinates start, Coordinates goal, Tag.SpeedType vehicle)
private static ValueTuple<OsmNode?, OsmNode?> SetupNodes(Coordinates startCoordinates, Coordinates goalCoordinates, RegionManager regionManager )
{ {
DateTime startTime = DateTime.Now; ValueTuple<OsmNode?, OsmNode?> retTuple = new();
TimeSpan calcTime; retTuple.Item1 = ClosestNodeToCoordinates(startCoordinates, Tag.SpeedType.road, regionManager);
RegionManager regionManager = new (workingDir); retTuple.Item2 = ClosestNodeToCoordinates(goalCoordinates, Tag.SpeedType.road, regionManager);
OsmNode? startNode = ClosestNodeToCoordinates(start, vehicle, ref regionManager); if (retTuple.Item1 is null || retTuple.Item2 is null)
OsmNode? goalNode = ClosestNodeToCoordinates(goal, vehicle, ref regionManager); return retTuple;
if (startNode == null || goalNode == null) retTuple.Item1.currentPathWeight = 0;
{ retTuple.Item1.currentPathLength = 0;
calcTime = DateTime.Now - startTime; retTuple.Item1.directDistanceToGoal = Utils.DistanceBetween(retTuple.Item1, retTuple.Item2);
return new ValueTuple<TimeSpan, List<PathNode>>(calcTime, new List<PathNode>()); return retTuple;
}
PriorityQueue<OsmNode, double> toVisit = new();
toVisit.Enqueue(startNode, 0);
startNode.currentPathWeight = 0;
startNode.currentPathLength = 0;
startNode.directDistanceToGoal = Utils.DistanceBetween(startNode, goalNode);
bool stop = false;
while (toVisit.Count > 0)
{
OsmNode closestNodeToGoal = toVisit.Dequeue();
//Console.WriteLine($"{toVisit.Count:000} {closestNodeToGoal.directDistanceToGoal:#.00} current:{closestNodeToGoal}");
foreach (OsmEdge edge in closestNodeToGoal.edges)
{
OsmNode? neighbor = regionManager.GetNode(edge.neighborId, edge.neighborRegion);
if (neighbor is not null)
{
double newPotentialWeight =
closestNodeToGoal.currentPathWeight + EdgeWeight(closestNodeToGoal, neighbor, edge.wayId, vehicle, ref regionManager);
if (newPotentialWeight < neighbor.currentPathWeight)
{
neighbor.previousPathNode = closestNodeToGoal;
neighbor.currentPathWeight = newPotentialWeight;
neighbor.currentPathLength = closestNodeToGoal.currentPathLength + Utils.DistanceBetween(closestNodeToGoal, neighbor);
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
if (neighbor.Equals(goalNode) || closestNodeToGoal.directDistanceToGoal < 10)
{
stop = true;
goalNode = neighbor;
}
else if(!stop)
{
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
}
}
}
}
}
List<PathNode> path = new();
OsmNode? currentNode = goalNode;
while (currentNode is not null)
{
path.Add(PathNode.FromOsmNode(currentNode)!);
currentNode = currentNode.previousPathNode;
}
path.Reverse();
calcTime = DateTime.Now - startTime;
return new ValueTuple<TimeSpan, List<PathNode>>(calcTime, path);
} }
public static OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Tag.SpeedType vehicle, ref RegionManager regionManager) public static OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Tag.SpeedType vehicle, RegionManager regionManager)
{ {
OsmNode? closest = null; OsmNode? closest = null;
double distance = double.MaxValue; double distance = double.MaxValue;
@ -84,7 +32,7 @@ public static class Pathfinder
bool hasConnectionUsingVehicle = false; bool hasConnectionUsingVehicle = false;
foreach (OsmEdge edge in node.edges) foreach (OsmEdge edge in node.edges)
{ {
double speed = GetSpeed(node, edge.wayId, vehicle, ref regionManager); double speed = GetSpeedForEdge(node, edge.wayId, vehicle, regionManager);
if (speed != 0) if (speed != 0)
hasConnectionUsingVehicle = true; hasConnectionUsingVehicle = true;
} }
@ -99,7 +47,7 @@ public static class Pathfinder
return closest; return closest;
} }
private static double GetSpeed(OsmNode node1, ulong wayId, Tag.SpeedType vehicle, ref RegionManager regionManager) private static double GetSpeedForEdge(OsmNode node1, ulong wayId, Tag.SpeedType vehicle, RegionManager regionManager)
{ {
TagManager tags = regionManager.GetRegion(node1.coordinates)!.tagManager; TagManager tags = regionManager.GetRegion(node1.coordinates)!.tagManager;
Tag.WayType wayType = (Tag.WayType)tags.GetTag(wayId, Tag.TagType.highway)!; Tag.WayType wayType = (Tag.WayType)tags.GetTag(wayId, Tag.TagType.highway)!;
@ -127,7 +75,7 @@ public static class Pathfinder
private static double EdgeWeight(OsmNode node1, OsmNode node2, ulong wayId, Tag.SpeedType vehicle, ref RegionManager regionManager) private static double EdgeWeight(OsmNode node1, OsmNode node2, ulong wayId, Tag.SpeedType vehicle, ref RegionManager regionManager)
{ {
double distance = Utils.DistanceBetween(node1, node2); double distance = Utils.DistanceBetween(node1, node2);
double speed = GetSpeed(node1, wayId, vehicle, ref regionManager); double speed = GetSpeedForEdge(node1, wayId, vehicle, regionManager);
if (speed is not 0) if (speed is not 0)
return distance / speed; return distance / speed;
return double.PositiveInfinity; return double.PositiveInfinity;

View File

@ -0,0 +1,64 @@
using OSMDatastructure;
using OSMDatastructure.Graph;
using OSMImporter;
namespace Pathfinding;
public static partial class Pathfinder
{
public static List<PathNode> AStarDistance(string workingDir, Coordinates start,
Coordinates goal)
{
RegionManager regionManager = new (workingDir);
ValueTuple<OsmNode?, OsmNode?> startAndEndNode = SetupNodes(start, goal, regionManager);
if (startAndEndNode.Item1 is null || startAndEndNode.Item2 is null)
return new List<PathNode>();
OsmNode goalNode = startAndEndNode.Item2!;
PriorityQueue<OsmNode, double> toVisit = new();
toVisit.Enqueue(startAndEndNode.Item1, 0);
bool stop = false;
while (toVisit.Count > 0)
{
OsmNode closestNodeToGoal = toVisit.Dequeue();
foreach (OsmEdge edge in closestNodeToGoal.edges)
{
OsmNode? neighbor = regionManager.GetNode(edge.neighborId, edge.neighborRegion);
if (neighbor is not null)
{
double newPotentialWeight =
closestNodeToGoal.currentPathWeight + Utils.DistanceBetween(closestNodeToGoal, neighbor);
if (newPotentialWeight < neighbor.currentPathWeight)
{
neighbor.previousPathNode = closestNodeToGoal;
neighbor.currentPathWeight = newPotentialWeight; //for other types of routing
neighbor.currentPathLength = newPotentialWeight;
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
if (neighbor.Equals(goalNode))
{
stop = true;
}
else if(!stop)
{
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
}
}
}
}
}
List<PathNode> path = new();
OsmNode? currentNode = goalNode;
while (currentNode is not null)
{
path.Add(PathNode.FromOsmNode(currentNode)!);
currentNode = currentNode.previousPathNode;
}
path.Reverse();
return path;
}
}