mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Replaced MapRect and Scale by Rect and Point
This commit is contained in:
parent
dd62545b41
commit
7e18b6b984
|
|
@ -3,6 +3,9 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if !WINUI && !UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
|
|
@ -16,12 +19,13 @@ namespace MapControl
|
|||
Type = MapProjectionType.Azimuthal;
|
||||
}
|
||||
|
||||
public override BoundingBox MapRectToBoundingBox(MapRect mapRect)
|
||||
public override BoundingBox MapToBoundingBox(Rect rect)
|
||||
{
|
||||
var center = MapToLocation(mapRect.Center);
|
||||
var rectCenter = new Point(rect.X + rect.Width / 2d, rect.Y + rect.Height / 2d);
|
||||
var center = MapToLocation(rectCenter);
|
||||
|
||||
return center != null
|
||||
? new CenteredBoundingBox(center, mapRect.Width / Wgs84MeterPerDegree, mapRect.Height / Wgs84MeterPerDegree)
|
||||
? new CenteredBoundingBox(center, rect.Width / Wgs84MeterPerDegree, rect.Height / Wgs84MeterPerDegree)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ namespace MapControl
|
|||
CrsId = DefaultCrsId;
|
||||
}
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
return new Scale(
|
||||
return new Point(
|
||||
1d / Math.Cos(location.Latitude * Math.PI / 180d),
|
||||
1d);
|
||||
}
|
||||
|
|
@ -47,14 +47,14 @@ namespace MapControl
|
|||
point.X / Wgs84MeterPerDegree);
|
||||
}
|
||||
|
||||
public override string GetBboxValue(MapRect mapRect)
|
||||
public override string GetBboxValue(Rect rect)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture,
|
||||
CrsId == "CRS:84" ? "{0},{1},{2},{3}" : "{1},{0},{3},{2}",
|
||||
mapRect.XMin / Wgs84MeterPerDegree,
|
||||
mapRect.YMin / Wgs84MeterPerDegree,
|
||||
mapRect.XMax / Wgs84MeterPerDegree,
|
||||
mapRect.YMax / Wgs84MeterPerDegree);
|
||||
rect.X / Wgs84MeterPerDegree,
|
||||
rect.Y / Wgs84MeterPerDegree,
|
||||
(rect.X + rect.Width) / Wgs84MeterPerDegree,
|
||||
(rect.Y + rect.Height) / Wgs84MeterPerDegree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,15 +119,15 @@ namespace MapControl
|
|||
|
||||
var p1 = transform.Transform(new Point());
|
||||
var p2 = transform.Transform(new Point(geoBitmap.Bitmap.PixelWidth, geoBitmap.Bitmap.PixelHeight));
|
||||
var mapRect = new MapRect(p1, p2);
|
||||
var rect = new Rect(p1, p2);
|
||||
|
||||
if (geoBitmap.Projection != null)
|
||||
{
|
||||
boundingBox = geoBitmap.Projection.MapRectToBoundingBox(mapRect);
|
||||
boundingBox = geoBitmap.Projection.MapToBoundingBox(rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
boundingBox = new BoundingBox(mapRect.YMin, mapRect.XMin, mapRect.YMax, mapRect.XMax);
|
||||
boundingBox = new BoundingBox(rect.Y, rect.X, rect.Y + rect.Height, rect.X + rect.Width);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ namespace MapControl
|
|||
{
|
||||
int epsgCode = geoKeyDirectory[i + 3];
|
||||
|
||||
projection = MapProjection.Factory.GetProjection(epsgCode) ??
|
||||
projection = MapProjectionFactory.Instance.GetProjection(epsgCode) ??
|
||||
throw new ArgumentException($"Can not create projection EPSG:{epsgCode} in {sourcePath}.");
|
||||
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -9,15 +9,14 @@ using System.IO;
|
|||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
#if WINUI
|
||||
#if AVALONIA
|
||||
using ImageSource = Avalonia.Media.IImage;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
|
|
@ -43,11 +42,7 @@ namespace MapControl
|
|||
|
||||
try
|
||||
{
|
||||
if (!uri.IsAbsoluteUri || uri.IsFile)
|
||||
{
|
||||
image = await LoadImageAsync(uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString);
|
||||
}
|
||||
else if (uri.Scheme == "http" || uri.Scheme == "https")
|
||||
if (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps)
|
||||
{
|
||||
var response = await GetHttpResponseAsync(uri, progress);
|
||||
|
||||
|
|
@ -56,9 +51,13 @@ namespace MapControl
|
|||
image = await LoadImageAsync(response.Buffer);
|
||||
}
|
||||
}
|
||||
else if (uri.IsFile || !uri.IsAbsoluteUri)
|
||||
{
|
||||
image = await LoadImageAsync(uri.IsAbsoluteUri ? uri.LocalPath : uri.OriginalString);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = new BitmapImage(uri);
|
||||
image = LoadImage(uri);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINUI || UWP
|
||||
using Windows.Foundation;
|
||||
#else
|
||||
#if !WINUI && !UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
|
|
@ -50,30 +48,30 @@ namespace MapControl
|
|||
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 topLeft = new Point(rect.X, rect.Y);
|
||||
var topRight = new Point(rect.X + rect.Width, rect.Y);
|
||||
var bottomLeft = new Point(rect.X, rect.Y + rect.Height);
|
||||
var bottomRight = new Point(rect.X + rect.Width, rect.Y + rect.Height);
|
||||
var numIntersections = 0;
|
||||
|
||||
if (GetIntersection(ref p1, ref p2, topLeft, bottomLeft, p => p.X <= rect.Left)) // left edge
|
||||
if (GetIntersection(ref p1, ref p2, topLeft, bottomLeft, p => p.X <= rect.X)) // left edge
|
||||
{
|
||||
numIntersections++;
|
||||
}
|
||||
|
||||
if (GetIntersection(ref p1, ref p2, topLeft, topRight, p => p.Y <= rect.Top)) // top edge
|
||||
if (GetIntersection(ref p1, ref p2, topLeft, topRight, p => p.Y <= rect.Y)) // top edge
|
||||
{
|
||||
numIntersections++;
|
||||
}
|
||||
|
||||
if (numIntersections < 2 &&
|
||||
GetIntersection(ref p1, ref p2, topRight, bottomRight, p => p.X >= rect.Right)) // right edge
|
||||
GetIntersection(ref p1, ref p2, topRight, bottomRight, p => p.X >= rect.X + rect.Width)) // right edge
|
||||
{
|
||||
numIntersections++;
|
||||
}
|
||||
|
||||
if (numIntersections < 2 &&
|
||||
GetIntersection(ref p1, ref p2, bottomLeft, bottomRight, p => p.Y >= rect.Bottom)) // bottom edge
|
||||
GetIntersection(ref p1, ref p2, bottomLeft, bottomRight, p => p.Y >= rect.Y + rect.Height)) // bottom edge
|
||||
{
|
||||
numIntersections++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -231,9 +231,11 @@ namespace MapControl
|
|||
/// 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.
|
||||
/// </summary>
|
||||
public Scale GetScale(Location location)
|
||||
public Point GetScale(Location location)
|
||||
{
|
||||
return ViewTransform.Scale * MapProjection.GetRelativeScale(location);
|
||||
var relativeScale = MapProjection.GetRelativeScale(location);
|
||||
|
||||
return new Point(ViewTransform.Scale * relativeScale.X, ViewTransform.Scale * relativeScale.Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -286,7 +288,7 @@ namespace MapControl
|
|||
var x2 = Math.Max(p1.X, Math.Max(p2.X, Math.Max(p3.X, p4.X)));
|
||||
var y2 = Math.Max(p1.Y, Math.Max(p2.Y, Math.Max(p3.Y, p4.Y)));
|
||||
|
||||
return MapProjection.MapRectToBoundingBox(new MapRect(x1, y1, x2, y2));
|
||||
return MapProjection.MapToBoundingBox(new Rect(x1, y1, x2 - x1, y2 - y1));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -342,8 +344,7 @@ namespace MapControl
|
|||
{
|
||||
SetTransformCenter(center);
|
||||
|
||||
viewCenter.X += translation.X;
|
||||
viewCenter.Y += translation.Y;
|
||||
viewCenter = new Point(viewCenter.X + translation.X, viewCenter.Y + translation.Y);
|
||||
|
||||
if (rotation != 0d)
|
||||
{
|
||||
|
|
@ -392,15 +393,16 @@ namespace MapControl
|
|||
/// </summary>
|
||||
public void ZoomToBounds(BoundingBox boundingBox)
|
||||
{
|
||||
var mapRect = MapProjection.BoundingBoxToMapRect(boundingBox);
|
||||
var rect = MapProjection.BoundingBoxToMap(boundingBox);
|
||||
|
||||
if (mapRect != null)
|
||||
if (rect.HasValue)
|
||||
{
|
||||
var targetCenter = MapProjection.MapToLocation(mapRect.Center);
|
||||
var rectCenter = new Point(rect.Value.X + rect.Value.Width / 2d, rect.Value.Y + rect.Value.Height / 2d);
|
||||
var targetCenter = MapProjection.MapToLocation(rectCenter);
|
||||
|
||||
if (targetCenter != null)
|
||||
{
|
||||
var scale = Math.Min(RenderSize.Width / mapRect.Width, RenderSize.Height / mapRect.Height);
|
||||
var scale = Math.Min(RenderSize.Width / rect.Value.Width, RenderSize.Height / rect.Value.Height);
|
||||
|
||||
TargetZoomLevel = ViewTransform.ScaleToZoomLevel(scale);
|
||||
TargetCenter = targetCenter;
|
||||
|
|
|
|||
|
|
@ -183,9 +183,9 @@ namespace MapControl
|
|||
{
|
||||
var viewRect = GetViewRect(boundingBox);
|
||||
|
||||
if (viewRect != null)
|
||||
if (viewRect.HasValue)
|
||||
{
|
||||
ArrangeElement(element, viewRect);
|
||||
ArrangeElement(element, viewRect.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -214,21 +214,27 @@ namespace MapControl
|
|||
return position;
|
||||
}
|
||||
|
||||
protected ViewRect GetViewRect(BoundingBox boundingBox)
|
||||
protected ViewRect? GetViewRect(BoundingBox boundingBox)
|
||||
{
|
||||
var mapRect = parentMap.MapProjection.BoundingBoxToMapRect(boundingBox);
|
||||
var rect = parentMap.MapProjection.BoundingBoxToMap(boundingBox);
|
||||
|
||||
return mapRect != null ? GetViewRect(mapRect) : null;
|
||||
if (!rect.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return GetViewRect(rect.Value);
|
||||
}
|
||||
|
||||
protected ViewRect GetViewRect(MapRect mapRect)
|
||||
protected ViewRect GetViewRect(Rect rect)
|
||||
{
|
||||
var position = parentMap.ViewTransform.MapToView(mapRect.Center);
|
||||
var rectCenter = new Point(rect.X + rect.Width / 2d, rect.Y + rect.Height / 2d);
|
||||
var position = parentMap.ViewTransform.MapToView(rectCenter);
|
||||
|
||||
if (parentMap.MapProjection.Type <= MapProjectionType.NormalCylindrical &&
|
||||
IsOutsideViewport(position))
|
||||
{
|
||||
var location = parentMap.MapProjection.MapToLocation(mapRect.Center);
|
||||
var location = parentMap.MapProjection.MapToLocation(rectCenter);
|
||||
|
||||
if (location != null)
|
||||
{
|
||||
|
|
@ -242,8 +248,8 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
var width = mapRect.Width * parentMap.ViewTransform.Scale;
|
||||
var height = mapRect.Height * parentMap.ViewTransform.Scale;
|
||||
var width = rect.Width * parentMap.ViewTransform.Scale;
|
||||
var height = rect.Height * parentMap.ViewTransform.Scale;
|
||||
var x = position.X - width / 2d;
|
||||
var y = position.Y - height / 2d;
|
||||
|
||||
|
|
@ -259,16 +265,17 @@ namespace MapControl
|
|||
private static void ArrangeElement(FrameworkElement element, Point position)
|
||||
{
|
||||
var size = GetDesiredSize(element);
|
||||
var rect = new Rect(position.X, position.Y, size.Width, size.Height);
|
||||
var x = position.X;
|
||||
var y = position.Y;
|
||||
|
||||
switch (element.HorizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Center:
|
||||
rect.X -= rect.Width / 2d;
|
||||
x -= size.Width / 2d;
|
||||
break;
|
||||
|
||||
case HorizontalAlignment.Right:
|
||||
rect.X -= rect.Width;
|
||||
x -= size.Width;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -278,37 +285,40 @@ namespace MapControl
|
|||
switch (element.VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Center:
|
||||
rect.Y -= rect.Height / 2d;
|
||||
y -= size.Height / 2d;
|
||||
break;
|
||||
|
||||
case VerticalAlignment.Bottom:
|
||||
rect.Y -= rect.Height;
|
||||
y -= size.Height;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ArrangeElement(element, rect);
|
||||
ArrangeElement(element, new Rect(x, y, size.Width, size.Height));
|
||||
}
|
||||
|
||||
private static void ArrangeElement(FrameworkElement element, Size parentSize)
|
||||
{
|
||||
var size = GetDesiredSize(element);
|
||||
var rect = new Rect(0d, 0d, size.Width, size.Height);
|
||||
var x = 0d;
|
||||
var y = 0d;
|
||||
var width = size.Width;
|
||||
var height = size.Height;
|
||||
|
||||
switch (element.HorizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Center:
|
||||
rect.X = (parentSize.Width - rect.Width) / 2d;
|
||||
x = (parentSize.Width - size.Width) / 2d;
|
||||
break;
|
||||
|
||||
case HorizontalAlignment.Right:
|
||||
rect.X = parentSize.Width - rect.Width;
|
||||
x = parentSize.Width - size.Width;
|
||||
break;
|
||||
|
||||
case HorizontalAlignment.Stretch:
|
||||
rect.Width = parentSize.Width;
|
||||
width = parentSize.Width;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -318,30 +328,30 @@ namespace MapControl
|
|||
switch (element.VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Center:
|
||||
rect.Y = (parentSize.Height - rect.Height) / 2d;
|
||||
y = (parentSize.Height - size.Height) / 2d;
|
||||
break;
|
||||
|
||||
case VerticalAlignment.Bottom:
|
||||
rect.Y = parentSize.Height - rect.Height;
|
||||
y = parentSize.Height - size.Height;
|
||||
break;
|
||||
|
||||
case VerticalAlignment.Stretch:
|
||||
rect.Height = parentSize.Height;
|
||||
height = parentSize.Height;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ArrangeElement(element, rect);
|
||||
ArrangeElement(element, new Rect(x, y, width, height));
|
||||
}
|
||||
|
||||
private static void ArrangeElement(FrameworkElement element, ViewRect rect)
|
||||
{
|
||||
element.Width = rect.Width;
|
||||
element.Height = rect.Height;
|
||||
element.Width = rect.Rect.Width;
|
||||
element.Height = rect.Rect.Height;
|
||||
|
||||
ArrangeElement(element, new Rect(rect.X, rect.Y, rect.Width, rect.Height));
|
||||
ArrangeElement(element, rect.Rect);
|
||||
|
||||
if (element.RenderTransform is RotateTransform rotateTransform)
|
||||
{
|
||||
|
|
@ -359,10 +369,7 @@ namespace MapControl
|
|||
{
|
||||
if (element.UseLayoutRounding)
|
||||
{
|
||||
rect.X = Math.Round(rect.X);
|
||||
rect.Y = Math.Round(rect.Y);
|
||||
rect.Width = Math.Round(rect.Width);
|
||||
rect.Height = Math.Round(rect.Height);
|
||||
rect = new Rect(Math.Round(rect.X), Math.Round(rect.Y), Math.Round(rect.Width), Math.Round(rect.Height));
|
||||
}
|
||||
|
||||
element.Arrange(rect);
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ namespace MapControl
|
|||
public const double Wgs84Flattening = 1d / 298.257223563;
|
||||
public static readonly double Wgs84Eccentricity = Math.Sqrt((2d - Wgs84Flattening) * Wgs84Flattening);
|
||||
|
||||
public static MapProjectionFactory Factory { get; set; } = new MapProjectionFactory();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the projection.
|
||||
/// </summary>
|
||||
|
|
@ -49,7 +47,7 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Gets the relative map scale at the specified Location.
|
||||
/// </summary>
|
||||
public virtual Scale GetRelativeScale(Location location) => new Scale(1d, 1d);
|
||||
public virtual Point GetRelativeScale(Location location) => new Point(1d, 1d);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a Location in geographic coordinates to a Point in projected map coordinates.
|
||||
|
|
@ -64,12 +62,12 @@ namespace MapControl
|
|||
public abstract Location MapToLocation(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a BoundingBox in geographic coordinates to a MapRect in projected map coordinates.
|
||||
/// Transforms a BoundingBox in geographic coordinates to a Rect in projected map coordinates.
|
||||
/// Returns null when the BoundingBox can not be transformed.
|
||||
/// </summary>
|
||||
public virtual MapRect BoundingBoxToMapRect(BoundingBox boundingBox)
|
||||
public virtual Rect? BoundingBoxToMap(BoundingBox boundingBox)
|
||||
{
|
||||
MapRect mapRect = null;
|
||||
Rect? rect = null;
|
||||
|
||||
if (boundingBox.South < boundingBox.North && boundingBox.West < boundingBox.East)
|
||||
{
|
||||
|
|
@ -78,7 +76,7 @@ namespace MapControl
|
|||
|
||||
if (p1.HasValue && p2.HasValue)
|
||||
{
|
||||
mapRect = new MapRect(p1.Value, p2.Value);
|
||||
rect = new Rect(p1.Value, p2.Value);
|
||||
}
|
||||
}
|
||||
else if (boundingBox.Center != null)
|
||||
|
|
@ -94,21 +92,21 @@ namespace MapControl
|
|||
var x = center.Value.X - width / 2d;
|
||||
var y = center.Value.Y - height / 2d;
|
||||
|
||||
mapRect = new MapRect(x, y, x + width, y + height);
|
||||
rect = new Rect(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
return mapRect;
|
||||
return rect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a MapRect in projected map coordinates to a BoundingBox in geographic coordinates.
|
||||
/// Transforms a Rect in projected map coordinates to a BoundingBox in geographic coordinates.
|
||||
/// Returns null when the MapRect can not be transformed.
|
||||
/// </summary>
|
||||
public virtual BoundingBox MapRectToBoundingBox(MapRect mapRect)
|
||||
public virtual BoundingBox MapToBoundingBox(Rect rect)
|
||||
{
|
||||
var southWest = MapToLocation(new Point(mapRect.XMin, mapRect.YMin));
|
||||
var northEast = MapToLocation(new Point(mapRect.XMax, mapRect.YMax));
|
||||
var southWest = MapToLocation(new Point(rect.X, rect.Y));
|
||||
var northEast = MapToLocation(new Point(rect.X + rect.Width, rect.Y + rect.Height));
|
||||
|
||||
return southWest != null && northEast != null
|
||||
? new BoundingBox(southWest, northEast)
|
||||
|
|
@ -128,16 +126,16 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Gets the BBOX parameter value for a WMS GetMap request.
|
||||
/// </summary>
|
||||
public virtual string GetBboxValue(MapRect mapRect)
|
||||
public virtual string GetBboxValue(Rect rect)
|
||||
{
|
||||
// Truncate values for seamless stitching of two WMS images at 180° longitude,
|
||||
// as done in WmsImageLayer.GetImageAsync.
|
||||
//
|
||||
return string.Format(CultureInfo.InvariantCulture, "{0:F2},{1:F2},{2:F2},{3:F2}",
|
||||
0.01 * Math.Ceiling(100d * mapRect.XMin),
|
||||
0.01 * Math.Ceiling(100d * mapRect.YMin),
|
||||
0.01 * Math.Floor(100d * mapRect.XMax),
|
||||
0.01 * Math.Floor(100d * mapRect.YMax));
|
||||
0.01 * Math.Ceiling(100d * rect.X),
|
||||
0.01 * Math.Ceiling(100d * rect.Y),
|
||||
0.01 * Math.Floor(100d * (rect.X + rect.Width)),
|
||||
0.01 * Math.Floor(100d * (rect.Y + rect.Height)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,14 @@ namespace MapControl
|
|||
{
|
||||
public class MapProjectionFactory
|
||||
{
|
||||
private static MapProjectionFactory instance;
|
||||
|
||||
public static MapProjectionFactory Instance
|
||||
{
|
||||
get => instance ?? (instance = new MapProjectionFactory());
|
||||
set => instance = value;
|
||||
}
|
||||
|
||||
public virtual MapProjection GetProjection(int epsgCode)
|
||||
{
|
||||
MapProjection projection = null;
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// Copyright © 2024 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if !WINUI && !UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Map rectangle with double floating point precision, in contrast to Windows.Foundation.Rect.
|
||||
/// Used by MapProjection when converting geographic bounding boxes to/from projected map coordinates.
|
||||
/// </summary>
|
||||
public class MapRect
|
||||
{
|
||||
public MapRect(double x1, double y1, double x2, double y2)
|
||||
{
|
||||
XMin = Math.Min(x1, x2);
|
||||
YMin = Math.Min(y1, y2);
|
||||
XMax = Math.Max(x1, x2);
|
||||
YMax = Math.Max(y1, y2);
|
||||
}
|
||||
|
||||
public MapRect(Point point1, Point point2)
|
||||
: this(point1.X, point1.Y, point2.X, point2.Y)
|
||||
{
|
||||
}
|
||||
|
||||
public double XMin { get; }
|
||||
public double YMin { get; }
|
||||
public double XMax { get; }
|
||||
public double YMax { get; }
|
||||
|
||||
public double Width => XMax - XMin;
|
||||
public double Height => YMax - YMin;
|
||||
|
||||
public Point Center => new Point((XMin + XMax) / 2d, (YMin + YMax) / 2d);
|
||||
|
||||
public bool Contains(Point p) => p.X >= XMin && p.X <= XMax && p.Y >= YMin && p.Y <= YMax;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,11 +23,6 @@ using System.Windows.Threading;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
public interface ITileImageLoader
|
||||
{
|
||||
Task LoadTilesAsync(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName, IProgress<double> progress);
|
||||
}
|
||||
|
||||
public abstract class MapTileLayerBase : Panel, IMapLayer
|
||||
{
|
||||
public static readonly DependencyProperty TileSourceProperty = DependencyProperty.Register(
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace MapControl
|
|||
public double FalseNorthing { get; set; } = 2e6;
|
||||
public bool IsNorth { get; set; }
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
var lat = location.Latitude * Math.PI / 180d;
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ namespace MapControl
|
|||
var m = Math.Cos(lat) / Math.Sqrt(1d - eSinLat * eSinLat); // p.160 (14-15)
|
||||
var k = r / (EquatorialRadius * m); // p.161 (21-32)
|
||||
|
||||
return new Scale(k, k);
|
||||
return new Point(k, k);
|
||||
}
|
||||
|
||||
public override Point? LocationToMap(Location location)
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// Copyright © 2024 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public readonly struct Scale
|
||||
{
|
||||
public Scale(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public double X { get; }
|
||||
public double Y { get; }
|
||||
|
||||
public static Scale operator *(double f, Scale v)
|
||||
{
|
||||
return new Scale(f * v.X, f * v.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,21 +3,19 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
#if AVALONIA
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using ImageSource = Avalonia.Media.IImage;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
|
|
@ -56,16 +54,5 @@ namespace MapControl
|
|||
AnimateImageOpacity();
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginOpacityAnimation()
|
||||
{
|
||||
Image.BeginAnimation(UIElement.OpacityProperty,
|
||||
new DoubleAnimation
|
||||
{
|
||||
From = 0d,
|
||||
Duration = MapBase.ImageFadeDuration,
|
||||
FillBehavior = FillBehavior.Stop
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ using System;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -19,6 +18,11 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Loads and optionally caches map tile images for a MapTileLayer.
|
||||
/// </summary>
|
||||
public interface ITileImageLoader
|
||||
{
|
||||
Task LoadTilesAsync(IEnumerable<Tile> tiles, TileSource tileSource, string cacheName, IProgress<double> progress);
|
||||
}
|
||||
|
||||
public partial class TileImageLoader : ITileImageLoader
|
||||
{
|
||||
private class TileQueue : ConcurrentStack<Tile>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#if WINUI
|
||||
#if AVALONIA
|
||||
using ImageSource = Avalonia.Media.IImage;
|
||||
#elif WINUI
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#elif UWP
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace MapControl
|
|||
public double FalseEasting { get; set; }
|
||||
public double FalseNorthing { get; set; }
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
var k = ScaleFactor;
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ namespace MapControl
|
|||
+ (61d - 148d * T + 16d * T_2) * A_6 / 720d); // p.61 (8-11)
|
||||
}
|
||||
|
||||
return new Scale(k, k);
|
||||
return new Point(k, k);
|
||||
}
|
||||
|
||||
public override Point? LocationToMap(Location location)
|
||||
|
|
|
|||
|
|
@ -2,26 +2,24 @@
|
|||
// Copyright © 2024 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if !WINUI && !UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Rotated rectangle used to arrange and rotate an element with a BoundingBox.
|
||||
/// </summary>
|
||||
public class ViewRect
|
||||
public readonly struct ViewRect
|
||||
{
|
||||
public ViewRect(double x, double y, double width, double height, double rotation)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = height;
|
||||
Rect = new Rect(x, y, width, height);
|
||||
Rotation = rotation;
|
||||
}
|
||||
|
||||
public double X { get; }
|
||||
public double Y { get; }
|
||||
public double Width { get; }
|
||||
public double Height { get; }
|
||||
public Rect Rect { get; }
|
||||
public double Rotation { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ namespace MapControl
|
|||
CrsId = DefaultCrsId;
|
||||
}
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
var k = 1d / Math.Cos(location.Latitude * Math.PI / 180d); // p.44 (7-3)
|
||||
|
||||
return new Scale(k, k);
|
||||
return new Point(k, k);
|
||||
}
|
||||
|
||||
public override Point? LocationToMap(Location location)
|
||||
|
|
|
|||
|
|
@ -239,9 +239,9 @@ namespace MapControl
|
|||
/// </summary>
|
||||
protected virtual string GetMapRequestUri(BoundingBox boundingBox)
|
||||
{
|
||||
var mapRect = ParentMap.MapProjection.BoundingBoxToMapRect(boundingBox);
|
||||
var rect = ParentMap.MapProjection.BoundingBoxToMap(boundingBox);
|
||||
|
||||
if (mapRect == null)
|
||||
if (!rect.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
@ -257,9 +257,9 @@ namespace MapControl
|
|||
{ "STYLES", Styles ?? "" },
|
||||
{ "FORMAT", "image/png" },
|
||||
{ "CRS", GetCrsValue() },
|
||||
{ "BBOX", GetBboxValue(mapRect) },
|
||||
{ "WIDTH", Math.Round(viewScale * mapRect.Width).ToString("F0") },
|
||||
{ "HEIGHT", Math.Round(viewScale * mapRect.Height).ToString("F0") }
|
||||
{ "BBOX", GetBboxValue(rect.Value) },
|
||||
{ "WIDTH", Math.Round(viewScale * rect.Value.Width).ToString("F0") },
|
||||
{ "HEIGHT", Math.Round(viewScale * rect.Value.Height).ToString("F0") }
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -270,18 +270,18 @@ namespace MapControl
|
|||
{
|
||||
var viewSize = ParentMap.RenderSize;
|
||||
var boundingBox = ParentMap.ViewRectToBoundingBox(new Rect(0d, 0d, viewSize.Width, viewSize.Height));
|
||||
var mapRect = ParentMap.MapProjection.BoundingBoxToMapRect(boundingBox);
|
||||
var rect = ParentMap.MapProjection.BoundingBoxToMap(boundingBox);
|
||||
|
||||
if (mapRect == null)
|
||||
if (!rect.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var viewRect = GetViewRect(mapRect);
|
||||
var viewRect = GetViewRect(rect.Value);
|
||||
|
||||
var transform = new Matrix(1, 0, 0, 1, -viewSize.Width / 2, -viewSize.Height / 2);
|
||||
var transform = new Matrix(1d, 0d, 0d, 1d, -viewSize.Width / 2d, -viewSize.Height / 2d);
|
||||
transform.Rotate(-viewRect.Rotation);
|
||||
transform.Translate(viewRect.Width / 2, viewRect.Height / 2);
|
||||
transform.Translate(viewRect.Rect.Width / 2d, viewRect.Rect.Height / 2d);
|
||||
|
||||
var imagePos = transform.Transform(position);
|
||||
|
||||
|
|
@ -295,9 +295,9 @@ namespace MapControl
|
|||
{ "FORMAT", "image/png" },
|
||||
{ "INFO_FORMAT", format },
|
||||
{ "CRS", GetCrsValue() },
|
||||
{ "BBOX", GetBboxValue(mapRect) },
|
||||
{ "WIDTH", Math.Round(viewRect.Width).ToString("F0") },
|
||||
{ "HEIGHT", Math.Round(viewRect.Height).ToString("F0") },
|
||||
{ "BBOX", GetBboxValue(rect.Value) },
|
||||
{ "WIDTH", Math.Round(viewRect.Rect.Width).ToString("F0") },
|
||||
{ "HEIGHT", Math.Round(viewRect.Rect.Height).ToString("F0") },
|
||||
{ "I", Math.Round(imagePos.X).ToString("F0") },
|
||||
{ "J", Math.Round(imagePos.Y).ToString("F0") }
|
||||
};
|
||||
|
|
@ -310,9 +310,9 @@ namespace MapControl
|
|||
return ParentMap.MapProjection.GetCrsValue();
|
||||
}
|
||||
|
||||
protected virtual string GetBboxValue(MapRect mapRect)
|
||||
protected virtual string GetBboxValue(Rect rect)
|
||||
{
|
||||
return ParentMap.MapProjection.GetBboxValue(mapRect);
|
||||
return ParentMap.MapProjection.GetBboxValue(rect);
|
||||
}
|
||||
|
||||
protected string GetRequestUri(IDictionary<string, string> queryParameters)
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@ namespace MapControl
|
|||
CrsId = DefaultCrsId;
|
||||
}
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
var lat = location.Latitude * Math.PI / 180d;
|
||||
var eSinLat = Wgs84Eccentricity * Math.Sin(lat);
|
||||
var k = Math.Sqrt(1d - eSinLat * eSinLat) / Math.Cos(lat); // p.44 (7-8)
|
||||
|
||||
return new Scale(k, k);
|
||||
return new Point(k, k);
|
||||
}
|
||||
|
||||
public override Point? LocationToMap(Location location)
|
||||
|
|
|
|||
|
|
@ -140,9 +140,6 @@
|
|||
<Compile Include="..\Shared\MapProjectionFactory.cs">
|
||||
<Link>MapProjectionFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapRect.cs">
|
||||
<Link>MapRect.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapScale.cs">
|
||||
<Link>MapScale.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -164,9 +161,6 @@
|
|||
<Compile Include="..\Shared\PushpinBorder.cs">
|
||||
<Link>PushpinBorder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\Scale.cs">
|
||||
<Link>Scale.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\StereographicProjection.cs">
|
||||
<Link>StereographicProjection.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -272,6 +266,9 @@
|
|||
<Compile Include="..\WinUI\PushpinBorder.WinUI.cs">
|
||||
<Link>PushpinBorder.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Rect.WinUI.cs">
|
||||
<Link>Rect.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Tile.WinUI.cs">
|
||||
<Link>Tile.WinUI.cs</Link>
|
||||
</Compile>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ namespace MapControl
|
|||
{
|
||||
public static partial class ImageLoader
|
||||
{
|
||||
public static ImageSource LoadImage(Uri uri)
|
||||
{
|
||||
return new BitmapImage(uri);
|
||||
}
|
||||
|
||||
public static ImageSource LoadImage(Stream stream)
|
||||
{
|
||||
var image = new BitmapImage();
|
||||
|
|
|
|||
|
|
@ -37,18 +37,18 @@ namespace MapControl
|
|||
|
||||
if (projection != null && items != null)
|
||||
{
|
||||
var mapRect = projection.BoundingBoxToMapRect(boundingBox);
|
||||
var rect = projection.BoundingBoxToMap(boundingBox);
|
||||
|
||||
if (mapRect != null)
|
||||
if (rect.HasValue)
|
||||
{
|
||||
image = await Task.Run(() => GetImage(projection, mapRect, items));
|
||||
image = await Task.Run(() => GetImage(projection, rect.Value, items));
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private DrawingImage GetImage(MapProjection projection, MapRect mapRect, IEnumerable<IMapDrawingItem> items)
|
||||
private DrawingImage GetImage(MapProjection projection, Rect rect, IEnumerable<IMapDrawingItem> items)
|
||||
{
|
||||
var scale = ParentMap.ViewTransform.Scale;
|
||||
var rotation = ParentMap.ViewTransform.Rotation;
|
||||
|
|
@ -62,13 +62,13 @@ namespace MapControl
|
|||
.Select(point => point.Value)
|
||||
.ToList();
|
||||
|
||||
if (points.Any(point => mapRect.Contains(point)))
|
||||
if (points.Any(point => rect.Contains(point)))
|
||||
{
|
||||
for (int i = 0; i < points.Count; i++)
|
||||
{
|
||||
points[i] = new Point(
|
||||
scale * (points[i].X - mapRect.XMin),
|
||||
scale * (mapRect.YMax - points[i].Y));
|
||||
scale * (points[i].X - rect.X),
|
||||
scale * ((rect.Y + rect.Height) - points[i].Y));
|
||||
}
|
||||
|
||||
drawings.Children.Add(item.GetDrawing(points, scale, rotation));
|
||||
|
|
@ -79,7 +79,7 @@ namespace MapControl
|
|||
{
|
||||
Drawing = drawings,
|
||||
ViewboxUnits = BrushMappingMode.Absolute,
|
||||
Viewbox = new Rect(0, 0, scale * mapRect.Width, scale * mapRect.Height),
|
||||
Viewbox = new Rect(0, 0, scale * rect.Width, scale * rect.Height),
|
||||
};
|
||||
|
||||
var drawing = new GeometryDrawing(
|
||||
|
|
|
|||
|
|
@ -3,14 +3,27 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class Tile
|
||||
{
|
||||
private void BeginOpacityAnimation()
|
||||
{
|
||||
Image.BeginAnimation(UIElement.OpacityProperty,
|
||||
new DoubleAnimation
|
||||
{
|
||||
From = 0d,
|
||||
Duration = MapBase.ImageFadeDuration,
|
||||
FillBehavior = FillBehavior.Stop
|
||||
});
|
||||
}
|
||||
|
||||
private void AnimateImageOpacity()
|
||||
{
|
||||
if (Image.Source is BitmapSource bitmap && bitmap.IsDownloading && !bitmap.IsFrozen)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ namespace MapControl
|
|||
{
|
||||
public static partial class ImageLoader
|
||||
{
|
||||
public static ImageSource LoadImage(Uri uri)
|
||||
{
|
||||
return new BitmapImage(uri);
|
||||
}
|
||||
|
||||
public static async Task<WriteableBitmap> LoadImageAsync(BitmapDecoder decoder)
|
||||
{
|
||||
var image = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace MapControl
|
|||
/// <summary>
|
||||
/// Replaces Windows.Foundation.Point for double floating point precision.
|
||||
/// </summary>
|
||||
public struct Point
|
||||
public readonly struct Point
|
||||
{
|
||||
public Point(double x, double y)
|
||||
{
|
||||
|
|
@ -15,8 +15,8 @@ namespace MapControl
|
|||
Y = y;
|
||||
}
|
||||
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double X { get; }
|
||||
public double Y { get; }
|
||||
|
||||
public static implicit operator Windows.Foundation.Point(Point p)
|
||||
{
|
||||
|
|
|
|||
43
MapControl/WinUI/Rect.WinUI.cs
Normal file
43
MapControl/WinUI/Rect.WinUI.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// Copyright © 2024 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces Windows.Foundation.Rect for double floating point precision.
|
||||
/// </summary>
|
||||
public readonly struct Rect
|
||||
{
|
||||
public Rect(double x, double y, double width, double height)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
|
||||
public Rect(Point p1, Point p2)
|
||||
: this(p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y)
|
||||
{
|
||||
}
|
||||
|
||||
public double X { get; }
|
||||
public double Y { get; }
|
||||
public double Width { get; }
|
||||
public double Height { get; }
|
||||
|
||||
public bool Contains(Point p) => p.X >= X && p.X <= X + Width && p.Y >= Y && p.Y <= Y + Height;
|
||||
|
||||
public static implicit operator Windows.Foundation.Rect(Rect r)
|
||||
{
|
||||
return new Windows.Foundation.Rect(r.X, r.Y, r.Width, r.Height);
|
||||
}
|
||||
|
||||
public static implicit operator Rect(Windows.Foundation.Rect r)
|
||||
{
|
||||
return new Rect(r.X, r.Y, r.Width, r.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#endif
|
||||
|
||||
|
|
@ -14,6 +16,17 @@ namespace MapControl
|
|||
{
|
||||
public partial class Tile
|
||||
{
|
||||
private void BeginOpacityAnimation()
|
||||
{
|
||||
Image.BeginAnimation(UIElement.OpacityProperty,
|
||||
new DoubleAnimation
|
||||
{
|
||||
From = 0d,
|
||||
Duration = MapBase.ImageFadeDuration,
|
||||
FillBehavior = FillBehavior.Stop
|
||||
});
|
||||
}
|
||||
|
||||
private void AnimateImageOpacity()
|
||||
{
|
||||
if (Image.Source is BitmapImage bitmap && bitmap.UriSource != null)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
|
||||
using ProjNet.CoordinateSystems;
|
||||
using System;
|
||||
#if !WINUI && !UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl.Projections
|
||||
{
|
||||
|
|
@ -20,11 +23,11 @@ namespace MapControl.Projections
|
|||
CoordinateSystem = ProjectedCoordinateSystem.WebMercator;
|
||||
}
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
var k = 1d / Math.Cos(location.Latitude * Math.PI / 180d); // p.44 (7-3)
|
||||
|
||||
return new Scale(k, k);
|
||||
return new Point(k, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if !WINUI && !UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl.Projections
|
||||
{
|
||||
|
|
@ -41,13 +44,13 @@ namespace MapControl.Projections
|
|||
+ "AUTHORITY[\"EPSG\",\"3395\"]]";
|
||||
}
|
||||
|
||||
public override Scale GetRelativeScale(Location location)
|
||||
public override Point GetRelativeScale(Location location)
|
||||
{
|
||||
var lat = location.Latitude * Math.PI / 180d;
|
||||
var eSinLat = Wgs84Eccentricity * Math.Sin(lat);
|
||||
var k = Math.Sqrt(1d - eSinLat * eSinLat) / Math.Cos(lat); // p.44 (7-8)
|
||||
|
||||
return new Scale(k, k);
|
||||
return new Point(k, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ namespace MapControl.UiTools
|
|||
if (selectedProjection != projection)
|
||||
{
|
||||
selectedProjection = projection;
|
||||
Map.MapProjection = MapProjection.Factory.GetProjection(selectedProjection);
|
||||
Map.MapProjection = MapProjectionFactory.Instance.GetProjection(selectedProjection);
|
||||
}
|
||||
|
||||
UpdateCheckedStates();
|
||||
|
|
|
|||
Loading…
Reference in a new issue