Compare commits

...

16 Commits

Author SHA1 Message Date
95c0088b73 Added function to mass-test the heuristic variables. 2023-04-21 13:49:48 +02:00
cd3905915b Cleanup 2023-04-21 13:43:50 +02:00
dd37430761 Moved RoadPriority Function to RegionManager 2023-04-21 13:41:01 +02:00
42e915ee05 Added distance and duration to PathResult. 2023-04-21 11:40:26 +02:00
7d769a064f Parallel reading of regionfiles. 2023-04-21 11:40:15 +02:00
93a448e189 Made Conversion-methods public 2023-04-21 11:01:50 +02:00
750ba5c624 Fixed angle calculation 2023-04-21 11:01:31 +02:00
1facca84ba Prevent multiple processes from reading same file. 2023-04-21 11:01:05 +02:00
8b7cfcbd77 Method for mass-testing all factors. 2023-04-21 00:43:58 +02:00
28ab2b2bb8 Added angleFactor variable 2023-04-21 00:43:38 +02:00
7201b9c993 Add turn-angle to Weight calculation.
For that added Vector-class.
Highways now have much higher priority.
2023-04-21 00:42:21 +02:00
d1f311a76b Cleanup 2023-04-21 00:41:18 +02:00
2b252e2b06 Cleanup of unnecessary code 2023-04-20 23:02:38 +02:00
d456275fc1 private field naming _cameFromDict 2023-04-20 22:58:50 +02:00
2bd6c5d9c4 Replaced local vars with fields. 2023-04-20 22:58:27 +02:00
90a09e84c5 Removed/Replaced unnecessary checks in AStar. 2023-04-20 22:53:23 +02:00
12 changed files with 295 additions and 165 deletions

View File

@ -1,4 +1,3 @@
using System.Text.Json.Serialization;
using OSMDatastructure; using OSMDatastructure;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;
using Pathfinding; using Pathfinding;
@ -14,11 +13,11 @@ builder.Services.AddSwaggerGen();
var app = builder.Build(); var app = builder.Build();
app.MapGet("/getRoute", (float latStart, float lonStart, float latEnd, float lonEnd, Tag.SpeedType vehicle, double stayOnSameRoadPriority, double useHigherLevelRoadsPriority, double useRoadsWithLessJunctionsPriority) => app.MapGet("/getRoute", (float latStart, float lonStart, float latEnd, float lonEnd, Tag.SpeedType vehicle, double stayOnSameRoadPriority, double useHigherLevelRoadsPriority, double useRoadsWithLessJunctionsPriority, double angleFactor) =>
{ {
Pathfinder result = new Pathfinder("D:/stuttgart-regbez-latest").AStar(new Coordinates(latStart, lonStart), Pathfinder result = new Pathfinder("D:/stuttgart-regbez-latest").AStar(new Coordinates(latStart, lonStart),
new Coordinates(latEnd, lonEnd), vehicle, useHigherLevelRoadsPriority, stayOnSameRoadPriority, new Coordinates(latEnd, lonEnd), vehicle, useHigherLevelRoadsPriority, stayOnSameRoadPriority,
useRoadsWithLessJunctionsPriority); useRoadsWithLessJunctionsPriority, angleFactor);
return result.pathResult; return result.pathResult;
} }
); );
@ -27,7 +26,7 @@ app.MapGet("/getShortestRoute", (float latStart, float lonStart, float latEnd, f
{ {
Pathfinder result = new Pathfinder("D:/stuttgart-regbez-latest").AStar(new Coordinates(latStart, lonStart), Pathfinder result = new Pathfinder("D:/stuttgart-regbez-latest").AStar(new Coordinates(latStart, lonStart),
new Coordinates(latEnd, lonEnd), Tag.SpeedType.any, 0, 0, new Coordinates(latEnd, lonEnd), Tag.SpeedType.any, 0, 0,
0); 0, 0);
return result.pathResult; return result.pathResult;
} }
); );

