diff --git a/MapControl/Avalonia/MapBase.Avalonia.cs b/MapControl/Avalonia/MapBase.Avalonia.cs index 1cbdc425..a99c9ff6 100644 --- a/MapControl/Avalonia/MapBase.Avalonia.cs +++ b/MapControl/Avalonia/MapBase.Avalonia.cs @@ -7,7 +7,6 @@ using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Controls; using Avalonia.Styling; -using System; using System.Threading; using System.Threading.Tasks; @@ -36,7 +35,7 @@ namespace MapControl public static readonly StyledProperty MaxZoomLevelProperty = DependencyPropertyHelper.Register(nameof(MaxZoomLevel), 20d, false, (map, oldValue, newValue) => map.MaxZoomLevelPropertyChanged(newValue), - (map, value) => map.CoerceMinZoomLevelProperty(value)); + (map, value) => map.CoerceMaxZoomLevelProperty(value)); public static readonly StyledProperty ZoomLevelProperty = DependencyPropertyHelper.Register(nameof(ZoomLevel), 1d, true, @@ -106,24 +105,8 @@ namespace MapControl /// public double ViewScale { - get => ViewTransform.Scale; - } - - private void SetViewScale(double viewScale) - { - RaisePropertyChanged(ViewScaleProperty, double.NaN, viewScale); - } - - /// - /// Gets a transform Matrix for scaling and rotating objects that are anchored - /// at a Location from map coordinates (i.e. meters) to view coordinates. - /// - public Matrix GetMapTransform(Location location) - { - var scale = GetScale(location); - - return Matrix.CreateScale(scale.X, scale.Y) - * Matrix.CreateRotation(ViewTransform.Rotation * Math.PI / 180d); + get => (double)GetValue(ViewScaleProperty); + private set => RaisePropertyChanged(ViewScaleProperty, double.NaN, value); } private void CenterPropertyChanged(Location center) diff --git a/MapControl/Avalonia/ViewTransform.Avalonia.cs b/MapControl/Avalonia/ViewTransform.Avalonia.cs index c4d2e5a6..6665d259 100644 --- a/MapControl/Avalonia/ViewTransform.Avalonia.cs +++ b/MapControl/Avalonia/ViewTransform.Avalonia.cs @@ -43,6 +43,25 @@ namespace MapControl /// public Matrix ViewToMapMatrix { get; private set; } + /// + /// Initializes a ViewTransform from a map center point in projected coordinates, + /// a view conter point, a scaling factor from projected coordinates to view coordinates + /// and a rotation angle in degrees. + /// + public void SetTransform(Point mapCenter, Point viewCenter, double scale, double rotation) + { + Scale = scale; + Rotation = ((rotation % 360d) + 360d) % 360d; + + MapToViewMatrix + = Matrix.CreateTranslation(-mapCenter.X, -mapCenter.Y) + * Matrix.CreateScale(scale, -scale) + * Matrix.CreateRotation(Rotation * Math.PI / 180d) + * Matrix.CreateTranslation(viewCenter.X, viewCenter.Y); + + ViewToMapMatrix = MapToViewMatrix.Invert(); + } + /// /// Transforms a Point from projected map coordinates to view coordinates. /// @@ -59,20 +78,29 @@ namespace MapControl return ViewToMapMatrix.Transform(point); } - public void SetTransform(Point mapCenter, Point viewCenter, double scale, double rotation) + /// + /// Transform relative to absolute map scale. Returns horizontal and vertical + /// scaling factors from meters to view coordinates. + /// + public Point GetMapScale(Point relativeScale) { - Scale = scale; - Rotation = ((rotation % 360d) + 360d) % 360d; - - MapToViewMatrix - = Matrix.CreateTranslation(-mapCenter.X, -mapCenter.Y) - * Matrix.CreateScale(scale, -scale) - * Matrix.CreateRotation(Rotation * Math.PI / 180d) - * Matrix.CreateTranslation(viewCenter.X, viewCenter.Y); - - ViewToMapMatrix = MapToViewMatrix.Invert(); + return new Point(Scale * relativeScale.X, Scale * relativeScale.Y); } + /// + /// Gets a transform Matrix from meters to view coordinates for a relative map scale. + /// + public Matrix GetMapTransform(Point relativeScale) + { + var scale = GetMapScale(relativeScale); + + return Matrix.CreateScale(scale.X, scale.Y) + * Matrix.CreateRotation(Rotation * Math.PI / 180d); + } + + /// + /// Gets the transform Matrix for the RenderTranform of a MapTileLayer. + /// public Matrix GetTileLayerTransform(double tileMatrixScale, Point tileMatrixTopLeft, Point tileMatrixOrigin) { // Tile matrix origin in map coordinates. @@ -92,6 +120,9 @@ namespace MapControl * Matrix.CreateTranslation(viewOrigin.X, viewOrigin.Y); } + /// + /// Gets the index bounds of a tile matrix. + /// public Rect GetTileMatrixBounds(double tileMatrixScale, Point tileMatrixTopLeft, Size viewSize) { // View origin in map coordinates. @@ -114,5 +145,15 @@ namespace MapControl // return new Rect(0d, 0d, viewSize.Width, viewSize.Height).TransformToAABB(transform); } + + internal static Matrix CreateTransformMatrix( + double translation1X, double translation1Y, + double rotation, + double translation2X, double translation2Y) + { + return Matrix.CreateTranslation(translation1X, translation1Y) + * Matrix.CreateRotation(rotation * Math.PI / 180d) + * Matrix.CreateTranslation(translation2X, translation2Y); + } } } diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs index a33980f4..26a33048 100644 --- a/MapControl/Shared/MapBase.cs +++ b/MapControl/Shared/MapBase.cs @@ -198,14 +198,21 @@ namespace MapControl public ViewTransform ViewTransform { get; } = new ViewTransform(); /// - /// Gets the map scale as the horizontal and vertical scaling factors from geographic - /// coordinates to view coordinates at the specified location, as pixels per meter. + /// Gets the map scale as horizontal and vertical scaling factors from meters to + /// view coordinates at the specified location. /// public Point GetScale(Location location) { - var relativeScale = MapProjection.GetRelativeScale(location); + return ViewTransform.GetMapScale(MapProjection.GetRelativeScale(location)); + } - return new Point(ViewTransform.Scale * relativeScale.X, ViewTransform.Scale * relativeScale.Y); + /// + /// Gets a transform Matrix from meters to view coordinates for scaling and rotating + /// objects that are anchored at a Location. + /// + public Matrix GetMapTransform(Location location) + { + return ViewTransform.GetMapTransform(MapProjection.GetRelativeScale(location)); } /// @@ -554,7 +561,7 @@ namespace MapControl } } - SetViewScale(ViewTransform.Scale); + ViewScale = ViewTransform.Scale; // Check if view center has moved across 180° longitude. // diff --git a/MapControl/Shared/ViewTransform.cs b/MapControl/Shared/ViewTransform.cs index 9abeba3a..9025a794 100644 --- a/MapControl/Shared/ViewTransform.cs +++ b/MapControl/Shared/ViewTransform.cs @@ -54,21 +54,10 @@ namespace MapControl public Matrix ViewToMapMatrix { get; private set; } /// - /// Transforms a Point from projected map coordinates to view coordinates. + /// Initializes a ViewTransform from a map center point in projected coordinates, + /// a view conter point, a scaling factor from projected coordinates to view coordinates + /// and a rotation angle in degrees. /// - public Point MapToView(Point point) - { - return MapToViewMatrix.Transform(point); - } - - /// - /// Transforms a Point from view coordinates to projected map coordinates. - /// - public Point ViewToMap(Point point) - { - return ViewToMapMatrix.Transform(point); - } - public void SetTransform(Point mapCenter, Point viewCenter, double scale, double rotation) { Scale = scale; @@ -85,6 +74,46 @@ namespace MapControl ViewToMapMatrix = transform; } + /// + /// Transforms a Point from projected map coordinates to view coordinates. + /// + public Point MapToView(Point point) + { + return MapToViewMatrix.Transform(point); + } + + /// + /// Transforms a Point from view coordinates to projected map coordinates. + /// + public Point ViewToMap(Point point) + { + return ViewToMapMatrix.Transform(point); + } + + /// + /// Gets scaling factors from meters to view coordinates for a relative map scale. + /// + public Point GetMapScale(Point relativeScale) + { + return new Point(Scale * relativeScale.X, Scale * relativeScale.Y); + } + + /// + /// Gets a transform Matrix from meters to view coordinates for a relative map scale. + /// + public Matrix GetMapTransform(Point relativeScale) + { + var scale = GetMapScale(relativeScale); + + var transform = new Matrix(scale.X, 0d, 0d, scale.Y, 0d, 0d); + transform.Rotate(Rotation); + + return transform; + } + + /// + /// Gets the transform Matrix for the RenderTranform of a MapTileLayer. + /// public Matrix GetTileLayerTransform(double tileMatrixScale, Point tileMatrixTopLeft, Point tileMatrixOrigin) { // Tile matrix origin in map coordinates. @@ -106,6 +135,9 @@ namespace MapControl return transform; } + /// + /// Gets the index bounds of a tile matrix. + /// public Rect GetTileMatrixBounds(double tileMatrixScale, Point tileMatrixTopLeft, Size viewSize) { // View origin in map coordinates. @@ -128,5 +160,17 @@ namespace MapControl return new MatrixTransform { Matrix = transform } .TransformBounds(new Rect(0d, 0d, viewSize.Width, viewSize.Height)); } + + internal static Matrix CreateTransformMatrix( + double translation1X, double translation1Y, + double rotation, + double translation2X, double translation2Y) + { + var transform = new Matrix(1d, 0d, 0d, 1d, translation1X, translation1Y); + transform.Rotate(rotation); + transform.Translate(translation2X, translation2Y); + + return transform; + } } } diff --git a/MapControl/Shared/WmsImageLayer.cs b/MapControl/Shared/WmsImageLayer.cs index bbb259ff..0156a767 100644 --- a/MapControl/Shared/WmsImageLayer.cs +++ b/MapControl/Shared/WmsImageLayer.cs @@ -9,18 +9,13 @@ using System.Linq; using System.Threading.Tasks; using System.Xml.Linq; #if AVALONIA -using Avalonia.Controls; -using Avalonia.Media; -using Avalonia.Threading; using DependencyProperty = Avalonia.AvaloniaProperty; using FrameworkElement = Avalonia.Controls.Control; using ImageSource = Avalonia.Media.IImage; #elif WINUI -using Windows.Foundation; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media; #elif UWP -using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Media; #else @@ -284,16 +279,12 @@ namespace MapControl } var viewRect = GetViewRect(rect.Value); -#if AVALONIA - var transform - = Matrix.CreateTranslation(-viewSize.Width / 2d, -viewSize.Height / 2d) - * Matrix.CreateRotation(-viewRect.Rotation * Math.PI / 180d) - * Matrix.CreateTranslation(viewRect.Rect.Width / 2d, viewRect.Rect.Height / 2d); -#else - var transform = new Matrix(1d, 0d, 0d, 1d, -viewSize.Width / 2d, -viewSize.Height / 2d); - transform.Rotate(-viewRect.Rotation); - transform.Translate(viewRect.Rect.Width / 2d, viewRect.Rect.Height / 2d); -#endif + + var transform = ViewTransform.CreateTransformMatrix( + -viewSize.Width / 2d, -viewSize.Height / 2d, + -viewRect.Rotation, + viewRect.Rect.Width / 2d, viewRect.Rect.Height / 2d); + var imagePos = transform.Transform(position); var queryParameters = new Dictionary diff --git a/MapControl/WPF/MapBase.WPF.cs b/MapControl/WPF/MapBase.WPF.cs index 883d60d5..089223cb 100644 --- a/MapControl/WPF/MapBase.WPF.cs +++ b/MapControl/WPF/MapBase.WPF.cs @@ -3,7 +3,6 @@ // Licensed under the Microsoft Public License (Ms-PL) using System.Windows; -using System.Windows.Media; using System.Windows.Media.Animation; namespace MapControl @@ -32,7 +31,7 @@ namespace MapControl public static readonly DependencyProperty MaxZoomLevelProperty = DependencyPropertyHelper.Register(nameof(MaxZoomLevel), 20d, false, (map, oldValue, newValue) => map.MaxZoomLevelPropertyChanged(newValue), - (map, value) => map.CoerceMinZoomLevelProperty(value)); + (map, value) => map.CoerceMaxZoomLevelProperty(value)); public static readonly DependencyProperty ZoomLevelProperty = DependencyPropertyHelper.Register(nameof(ZoomLevel), 1d, true, @@ -83,20 +82,10 @@ namespace MapControl /// Gets the scaling factor from projected map coordinates to view coordinates, /// as pixels per meter. /// - public double ViewScale => (double)GetValue(ViewScaleProperty); - - /// - /// Gets a transform Matrix for scaling and rotating objects that are anchored - /// at a Location from map coordinates (i.e. meters) to view coordinates. - /// - public Matrix GetMapTransform(Location location) + public double ViewScale { - var scale = GetScale(location); - - var transform = new Matrix(scale.X, 0d, 0d, scale.Y, 0d, 0d); - transform.Rotate(ViewTransform.Rotation); - - return transform; + get => (double)GetValue(ViewScaleProperty); + private set => SetValue(ViewScalePropertyKey, value); } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) @@ -107,11 +96,6 @@ namespace MapControl UpdateTransform(); } - private void SetViewScale(double scale) - { - SetValue(ViewScalePropertyKey, scale); - } - private void CenterPropertyChanged(Location center) { if (!internalPropertyChange) diff --git a/MapControl/WinUI/MapBase.WinUI.cs b/MapControl/WinUI/MapBase.WinUI.cs index cf63adb5..bde1ccf5 100644 --- a/MapControl/WinUI/MapBase.WinUI.cs +++ b/MapControl/WinUI/MapBase.WinUI.cs @@ -92,20 +92,10 @@ namespace MapControl /// Gets the scaling factor from projected map coordinates to view coordinates, /// as pixels per meter. /// - public double ViewScale => (double)GetValue(ViewScaleProperty); - - /// - /// Gets a transform Matrix for scaling and rotating objects that are anchored - /// at a Location from map coordinates (i.e. meters) to view coordinates. - /// - public Matrix GetMapTransform(Location location) + public double ViewScale { - var scale = GetScale(location); - - var transform = new Matrix(scale.X, 0d, 0d, scale.Y, 0d, 0d); - transform.Rotate(ViewTransform.Rotation); - - return transform; + get => (double)GetValue(ViewScaleProperty); + private set => SetValue(ViewScaleProperty, value); } private void OnSizeChanged(object sender, SizeChangedEventArgs e) @@ -119,11 +109,6 @@ namespace MapControl UpdateTransform(); } - private void SetViewScale(double scale) - { - SetValue(ViewScaleProperty, scale); - } - private void CenterPropertyChanged(Location value) { if (!internalPropertyChange)