Add separation between cars and pedestrian highways.
Add priority for high-speed routes.
This commit is contained in:
parent
4261bc2f48
commit
3a1ca0cc3d
@ -61,7 +61,7 @@ if (arguments.TryGetValue(pathArg, out string[]? pathValue))
|
|||||||
converter.SplitOsmExportIntoRegionFiles(pathValue[0]);
|
converter.SplitOsmExportIntoRegionFiles(pathValue[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Route route = Astar.FindPath(startLat, startLon, endLat, endLon, regionSize, importPath, logger);
|
Route route = Astar.FindPath(startLat, startLon, endLat, endLon, regionSize, true, importPath, logger);
|
||||||
if(route.RouteFound)
|
if(route.RouteFound)
|
||||||
Console.WriteLine(route);
|
Console.WriteLine(route);
|
||||||
else
|
else
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
@ -1,4 +1,6 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using astar.PathingHelper;
|
||||||
|
using Graph;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Graph.Utils;
|
using Graph.Utils;
|
||||||
using OSM_Regions;
|
using OSM_Regions;
|
||||||
|
|
||||||
@ -6,19 +8,19 @@ namespace astar
|
|||||||
{
|
{
|
||||||
public static class Astar
|
public static class Astar
|
||||||
{
|
{
|
||||||
public static Route FindPath(float startLat, float startLon, float endLat, float endLon, float regionSize, string? importFolderPath = null,
|
public static Route FindPath(float startLat, float startLon, float endLat, float endLon, float regionSize, bool car = true, string? importFolderPath = null,
|
||||||
ILogger? logger = null)
|
ILogger? logger = null)
|
||||||
{
|
{
|
||||||
RegionLoader rl = new(regionSize, importFolderPath, logger: logger);
|
RegionLoader rl = new(regionSize, importFolderPath, logger: logger);
|
||||||
Graph graph = Spiral(rl, startLat, startLon, regionSize);
|
Graph graph = Spiral(rl, startLat, startLon, regionSize);
|
||||||
KeyValuePair<ulong, Node> startNode = graph.ClosestNodeToCoordinates(startLat, startLon);
|
KeyValuePair<ulong, Node> startNode = graph.ClosestNodeToCoordinates(startLat, startLon, car);
|
||||||
startNode.Value.PreviousIsFromStart = true;
|
startNode.Value.PreviousIsFromStart = true;
|
||||||
startNode.Value.PreviousNodeId = startNode.Key;
|
startNode.Value.PreviousNodeId = startNode.Key;
|
||||||
startNode.Value.Distance = 0f;
|
startNode.Value.Distance = 0f;
|
||||||
|
|
||||||
Graph endRegion = Spiral(rl, endLat, endLon, regionSize);
|
Graph endRegion = Spiral(rl, endLat, endLon, regionSize);
|
||||||
graph.ConcatGraph(endRegion);
|
graph.ConcatGraph(endRegion);
|
||||||
KeyValuePair<ulong, Node> endNode = graph.ClosestNodeToCoordinates(endLat, endLon);
|
KeyValuePair<ulong, Node> endNode = graph.ClosestNodeToCoordinates(endLat, endLon, car);
|
||||||
endNode.Value.PreviousIsFromStart = false;
|
endNode.Value.PreviousIsFromStart = false;
|
||||||
endNode.Value.PreviousNodeId = endNode.Key;
|
endNode.Value.PreviousNodeId = endNode.Key;
|
||||||
endNode.Value.Distance = 0f;
|
endNode.Value.Distance = 0f;
|
||||||
@ -42,6 +44,16 @@ namespace astar
|
|||||||
{
|
{
|
||||||
if (!graph.ContainsNode(neighborId))
|
if (!graph.ContainsNode(neighborId))
|
||||||
graph.ConcatGraph(Graph.FromGraph(rl.LoadRegionFromNodeId(neighborId)));
|
graph.ConcatGraph(Graph.FromGraph(rl.LoadRegionFromNodeId(neighborId)));
|
||||||
|
if (!graph.ContainsWay(wayId))
|
||||||
|
{
|
||||||
|
foreach (global::Graph.Graph? g in rl.LoadRegionsFromWayId(wayId))
|
||||||
|
graph.ConcatGraph(Graph.FromGraph(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
Way way = graph.Ways[wayId];
|
||||||
|
byte speed = SpeedHelper.GetSpeed(way, car);
|
||||||
|
if(speed < 1)
|
||||||
|
continue;
|
||||||
Node neighborNode = graph.Nodes[neighborId];
|
Node neighborNode = graph.Nodes[neighborId];
|
||||||
|
|
||||||
if (neighborNode.PreviousIsFromStart is false)//Check if we found the opposite End
|
if (neighborNode.PreviousIsFromStart is false)//Check if we found the opposite End
|
||||||
@ -53,7 +65,7 @@ namespace astar
|
|||||||
neighborNode.PreviousNodeId = currentNodeStartId;
|
neighborNode.PreviousNodeId = currentNodeStartId;
|
||||||
neighborNode.Distance = distance;
|
neighborNode.Distance = distance;
|
||||||
neighborNode.PreviousIsFromStart = true;
|
neighborNode.PreviousIsFromStart = true;
|
||||||
toVisitStart.Enqueue(neighborId, NodeUtils.DistanceBetween(neighborNode, endNode.Value));
|
toVisitStart.Enqueue(neighborId, NodeUtils.DistanceBetween(neighborNode, endNode.Value) / speed);
|
||||||
}
|
}
|
||||||
logger?.LogTrace($"Neighbor {neighborId} {neighborNode}");
|
logger?.LogTrace($"Neighbor {neighborId} {neighborNode}");
|
||||||
}
|
}
|
||||||
@ -64,6 +76,16 @@ namespace astar
|
|||||||
{
|
{
|
||||||
if (!graph.ContainsNode(neighborId))
|
if (!graph.ContainsNode(neighborId))
|
||||||
graph.ConcatGraph(Graph.FromGraph(rl.LoadRegionFromNodeId(neighborId)));
|
graph.ConcatGraph(Graph.FromGraph(rl.LoadRegionFromNodeId(neighborId)));
|
||||||
|
if (!graph.ContainsWay(wayId))
|
||||||
|
{
|
||||||
|
foreach (global::Graph.Graph? g in rl.LoadRegionsFromWayId(wayId))
|
||||||
|
graph.ConcatGraph(Graph.FromGraph(g));
|
||||||
|
}
|
||||||
|
|
||||||
|
Way way = graph.Ways[wayId];
|
||||||
|
byte speed = SpeedHelper.GetSpeed(way, car);
|
||||||
|
if(speed < 1)
|
||||||
|
continue;
|
||||||
Node neighborNode = graph.Nodes[neighborId];
|
Node neighborNode = graph.Nodes[neighborId];
|
||||||
|
|
||||||
if (neighborNode.PreviousIsFromStart is true)//Check if we found the opposite End
|
if (neighborNode.PreviousIsFromStart is true)//Check if we found the opposite End
|
||||||
@ -75,7 +97,7 @@ namespace astar
|
|||||||
neighborNode.PreviousNodeId = currentNodeEndId;
|
neighborNode.PreviousNodeId = currentNodeEndId;
|
||||||
neighborNode.Distance = distance;
|
neighborNode.Distance = distance;
|
||||||
neighborNode.PreviousIsFromStart = false;
|
neighborNode.PreviousIsFromStart = false;
|
||||||
toVisitEnd.Enqueue(neighborId, NodeUtils.DistanceBetween(neighborNode, startNode.Value));
|
toVisitEnd.Enqueue(neighborId, NodeUtils.DistanceBetween(neighborNode, startNode.Value) / speed);
|
||||||
}
|
}
|
||||||
logger?.LogTrace($"Neighbor {neighborId} {neighborNode}");
|
logger?.LogTrace($"Neighbor {neighborId} {neighborNode}");
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Graph;
|
using astar.PathingHelper;
|
||||||
|
using Graph;
|
||||||
|
|
||||||
namespace astar;
|
namespace astar;
|
||||||
|
|
||||||
@ -49,9 +50,9 @@ public class Graph
|
|||||||
return Ways.ContainsKey(wayId);
|
return Ways.ContainsKey(wayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyValuePair<ulong, Node> ClosestNodeToCoordinates(float lat, float lon)
|
public KeyValuePair<ulong, Node> ClosestNodeToCoordinates(float lat, float lon, bool car = true)
|
||||||
{
|
{
|
||||||
return Nodes.MinBy(n => n.Value.DistanceTo(lat, lon));
|
return Nodes.Where(n => n.Value.Neighbors.Values.Any(wayId => SpeedHelper.GetSpeed(Ways[wayId], car) > 0)).MinBy(n => n.Value.DistanceTo(lat, lon));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
36
astar/PathingHelper/HighwayType.cs
Normal file
36
astar/PathingHelper/HighwayType.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
namespace astar.PathingHelper;
|
||||||
|
|
||||||
|
public enum HighwayType
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
motorway,
|
||||||
|
trunk,
|
||||||
|
primary,
|
||||||
|
secondary,
|
||||||
|
tertiary,
|
||||||
|
unclassified,
|
||||||
|
residential,
|
||||||
|
motorway_link,
|
||||||
|
trunk_link,
|
||||||
|
primary_link,
|
||||||
|
secondary_link,
|
||||||
|
tertiary_link,
|
||||||
|
living_street,
|
||||||
|
service,
|
||||||
|
pedestrian,
|
||||||
|
track,
|
||||||
|
bus_guideway,
|
||||||
|
escape,
|
||||||
|
raceway,
|
||||||
|
road,
|
||||||
|
busway,
|
||||||
|
footway,
|
||||||
|
bridleway,
|
||||||
|
steps,
|
||||||
|
corridor,
|
||||||
|
path,
|
||||||
|
cycleway,
|
||||||
|
construction
|
||||||
|
}
|
79
astar/PathingHelper/SpeedHelper.cs
Normal file
79
astar/PathingHelper/SpeedHelper.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
using Graph;
|
||||||
|
|
||||||
|
namespace astar.PathingHelper;
|
||||||
|
|
||||||
|
internal static class SpeedHelper
|
||||||
|
{
|
||||||
|
public static byte GetSpeed(Way way, bool car = true)
|
||||||
|
{
|
||||||
|
if (!way.Tags.TryGetValue("highway", out string? highwayTypeStr))
|
||||||
|
return 0;
|
||||||
|
if (!Enum.TryParse(highwayTypeStr, out HighwayType highwayType))
|
||||||
|
return 0;
|
||||||
|
return car ? SpeedCar[highwayType] : SpeedPedestrian[highwayType];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<HighwayType, byte> SpeedPedestrian = new() {
|
||||||
|
{ HighwayType.NONE, 0 },
|
||||||
|
{ HighwayType.motorway, 0 },
|
||||||
|
{ HighwayType.trunk, 0 },
|
||||||
|
{ HighwayType.primary, 0 },
|
||||||
|
{ HighwayType.secondary, 0 },
|
||||||
|
{ HighwayType.tertiary, 0 },
|
||||||
|
{ HighwayType.unclassified, 1 },
|
||||||
|
{ HighwayType.residential, 3 },
|
||||||
|
{ HighwayType.motorway_link, 0 },
|
||||||
|
{ HighwayType.trunk_link, 0 },
|
||||||
|
{ HighwayType.primary_link, 0 },
|
||||||
|
{ HighwayType.secondary_link, 0 },
|
||||||
|
{ HighwayType.tertiary_link, 0 },
|
||||||
|
{ HighwayType.living_street, 5 },
|
||||||
|
{ HighwayType.service, 2 },
|
||||||
|
{ HighwayType.pedestrian, 5 },
|
||||||
|
{ HighwayType.track, 0 },
|
||||||
|
{ HighwayType.bus_guideway, 0 },
|
||||||
|
{ HighwayType.escape, 0 },
|
||||||
|
{ HighwayType.raceway, 0 },
|
||||||
|
{ HighwayType.road, 3 },
|
||||||
|
{ HighwayType.busway, 0 },
|
||||||
|
{ HighwayType.footway, 4 },
|
||||||
|
{ HighwayType.bridleway, 1 },
|
||||||
|
{ HighwayType.steps, 2 },
|
||||||
|
{ HighwayType.corridor, 3 },
|
||||||
|
{ HighwayType.path, 4 },
|
||||||
|
{ HighwayType.cycleway, 2 },
|
||||||
|
{ HighwayType.construction, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
private static Dictionary<HighwayType, byte> SpeedCar = new() {
|
||||||
|
{ HighwayType.NONE, 0 },
|
||||||
|
{ HighwayType.motorway, 110 },
|
||||||
|
{ HighwayType.trunk, 100 },
|
||||||
|
{ HighwayType.primary, 80 },
|
||||||
|
{ HighwayType.secondary, 80 },
|
||||||
|
{ HighwayType.tertiary, 70 },
|
||||||
|
{ HighwayType.unclassified, 20 },
|
||||||
|
{ HighwayType.residential, 10 },
|
||||||
|
{ HighwayType.motorway_link, 50 },
|
||||||
|
{ HighwayType.trunk_link, 50 },
|
||||||
|
{ HighwayType.primary_link, 30 },
|
||||||
|
{ HighwayType.secondary_link, 25 },
|
||||||
|
{ HighwayType.tertiary_link, 25 },
|
||||||
|
{ HighwayType.living_street, 10 },
|
||||||
|
{ HighwayType.service, 0 },
|
||||||
|
{ HighwayType.pedestrian, 0 },
|
||||||
|
{ HighwayType.track, 0 },
|
||||||
|
{ HighwayType.bus_guideway, 0 },
|
||||||
|
{ HighwayType.escape, 0 },
|
||||||
|
{ HighwayType.raceway, 0 },
|
||||||
|
{ HighwayType.road, 25 },
|
||||||
|
{ HighwayType.busway, 0 },
|
||||||
|
{ HighwayType.footway, 0 },
|
||||||
|
{ HighwayType.bridleway, 0 },
|
||||||
|
{ HighwayType.steps, 0 },
|
||||||
|
{ HighwayType.corridor, 0 },
|
||||||
|
{ HighwayType.path, 0 },
|
||||||
|
{ HighwayType.cycleway, 0 },
|
||||||
|
{ HighwayType.construction, 0 }
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user