Compare commits

..

No commits in common. "619cad61eed86e84b1cf7ca5637758e0a90289d3" and "055a751c9ddc7be11421f2f5e6b7f3c2a94aba61" have entirely different histories.

5 changed files with 34 additions and 120 deletions

View File

@ -8,17 +8,16 @@ public class PathResult
[JsonInclude]public TimeSpan calcTime; [JsonInclude]public TimeSpan calcTime;
[JsonInclude]public List<PathNode> pathNodes; [JsonInclude]public List<PathNode> pathNodes;
[JsonInclude]public Dictionary<ulong, double>? gScore; [JsonInclude]public Dictionary<ulong, double>? gScore;
[JsonInclude]public HashSet<OsmNode>? gScoreNodes; [JsonInclude]public HashSet<OsmNode>? nodes;
[JsonIgnore] public RegionManager? regionManager { get; set; }
public string? name { get; set; } public string? name { get; set; }
[JsonConstructor] [JsonConstructor]
public PathResult(TimeSpan calcTime, List<PathNode> pathNodes, Dictionary<ulong, double>? gScore, HashSet<OsmNode>? gScoreNodes) public PathResult(TimeSpan calcTime, List<PathNode> pathNodes, Dictionary<ulong, double>? gScore, HashSet<OsmNode>? nodes)
{ {
this.calcTime = calcTime; this.calcTime = calcTime;
this.pathNodes = pathNodes; this.pathNodes = pathNodes;
this.gScore = gScore; this.gScore = gScore;
this.gScoreNodes = gScoreNodes; this.nodes = nodes;
} }
public PathResult(TimeSpan calcTime, List<PathNode> pathNodes) public PathResult(TimeSpan calcTime, List<PathNode> pathNodes)
@ -37,11 +36,11 @@ public class PathResult
public void AddGScores(Dictionary<OsmNode, double> gScore) public void AddGScores(Dictionary<OsmNode, double> gScore)
{ {
this.gScore = new(); this.gScore = new();
this.gScoreNodes = new(); this.nodes = new();
foreach (KeyValuePair<OsmNode, double> kv in gScore) foreach (KeyValuePair<OsmNode, double> kv in gScore)
{ {
this.gScore.Add(kv.Key.nodeId, kv.Value); this.gScore.Add(kv.Key.nodeId, kv.Value);
this.gScoreNodes.Add(kv.Key); this.nodes.Add(kv.Key);
} }
} }
} }

View File

@ -33,12 +33,11 @@ public static class Pathfinder
{ {
Console.WriteLine("Path found."); Console.WriteLine("Path found.");
PathResult path = GetPath(cameFromDict, goalNode, regionManager, DateTime.Now - startCalc); PathResult path = GetPath(cameFromDict, goalNode, regionManager, DateTime.Now - startCalc);
path.AddGScores(gScore);
string fileName = $"{new DirectoryInfo(workingDir).Name}-{DateTime.Now.ToFileTime()}.result"; string fileName = $"{new DirectoryInfo(workingDir).Name}-{DateTime.Now.ToFileTime()}.result";
string outputFilepath = Path.Join(Directory.GetParent(workingDir)!.FullName, fileName); string outputFilepath = Path.Join(Directory.GetParent(workingDir)!.FullName, fileName);
path.name = outputFilepath; path.name = outputFilepath;
path.AddGScores(gScore);
SaveGraph(path, outputFilepath); SaveGraph(path, outputFilepath);
path.regionManager = regionManager;
return path; return path;
} }
@ -64,6 +63,7 @@ public static class Pathfinder
heuristicRoadLevelPriority, heuristicFewJunctionsPriority, heuristicSameRoadPriority); 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);
} }
} }
} }
@ -105,7 +105,7 @@ public static class Pathfinder
double distance = Utils.DistanceBetween(fromNode, neighborNode); double distance = Utils.DistanceBetween(fromNode, neighborNode);
double speed = regionManager.GetSpeedForEdge(fromNode, edge.wayId, vehicle); double speed = regionManager.GetSpeedForEdge(fromNode, edge.wayId, vehicle);
double prio = GetPriorityVehicleRoad(edge, vehicle, regionManager.GetRegion(fromNode.coordinates)!); double prio = GetPriorityVehicleRoad(edge, vehicle, regionManager.GetRegion(fromNode.coordinates)!);
return distance / speed; return distance / (speed + prio * 50);
} }
private static double Heuristic(OsmNode fromNode, OsmNode neighborNode, OsmNode goalNode, OsmEdge edge, SpeedType vehicle, RegionManager regionManager, double roadPriorityFactor, double junctionFactor, double sameRoadFactor) private static double Heuristic(OsmNode fromNode, OsmNode neighborNode, OsmNode goalNode, OsmEdge edge, SpeedType vehicle, RegionManager regionManager, double roadPriorityFactor, double junctionFactor, double sameRoadFactor)
@ -131,7 +131,9 @@ public static 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); //Console.WriteLine($"{roadPriority:000.00} {sameRoadName:000.00} {junctionCount:000.00} {distanceImprovement:+000.00;-000.00;0000.00}");
return Utils.DistanceBetween(neighborNode, goalNode) - (roadPriority + sameRoadName + junctionCount) * 20;
} }
private static double GetPriorityVehicleRoad(OsmEdge edge, SpeedType vehicle, Region region) private static double GetPriorityVehicleRoad(OsmEdge edge, SpeedType vehicle, Region region)
@ -152,10 +154,10 @@ public static class Pathfinder
case WayType.trunk_link: case WayType.trunk_link:
case WayType.primary: case WayType.primary:
case WayType.primary_link: case WayType.primary_link:
return 10; return 8;
case WayType.secondary: case WayType.secondary:
case WayType.secondary_link: case WayType.secondary_link:
return 7; return 6;
case WayType.tertiary: case WayType.tertiary:
case WayType.tertiary_link: case WayType.tertiary_link:
return 5; return 5;
@ -166,7 +168,7 @@ public static class Pathfinder
return 2; return 2;
case WayType.service: case WayType.service:
case WayType.track: case WayType.track:
return 0.0001; return 0.01;
} }
} }
if (vehicle == SpeedType.pedestrian) if (vehicle == SpeedType.pedestrian)

View File

