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 OSMDatastructure.Graph;
using OSMImporter;
using Pathfinding;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -15,12 +18,19 @@ 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) =>
{ {
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); 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. // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
@ -35,3 +45,19 @@ app.UseAuthorization();
app.MapControllers(); 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; } public Coordinates coordinates { get; }
[JsonIgnore][NonSerialized]public OsmNode? previousPathNode = null; [JsonIgnore][NonSerialized]public OsmNode? previousPathNode = null;
[JsonInclude][NonSerialized]public double currentPathWeight = double.MaxValue; [JsonIgnore][NonSerialized]public double currentPathWeight = double.MaxValue;
[JsonInclude][NonSerialized]public double currentPathLength = double.MaxValue; [JsonIgnore][NonSerialized]public double currentPathLength = double.MaxValue;
[JsonIgnore][NonSerialized]public double directDistanceToGoal = double.MaxValue; [JsonIgnore][NonSerialized]public double directDistanceToGoal = double.MaxValue;
[OnDeserialized] [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 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); DateTime startTime = DateTime.Now;
Region? startRegion = regionManager.GetRegion(start); TimeSpan calcTime;
Region? goalRegion = regionManager.GetRegion(goal); RegionManager regionManager = new (workingDir);
if (startRegion is null || goalRegion is null) OsmNode? startNode = ClosestNodeToCoordinates(start, vehicle, ref regionManager);
return new List<OsmNode>(); OsmNode? goalNode = ClosestNodeToCoordinates(goal, vehicle, ref regionManager);
OsmNode? startNode = ClosestNodeToCoordinates(start, startRegion, vehicle, ref regionManager);
OsmNode? goalNode = ClosestNodeToCoordinates(goal, goalRegion, vehicle, ref regionManager);
if (startNode == null || goalNode == null) 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(); PriorityQueue<OsmNode, double> toVisit = new();
toVisit.Enqueue(startNode, 0); toVisit.Enqueue(startNode, 0);
startNode.currentPathWeight = 0; startNode.currentPathWeight = 0;
startNode.currentPathLength = 0; startNode.currentPathLength = 0;
startNode.directDistanceToGoal = Utils.DistanceBetween(startNode, goalNode); startNode.directDistanceToGoal = Utils.DistanceBetween(startNode, goalNode);
OsmNode closestNodeToGoal = startNode;
bool stop = false; bool stop = false;
while (toVisit.Count > 0) while (toVisit.Count > 0)
{ {
closestNodeToGoal = toVisit.Dequeue(); OsmNode closestNodeToGoal = toVisit.Dequeue();
Console.WriteLine($"{toVisit.Count:000} {closestNodeToGoal.directDistanceToGoal:#.00} current:{closestNodeToGoal}"); //Console.WriteLine($"{toVisit.Count:000} {closestNodeToGoal.directDistanceToGoal:#.00} current:{closestNodeToGoal}");
foreach (OsmEdge edge in closestNodeToGoal.edges) foreach (OsmEdge edge in closestNodeToGoal.edges)
{ {
@ -44,6 +43,7 @@ public static class Pathfinder
neighbor.previousPathNode = closestNodeToGoal; neighbor.previousPathNode = closestNodeToGoal;
neighbor.currentPathWeight = newPotentialWeight; neighbor.currentPathWeight = newPotentialWeight;
neighbor.currentPathLength = closestNodeToGoal.currentPathLength + Utils.DistanceBetween(closestNodeToGoal, neighbor); neighbor.currentPathLength = closestNodeToGoal.currentPathLength + Utils.DistanceBetween(closestNodeToGoal, neighbor);
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
if (neighbor.Equals(goalNode) || closestNodeToGoal.directDistanceToGoal < 10) if (neighbor.Equals(goalNode) || closestNodeToGoal.directDistanceToGoal < 10)
{ {
@ -52,7 +52,6 @@ public static class Pathfinder
} }
else if(!stop) else if(!stop)
{ {
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal); toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
} }
} }
@ -60,23 +59,26 @@ public static class Pathfinder
} }
} }
List<OsmNode> path = new(); List<PathNode> path = new();
OsmNode? currentNode = goalNode; 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; currentNode = currentNode.previousPathNode;
} }
path.Add(startNode);
path.Reverse(); 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; OsmNode? closest = null;
double distance = double.MaxValue; double distance = double.MaxValue;
Region? region = regionManager.GetRegion(coordinates);
if (region is null)
return null;
foreach (OsmNode node in region.nodes) foreach (OsmNode node in region.nodes)
{ {
bool hasConnectionUsingVehicle = false; bool hasConnectionUsingVehicle = false;

View File

@ -13,21 +13,21 @@ public class Server
Console.SetOut(newConsole); Console.SetOut(newConsole);
Console.SetError(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"); //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 start = new Coordinates(48.794567f, 9.820625f);
Coordinates finish = new Coordinates(48.8407888f, 10.0676020f); Coordinates finish = new Coordinates(48.79593f, 9.824013f);
DateTime startTime = DateTime.Now; 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; TimeSpan duration = DateTime.Now - startTime;
Console.WriteLine($"Took {duration.TotalMilliseconds}ms ({duration:g})"); Console.WriteLine($"Took {duration.TotalMilliseconds}ms ({duration:g})");
for (int i = 0; i < path.Length - 1; i++) for (int i = 0; i < path.Length - 1; i++)
{ {
Console.WriteLine(path[i]); Console.WriteLine(path[i]);
} }
Console.WriteLine(); Console.WriteLine();*/
} }
} }