diff --git a/Graph_Renderer.sln.DotSettings.user b/Graph_Renderer.sln.DotSettings.user
new file mode 100644
index 0000000..d5c2113
--- /dev/null
+++ b/Graph_Renderer.sln.DotSettings.user
@@ -0,0 +1,4 @@
+
+ True
+ True
+ True
\ No newline at end of file
diff --git a/Graph_Renderer/Coloring.cs b/Graph_Renderer/Coloring.cs
new file mode 100644
index 0000000..e9e0c94
--- /dev/null
+++ b/Graph_Renderer/Coloring.cs
@@ -0,0 +1,49 @@
+using System.Drawing;
+using astar.PathingHelper;
+using Graph;
+
+namespace Graph_Renderer;
+
+public static class Coloring
+{
+ public static Color GetColorForWay(Way way)
+ {
+ if (!way.Tags.TryGetValue("highway", out string? highwayTypeStr))
+ return Color.Gray;
+ if (!Enum.TryParse(highwayTypeStr, out HighwayType highwayType))
+ return Color.Gray;
+ return ColorDictionary[highwayType];
+ }
+
+ private static readonly Dictionary ColorDictionary = new() {
+ { HighwayType.NONE, Color.Gray },
+ { HighwayType.motorway, Color.OrangeRed },
+ { HighwayType.trunk, Color.Orange },
+ { HighwayType.primary, Color.Yellow },
+ { HighwayType.secondary, Color.Aqua },
+ { HighwayType.tertiary, Color.Black },
+ { HighwayType.unclassified, Color.Gray },
+ { HighwayType.residential, Color.Gray },
+ { HighwayType.motorway_link, Color.OrangeRed },
+ { HighwayType.trunk_link, Color.Orange },
+ { HighwayType.primary_link, Color.Yellow },
+ { HighwayType.secondary_link, Color.Aqua },
+ { HighwayType.tertiary_link, Color.Black },
+ { HighwayType.living_street, Color.Gray },
+ { HighwayType.service, Color.Gray },
+ { HighwayType.pedestrian, Color.ForestGreen },
+ { HighwayType.track, Color.Gray },
+ { HighwayType.bus_guideway, Color.Navy },
+ { HighwayType.escape, Color.Gray },
+ { HighwayType.raceway, Color.Gray },
+ { HighwayType.road, Color.Gray },
+ { HighwayType.busway, Color.Navy },
+ { HighwayType.footway, Color.GreenYellow },
+ { HighwayType.bridleway, Color.Gray },
+ { HighwayType.steps, Color.PaleGreen },
+ { HighwayType.corridor, Color.Green },
+ { HighwayType.path, Color.Green },
+ { HighwayType.cycleway, Color.Salmon },
+ { HighwayType.construction, Color.Gray }
+ };
+}
\ No newline at end of file
diff --git a/Graph_Renderer/Graph_Renderer.csproj b/Graph_Renderer/Graph_Renderer.csproj
index 2f4fc77..2ce7315 100644
--- a/Graph_Renderer/Graph_Renderer.csproj
+++ b/Graph_Renderer/Graph_Renderer.csproj
@@ -7,4 +7,22 @@
enable
+
+
+ ..\..\astar\Executable\bin\Debug\net8.0\astar.dll
+
+
+ ..\..\OSM_Graph\OSM_Graph\bin\Debug\net8.0\Graph.dll
+
+
+ ..\..\OSM_Graph\OSM_Graph\bin\Debug\net8.0\OSM_Graph.dll
+
+
+
+
+
+
+
+
+
diff --git a/Graph_Renderer/Program.cs b/Graph_Renderer/Program.cs
index e5dff12..daf48c4 100644
--- a/Graph_Renderer/Program.cs
+++ b/Graph_Renderer/Program.cs
@@ -1,3 +1,43 @@
// See https://aka.ms/new-console-template for more information
-Console.WriteLine("Hello, World!");
\ No newline at end of file
+using System.Globalization;
+using System.Runtime.InteropServices;
+using astar;
+using GlaxArguments;
+using GlaxLogger;
+using Graph_Renderer;
+using Microsoft.Extensions.Logging;
+
+if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+{
+ Console.WriteLine("Only runs on Windows. Sorry.");
+ return -1;
+}
+
+Argument regionArg = new (["-r", "--regionSize"], 1, "Region-Size");
+Argument importPathArg = new (["-i", "--importPath"], 1, "Region-Directory");
+Argument routeCoordinateArg = new(["-c", "--route", "--coordinates"], 4, "Start and end coordinates");
+
+ArgumentFetcher af = new ([regionArg, importPathArg, routeCoordinateArg]);
+
+Dictionary arguments = af.Fetch(args);
+
+if (!arguments.TryGetValue(regionArg, out string[]? regionVal) ||
+ !float.TryParse(regionVal[0], NumberFormatInfo.InvariantInfo, out float regionSize) ||
+ !arguments.TryGetValue(importPathArg, out string[]? importPathVal) ||
+ !arguments.TryGetValue(routeCoordinateArg, out string[]? routeCoordinateVal) ||
+ !float.TryParse(routeCoordinateVal[0], NumberFormatInfo.InvariantInfo, out float startLat) ||
+ !float.TryParse(routeCoordinateVal[1], NumberFormatInfo.InvariantInfo, out float startLon) ||
+ !float.TryParse(routeCoordinateVal[2], NumberFormatInfo.InvariantInfo, out float endLat) ||
+ !float.TryParse(routeCoordinateVal[3], NumberFormatInfo.InvariantInfo, out float endLon))
+{
+ return -1;
+}
+
+Logger logger = new(LogLevel.Information, consoleOut: Console.Out);
+
+Route r = Astar.FindPath(startLat, startLon, endLat, endLon, regionSize, true, importPathVal[0], logger);
+
+Renderer.Render(r, 30000, "render.png");
+
+return 0;
\ No newline at end of file
diff --git a/Graph_Renderer/Renderer.cs b/Graph_Renderer/Renderer.cs
new file mode 100644
index 0000000..aa8b5cf
--- /dev/null
+++ b/Graph_Renderer/Renderer.cs
@@ -0,0 +1,79 @@
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Runtime.Versioning;
+using astar;
+
+namespace Graph_Renderer;
+
+public static class Renderer
+{
+
+ [SupportedOSPlatform("Windows")]
+ public static void Render(Route r, int longestEdge, string outputPath)
+ {
+ ValueTuple minCoordinates = r.MinCoordinates();
+ ValueTuple maxCoordinates = r.MaxCoordinates();
+ float deltaLat = maxCoordinates.Item1 - minCoordinates.Item1;
+ float deltaLon = maxCoordinates.Item2 - minCoordinates.Item2;
+ float multiplier = deltaLat > deltaLon ? longestEdge / deltaLat : longestEdge / deltaLon;
+
+
+ Bitmap bitmap = new((int)(deltaLon * multiplier), (int)(deltaLat * multiplier), System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
+ Graphics graphics = Graphics.FromImage(bitmap);
+ Pen previous = new (Color.White, 2);
+ using(GraphicsPath capPath = new ())
+ {
+ // A triangle
+ capPath.AddLines(new Point[]{new (-2, -2), new (0, 2), new (2, -2)});
+
+ previous.CustomEndCap = new CustomLineCap(null, capPath);
+ }
+
+ foreach ((ulong nodeId, Node? node) in r.Graph.Nodes)
+ {
+ Point startCoordinates = PixelCoordinatesFromGeoCoordinates(node, minCoordinates, multiplier, bitmap.Height);
+
+ //All neighbors
+ foreach ((ulong neighborNodeId, ulong wayId) in node.Neighbors.Where(kv => r.Graph.ContainsNode(kv.Key)))
+ {
+ Point endCoordinates = PixelCoordinatesFromGeoCoordinates(r.Graph.Nodes[neighborNodeId], minCoordinates, multiplier, bitmap.Height);
+ graphics.DrawLine(new Pen(Coloring.GetColorForWay(r.Graph.Ways[wayId]), 2), startCoordinates, endCoordinates);
+ }
+
+ //Previous
+ if (node.PreviousNodeId is not null)
+ {
+ Point previousCoordinates = PixelCoordinatesFromGeoCoordinates(r.Graph.Nodes[(ulong)node.PreviousNodeId], minCoordinates, multiplier, bitmap.Height);
+ graphics.DrawLine(previous, startCoordinates, previousCoordinates);
+ }
+ }
+
+ if (r.RouteFound)
+ {
+ Pen route = new(Color.BlueViolet, 2);
+ foreach (Step step in r.Steps)
+ {
+ Point startCoordinates = PixelCoordinatesFromGeoCoordinates(step.Node1, minCoordinates, multiplier, bitmap.Height);
+ Point endCoordinates = PixelCoordinatesFromGeoCoordinates(step.Node2, minCoordinates, multiplier, bitmap.Height);
+ graphics.DrawLine(route, startCoordinates, endCoordinates);
+ }
+ }
+
+ Directory.CreateDirectory(new FileInfo(outputPath).DirectoryName!);
+ bitmap.Save(outputPath);
+ Console.WriteLine(outputPath);
+ }
+
+ private static Point PixelCoordinatesFromGeoCoordinates
+ (Node node, ValueTuple minCoordinates, float multiplier, int height) =>
+ PixelCoordinatesFromGeoCoordinates(node.Lat, node.Lon, minCoordinates, multiplier, height);
+
+ private static Point PixelCoordinatesFromGeoCoordinates(float lat, float lon,
+ ValueTuple minCoordinates, float multiplier, int height)
+ {
+ float pLat = lat - minCoordinates.Item1;
+ float pLon = lon - minCoordinates.Item2;
+
+ return new Point((int)(pLon * multiplier), height - (int)(pLat * multiplier));
+ }
+}
\ No newline at end of file