Compare commits
No commits in common. "c238a9eed345f1f0551846425ba84ce6b850efad" and "0f53ae579ccf961986f50e7f52188b487a794cea" have entirely different histories.
c238a9eed3
...
0f53ae579c
@ -1,4 +1,3 @@
|
|||||||
using System.Text;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using OSMDatastructure;
|
using OSMDatastructure;
|
||||||
using OSMDatastructure.Graph;
|
using OSMDatastructure.Graph;
|
||||||
@ -15,6 +14,8 @@ builder.Services.AddSwaggerGen();
|
|||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.MapGet("/getRouteDistance", (float latStart, float lonStart, float latEnd, float lonEnd) =>
|
app.MapGet("/getRouteDistance", (float latStart, float lonStart, float latEnd, float lonEnd) =>
|
||||||
{
|
{
|
||||||
DateTime startCalc = DateTime.Now;
|
DateTime startCalc = DateTime.Now;
|
||||||
|
@ -98,20 +98,19 @@ public class Tag
|
|||||||
|
|
||||||
public static readonly Dictionary<WayType, byte> defaultSpeedCar = new() {
|
public static readonly Dictionary<WayType, byte> defaultSpeedCar = new() {
|
||||||
{ WayType.NONE, 0 },
|
{ WayType.NONE, 0 },
|
||||||
{ WayType.motorway, 100 },
|
{ WayType.motorway, 110 },
|
||||||
{ WayType.motorroad, 90 },
|
{ WayType.trunk, 100 },
|
||||||
{ WayType.trunk, 85 },
|
{ WayType.primary, 80 },
|
||||||
{ WayType.primary, 65 },
|
{ WayType.secondary, 80 },
|
||||||
{ WayType.secondary, 60 },
|
{ WayType.tertiary, 70 },
|
||||||
{ WayType.tertiary, 50 },
|
{ WayType.unclassified, 20 },
|
||||||
{ WayType.unclassified, 15 },
|
|
||||||
{ WayType.residential, 10 },
|
{ WayType.residential, 10 },
|
||||||
{ WayType.motorway_link, 60 },
|
{ WayType.motorway_link, 50 },
|
||||||
{ WayType.trunk_link, 50 },
|
{ WayType.trunk_link, 50 },
|
||||||
{ WayType.primary_link, 50 },
|
{ WayType.primary_link, 30 },
|
||||||
{ WayType.secondary_link, 50 },
|
{ WayType.secondary_link, 25 },
|
||||||
{ WayType.tertiary_link, 30 },
|
{ WayType.tertiary_link, 25 },
|
||||||
{ WayType.living_street, 10 },
|
{ WayType.living_street, 5 },
|
||||||
{ WayType.service, 1 },
|
{ WayType.service, 1 },
|
||||||
{ WayType.pedestrian, 0 },
|
{ WayType.pedestrian, 0 },
|
||||||
{ WayType.track, 15 },
|
{ WayType.track, 15 },
|
||||||
@ -161,7 +160,7 @@ public class Tag
|
|||||||
{ WayType.construction, 0 }
|
{ WayType.construction, 0 }
|
||||||
};
|
};
|
||||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||||
public enum WayType : byte { NONE, motorway, motorroad, 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 }
|
public enum WayType : byte { 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 }
|
||||||
// ReSharper restore InconsistentNaming
|
// ReSharper restore InconsistentNaming
|
||||||
|
|
||||||
public enum SpeedType { pedestrian, car, any }
|
public enum SpeedType { pedestrian, car, any }
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using OSMDatastructure;
|
using OSMDatastructure;
|
||||||
using OSMDatastructure.Graph;
|
using OSMDatastructure.Graph;
|
||||||
using WayType = OSMDatastructure.Tag.WayType;
|
|
||||||
|
|
||||||
namespace Pathfinding;
|
namespace Pathfinding;
|
||||||
|
|
||||||
@ -26,112 +25,10 @@ public static partial class Pathfinder
|
|||||||
if (node2 is null)
|
if (node2 is null)
|
||||||
return double.MaxValue;
|
return double.MaxValue;
|
||||||
double distance = Utils.DistanceBetween(node1, node2);
|
double distance = Utils.DistanceBetween(node1, node2);
|
||||||
byte speed = regionManager.GetSpeedForEdge(node1, edge.wayId, vehicle);
|
double speed = regionManager.GetSpeedForEdge(node1, edge.wayId, vehicle);
|
||||||
return speed is 0 ? double.MaxValue : distance / speed;
|
if (speed is 0)
|
||||||
}
|
|
||||||
|
|
||||||
private static double GetPriority(OsmNode current, OsmNode? previous, OsmEdge edge, Tag.SpeedType vehicle, RegionManager regionManager)
|
|
||||||
{
|
|
||||||
if (vehicle == Tag.SpeedType.any)
|
|
||||||
return 1;
|
|
||||||
const double roadPriorityFactor = 1;
|
|
||||||
const double junctionFactor = 2;
|
|
||||||
const double wayChangeFactor = 2;
|
|
||||||
Region r = regionManager.GetRegion(current.coordinates)!;
|
|
||||||
|
|
||||||
double roadPriority = GetPriorityVehicleRoad(edge, vehicle, r) * 0.1 * roadPriorityFactor;
|
|
||||||
double roadSpeed = regionManager.GetSpeedForEdge(current, edge.wayId, vehicle);
|
|
||||||
|
|
||||||
if(vehicle == Tag.SpeedType.pedestrian)
|
|
||||||
return (current.directDistanceToGoal / roadSpeed) * roadPriority;
|
|
||||||
|
|
||||||
ulong previousWayId = UInt64.MaxValue;
|
|
||||||
if (previous?.edges is not null)
|
|
||||||
{
|
|
||||||
foreach (OsmEdge e in previous.edges)
|
|
||||||
if (e.neighborId.Equals(current.nodeId))
|
|
||||||
{
|
|
||||||
previousWayId = e.wayId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double junctionPriority = (current.edges.Count > 2 ? 1 : 0) * junctionFactor;
|
|
||||||
double wayChange = (previousWayId != edge.wayId ? 1 : 0) * wayChangeFactor;
|
|
||||||
|
|
||||||
if(vehicle == Tag.SpeedType.car)
|
|
||||||
return (current.directDistanceToGoal / roadSpeed) * roadPriority * ((junctionPriority + wayChange) / 2);
|
|
||||||
|
|
||||||
return double.MaxValue;
|
return double.MaxValue;
|
||||||
}
|
return distance / speed;
|
||||||
|
|
||||||
private static double GetPriorityVehicleRoad(OsmEdge edge, Tag.SpeedType vehicle, Region region)
|
|
||||||
{
|
|
||||||
if (vehicle == Tag.SpeedType.any)
|
|
||||||
return 1;
|
|
||||||
WayType? wayType = (WayType?)region.tagManager.GetTag(edge.wayId, Tag.TagType.highway);
|
|
||||||
if(wayType is null)
|
|
||||||
return double.MaxValue;
|
|
||||||
if (vehicle == Tag.SpeedType.car)
|
|
||||||
{
|
|
||||||
switch (wayType)
|
|
||||||
{
|
|
||||||
case WayType.motorway:
|
|
||||||
case WayType.motorway_link:
|
|
||||||
case WayType.motorroad:
|
|
||||||
case WayType.trunk:
|
|
||||||
case WayType.trunk_link:
|
|
||||||
case WayType.primary:
|
|
||||||
case WayType.primary_link:
|
|
||||||
return 1;
|
|
||||||
case WayType.secondary:
|
|
||||||
case WayType.secondary_link:
|
|
||||||
return 2;
|
|
||||||
case WayType.tertiary:
|
|
||||||
case WayType.tertiary_link:
|
|
||||||
return 3;
|
|
||||||
case WayType.unclassified:
|
|
||||||
case WayType.residential:
|
|
||||||
case WayType.road:
|
|
||||||
return 4;
|
|
||||||
case WayType.living_street:
|
|
||||||
case WayType.service:
|
|
||||||
case WayType.track:
|
|
||||||
return 5;
|
|
||||||
default:
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vehicle == Tag.SpeedType.pedestrian)
|
|
||||||
{
|
|
||||||
switch (wayType)
|
|
||||||
{
|
|
||||||
case WayType.pedestrian:
|
|
||||||
case WayType.corridor:
|
|
||||||
case WayType.footway:
|
|
||||||
case WayType.path:
|
|
||||||
case WayType.steps:
|
|
||||||
case WayType.residential:
|
|
||||||
case WayType.living_street:
|
|
||||||
return 1;
|
|
||||||
case WayType.service:
|
|
||||||
case WayType.cycleway:
|
|
||||||
case WayType.bridleway:
|
|
||||||
case WayType.road:
|
|
||||||
case WayType.track:
|
|
||||||
case WayType.unclassified:
|
|
||||||
return 2;
|
|
||||||
case WayType.tertiary:
|
|
||||||
case WayType.tertiary_link:
|
|
||||||
case WayType.escape:
|
|
||||||
return 5;
|
|
||||||
default:
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 100;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<PathNode> GetRouteFromCalc(OsmNode goalNode, RegionManager regionManager)
|
private static List<PathNode> GetRouteFromCalc(OsmNode goalNode, RegionManager regionManager)
|
||||||
|
@ -20,25 +20,25 @@ public static partial class Pathfinder
|
|||||||
|
|
||||||
while (toVisit.Count > 0)
|
while (toVisit.Count > 0)
|
||||||
{
|
{
|
||||||
OsmNode currentNode = toVisit.Dequeue();
|
OsmNode closestNodeToGoal = toVisit.Dequeue();
|
||||||
|
|
||||||
foreach (OsmEdge edge in currentNode.edges)
|
foreach (OsmEdge edge in closestNodeToGoal.edges)
|
||||||
{
|
{
|
||||||
OsmNode? neighbor = regionManager.GetNode(edge.neighborId, edge.neighborRegion);
|
OsmNode? neighbor = regionManager.GetNode(edge.neighborId, edge.neighborRegion);
|
||||||
if (neighbor is not null)
|
if (neighbor is not null)
|
||||||
{
|
{
|
||||||
if (Math.Abs(neighbor.directDistanceToGoal - double.MaxValue) < 1)
|
double newPotentialLength = closestNodeToGoal.currentPathLength + Utils.DistanceBetween(closestNodeToGoal, neighbor);
|
||||||
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
|
|
||||||
double newPotentialLength = currentNode.currentPathLength + Utils.DistanceBetween(currentNode, neighbor);
|
|
||||||
if (newPotentialLength < neighbor.currentPathLength)
|
if (newPotentialLength < neighbor.currentPathLength)
|
||||||
{
|
{
|
||||||
neighbor.previousPathNode = currentNode;
|
neighbor.previousPathNode = closestNodeToGoal;
|
||||||
neighbor.currentPathLength = newPotentialLength;
|
neighbor.currentPathLength = newPotentialLength;
|
||||||
|
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
|
||||||
|
|
||||||
if (neighbor.Equals(goalNode))
|
if (neighbor.Equals(goalNode))
|
||||||
return GetRouteFromCalc(goalNode, regionManager);
|
{
|
||||||
//stop = true;
|
stop = true;
|
||||||
if (!toVisit.UnorderedItems.Any(item => item.Element.Equals(neighbor)) && !stop)
|
}
|
||||||
|
else if(!stop)
|
||||||
{
|
{
|
||||||
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
|
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
|
||||||
}
|
}
|
||||||
|
@ -21,41 +21,31 @@ public static partial class Pathfinder
|
|||||||
|
|
||||||
while (toVisit.Count > 0)
|
while (toVisit.Count > 0)
|
||||||
{
|
{
|
||||||
OsmNode currentNode = toVisit.Dequeue();
|
OsmNode closestNodeToGoal = toVisit.Dequeue();
|
||||||
|
|
||||||
foreach (OsmEdge edge in currentNode.edges.Where(
|
foreach (OsmEdge edge in closestNodeToGoal.edges.Where(
|
||||||
edge => regionManager.TestValidConnectionForType(currentNode, edge, vehicle)))
|
edge => regionManager.TestValidConnectionForType(closestNodeToGoal, edge, vehicle)))
|
||||||
{
|
{
|
||||||
OsmNode? neighbor = regionManager.GetNode(edge.neighborId, edge.neighborRegion);
|
OsmNode? neighbor = regionManager.GetNode(edge.neighborId, edge.neighborRegion);
|
||||||
if (neighbor is not null)
|
if (neighbor is not null)
|
||||||
{
|
{
|
||||||
if (Math.Abs(neighbor.directDistanceToGoal - double.MaxValue) < 1)
|
double newPotentialWeight = closestNodeToGoal.currentPathWeight +
|
||||||
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
|
EdgeWeight(closestNodeToGoal, edge, vehicle, regionManager);
|
||||||
|
|
||||||
double newPotentialWeight = currentNode.currentPathWeight +
|
|
||||||
EdgeWeight(currentNode, edge, vehicle, regionManager);
|
|
||||||
|
|
||||||
if (newPotentialWeight < neighbor.currentPathWeight)
|
if (newPotentialWeight < neighbor.currentPathWeight)
|
||||||
{
|
{
|
||||||
neighbor.previousPathNode = currentNode;
|
neighbor.previousPathNode = closestNodeToGoal;
|
||||||
|
neighbor.currentPathLength = closestNodeToGoal.currentPathLength + Utils.DistanceBetween(closestNodeToGoal, neighbor);
|
||||||
neighbor.currentPathWeight = newPotentialWeight;
|
neighbor.currentPathWeight = newPotentialWeight;
|
||||||
|
neighbor.directDistanceToGoal = Utils.DistanceBetween(neighbor, goalNode);
|
||||||
|
|
||||||
if (neighbor.Equals(goalNode))
|
if (neighbor.Equals(goalNode))
|
||||||
{
|
{
|
||||||
currentNode = neighbor;
|
stop = true;
|
||||||
currentNode.currentPathLength = 0;
|
}
|
||||||
while (currentNode != startAndEndNode.Item1 && currentNode.previousPathNode is not null)
|
else if(!stop)
|
||||||
{
|
{
|
||||||
currentNode.previousPathNode.currentPathLength = currentNode.currentPathLength +
|
toVisit.Enqueue(neighbor, neighbor.directDistanceToGoal);
|
||||||
Utils.DistanceBetween(currentNode, currentNode.previousPathNode);
|
|
||||||
currentNode = currentNode.previousPathNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetRouteFromCalc(goalNode, regionManager);
|
|
||||||
}
|
|
||||||
//stop = true;
|
|
||||||
if (!toVisit.UnorderedItems.Any(item => item.Element.Equals(neighbor)))
|
|
||||||
toVisit.Enqueue(neighbor, GetPriority(currentNode, currentNode.previousPathNode, edge, vehicle, regionManager));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,10 @@ namespace Pathfinding
|
|||||||
{
|
{
|
||||||
if (type == Tag.SpeedType.any)
|
if (type == Tag.SpeedType.any)
|
||||||
return true;
|
return true;
|
||||||
byte speed = GetSpeedForEdge(node1, edge.wayId, type);
|
double speed = GetSpeedForEdge(node1, edge.wayId, type);
|
||||||
return (speed is not 0);
|
if (speed != 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Tag.SpeedType vehicle)
|
public OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Tag.SpeedType vehicle)
|
||||||
@ -95,7 +97,7 @@ namespace Pathfinding
|
|||||||
hasConnectionUsingVehicle = false;
|
hasConnectionUsingVehicle = false;
|
||||||
foreach (OsmEdge edge in node.edges)
|
foreach (OsmEdge edge in node.edges)
|
||||||
{
|
{
|
||||||
byte speed = GetSpeedForEdge(node, edge.wayId, vehicle);
|
double speed = GetSpeedForEdge(node, edge.wayId, vehicle);
|
||||||
if (speed != 0)
|
if (speed != 0)
|
||||||
hasConnectionUsingVehicle = true;
|
hasConnectionUsingVehicle = true;
|
||||||
}
|
}
|
||||||
@ -112,20 +114,25 @@ namespace Pathfinding
|
|||||||
return closest;
|
return closest;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte GetSpeedForEdge(OsmNode node1, ulong wayId, Tag.SpeedType vehicle)
|
public double GetSpeedForEdge(OsmNode node1, ulong wayId, Tag.SpeedType vehicle)
|
||||||
{
|
{
|
||||||
TagManager tags = GetRegion(node1.coordinates)!.tagManager;
|
TagManager tags = GetRegion(node1.coordinates)!.tagManager;
|
||||||
Tag.WayType wayType = (Tag.WayType)tags.GetTag(wayId, Tag.TagType.highway)!;
|
Tag.WayType wayType = (Tag.WayType)tags.GetTag(wayId, Tag.TagType.highway)!;
|
||||||
byte speed = 0;
|
|
||||||
switch (vehicle)
|
switch (vehicle)
|
||||||
{
|
{
|
||||||
case Tag.SpeedType.pedestrian:
|
case Tag.SpeedType.pedestrian:
|
||||||
speed = Tag.defaultSpeedPedestrian[wayType];
|
byte speed = Tag.defaultSpeedPedestrian[wayType];
|
||||||
return speed is not 0 ? speed : (byte)0;
|
if (speed is not 0)
|
||||||
|
return speed;
|
||||||
|
return 0;
|
||||||
case Tag.SpeedType.car:
|
case Tag.SpeedType.car:
|
||||||
byte? maxSpeed = (byte?)tags.GetTag(wayId, Tag.TagType.maxspeed);
|
byte? maxSpeed = (byte?)tags.GetTag(wayId, Tag.TagType.maxspeed);
|
||||||
speed = Tag.defaultSpeedCar[wayType];
|
if (maxSpeed is not null)
|
||||||
return maxSpeed < speed ? (byte)maxSpeed : speed;
|
return (double)maxSpeed;
|
||||||
|
maxSpeed = Tag.defaultSpeedCar[wayType];
|
||||||
|
if(maxSpeed is not 0)
|
||||||
|
return (byte)maxSpeed;
|
||||||
|
return 0;
|
||||||
case Tag.SpeedType.any:
|
case Tag.SpeedType.any:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user