View File

@ -12,15 +12,15 @@ public class OsmNode
public OsmNode(ulong nodeId, float lat, float lon) public OsmNode(ulong nodeId, float lat, float lon)
{ {
this.nodeId = nodeId; this.nodeId = nodeId;
this.edges = new(); edges = new();
this.coordinates = new Coordinates(lat, lon); coordinates = new Coordinates(lat, lon);
} }
[JsonConstructor] [JsonConstructor]
public OsmNode(ulong nodeId, Coordinates coordinates) public OsmNode(ulong nodeId, Coordinates coordinates)
{ {
this.nodeId = nodeId; this.nodeId = nodeId;
this.edges = new(); edges = new();
this.coordinates = coordinates; this.coordinates = coordinates;
} }
@ -29,7 +29,8 @@ public class OsmNode
HashSet<OsmEdge> e = edges.Where(edge => edge.neighborId == n.nodeId).ToHashSet(); HashSet<OsmEdge> e = edges.Where(edge => edge.neighborId == n.nodeId).ToHashSet();
if (e.Count > 0) if (e.Count > 0)
return e.First(); return e.First();
else return null;
return null;
} }
public override bool Equals(object? obj) public override bool Equals(object? obj)

View File

@ -47,16 +47,12 @@ public class Region
public OsmNode? GetNode(ulong id) public OsmNode? GetNode(ulong id)
{ {
if (ContainsNode(id)) return ContainsNode(id) ? nodes.First(node => node.nodeId == id) : null;
return nodes.First(node => node.nodeId == id);
else return null;
} }
public OsmNode? GetNode(Coordinates coordinates) public OsmNode? GetNode(Coordinates coordinates)
{ {
if (ContainsNode(coordinates)) return ContainsNode(coordinates) ? nodes.First(node => node.coordinates.Equals(coordinates)) : null;
return nodes.First(node => node.coordinates.Equals(coordinates));
else return null;
} }
} }

View File

@ -1,5 +1,4 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using OSMDatastructure.Graph;
namespace OSMDatastructure; namespace OSMDatastructure;

View File

@ -65,12 +65,12 @@ namespace OSMDatastructure
return d; return d;
} }
private static double DegreesToRadians(double deg) public static double DegreesToRadians(double deg)
{ {
return deg * Math.PI / 180.0; return deg * Math.PI / 180.0;
} }
private static double RadiansToDegrees(double rad) public static double RadiansToDegrees(double rad)
{ {
return rad * 180.0 / Math.PI; return rad * 180.0 / Math.PI;
} }

View File

@ -1,4 +1,3 @@
using System.Diagnostics.Tracing;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using OSMDatastructure; using OSMDatastructure;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;

View File

@ -6,11 +6,15 @@ public class PathResult
{ {
[JsonInclude]public TimeSpan calcTime; [JsonInclude]public TimeSpan calcTime;
[JsonInclude]public List<PathNode> pathNodes; [JsonInclude]public List<PathNode> pathNodes;
[JsonInclude]public double distance;
[JsonInclude]public double weight;
[JsonConstructor] [JsonConstructor]
public PathResult(TimeSpan calcTime, List<PathNode> pathNodes) public PathResult(TimeSpan calcTime, List<PathNode> pathNodes, double distance, double weight)
{ {
this.calcTime = calcTime; this.calcTime = calcTime;
this.pathNodes = pathNodes; this.pathNodes = pathNodes;
this.distance = distance;
this.weight = weight;
} }
} }

View File

