From a7e7442d44b4088e17a3b8cbe6d60c801481b0ec Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Sun, 8 Feb 2026 17:18:32 +0100 Subject: [PATCH] Update map grids --- MapControl/Avalonia/MapGrid.Avalonia.cs | 17 +++++- MapControl/Shared/MapGraticule.cs | 73 ++++++++++++++++++------- MapControl/Shared/MapGrid.cs | 7 ++- MapControl/Shared/MetricGrid.cs | 37 ++++--------- MapControl/WPF/MapGrid.WPF.cs | 16 +++++- MapControl/WinUI/MapGrid.WinUI.cs | 15 ++++- 6 files changed, 113 insertions(+), 52 deletions(-) diff --git a/MapControl/Avalonia/MapGrid.Avalonia.cs b/MapControl/Avalonia/MapGrid.Avalonia.cs index 06b882c6..31cc0c1e 100644 --- a/MapControl/Avalonia/MapGrid.Avalonia.cs +++ b/MapControl/Avalonia/MapGrid.Avalonia.cs @@ -1,6 +1,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Documents; +using Avalonia.Layout; using Avalonia.Media; using System; using System.Collections.Generic; @@ -80,8 +81,20 @@ namespace MapControl { var text = new FormattedText(label.Text, CultureInfo.InvariantCulture, FlowDirection.LeftToRight, typeface, FontSize, Foreground); - var x = label.X + StrokeThickness / 2d + 2d; - var y = label.Y - text.Height / 2d; + var x = label.X + + label.HorizontalAlignment switch + { + HorizontalAlignment.Left => 2d, + HorizontalAlignment.Right => -text.Width - 2d, + _ => -text.Width / 2d + }; + var y = label.Y + + label.VerticalAlignment switch + { + VerticalAlignment.Top => 0, + VerticalAlignment.Bottom => -text.Height, + _ => -text.Height / 2d + }; if (label.Rotation != 0d) { diff --git a/MapControl/Shared/MapGraticule.cs b/MapControl/Shared/MapGraticule.cs index c5e32a04..f487e7a5 100644 --- a/MapControl/Shared/MapGraticule.cs +++ b/MapControl/Shared/MapGraticule.cs @@ -6,11 +6,14 @@ using System.Linq; using System.Windows; using System.Windows.Media; #elif UWP +using Windows.UI.Xaml; using Windows.UI.Xaml.Media; #elif WINUI +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; #elif AVALONIA using Avalonia; +using Avalonia.Layout; using PathFigureCollection = Avalonia.Media.PathFigures; #endif @@ -74,6 +77,13 @@ namespace MapControl var p1 = ParentMap.LocationToView(lat, southWest.Longitude); var p2 = ParentMap.LocationToView(lat, northEast.Longitude); figures.Add(CreateLineFigure(p1, p2)); + + if (ParentMap.ViewTransform.Rotation == 0d) + { + var text = GetLatitudeLabelText(lat, labelFormat); + labels.Add(new Label(text, p1.X, p1.Y, 0d, HorizontalAlignment.Left, VerticalAlignment.Bottom)); + labels.Add(new Label(text, p2.X, p2.Y, 0d, HorizontalAlignment.Right, VerticalAlignment.Bottom)); + } } for (var lon = minLon; lon <= northEast.Longitude; lon += lineDistance) @@ -82,9 +92,18 @@ namespace MapControl var p2 = ParentMap.LocationToView(northEast.Latitude, lon); figures.Add(CreateLineFigure(p1, p2)); - for (var lat = minLat; lat <= northEast.Latitude; lat += lineDistance) + if (ParentMap.ViewTransform.Rotation == 0d) { - AddLabel(labels, labelFormat, lat, lon, ParentMap.LocationToView(lat, lon), 0d); + var text = GetLongitudeLabelText(lon, labelFormat); + labels.Add(new Label(text, p1.X, p1.Y, 0d, HorizontalAlignment.Left, VerticalAlignment.Bottom)); + labels.Add(new Label(text, p2.X, p2.Y, 0d, HorizontalAlignment.Left, VerticalAlignment.Top)); + } + else + { + for (var lat = minLat; lat <= northEast.Latitude; lat += lineDistance) + { + AddLabel(labels, labelFormat, lat, lon, ParentMap.LocationToView(lat, lon), 0d); + } } } } @@ -125,8 +144,14 @@ namespace MapControl maxLon += lineDistance; } - minLat = Math.Ceiling(minLat / lineDistance) * lineDistance; - maxLat = Math.Floor(maxLat / lineDistance) * lineDistance; + if (pointDistance < lineDistance) + { + minLat = Math.Ceiling(minLat / lineDistance - 1e-6) * lineDistance; + maxLat = Math.Floor(maxLat / lineDistance + 1e-6) * lineDistance; + } + + maxLat += 1e-6; + maxLon += 1e-6; for (var lat = minLat; lat <= maxLat; lat += lineDistance) { @@ -209,27 +234,37 @@ namespace MapControl rotation -= 180d; } - var text = GetLabelText(lat, labelFormat, "NS") + - "\n" + GetLabelText(Location.NormalizeLongitude(lon), labelFormat, "EW"); + var text = GetLatitudeLabelText(lat, labelFormat) + + "\n" + GetLongitudeLabelText(lon, labelFormat); labels.Add(new Label(text, position.X, position.Y, rotation)); } + } - static string GetLabelText(double value, string labelFormat, string hemispheres) + private static string GetLatitudeLabelText(double value, string labelFormat) + { + return GetLabelText(value, labelFormat, "NS"); + } + + private static string GetLongitudeLabelText(double value, string labelFormat) + { + return GetLabelText(Location.NormalizeLongitude(value), labelFormat, "EW"); + } + + private static string GetLabelText(double value, string labelFormat, string hemispheres) + { + var hemisphere = hemispheres[0]; + + if (value < -1e-8) // ~1 mm { - var hemisphere = hemispheres[0]; - - if (value < -1e-8) // ~1 mm - { - value = -value; - hemisphere = hemispheres[1]; - } - - var seconds = (int)Math.Round(value * 3600d); - - return string.Format(CultureInfo.InvariantCulture, - labelFormat, hemisphere, seconds / 3600, seconds / 60 % 60, seconds % 60); + value = -value; + hemisphere = hemispheres[1]; } + + var seconds = (int)Math.Round(value * 3600d); + + return string.Format(CultureInfo.InvariantCulture, + labelFormat, hemisphere, seconds / 3600, seconds / 60 % 60, seconds % 60); } } } diff --git a/MapControl/Shared/MapGrid.cs b/MapControl/Shared/MapGrid.cs index 05336890..5f4e549e 100644 --- a/MapControl/Shared/MapGrid.cs +++ b/MapControl/Shared/MapGrid.cs @@ -11,6 +11,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; #elif AVALONIA using Avalonia; +using Avalonia.Layout; using Avalonia.Media; using Brush = Avalonia.Media.IBrush; using PathFigureCollection = Avalonia.Media.PathFigures; @@ -23,12 +24,16 @@ namespace MapControl /// public abstract partial class MapGrid { - protected class Label(string text, double x, double y, double rotation) + protected class Label(string text, double x, double y, double rotation, + HorizontalAlignment horizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment verticalAlignment = VerticalAlignment.Center) { public string Text => text; public double X => x; public double Y => y; public double Rotation => rotation; + public HorizontalAlignment HorizontalAlignment => horizontalAlignment; + public VerticalAlignment VerticalAlignment => verticalAlignment; } public static readonly DependencyProperty MinLineDistanceProperty = diff --git a/MapControl/Shared/MetricGrid.cs b/MapControl/Shared/MetricGrid.cs index 8dbee524..63d96d7e 100644 --- a/MapControl/Shared/MetricGrid.cs +++ b/MapControl/Shared/MetricGrid.cs @@ -4,11 +4,14 @@ using System.Collections.Generic; using System.Windows; using System.Windows.Media; #elif UWP +using Windows.UI.Xaml; using Windows.UI.Xaml.Media; #elif WINUI +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; #elif AVALONIA using Avalonia; +using Avalonia.Layout; using PathFigureCollection = Avalonia.Media.PathFigures; #endif @@ -43,6 +46,10 @@ namespace MapControl var p1 = ParentMap.ViewTransform.MapToView(new Point(x, mapRect.Y)); var p2 = ParentMap.ViewTransform.MapToView(new Point(x, mapRect.Y + mapRect.Height)); figures.Add(CreateLineFigure(p1, p2)); + + var text = string.Format("{0:F0}", x); + labels.Add(new Label(text, p1.X, p1.Y, 0d, HorizontalAlignment.Left, VerticalAlignment.Bottom)); + labels.Add(new Label(text, p2.X, p2.Y, 0d, HorizontalAlignment.Left, VerticalAlignment.Top)); } for (var y = minY; y <= mapRect.Y + mapRect.Height; y += lineDistance) @@ -51,33 +58,9 @@ namespace MapControl var p2 = ParentMap.ViewTransform.MapToView(new Point(mapRect.X + mapRect.Width, y)); figures.Add(CreateLineFigure(p1, p2)); - for (var x = minX; x <= mapRect.X + mapRect.Width; x += lineDistance) - { - AddLabel(labels, x, y); - } - } - } - - private void AddLabel(List