Compare commits

...

5 Commits

5 changed files with 93 additions and 33 deletions

View File

@ -1,4 +1,7 @@
using System.Text.Json.Serialization;
using OSMDatastructure.Graph;
using OSMImporter;
using Pathfinding;
var builder = WebApplication.CreateBuilder(args);
@ -15,12 +18,19 @@ var app = builder.Build();
app.MapGet("/getRoute", (float latStart, float lonStart, float latEnd, float lonEnd) =>
{
List<OsmNode> path = Pathfinding.Pathfinder.CustomAStar("D:/stuttgart-regbez-latest", new Coordinates(latStart, lonStart), new Coordinates(latEnd, lonEnd),
ValueTuple<TimeSpan, List<PathNode>> result = Pathfinder.CustomAStar("D:/stuttgart-regbez-latest", new Coordinates(latStart, lonStart), new Coordinates(latEnd, lonEnd),
Tag.SpeedType.car);
return path;
PathResult pathResult = new PathResult(result.Item1, result.Item2);
return pathResult;
}
);
app.MapGet("/getClosestNode", (float lat, float lon) =>
{
RegionManager regionManager = new RegionManager("D:/stuttgart-regbez-latest");
return Pathfinder.ClosestNodeToCoordinates(new Coordinates(lat, lon), Tag.SpeedType.car, ref regionManager);
});
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
@ -34,4 +44,20 @@ app.UseAuthorization();
app.MapControllers();
app.Run();
app.Run();
internal class PathResult
{
[JsonInclude]public TimeSpan calcTime;
[JsonInclude] public double pathWeight;
[JsonInclude] public double pathTravelDistance;
[JsonInclude]public List<PathNode> pathNodes;
public PathResult(TimeSpan calcTime, List<PathNode> pathNodes)
{
this.calcTime = calcTime;
this.pathNodes = pathNodes;
this.pathWeight = pathNodes.Last().currentPathWeight;
this.pathTravelDistance = pathNodes.Last().currentPathLength;
}
}

View File

@ -12,8 +12,8 @@ public class OsmNode
public Coordinates coordinates { get; }
[JsonIgnore][NonSerialized]public OsmNode? previousPathNode = null;
[JsonInclude][NonSerialized]public double currentPathWeight = double.MaxValue;
[JsonInclude][NonSerialized]public double currentPathLength = double.MaxValue;
[JsonIgnore][NonSerialized]public double currentPathWeight = double.MaxValue;
[JsonIgnore][NonSerialized]public double currentPathLength = double.MaxValue;
[JsonIgnore][NonSerialized]public double directDistanceToGoal = double.MaxValue;
[OnDeserialized]

32
Pathfinding/PathNode.cs Normal file
View File

@ -0,0 +1,32 @@
using System.Text.Json.Serialization;
using OSMDatastructure.Graph;
namespace Pathfinding;
public class PathNode : OsmNode
{
[JsonInclude]public new double currentPathWeight = double.MaxValue;
[JsonInclude]public new double currentPathLength = double.MaxValue;
[JsonInclude]public new double directDistanceToGoal = double.MaxValue;
public PathNode(ulong nodeId, float lat, float lon) : base(nodeId, lat, lon)
{
}
public PathNode(ulong nodeId, Coordinates coordinates) : base(nodeId, coordinates)
{
}
public static PathNode? FromOsmNode(OsmNode? node)
{
if (node is null)
return null;
PathNode retNode = new PathNode(node.nodeId, node.coordinates)
{
currentPathLength = node.currentPathLength,
currentPathWeight = node.currentPathWeight,
directDistanceToGoal = node.directDistanceToGoal
};
return retNode;
}
}

View File

@ -6,31 +6,30 @@ namespace Pathfinding;
public static class Pathfinder
{
public static List<OsmNode> CustomAStar(string workingDir, Coordinates start, Coordinates goal, Tag.SpeedType vehicle)
public static ValueTuple<TimeSpan, List<PathNode>> CustomAStar(string workingDir, Coordinates start, Coordinates goal, Tag.SpeedType vehicle)
{
RegionManager regionManager = new RegionManager(workingDir);
Region? startRegion = regionManager.GetRegion(start);
Region? goalRegion = regionManager.GetRegion(goal);
if (startRegion is null || goalRegion is null)
return new List<OsmNode>();
OsmNode? startNode = ClosestNodeToCoordinates(start, startRegion, vehicle, ref regionManager);
OsmNode? goalNode = ClosestNodeToCoordinates(goal, goalRegion, vehicle, ref regionManager);
DateTime startTime = DateTime.Now;
TimeSpan calcTime;
RegionManager regionManager = new (workingDir);
OsmNode? startNode = ClosestNodeToCoordinates(start, vehicle, ref regionManager);
OsmNode? goalNode = ClosestNodeToCoordinates(goal, vehicle, ref regionManager);
if (startNode == null || goalNode == null)
return new List<OsmNode>();
{
calcTime = DateTime.Now - startTime;
return new ValueTuple<TimeSpan, List<PathNode>>(calcTime, new List<PathNode>());
}
PriorityQueue<OsmNode, double> toVisit = new();
toVisit.Enqueue(startNode, 0);
startNode.currentPathWeight = 0;
startNode.currentPathLength = 0;
startNode.directDistanceToGoal = Utils.DistanceBetween(startNode, goalNode);
OsmNode closestNodeToGoal = startNode;
bool stop = false;
while (toVisit.Count > 0)
{
closestNodeToGoal = toVisit.Dequeue();
Console.WriteLine($"{toVisit.Count:000} {closestNodeToGoal.directDistanceToGoal:#.00} current:{closestNodeToGoal}");
OsmNode closestNodeToGoal = toVisit.Dequeue();
//Console.WriteLine($"{toVisit.Count:000} {closestNodeToGoal.directDistanceToGoal:#.00} current:{closestNodeToGoal}");
foreach (OsmEdge edge in closestNodeToGoal.edges)
{
@ -44,6 +43,7 @@ public static class Pathfinder
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)
{
@ -52,7 +52,6 @@ public static class Pathfinder
}
else if(!stop)
{
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
}
}
@ -60,23 +59,26 @@ public static class Pathfinder
}
}
List<OsmNode> path = new();
List<PathNode> path = new();
OsmNode? currentNode = goalNode;
while (currentNode != null && !currentNode.Equals(startNode))
while (currentNode is not null)
{
path.Add(currentNode);
path.Add(PathNode.FromOsmNode(currentNode)!);
currentNode = currentNode.previousPathNode;
}
path.Add(startNode);
path.Reverse();
return path;
calcTime = DateTime.Now - startTime;
return new ValueTuple<TimeSpan, List<PathNode>>(calcTime, path);
}
private static OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Region region, Tag.SpeedType vehicle, ref RegionManager regionManager)
public static OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Tag.SpeedType vehicle, ref RegionManager regionManager)
{
OsmNode? closest = null;
double distance = double.MaxValue;
Region? region = regionManager.GetRegion(coordinates);
if (region is null)
return null;
foreach (OsmNode node in region.nodes)
{
bool hasConnectionUsingVehicle = false;

View File

@ -13,21 +13,21 @@ public class Server
Console.SetOut(newConsole);
Console.SetError(newConsole);
//RegionConverter.ConvertXMLToRegions("D:/stuttgart-regbez-latest.osm", "D:/stuttgart-regbez-latest");
RegionConverter.ConvertXMLToRegions("D:/stuttgart-regbez-latest.osm", "D:/stuttgart-regbez-latest");
//RegionConverter.ConvertXMLToRegions("D:/map.osm", "D:/map");
Console.WriteLine("Loaded");
//RegionConverter.ConvertXMLToRegions("D:/germany-latest.osm", "D:/germany-latest");
Coordinates start = new Coordinates(48.793319f, 9.832102f);
Coordinates finish = new Coordinates(48.8407888f, 10.0676020f);
/*
Coordinates start = new Coordinates(48.794567f, 9.820625f);
Coordinates finish = new Coordinates(48.79593f, 9.824013f);
DateTime startTime = DateTime.Now;
OsmNode[] path = Pathfinder.CustomAStar("D:/stuttgart-regbez-latest", start, finish, Tag.SpeedType.car).ToArray();
OsmNode[] path = Pathfinder.CustomAStar("D:/map", start, finish, Tag.SpeedType.car).ToArray();
TimeSpan duration = DateTime.Now - startTime;
Console.WriteLine($"Took {duration.TotalMilliseconds}ms ({duration:g})");
for (int i = 0; i < path.Length - 1; i++)
{
Console.WriteLine(path[i]);
}
Console.WriteLine();
Console.WriteLine();*/
}
}