@ -2,11 +2,9 @@
using OSMDatastructure; using OSMDatastructure;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;
using static OSMDatastructure.Tag; using static OSMDatastructure.Tag;
using WayType = OSMDatastructure.Tag.WayType;
namespace Pathfinding; namespace Pathfinding;
//TODO check parameters for all functions and determine global fields
public class Pathfinder public class Pathfinder
{ {
@ -14,6 +12,8 @@ public class Pathfinder
public readonly string workingDir; public readonly string workingDir;
public PathResult? pathResult; public PathResult? pathResult;
public Dictionary<OsmNode, double>? gScore; public Dictionary<OsmNode, double>? gScore;
private Dictionary<OsmNode, OsmNode>? _cameFromDict;
private SpeedType _speedType;
public Pathfinder(string workingDirectory) public Pathfinder(string workingDirectory)
{ {
@ -25,30 +25,32 @@ public class Pathfinder
public Pathfinder AStar(Coordinates startCoordinates, Coordinates goalCoordinates, public Pathfinder AStar(Coordinates startCoordinates, Coordinates goalCoordinates,
SpeedType vehicle, double heuristicRoadLevelPriority, double heuristicSameRoadPriority, SpeedType vehicle, double heuristicRoadLevelPriority, double heuristicSameRoadPriority,
double heuristicFewJunctionsPriority) double heuristicFewJunctionsPriority, double angleWeightFactor)
{ {
DateTime startCalc = DateTime.Now; DateTime startCalc = DateTime.Now;
regionManager = new RegionManager(workingDir); regionManager = new RegionManager(workingDir);
OsmNode? startNode = regionManager.ClosestNodeToCoordinates(startCoordinates, vehicle); _speedType = vehicle;
OsmNode? goalNode = regionManager.ClosestNodeToCoordinates(goalCoordinates, vehicle); OsmNode? startNode = regionManager.ClosestNodeToCoordinates(startCoordinates, _speedType);
OsmNode? goalNode = regionManager.ClosestNodeToCoordinates(goalCoordinates, _speedType);
if (startNode is null || goalNode is null) if (startNode is null || goalNode is null)
{ {
pathResult = new(DateTime.Now - startCalc, new List<PathNode>()); pathResult = new(DateTime.Now - startCalc, new List<PathNode>(),0 ,0);
return this; return this;
} }
PriorityQueue<OsmNode, double> openSetfScore = new(); PriorityQueue<OsmNode, double> openSetfScore = new();
openSetfScore.Enqueue(startNode, 0); openSetfScore.Enqueue(startNode, 0);
Dictionary<OsmNode, OsmNode> cameFromDict = new();
gScore = new() { { startNode, 0 } }; gScore = new() { { startNode, 0 } };
_cameFromDict = new();
while (openSetfScore.Count > 0) while (openSetfScore.Count > 0)
{ {
OsmNode currentNode = openSetfScore.Dequeue(); OsmNode currentNode = openSetfScore.Dequeue();
if (currentNode.Equals(goalNode)) if (currentNode.Equals(goalNode))
{ {
Console.WriteLine("Path found."); TimeSpan calcTime = DateTime.Now - startCalc;
this.pathResult = GetPath(cameFromDict, goalNode, DateTime.Now - startCalc); pathResult = GetPath(goalNode, calcTime);
Console.WriteLine($"Path found. {calcTime} PathLength {pathResult.pathNodes.Count} VisitedNodes {gScore.Count} Distance {pathResult.distance} Duration {pathResult.weight}");
return this; return this;
} }
@ -58,20 +60,15 @@ public class Pathfinder
if (neighbor is not null) if (neighbor is not null)
{ {
double tentativeGScore = double tentativeGScore =
gScore[currentNode] + Weight(currentNode, neighbor, edge, vehicle); gScore[currentNode] + Weight(currentNode, neighbor, edge, angleWeightFactor);
gScore.TryAdd(neighbor, double.MaxValue); gScore.TryAdd(neighbor, double.MaxValue);
if (tentativeGScore < gScore[neighbor]) if (tentativeGScore < gScore[neighbor])
{ {
if (cameFromDict.ContainsKey(neighbor)) if(!_cameFromDict.TryAdd(neighbor, currentNode))
cameFromDict[neighbor] = currentNode; _cameFromDict[neighbor] = currentNode;
else gScore[neighbor] = tentativeGScore;
cameFromDict.Add(neighbor, currentNode); double h = Heuristic(currentNode, neighbor, goalNode, edge,
if (gScore.ContainsKey(neighbor)) heuristicRoadLevelPriority, heuristicFewJunctionsPriority, heuristicSameRoadPriority, angleWeightFactor);
gScore[neighbor] = tentativeGScore;
else
gScore.Add(neighbor, tentativeGScore);
double h = Heuristic(currentNode, neighbor, goalNode, edge, vehicle,
heuristicRoadLevelPriority, heuristicFewJunctionsPriority, heuristicSameRoadPriority);
//Console.WriteLine($"Queue: {openSetfScore.Count:00000} Current Distance: {Utils.DistanceBetween(currentNode, goalNode):000000.00} Visited: {cameFromDict.Count:00000} Current heuristic: {h:00000.00}"); //Console.WriteLine($"Queue: {openSetfScore.Count:00000} Current Distance: {Utils.DistanceBetween(currentNode, goalNode):000000.00} Visited: {cameFromDict.Count:00000} Current heuristic: {h:00000.00}");
openSetfScore.Enqueue(neighbor, tentativeGScore + h); openSetfScore.Enqueue(neighbor, tentativeGScore + h);
} }
@ -79,51 +76,37 @@ public class Pathfinder
} }
} }
pathResult = new(DateTime.Now - startCalc, new List<PathNode>()); pathResult = new(DateTime.Now - startCalc, new List<PathNode>(),0 ,0);
return this; return this;
} }
public void SaveResult(string path) private double Weight(OsmNode currentNode, OsmNode neighborNode, OsmEdge edge, double angleWeightFactor)
{ {
FileStream fs = new (path, FileMode.CreateNew); double distance = Utils.DistanceBetween(currentNode, neighborNode);
JsonSerializer.Serialize(fs, pathResult, JsonSerializerOptions.Default); double speed = regionManager.GetSpeedForEdge(currentNode, edge.wayId, _speedType);
fs.Dispose();
Console.WriteLine($"Saved result to {path}");
}
private PathResult GetPath(Dictionary<OsmNode, OsmNode> cameFromDict, OsmNode goalNode, TimeSpan calcFinished)
{
List<PathNode> path = new();
OsmNode currentNode = goalNode;
while (cameFromDict.ContainsKey(cameFromDict[currentNode]))
{
OsmEdge? currentEdge = cameFromDict[currentNode].edges.First(edge => edge.neighborId == currentNode.nodeId);
HashSet<Tag>? tags =
regionManager.GetRegion(currentNode.coordinates)!.tagManager.GetTagsForWayId(currentEdge.wayId);
PathNode? newNode = PathNode.FromOsmNode(currentNode, tags);
if(newNode is not null)
path.Add(newNode);
currentNode = cameFromDict[currentNode];
}
path.Reverse();
return new PathResult(calcFinished, path);
}
private double Weight(OsmNode fromNode, OsmNode neighborNode, OsmEdge edge, SpeedType vehicle)
{
double distance = Utils.DistanceBetween(fromNode, neighborNode);
double speed = regionManager.GetSpeedForEdge(fromNode, edge.wayId, vehicle);
//double prio = GetPriorityVehicleRoad(edge, vehicle, regionManager.GetRegion(fromNode.coordinates)!);
return distance / speed;
}
private double Heuristic(OsmNode fromNode, OsmNode neighborNode, OsmNode goalNode, OsmEdge edge, SpeedType vehicle, double roadPriorityFactor, double junctionFactor, double sameRoadFactor)
{
double roadPriority = GetPriorityVehicleRoad(edge, vehicle, regionManager.GetRegion(fromNode.coordinates)!) * roadPriorityFactor;
TagManager curTags = regionManager.GetRegion(fromNode.coordinates)!.tagManager; double angle = 1;
if (_cameFromDict!.ContainsKey(currentNode))
{
OsmNode previousNode = _cameFromDict[currentNode];
Vector v1 = new(previousNode, currentNode);
Vector v2 = new(currentNode, neighborNode);
double nodeAngle = v1.Angle(v2);
angle = ((180 - nodeAngle) / 180) * angleWeightFactor;
}
double prio = regionManager.GetPriorityForVehicle(_speedType,edge, currentNode);
return distance / (1 + speed + angle + prio);
}
private double Heuristic(OsmNode currentNode, OsmNode neighborNode, OsmNode goalNode, OsmEdge edge, double roadPriorityFactor, double junctionFactor, double sameRoadFactor, double nodeAngleFactor)
{
double roadPriority = regionManager.GetPriorityForVehicle(_speedType, edge, currentNode) * roadPriorityFactor;
if (roadPriority == 0)
return double.MaxValue;
double speed = regionManager.GetSpeedForEdge(currentNode, edge.wayId, _speedType) * 0.0003;
TagManager curTags = regionManager.GetRegion(currentNode.coordinates)!.tagManager;
TagManager nextTags = regionManager.GetRegion(neighborNode.coordinates)!.tagManager; TagManager nextTags = regionManager.GetRegion(neighborNode.coordinates)!.tagManager;
bool sameName = false; bool sameName = false;
@ -142,70 +125,82 @@ public class Pathfinder
double junctionCount = (neighborNode.edges.Count > 2 ? 0 : 1) * junctionFactor; double junctionCount = (neighborNode.edges.Count > 2 ? 0 : 1) * junctionFactor;
return Utils.DistanceBetween(neighborNode, goalNode) / (1 + roadPriority + sameRoadName + junctionCount); double angle = 0;
} if (_cameFromDict!.ContainsKey(currentNode))
private static double GetPriorityVehicleRoad(OsmEdge edge, SpeedType vehicle, Region region)
{
if (vehicle == SpeedType.any)
return 1;
WayType? wayType = (WayType?)region.tagManager.GetTag(edge.wayId, TagType.highway);
if(wayType is null)
return 0;
if (vehicle == SpeedType.car)
{ {
switch (wayType) OsmNode previousNode = _cameFromDict[currentNode];
{ Vector v1 = new(previousNode, currentNode);
case WayType.motorway: Vector v2 = new(currentNode, neighborNode);
case WayType.motorway_link: double nodeAngle = v1.Angle(v2);
case WayType.motorroad: angle = ((180 - nodeAngle) / 180) * nodeAngleFactor;
case WayType.trunk:
case WayType.trunk_link:
case WayType.primary:
case WayType.primary_link:
return 10;
case WayType.secondary:
case WayType.secondary_link:
return 7;
case WayType.tertiary:
case WayType.tertiary_link:
return 5;
case WayType.unclassified:
case WayType.residential:
case WayType.road:
case WayType.living_street:
return 2;
case WayType.service:
case WayType.track:
return 0.0001;
}
} }
if (vehicle == SpeedType.pedestrian) return Utils.DistanceBetween(neighborNode, goalNode) / (roadPriority + sameRoadName + junctionCount + angle);
}
public void SaveResult(string path)
{
FileStream fs = new (path, FileMode.CreateNew);
JsonSerializer.Serialize(fs, pathResult, JsonSerializerOptions.Default);
fs.Dispose();
Console.WriteLine($"Saved result to {path}");
}
private PathResult GetPath(OsmNode goalNode, TimeSpan calcFinished)
{
List<PathNode> path = new();
OsmNode currentNode = goalNode;
double retDistance = 0;
double weight = 0;
while (_cameFromDict!.ContainsKey(_cameFromDict[currentNode]))
{ {
switch (wayType) OsmEdge? currentEdge = _cameFromDict[currentNode].edges.FirstOrDefault(edge => edge.neighborId == currentNode.nodeId);
{ HashSet<Tag>? tags =
case WayType.pedestrian: regionManager.GetRegion(currentNode.coordinates)!.tagManager.GetTagsForWayId(currentEdge!.wayId);
case WayType.corridor: PathNode? newNode = PathNode.FromOsmNode(currentNode, tags);
case WayType.footway: if(newNode is not null)
case WayType.path: path.Add(newNode);
case WayType.steps:
case WayType.residential: double distance = Utils.DistanceBetween(currentNode, _cameFromDict[currentNode]);
case WayType.living_street: retDistance += distance;
return 10; weight += regionManager.GetSpeedForEdge(_cameFromDict[currentNode], currentEdge.wayId, _speedType);
case WayType.service:
case WayType.cycleway: currentNode = _cameFromDict[currentNode];
case WayType.bridleway:
case WayType.road:
case WayType.track:
case WayType.unclassified:
return 5;
case WayType.tertiary:
case WayType.tertiary_link:
case WayType.escape:
return 2;
}
} }
return 0.01; path.Reverse();
return new PathResult(calcFinished, path, retDistance, retDistance / (weight / path.Count));
}
private class Vector
{
public readonly float x, y;
public Vector(float x, float y)
{
this.x = x;
this.y = y;
}
public Vector(OsmNode n1, OsmNode n2)
{
this.x = n1.coordinates.longitude - n2.coordinates.longitude;
this.y = n1.coordinates.latitude - n2.coordinates.latitude;
}
public double Angle(Vector v2)
{
return Angle(this, v2);
}
public static double Angle(Vector v1, Vector v2)
{
double dotProd = v1.x * v2.x + v1.y * v2.y;
double v1L = Math.Sqrt(v1.x * v1.x + v1.y * v1.y);
double v2L = Math.Sqrt(v2.x * v2.x + v2.y * v2.y);
double ang = Math.Acos(dotProd / (v1L * v2L));
double angle = Utils.RadiansToDegrees(ang);
return angle;
}
} }
} }

View File

@ -1,6 +1,8 @@
using System.Text.Json; using System.Text.Json;
using OSMDatastructure; using OSMDatastructure;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;
using SpeedType = OSMDatastructure.Tag.SpeedType;
using WayType = OSMDatastructure.Tag.WayType;
namespace Pathfinding namespace Pathfinding
{ {
@ -23,29 +25,26 @@ namespace Pathfinding
{ {
if(_regions.TryGetValue(id, out Region? value)) if(_regions.TryGetValue(id, out Region? value))
return value; return value;
else
{ Region? loadedRegion = RegionFromId(id);
Region? loadedRegion = RegionFromId(id); if(loadedRegion is not null)
if(loadedRegion is not null) _regions.Add(loadedRegion!.regionHash, value: loadedRegion);
_regions.Add(loadedRegion!.regionHash, value: loadedRegion); return loadedRegion;
return loadedRegion;
}
} }
public Region[] GetAllRegions() public Region[] GetAllRegions()
{ {
return this._regions.Values.ToArray(); return _regions.Values.ToArray();
} }
private Region? RegionFromFile(string filePath) private Region? RegionFromFile(string filePath)
{ {
Region? retRegion = null; if (!File.Exists(filePath))
if (File.Exists(filePath)) return null;
{
FileStream regionFile = new FileStream(filePath, FileMode.Open); FileStream regionFile = new (filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
retRegion = JsonSerializer.Deserialize<Region>(regionFile, Region.serializerOptions)!; Region retRegion = JsonSerializer.Deserialize<Region>(regionFile, Region.serializerOptions)!;
regionFile.Dispose(); regionFile.Dispose();
}
return retRegion; return retRegion;
} }
@ -131,5 +130,69 @@ namespace Pathfinding
return 0; return 0;
} }
} }
public double GetPriorityForVehicle(SpeedType speedType, OsmEdge edge, OsmNode node)
{
if (speedType == SpeedType.any)
return 1;
Region region = GetRegion(node.coordinates)!;
WayType? wayType = (WayType?)region.tagManager.GetTag(edge.wayId, Tag.TagType.highway);
if(wayType is null)
return 0;
if (speedType == SpeedType.car)
{
switch (wayType)
{
case WayType.motorway:
case WayType.motorway_link:
case WayType.motorroad:
return 17;
case WayType.trunk:
case WayType.trunk_link:
case WayType.primary:
case WayType.primary_link:
return 10;
case WayType.secondary:
case WayType.secondary_link:
return 7;
case WayType.tertiary:
case WayType.tertiary_link:
return 5;
case WayType.unclassified:
case WayType.residential:
case WayType.road:
case WayType.living_street:
return 2;
}
}
if (speedType == 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 10;
case WayType.service:
case WayType.cycleway:
case WayType.bridleway:
case WayType.road:
case WayType.track:
case WayType.unclassified:
return 5;
case WayType.tertiary:
case WayType.tertiary_link:
case WayType.escape:
return 2;
}
}
return 0;
}
} }
} }

