diff --git a/FileDbCache/UWP/Properties/AssemblyInfo.cs b/FileDbCache/UWP/Properties/AssemblyInfo.cs
index 1585e4a7..e36cb138 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.5.0")]
-[assembly: AssemblyFileVersion("4.5.0")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/FileDbCache/WPF/Properties/AssemblyInfo.cs b/FileDbCache/WPF/Properties/AssemblyInfo.cs
index 2b6e054a..0e3c8a61 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.5.0")]
-[assembly: AssemblyFileVersion("4.5.0")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MBTiles/UWP/Properties/AssemblyInfo.cs b/MBTiles/UWP/Properties/AssemblyInfo.cs
index 2a504bcc..d474d2eb 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.5.0")]
-[assembly: AssemblyFileVersion("4.5.0")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MBTiles/WPF/Properties/AssemblyInfo.cs b/MBTiles/WPF/Properties/AssemblyInfo.cs
index 87307be1..c14b2b3a 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.5.0")]
-[assembly: AssemblyFileVersion("4.5.0")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MapControl/Shared/AzimuthalEquidistantProjection.cs b/MapControl/Shared/AzimuthalEquidistantProjection.cs
index 7565961c..52016c77 100644
--- a/MapControl/Shared/AzimuthalEquidistantProjection.cs
+++ b/MapControl/Shared/AzimuthalEquidistantProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/Shared/EquirectangularProjection.cs b/MapControl/Shared/EquirectangularProjection.cs
index 42f10cc3..719cb488 100644
--- a/MapControl/Shared/EquirectangularProjection.cs
+++ b/MapControl/Shared/EquirectangularProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/Shared/GnomonicProjection.cs b/MapControl/Shared/GnomonicProjection.cs
index 468f5033..dfdf9b75 100644
--- a/MapControl/Shared/GnomonicProjection.cs
+++ b/MapControl/Shared/GnomonicProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs
index 567766c5..428482fd 100644
--- a/MapControl/Shared/MapBase.cs
+++ b/MapControl/Shared/MapBase.cs
@@ -4,7 +4,6 @@
using System;
#if WINDOWS_UWP
-using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
diff --git a/MapControl/Shared/MapPanel.cs b/MapControl/Shared/MapPanel.cs
index a7b1878b..dc3b36df 100644
--- a/MapControl/Shared/MapPanel.cs
+++ b/MapControl/Shared/MapPanel.cs
@@ -261,7 +261,7 @@ namespace MapControl
var center = new Point(rect.X + rect.Width / 2d, rect.Y + rect.Height / 2d);
rotation = parentMap.Heading;
- viewportPosition = projection.ViewportTransform.Transform(center);
+ viewportPosition = projection.ViewportTransformMatrix.Transform(center);
if (parentMap.MapProjection.IsContinuous &&
(viewportPosition.X < 0d || viewportPosition.X > parentMap.RenderSize.Width ||
diff --git a/MapControl/Shared/MapProjection.cs b/MapControl/Shared/MapProjection.cs
index fbdd92f0..84660786 100644
--- a/MapControl/Shared/MapProjection.cs
+++ b/MapControl/Shared/MapProjection.cs
@@ -25,6 +25,8 @@ namespace MapControl
public const double Wgs84EquatorialRadius = 6378137d;
public const double MetersPerDegree = Wgs84EquatorialRadius * Math.PI / 180d;
+ private Matrix inverseViewportTransformMatrix;
+
///
/// Gets or sets the WMS 1.3.0 CRS Identifier.
///
@@ -56,6 +58,11 @@ namespace MapControl
///
public double MaxLatitude { get; protected set; } = 90d;
+ ///
+ /// Gets the transformation matrix from cartesian map coordinates to viewport coordinates (pixels).
+ ///
+ public Matrix ViewportTransformMatrix { get; private set; }
+
///
/// Gets the transformation from cartesian map coordinates to viewport coordinates (pixels).
///
@@ -112,7 +119,7 @@ namespace MapControl
///
public Point LocationToViewportPoint(Location location)
{
- return ViewportTransform.Transform(LocationToPoint(location));
+ return ViewportTransformMatrix.Transform(LocationToPoint(location));
}
///
@@ -120,7 +127,7 @@ namespace MapControl
///
public Location ViewportPointToLocation(Point point)
{
- return PointToLocation(ViewportTransform.Inverse.Transform(point));
+ return PointToLocation(inverseViewportTransformMatrix.Transform(point));
}
///
@@ -128,7 +135,9 @@ namespace MapControl
///
public BoundingBox ViewportRectToBoundingBox(Rect rect)
{
- return RectToBoundingBox(ViewportTransform.Inverse.TransformBounds(rect));
+ var transform = new MatrixTransform { Matrix = inverseViewportTransformMatrix };
+
+ return RectToBoundingBox(transform.TransformBounds(rect));
}
///
@@ -139,9 +148,14 @@ namespace MapControl
ViewportScale = Math.Pow(2d, zoomLevel) * PixelPerDegree / TrueScale;
var center = LocationToPoint(mapCenter);
-
- ViewportTransform.Matrix = MatrixEx.TranslateScaleRotateTranslate(
+ var transformMatrix = CreateTransformMatrix(
-center.X, -center.Y, ViewportScale, -ViewportScale, heading, viewportCenter.X, viewportCenter.Y);
+
+ ViewportTransformMatrix = transformMatrix;
+ ViewportTransform.Matrix = transformMatrix;
+
+ transformMatrix.Invert();
+ inverseViewportTransformMatrix = transformMatrix;
}
///
@@ -173,5 +187,17 @@ namespace MapControl
return string.Format(CultureInfo.InvariantCulture, format, CrsId,
rect.X, rect.Y, (rect.X + rect.Width), (rect.Y + rect.Height), width, height);
}
+
+ public static Matrix CreateTransformMatrix(
+ double translation1X, double translation1Y,
+ double scaleX, double scaleY, double rotationAngle,
+ double translation2X, double translation2Y)
+ {
+ var matrix = new Matrix(1d, 0d, 0d, 1d, translation1X, translation1Y);
+ matrix.Scale(scaleX, scaleY);
+ matrix.Rotate(rotationAngle);
+ matrix.Translate(translation2X, translation2Y);
+ return matrix;
+ }
}
}
diff --git a/MapControl/Shared/MapShape.cs b/MapControl/Shared/MapShape.cs
index 4b9d5147..467ac2ac 100644
--- a/MapControl/Shared/MapShape.cs
+++ b/MapControl/Shared/MapShape.cs
@@ -3,7 +3,6 @@
// Licensed under the Microsoft Public License (Ms-PL)
#if WINDOWS_UWP
-using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
#else
@@ -98,7 +97,7 @@ namespace MapControl
protected Point LocationToViewportPoint(Location location)
{
- return parentMap.MapProjection.ViewportTransform.Transform(LocationToPoint(location));
+ return parentMap.MapProjection.ViewportTransformMatrix.Transform(LocationToPoint(location));
}
protected double GetLongitudeOffset()
diff --git a/MapControl/Shared/MapTileLayer.cs b/MapControl/Shared/MapTileLayer.cs
index 3238ad1d..2e585075 100644
--- a/MapControl/Shared/MapTileLayer.cs
+++ b/MapControl/Shared/MapTileLayer.cs
@@ -312,7 +312,7 @@ namespace MapControl
var transform = new MatrixTransform
{
- Matrix = MatrixEx.TranslateScaleRotateTranslate(-viewCenterX, -viewCenterY, scale, scale, -parentMap.Heading, tileCenterX, tileCenterY)
+ Matrix = MapProjection.CreateTransformMatrix(-viewCenterX, -viewCenterY, scale, scale, -parentMap.Heading, tileCenterX, tileCenterY)
};
var bounds = transform.TransformBounds(new Rect(0d, 0d, parentMap.RenderSize.Width, parentMap.RenderSize.Height));
@@ -333,7 +333,7 @@ namespace MapControl
var viewCenterX = parentMap.RenderSize.Width / 2d;
var viewCenterY = parentMap.RenderSize.Height / 2d;
- ((MatrixTransform)RenderTransform).Matrix = MatrixEx.TranslateScaleRotateTranslate(
+ ((MatrixTransform)RenderTransform).Matrix = MapProjection.CreateTransformMatrix(
-tileOriginX, -tileOriginY, scale, scale, parentMap.Heading, viewCenterX, viewCenterY);
}
diff --git a/MapControl/Shared/OrthographicProjection.cs b/MapControl/Shared/OrthographicProjection.cs
index d650d6b1..04c52aa8 100644
--- a/MapControl/Shared/OrthographicProjection.cs
+++ b/MapControl/Shared/OrthographicProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/Shared/StereographicProjection.cs b/MapControl/Shared/StereographicProjection.cs
index 9abb283b..e77ed078 100644
--- a/MapControl/Shared/StereographicProjection.cs
+++ b/MapControl/Shared/StereographicProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/Shared/WebMercatorProjection.cs b/MapControl/Shared/WebMercatorProjection.cs
index 094ff2de..ea950b05 100644
--- a/MapControl/Shared/WebMercatorProjection.cs
+++ b/MapControl/Shared/WebMercatorProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/Shared/WorldMercatorProjection.cs b/MapControl/Shared/WorldMercatorProjection.cs
index 72dae059..7d1085e3 100644
--- a/MapControl/Shared/WorldMercatorProjection.cs
+++ b/MapControl/Shared/WorldMercatorProjection.cs
@@ -3,9 +3,7 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-#if WINDOWS_UWP
-using Windows.Foundation;
-#else
+#if !WINDOWS_UWP
using System.Windows;
#endif
diff --git a/MapControl/UWP/Extensions.UWP.cs b/MapControl/UWP/Extensions.UWP.cs
index 1783309a..c60240f5 100644
--- a/MapControl/UWP/Extensions.UWP.cs
+++ b/MapControl/UWP/Extensions.UWP.cs
@@ -2,20 +2,13 @@
// © 2018 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
-using Windows.Foundation;
using Windows.UI.Xaml;
-using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
namespace MapControl
{
internal static class Extensions
{
- public static Point Transform(this GeneralTransform transform, Point point)
- {
- return transform.TransformPoint(point);
- }
-
public static void BeginAnimation(this DependencyObject obj, DependencyProperty property, Timeline animation)
{
if (animation != null)
diff --git a/MapControl/UWP/Map.UWP.cs b/MapControl/UWP/Map.UWP.cs
index 6e725894..e9a11915 100644
--- a/MapControl/UWP/Map.UWP.cs
+++ b/MapControl/UWP/Map.UWP.cs
@@ -3,7 +3,6 @@
// Licensed under the Microsoft Public License (Ms-PL)
using System;
-using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Input;
diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj
index 1c20e261..56e189c2 100644
--- a/MapControl/UWP/MapControl.UWP.csproj
+++ b/MapControl/UWP/MapControl.UWP.csproj
@@ -153,7 +153,8 @@
-
+
+
diff --git a/MapControl/UWP/MapGraticule.UWP.cs b/MapControl/UWP/MapGraticule.UWP.cs
index d4621b4e..d1ed0f42 100644
--- a/MapControl/UWP/MapGraticule.UWP.cs
+++ b/MapControl/UWP/MapGraticule.UWP.cs
@@ -15,8 +15,6 @@ namespace MapControl
public partial class MapGraticule
{
private Path path;
- private Location graticuleStart;
- private Location graticuleEnd;
public MapGraticule()
{
@@ -75,104 +73,97 @@ namespace MapControl
Math.Min(Math.Max(labelEnd.Latitude + lineDistance, -projection.MaxLatitude), projection.MaxLatitude),
labelEnd.Longitude + lineDistance);
- if (!lineStart.Equals(graticuleStart) || !lineEnd.Equals(graticuleEnd))
+ var geometry = (PathGeometry)path.Data;
+ geometry.Figures.Clear();
+
+ for (var lat = labelStart.Latitude; lat <= bounds.North; lat += lineDistance)
{
- graticuleStart = lineStart;
- graticuleEnd = lineEnd;
-
- var geometry = (PathGeometry)path.Data;
- geometry.Figures.Clear();
- geometry.Transform = projection.ViewportTransform;
-
- for (var lat = labelStart.Latitude; lat <= bounds.North; lat += lineDistance)
+ var figure = new PathFigure
{
- var figure = new PathFigure
- {
- StartPoint = projection.LocationToPoint(new Location(lat, lineStart.Longitude)),
- IsClosed = false,
- IsFilled = false
- };
+ StartPoint = projection.LocationToViewportPoint(new Location(lat, lineStart.Longitude)),
+ IsClosed = false,
+ IsFilled = false
+ };
- figure.Segments.Add(new LineSegment
- {
- Point = projection.LocationToPoint(new Location(lat, lineEnd.Longitude)),
- });
+ figure.Segments.Add(new LineSegment
+ {
+ Point = projection.LocationToViewportPoint(new Location(lat, lineEnd.Longitude))
+ });
- geometry.Figures.Add(figure);
- }
+ geometry.Figures.Add(figure);
+ }
+ for (var lon = labelStart.Longitude; lon <= bounds.East; lon += lineDistance)
+ {
+ var figure = new PathFigure
+ {
+ StartPoint = projection.LocationToViewportPoint(new Location(lineStart.Latitude, lon)),
+ IsClosed = false,
+ IsFilled = false
+ };
+
+ figure.Segments.Add(new LineSegment
+ {
+ Point = projection.LocationToViewportPoint(new Location(lineEnd.Latitude, lon))
+ });
+
+ geometry.Figures.Add(figure);
+ }
+
+ var labelFormat = GetLabelFormat(lineDistance);
+ var childIndex = 1; // 0 for Path
+
+ for (var lat = labelStart.Latitude; lat <= bounds.North; lat += lineDistance)
+ {
for (var lon = labelStart.Longitude; lon <= bounds.East; lon += lineDistance)
{
- var figure = new PathFigure
+ TextBlock label;
+
+ if (childIndex < Children.Count)
{
- StartPoint = projection.LocationToPoint(new Location(lineStart.Latitude, lon)),
- IsClosed = false,
- IsFilled = false
- };
-
- figure.Segments.Add(new LineSegment
- {
- Point = projection.LocationToPoint(new Location(lineEnd.Latitude, lon)),
- });
-
- geometry.Figures.Add(figure);
- }
-
- var labelFormat = GetLabelFormat(lineDistance);
- var childIndex = 1; // 0 for Path
-
- for (var lat = labelStart.Latitude; lat <= bounds.North; lat += lineDistance)
- {
- for (var lon = labelStart.Longitude; lon <= bounds.East; lon += lineDistance)
- {
- TextBlock label;
-
- if (childIndex < Children.Count)
- {
- label = (TextBlock)Children[childIndex];
- }
- else
- {
- var renderTransform = new TransformGroup();
- renderTransform.Children.Add(new TranslateTransform());
- renderTransform.Children.Add(ParentMap.RotateTransform);
- renderTransform.Children.Add(new TranslateTransform());
-
- label = new TextBlock
- {
- RenderTransform = renderTransform
- };
-
- label.SetBinding(TextBlock.ForegroundProperty,
- GetBindingExpression(ForegroundProperty)?.ParentBinding ??
- new Binding
- {
- Source = this,
- Path = new PropertyPath("Foreground")
- });
-
- Children.Add(label);
- }
-
- childIndex++;
-
- if (FontFamily != null)
- {
- label.FontFamily = FontFamily;
- }
-
- label.FontSize = FontSize;
- label.FontStyle = FontStyle;
- label.FontStretch = FontStretch;
- label.FontWeight = FontWeight;
- label.Text = GetLabelText(lat, labelFormat, "NS") + "\n" + GetLabelText(Location.NormalizeLongitude(lon), labelFormat, "EW");
- label.Tag = new Location(lat, lon);
- label.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
-
- var translateTransform = (TranslateTransform)((TransformGroup)label.RenderTransform).Children[0];
- translateTransform.X = StrokeThickness / 2d + 2d;
- translateTransform.Y = -label.DesiredSize.Height / 2d;
+ label = (TextBlock)Children[childIndex];
}
+ else
+ {
+ var renderTransform = new TransformGroup();
+ renderTransform.Children.Add(new TranslateTransform());
+ renderTransform.Children.Add(ParentMap.RotateTransform);
+ renderTransform.Children.Add(new TranslateTransform());
+
+ label = new TextBlock
+ {
+ RenderTransform = renderTransform
+ };
+
+ label.SetBinding(TextBlock.ForegroundProperty,
+ GetBindingExpression(ForegroundProperty)?.ParentBinding ??
+ new Binding
+ {
+ Source = this,
+ Path = new PropertyPath("Foreground")
+ });
+
+ Children.Add(label);
+ }
+
+ childIndex++;
+
+ if (FontFamily != null)
+ {
+ label.FontFamily = FontFamily;
+ }
+
+ label.FontSize = FontSize;
+ label.FontStyle = FontStyle;
+ label.FontStretch = FontStretch;
+ label.FontWeight = FontWeight;
+ label.Text = GetLabelText(lat, labelFormat, "NS") + "\n" + GetLabelText(Location.NormalizeLongitude(lon), labelFormat, "EW");
+ label.Tag = new Location(lat, lon);
+ label.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+
+ var translateTransform = (TranslateTransform)((TransformGroup)label.RenderTransform).Children[0];
+ translateTransform.X = StrokeThickness / 2d + 2d;
+ translateTransform.Y = -label.DesiredSize.Height / 2d;
}
while (Children.Count > childIndex)
@@ -196,9 +187,6 @@ namespace MapControl
else if (path != null)
{
path = null;
- graticuleStart = null;
- graticuleEnd = null;
-
Children.Clear();
}
diff --git a/MapControl/UWP/Matrix.UWP.cs b/MapControl/UWP/Matrix.UWP.cs
new file mode 100644
index 00000000..27484b15
--- /dev/null
+++ b/MapControl/UWP/Matrix.UWP.cs
@@ -0,0 +1,101 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2018 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+using System;
+
+namespace MapControl
+{
+ public struct Matrix
+ {
+ public double M11 { get; set; }
+ public double M12 { get; set; }
+ public double M21 { get; set; }
+ public double M22 { get; set; }
+ public double OffsetX { get; set; }
+ public double OffsetY { get; set; }
+
+ public static implicit operator Windows.UI.Xaml.Media.Matrix(Matrix m)
+ {
+ return new Windows.UI.Xaml.Media.Matrix(m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY);
+ }
+
+ public Matrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
+ {
+ M11 = m11;
+ M12 = m12;
+ M21 = m21;
+ M22 = m22;
+ OffsetX = offsetX;
+ OffsetY = offsetY;
+ }
+
+ public Point Transform(Point p)
+ {
+ return new Point(M11 * p.X + M12 * p.Y + OffsetX, M21 * p.X + M22 * p.Y + OffsetY);
+ }
+
+ public void Translate(double x, double y)
+ {
+ OffsetX += x;
+ OffsetY += y;
+ }
+
+ public void Scale(double scaleX, double scaleY)
+ {
+ if (M12 != 0d || M21 != 0d)
+ {
+ throw new NotSupportedException("Scale not supported for rotated Matrix");
+ }
+
+ SetMatrix(scaleX * M11, 0d, 0d, scaleY * M22, scaleX * OffsetX, scaleY * OffsetY);
+ }
+
+ public void Rotate(double angle)
+ {
+ angle = (angle % 360d) / 180d * Math.PI;
+
+ if (angle != 0d)
+ {
+ var cos = Math.Cos(angle);
+ var sin = Math.Sin(angle);
+
+ SetMatrix(
+ cos * M11 - sin * M12,
+ sin * M11 + cos * M12,
+ cos * M21 - sin * M22,
+ sin * M21 + cos * M22,
+ cos * OffsetX - sin * OffsetY,
+ sin * OffsetX + cos * OffsetY);
+ }
+ }
+
+ public void Invert()
+ {
+ var invDet = 1d / (M11 * M22 - M12 * M21);
+
+ if (double.IsInfinity(invDet))
+ {
+ throw new InvalidOperationException("Matrix is not invertible");
+ }
+
+ SetMatrix(
+ invDet * M22,
+ invDet * -M12,
+ invDet * -M21,
+ invDet * M11,
+ invDet * (M21 * OffsetY - M22 * OffsetX),
+ invDet * (M12 * OffsetX - M11 * OffsetY));
+ }
+
+ private void SetMatrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
+ {
+ M11 = m11;
+ M12 = m12;
+ M21 = m21;
+ M22 = m22;
+ OffsetX = offsetX;
+ OffsetY = offsetY;
+ }
+ }
+}
diff --git a/MapControl/UWP/MatrixEx.UWP.cs b/MapControl/UWP/MatrixEx.UWP.cs
deleted file mode 100644
index 4f0a2ca0..00000000
--- a/MapControl/UWP/MatrixEx.UWP.cs
+++ /dev/null
@@ -1,87 +0,0 @@
-// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
-// © 2018 Clemens Fischer
-// Licensed under the Microsoft Public License (Ms-PL)
-
-using System;
-using Windows.UI.Xaml.Media;
-
-namespace MapControl
-{
- internal static class MatrixEx
- {
- ///
- /// Used in MapProjection and MapTileLayer.
- ///
- public static Matrix TranslateScaleRotateTranslate(
- double translation1X, double translation1Y,
- double scaleX, double scaleY, double rotationAngle,
- double translation2X, double translation2Y)
- {
- var matrix = new Matrix(
- scaleX, 0d, 0d, scaleY,
- scaleX * translation1X,
- scaleY * translation1Y);
-
- if (rotationAngle != 0d)
- {
- rotationAngle = (rotationAngle % 360d) / 180d * Math.PI;
-
- var cos = Math.Cos(rotationAngle);
- var sin = Math.Sin(rotationAngle);
-
- matrix = new Matrix(
- matrix.M11 * cos - matrix.M12 * sin,
- matrix.M11 * sin + matrix.M12 * cos,
- matrix.M21 * cos - matrix.M22 * sin,
- matrix.M21 * sin + matrix.M22 * cos,
- cos * matrix.OffsetX - sin * matrix.OffsetY,
- sin * matrix.OffsetX + cos * matrix.OffsetY);
- }
-
- matrix.OffsetX += translation2X;
- matrix.OffsetY += translation2Y;
-
- return matrix;
- }
-
- public static Matrix TranslateScaleRotateTranslate_(
- double translation1X, double translation1Y,
- double scaleX, double scaleY, double rotationAngle,
- double translation2X, double translation2Y)
- {
- var m11 = scaleX;
- var m12 = 0d;
- var m21 = 0d;
- var m22 = scaleY;
- var offsetX = scaleX * translation1X;
- var offsetY = scaleY * translation1Y;
-
- if (rotationAngle != 0d)
- {
- rotationAngle = (rotationAngle % 360d) / 180d * Math.PI;
-
- var cos = Math.Cos(rotationAngle);
- var sin = Math.Sin(rotationAngle);
-
- var _m11 = m11;
- var _m12 = m12;
- var _m21 = m21;
- var _m22 = m22;
- var _offsetX = offsetX;
- var _offsetY = offsetY;
-
- m11 = _m11 * cos - _m12 * sin;
- m12 = _m11 * sin + _m12 * cos;
- m21 = _m21 * cos - _m22 * sin;
- m22 = _m21 * sin + _m22 * cos;
- offsetX = cos * _offsetX - sin * _offsetY;
- offsetY = sin * _offsetX + cos * _offsetY;
- }
-
- offsetX += translation2X;
- offsetY += translation2Y;
-
- return new Matrix(m11, m12, m21, m22, offsetX, offsetY);
- }
- }
-}
diff --git a/MapControl/UWP/Point.UWP.cs b/MapControl/UWP/Point.UWP.cs
new file mode 100644
index 00000000..833c592f
--- /dev/null
+++ b/MapControl/UWP/Point.UWP.cs
@@ -0,0 +1,48 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2018 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+namespace MapControl
+{
+ public struct Point
+ {
+ public double X { get; set; }
+ public double Y { get; set; }
+
+ public Point(double x, double y)
+ {
+ X = x;
+ Y = y;
+ }
+
+ public static implicit operator Point(Windows.Foundation.Point p)
+ {
+ return new Point(p.X, p.Y);
+ }
+
+ public static implicit operator Windows.Foundation.Point(Point p)
+ {
+ return new Windows.Foundation.Point(p.X, p.Y);
+ }
+
+ public static bool operator ==(Point p1, Point p2)
+ {
+ return p1.X == p2.X && p1.Y == p2.Y;
+ }
+
+ public static bool operator !=(Point p1, Point p2)
+ {
+ return !(p1 == p2);
+ }
+
+ public override bool Equals(object o)
+ {
+ return o is Point && this == (Point)o;
+ }
+
+ public override int GetHashCode()
+ {
+ return X.GetHashCode() ^ Y.GetHashCode();
+ }
+ }
+}
diff --git a/MapControl/UWP/Properties/AssemblyInfo.cs b/MapControl/UWP/Properties/AssemblyInfo.cs
index 5979b0e5..e04f14c4 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.5.0")]
-[assembly: AssemblyFileVersion("4.5.0")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/MapControl/WPF/MapControl.WPF.csproj b/MapControl/WPF/MapControl.WPF.csproj
index d1eb863f..1b838a51 100644
--- a/MapControl/WPF/MapControl.WPF.csproj
+++ b/MapControl/WPF/MapControl.WPF.csproj
@@ -177,7 +177,6 @@
-
Code
diff --git a/MapControl/WPF/MatrixEx.WPF.cs b/MapControl/WPF/MatrixEx.WPF.cs
deleted file mode 100644
index 3998b222..00000000
--- a/MapControl/WPF/MatrixEx.WPF.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
-// © 2018 Clemens Fischer
-// Licensed under the Microsoft Public License (Ms-PL)
-
-using System.Windows.Media;
-
-namespace MapControl
-{
- internal static class MatrixEx
- {
- ///
- /// Used in MapProjection and MapTileLayer.
- ///
- public static Matrix TranslateScaleRotateTranslate(
- double translation1X, double translation1Y,
- double scaleX, double scaleY, double rotationAngle,
- double translation2X, double translation2Y)
- {
- var matrix = new Matrix(1d, 0d, 0d, 1d, translation1X, translation1Y);
- matrix.Scale(scaleX, scaleY);
- matrix.Rotate(rotationAngle);
- matrix.Translate(translation2X, translation2Y);
- return matrix;
- }
- }
-}
diff --git a/MapControl/WPF/Properties/AssemblyInfo.cs b/MapControl/WPF/Properties/AssemblyInfo.cs
index 4991c358..3b9f196d 100644
--- a/MapControl/WPF/Properties/AssemblyInfo.cs
+++ b/MapControl/WPF/Properties/AssemblyInfo.cs
@@ -8,8 +8,8 @@ using System.Windows;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("4.5.0")]
-[assembly: AssemblyFileVersion("4.5.0")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
diff --git a/SampleApps/UniversalApp/Properties/AssemblyInfo.cs b/SampleApps/UniversalApp/Properties/AssemblyInfo.cs
index 520ebe65..9fb632a8 100644
--- a/SampleApps/UniversalApp/Properties/AssemblyInfo.cs
+++ b/SampleApps/UniversalApp/Properties/AssemblyInfo.cs
@@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("© 2018 Clemens Fischer")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
-[assembly: AssemblyVersion("4.4.1")]
-[assembly: AssemblyFileVersion("4.4.1")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: ComVisible(false)]
diff --git a/SampleApps/UniversalApp/UniversalApp.csproj b/SampleApps/UniversalApp/UniversalApp.csproj
index 078a78d5..c4069022 100644
--- a/SampleApps/UniversalApp/UniversalApp.csproj
+++ b/SampleApps/UniversalApp/UniversalApp.csproj
@@ -11,8 +11,8 @@
UniversalApp
en-US
UAP
- 10.0.10240.0
- 10.0.10240.0
+ 10.0.10586.0
+ 10.0.10586.0
14
true
512
@@ -70,7 +70,7 @@
false
prompt
true
- true
+ false
false
@@ -156,7 +156,7 @@
- 6.0.1
+ 6.0.7
diff --git a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
index c7f92947..787e542a 100644
--- a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
+++ b/SampleApps/WpfApplication/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.1")]
-[assembly: AssemblyFileVersion("4.4.1")]
+[assembly: AssemblyVersion("4.6.0")]
+[assembly: AssemblyFileVersion("4.6.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]