From 27729bf06c53024832b809583279981343014e55 Mon Sep 17 00:00:00 2001 From: ClemensFischer Date: Thu, 29 Aug 2024 23:56:29 +0200 Subject: [PATCH] MapPanel, MapPath location coercion --- MapControl/Shared/BoundingBox.cs | 22 ++------- MapControl/Shared/CenteredBoundingBox.cs | 2 +- MapControl/Shared/MapBase.cs | 4 ++ MapControl/Shared/MapPanel.cs | 60 ++++++++++++++---------- MapControl/Shared/MapPath.cs | 15 +++++- 5 files changed, 57 insertions(+), 46 deletions(-) diff --git a/MapControl/Shared/BoundingBox.cs b/MapControl/Shared/BoundingBox.cs index c62836d1..d208e9fc 100644 --- a/MapControl/Shared/BoundingBox.cs +++ b/MapControl/Shared/BoundingBox.cs @@ -34,27 +34,15 @@ namespace MapControl { } - public double South { get; private set; } - public double North { get; private set; } - public double West { get; private set; } - public double East { get; private set; } + public double South { get; } + public double North { get; } + public double West { get; } + public double East { get; } public virtual double Width => East - West; public virtual double Height => North - South; - public virtual Location Center - { - get => new Location((South + North) / 2d, (West + East) / 2d); - set - { - var latOffset = value.Latitude - (South + North) / 2d; - var lonOffset = value.Longitude - (West + East) / 2d; - South += latOffset; - North += latOffset; - West += lonOffset; - East += lonOffset; - } - } + public virtual Location Center => new Location((South + North) / 2d, (West + East) / 2d); /// /// Creates a BoundingBox instance from a string containing a comma-separated sequence of four floating point numbers. diff --git a/MapControl/Shared/CenteredBoundingBox.cs b/MapControl/Shared/CenteredBoundingBox.cs index b8c06761..a6bfc665 100644 --- a/MapControl/Shared/CenteredBoundingBox.cs +++ b/MapControl/Shared/CenteredBoundingBox.cs @@ -15,7 +15,7 @@ namespace MapControl Height = Math.Max(height, 0d); } - public override Location Center { get; set; } + public override Location Center { get; } public override double Width { get; } public override double Height { get; } } diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs index 9199c3f1..9612415e 100644 --- a/MapControl/Shared/MapBase.cs +++ b/MapControl/Shared/MapBase.cs @@ -372,6 +372,10 @@ namespace MapControl } } + internal bool InsideViewport(Point point) => + point.X >= 0d && point.X <= ActualWidth && + point.Y >= 0d && point.Y <= ActualHeight; + internal double CoerceLongitude(double longitude) { var offset = longitude - Center.Longitude; diff --git a/MapControl/Shared/MapPanel.cs b/MapControl/Shared/MapPanel.cs index 92458317..117aaefa 100644 --- a/MapControl/Shared/MapPanel.cs +++ b/MapControl/Shared/MapPanel.cs @@ -189,32 +189,25 @@ namespace MapControl protected Point? GetViewPosition(Location location) { - if (parentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical) - { - var longitude = parentMap.CoerceLongitude(location.Longitude); + var position = parentMap.LocationToView(location); - if (longitude != location.Longitude) + if (parentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical && + position.HasValue && !parentMap.InsideViewport(position.Value)) + { + var coercedPosition = parentMap.LocationToView( + new Location(location.Latitude, parentMap.CoerceLongitude(location.Longitude))); + + if (coercedPosition.HasValue && parentMap.InsideViewport(coercedPosition.Value)) { - location = new Location(location.Latitude, longitude); + position = coercedPosition; } } - return parentMap.LocationToView(location); + return position; } protected ViewRect? GetViewRect(BoundingBox boundingBox) { - if (parentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical) - { - var center = boundingBox.Center; - var longitude = parentMap.CoerceLongitude(center.Longitude); - - if (longitude != center.Longitude) - { - boundingBox.Center = new Location(center.Latitude, longitude); - } - } - var mapRect = parentMap.MapProjection.BoundingBoxToMap(boundingBox); if (mapRect.HasValue) @@ -227,15 +220,33 @@ namespace MapControl protected ViewRect GetViewRect(Rect mapRect) { - var transform = parentMap.ViewTransform; var center = new Point(mapRect.X + mapRect.Width / 2d, mapRect.Y + mapRect.Height / 2d); - var position = transform.MapToView(center); - var width = mapRect.Width * transform.Scale; - var height = mapRect.Height * transform.Scale; + var position = parentMap.ViewTransform.MapToView(center); + var projection = parentMap.MapProjection; + + if (projection.Type <= MapProjectionType.NormalCylindrical && + !parentMap.InsideViewport(position)) + { + var location = projection.MapToLocation(center); + + if (location != null) + { + var coercedPosition = parentMap.LocationToView( + new Location(location.Latitude, parentMap.CoerceLongitude(location.Longitude))); + + if (coercedPosition.HasValue && parentMap.InsideViewport(coercedPosition.Value)) + { + position = coercedPosition.Value; + } + } + } + + var width = mapRect.Width * parentMap.ViewTransform.Scale; + var height = mapRect.Height * parentMap.ViewTransform.Scale; var x = position.X - width / 2d; var y = position.Y - height / 2d; - return new ViewRect(x, y, width, height, transform.Rotation); + return new ViewRect(x, y, width, height, parentMap.ViewTransform.Rotation); } private void ArrangeChildElement(FrameworkElement element, Size panelSize) @@ -250,10 +261,7 @@ namespace MapControl if (GetAutoCollapse(element)) { - SetVisible(element, - position.HasValue && - position.Value.X >= 0d && position.Value.X <= parentMap.ActualWidth && - position.Value.Y >= 0d && position.Value.Y <= parentMap.ActualHeight); + SetVisible(element, position.HasValue && parentMap.InsideViewport(position.Value)); } if (position.HasValue) diff --git a/MapControl/Shared/MapPath.cs b/MapControl/Shared/MapPath.cs index b6d77f3b..5a65c643 100644 --- a/MapControl/Shared/MapPath.cs +++ b/MapControl/Shared/MapPath.cs @@ -80,9 +80,20 @@ namespace MapControl { var longitudeOffset = 0d; - if (location != null && parentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical) + if (parentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical && location != null) { - longitudeOffset = parentMap.CoerceLongitude(location.Longitude) - location.Longitude; + var position = parentMap.LocationToView(location); + + if (position.HasValue && !parentMap.InsideViewport(position.Value)) + { + var coercedLongitude = parentMap.CoerceLongitude(location.Longitude); + var coercedPosition = parentMap.LocationToView(new Location(location.Latitude, coercedLongitude)); + + if (coercedPosition.HasValue && parentMap.InsideViewport(coercedPosition.Value)) + { + longitudeOffset = coercedLongitude - location.Longitude; + } + } } return longitudeOffset;