mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Version 4.17.0: Added support for WMTS
This commit is contained in:
parent
e650c9081f
commit
e821e39841
|
|
@ -52,7 +52,7 @@
|
|||
<Version>7.4.4</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Data.SQLite.Core">
|
||||
<Version>1.0.112</Version>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -60,9 +60,10 @@ namespace MapControl
|
|||
|
||||
try
|
||||
{
|
||||
var stream = await ImageLoader.HttpClient.GetStreamAsync(metadataUri);
|
||||
|
||||
ProcessImageryMetadata(XDocument.Load(stream).Root);
|
||||
using (var stream = await ImageLoader.HttpClient.GetStreamAsync(metadataUri))
|
||||
{
|
||||
ReadImageryMetadata(XDocument.Load(stream).Root);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -70,7 +71,7 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private void ProcessImageryMetadata(XElement metadataResponse)
|
||||
private void ReadImageryMetadata(XElement metadataResponse)
|
||||
{
|
||||
var ns = metadataResponse.Name.Namespace;
|
||||
var metadata = metadataResponse.Descendants(ns + "ImageryMetadata").FirstOrDefault();
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transformation from cartesian map coordinates to viewport coordinates (pixels).
|
||||
/// Gets the transformation from cartesian map coordinates to viewport coordinates.
|
||||
/// </summary>
|
||||
public MatrixTransform ViewportTransform { get; } = new MatrixTransform();
|
||||
|
||||
|
|
|
|||
|
|
@ -65,22 +65,22 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the projection center. Only relevant for azimuthal pprojections.
|
||||
/// Gets the projection center. Only relevant for azimuthal projections.
|
||||
/// </summary>
|
||||
public Location ProjectionCenter { get; private set; } = new Location();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transform matrix from cartesian map coordinates to viewport coordinates (pixels).
|
||||
/// Gets the transform matrix from cartesian map coordinates to viewport coordinates.
|
||||
/// </summary>
|
||||
public Matrix ViewportTransform { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the transform matrix from viewport coordinates (pixels) to cartesian map coordinates.
|
||||
/// Gets the transform matrix from viewport coordinates to cartesian map coordinates.
|
||||
/// </summary>
|
||||
public Matrix InverseViewportTransform { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the scaling factor from cartesian map coordinates to viewport coordinates (pixels)
|
||||
/// Gets the scaling factor from cartesian map coordinates to viewport coordinates
|
||||
/// at the projection's point of true scale.
|
||||
/// </summary>
|
||||
public double ViewportScale { get; private set; }
|
||||
|
|
@ -186,26 +186,11 @@ namespace MapControl
|
|||
ViewportScale = Math.Pow(2d, zoomLevel) * TileSize / (360d * TrueScale);
|
||||
|
||||
var center = LocationToPoint(mapCenter);
|
||||
var matrix = CreateTransformMatrix(center, ViewportScale, -ViewportScale, heading, viewportCenter);
|
||||
var matrix = MatrixFactory.Create(center, ViewportScale, -ViewportScale, heading, viewportCenter);
|
||||
|
||||
ViewportTransform = matrix;
|
||||
matrix.Invert();
|
||||
InverseViewportTransform = matrix;
|
||||
}
|
||||
|
||||
internal static Matrix CreateTransformMatrix(
|
||||
Point translation1, double scale, double rotation, Point translation2)
|
||||
{
|
||||
return CreateTransformMatrix(translation1, scale, scale, rotation, translation2);
|
||||
}
|
||||
|
||||
internal static Matrix CreateTransformMatrix(
|
||||
Point translation1, double scaleX, double scaleY, double rotation, Point translation2)
|
||||
{
|
||||
var matrix = new Matrix(scaleX, 0d, 0d, scaleY, -translation1.X * scaleX, -translation1.Y * scaleY);
|
||||
matrix.Rotate(rotation);
|
||||
matrix.Translate(translation2.X, translation2.Y);
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,27 +8,21 @@ using System.Linq;
|
|||
#if WINDOWS_UWP
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public interface ITileImageLoader
|
||||
{
|
||||
void LoadTilesAsync(IEnumerable<Tile> tiles, TileSource tileSource, string sourceName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills the map viewport with map tiles from a TileSource.
|
||||
/// </summary>
|
||||
public class MapTileLayer : Panel, IMapLayer
|
||||
public class MapTileLayer : MapTileLayerBase
|
||||
{
|
||||
private const double WebMercatorMapSize = 2 * Math.PI * MapProjection.Wgs84EquatorialRadius;
|
||||
|
||||
/// <summary>
|
||||
/// A default MapTileLayer using OpenStreetMap data.
|
||||
/// </summary>
|
||||
|
|
@ -46,103 +40,25 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TileSourceProperty = DependencyProperty.Register(
|
||||
nameof(TileSource), typeof(TileSource), typeof(MapTileLayer),
|
||||
new PropertyMetadata(null, (o, e) => ((MapTileLayer)o).TileSourcePropertyChanged()));
|
||||
|
||||
public static readonly DependencyProperty SourceNameProperty = DependencyProperty.Register(
|
||||
nameof(SourceName), typeof(string), typeof(MapTileLayer), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
nameof(Description), typeof(string), typeof(MapTileLayer), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty ZoomLevelOffsetProperty = DependencyProperty.Register(
|
||||
nameof(ZoomLevelOffset), typeof(double), typeof(MapTileLayer),
|
||||
new PropertyMetadata(0d, (o, e) => ((MapTileLayer)o).UpdateTileGrid()));
|
||||
|
||||
public static readonly DependencyProperty MinZoomLevelProperty = DependencyProperty.Register(
|
||||
nameof(MinZoomLevel), typeof(int), typeof(MapTileLayer), new PropertyMetadata(0));
|
||||
|
||||
public static readonly DependencyProperty MaxZoomLevelProperty = DependencyProperty.Register(
|
||||
nameof(MaxZoomLevel), typeof(int), typeof(MapTileLayer), new PropertyMetadata(18));
|
||||
|
||||
public static readonly DependencyProperty MaxBackgroundLevelsProperty = DependencyProperty.Register(
|
||||
nameof(MaxBackgroundLevels), typeof(int), typeof(MapTileLayer), new PropertyMetadata(8));
|
||||
|
||||
public static readonly DependencyProperty UpdateIntervalProperty = DependencyProperty.Register(
|
||||
nameof(UpdateInterval), typeof(TimeSpan), typeof(MapTileLayer),
|
||||
new PropertyMetadata(TimeSpan.FromSeconds(0.2), (o, e) => ((MapTileLayer)o).updateTimer.Interval = (TimeSpan)e.NewValue));
|
||||
|
||||
public static readonly DependencyProperty UpdateWhileViewportChangingProperty = DependencyProperty.Register(
|
||||
nameof(UpdateWhileViewportChanging), typeof(bool), typeof(MapTileLayer), new PropertyMetadata(false));
|
||||
|
||||
public static readonly DependencyProperty MapBackgroundProperty = DependencyProperty.Register(
|
||||
nameof(MapBackground), typeof(Brush), typeof(MapTileLayer), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty MapForegroundProperty = DependencyProperty.Register(
|
||||
nameof(MapForeground), typeof(Brush), typeof(MapTileLayer), new PropertyMetadata(null));
|
||||
|
||||
private readonly DispatcherTimer updateTimer;
|
||||
private MapBase parentMap;
|
||||
|
||||
public MapTileLayer()
|
||||
: this(new TileImageLoader())
|
||||
{
|
||||
}
|
||||
|
||||
public MapTileLayer(ITileImageLoader tileImageLoader)
|
||||
: base(tileImageLoader)
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
RenderTransform = new MatrixTransform();
|
||||
TileImageLoader = tileImageLoader;
|
||||
|
||||
updateTimer = new DispatcherTimer { Interval = UpdateInterval };
|
||||
updateTimer.Tick += (s, e) => UpdateTileGrid();
|
||||
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
public ITileImageLoader TileImageLoader { get; }
|
||||
|
||||
public TileGrid TileGrid { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<Tile> Tiles { get; private set; } = new List<Tile>();
|
||||
|
||||
/// <summary>
|
||||
/// Provides map tile URIs or images.
|
||||
/// </summary>
|
||||
public TileSource TileSource
|
||||
{
|
||||
get { return (TileSource)GetValue(TileSourceProperty); }
|
||||
set { SetValue(TileSourceProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the TileSource. Used as component of a tile cache key.
|
||||
/// </summary>
|
||||
public string SourceName
|
||||
{
|
||||
get { return (string)GetValue(SourceNameProperty); }
|
||||
set { SetValue(SourceNameProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Description of the MapTileLayer. Used to display copyright information on top of the map.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get { return (string)GetValue(DescriptionProperty); }
|
||||
set { SetValue(DescriptionProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an offset to the Map's ZoomLevel for a relative scale between the Map and the MapTileLayer.
|
||||
/// </summary>
|
||||
public double ZoomLevelOffset
|
||||
{
|
||||
get { return (double)GetValue(ZoomLevelOffsetProperty); }
|
||||
set { SetValue(ZoomLevelOffsetProperty, value); }
|
||||
}
|
||||
public TileGrid TileGrid { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum zoom level supported by the MapTileLayer. Default value is 0.
|
||||
|
|
@ -162,73 +78,6 @@ namespace MapControl
|
|||
set { SetValue(MaxZoomLevelProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of background tile levels. Default value is 8.
|
||||
/// Is only effective in a MapTileLayer that is the MapLayer of its ParentMap.
|
||||
/// </summary>
|
||||
public int MaxBackgroundLevels
|
||||
{
|
||||
get { return (int)GetValue(MaxBackgroundLevelsProperty); }
|
||||
set { SetValue(MaxBackgroundLevelsProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time interval between tile updates.
|
||||
/// </summary>
|
||||
public TimeSpan UpdateInterval
|
||||
{
|
||||
get { return (TimeSpan)GetValue(UpdateIntervalProperty); }
|
||||
set { SetValue(UpdateIntervalProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls if tiles are updated while the viewport is still changing.
|
||||
/// </summary>
|
||||
public bool UpdateWhileViewportChanging
|
||||
{
|
||||
get { return (bool)GetValue(UpdateWhileViewportChangingProperty); }
|
||||
set { SetValue(UpdateWhileViewportChangingProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional background brush. Sets MapBase.Background if not null and the MapTileLayer is the base map layer.
|
||||
/// </summary>
|
||||
public Brush MapBackground
|
||||
{
|
||||
get { return (Brush)GetValue(MapBackgroundProperty); }
|
||||
set { SetValue(MapBackgroundProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional foreground brush. Sets MapBase.Foreground if not null and the MapTileLayer is the base map layer.
|
||||
/// </summary>
|
||||
public Brush MapForeground
|
||||
{
|
||||
get { return (Brush)GetValue(MapForegroundProperty); }
|
||||
set { SetValue(MapForegroundProperty, value); }
|
||||
}
|
||||
|
||||
public MapBase ParentMap
|
||||
{
|
||||
get { return parentMap; }
|
||||
set
|
||||
{
|
||||
if (parentMap != null)
|
||||
{
|
||||
parentMap.ViewportChanged -= OnViewportChanged;
|
||||
}
|
||||
|
||||
parentMap = value;
|
||||
|
||||
if (parentMap != null)
|
||||
{
|
||||
parentMap.ViewportChanged += OnViewportChanged;
|
||||
}
|
||||
|
||||
UpdateTileGrid();
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||
|
|
@ -260,29 +109,7 @@ namespace MapControl
|
|||
return finalSize;
|
||||
}
|
||||
|
||||
protected virtual void UpdateTileGrid()
|
||||
{
|
||||
updateTimer.Stop();
|
||||
|
||||
if (parentMap != null && parentMap.MapProjection.IsWebMercator)
|
||||
{
|
||||
var tileGrid = GetTileGrid();
|
||||
|
||||
if (!tileGrid.Equals(TileGrid))
|
||||
{
|
||||
TileGrid = tileGrid;
|
||||
SetRenderTransform();
|
||||
UpdateTiles();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TileGrid = null;
|
||||
UpdateTiles();
|
||||
}
|
||||
}
|
||||
|
||||
private void TileSourcePropertyChanged()
|
||||
protected override void TileSourcePropertyChanged()
|
||||
{
|
||||
if (TileGrid != null)
|
||||
{
|
||||
|
|
@ -291,68 +118,90 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private void OnViewportChanged(object sender, ViewportChangedEventArgs e)
|
||||
protected override void UpdateTileLayer()
|
||||
{
|
||||
if (TileGrid == null || e.ProjectionChanged || Math.Abs(e.LongitudeOffset) > 180d)
|
||||
UpdateTimer.Stop();
|
||||
|
||||
if (ParentMap == null || !ParentMap.MapProjection.IsWebMercator)
|
||||
{
|
||||
UpdateTileGrid(); // update immediately when projection has changed or center has moved across 180° longitude
|
||||
TileGrid = null;
|
||||
UpdateTiles();
|
||||
}
|
||||
else
|
||||
else if (SetTileGrid())
|
||||
{
|
||||
SetRenderTransform();
|
||||
|
||||
if (updateTimer.IsEnabled && !UpdateWhileViewportChanging)
|
||||
{
|
||||
updateTimer.Stop(); // restart
|
||||
}
|
||||
|
||||
if (!updateTimer.IsEnabled)
|
||||
{
|
||||
updateTimer.Start();
|
||||
}
|
||||
UpdateTiles();
|
||||
}
|
||||
}
|
||||
|
||||
private TileGrid GetTileGrid()
|
||||
protected override void SetRenderTransform()
|
||||
{
|
||||
var tileZoomLevel = Math.Max(0, (int)Math.Round(parentMap.ZoomLevel + ZoomLevelOffset));
|
||||
var tileScale = (double)(1 << tileZoomLevel);
|
||||
var scale = tileScale / (Math.Pow(2d, parentMap.ZoomLevel) * MapProjection.TileSize);
|
||||
var tileCenter = new Point(tileScale * (0.5 + parentMap.Center.Longitude / 360d),
|
||||
tileScale * (0.5 - WebMercatorProjection.LatitudeToY(parentMap.Center.Latitude) / 360d));
|
||||
var viewCenter = new Point(parentMap.RenderSize.Width / 2d, parentMap.RenderSize.Height / 2d);
|
||||
var tileGridSize = (double)(1 << TileGrid.ZoomLevel);
|
||||
|
||||
var transform = new MatrixTransform
|
||||
{
|
||||
Matrix = MapProjection.CreateTransformMatrix(viewCenter, scale, -parentMap.Heading, tileCenter)
|
||||
};
|
||||
// top/left tile grid corner in map coordinates
|
||||
//
|
||||
var tileGridOrigin = new Point(
|
||||
WebMercatorMapSize * (TileGrid.XMin / tileGridSize - 0.5),
|
||||
WebMercatorMapSize * (0.5 - TileGrid.YMin / tileGridSize));
|
||||
|
||||
var bounds = transform.TransformBounds(new Rect(0d, 0d, parentMap.RenderSize.Width, parentMap.RenderSize.Height));
|
||||
// top/left tile grid corner in viewport coordinates
|
||||
//
|
||||
var viewOrigin = ParentMap.MapProjection.ViewportTransform.Transform(tileGridOrigin);
|
||||
|
||||
return new TileGrid(tileZoomLevel,
|
||||
(int)Math.Floor(bounds.X), (int)Math.Floor(bounds.Y),
|
||||
(int)Math.Floor(bounds.X + bounds.Width), (int)Math.Floor(bounds.Y + bounds.Height));
|
||||
// tile pixels per viewport unit, 0.5 .. 2
|
||||
//
|
||||
var tileScale = Math.Pow(2d, ParentMap.ZoomLevel - TileGrid.ZoomLevel);
|
||||
|
||||
((MatrixTransform)RenderTransform).Matrix = MatrixFactory.Create(tileScale, ParentMap.Heading, viewOrigin);
|
||||
}
|
||||
|
||||
private void SetRenderTransform()
|
||||
private bool SetTileGrid()
|
||||
{
|
||||
var tileScale = (double)(1 << TileGrid.ZoomLevel);
|
||||
var scale = Math.Pow(2d, parentMap.ZoomLevel) / tileScale;
|
||||
var tileCenter = new Point(tileScale * (0.5 + parentMap.Center.Longitude / 360d),
|
||||
tileScale * (0.5 - WebMercatorProjection.LatitudeToY(parentMap.Center.Latitude) / 360d));
|
||||
var tileOrigin = new Point(MapProjection.TileSize * (tileCenter.X - TileGrid.XMin),
|
||||
MapProjection.TileSize * (tileCenter.Y - TileGrid.YMin));
|
||||
var viewCenter = new Point(parentMap.RenderSize.Width / 2d, parentMap.RenderSize.Height / 2d);
|
||||
var tileGridZoomLevel = (int)Math.Round(ParentMap.ZoomLevel);
|
||||
var tileGridSize = (double)(1 << tileGridZoomLevel);
|
||||
|
||||
((MatrixTransform)RenderTransform).Matrix =
|
||||
MapProjection.CreateTransformMatrix(tileOrigin, scale, parentMap.Heading, viewCenter);
|
||||
// top/left viewport corner in map coordinates
|
||||
//
|
||||
var tileOrigin = ParentMap.MapProjection.InverseViewportTransform.Transform(new Point());
|
||||
|
||||
// top/left viewport corner in tile grid coordinates
|
||||
//
|
||||
var tileGridOrigin = new Point(
|
||||
tileGridSize * (0.5 + tileOrigin.X / WebMercatorMapSize),
|
||||
tileGridSize * (0.5 - tileOrigin.Y / WebMercatorMapSize));
|
||||
|
||||
// transforms viewport bounds to tile grid bounds
|
||||
//
|
||||
var transform = new MatrixTransform
|
||||
{
|
||||
Matrix = MatrixFactory.Create(1d / MapProjection.TileSize, -ParentMap.Heading, tileGridOrigin)
|
||||
};
|
||||
|
||||
var bounds = transform.TransformBounds(new Rect(0d, 0d, ParentMap.RenderSize.Width, ParentMap.RenderSize.Height));
|
||||
|
||||
var xMin = (int)Math.Floor(bounds.X);
|
||||
var yMin = (int)Math.Floor(bounds.Y);
|
||||
var xMax = (int)Math.Floor(bounds.X + bounds.Width);
|
||||
var yMax = (int)Math.Floor(bounds.Y + bounds.Height);
|
||||
|
||||
if (TileGrid != null &&
|
||||
TileGrid.ZoomLevel == tileGridZoomLevel &&
|
||||
TileGrid.XMin == xMin && TileGrid.YMin == yMin &&
|
||||
TileGrid.XMax == xMax && TileGrid.YMax == yMax)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TileGrid = new TileGrid(tileGridZoomLevel, xMin, yMin, xMax, yMax);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void UpdateTiles()
|
||||
{
|
||||
var newTiles = new List<Tile>();
|
||||
|
||||
if (parentMap != null && TileGrid != null && TileSource != null)
|
||||
if (ParentMap != null && TileGrid != null && TileSource != null)
|
||||
{
|
||||
var maxZoomLevel = Math.Min(TileGrid.ZoomLevel, MaxZoomLevel);
|
||||
|
||||
|
|
@ -360,7 +209,7 @@ namespace MapControl
|
|||
{
|
||||
var minZoomLevel = maxZoomLevel;
|
||||
|
||||
if (this == parentMap.MapLayer) // load background tiles
|
||||
if (this == ParentMap.MapLayer) // load background tiles
|
||||
{
|
||||
minZoomLevel = Math.Max(TileGrid.ZoomLevel - MaxBackgroundLevels, MinZoomLevel);
|
||||
}
|
||||
|
|
|
|||
198
MapControl/Shared/MapTileLayerBase.cs
Normal file
198
MapControl/Shared/MapTileLayerBase.cs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
#if WINDOWS_UWP
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public interface ITileImageLoader
|
||||
{
|
||||
void LoadTilesAsync(IEnumerable<Tile> tiles, TileSource tileSource, string sourceName);
|
||||
}
|
||||
|
||||
public abstract class MapTileLayerBase : Panel, IMapLayer
|
||||
{
|
||||
public static readonly DependencyProperty TileSourceProperty = DependencyProperty.Register(
|
||||
nameof(TileSource), typeof(TileSource), typeof(MapTileLayerBase),
|
||||
new PropertyMetadata(null, (o, e) => ((MapTileLayerBase)o).TileSourcePropertyChanged()));
|
||||
|
||||
public static readonly DependencyProperty SourceNameProperty = DependencyProperty.Register(
|
||||
nameof(SourceName), typeof(string), typeof(MapTileLayerBase), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
nameof(Description), typeof(string), typeof(MapTileLayerBase), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty MaxBackgroundLevelsProperty = DependencyProperty.Register(
|
||||
nameof(MaxBackgroundLevels), typeof(int), typeof(MapTileLayerBase), new PropertyMetadata(8));
|
||||
|
||||
public static readonly DependencyProperty UpdateIntervalProperty = DependencyProperty.Register(
|
||||
nameof(UpdateInterval), typeof(TimeSpan), typeof(MapTileLayerBase),
|
||||
new PropertyMetadata(TimeSpan.FromSeconds(0.2), (o, e) => ((MapTileLayerBase)o).UpdateTimer.Interval = (TimeSpan)e.NewValue));
|
||||
|
||||
public static readonly DependencyProperty UpdateWhileViewportChangingProperty = DependencyProperty.Register(
|
||||
nameof(UpdateWhileViewportChanging), typeof(bool), typeof(MapTileLayerBase), new PropertyMetadata(false));
|
||||
|
||||
public static readonly DependencyProperty MapBackgroundProperty = DependencyProperty.Register(
|
||||
nameof(MapBackground), typeof(Brush), typeof(MapTileLayerBase), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty MapForegroundProperty = DependencyProperty.Register(
|
||||
nameof(MapForeground), typeof(Brush), typeof(MapTileLayerBase), new PropertyMetadata(null));
|
||||
|
||||
private MapBase parentMap;
|
||||
|
||||
public MapTileLayerBase()
|
||||
: this(new TileImageLoader())
|
||||
{
|
||||
}
|
||||
|
||||
public MapTileLayerBase(ITileImageLoader tileImageLoader)
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
RenderTransform = new MatrixTransform();
|
||||
TileImageLoader = tileImageLoader;
|
||||
|
||||
UpdateTimer = new DispatcherTimer { Interval = UpdateInterval };
|
||||
UpdateTimer.Tick += (s, e) => UpdateTileLayer();
|
||||
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
public ITileImageLoader TileImageLoader { get; }
|
||||
|
||||
public DispatcherTimer UpdateTimer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides map tile URIs or images.
|
||||
/// </summary>
|
||||
public TileSource TileSource
|
||||
{
|
||||
get { return (TileSource)GetValue(TileSourceProperty); }
|
||||
set { SetValue(TileSourceProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the TileSource. Used as component of a tile cache key.
|
||||
/// </summary>
|
||||
public string SourceName
|
||||
{
|
||||
get { return (string)GetValue(SourceNameProperty); }
|
||||
set { SetValue(SourceNameProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Description of the tile layer. Used to display copyright information on top of the map.
|
||||
/// </summary>
|
||||
public string Description
|
||||
{
|
||||
get { return (string)GetValue(DescriptionProperty); }
|
||||
set { SetValue(DescriptionProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of background tile levels. Default value is 8.
|
||||
/// Is only effective in a MapTileLayer that is the MapLayer of its ParentMap.
|
||||
/// </summary>
|
||||
public int MaxBackgroundLevels
|
||||
{
|
||||
get { return (int)GetValue(MaxBackgroundLevelsProperty); }
|
||||
set { SetValue(MaxBackgroundLevelsProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum time interval between tile updates.
|
||||
/// </summary>
|
||||
public TimeSpan UpdateInterval
|
||||
{
|
||||
get { return (TimeSpan)GetValue(UpdateIntervalProperty); }
|
||||
set { SetValue(UpdateIntervalProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls if tiles are updated while the viewport is still changing.
|
||||
/// </summary>
|
||||
public bool UpdateWhileViewportChanging
|
||||
{
|
||||
get { return (bool)GetValue(UpdateWhileViewportChangingProperty); }
|
||||
set { SetValue(UpdateWhileViewportChangingProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional background brush. Sets MapBase.Background if not null and this layer is the base map layer.
|
||||
/// </summary>
|
||||
public Brush MapBackground
|
||||
{
|
||||
get { return (Brush)GetValue(MapBackgroundProperty); }
|
||||
set { SetValue(MapBackgroundProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Optional foreground brush. Sets MapBase.Foreground if not null and this layer is the base map layer.
|
||||
/// </summary>
|
||||
public Brush MapForeground
|
||||
{
|
||||
get { return (Brush)GetValue(MapForegroundProperty); }
|
||||
set { SetValue(MapForegroundProperty, value); }
|
||||
}
|
||||
|
||||
public MapBase ParentMap
|
||||
{
|
||||
get { return parentMap; }
|
||||
set
|
||||
{
|
||||
if (parentMap != null)
|
||||
{
|
||||
parentMap.ViewportChanged -= OnViewportChanged;
|
||||
}
|
||||
|
||||
parentMap = value;
|
||||
|
||||
if (parentMap != null)
|
||||
{
|
||||
parentMap.ViewportChanged += OnViewportChanged;
|
||||
}
|
||||
|
||||
UpdateTileLayer();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnViewportChanged(object sender, ViewportChangedEventArgs e)
|
||||
{
|
||||
if (Children.Count == 0 || e.ProjectionChanged || Math.Abs(e.LongitudeOffset) > 180d)
|
||||
{
|
||||
UpdateTileLayer(); // update immediately when projection has changed or center has moved across 180° longitude
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRenderTransform();
|
||||
|
||||
if (UpdateTimer.IsEnabled && !UpdateWhileViewportChanging)
|
||||
{
|
||||
UpdateTimer.Stop(); // restart
|
||||
}
|
||||
|
||||
if (!UpdateTimer.IsEnabled)
|
||||
{
|
||||
UpdateTimer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void UpdateTileLayer();
|
||||
|
||||
protected abstract void SetRenderTransform();
|
||||
|
||||
protected abstract void TileSourcePropertyChanged();
|
||||
}
|
||||
}
|
||||
30
MapControl/Shared/MatrixFactory.cs
Normal file
30
MapControl/Shared/MatrixFactory.cs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if !WINDOWS_UWP
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public static class MatrixFactory
|
||||
{
|
||||
public static Matrix Create(Point translation1, double scaleX, double scaleY, double rotation, Point translation2)
|
||||
{
|
||||
var matrix = new Matrix(scaleX, 0d, 0d, scaleY, -scaleX * translation1.X, -scaleY * translation1.Y);
|
||||
matrix.Rotate(rotation);
|
||||
matrix.Translate(translation2.X, translation2.Y);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public static Matrix Create(double scale, double rotation, Point translation)
|
||||
{
|
||||
var matrix = new Matrix(scale, 0d, 0d, scale, 0d, 0d);
|
||||
matrix.Rotate(rotation);
|
||||
matrix.Translate(translation.X, translation.Y);
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,11 +2,9 @@
|
|||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class TileGrid : IEquatable<TileGrid>
|
||||
public class TileGrid
|
||||
{
|
||||
public readonly int ZoomLevel;
|
||||
public readonly int XMin;
|
||||
|
|
@ -22,25 +20,5 @@ namespace MapControl
|
|||
XMax = xMax;
|
||||
YMax = yMax;
|
||||
}
|
||||
|
||||
public bool Equals(TileGrid tileGrid)
|
||||
{
|
||||
return tileGrid != null
|
||||
&& tileGrid.ZoomLevel == ZoomLevel
|
||||
&& tileGrid.XMin == XMin
|
||||
&& tileGrid.YMin == YMin
|
||||
&& tileGrid.XMax == XMax
|
||||
&& tileGrid.YMax == YMax;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as TileGrid);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return ZoomLevel ^ XMin ^ YMin ^ XMax ^ YMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,8 +74,13 @@ namespace MapControl
|
|||
|
||||
try
|
||||
{
|
||||
var stream = await ImageLoader.HttpClient.GetStreamAsync(uri);
|
||||
var capabilities = XDocument.Load(stream).Root;
|
||||
XElement capabilities;
|
||||
|
||||
using (var stream = await ImageLoader.HttpClient.GetStreamAsync(uri))
|
||||
{
|
||||
capabilities = XDocument.Load(stream).Root;
|
||||
}
|
||||
|
||||
var ns = capabilities.Name.Namespace;
|
||||
|
||||
layerNames = capabilities
|
||||
|
|
|
|||
336
MapControl/Shared/WmtsTileLayer.cs
Normal file
336
MapControl/Shared/WmtsTileLayer.cs
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
#if WINDOWS_UWP
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml;
|
||||
#else
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class WmtsTileLayer : MapTileLayerBase
|
||||
{
|
||||
public static readonly DependencyProperty CapabilitiesProperty = DependencyProperty.Register(
|
||||
nameof(Capabilities), typeof(Uri), typeof(WmtsTileLayer), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty LayerIdentifierProperty = DependencyProperty.Register(
|
||||
nameof(LayerIdentifier), typeof(string), typeof(WmtsTileLayer), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty TileMatrixSetProperty = DependencyProperty.Register(
|
||||
nameof(TileMatrixSet), typeof(WmtsTileMatrixSet), typeof(WmtsTileLayer),
|
||||
new PropertyMetadata(null, (o, e) => ((WmtsTileLayer)o).UpdateTileLayer()));
|
||||
|
||||
public WmtsTileLayer()
|
||||
: this(new TileImageLoader())
|
||||
{
|
||||
}
|
||||
|
||||
public WmtsTileLayer(ITileImageLoader tileImageLoader)
|
||||
: base(tileImageLoader)
|
||||
{
|
||||
Loaded += OnLoaded;
|
||||
}
|
||||
|
||||
public Uri Capabilities
|
||||
{
|
||||
get { return (Uri)GetValue(CapabilitiesProperty); }
|
||||
set { SetValue(CapabilitiesProperty, value); }
|
||||
}
|
||||
|
||||
public string LayerIdentifier
|
||||
{
|
||||
get { return (string)GetValue(LayerIdentifierProperty); }
|
||||
set { SetValue(LayerIdentifierProperty, value); }
|
||||
}
|
||||
|
||||
public WmtsTileMatrixSet TileMatrixSet
|
||||
{
|
||||
get { return (WmtsTileMatrixSet)GetValue(TileMatrixSetProperty); }
|
||||
set { SetValue(TileMatrixSetProperty, value); }
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
foreach (var layer in Children.Cast<WmtsTileMatrixLayer>())
|
||||
{
|
||||
layer.Measure(availableSize);
|
||||
}
|
||||
|
||||
return new Size();
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (var layer in Children.Cast<WmtsTileMatrixLayer>())
|
||||
{
|
||||
layer.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
protected override void TileSourcePropertyChanged()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void UpdateTileLayer()
|
||||
{
|
||||
UpdateTimer.Stop();
|
||||
|
||||
if (ParentMap == null ||
|
||||
TileMatrixSet == null ||
|
||||
ParentMap.MapProjection.CrsId != TileMatrixSet.SupportedCrs)
|
||||
{
|
||||
Children.Clear();
|
||||
UpdateTiles();
|
||||
}
|
||||
else if (UpdateChildLayers())
|
||||
{
|
||||
SetRenderTransform();
|
||||
UpdateTiles();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SetRenderTransform()
|
||||
{
|
||||
foreach (var layer in Children.Cast<WmtsTileMatrixLayer>())
|
||||
{
|
||||
layer.SetRenderTransform(ParentMap.MapProjection, ParentMap.Heading);
|
||||
}
|
||||
}
|
||||
|
||||
private bool UpdateChildLayers()
|
||||
{
|
||||
bool layersChanged = false;
|
||||
|
||||
if (TileMatrixSet != null)
|
||||
{
|
||||
// show all TileMatrix layers with Scale <= ViewportScale, or at least the first layer
|
||||
//
|
||||
var currentMatrixes = TileMatrixSet.TileMatrixes
|
||||
.Where((matrix, i) => i == 0 || matrix.Scale <= ParentMap.MapProjection.ViewportScale)
|
||||
.ToList();
|
||||
|
||||
if (this != ParentMap.MapLayer) // do not load background tiles
|
||||
{
|
||||
currentMatrixes = currentMatrixes.Skip(currentMatrixes.Count - 1).ToList(); // last element only
|
||||
}
|
||||
|
||||
var currentLayers = Children.Cast<WmtsTileMatrixLayer>()
|
||||
.Where(layer => currentMatrixes.Contains(layer.TileMatrix))
|
||||
.ToList();
|
||||
|
||||
Children.Clear();
|
||||
|
||||
foreach (var tileMatrix in currentMatrixes)
|
||||
{
|
||||
var layer = currentLayers.FirstOrDefault(l => l.TileMatrix == tileMatrix);
|
||||
|
||||
if (layer == null)
|
||||
{
|
||||
layer = new WmtsTileMatrixLayer(tileMatrix, TileMatrixSet.TileMatrixes.IndexOf(tileMatrix));
|
||||
layersChanged = true;
|
||||
}
|
||||
|
||||
if (layer.SetBounds(ParentMap.MapProjection, ParentMap.Heading, ParentMap.RenderSize))
|
||||
{
|
||||
layersChanged = true;
|
||||
}
|
||||
|
||||
Children.Add(layer);
|
||||
}
|
||||
}
|
||||
|
||||
return layersChanged;
|
||||
}
|
||||
|
||||
private void UpdateTiles()
|
||||
{
|
||||
var tiles = new List<Tile>();
|
||||
|
||||
foreach (var layer in Children.Cast<WmtsTileMatrixLayer>())
|
||||
{
|
||||
layer.UpdateTiles();
|
||||
|
||||
tiles.AddRange(layer.Tiles);
|
||||
}
|
||||
|
||||
TileImageLoader.LoadTilesAsync(tiles, TileSource, SourceName);
|
||||
}
|
||||
|
||||
private async void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Capabilities != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Capabilities.IsAbsoluteUri && (Capabilities.Scheme == "http" || Capabilities.Scheme == "https"))
|
||||
{
|
||||
using (var stream = await ImageLoader.HttpClient.GetStreamAsync(Capabilities))
|
||||
{
|
||||
ReadCapabilities(XDocument.Load(stream).Root);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadCapabilities(XDocument.Load(Capabilities.ToString()).Root);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("WmtsTileLayer: {0}: {1}", Capabilities, ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadCapabilities(XElement capabilities)
|
||||
{
|
||||
var ns = capabilities.Name.Namespace;
|
||||
var contentsElement = capabilities.Element(ns + "Contents");
|
||||
|
||||
if (contentsElement == null)
|
||||
{
|
||||
throw new ArgumentException("Contents element not found.");
|
||||
}
|
||||
|
||||
XNamespace ows = "http://www.opengis.net/ows/1.1";
|
||||
XElement layerElement;
|
||||
|
||||
if (!string.IsNullOrEmpty(LayerIdentifier))
|
||||
{
|
||||
layerElement = contentsElement.Descendants(ns + "Layer")
|
||||
.FirstOrDefault(e => e.Element(ows + "Identifier")?.Value == LayerIdentifier);
|
||||
|
||||
if (layerElement == null)
|
||||
{
|
||||
throw new ArgumentException("Layer element \"" + LayerIdentifier + "\" not found.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
layerElement = capabilities.Descendants(ns + "Layer").FirstOrDefault();
|
||||
|
||||
if (layerElement == null)
|
||||
{
|
||||
throw new ArgumentException("No Layer element found.");
|
||||
}
|
||||
|
||||
LayerIdentifier = layerElement.Element(ows + "Identifier")?.Value ?? "";
|
||||
}
|
||||
|
||||
var tileMatrixSetId = layerElement.Element(ns + "TileMatrixSetLink")?.Element(ns + "TileMatrixSet")?.Value;
|
||||
|
||||
if (tileMatrixSetId == null)
|
||||
{
|
||||
throw new ArgumentException("TileMatrixSetLink element not found.");
|
||||
}
|
||||
|
||||
var urlTemplate = layerElement.Element(ns + "ResourceURL")?.Attribute("template")?.Value;
|
||||
|
||||
if (urlTemplate == null)
|
||||
{
|
||||
throw new ArgumentException("ResourceURL element (or template attribute) not found in Layer \"" + LayerIdentifier + "\".");
|
||||
}
|
||||
|
||||
var tileMatrixSetElement = capabilities.Descendants(ns + "TileMatrixSet")
|
||||
.FirstOrDefault(e => e.Element(ows + "Identifier")?.Value == tileMatrixSetId);
|
||||
|
||||
if (tileMatrixSetElement == null)
|
||||
{
|
||||
throw new ArgumentException("Linked TileMatrixSet element not found in Layer \"" + LayerIdentifier + "\".");
|
||||
}
|
||||
|
||||
var supportedCrs = tileMatrixSetElement.Element(ows + "SupportedCRS")?.Value;
|
||||
|
||||
if (supportedCrs == null)
|
||||
{
|
||||
throw new ArgumentException("ows:SupportedCRS element not found in TileMatrixSet \"" + tileMatrixSetId + "\".");
|
||||
}
|
||||
|
||||
var tileMatrixes = new List<WmtsTileMatrix>();
|
||||
|
||||
foreach (var tileMatrix in tileMatrixSetElement.Descendants(ns + "TileMatrix"))
|
||||
{
|
||||
var tileMatrixId = tileMatrix.Element(ows + "Identifier")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(tileMatrixId))
|
||||
{
|
||||
throw new ArgumentException("ows:Identifier element not found in TileMatrix.");
|
||||
}
|
||||
|
||||
string[] topLeftCornerStrings;
|
||||
double scaleDenominator, top, left;
|
||||
int tileWidth, tileHeight, matrixWidth, matrixHeight;
|
||||
|
||||
var valueString = tileMatrix.Element(ns + "ScaleDenominator")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(valueString) ||
|
||||
!double.TryParse(valueString, NumberStyles.Float, CultureInfo.InvariantCulture, out scaleDenominator))
|
||||
{
|
||||
throw new ArgumentException("ScaleDenominator element not found in TileMatrix \"" + tileMatrixId + "\".");
|
||||
}
|
||||
|
||||
valueString = tileMatrix.Element(ns + "TopLeftCorner")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(valueString) ||
|
||||
(topLeftCornerStrings = valueString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)).Length < 2 ||
|
||||
!double.TryParse(topLeftCornerStrings[0], NumberStyles.Float, CultureInfo.InvariantCulture, out left) ||
|
||||
!double.TryParse(topLeftCornerStrings[1], NumberStyles.Float, CultureInfo.InvariantCulture, out top))
|
||||
{
|
||||
throw new ArgumentException("TopLeftCorner element not found in TileMatrix \"" + tileMatrixId + "\".");
|
||||
}
|
||||
|
||||
valueString = tileMatrix.Element(ns + "TileWidth")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(valueString) || !int.TryParse(valueString, out tileWidth))
|
||||
{
|
||||
throw new ArgumentException("TileWidth element not found in TileMatrix \"" + tileMatrixId + "\".");
|
||||
}
|
||||
|
||||
valueString = tileMatrix.Element(ns + "TileHeight")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(valueString) || !int.TryParse(valueString, out tileHeight))
|
||||
{
|
||||
throw new ArgumentException("TileHeight element not found in TileMatrix \"" + tileMatrixId + "\".");
|
||||
}
|
||||
|
||||
valueString = tileMatrix.Element(ns + "MatrixWidth")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(valueString) || !int.TryParse(valueString, out matrixWidth))
|
||||
{
|
||||
throw new ArgumentException("MatrixWidth element not found in TileMatrix \"" + tileMatrixId + "\".");
|
||||
}
|
||||
|
||||
valueString = tileMatrix.Element(ns + "MatrixHeight")?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(valueString) || !int.TryParse(valueString, out matrixHeight))
|
||||
{
|
||||
throw new ArgumentException("MatrixHeight element not found in TileMatrix \"" + tileMatrixId + "\".");
|
||||
}
|
||||
|
||||
tileMatrixes.Add(new WmtsTileMatrix(
|
||||
tileMatrixId, scaleDenominator, new Point(left, top), tileWidth, tileHeight, matrixWidth, matrixHeight));
|
||||
}
|
||||
|
||||
if (tileMatrixes.Count <= 0)
|
||||
{
|
||||
throw new ArgumentException("No TileMatrix elements found in TileMatrixSet \"" + tileMatrixSetId + "\".");
|
||||
}
|
||||
|
||||
var tileMatrixSet = new WmtsTileMatrixSet(tileMatrixSetId, supportedCrs, tileMatrixes);
|
||||
|
||||
SourceName = tileMatrixSet.Identifier;
|
||||
TileSource = new WmtsTileSource(urlTemplate, tileMatrixSet);
|
||||
TileMatrixSet = tileMatrixSet; // calls UpdateTileLayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
33
MapControl/Shared/WmtsTileMatrix.cs
Normal file
33
MapControl/Shared/WmtsTileMatrix.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if !WINDOWS_UWP
|
||||
using System.Windows;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class WmtsTileMatrix
|
||||
{
|
||||
public WmtsTileMatrix(string identifier, double scaleDenominator, Point topLeft,
|
||||
int tileWidth, int tileHeight, int matrixWidth, int matrixHeight)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Scale = 1 / (scaleDenominator * 0.00028);
|
||||
TopLeft = topLeft;
|
||||
TileWidth = tileWidth;
|
||||
TileHeight = tileHeight;
|
||||
MatrixWidth = matrixWidth;
|
||||
MatrixHeight = matrixHeight;
|
||||
}
|
||||
|
||||
public string Identifier { get; }
|
||||
public double Scale { get; }
|
||||
public Point TopLeft { get; }
|
||||
public int TileWidth { get; }
|
||||
public int TileHeight { get; }
|
||||
public int MatrixWidth { get; }
|
||||
public int MatrixHeight { get; }
|
||||
}
|
||||
}
|
||||
147
MapControl/Shared/WmtsTileMatrixLayer.cs
Normal file
147
MapControl/Shared/WmtsTileMatrixLayer.cs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if WINDOWS_UWP
|
||||
using Windows.Foundation;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#else
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class WmtsTileMatrixLayer : Panel
|
||||
{
|
||||
public WmtsTileMatrixLayer(WmtsTileMatrix tileMatrix, int zoomLevel)
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
RenderTransform = new MatrixTransform();
|
||||
TileMatrix = tileMatrix;
|
||||
ZoomLevel = zoomLevel;
|
||||
}
|
||||
|
||||
public WmtsTileMatrix TileMatrix { get; }
|
||||
public int ZoomLevel { get; }
|
||||
public int XMin { get; private set; }
|
||||
public int YMin { get; private set; }
|
||||
public int XMax { get; private set; }
|
||||
public int YMax { get; private set; }
|
||||
|
||||
public IReadOnlyCollection<Tile> Tiles { get; private set; } = new List<Tile>();
|
||||
|
||||
public bool SetBounds(MapProjection projection, double heading, Size mapSize)
|
||||
{
|
||||
// top/left viewport corner in map coordinates
|
||||
//
|
||||
var tileOrigin = projection.InverseViewportTransform.Transform(new Point());
|
||||
|
||||
// top/left viewport corner in tile matrix coordinates
|
||||
//
|
||||
var tileMatrixOrigin = new Point(
|
||||
TileMatrix.Scale * (tileOrigin.X - TileMatrix.TopLeft.X),
|
||||
TileMatrix.Scale * (TileMatrix.TopLeft.Y - tileOrigin.Y));
|
||||
|
||||
var transform = new MatrixTransform
|
||||
{
|
||||
Matrix = MatrixFactory.Create(1, -heading, tileMatrixOrigin)
|
||||
};
|
||||
|
||||
var bounds = transform.TransformBounds(new Rect(0d, 0d, mapSize.Width, mapSize.Height));
|
||||
|
||||
var xMin = (int)Math.Floor(bounds.X / TileMatrix.TileWidth);
|
||||
var yMin = (int)Math.Floor(bounds.Y / TileMatrix.TileHeight);
|
||||
var xMax = (int)Math.Floor((bounds.X + bounds.Width) / TileMatrix.TileWidth);
|
||||
var yMax = (int)Math.Floor((bounds.Y + bounds.Height) / TileMatrix.TileHeight);
|
||||
|
||||
xMin = Math.Max(xMin, 0);
|
||||
yMin = Math.Max(yMin, 0);
|
||||
xMax = Math.Min(Math.Max(xMax, 0), TileMatrix.MatrixWidth - 1);
|
||||
yMax = Math.Min(Math.Max(yMax, 0), TileMatrix.MatrixHeight - 1);
|
||||
|
||||
if (XMin == xMin && YMin == yMin && XMax == xMax && YMax == yMax)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
XMin = xMin;
|
||||
YMin = yMin;
|
||||
XMax = xMax;
|
||||
YMax = yMax;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void SetRenderTransform(MapProjection projection, double heading)
|
||||
{
|
||||
// XMin/YMin corner in map and viewport coordinates
|
||||
//
|
||||
var mapOrigin = new Point(
|
||||
TileMatrix.TopLeft.X + XMin * TileMatrix.TileWidth / TileMatrix.Scale,
|
||||
TileMatrix.TopLeft.Y - YMin * TileMatrix.TileHeight / TileMatrix.Scale);
|
||||
|
||||
var viewOrigin = projection.ViewportTransform.Transform(mapOrigin);
|
||||
|
||||
var tileScale = projection.ViewportScale / TileMatrix.Scale; // relative scale
|
||||
|
||||
((MatrixTransform)RenderTransform).Matrix = MatrixFactory.Create(tileScale, heading, viewOrigin);
|
||||
}
|
||||
|
||||
public void UpdateTiles()
|
||||
{
|
||||
var newTiles = new List<Tile>();
|
||||
|
||||
for (var y = YMin; y <= YMax; y++)
|
||||
{
|
||||
for (var x = XMin; x <= XMax; x++)
|
||||
{
|
||||
newTiles.Add(Tiles.FirstOrDefault(t => t.X == x && t.Y == y) ?? new Tile(ZoomLevel, x, y));
|
||||
}
|
||||
}
|
||||
|
||||
Tiles = newTiles;
|
||||
|
||||
Children.Clear();
|
||||
|
||||
foreach (var tile in Tiles)
|
||||
{
|
||||
Children.Add(tile.Image);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
availableSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
|
||||
|
||||
foreach (var tile in Tiles)
|
||||
{
|
||||
tile.Image.Measure(availableSize);
|
||||
}
|
||||
|
||||
return new Size();
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
foreach (var tile in Tiles)
|
||||
{
|
||||
// arrange tiles relative to XMin/YMin
|
||||
//
|
||||
var x = TileMatrix.TileWidth * (tile.X - XMin);
|
||||
var y = TileMatrix.TileHeight * (tile.Y - YMin);
|
||||
|
||||
tile.Image.Width = TileMatrix.TileWidth;
|
||||
tile.Image.Height = TileMatrix.TileHeight;
|
||||
tile.Image.Arrange(new Rect(x, y, TileMatrix.TileWidth, TileMatrix.TileHeight));
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
MapControl/Shared/WmtsTileMatrixSet.cs
Normal file
39
MapControl/Shared/WmtsTileMatrixSet.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class WmtsTileMatrixSet
|
||||
{
|
||||
public WmtsTileMatrixSet(string identifier, string supportedCrs, IEnumerable<WmtsTileMatrix> tileMatrixes)
|
||||
{
|
||||
if (string.IsNullOrEmpty(identifier))
|
||||
{
|
||||
throw new ArgumentException("The parameter identifier must not be null or empty.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(supportedCrs))
|
||||
{
|
||||
throw new ArgumentException("The parameter supportedCrs must not be null or empty.");
|
||||
}
|
||||
|
||||
if (tileMatrixes == null || tileMatrixes.Count() <= 0)
|
||||
{
|
||||
throw new ArgumentException("The parameter tileMatrixes must not be null or an empty collection.");
|
||||
}
|
||||
|
||||
Identifier = identifier;
|
||||
SupportedCrs = supportedCrs;
|
||||
TileMatrixes = tileMatrixes.OrderBy(m => m.Scale).ToList();
|
||||
}
|
||||
|
||||
public string Identifier { get; }
|
||||
public string SupportedCrs { get; }
|
||||
public IList<WmtsTileMatrix> TileMatrixes { get; }
|
||||
}
|
||||
}
|
||||
35
MapControl/Shared/WmtsTileSource.cs
Normal file
35
MapControl/Shared/WmtsTileSource.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2020 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public class WmtsTileSource : TileSource
|
||||
{
|
||||
private readonly IList<WmtsTileMatrix> tileMatrixes;
|
||||
|
||||
public WmtsTileSource(string uriFormat, WmtsTileMatrixSet tileMatrixSet)
|
||||
: base(uriFormat.Replace("{TileMatrixSet}", tileMatrixSet.Identifier))
|
||||
{
|
||||
tileMatrixes = tileMatrixSet.TileMatrixes;
|
||||
}
|
||||
|
||||
public override Uri GetUri(int x, int y, int zoomLevel)
|
||||
{
|
||||
if (zoomLevel < 0 || zoomLevel >= tileMatrixes.Count)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var url = UriFormat
|
||||
.Replace("{TileMatrix}", tileMatrixes[zoomLevel].Identifier)
|
||||
.Replace("{TileCol}", x.ToString())
|
||||
.Replace("{TileRow}", y.ToString());
|
||||
|
||||
return new Uri(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,12 +3,18 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -125,6 +125,12 @@
|
|||
<Compile Include="..\Shared\MapTileLayer.cs">
|
||||
<Link>MapTileLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MapTileLayerBase.cs">
|
||||
<Link>MapTileLayerBase.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\MatrixFactory.cs">
|
||||
<Link>MatrixFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\OrthographicProjection.cs">
|
||||
<Link>OrthographicProjection.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -155,6 +161,21 @@
|
|||
<Compile Include="..\Shared\WmsImageLayer.cs">
|
||||
<Link>WmsImageLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\WmtsTileLayer.cs">
|
||||
<Link>WmtsTileLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\WmtsTileMatrix.cs">
|
||||
<Link>WmtsTileMatrix.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\WmtsTileMatrixLayer.cs">
|
||||
<Link>WmtsTileMatrixLayer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\WmtsTileMatrixSet.cs">
|
||||
<Link>WmtsTileMatrixSet.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\WmtsTileSource.cs">
|
||||
<Link>WmtsTileSource.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Shared\WorldMercatorProjection.cs">
|
||||
<Link>WorldMercatorProjection.cs</Link>
|
||||
</Compile>
|
||||
|
|
@ -179,7 +200,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<AssemblyOriginatorKeyFile>..\..\MapControl.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>false</DelaySign>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>4.16.0</Version>
|
||||
<Version>4.17.0</Version>
|
||||
<Description>XAML Map Control Library</Description>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2020 Clemens Fischer</Copyright>
|
||||
|
|
@ -45,5 +45,4 @@
|
|||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Runtime.Caching" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="ProjNET4GeoAPI">
|
||||
<Version>1.4.1</Version>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Data.SQLite.Core">
|
||||
<Version>1.0.112</Version>
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using MapControl;
|
||||
using System;
|
||||
using ViewModel;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
|
@ -13,12 +14,29 @@ namespace UniversalApp
|
|||
public MainPage()
|
||||
{
|
||||
ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Test Application");
|
||||
//TileImageLoader.Cache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder);
|
||||
TileImageLoader.Cache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder);
|
||||
//TileImageLoader.Cache = new MapControl.Caching.FileDbCache(TileImageLoader.DefaultCacheFolder);
|
||||
//TileImageLoader.Cache = new MapControl.Caching.SQLiteCache(TileImageLoader.DefaultCacheFolder);
|
||||
|
||||
InitializeComponent();
|
||||
DataContext = ViewModel;
|
||||
|
||||
Loaded += MainWindow_Loaded;
|
||||
}
|
||||
|
||||
private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var seachartLayer = new WmsImageLayer
|
||||
{
|
||||
ServiceUri = new Uri("https://wms.sevencs.com:9090")
|
||||
};
|
||||
|
||||
var layers = await seachartLayer.GetLayerNamesAsync();
|
||||
|
||||
foreach (var layer in layers)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(layer);
|
||||
}
|
||||
}
|
||||
|
||||
private void ImageOpacitySliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform">
|
||||
<Version>6.2.9</Version>
|
||||
<Version>6.2.10</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("4.16.0")]
|
||||
[assembly: AssemblyFileVersion("4.16.0")]
|
||||
[assembly: AssemblyVersion("4.17.0")]
|
||||
[assembly: AssemblyFileVersion("4.17.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@
|
|||
<Project>{62f1726b-3144-49f4-8bcc-94160a3b2186}</Project>
|
||||
<Name>MapControl.WPF</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\SQLiteCache\WPF\SQLiteCache.WPF.csproj">
|
||||
<Project>{0109c2f0-ba2c-420f-b2ca-db5b29b1a349}</Project>
|
||||
<Name>SQLiteCache.WPF</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<UseWPF>true</UseWPF>
|
||||
<RootNamespace>WpfCoreApp</RootNamespace>
|
||||
<Product>XAML Map Control</Product>
|
||||
<Version>4.16.0</Version>
|
||||
<Version>4.17.0</Version>
|
||||
<Description>XAML Map Control WPF Sample Application</Description>
|
||||
<Authors>Clemens Fischer</Authors>
|
||||
<Copyright>Copyright © 2020 Clemens Fischer</Copyright>
|
||||
|
|
|
|||
Loading…
Reference in a new issue