OSMServer/RenderPath/Renderer.cs

79 lines
3.4 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.Drawing.Imaging;
using OSMDatastructure.Graph;
namespace RenderPath;
public class Renderer
{
[SuppressMessage("Interoperability", "CA1416:Plattformkompatibilität überprüfen")]
public static void DrawLoadedNodes(Dictionary<OsmNode, double> gScoreDict, List<Coordinates> pathCoordinates, string workingDir)
{
float minLat = gScoreDict.Min(kv => kv.Key.coordinates.latitude);
float minLon = gScoreDict.Min(kv => kv.Key.coordinates.longitude);
float maxLat = gScoreDict.Max(kv => kv.Key.coordinates.latitude);
float maxLon = gScoreDict.Max(kv => kv.Key.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;
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);
Color start = Color.FromArgb(0, 0, 255);
Color center = Color.FromArgb(255, 255, 0);
Color end = Color.FromArgb(255, 0, 0);
foreach (KeyValuePair<OsmNode, double> kv in gScoreDict)
{
double percentage = kv.Value / maxWeight;
Brush b = new SolidBrush(GradientPick(percentage, start, center, end));
float x = (kv.Key.coordinates.longitude - minLon) * scaleFactor;
float y = (maxLat - kv.Key.coordinates.latitude) * scaleFactor;
g.FillEllipse(b, x, y, 4, 4);
}
Pen p = new Pen(Color.Red, 2);
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));
g.DrawLine(p, p1, p2);
}
ret.Save(Path.Join(Directory.GetParent(workingDir)!.FullName, "routing.png"), ImageFormat.Bmp);
}
/*
* https://stackoverflow.com/questions/55601338/get-a-color-value-within-a-gradient-based-on-a-value
*/
private static int LinearInterp(int start, int end, double percentage) => start + (int)Math.Round(percentage * (end - start));
private static Color ColorInterp(Color start, Color end, double percentage) =>
Color.FromArgb(LinearInterp(start.A, end.A, percentage),
LinearInterp(start.R, end.R, percentage),
LinearInterp(start.G, end.G, percentage),
LinearInterp(start.B, end.B, percentage));
private static Color GradientPick(double percentage, Color Start, Color Center, Color End) {
if (percentage < 0.5)
return ColorInterp(Start, Center, percentage / 0.5);
else if (percentage == 0.5)
return Center;
else
return ColorInterp(Center, End, (percentage - 0.5)/0.5);
}
}