diff --git a/FileDbCache/UWP/Properties/AssemblyInfo.cs b/FileDbCache/UWP/Properties/AssemblyInfo.cs
index d1482c16..a3e202bc 100644
--- a/FileDbCache/UWP/Properties/AssemblyInfo.cs
+++ b/FileDbCache/UWP/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("4.4.0")]
-[assembly: AssemblyFileVersion("4.4.0")]
+[assembly: AssemblyVersion("4.4.1")]
+[assembly: AssemblyFileVersion("4.4.1")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/FileDbCache/WPF/Properties/AssemblyInfo.cs b/FileDbCache/WPF/Properties/AssemblyInfo.cs
index 11d32ffc..930a9109 100644
--- a/FileDbCache/WPF/Properties/AssemblyInfo.cs
+++ b/FileDbCache/WPF/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("4.4.0")]
-[assembly: AssemblyFileVersion("4.4.0")]
+[assembly: AssemblyVersion("4.4.1")]
+[assembly: AssemblyFileVersion("4.4.1")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MBTiles/UWP/Properties/AssemblyInfo.cs b/MBTiles/UWP/Properties/AssemblyInfo.cs
index 9f0caf66..2d008093 100644
--- a/MBTiles/UWP/Properties/AssemblyInfo.cs
+++ b/MBTiles/UWP/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("4.4.0")]
-[assembly: AssemblyFileVersion("4.4.0")]
+[assembly: AssemblyVersion("4.4.1")]
+[assembly: AssemblyFileVersion("4.4.1")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MBTiles/WPF/Properties/AssemblyInfo.cs b/MBTiles/WPF/Properties/AssemblyInfo.cs
index 35124928..99111b66 100644
--- a/MBTiles/WPF/Properties/AssemblyInfo.cs
+++ b/MBTiles/WPF/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("4.4.0")]
-[assembly: AssemblyFileVersion("4.4.0")]
+[assembly: AssemblyVersion("4.4.1")]
+[assembly: AssemblyFileVersion("4.4.1")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MapControl/Shared/Intersections.cs b/MapControl/Shared/Intersections.cs
new file mode 100644
index 00000000..4272fac0
--- /dev/null
+++ b/MapControl/Shared/Intersections.cs
@@ -0,0 +1,105 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2018 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+using System;
+#if WINDOWS_UWP
+using Windows.Foundation;
+#else
+using System.Windows;
+#endif
+
+namespace MapControl
+{
+ public static class Intersections
+ {
+ ///
+ /// Returns the intersection point of two line segments given by (p1,p2) and (p3,p4),
+ /// or null if no intersection exists. See https://stackoverflow.com/a/1968345.
+ ///
+ public static Point? GetIntersection(Point p1, Point p2, Point p3, Point p4)
+ {
+ var x12 = p2.X - p1.X;
+ var y12 = p2.Y - p1.Y;
+ var x34 = p4.X - p3.X;
+ var y34 = p4.Y - p3.Y;
+ var x13 = p3.X - p1.X;
+ var y13 = p3.Y - p1.Y;
+
+ var d = x12 * y34 - x34 * y12;
+ var s = (x13 * y12 - y13 * x12) / d;
+ var t = (x13 * y34 - y13 * x34) / d;
+
+ if (s >= 0d && s <= 1d && t >= 0d && t <= 1d)
+ {
+ return new Point(p1.X + t * x12, p1.Y + t * y12);
+ }
+
+ return null;
+ }
+
+ ///
+ /// Calculates the potential intersections of a line segment given by (p1,p2) with a rectangle.
+ /// Updates either p1, p2, or both with any found intersection and returns a value that indicates
+ /// whether the segment intersects or lies inside the rectangle.
+ ///
+ public static bool GetIntersections(ref Point p1, ref Point p2, Rect rect)
+ {
+ if (rect.Contains(p1) && rect.Contains(p2))
+ {
+ return true;
+ }
+
+ var topLeft = new Point(rect.Left, rect.Top);
+ var topRight = new Point(rect.Right, rect.Top);
+ var bottomLeft = new Point(rect.Left, rect.Bottom);
+ var bottomRight = new Point(rect.Right, rect.Bottom);
+ var numIntersections = 0;
+
+ if (GetIntersection(ref p1, ref p2, topLeft, bottomLeft, p => p.X <= rect.Left)) // left edge
+ {
+ numIntersections++;
+ }
+
+ if (GetIntersection(ref p1, ref p2, topLeft, topRight, p => p.Y <= rect.Top)) // top edge
+ {
+ numIntersections++;
+ }
+
+ if (numIntersections < 2 &&
+ GetIntersection(ref p1, ref p2, topRight, bottomRight, p => p.X >= rect.Right)) // right edge
+ {
+ numIntersections++;
+ }
+
+ if (numIntersections < 2 &&
+ GetIntersection(ref p1, ref p2, bottomLeft, bottomRight, p => p.Y >= rect.Bottom)) // bottom edge
+ {
+ numIntersections++;
+ }
+
+ return numIntersections > 0;
+ }
+
+ private static bool GetIntersection(ref Point p1, ref Point p2, Point p3, Point p4, Func condition)
+ {
+ var intersection = GetIntersection(p1, p2, p3, p4);
+
+ if (!intersection.HasValue)
+ {
+ return false;
+ }
+
+ if (condition(p1))
+ {
+ p1 = intersection.Value;
+ }
+ else
+ {
+ p2 = intersection.Value;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/MapControl/Shared/LocationEx.cs b/MapControl/Shared/LocationEx.cs
new file mode 100644
index 00000000..f340728d
--- /dev/null
+++ b/MapControl/Shared/LocationEx.cs
@@ -0,0 +1,172 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2018 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+using System;
+using System.Linq;
+
+namespace MapControl
+{
+ public static class LocationEx
+ {
+ ///
+ /// see https://en.wikipedia.org/wiki/Great-circle_navigation
+ ///
+ public static double GreatCircleDistance(this Location location1, Location location2, double earthRadius = MapProjection.Wgs84EquatorialRadius)
+ {
+ var lat1 = location1.Latitude * Math.PI / 180d;
+ var lon1 = location1.Longitude * Math.PI / 180d;
+ var lat2 = location2.Latitude * Math.PI / 180d;
+ var lon2 = location2.Longitude * Math.PI / 180d;
+ var cosS12 = Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon2 - lon1);
+
+ return earthRadius * Math.Acos(Math.Min(Math.Max(cosS12, -1d), 1d));
+ }
+
+ public static LocationCollection CalculateMeridianLocations(this Location location, double latitude2, double resolution = 1d)
+ {
+ if (resolution <= 0d)
+ {
+ throw new ArgumentOutOfRangeException("resolution");
+ }
+
+ var locations = new LocationCollection();
+ var s = latitude2 - location.Latitude;
+ var n = (int)Math.Ceiling(Math.Abs(s) / resolution);
+
+ for (int i = 0; i <= n; i++)
+ {
+ locations.Add(new Location(location.Latitude + i * s / n, location.Longitude));
+ }
+
+ return locations;
+ }
+
+ ///
+ /// see https://en.wikipedia.org/wiki/Great-circle_navigation
+ ///
+ public static LocationCollection CalculateGreatCircleLocations(this Location location1, Location location2, double resolution = 1d)
+ {
+ if (resolution <= 0d)
+ {
+ throw new ArgumentOutOfRangeException("resolution");
+ }
+
+ if (location1.Longitude == location2.Longitude ||
+ location1.Latitude <= -90d || location1.Latitude >= 90d ||
+ location2.Latitude <= -90d || location2.Latitude >= 90d)
+ {
+ return CalculateMeridianLocations(location1, location2.Latitude);
+ }
+
+ var locations = new LocationCollection(new Location(location1.Latitude, location1.Longitude));
+
+ var lat1 = location1.Latitude * Math.PI / 180d;
+ var lon1 = location1.Longitude * Math.PI / 180d;
+ var lat2 = location2.Latitude * Math.PI / 180d;
+ var lon2 = location2.Longitude * Math.PI / 180d;
+ var cosLat1 = Math.Cos(lat1);
+ var sinLat1 = Math.Sin(lat1);
+ var cosLat2 = Math.Cos(lat2);
+ var sinLat2 = Math.Sin(lat2);
+ var cosLon12 = Math.Cos(lon2 - lon1);
+ var sinLon12 = Math.Sin(lon2 - lon1);
+
+ var cosS12 = sinLat1 * sinLat2 + cosLat1 * cosLat2 * cosLon12;
+ var s12 = Math.Acos(Math.Min(Math.Max(cosS12, -1d), 1d));
+ var n = (int)Math.Ceiling(s12 / resolution * 180d / Math.PI);
+
+ if (n > 1)
+ {
+ var az1 = Math.Atan2(sinLon12, cosLat1 * sinLat2 / cosLat2 - sinLat1 * cosLon12);
+ var cosAz1 = Math.Cos(az1);
+ var sinAz1 = Math.Sin(az1);
+
+ var az0 = Math.Atan2(sinAz1 * cosLat1, Math.Sqrt(cosAz1 * cosAz1 + sinAz1 * sinAz1 * sinLat1 * sinLat1));
+ var sinAz0 = Math.Sin(az0);
+ var cosAz0 = Math.Cos(az0);
+
+ var s01 = Math.Atan2(sinLat1, cosLat1 * cosAz1);
+ var lon0 = lon1 - Math.Atan2(sinAz0 * Math.Sin(s01), Math.Cos(s01));
+
+ for (int i = 1; i < n; i++)
+ {
+ double s = s01 + i * s12 / n;
+ double sinS = Math.Sin(s);
+ double cosS = Math.Cos(s);
+ double lat = Math.Atan2(cosAz0 * sinS, Math.Sqrt(cosS * cosS + sinAz0 * sinAz0 * sinS * sinS));
+ double lon = Math.Atan2(sinAz0 * sinS, cosS) + lon0;
+
+ locations.Add(lat * 180d / Math.PI, lon * 180d / Math.PI);
+ }
+ }
+
+ locations.Add(location2.Latitude, location2.Longitude);
+ return locations;
+ }
+
+ ///
+ /// see https://en.wikipedia.org/wiki/Rhumb_line
+ ///
+ public static LocationCollection CalculateRhumbLineLocations(this Location location1, Location location2, double resolution = 1d)
+ {
+ if (resolution <= 0d)
+ {
+ throw new ArgumentOutOfRangeException("resolution");
+ }
+
+ var y1 = WebMercatorProjection.LatitudeToY(location1.Latitude);
+
+ if (double.IsInfinity(y1))
+ {
+ throw new ArgumentOutOfRangeException("location1");
+ }
+
+ var y2 = WebMercatorProjection.LatitudeToY(location2.Latitude);
+
+ if (double.IsInfinity(y2))
+ {
+ throw new ArgumentOutOfRangeException("location2");
+ }
+
+ var x1 = location1.Longitude;
+ var x2 = location2.Longitude;
+ var dx = x2 - x1;
+ var dy = y2 - y1;
+ var s = Math.Sqrt(dx * dx + dy * dy);
+ var n = (int)Math.Ceiling(s / resolution);
+
+ var locations = new LocationCollection(new Location(location1.Latitude, location1.Longitude));
+
+ for (int i = 1; i < n; i++)
+ {
+ double x = x1 + i * dx / n;
+ double y = y1 + i * dy / n;
+
+ locations.Add(WebMercatorProjection.YToLatitude(y), x);
+ }
+
+ locations.Add(location2.Latitude, location2.Longitude);
+ return locations;
+ }
+
+ public static void Add(this LocationCollection locations, double latitude, double longitude)
+ {
+ if (locations.Count > 0)
+ {
+ var deltaLon = longitude - locations.Last().Longitude;
+
+ if (deltaLon < -180d)
+ {
+ longitude += 360d;
+ }
+ else if (deltaLon > 180)
+ {
+ longitude -= 360;
+ }
+ }
+
+ locations.Add(new Location(latitude, longitude));
+ }
+ }
+}
diff --git a/MapControl/Shared/MapShape.cs b/MapControl/Shared/MapShape.cs
index cd64abf1..e45d236d 100644
--- a/MapControl/Shared/MapShape.cs
+++ b/MapControl/Shared/MapShape.cs
@@ -32,6 +32,14 @@ namespace MapControl
set { SetValue(LocationProperty, value); }
}
+ private void LocationPropertyChanged()
+ {
+ if (parentMap != null)
+ {
+ OnViewportChanged(parentMap, new ViewportChangedEventArgs());
+ }
+ }
+
private MapBase parentMap;
public MapBase ParentMap
@@ -99,13 +107,5 @@ namespace MapControl
return longitudeOffset;
}
-
- private void LocationPropertyChanged()
- {
- if (parentMap != null)
- {
- OnViewportChanged(parentMap, new ViewportChangedEventArgs());
- }
- }
}
}
diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj
index cf6b0b51..1b1208f2 100644
--- a/MapControl/UWP/MapControl.UWP.csproj
+++ b/MapControl/UWP/MapControl.UWP.csproj
@@ -67,12 +67,18 @@
HyperlinkText.cs
+
+ Intersections.cs
+
Location.cs
LocationCollection.cs
+
+ LocationEx.cs
+
MapBase.cs
@@ -144,6 +150,7 @@
+
diff --git a/MapControl/UWP/MapPolygon.UWP.cs b/MapControl/UWP/MapPolygon.UWP.cs
new file mode 100644
index 00000000..3c4575c3
--- /dev/null
+++ b/MapControl/UWP/MapPolygon.UWP.cs
@@ -0,0 +1,55 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2018 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+using System.Collections.Generic;
+using System.Linq;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+
+namespace MapControl
+{
+ ///
+ /// A polygon defined by a collection of Locations.
+ ///
+ public class MapPolygon : MapShape
+ {
+ public static readonly DependencyProperty LocationsProperty = DependencyProperty.Register(
+ nameof(Locations), typeof(IEnumerable), typeof(MapPolygon),
+ new PropertyMetadata(null, (o, e) => ((MapPolygon)o).LocationsPropertyChanged(e)));
+
+ ///
+ /// Gets or sets the Locations that define the polyline points.
+ ///
+ public IEnumerable Locations
+ {
+ get { return (IEnumerable)GetValue(LocationsProperty); }
+ set { SetValue(LocationsProperty, value); }
+ }
+
+ protected override void UpdateData()
+ {
+ var figures = ((PathGeometry)Data).Figures;
+ figures.Clear();
+
+ if (ParentMap != null && Locations != null)
+ {
+ var locations = Locations;
+ var offset = GetLongitudeOffset();
+
+ if (offset != 0d)
+ {
+ locations = locations.Select(loc => new Location(loc.Latitude, loc.Longitude + offset));
+ }
+
+ var points = locations.Select(loc => ParentMap.MapProjection.LocationToViewportPoint(loc)).ToList();
+
+ if (points.Count >= 2)
+ {
+ points.Add(points[0]);
+ CreatePolylineFigures(points);
+ }
+ }
+ }
+ }
+}
diff --git a/MapControl/UWP/MapPolyline.UWP.cs b/MapControl/UWP/MapPolyline.UWP.cs
index 83e4df6d..c94bab00 100644
--- a/MapControl/UWP/MapPolyline.UWP.cs
+++ b/MapControl/UWP/MapPolyline.UWP.cs
@@ -3,7 +3,6 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System.Collections.Generic;
-using System.Collections.Specialized;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
@@ -30,72 +29,25 @@ namespace MapControl
protected override void UpdateData()
{
- var geometry = (PathGeometry)Data;
- geometry.Figures.Clear();
+ ((PathGeometry)Data).Figures.Clear();
- if (ParentMap != null && Locations != null && Locations.Any())
+ if (ParentMap != null && Locations != null)
{
- PathFigure figure = null;
- PolyLineSegment segment = null;
- var size = ParentMap.RenderSize;
- var offset = GetLongitudeOffset();
var locations = Locations;
+ var offset = GetLongitudeOffset();
if (offset != 0d)
{
locations = locations.Select(loc => new Location(loc.Latitude, loc.Longitude + offset));
}
- var points = locations.Select(loc => ParentMap.MapProjection.LocationToViewportPoint(loc));
- var p1 = points.First();
+ var points = locations.Select(loc => ParentMap.MapProjection.LocationToViewportPoint(loc)).ToList();
- foreach (var p2 in points.Skip(1))
+ if (points.Count >= 2)
{
- if ((p1.X <= 0 && p2.X <= 0) || (p1.X >= size.Width && p2.X >= size.Width) ||
- (p1.Y <= 0 && p2.Y <= 0) || (p1.Y >= size.Height && p2.Y >= size.Height))
- {
- // line (p1,p2) is out of visible bounds, end figure
- figure = null;
- }
- else
- {
- if (figure == null)
- {
- figure = new PathFigure { StartPoint = p1, IsClosed = false, IsFilled = false };
- segment = new PolyLineSegment();
- figure.Segments.Add(segment);
- geometry.Figures.Add(figure);
- }
-
- segment.Points.Add(p2);
- }
-
- p1 = p2;
+ CreatePolylineFigures(points);
}
}
}
-
- private void LocationsPropertyChanged(DependencyPropertyChangedEventArgs e)
- {
- var oldCollection = e.OldValue as INotifyCollectionChanged;
- var newCollection = e.NewValue as INotifyCollectionChanged;
-
- if (oldCollection != null)
- {
- oldCollection.CollectionChanged -= LocationCollectionChanged;
- }
-
- if (newCollection != null)
- {
- newCollection.CollectionChanged += LocationCollectionChanged;
- }
-
- UpdateData();
- }
-
- private void LocationCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- UpdateData();
- }
}
}
diff --git a/MapControl/UWP/MapShape.UWP.cs b/MapControl/UWP/MapShape.UWP.cs
index f1f604ba..42939056 100644
--- a/MapControl/UWP/MapShape.UWP.cs
+++ b/MapControl/UWP/MapShape.UWP.cs
@@ -2,6 +2,11 @@
// © 2018 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Windows.Foundation;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
namespace MapControl
@@ -17,5 +22,62 @@ namespace MapControl
{
UpdateData();
}
+
+ protected void LocationsPropertyChanged(DependencyPropertyChangedEventArgs e)
+ {
+ var oldCollection = e.OldValue as INotifyCollectionChanged;
+ var newCollection = e.NewValue as INotifyCollectionChanged;
+
+ if (oldCollection != null)
+ {
+ oldCollection.CollectionChanged -= LocationCollectionChanged;
+ }
+
+ if (newCollection != null)
+ {
+ newCollection.CollectionChanged += LocationCollectionChanged;
+ }
+
+ UpdateData();
+ }
+
+ protected void LocationCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ UpdateData();
+ }
+
+ protected void CreatePolylineFigures(IList points)
+ {
+ var viewport = new Rect(0, 0, ParentMap.RenderSize.Width, ParentMap.RenderSize.Height);
+ var figures = ((PathGeometry)Data).Figures;
+
+ PathFigure figure = null;
+ PolyLineSegment segment = null;
+
+ for (int i = 1; i < points.Count; i++)
+ {
+ var p1 = points[i - 1];
+ var p2 = points[i];
+ var inside = Intersections.GetIntersections(ref p1, ref p2, viewport);
+
+ if (inside)
+ {
+ if (figure == null)
+ {
+ figure = new PathFigure { StartPoint = p1, IsClosed = false, IsFilled = false };
+ segment = new PolyLineSegment();
+ figure.Segments.Add(segment);
+ figures.Add(figure);
+ }
+
+ segment.Points.Add(p2);
+ }
+
+ if (!inside || p2 != points[i])
+ {
+ figure = null;
+ }
+ }
+ }
}
}
diff --git a/MapControl/UWP/Properties/AssemblyInfo.cs b/MapControl/UWP/Properties/AssemblyInfo.cs
index 3c3e9e03..bb8e6f6f 100644
--- a/MapControl/UWP/Properties/AssemblyInfo.cs
+++ b/MapControl/UWP/Properties/AssemblyInfo.cs
@@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("4.4.0")]
-[assembly: AssemblyFileVersion("4.4.0")]
+[assembly: AssemblyVersion("4.4.1")]
+[assembly: AssemblyFileVersion("4.4.1")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MapControl/WPF/MapControl.WPF.csproj b/MapControl/WPF/MapControl.WPF.csproj
index 9ba7d387..d1eb863f 100644
--- a/MapControl/WPF/MapControl.WPF.csproj
+++ b/MapControl/WPF/MapControl.WPF.csproj
@@ -86,12 +86,18 @@
HyperlinkText.cs
+
+ Intersections.cs
+
Location.cs
LocationCollection.cs
+
+ LocationEx.cs
+
MapBase.cs
diff --git a/MapControl/WPF/MapGraticule.WPF.cs b/MapControl/WPF/MapGraticule.WPF.cs
index 20781e22..1359205f 100644
--- a/MapControl/WPF/MapGraticule.WPF.cs
+++ b/MapControl/WPF/MapGraticule.WPF.cs
@@ -39,62 +39,75 @@ namespace MapControl
{
var projection = ParentMap?.MapProjection;
- if (projection != null && !projection.IsAzimuthal)
+ if (projection != null)
{
- var bounds = projection.ViewportRectToBoundingBox(new Rect(ParentMap.RenderSize));
+ var lineDistance = GetLineDistance();
+ var labelFormat = GetLabelFormat(lineDistance);
- if (bounds.HasValidBounds)
+ if (projection.IsAzimuthal)
{
- var lineDistance = GetLineDistance();
- var labelFormat = GetLabelFormat(lineDistance);
- var latLabelStart = Math.Ceiling(bounds.South / lineDistance) * lineDistance;
- var lonLabelStart = Math.Ceiling(bounds.West / lineDistance) * lineDistance;
- var latLabels = new List