From 7208cc71bde14ff64b71a25504b640704c9f124a Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Sun, 25 Jan 2026 11:57:14 +0100 Subject: [PATCH] Location equality --- MapControl/Avalonia/MapBase.Avalonia.cs | 2 +- MapControl/Shared/Location.cs | 6 +++- MapControl/Shared/MapBase.cs | 36 ++++++++++++++------ MapControl/Shared/MapPanel.cs | 16 ++++----- MapControl/Shared/MapPath.cs | 2 +- MapControl/Shared/MapProjection.cs | 12 +++---- MapControl/WPF/MapBase.WPF.cs | 2 +- MapControl/WinUI/MapBase.WinUI.cs | 2 +- SampleApps/WpfApplication/MainWindow.xaml.cs | 2 +- 9 files changed, 50 insertions(+), 30 deletions(-) diff --git a/MapControl/Avalonia/MapBase.Avalonia.cs b/MapControl/Avalonia/MapBase.Avalonia.cs index 1ee197fb..968d0f41 100644 --- a/MapControl/Avalonia/MapBase.Avalonia.cs +++ b/MapControl/Avalonia/MapBase.Avalonia.cs @@ -136,7 +136,7 @@ namespace MapControl centerCts?.Cancel(); - centerAnimation = CreateAnimation(CenterProperty, new Location(targetCenter.Latitude, CoerceLongitude(targetCenter.Longitude))); + centerAnimation = CreateAnimation(CenterProperty, new Location(targetCenter.Latitude, NearestLongitude(targetCenter.Longitude))); using (centerCts = new CancellationTokenSource()) { diff --git a/MapControl/Shared/Location.cs b/MapControl/Shared/Location.cs index e3ecb9ae..1c0e3d1f 100644 --- a/MapControl/Shared/Location.cs +++ b/MapControl/Shared/Location.cs @@ -35,7 +35,11 @@ namespace MapControl public double Latitude { get; } public double Longitude { get; } - public bool Equals(double latitude, double longitude) => Latitude == latitude && Longitude == longitude; + public bool LatitudeEquals(double latitude) => Math.Abs(Latitude - latitude) < 1e-9; + + public bool LongitudeEquals(double longitude) => Math.Abs(Longitude - longitude) < 1e-9; + + public bool Equals(double latitude, double longitude) => LatitudeEquals(latitude) && LongitudeEquals(longitude); public bool Equals(Location location) => location != null && Equals(location.Latitude, location.Longitude); diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs index 47d5cc79..f3d77bc9 100644 --- a/MapControl/Shared/MapBase.cs +++ b/MapControl/Shared/MapBase.cs @@ -45,7 +45,7 @@ namespace MapControl public static readonly DependencyProperty ProjectionCenterProperty = DependencyPropertyHelper.Register(nameof(ProjectionCenter), null, - (map, oldValue, newValue) => map.ProjectionCenterPropertyChanged()); + (map, oldValue, newValue) => map.ProjectionCenterPropertyChanged(newValue)); private Location transformCenter; private Point viewCenter; @@ -365,7 +365,7 @@ namespace MapControl return point.X >= 0d && point.Y >= 0d && point.X <= ActualWidth && point.Y <= ActualHeight; } - internal double CoerceLongitude(double longitude) + internal double NearestLongitude(double longitude) { var offset = longitude - Center.Longitude; @@ -445,10 +445,23 @@ namespace MapControl UpdateTransform(false, true); } - private void ProjectionCenterPropertyChanged() + private void ProjectionCenterPropertyChanged(Location center) { - ResetTransformCenter(); - UpdateTransform(); + if (!internalPropertyChange) + { + if (center != null) + { + var longitude = Location.NormalizeLongitude(center.Longitude); + + if (!center.LongitudeEquals(longitude)) + { + SetValueInternal(ProjectionCenterProperty, new Location(center.Latitude, longitude)); + } + } + + ResetTransformCenter(); + UpdateTransform(); + } } private void UpdateTransform(bool resetTransformCenter = false, bool projectionChanged = false) @@ -471,16 +484,19 @@ namespace MapControl if (center != null) { - var centerLat = center.Latitude; - var centerLon = Location.NormalizeLongitude(center.Longitude); + var latitude = center.Latitude; + var longitude = Location.NormalizeLongitude(center.Longitude); - if (centerLat < -maxLatitude || centerLat > maxLatitude) + if (latitude < -maxLatitude || latitude > maxLatitude) { - centerLat = Math.Min(Math.Max(centerLat, -maxLatitude), maxLatitude); + latitude = Math.Min(Math.Max(latitude, -maxLatitude), maxLatitude); resetTransformCenter = true; } - center = new Location(centerLat, centerLon); + if (!center.Equals(latitude, longitude)) + { + center = new Location(latitude, longitude); + } SetValueInternal(CenterProperty, center); diff --git a/MapControl/Shared/MapPanel.cs b/MapControl/Shared/MapPanel.cs index 841a2927..6ed791d1 100644 --- a/MapControl/Shared/MapPanel.cs +++ b/MapControl/Shared/MapPanel.cs @@ -205,12 +205,12 @@ namespace MapControl if (parentMap.MapProjection.IsNormalCylindrical && position.HasValue && !parentMap.InsideViewBounds(position.Value)) { - var coercedPosition = parentMap.LocationToView( - location.Latitude, parentMap.CoerceLongitude(location.Longitude)); + var nearestPosition = parentMap.LocationToView( + location.Latitude, parentMap.NearestLongitude(location.Longitude)); - if (coercedPosition.HasValue) + if (nearestPosition.HasValue) { - position = coercedPosition; + position = nearestPosition; } } @@ -229,12 +229,12 @@ namespace MapControl if (location != null) { - var coercedPosition = parentMap.LocationToView( - location.Latitude, parentMap.CoerceLongitude(location.Longitude)); + var nearestPosition = parentMap.LocationToView( + location.Latitude, parentMap.NearestLongitude(location.Longitude)); - if (coercedPosition.HasValue) + if (nearestPosition.HasValue) { - position = coercedPosition.Value; + position = nearestPosition.Value; } } } diff --git a/MapControl/Shared/MapPath.cs b/MapControl/Shared/MapPath.cs index c27f91bf..1091a8f3 100644 --- a/MapControl/Shared/MapPath.cs +++ b/MapControl/Shared/MapPath.cs @@ -82,7 +82,7 @@ namespace MapControl if (position.HasValue && !ParentMap.InsideViewBounds(position.Value)) { - longitudeOffset = ParentMap.CoerceLongitude(location.Longitude) - location.Longitude; + longitudeOffset = ParentMap.NearestLongitude(location.Longitude) - location.Longitude; } } diff --git a/MapControl/Shared/MapProjection.cs b/MapControl/Shared/MapProjection.cs index f41c6087..6fac8b40 100644 --- a/MapControl/Shared/MapProjection.cs +++ b/MapControl/Shared/MapProjection.cs @@ -71,7 +71,10 @@ namespace MapControl if (value != null) { - SetCenter(value); + var longitude = Location.NormalizeLongitude(value.Longitude); + + SetCenter(value.LongitudeEquals(longitude) ? value : new Location(value.Latitude, longitude)); + updateCenter = false; } } @@ -89,12 +92,9 @@ namespace MapControl { if (updateCenter) { - var latitude = value.Latitude; - var longitude = Location.NormalizeLongitude(value.Longitude); - - if (center == null || !center.Equals(latitude, longitude)) + if (center == null || !center.Equals(value)) { - center = new Location(latitude, longitude); + center = value; CenterChanged(); } } diff --git a/MapControl/WPF/MapBase.WPF.cs b/MapControl/WPF/MapBase.WPF.cs index a1f509b8..83c45030 100644 --- a/MapControl/WPF/MapBase.WPF.cs +++ b/MapControl/WPF/MapBase.WPF.cs @@ -130,7 +130,7 @@ namespace MapControl centerAnimation = new LocationAnimation { - To = new Location(targetCenter.Latitude, CoerceLongitude(targetCenter.Longitude)), + To = new Location(targetCenter.Latitude, NearestLongitude(targetCenter.Longitude)), Duration = AnimationDuration, EasingFunction = AnimationEasingFunction }; diff --git a/MapControl/WinUI/MapBase.WinUI.cs b/MapControl/WinUI/MapBase.WinUI.cs index 124e9307..b15024bc 100644 --- a/MapControl/WinUI/MapBase.WinUI.cs +++ b/MapControl/WinUI/MapBase.WinUI.cs @@ -155,7 +155,7 @@ namespace MapControl centerAnimation = new PointAnimation { From = new Windows.Foundation.Point(Center.Longitude, Center.Latitude), - To = new Windows.Foundation.Point(CoerceLongitude(targetCenter.Longitude), targetCenter.Latitude), + To = new Windows.Foundation.Point(NearestLongitude(targetCenter.Longitude), targetCenter.Latitude), Duration = AnimationDuration, EasingFunction = AnimationEasingFunction, EnableDependentAnimation = true diff --git a/SampleApps/WpfApplication/MainWindow.xaml.cs b/SampleApps/WpfApplication/MainWindow.xaml.cs index dbfb27cf..0cc26258 100644 --- a/SampleApps/WpfApplication/MainWindow.xaml.cs +++ b/SampleApps/WpfApplication/MainWindow.xaml.cs @@ -37,7 +37,7 @@ namespace SampleApplication public MainWindow() { var httpClient = new HttpClient(new HttpHandler()) { Timeout = TimeSpan.FromSeconds(10) }; - httpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Avalonia Sample Application"); + httpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control WPF Sample Application"); ImageLoader.HttpClient = httpClient; var loggerFactory = LoggerFactory.Create(builder => builder.AddDebug().SetMinimumLevel(LogLevel.Information));