From 49d508b3f5e24e9fdc21abf6b1344b81e4c334e7 Mon Sep 17 00:00:00 2001 From: ClemensF Date: Wed, 13 May 2020 18:17:28 +0200 Subject: [PATCH] Reworked MapPath and derived classes --- MapControl/Shared/Location.cs | 18 +------ MapControl/Shared/MapBase.cs | 22 +++++++-- MapControl/Shared/MapPanel.cs | 8 ++-- MapControl/Shared/MapPath.cs | 69 +++++++++++++++------------ MapControl/Shared/MapPolygon.cs | 11 +++-- MapControl/Shared/MapPolyline.cs | 11 +++-- MapControl/UWP/MapPath.UWP.cs | 21 ++++---- MapControl/WPF/MapMultiPolygon.WPF.cs | 8 ++-- MapControl/WPF/MapPath.WPF.cs | 22 +++++---- 9 files changed, 106 insertions(+), 84 deletions(-) diff --git a/MapControl/Shared/Location.cs b/MapControl/Shared/Location.cs index 983eba1a..dfa7e571 100644 --- a/MapControl/Shared/Location.cs +++ b/MapControl/Shared/Location.cs @@ -84,7 +84,7 @@ namespace MapControl } /// - /// Normalizes a longitude to a value in the interval [-180..180]. + /// Normalizes a longitude to a value in the interval [-180 .. 180]. /// public static double NormalizeLongitude(double longitude) { @@ -99,21 +99,5 @@ namespace MapControl return longitude; } - - internal static double NearestLongitude(double longitude, double referenceLongitude) - { - longitude = NormalizeLongitude(longitude); - - if (longitude > referenceLongitude + 180d) - { - longitude -= 360d; - } - else if (longitude < referenceLongitude - 180d) - { - longitude += 360d; - } - - return longitude; - } } } diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs index 78bf8759..f901530c 100644 --- a/MapControl/Shared/MapBase.cs +++ b/MapControl/Shared/MapBase.cs @@ -370,6 +370,22 @@ namespace MapControl TargetHeading = 0d; } + internal double ConstrainedLongitude(double longitude) + { + var offset = longitude - Center.Longitude; + + if (offset > 180d) + { + longitude = Center.Longitude - 360d + offset % 360d; + } + else if (offset < -180d) + { + longitude = Center.Longitude + 360d + offset % 360d; + } + + return longitude; + } + private void MapLayerPropertyChanged(UIElement oldLayer, UIElement newLayer) { if (oldLayer != null) @@ -458,10 +474,6 @@ namespace MapControl if (!targetCenter.Equals(Center)) { - var targetCenterLongitude = MapProjection.IsNormalCylindrical - ? Location.NearestLongitude(targetCenter.Longitude, Center.Longitude) - : targetCenter.Longitude; - if (centerAnimation != null) { centerAnimation.Completed -= CenterAnimationCompleted; @@ -470,7 +482,7 @@ namespace MapControl centerAnimation = new PointAnimation { From = new Point(Center.Longitude, Center.Latitude), - To = new Point(targetCenterLongitude, targetCenter.Latitude), + To = new Point(ConstrainedLongitude(targetCenter.Longitude), targetCenter.Latitude), Duration = AnimationDuration, EasingFunction = AnimationEasingFunction }; diff --git a/MapControl/Shared/MapPanel.cs b/MapControl/Shared/MapPanel.cs index a44f4c48..fdd031f5 100644 --- a/MapControl/Shared/MapPanel.cs +++ b/MapControl/Shared/MapPanel.cs @@ -151,9 +151,9 @@ namespace MapControl (pos.X < 0d || pos.X > parentMap.RenderSize.Width || pos.Y < 0d || pos.Y > parentMap.RenderSize.Height)) { - pos = parentMap.LocationToView(new Location( - location.Latitude, - Location.NearestLongitude(location.Longitude, parentMap.Center.Longitude))); + location = new Location(location.Latitude, parentMap.ConstrainedLongitude(location.Longitude)); + + pos = parentMap.LocationToView(location); } var rect = new Rect(pos, element.DesiredSize); @@ -208,7 +208,7 @@ namespace MapControl pos.Y < 0d || pos.Y > parentMap.RenderSize.Height)) { var location = projection.MapToLocation(center); - location.Longitude = Location.NearestLongitude(location.Longitude, parentMap.Center.Longitude); + location.Longitude = parentMap.ConstrainedLongitude(location.Longitude); pos = parentMap.LocationToView(location); } diff --git a/MapControl/Shared/MapPath.cs b/MapControl/Shared/MapPath.cs index 3038f76a..e6156d41 100644 --- a/MapControl/Shared/MapPath.cs +++ b/MapControl/Shared/MapPath.cs @@ -20,11 +20,9 @@ namespace MapControl { public static readonly DependencyProperty LocationProperty = DependencyProperty.Register( nameof(Location), typeof(Location), typeof(MapPath), - new PropertyMetadata(null, (o, e) => ((MapPath)o).LocationOrViewportChanged())); + new PropertyMetadata(null, (o, e) => ((MapPath)o).UpdateData())); private MapBase parentMap; - private MatrixTransform dataTransform; - private double longitudeOffset; public MapPath() { @@ -61,30 +59,12 @@ namespace MapControl parentMap.ViewportChanged += OnViewportChanged; } - LocationOrViewportChanged(); + UpdateData(); } } private void OnViewportChanged(object sender, ViewportChangedEventArgs e) { - LocationOrViewportChanged(); - } - - private void LocationOrViewportChanged() - { - longitudeOffset = 0d; - - if (parentMap != null && parentMap.MapProjection.IsNormalCylindrical && Location != null) - { - var viewPos = LocationToView(Location); - - if (viewPos.X < 0d || viewPos.X > parentMap.RenderSize.Width || - viewPos.Y < 0d || viewPos.Y > parentMap.RenderSize.Height) - { - longitudeOffset = Location.NearestLongitude(Location.Longitude, parentMap.Center.Longitude) - Location.Longitude; - } - } - UpdateData(); } @@ -92,21 +72,48 @@ namespace MapControl { if (parentMap != null && Data != null && Location != null) { - if (dataTransform == null) + var location = Location; + var viewPos = parentMap.LocationToView(location); + + if (parentMap.MapProjection.IsNormalCylindrical && + (viewPos.X < 0d || viewPos.X > parentMap.RenderSize.Width || + viewPos.Y < 0d || viewPos.Y > parentMap.RenderSize.Height)) { - Data.Transform = dataTransform = new MatrixTransform(); + location = new Location(location.Latitude, parentMap.ConstrainedLongitude(location.Longitude)); + viewPos = parentMap.LocationToView(location); } - var viewPos = LocationToView(Location); - var scale = parentMap.GetScale(Location); + var scale = parentMap.GetScale(location); var transform = new Matrix(scale.X, 0d, 0d, scale.Y, 0d, 0d); + transform.Rotate(parentMap.ViewTransform.Rotation); transform.Translate(viewPos.X, viewPos.Y); - dataTransform.Matrix = transform; + + Data.Transform = new MatrixTransform { Matrix = transform }; } } - protected Point LocationToMap(Location location) + #region Method used only by derived classes MapPolyline, MapPolygon and MapMultiPolygon + + protected double GetLongitudeOffset(Location location) + { + var longitudeOffset = 0d; + + if (location != null && parentMap.MapProjection.IsNormalCylindrical) + { + var viewPos = parentMap.LocationToView(location); + + if (viewPos.X < 0d || viewPos.X > parentMap.RenderSize.Width || + viewPos.Y < 0d || viewPos.Y > parentMap.RenderSize.Height) + { + longitudeOffset = parentMap.ConstrainedLongitude(location.Longitude) - location.Longitude; + } + } + + return longitudeOffset; + } + + protected Point LocationToMap(Location location, double longitudeOffset) { if (longitudeOffset != 0d) { @@ -127,9 +134,11 @@ namespace MapControl return point; } - protected Point LocationToView(Location location) + protected Point LocationToView(Location location, double longitudeOffset) { - return parentMap.ViewTransform.MapToView(LocationToMap(location)); + return parentMap.ViewTransform.MapToView(LocationToMap(location, longitudeOffset)); } + + #endregion } } diff --git a/MapControl/Shared/MapPolygon.cs b/MapControl/Shared/MapPolygon.cs index 06a18eef..eeae14dd 100644 --- a/MapControl/Shared/MapPolygon.cs +++ b/MapControl/Shared/MapPolygon.cs @@ -3,6 +3,7 @@ // Licensed under the Microsoft Public License (Ms-PL) using System.Collections.Generic; +using System.Linq; #if WINDOWS_UWP using Windows.UI.Xaml; using Windows.UI.Xaml.Media; @@ -42,12 +43,14 @@ namespace MapControl protected override void UpdateData() { - var figures = ((PathGeometry)Data).Figures; - figures.Clear(); + var pathFigures = ((PathGeometry)Data).Figures; + pathFigures.Clear(); - if (ParentMap != null) + if (ParentMap != null && Locations != null) { - AddPolylineLocations(figures, Locations, true); + var longitudeOffset = GetLongitudeOffset(Location ?? Locations.FirstOrDefault()); + + AddPolylineLocations(pathFigures, Locations, longitudeOffset, true); } } } diff --git a/MapControl/Shared/MapPolyline.cs b/MapControl/Shared/MapPolyline.cs index a2df81db..a1bbc66d 100644 --- a/MapControl/Shared/MapPolyline.cs +++ b/MapControl/Shared/MapPolyline.cs @@ -3,6 +3,7 @@ // Licensed under the Microsoft Public License (Ms-PL) using System.Collections.Generic; +using System.Linq; #if WINDOWS_UWP using Windows.UI.Xaml; using Windows.UI.Xaml.Media; @@ -42,12 +43,14 @@ namespace MapControl protected override void UpdateData() { - var figures = ((PathGeometry)Data).Figures; - figures.Clear(); + var pathFigures = ((PathGeometry)Data).Figures; + pathFigures.Clear(); - if (ParentMap != null) + if (ParentMap != null && Locations != null) { - AddPolylineLocations(figures, Locations, false); + var longitudeOffset = GetLongitudeOffset(Location ?? Locations.FirstOrDefault()); + + AddPolylineLocations(pathFigures, Locations, longitudeOffset, false); } } } diff --git a/MapControl/UWP/MapPath.UWP.cs b/MapControl/UWP/MapPath.UWP.cs index 1bc3befb..b76a1da4 100644 --- a/MapControl/UWP/MapPath.UWP.cs +++ b/MapControl/UWP/MapPath.UWP.cs @@ -14,10 +14,7 @@ namespace MapControl { public partial class MapPath : Path { - protected void DataCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - UpdateData(); - } + #region Method used only by derived classes MapPolyline and MapPolygon protected void DataCollectionPropertyChanged(DependencyPropertyChangedEventArgs e) { @@ -34,11 +31,17 @@ namespace MapControl UpdateData(); } - protected void AddPolylineLocations(PathFigureCollection figures, IEnumerable locations, bool closed) + protected void DataCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (locations != null && locations.Count() >= 2) + UpdateData(); + } + + protected void AddPolylineLocations(PathFigureCollection pathFigures, IEnumerable locations, double longitudeOffset, bool closed) + { + if (locations.Count() >= 2) { - var points = locations.Select(loc => LocationToView(loc)).ToList(); + var points = locations.Select(location => LocationToView(location, longitudeOffset)).ToList(); + if (closed) { points.Add(points[0]); @@ -67,7 +70,7 @@ namespace MapControl segment = new PolyLineSegment(); figure.Segments.Add(segment); - figures.Add(figure); + pathFigures.Add(figure); } segment.Points.Add(p2); @@ -80,5 +83,7 @@ namespace MapControl } } } + + #endregion } } diff --git a/MapControl/WPF/MapMultiPolygon.WPF.cs b/MapControl/WPF/MapMultiPolygon.WPF.cs index 7292ce87..a3a0ae3c 100644 --- a/MapControl/WPF/MapMultiPolygon.WPF.cs +++ b/MapControl/WPF/MapMultiPolygon.WPF.cs @@ -38,14 +38,16 @@ namespace MapControl protected override void UpdateData() { - var figures = ((PathGeometry)Data).Figures; - figures.Clear(); + var pathFigures = ((PathGeometry)Data).Figures; + pathFigures.Clear(); if (ParentMap != null && Polygons != null) { + var longitudeOffset = GetLongitudeOffset(Location); + foreach (var polygon in Polygons) { - AddPolylineLocations(figures, polygon, true); + AddPolylineLocations(pathFigures, polygon, longitudeOffset, true); } } } diff --git a/MapControl/WPF/MapPath.WPF.cs b/MapControl/WPF/MapPath.WPF.cs index c68ec19c..a2d8f3f6 100644 --- a/MapControl/WPF/MapPath.WPF.cs +++ b/MapControl/WPF/MapPath.WPF.cs @@ -27,11 +27,7 @@ namespace MapControl get { return Data; } } - public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) - { - UpdateData(); - return true; - } + #region Method used only by derived classes MapPolyline, MapPolygon and MapMultiPolygon protected void DataCollectionPropertyChanged(DependencyPropertyChangedEventArgs e) { @@ -48,11 +44,17 @@ namespace MapControl UpdateData(); } - protected void AddPolylineLocations(PathFigureCollection figures, IEnumerable locations, bool closed) + bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) { - if (locations != null && locations.Count() >= 2) + UpdateData(); + return true; + } + + protected void AddPolylineLocations(PathFigureCollection pathFigures, IEnumerable locations, double longitudeOffset, bool closed) + { + if (locations.Count() >= 2) { - var points = locations.Select(loc => LocationToView(loc)); + var points = locations.Select(location => LocationToView(location, longitudeOffset)); var figure = new PathFigure { StartPoint = points.First(), @@ -61,8 +63,10 @@ namespace MapControl }; figure.Segments.Add(new PolyLineSegment(points.Skip(1), true)); - figures.Add(figure); + pathFigures.Add(figure); } } + + #endregion } }