View File

@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Text.Json;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;
using Pathfinding; using Pathfinding;
@ -45,7 +44,7 @@ public static class Renderer
[SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")] [SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")]
public static ValueTuple<Image, Bounds> DrawArea(RegionManager rm) public static ValueTuple<Image, Bounds> DrawArea(RegionManager rm)
{ {
HashSet<OsmNode> nodes = new HashSet<OsmNode>(); HashSet<OsmNode> nodes = new();
foreach (OSMDatastructure.Region r in rm.GetAllRegions()) foreach (OSMDatastructure.Region r in rm.GetAllRegions())
nodes = nodes.Concat(r.nodes).ToHashSet(); nodes = nodes.Concat(r.nodes).ToHashSet();
@ -79,7 +78,7 @@ public static class Renderer
OsmNode nNode = rm.GetNode(edge.neighborId, edge.neighborRegion)!; OsmNode nNode = rm.GetNode(edge.neighborId, edge.neighborRegion)!;
Coordinates c2 = nNode.coordinates; Coordinates c2 = nNode.coordinates;
Pen p = new Pen(GradientPick(0, start, center, end), PenThickness); Pen p = new(GradientPick(0, start, center, end), PenThickness);
float x1 = (c1.longitude - minLon) * scaleFactor; float x1 = (c1.longitude - minLon) * scaleFactor;
float y1 = (maxLat - c1.latitude) * scaleFactor; float y1 = (maxLat - c1.latitude) * scaleFactor;
float x2 = (c2.longitude - minLon) * scaleFactor; float x2 = (c2.longitude - minLon) * scaleFactor;

View File

@ -1,4 +1,3 @@
using System.Globalization;
using System.Text; using System.Text;
namespace Server; namespace Server;

View File

@ -4,6 +4,7 @@ using OSMDatastructure;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;
using Pathfinding; using Pathfinding;
using RenderPath; using RenderPath;
using Region = OSMDatastructure.Region;
namespace Server; namespace Server;
@ -24,18 +25,93 @@ public class Server
Coordinates start = new (48.7933798f, 9.8275859f); Coordinates start = new (48.7933798f, 9.8275859f);
Coordinates finish = new (48.795918f, 9.021618f); Coordinates finish = new (48.795918f, 9.021618f);
Pathfinder result = new Pathfinder(workingDir).AStar(start,
finish, Tag.SpeedType.car, 0.01, 0.0001,
0);
TestVariables(workingDir, start, finish);
string parentFolder = new DirectoryInfo(workingDir).Parent!.FullName; string parentFolder = new DirectoryInfo(workingDir).Parent!.FullName;
string resultFileName = $"{new DirectoryInfo(workingDir).Name}-{DateTime.Now.ToFileTime()}.result";
/*
Console.WriteLine("Preparing BaseRender");
RegionManager allRegions = new(workingDir);
for (float lat = 48.78f - Region.RegionSize / 2; lat < 48.87f + Region.RegionSize / 2; lat += Region.RegionSize / 2)
{
for (float lon = 9f - Region.RegionSize / 2; lon < 9.9f + Region.RegionSize / 2; lon += Region.RegionSize / 2)
{
allRegions.GetRegion(new Coordinates(lat, lon));
}
}
Console.WriteLine("Regions Loaded. Rendering.");
ValueTuple<Image, Renderer.Bounds> baseRender = Renderer.DrawArea(allRegions);
*/
/*
Pathfinder result = new Pathfinder(workingDir).AStar(start,
finish, Tag.SpeedType.car, 0.034, 0.012,
0, 0.18);
Console.WriteLine($"Calc-time {result.pathResult!.calcTime} Path-length: {result.pathResult.pathNodes.Count} Visited-nodes: {result.gScore!.Count}");
string fileName = DateTime.Now.ToFileTime().ToString();
string resultFileName = $"{new DirectoryInfo(workingDir).Name}-{fileName}.result";
result.SaveResult(Path.Join(parentFolder, resultFileName)); result.SaveResult(Path.Join(parentFolder, resultFileName));
string renderFileName = $"{new DirectoryInfo(workingDir).Name}-{DateTime.Now.ToFileTime()}.render.png"; string renderFileName = $"{new DirectoryInfo(workingDir).Name}-{fileName}.render.png";
Image render = Renderer.DrawPathfinder(result); Image render = Renderer.DrawPathfinder(result);
#pragma warning disable CA1416 #pragma warning disable CA1416
render.Save(Path.Join(parentFolder, renderFileName), ImageFormat.Png); render.Save(Path.Join(parentFolder, renderFileName), ImageFormat.Png);
#pragma warning restore CA1416 #pragma warning restore CA1416*/
}
private static void TestVariables(string workingDir, Coordinates start, Coordinates finish)
{
string parentFolder = new DirectoryInfo(workingDir).Parent!.FullName;
Queue<Thread> CalcThreads = new();
for (double sameRoadPriority = 0.002; sameRoadPriority < 0.4; sameRoadPriority += 0.02)
{
for (double roadLevelPriority = 0.4; roadLevelPriority > 0; roadLevelPriority -= 0.02)
{
for (double angleWeightFactor = 0.01; angleWeightFactor < 0.25; angleWeightFactor += 0.01)
{
double priority = roadLevelPriority;
double roadPriority = sameRoadPriority;
double factor = angleWeightFactor;
CalcThreads.Enqueue(new Thread(() =>
{
Pathfinder testresult = new Pathfinder(workingDir).AStar(start,
finish, Tag.SpeedType.car, priority, roadPriority,
0, factor);
string fileName =
$"angle{factor:0.000}_level{priority:0.000}_same{roadPriority:0.000}.result";
testresult.SaveResult(Path.Join(parentFolder, fileName));
}));
}
}
}
int totalTasks = CalcThreads.Count;
int completed = 0;
DateTime startTime = DateTime.Now;
HashSet<Thread> runningThreads = new();
while (CalcThreads.Count > 0)
{
while (runningThreads.Count < 16 && CalcThreads.Count > 0)
{
Thread t = CalcThreads.Dequeue();
runningThreads.Add(t);
t.Start();
}
int newCompleted = runningThreads.RemoveWhere(thread => !thread.IsAlive);
completed += newCompleted;
if(newCompleted > 0)
Console.WriteLine($"To calculate: {CalcThreads.Count}/{totalTasks} Average Time: {(DateTime.Now - startTime)/(completed)} Elapsed: {DateTime.Now - startTime} Remaining: {(DateTime.Now - startTime)/(completed)*CalcThreads.Count}");
}
} }
} }