OSMServer/Pathfinding/RegionManager.cs

132 lines
4.4 KiB
C#
Raw Normal View History

2023-04-09 16:22:22 +02:00
using System.Text.Json;
2023-02-03 23:35:22 +01:00
using OSMDatastructure;
using OSMDatastructure.Graph;
2023-02-03 23:35:22 +01:00
2023-04-09 16:24:43 +02:00
namespace Pathfinding
2023-02-03 23:35:22 +01:00
{
public class RegionManager
{
private string workingDirectory { get; }
private readonly Dictionary<ulong, Region> _regions = new();
2023-02-03 23:35:22 +01:00
public RegionManager(string workingDirectory)
{
this.workingDirectory = workingDirectory;
}
2023-04-01 14:43:05 +02:00
public Region? GetRegion(Coordinates coordinates)
{
return GetRegion(Coordinates.GetRegionHashCode(coordinates));
}
public Region? GetRegion(ulong id)
{
if(_regions.TryGetValue(id, out Region? value))
return value;
2023-04-20 23:02:38 +02:00
Region? loadedRegion = RegionFromId(id);
if(loadedRegion is not null)
_regions.Add(loadedRegion!.regionHash, value: loadedRegion);
return loadedRegion;
2023-02-03 23:35:22 +01:00
}
public Region[] GetAllRegions()
{
2023-04-20 23:02:38 +02:00
return _regions.Values.ToArray();
2023-02-03 23:35:22 +01:00
}
2023-04-01 14:43:05 +02:00
2023-04-09 16:22:22 +02:00
private Region? RegionFromFile(string filePath)
{
2023-04-20 23:02:38 +02:00
if (!File.Exists(filePath))
return null;
FileStream regionFile = new (filePath, FileMode.Open);
Region retRegion = JsonSerializer.Deserialize<Region>(regionFile, Region.serializerOptions)!;
regionFile.Dispose();
2023-04-09 16:22:22 +02:00
return retRegion;
}
private Region? RegionFromId(ulong regionId)
{
string filePath = Path.Join(workingDirectory, $"{regionId}.region");
return RegionFromFile(filePath);
}
2023-04-09 16:32:02 +02:00
public OsmNode? GetNode(ulong nodeId, ulong regionId)
{
Region? r = GetRegion(regionId);
return r?.GetNode(nodeId);
}
public bool TestValidConnectionForType(OsmNode node1, OsmNode node2, Tag.SpeedType type)
{
foreach (OsmEdge edge in node1.edges)
{
if (edge.neighborId.Equals(node2.nodeId))
return TestValidConnectionForType(node1, edge, type);
}
return false;
}
public bool TestValidConnectionForType(OsmNode node1, OsmEdge edge, Tag.SpeedType type)
{
if (type == Tag.SpeedType.any)
return true;
2023-04-09 19:22:34 +02:00
byte speed = GetSpeedForEdge(node1, edge.wayId, type);
return (speed is not 0);
}
public OsmNode? ClosestNodeToCoordinates(Coordinates coordinates, Tag.SpeedType vehicle)
{
OsmNode? closest = null;
double distance = double.MaxValue;
Region? region = GetRegion(coordinates);
if (region is null)
return null;
foreach (OsmNode node in region.nodes)
{
bool hasConnectionUsingVehicle = true;
if (vehicle is not Tag.SpeedType.any)
{
hasConnectionUsingVehicle = false;
foreach (OsmEdge edge in node.edges)
{
2023-04-09 21:02:32 +02:00
if (TestValidConnectionForType(node, edge, vehicle))
hasConnectionUsingVehicle = true;
}
}
double nodeDistance = Utils.DistanceBetween(node, coordinates);
2023-04-09 21:02:32 +02:00
if (hasConnectionUsingVehicle && nodeDistance < distance)
{
closest = node;
distance = nodeDistance;
}
}
return closest;
}
2023-04-09 19:22:34 +02:00
public byte GetSpeedForEdge(OsmNode node1, ulong wayId, Tag.SpeedType vehicle)
{
TagManager tags = GetRegion(node1.coordinates)!.tagManager;
Tag.WayType wayType = (Tag.WayType)tags.GetTag(wayId, Tag.TagType.highway)!;
2023-04-09 19:22:34 +02:00
byte speed = 0;
switch (vehicle)
{
case Tag.SpeedType.pedestrian:
2023-04-09 19:22:34 +02:00
speed = Tag.defaultSpeedPedestrian[wayType];
2023-04-09 21:02:32 +02:00
return speed;
case Tag.SpeedType.car:
byte? maxSpeed = (byte?)tags.GetTag(wayId, Tag.TagType.maxspeed);
2023-04-09 19:22:34 +02:00
speed = Tag.defaultSpeedCar[wayType];
return maxSpeed < speed ? (byte)maxSpeed : speed;
case Tag.SpeedType.any:
return 1;
default:
return 0;
}
}
2023-02-03 23:35:22 +01:00
}
}