mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2026-04-04 14:08:32 +00:00
Version 7.0: WinUI
This commit is contained in:
parent
448f599d96
commit
9f61b90795
56 changed files with 94 additions and 81 deletions
|
|
@ -1,55 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media.Animation;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
internal static class Animatable
|
||||
{
|
||||
public static void BeginAnimation(this DependencyObject obj, DependencyProperty property, Timeline animation)
|
||||
{
|
||||
if (animation != null)
|
||||
{
|
||||
string propertyName = null;
|
||||
|
||||
if (property == MapBase.CenterPointProperty)
|
||||
{
|
||||
propertyName = "CenterPoint";
|
||||
((PointAnimation)animation).EnableDependentAnimation = true;
|
||||
}
|
||||
else if (property == MapBase.ZoomLevelProperty)
|
||||
{
|
||||
propertyName = "ZoomLevel";
|
||||
((DoubleAnimation)animation).EnableDependentAnimation = true;
|
||||
}
|
||||
else if (property == MapBase.HeadingProperty)
|
||||
{
|
||||
propertyName = "Heading";
|
||||
((DoubleAnimation)animation).EnableDependentAnimation = true;
|
||||
}
|
||||
else if (property == UIElement.OpacityProperty)
|
||||
{
|
||||
propertyName = "Opacity";
|
||||
}
|
||||
|
||||
if (propertyName != null)
|
||||
{
|
||||
Storyboard.SetTargetProperty(animation, propertyName);
|
||||
Storyboard.SetTarget(animation, obj);
|
||||
|
||||
var storyboard = new Storyboard();
|
||||
storyboard.Children.Add(animation);
|
||||
storyboard.Begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MapControl.Caching
|
||||
{
|
||||
public partial class ImageFileCache : IImageCache
|
||||
{
|
||||
public async Task<Tuple<byte[], DateTime>> GetAsync(string key)
|
||||
{
|
||||
Tuple<byte[], DateTime> cacheItem = null;
|
||||
var path = GetPath(key);
|
||||
|
||||
try
|
||||
{
|
||||
if (path != null && File.Exists(path))
|
||||
{
|
||||
var buffer = await File.ReadAllBytesAsync(path);
|
||||
var expiration = ReadExpiration(ref buffer);
|
||||
|
||||
cacheItem = Tuple.Create(buffer, expiration);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"ImageFileCache: Failed reading {path}: {ex.Message}");
|
||||
}
|
||||
|
||||
return cacheItem;
|
||||
}
|
||||
|
||||
public async Task SetAsync(string key, byte[] buffer, DateTime expiration)
|
||||
{
|
||||
var path = GetPath(key);
|
||||
|
||||
if (buffer != null && buffer.Length > 0 && path != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
using (var stream = File.Create(path))
|
||||
{
|
||||
await stream.WriteAsync(buffer, 0, buffer.Length);
|
||||
await WriteExpirationAsync(stream, expiration);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"ImageFileCache: Failed writing {path}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Streams;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public static partial class ImageLoader
|
||||
{
|
||||
public static async Task<ImageSource> LoadImageAsync(IRandomAccessStream stream)
|
||||
{
|
||||
var image = new BitmapImage();
|
||||
|
||||
await image.SetSourceAsync(stream);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public static Task<ImageSource> LoadImageAsync(Stream stream)
|
||||
{
|
||||
return LoadImageAsync(stream.AsRandomAccessStream());
|
||||
}
|
||||
|
||||
public static Task<ImageSource> LoadImageAsync(byte[] buffer)
|
||||
{
|
||||
using (var stream = new MemoryStream(buffer))
|
||||
{
|
||||
return LoadImageAsync(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<ImageSource> LoadImageAsync(string path)
|
||||
{
|
||||
ImageSource image = null;
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var file = await StorageFile.GetFileFromPathAsync(Path.GetFullPath(path));
|
||||
|
||||
using (var stream = await file.OpenReadAsync())
|
||||
{
|
||||
image = await LoadImageAsync(stream);
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Input;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// MapBase with default input event handling.
|
||||
/// </summary>
|
||||
public class Map : MapBase
|
||||
{
|
||||
public static readonly DependencyProperty MouseWheelZoomDeltaProperty = DependencyProperty.Register(
|
||||
nameof(MouseWheelZoomDelta), typeof(double), typeof(Map), new PropertyMetadata(1d));
|
||||
|
||||
public Map()
|
||||
{
|
||||
ManipulationMode = ManipulationModes.Scale
|
||||
| ManipulationModes.TranslateX
|
||||
| ManipulationModes.TranslateY
|
||||
| ManipulationModes.TranslateInertia;
|
||||
|
||||
ManipulationDelta += OnManipulationDelta;
|
||||
PointerWheelChanged += OnPointerWheelChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
|
||||
/// The default value is 1.
|
||||
/// </summary>
|
||||
public double MouseWheelZoomDelta
|
||||
{
|
||||
get { return (double)GetValue(MouseWheelZoomDeltaProperty); }
|
||||
set { SetValue(MouseWheelZoomDeltaProperty, value); }
|
||||
}
|
||||
|
||||
private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
|
||||
{
|
||||
TransformMap(e.Position, e.Delta.Translation, e.Delta.Rotation, e.Delta.Scale);
|
||||
}
|
||||
|
||||
private void OnPointerWheelChanged(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
var point = e.GetCurrentPoint(this);
|
||||
var zoomLevel = TargetZoomLevel + MouseWheelZoomDelta * Math.Sign(point.Properties.MouseWheelDelta);
|
||||
|
||||
ZoomMap(point.Position, MouseWheelZoomDelta * Math.Round(zoomLevel / MouseWheelZoomDelta));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINUI
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#else
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapBase
|
||||
{
|
||||
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
|
||||
nameof(Foreground), typeof(Brush), typeof(MapBase), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
|
||||
|
||||
public static readonly DependencyProperty CenterProperty = DependencyProperty.Register(
|
||||
nameof(Center), typeof(Location), typeof(MapBase),
|
||||
new PropertyMetadata(new Location(), (o, e) => ((MapBase)o).CenterPropertyChanged((Location)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty TargetCenterProperty = DependencyProperty.Register(
|
||||
nameof(TargetCenter), typeof(Location), typeof(MapBase),
|
||||
new PropertyMetadata(new Location(), (o, e) => ((MapBase)o).TargetCenterPropertyChanged((Location)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty ZoomLevelProperty = DependencyProperty.Register(
|
||||
nameof(ZoomLevel), typeof(double), typeof(MapBase),
|
||||
new PropertyMetadata(1d, (o, e) => ((MapBase)o).ZoomLevelPropertyChanged((double)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty TargetZoomLevelProperty = DependencyProperty.Register(
|
||||
nameof(TargetZoomLevel), typeof(double), typeof(MapBase),
|
||||
new PropertyMetadata(1d, (o, e) => ((MapBase)o).TargetZoomLevelPropertyChanged((double)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty HeadingProperty = DependencyProperty.Register(
|
||||
nameof(Heading), typeof(double), typeof(MapBase),
|
||||
new PropertyMetadata(0d, (o, e) => ((MapBase)o).HeadingPropertyChanged((double)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty TargetHeadingProperty = DependencyProperty.Register(
|
||||
nameof(TargetHeading), typeof(double), typeof(MapBase),
|
||||
new PropertyMetadata(0d, (o, e) => ((MapBase)o).TargetHeadingPropertyChanged((double)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty ViewScaleProperty = DependencyProperty.Register(
|
||||
nameof(ViewScale), typeof(double), typeof(MapBase), new PropertyMetadata(0d));
|
||||
|
||||
internal static readonly DependencyProperty CenterPointProperty = DependencyProperty.Register(
|
||||
"CenterPoint", typeof(Windows.Foundation.Point), typeof(MapBase),
|
||||
new PropertyMetadata(new Windows.Foundation.Point(), (o, e) =>
|
||||
{
|
||||
var center = (Windows.Foundation.Point)e.NewValue;
|
||||
((MapBase)o).CenterPointPropertyChanged(new Location(center.Y, center.X));
|
||||
}));
|
||||
|
||||
public MapBase()
|
||||
{
|
||||
// set Background by Style to enable resetting by ClearValue in MapLayerPropertyChanged
|
||||
var style = new Style(typeof(MapBase));
|
||||
style.Setters.Add(new Setter(BackgroundProperty, new SolidColorBrush(Colors.White)));
|
||||
Style = style;
|
||||
|
||||
SizeChanged += OnSizeChanged;
|
||||
}
|
||||
|
||||
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
Clip = new RectangleGeometry
|
||||
{
|
||||
Rect = new Windows.Foundation.Rect(0d, 0d, e.NewSize.Width, e.NewSize.Height)
|
||||
};
|
||||
|
||||
ResetTransformCenter();
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
private void SetViewScale(double scale)
|
||||
{
|
||||
SetValue(ViewScaleProperty, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// ContentControl placed on a MapPanel at a geographic location specified by the Location property.
|
||||
/// </summary>
|
||||
public class MapContentControl : ContentControl
|
||||
{
|
||||
public static readonly DependencyProperty AutoCollapseProperty = DependencyProperty.Register(
|
||||
nameof(AutoCollapse), typeof(bool), typeof(MapContentControl),
|
||||
new PropertyMetadata(false, (o, e) => MapPanel.SetAutoCollapse((MapContentControl)o, (bool)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty LocationProperty = DependencyProperty.Register(
|
||||
nameof(Location), typeof(Location), typeof(MapContentControl),
|
||||
new PropertyMetadata(null, (o, e) => MapPanel.SetLocation((MapContentControl)o, (Location)e.NewValue)));
|
||||
|
||||
public MapContentControl()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapContentControl);
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets MapPanel.AutoCollapse.
|
||||
/// </summary>
|
||||
public bool AutoCollapse
|
||||
{
|
||||
get { return (bool)GetValue(AutoCollapseProperty); }
|
||||
set { SetValue(AutoCollapseProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets MapPanel.Location.
|
||||
/// </summary>
|
||||
public Location Location
|
||||
{
|
||||
get { return (Location)GetValue(LocationProperty); }
|
||||
set { SetValue(LocationProperty, value); }
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
var parentMap = MapPanel.GetParentMap(this);
|
||||
|
||||
if (parentMap != null)
|
||||
{
|
||||
this.ValidateProperty(BackgroundProperty, parentMap, nameof(MapBase.Background));
|
||||
this.ValidateProperty(BorderBrushProperty, parentMap, nameof(MapBase.Foreground));
|
||||
this.ValidateProperty(ForegroundProperty, parentMap, nameof(MapBase.Foreground));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MapContentControl with a Pushpin Style.
|
||||
/// </summary>
|
||||
public class Pushpin : MapContentControl
|
||||
{
|
||||
public Pushpin()
|
||||
{
|
||||
DefaultStyleKey = typeof(Pushpin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;WINDOWS_UWP</DefineConstants>
|
||||
<DefineConstants>DEBUG;UWP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>WINDOWS_UWP</DefineConstants>
|
||||
<DefineConstants>UWP</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<GenerateLibraryLayout>true</GenerateLibraryLayout>
|
||||
|
|
@ -182,23 +182,53 @@
|
|||
<Compile Include="..\Shared\WorldMercatorProjection.cs">
|
||||
<Link>WorldMercatorProjection.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Animatable.UWP.cs" />
|
||||
<Compile Include="ImageFileCache.UWP.cs" />
|
||||
<Compile Include="Map.UWP.cs" />
|
||||
<Compile Include="MapBase.UWP.cs" />
|
||||
<Compile Include="MapGraticule.UWP.cs" />
|
||||
<Compile Include="MapItemsControl.UWP.cs" />
|
||||
<Compile Include="MapOverlay.UWP.cs" />
|
||||
<Compile Include="MapPanel.UWP.cs" />
|
||||
<Compile Include="MapPath.UWP.cs" />
|
||||
<Compile Include="Matrix.UWP.cs" />
|
||||
<Compile Include="Point.UWP.cs" />
|
||||
<Compile Include="..\WinUI\Animatable.WinUI.cs">
|
||||
<Link>Animatable.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\ImageFileCache.WinUI.cs">
|
||||
<Link>ImageFileCache.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\ImageLoader.WinUI.cs">
|
||||
<Link>ImageLoader.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Map.WinUI.cs">
|
||||
<Link>Map.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapBase.WinUI.cs">
|
||||
<Link>MapBase.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapContentControl.WinUI.cs">
|
||||
<Link>MapContentControl.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapGraticule.WinUI.cs">
|
||||
<Link>MapGraticule.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapItemsControl.WinUI.cs">
|
||||
<Link>MapItemsControl.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapOverlay.WinUI.cs">
|
||||
<Link>MapOverlay.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapPanel.WinUI.cs">
|
||||
<Link>MapPanel.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\MapPath.WinUI.cs">
|
||||
<Link>MapPath.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Matrix.WinUI.cs">
|
||||
<Link>Matrix.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Point.WinUI.cs">
|
||||
<Link>Point.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Tile.WinUI.cs">
|
||||
<Link>Tile.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\WinUI\Vector.WinUI.cs">
|
||||
<Link>Vector.WinUI.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="MapContentControl.UWP.cs" />
|
||||
<Compile Include="Tile.UWP.cs" />
|
||||
<Compile Include="TileImageLoader.UWP.cs" />
|
||||
<Compile Include="ImageLoader.UWP.cs" />
|
||||
<Compile Include="Vector.UWP.cs" />
|
||||
<EmbeddedResource Include="Properties\MapControl.UWP.rd.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,170 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using Windows.Foundation;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
#else
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Shapes;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapGraticule
|
||||
{
|
||||
private Path path;
|
||||
|
||||
public MapGraticule()
|
||||
{
|
||||
StrokeThickness = 0.5;
|
||||
}
|
||||
|
||||
protected override void OnViewportChanged(ViewportChangedEventArgs e)
|
||||
{
|
||||
var map = ParentMap;
|
||||
var projection = map.MapProjection;
|
||||
|
||||
if (projection.IsNormalCylindrical)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
path = new Path { Data = new PathGeometry() };
|
||||
path.SetBinding(Shape.StrokeProperty, this.GetBinding(nameof(Stroke)));
|
||||
path.SetBinding(Shape.StrokeThicknessProperty, this.GetBinding(nameof(StrokeThickness)));
|
||||
path.SetBinding(Shape.StrokeDashArrayProperty, this.GetBinding(nameof(StrokeDashArray)));
|
||||
path.SetBinding(Shape.StrokeDashOffsetProperty, this.GetBinding(nameof(StrokeDashOffset)));
|
||||
path.SetBinding(Shape.StrokeDashCapProperty, this.GetBinding(nameof(StrokeDashCap)));
|
||||
Children.Add(path);
|
||||
}
|
||||
|
||||
var bounds = map.ViewRectToBoundingBox(new Rect(0d, 0d, map.RenderSize.Width, map.RenderSize.Height));
|
||||
var lineDistance = GetLineDistance();
|
||||
|
||||
var labelStart = new Location(
|
||||
Math.Ceiling(bounds.South / lineDistance) * lineDistance,
|
||||
Math.Ceiling(bounds.West / lineDistance) * lineDistance);
|
||||
|
||||
var labelEnd = new Location(
|
||||
Math.Floor(bounds.North / lineDistance) * lineDistance,
|
||||
Math.Floor(bounds.East / lineDistance) * lineDistance);
|
||||
|
||||
var lineStart = new Location(
|
||||
Math.Min(Math.Max(labelStart.Latitude - lineDistance, -projection.MaxLatitude), projection.MaxLatitude),
|
||||
labelStart.Longitude - lineDistance);
|
||||
|
||||
var lineEnd = new Location(
|
||||
Math.Min(Math.Max(labelEnd.Latitude + lineDistance, -projection.MaxLatitude), projection.MaxLatitude),
|
||||
labelEnd.Longitude + lineDistance);
|
||||
|
||||
var geometry = (PathGeometry)path.Data;
|
||||
geometry.Figures.Clear();
|
||||
|
||||
for (var lat = labelStart.Latitude; lat <= bounds.North; lat += lineDistance)
|
||||
{
|
||||
var figure = new PathFigure
|
||||
{
|
||||
StartPoint = map.LocationToView(new Location(lat, lineStart.Longitude)),
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
figure.Segments.Add(new LineSegment
|
||||
{
|
||||
Point = map.LocationToView(new Location(lat, lineEnd.Longitude))
|
||||
});
|
||||
|
||||
geometry.Figures.Add(figure);
|
||||
}
|
||||
|
||||
for (var lon = labelStart.Longitude; lon <= bounds.East; lon += lineDistance)
|
||||
{
|
||||
var figure = new PathFigure
|
||||
{
|
||||
StartPoint = map.LocationToView(new Location(lineStart.Latitude, lon)),
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
figure.Segments.Add(new LineSegment
|
||||
{
|
||||
Point = map.LocationToView(new Location(lineEnd.Latitude, lon))
|
||||
});
|
||||
|
||||
geometry.Figures.Add(figure);
|
||||
}
|
||||
|
||||
var labelFormat = GetLabelFormat(lineDistance);
|
||||
var childIndex = 1; // 0 for Path
|
||||
|
||||
for (var lat = labelStart.Latitude; lat <= bounds.North; lat += lineDistance)
|
||||
{
|
||||
for (var lon = labelStart.Longitude; lon <= bounds.East; lon += lineDistance)
|
||||
{
|
||||
TextBlock label;
|
||||
|
||||
if (childIndex < Children.Count)
|
||||
{
|
||||
label = (TextBlock)Children[childIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
label = new TextBlock { RenderTransform = new MatrixTransform() };
|
||||
label.SetBinding(TextBlock.FontSizeProperty, this.GetBinding(nameof(FontSize)));
|
||||
label.SetBinding(TextBlock.FontStyleProperty, this.GetBinding(nameof(FontStyle)));
|
||||
label.SetBinding(TextBlock.FontStretchProperty, this.GetBinding(nameof(FontStretch)));
|
||||
label.SetBinding(TextBlock.FontWeightProperty, this.GetBinding(nameof(FontWeight)));
|
||||
label.SetBinding(TextBlock.ForegroundProperty, this.GetBinding(nameof(Foreground)));
|
||||
|
||||
if (FontFamily != null)
|
||||
{
|
||||
label.SetBinding(TextBlock.FontFamilyProperty, this.GetBinding(nameof(FontFamily)));
|
||||
}
|
||||
|
||||
Children.Add(label);
|
||||
}
|
||||
|
||||
childIndex++;
|
||||
|
||||
label.Text = GetLabelText(lat, labelFormat, "NS") + "\n" + GetLabelText(Location.NormalizeLongitude(lon), labelFormat, "EW");
|
||||
label.Tag = new Location(lat, lon);
|
||||
label.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
}
|
||||
|
||||
while (Children.Count > childIndex)
|
||||
{
|
||||
Children.RemoveAt(Children.Count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// don't use MapPanel.Location because labels may be at more than 180° distance from map center
|
||||
|
||||
for (int i = 1; i < Children.Count; i++)
|
||||
{
|
||||
var label = (TextBlock)Children[i];
|
||||
var location = (Location)label.Tag;
|
||||
var viewPosition = map.LocationToView(location);
|
||||
var matrix = new Matrix(1, 0, 0, 1, 0, 0);
|
||||
|
||||
matrix.Translate(StrokeThickness / 2d + 2d, -label.DesiredSize.Height / 2d);
|
||||
matrix.Rotate(map.ViewTransform.Rotation);
|
||||
matrix.Translate(viewPosition.X, viewPosition.Y);
|
||||
|
||||
((MatrixTransform)label.RenderTransform).Matrix = matrix;
|
||||
}
|
||||
}
|
||||
else if (path != null)
|
||||
{
|
||||
path = null;
|
||||
Children.Clear();
|
||||
}
|
||||
|
||||
base.OnViewportChanged(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using Windows.System;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Input;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapItem
|
||||
{
|
||||
public static readonly DependencyProperty AutoCollapseProperty = DependencyProperty.Register(
|
||||
nameof(AutoCollapse), typeof(bool), typeof(MapItem),
|
||||
new PropertyMetadata(false, (o, e) => MapPanel.SetAutoCollapse((MapItem)o, (bool)e.NewValue)));
|
||||
|
||||
public static readonly DependencyProperty LocationProperty = DependencyProperty.Register(
|
||||
nameof(Location), typeof(Location), typeof(MapItem),
|
||||
new PropertyMetadata(null, (o, e) => MapPanel.SetLocation((MapItem)o, (Location)e.NewValue)));
|
||||
|
||||
public MapItem()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapItem);
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerRoutedEventArgs e)
|
||||
{
|
||||
(ItemsControl.ItemsControlFromItemContainer(this) as MapItemsControl)?.OnItemClicked(
|
||||
this, e.KeyModifiers.HasFlag(VirtualKeyModifiers.Control), e.KeyModifiers.HasFlag(VirtualKeyModifiers.Shift));
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
var parentMap = MapPanel.GetParentMap(this);
|
||||
|
||||
if (parentMap != null)
|
||||
{
|
||||
this.ValidateProperty(BackgroundProperty, parentMap, nameof(MapBase.Background));
|
||||
this.ValidateProperty(BorderBrushProperty, parentMap, nameof(MapBase.Foreground));
|
||||
this.ValidateProperty(ForegroundProperty, parentMap, nameof(MapBase.Foreground));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MapItemsControl
|
||||
{
|
||||
public MapItemsControl()
|
||||
{
|
||||
DefaultStyleKey = typeof(MapItemsControl);
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
public new FrameworkElement ContainerFromItem(object item)
|
||||
{
|
||||
return (FrameworkElement)base.ContainerFromItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINUI
|
||||
using Microsoft.UI.Text;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.UI.Text;
|
||||
#else
|
||||
using Windows.UI.Text;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapOverlay
|
||||
{
|
||||
public static readonly DependencyProperty FontFamilyProperty = DependencyProperty.Register(
|
||||
nameof(FontFamily), typeof(FontFamily), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty FontSizeProperty = DependencyProperty.Register(
|
||||
nameof(FontSize), typeof(double), typeof(MapOverlay), new PropertyMetadata(12d));
|
||||
|
||||
public static readonly DependencyProperty FontStyleProperty = DependencyProperty.Register(
|
||||
nameof(FontStyle), typeof(FontStyle), typeof(MapOverlay), new PropertyMetadata(FontStyle.Normal));
|
||||
|
||||
public static readonly DependencyProperty FontStretchProperty = DependencyProperty.Register(
|
||||
nameof(FontStretch), typeof(FontStretch), typeof(MapOverlay), new PropertyMetadata(FontStretch.Normal));
|
||||
|
||||
public static readonly DependencyProperty FontWeightProperty = DependencyProperty.Register(
|
||||
nameof(FontWeight), typeof(FontWeight), typeof(MapOverlay), new PropertyMetadata(FontWeights.Normal));
|
||||
|
||||
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
|
||||
nameof(Foreground), typeof(Brush), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(
|
||||
nameof(Stroke), typeof(Brush), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
|
||||
nameof(StrokeThickness), typeof(double), typeof(MapOverlay), new PropertyMetadata(1d));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register(
|
||||
nameof(StrokeDashArray), typeof(DoubleCollection), typeof(MapOverlay), new PropertyMetadata(null));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashOffsetProperty = DependencyProperty.Register(
|
||||
nameof(StrokeDashOffset), typeof(double), typeof(MapOverlay), new PropertyMetadata(0d));
|
||||
|
||||
public static readonly DependencyProperty StrokeDashCapProperty = DependencyProperty.Register(
|
||||
nameof(StrokeDashCap), typeof(PenLineCap), typeof(MapOverlay), new PropertyMetadata(PenLineCap.Flat));
|
||||
|
||||
public static readonly DependencyProperty StrokeStartLineCapProperty = DependencyProperty.Register(
|
||||
nameof(StrokeStartLineCap), typeof(PenLineCap), typeof(MapOverlay), new PropertyMetadata(PenLineCap.Flat));
|
||||
|
||||
public static readonly DependencyProperty StrokeEndLineCapProperty = DependencyProperty.Register(
|
||||
nameof(StrokeEndLineCap), typeof(PenLineCap), typeof(MapOverlay), new PropertyMetadata(PenLineCap.Flat));
|
||||
|
||||
public static readonly DependencyProperty StrokeLineJoinProperty = DependencyProperty.Register(
|
||||
nameof(StrokeLineJoin), typeof(PenLineJoin), typeof(MapOverlay), new PropertyMetadata(PenLineJoin.Miter));
|
||||
|
||||
public static readonly DependencyProperty StrokeMiterLimitProperty = DependencyProperty.Register(
|
||||
nameof(StrokeMiterLimit), typeof(double), typeof(MapOverlay), new PropertyMetadata(1d));
|
||||
|
||||
public MapOverlay()
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
}
|
||||
|
||||
protected override void SetParentMap(MapBase map)
|
||||
{
|
||||
if (map != null)
|
||||
{
|
||||
this.ValidateProperty(ForegroundProperty, map, nameof(MapBase.Foreground));
|
||||
this.ValidateProperty(StrokeProperty, this, nameof(Foreground));
|
||||
}
|
||||
|
||||
base.SetParentMap(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapPanel
|
||||
{
|
||||
public static readonly DependencyProperty LocationProperty = DependencyProperty.RegisterAttached(
|
||||
"Location", typeof(Location), typeof(MapPanel),
|
||||
new PropertyMetadata(null, (o, e) => (((FrameworkElement)o).Parent as MapPanel)?.InvalidateArrange()));
|
||||
|
||||
public static readonly DependencyProperty BoundingBoxProperty = DependencyProperty.RegisterAttached(
|
||||
"BoundingBox", typeof(BoundingBox), typeof(MapPanel),
|
||||
new PropertyMetadata(null, (o, e) => (((FrameworkElement)o).Parent as MapPanel)?.InvalidateArrange()));
|
||||
|
||||
public static readonly DependencyProperty ParentMapProperty = DependencyProperty.RegisterAttached(
|
||||
"ParentMap", typeof(MapBase), typeof(MapPanel), new PropertyMetadata(null, ParentMapPropertyChanged));
|
||||
|
||||
private static readonly DependencyProperty ViewPositionProperty = DependencyProperty.RegisterAttached(
|
||||
"ViewPosition", typeof(Point?), typeof(MapPanel), new PropertyMetadata(null));
|
||||
|
||||
public MapPanel()
|
||||
{
|
||||
InitMapElement(this);
|
||||
}
|
||||
|
||||
public static void InitMapElement(FrameworkElement element)
|
||||
{
|
||||
if (element is MapBase)
|
||||
{
|
||||
element.SetValue(ParentMapProperty, element);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Workaround for missing property value inheritance.
|
||||
// Loaded and Unloaded handlers set and clear the ParentMap property value.
|
||||
|
||||
element.Loaded += (s, e) => GetParentMap(element);
|
||||
element.Unloaded += (s, e) => element.ClearValue(ParentMapProperty);
|
||||
}
|
||||
}
|
||||
|
||||
public static MapBase GetParentMap(FrameworkElement element)
|
||||
{
|
||||
var parentMap = (MapBase)element.GetValue(ParentMapProperty);
|
||||
|
||||
if (parentMap == null && (parentMap = FindParentMap(element)) != null)
|
||||
{
|
||||
element.SetValue(ParentMapProperty, parentMap);
|
||||
}
|
||||
|
||||
return parentMap;
|
||||
}
|
||||
|
||||
private static MapBase FindParentMap(FrameworkElement element)
|
||||
{
|
||||
return VisualTreeHelper.GetParent(element) is FrameworkElement parent
|
||||
? ((parent as MapBase) ?? (MapBase)element.GetValue(ParentMapProperty) ?? FindParentMap(parent))
|
||||
: null;
|
||||
}
|
||||
|
||||
private static void SetViewPosition(FrameworkElement element, Point? viewPosition)
|
||||
{
|
||||
element.SetValue(ViewPositionProperty, viewPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using Windows.Foundation;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Shapes;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class MapPath : Path
|
||||
{
|
||||
public MapPath()
|
||||
{
|
||||
MapPanel.InitMapElement(this);
|
||||
}
|
||||
|
||||
#region Methods used only by derived classes MapPolyline and MapPolygon
|
||||
|
||||
protected void DataCollectionPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.OldValue is INotifyCollectionChanged oldCollection)
|
||||
{
|
||||
oldCollection.CollectionChanged -= DataCollectionChanged;
|
||||
}
|
||||
|
||||
if (e.NewValue is INotifyCollectionChanged newCollection)
|
||||
{
|
||||
newCollection.CollectionChanged += DataCollectionChanged;
|
||||
}
|
||||
|
||||
UpdateData();
|
||||
}
|
||||
|
||||
protected void DataCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
UpdateData();
|
||||
}
|
||||
|
||||
protected void AddPolylineLocations(PathFigureCollection pathFigures, IEnumerable<Location> locations, double longitudeOffset, bool closed)
|
||||
{
|
||||
if (locations.Count() >= 2)
|
||||
{
|
||||
var points = locations.Select(location => LocationToView(location, longitudeOffset));
|
||||
|
||||
if (closed)
|
||||
{
|
||||
var segment = new PolyLineSegment();
|
||||
|
||||
foreach (var point in points.Skip(1))
|
||||
{
|
||||
segment.Points.Add(point);
|
||||
}
|
||||
|
||||
var figure = new PathFigure
|
||||
{
|
||||
StartPoint = points.First(),
|
||||
IsClosed = closed,
|
||||
IsFilled = closed
|
||||
};
|
||||
|
||||
figure.Segments.Add(segment);
|
||||
pathFigures.Add(figure);
|
||||
}
|
||||
else
|
||||
{
|
||||
var pointList = points.ToList();
|
||||
|
||||
if (closed)
|
||||
{
|
||||
pointList.Add(pointList[0]);
|
||||
}
|
||||
|
||||
var viewport = new Rect(0, 0, ParentMap.RenderSize.Width, ParentMap.RenderSize.Height);
|
||||
PathFigure figure = null;
|
||||
PolyLineSegment segment = null;
|
||||
|
||||
for (int i = 1; i < pointList.Count; i++)
|
||||
{
|
||||
var p1 = pointList[i - 1];
|
||||
var p2 = pointList[i];
|
||||
var inside = Intersections.GetIntersections(ref p1, ref p2, viewport);
|
||||
|
||||
if (inside)
|
||||
{
|
||||
if (figure == null)
|
||||
{
|
||||
figure = new PathFigure
|
||||
{
|
||||
StartPoint = p1,
|
||||
IsClosed = false,
|
||||
IsFilled = false
|
||||
};
|
||||
|
||||
segment = new PolyLineSegment();
|
||||
figure.Segments.Add(segment);
|
||||
pathFigures.Add(figure);
|
||||
}
|
||||
|
||||
segment.Points.Add(p2);
|
||||
}
|
||||
|
||||
if (!inside || p2 != pointList[i])
|
||||
{
|
||||
figure = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINUI
|
||||
using XamlMedia = Microsoft.UI.Xaml.Media;
|
||||
#else
|
||||
using XamlMedia = Windows.UI.Xaml.Media;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces Windows.UI.Xaml.Media.Matrix to achieve necessary floating point precision.
|
||||
/// </summary>
|
||||
public struct Matrix
|
||||
{
|
||||
public double M11 { get; set; }
|
||||
public double M12 { get; set; }
|
||||
public double M21 { get; set; }
|
||||
public double M22 { get; set; }
|
||||
public double OffsetX { get; set; }
|
||||
public double OffsetY { get; set; }
|
||||
|
||||
public Matrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
|
||||
{
|
||||
M11 = m11;
|
||||
M12 = m12;
|
||||
M21 = m21;
|
||||
M22 = m22;
|
||||
OffsetX = offsetX;
|
||||
OffsetY = offsetY;
|
||||
}
|
||||
|
||||
public static implicit operator XamlMedia.Matrix(Matrix m)
|
||||
{
|
||||
return new XamlMedia.Matrix(m.M11, m.M12, m.M21, m.M22, m.OffsetX, m.OffsetY);
|
||||
}
|
||||
|
||||
public Point Transform(Point p)
|
||||
{
|
||||
return new Point(M11 * p.X + M12 * p.Y + OffsetX, M21 * p.X + M22 * p.Y + OffsetY);
|
||||
}
|
||||
|
||||
public void Translate(double x, double y)
|
||||
{
|
||||
OffsetX += x;
|
||||
OffsetY += y;
|
||||
}
|
||||
|
||||
public void Rotate(double angle)
|
||||
{
|
||||
angle = (angle % 360d) / 180d * Math.PI;
|
||||
|
||||
if (angle != 0d)
|
||||
{
|
||||
var cos = Math.Cos(angle);
|
||||
var sin = Math.Sin(angle);
|
||||
|
||||
SetMatrix(
|
||||
cos * M11 - sin * M12,
|
||||
sin * M11 + cos * M12,
|
||||
cos * M21 - sin * M22,
|
||||
sin * M21 + cos * M22,
|
||||
cos * OffsetX - sin * OffsetY,
|
||||
sin * OffsetX + cos * OffsetY);
|
||||
}
|
||||
}
|
||||
|
||||
public void Invert()
|
||||
{
|
||||
var invDet = 1d / (M11 * M22 - M12 * M21);
|
||||
|
||||
if (double.IsInfinity(invDet))
|
||||
{
|
||||
throw new InvalidOperationException("Matrix is not invertible.");
|
||||
}
|
||||
|
||||
SetMatrix(
|
||||
invDet * M22, invDet * -M12, invDet * -M21, invDet * M11,
|
||||
invDet * (M21 * OffsetY - M22 * OffsetX),
|
||||
invDet * (M12 * OffsetX - M11 * OffsetY));
|
||||
}
|
||||
|
||||
private void SetMatrix(double m11, double m12, double m21, double m22, double offsetX, double offsetY)
|
||||
{
|
||||
M11 = m11;
|
||||
M12 = m12;
|
||||
M21 = m21;
|
||||
M22 = m22;
|
||||
OffsetX = offsetX;
|
||||
OffsetY = offsetY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Replaces Windows.Foundation.Point to achieve necessary floating point precision.
|
||||
/// </summary>
|
||||
public struct Point
|
||||
{
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
|
||||
public Point(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public static implicit operator Windows.Foundation.Point(Point p)
|
||||
{
|
||||
return new Windows.Foundation.Point(p.X, p.Y);
|
||||
}
|
||||
|
||||
public static implicit operator Point(Windows.Foundation.Point p)
|
||||
{
|
||||
return new Point(p.X, p.Y);
|
||||
}
|
||||
|
||||
public static explicit operator Point(Vector v)
|
||||
{
|
||||
return new Point(v.X, v.Y);
|
||||
}
|
||||
|
||||
public static Point operator -(Point p)
|
||||
{
|
||||
return new Point(-p.X, -p.Y);
|
||||
}
|
||||
|
||||
public static Point operator +(Point p, Vector v)
|
||||
{
|
||||
return new Point(p.X + v.X, p.Y + v.Y);
|
||||
}
|
||||
|
||||
public static Point operator -(Point p, Vector v)
|
||||
{
|
||||
return new Point(p.X - v.X, p.Y - v.Y);
|
||||
}
|
||||
|
||||
public static Vector operator -(Point p1, Point p2)
|
||||
{
|
||||
return new Vector(p1.X - p2.X, p1.Y - p2.Y);
|
||||
}
|
||||
|
||||
public static bool operator ==(Point p1, Point p2)
|
||||
{
|
||||
return p1.X == p2.X && p1.Y == p2.Y;
|
||||
}
|
||||
|
||||
public static bool operator !=(Point p1, Point p2)
|
||||
{
|
||||
return !(p1 == p2);
|
||||
}
|
||||
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
return o is Point && this == (Point)o;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return X.GetHashCode() ^ Y.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyCompany("Clemens Fischer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021 Clemens Fischer")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyVersion("6.1.0")]
|
||||
[assembly: AssemblyFileVersion("6.1.0")]
|
||||
[assembly: AssemblyVersion("7.0.0")]
|
||||
[assembly: AssemblyFileVersion("7.0.0")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: ComVisible(false)]
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
#if WINUI
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
#else
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Media;
|
||||
using Windows.UI.Xaml.Media.Imaging;
|
||||
#endif
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public partial class Tile
|
||||
{
|
||||
public void SetImage(ImageSource image, bool fadeIn = true)
|
||||
{
|
||||
Pending = false;
|
||||
|
||||
if (image != null && fadeIn && MapBase.ImageFadeDuration > TimeSpan.Zero)
|
||||
{
|
||||
if (image is BitmapImage bitmap && bitmap.UriSource != null)
|
||||
{
|
||||
bitmap.ImageOpened += BitmapImageOpened;
|
||||
bitmap.ImageFailed += BitmapImageFailed;
|
||||
}
|
||||
else
|
||||
{
|
||||
FadeIn();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Image.Opacity = 1d;
|
||||
}
|
||||
|
||||
Image.Source = image;
|
||||
}
|
||||
|
||||
private void BitmapImageOpened(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var bitmap = (BitmapImage)sender;
|
||||
|
||||
bitmap.ImageOpened -= BitmapImageOpened;
|
||||
bitmap.ImageFailed -= BitmapImageFailed;
|
||||
|
||||
FadeIn();
|
||||
}
|
||||
|
||||
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
|
||||
{
|
||||
var bitmap = (BitmapImage)sender;
|
||||
|
||||
bitmap.ImageOpened -= BitmapImageOpened;
|
||||
bitmap.ImageFailed -= BitmapImageFailed;
|
||||
|
||||
Image.Source = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
|
||||
// © 2021 Clemens Fischer
|
||||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
namespace MapControl
|
||||
{
|
||||
public struct Vector
|
||||
{
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
|
||||
public Vector(double x, double y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public static implicit operator Windows.Foundation.Point(Vector v)
|
||||
{
|
||||
return new Windows.Foundation.Point(v.X, v.Y);
|
||||
}
|
||||
|
||||
public static implicit operator Vector(Windows.Foundation.Point v)
|
||||
{
|
||||
return new Vector(v.X, v.Y);
|
||||
}
|
||||
|
||||
public static explicit operator Vector(Point p)
|
||||
{
|
||||
return new Vector(p.X, p.Y);
|
||||
}
|
||||
|
||||
public static Vector operator -(Vector v)
|
||||
{
|
||||
return new Vector(-v.X, -v.Y);
|
||||
}
|
||||
|
||||
public static Point operator +(Vector v, Point p)
|
||||
{
|
||||
return new Point(v.X + p.X, v.Y + p.Y);
|
||||
}
|
||||
|
||||
public static Vector operator +(Vector v1, Vector v2)
|
||||
{
|
||||
return new Vector(v1.X + v2.X, v1.Y + v2.Y);
|
||||
}
|
||||
|
||||
public static Vector operator -(Vector v1, Vector v2)
|
||||
{
|
||||
return new Vector(v1.X - v2.X, v1.Y - v2.Y);
|
||||
}
|
||||
|
||||
public static Vector operator *(double f, Vector v)
|
||||
{
|
||||
return new Vector(f * v.X, f * v.Y);
|
||||
}
|
||||
|
||||
public static Vector operator *(Vector v, double f)
|
||||
{
|
||||
return new Vector(f * v.X, f * v.Y);
|
||||
}
|
||||
|
||||
public static bool operator ==(Vector v1, Vector v2)
|
||||
{
|
||||
return v1.X == v2.X && v1.Y == v2.Y;
|
||||
}
|
||||
|
||||
public static bool operator !=(Vector v1, Vector v2)
|
||||
{
|
||||
return !(v1 == v2);
|
||||
}
|
||||
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
return o is Vector && this == (Vector)o;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return X.GetHashCode() ^ Y.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue