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