Reworked MapPath and derived classes

This commit is contained in:
ClemensF 2020-05-13 18:17:28 +02:00
parent 414389513e
commit 49d508b3f5
9 changed files with 106 additions and 84 deletions

View file

@ -84,7 +84,7 @@ namespace MapControl
}
/// <summary>
/// Normalizes a longitude to a value in the interval [-180..180].
/// Normalizes a longitude to a value in the interval [-180 .. 180].
/// </summary>
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;
}
}
}

View file

@ -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
};

View file

@ -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);
}

View file

@ -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
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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<Location> locations, bool closed)
protected void DataCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (locations != null && locations.Count() >= 2)
UpdateData();
}
protected void AddPolylineLocations(PathFigureCollection pathFigures, IEnumerable<Location> 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
}
}

View file

@ -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);
}
}
}

View file

@ -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<Location> 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<Location> 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
}
}