OSMServer/Pathfinding/Pathfinder.cs

103 lines
3.6 KiB
C#
Raw Normal View History

2023-02-03 23:35:22 +01:00
using OSMDatastructure;
using OSMImporter;
namespace Pathfinding;
public class Pathfinder
{
public static List<OsmNode> CustomAStar(string workingDir, Coordinates start, Coordinates goal, OsmEdge.speedType vehicle)
2023-02-03 23:35:22 +01:00
{
RegionManager regionManager = new RegionManager(workingDir);
2023-02-05 20:03:47 +01:00
Region startRegion, goalRegion;
try
{
startRegion = regionManager.GetRegion(start);
goalRegion = regionManager.GetRegion(goal);
}
catch (FileNotFoundException e)
{
2023-02-06 17:32:55 +01:00
throw new Exception(string.Format("No region at coordinates {0}", e.FileName), e);
2023-02-05 20:03:47 +01:00
}
2023-02-06 17:32:55 +01:00
2023-02-08 18:09:06 +01:00
OsmNode? startNode = ClosestNodeToCoordinates(start, startRegion);
OsmNode? goalNode = ClosestNodeToCoordinates(goal, goalRegion);
2023-02-06 17:32:55 +01:00
if (startNode == null || goalNode == null)
return new List<OsmNode>();
2023-02-03 23:35:22 +01:00
2023-02-06 17:32:55 +01:00
List<OsmNode> toVisit = new() { startNode };
2023-02-08 18:09:06 +01:00
OsmNode closestNodeToGoal = toVisit.First();
closestNodeToGoal.currentPathWeight = 0;
2023-02-08 19:09:46 +01:00
closestNodeToGoal.currentPathLength = 0;
2023-02-05 20:03:47 +01:00
bool stop = false;
while (toVisit.Count > 0 && !stop)
{
2023-02-08 19:06:04 +01:00
//Console.WriteLine("toVisit-length: {0}", toVisit.Count);
2023-02-06 17:32:55 +01:00
closestNodeToGoal = toVisit.First();
foreach (OsmNode node in toVisit)
2023-02-05 20:03:47 +01:00
{
2023-02-07 23:53:38 +01:00
if (node.directDistanceToGoal.Equals(double.MaxValue))
2023-02-06 17:32:55 +01:00
{
2023-02-07 23:53:38 +01:00
node.directDistanceToGoal = Utils.DistanceBetween(node, goalNode);
2023-02-06 17:32:55 +01:00
}
2023-02-07 23:53:38 +01:00
if (node.directDistanceToGoal < closestNodeToGoal.directDistanceToGoal)
2023-02-05 20:03:47 +01:00
{
closestNodeToGoal = node;
}
}
2023-02-08 18:09:06 +01:00
foreach (OsmEdge edge in closestNodeToGoal.edges)
2023-02-05 20:03:47 +01:00
{
2023-02-08 18:09:06 +01:00
OsmNode? neighbor = regionManager.GetNode(edge.neighborCoordinates);
if (neighbor != null)
2023-02-05 20:03:47 +01:00
{
double newPotentialWeight =
closestNodeToGoal.currentPathWeight + edge.GetWeight(closestNodeToGoal, vehicle);
if (neighbor.currentPathWeight > newPotentialWeight)
{
neighbor.previousPathNode = closestNodeToGoal;
neighbor.currentPathWeight = newPotentialWeight;
2023-02-08 19:09:46 +01:00
neighbor.currentPathLength = closestNodeToGoal.currentPathLength + Utils.DistanceBetween(closestNodeToGoal, neighbor);
2023-02-05 20:03:47 +01:00
if (neighbor.Equals(goalNode))
stop = true;
else
toVisit.Add(neighbor);
}
2023-02-05 20:03:47 +01:00
}
}
2023-02-06 17:32:55 +01:00
toVisit.Remove(closestNodeToGoal);
2023-02-05 20:03:47 +01:00
}
2023-02-06 17:32:55 +01:00
List<OsmNode> path = new();
OsmNode? currentNode = goalNode;
while (currentNode != null && !currentNode.Equals(startNode))
2023-02-05 20:03:47 +01:00
{
path.Add(currentNode);
2023-02-06 17:32:55 +01:00
currentNode = currentNode.previousPathNode;
2023-02-05 20:03:47 +01:00
}
path.Add(startNode);
path.Reverse();
2023-02-05 20:03:47 +01:00
return path;
2023-02-03 23:35:22 +01:00
}
2023-02-06 17:32:55 +01:00
private static OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Region region)
2023-02-03 23:35:22 +01:00
{
2023-02-06 17:32:55 +01:00
OsmNode? closest = null;
double distance = double.MaxValue;
foreach (OsmNode node in region.nodes)
2023-02-03 23:35:22 +01:00
{
2023-02-06 17:32:55 +01:00
double nodeDistance = Utils.DistanceBetween(node, coordinates);
if (nodeDistance < distance)
2023-02-03 23:35:22 +01:00
{
2023-02-06 17:32:55 +01:00
closest = node;
distance = nodeDistance;
2023-02-03 23:35:22 +01:00
}
}
2023-02-06 17:32:55 +01:00
return closest;
2023-02-03 23:35:22 +01:00
}
}