2023-02-03 23:35:22 +01:00
|
|
|
|
using OSMDatastructure;
|
|
|
|
|
using OSMImporter;
|
|
|
|
|
|
|
|
|
|
namespace Pathfinding;
|
|
|
|
|
|
|
|
|
|
public class Pathfinder
|
|
|
|
|
{
|
|
|
|
|
|
2023-02-06 17:32:55 +01:00
|
|
|
|
public static List<OsmNode> CustomAStar(string workingDir, Coordinates start, Coordinates goal)
|
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-05 20:03:47 +01:00
|
|
|
|
bool stop = false;
|
|
|
|
|
|
|
|
|
|
while (toVisit.Count > 0 && !stop)
|
|
|
|
|
{
|
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 && neighbor.currentPathWeight > closestNodeToGoal.currentPathWeight + Utils.DistanceBetween(closestNodeToGoal, neighbor))
|
2023-02-05 20:03:47 +01:00
|
|
|
|
{
|
|
|
|
|
neighbor.previousPathNode = closestNodeToGoal;
|
|
|
|
|
neighbor.currentPathWeight = closestNodeToGoal.currentPathWeight +
|
|
|
|
|
Utils.DistanceBetween(closestNodeToGoal, neighbor);
|
|
|
|
|
|
|
|
|
|
if (neighbor.Equals(goalNode))
|
|
|
|
|
stop = true;
|
|
|
|
|
else
|
|
|
|
|
toVisit.Add(neighbor);
|
|
|
|
|
}
|
|
|
|
|
}
|
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);
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
}
|