mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 4.6.0: Own Point and Matrix to work around rounding errors in UWP
This commit is contained in:
parent
30a5b6d53f
commit
a3542bf106
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ namespace MapControl
|
|||
public const double Wgs84EquatorialRadius = 6378137d;
|
||||
public const double MetersPerDegree = Wgs84EquatorialRadius * Math.PI / 180d;
|
||||
|
||||
private Matrix inverseViewportTransformMatrix;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the WMS 1.3.0 CRS Identifier.
|
||||
/// </summary>
|
||||
|
|
@ -56,6 +58,11 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public double MaxLatitude { get; protected set; } = 90d;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transformation matrix from cartesian map coordinates to viewport coordinates (pixels).
|
||||
/// </summary>
|
||||
public Matrix ViewportTransformMatrix { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transformation from cartesian map coordinates to viewport coordinates (pixels).
|
||||
/// </summary>
|
||||
|
|
@ -112,7 +119,7 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public Point LocationToViewportPoint(Location location)
|
||||
{
|
||||
return ViewportTransform.Transform(LocationToPoint(location));
|
||||
return ViewportTransformMatrix.Transform(LocationToPoint(location));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -120,7 +127,7 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public Location ViewportPointToLocation(Point point)
|
||||
{
|
||||
return PointToLocation(ViewportTransform.Inverse.Transform(point));
|
||||
return PointToLocation(inverseViewportTransformMatrix.Transform(point));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -128,7 +135,9 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public BoundingBox ViewportRectToBoundingBox(Rect rect)
|
||||
{
|
||||
return RectToBoundingBox(ViewportTransform.Inverse.TransformBounds(rect));
|
||||
var transform = new MatrixTransform { Matrix = inverseViewportTransformMatrix };
|
||||
|
||||
return RectToBoundingBox(transform.TransformBounds(rect));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -153,7 +153,8 @@
|
|||
<Compile Include="MapPolygon.UWP.cs" />
|
||||
<Compile Include="MapPolyline.UWP.cs" />
|
||||
<Compile Include="MapShape.UWP.cs" />
|
||||
<Compile Include="MatrixEx.UWP.cs" />
|
||||
<Compile Include="Matrix.UWP.cs" />
|
||||
<Compile Include="Point.UWP.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Tile.UWP.cs" />
|
||||
<Compile Include="TileImageLoader.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();
|
||||
}
|
||||
|
||||
|
|
|
|||
101
MapControl/UWP/Matrix.UWP.cs
Normal file
101
MapControl/UWP/Matrix.UWP.cs
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used in MapProjection and MapTileLayer.
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
MapControl/UWP/Point.UWP.cs
Normal file
48
MapControl/UWP/Point.UWP.cs
Normal file
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -177,7 +177,6 @@
|
|||
<Compile Include="TileImageLoader.WPF.cs" />
|
||||
<Compile Include="ImageLoader.WPF.cs" />
|
||||
<Compile Include="TypeConverters.WPF.cs" />
|
||||
<Compile Include="MatrixEx.WPF.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used in MapProjection and MapTileLayer.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
<AssemblyName>UniversalApp</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||
<TargetPlatformVersion>10.0.10586.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.10586.0</TargetPlatformMinVersion>
|
||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
<UseDotNetNativeToolchain>false</UseDotNetNativeToolchain>
|
||||
<EnableGatekeeperAnalysis>false</EnableGatekeeperAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.0.1</Version>
|
||||
<Version>6.0.7</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
Loading…
Reference in a new issue