@ -7,26 +7,10 @@ using Pathfinding;
namespace RenderPath; namespace RenderPath;
public static class Renderer public class Renderer
{ {
private const int ImageMaxSize = 20000;
private const float PenThickness = 4;
public class Bounds public static void DrawGraph(string resultPath)
{
public readonly float minLat, maxLat, minLon, maxLon;
public Bounds(float minLat, float minLon, float maxLat, float maxLon)
{
this.minLon = minLon;
this.maxLat = maxLat;
this.maxLon = maxLon;
this.minLat = minLat;
}
}
[SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")]
public static void DrawGraph(string resultPath, Image? area = null, Bounds? bounds = null)
{ {
FileStream fs = new FileStream(resultPath, FileMode.Open); FileStream fs = new FileStream(resultPath, FileMode.Open);
PathResult graph = JsonSerializer.Deserialize<PathResult>(fs)!; PathResult graph = JsonSerializer.Deserialize<PathResult>(fs)!;
@ -35,92 +19,32 @@ public static class Renderer
coords.Add(node.coordinates); coords.Add(node.coordinates);
string workingDir = new DirectoryInfo(resultPath).FullName; string workingDir = new DirectoryInfo(resultPath).FullName;
Image renderedImage = DrawLoadedNodes(graph.gScoreNodes!, graph.gScore!, coords, area, bounds); DrawLoadedNodes(graph.nodes!, graph.gScore!, coords, workingDir);
renderedImage.Save($"{workingDir}-routing.png");
} }
[SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")] [SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")]
public static ValueTuple<Image, Bounds> DrawArea(RegionManager rm) public static void DrawLoadedNodes(HashSet<OsmNode> nodes, Dictionary<ulong, double> gScoreDict, List<Coordinates> pathCoordinates, string workingDir)
{ {
HashSet<OsmNode> nodes = new HashSet<OsmNode>();
foreach (OSMDatastructure.Region r in rm.GetAllRegions())
nodes = nodes.Concat(r.nodes).ToHashSet();
float minLat = nodes.Min(node => node.coordinates.latitude); float minLat = nodes.Min(node => node.coordinates.latitude);
float minLon = nodes.Min(node => node.coordinates.longitude); float minLon = nodes.Min(node => node.coordinates.longitude);
float maxLat = nodes.Max(node => node.coordinates.latitude); float maxLat = nodes.Max(node => node.coordinates.latitude);
float maxLon = nodes.Max(node => node.coordinates.longitude); float maxLon = nodes.Max(node => node.coordinates.longitude);
float latDiff = maxLat - minLat;
float lonDiff = maxLon - minLon;
float scaleFactor = latDiff > lonDiff ? ImageMaxSize / latDiff : ImageMaxSize / lonDiff;
int pixelsX = (int)(lonDiff * scaleFactor);
int pixelsY = (int)(latDiff * scaleFactor);
Image ret = new Bitmap(pixelsX, pixelsY, PixelFormat.Format32bppRgb);
Graphics g = Graphics.FromImage(ret);
g.Clear(Color.White);
Color start = Color.FromArgb(255, 25, 25, 25);
Color center = Color.FromArgb(255, 0, 0, 0);
Color end = Color.FromArgb(255, 0, 255, 0);
foreach (OsmNode node in nodes)
{
foreach (OsmEdge edge in node.edges)
{
Coordinates c1 = node.coordinates;
OsmNode nNode = rm.GetNode(edge.neighborId, edge.neighborRegion)!;
Coordinates c2 = nNode.coordinates;
Pen p = new Pen(GradientPick(0, start, center, end), PenThickness);
float x1 = (c1.longitude - minLon) * scaleFactor;
float y1 = (maxLat - c1.latitude) * scaleFactor;
float x2 = (c2.longitude - minLon) * scaleFactor;
float y2 = (maxLat - c2.latitude) * scaleFactor;
g.DrawLine(p, x1, y1, x2, y2);
}
}
return new ValueTuple<Image, Bounds>(ret, new Bounds(minLat,minLon,maxLat,maxLon));
}
[SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")]
public static Image DrawLoadedNodes(HashSet<OsmNode> nodes, Dictionary<ulong, double> gScoreDict,
List<Coordinates> pathCoordinates, Image? renderOver = null, Bounds? bounds = null)
{
float minLat = bounds?.minLat ?? nodes.Min(node => node.coordinates.latitude);
float minLon = bounds?.minLon ?? nodes.Min(node => node.coordinates.longitude);
float maxLat = bounds?.maxLat ?? nodes.Max(node => node.coordinates.latitude);
float maxLon = bounds?.maxLon ?? nodes.Max(node => node.coordinates.longitude);
double minWeight = gScoreDict.Min(kv => kv.Value); double minWeight = gScoreDict.Min(kv => kv.Value);
double maxWeight = gScoreDict.Max(kv => kv.Value); double maxWeight = gScoreDict.Max(kv => kv.Value);
float latDiff = maxLat - minLat; float latDiff = maxLat - minLat;
float lonDiff = maxLon - minLon; float lonDiff = maxLon - minLon;
float scaleFactor = latDiff > lonDiff ? ImageMaxSize / latDiff : ImageMaxSize / lonDiff; const int imageMaxSize = 10000;
float scaleFactor = latDiff > lonDiff ? imageMaxSize / latDiff : imageMaxSize / lonDiff;
int pixelsX = (int)(lonDiff * scaleFactor); int pixelsX = (int)(lonDiff * scaleFactor);
int pixelsY = (int)(latDiff * scaleFactor); int pixelsY = (int)(latDiff * scaleFactor);
Image ret; Bitmap ret = new Bitmap(pixelsX, pixelsY, PixelFormat.Format32bppRgb);
Graphics g; Graphics g = Graphics.FromImage(ret);
if (renderOver is null)
{
ret = new Bitmap(pixelsX, pixelsY, PixelFormat.Format32bppRgb);
g = Graphics.FromImage(ret);
g.Clear(Color.White); g.Clear(Color.White);
}
else
{
ret = renderOver;
g = Graphics.FromImage(ret);
}
Color start = Color.FromArgb(0, 0, 255); Color start = Color.FromArgb(0, 0, 255);
Color center = Color.FromArgb(255, 255, 0); Color center = Color.FromArgb(255, 255, 0);
@ -134,26 +58,21 @@ public static class Renderer
float x = (node.coordinates.longitude - minLon) * scaleFactor; float x = (node.coordinates.longitude - minLon) * scaleFactor;
float y = (maxLat - node.coordinates.latitude) * scaleFactor; float y = (maxLat - node.coordinates.latitude) * scaleFactor;
g.FillEllipse(b, x, y, 2, 2);
x -= (PenThickness * 1.5f) / 2;
y -= (PenThickness * 1.5f) / 2;
g.FillEllipse(b, x, y, PenThickness * 1.5f, PenThickness * 1.5f);
} }
Pen p = new Pen(Color.Red, PenThickness); Pen p = new Pen(Color.Red, 2);
for (int i = 0; i < pathCoordinates.Count - 1; i++) for (int i = 0; i < pathCoordinates.Count - 1; i++)
{ {
Coordinates c1 = pathCoordinates[i]; Coordinates c1 = pathCoordinates[i];
Coordinates c2 = pathCoordinates[i + 1]; Coordinates c2 = pathCoordinates[i+1];
Point p1 = new(Convert.ToInt32((c1.longitude - minLon) * scaleFactor), Point p1 = new(Convert.ToInt32((c1.longitude - minLon) * scaleFactor), Convert.ToInt32((maxLat - c1.latitude) * scaleFactor));
Convert.ToInt32((maxLat - c1.latitude) * scaleFactor)); Point p2 = new(Convert.ToInt32((c2.longitude - minLon) * scaleFactor), Convert.ToInt32((maxLat - c2.latitude) * scaleFactor));
Point p2 = new(Convert.ToInt32((c2.longitude - minLon) * scaleFactor),
Convert.ToInt32((maxLat - c2.latitude) * scaleFactor));
g.DrawLine(p, p1, p2); g.DrawLine(p, p1, p2);
} }
return ret; ret.Save($"{workingDir}-routing.png", ImageFormat.Bmp);
} }
/* /*

View File

@ -1,4 +1,3 @@
using System.Drawing;
using OSMDatastructure; using OSMDatastructure;
using OSMDatastructure.Graph; using OSMDatastructure.Graph;
using Pathfinding; using Pathfinding;
@ -20,16 +19,12 @@ public class Server
//RegionConverter.ConvertXMLToRegions("D:/germany-latest.osm", "D:/germany-latest"); //RegionConverter.ConvertXMLToRegions("D:/germany-latest.osm", "D:/germany-latest");
Coordinates start = new Coordinates(48.7933798f, 9.8275859f); Coordinates start = new Coordinates( 48.7933798f, 9.8275859f);
Coordinates finish = new Coordinates(48.795918f, 9.021618f); Coordinates finish = new Coordinates( 48.795918f, 9.021618f);
PathResult result = Pathfinder.AStar("D:/stuttgart-regbez-latest", start, PathResult result = Pathfinder.AStar("D:/stuttgart-regbez-latest", start,
finish, Tag.SpeedType.car, 0.01, 0.0001, finish, Tag.SpeedType.car, 0.1, 0.2,
0); 0);
Console.WriteLine("Drawing area"); Renderer.DrawGraph(result.name);
ValueTuple<Image, Renderer.Bounds> area = Renderer.DrawArea(result.regionManager);
Console.WriteLine("Drawing route");
Renderer.DrawGraph(result.name, area.Item1, area.Item2);
} }
} }

View File

@ -13,7 +13,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="7.0.0" />
<PackageReference Include="System.Runtime.Serialization.Json" Version="4.3.0" /> <PackageReference Include="System.Runtime.Serialization.Json" Version="4.3.0" />
</ItemGroup> </ItemGroup>