mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Some cleanup.
This commit is contained in:
parent
65a0d8d51a
commit
be3144af07
|
|
@ -3,6 +3,8 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
|
@ -41,7 +43,7 @@ namespace MapControl
|
|||
|
||||
public static readonly DependencyProperty TileLayersProperty = DependencyProperty.Register(
|
||||
"TileLayers", typeof(TileLayerCollection), typeof(Map), new FrameworkPropertyMetadata(
|
||||
(o, e) => ((Map)o).TileLayersPropertyChanged((TileLayerCollection)e.NewValue),
|
||||
(o, e) => ((Map)o).TileLayersPropertyChanged((TileLayerCollection)e.OldValue, (TileLayerCollection)e.NewValue),
|
||||
(o, v) => ((Map)o).CoerceTileLayersProperty((TileLayerCollection)v)));
|
||||
|
||||
public static readonly DependencyProperty MainTileLayerProperty = DependencyProperty.Register(
|
||||
|
|
@ -122,14 +124,9 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the ViewTransform property has changed.
|
||||
/// Raised when the current viewport has changed.
|
||||
/// </summary>
|
||||
public event EventHandler ViewTransformChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raised when the TileLayers property has changed.
|
||||
/// </summary>
|
||||
public event EventHandler TileLayersChanged;
|
||||
public event Action ViewportChanged;
|
||||
|
||||
public double MinZoomLevel { get; set; }
|
||||
public double MaxZoomLevel { get; set; }
|
||||
|
|
@ -258,7 +255,7 @@ namespace MapControl
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the map rotation angle in degrees.
|
||||
/// Gets or sets the map heading, or clockwise rotation angle in degrees.
|
||||
/// </summary>
|
||||
public double Heading
|
||||
{
|
||||
|
|
@ -381,7 +378,7 @@ namespace MapControl
|
|||
if (transformOrigin != null)
|
||||
{
|
||||
viewportOrigin += translation;
|
||||
UpdateViewTransform();
|
||||
UpdateTransform();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -404,7 +401,7 @@ namespace MapControl
|
|||
Heading = (((Heading + rotation) % 360d) + 360d) % 360d;
|
||||
ZoomLevel += Math.Log(scale, 2d);
|
||||
updateTransform = true;
|
||||
UpdateViewTransform();
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
TranslateMap(translation);
|
||||
|
|
@ -448,7 +445,7 @@ namespace MapControl
|
|||
base.OnRenderSizeChanged(sizeInfo);
|
||||
|
||||
ResetTransformOrigin();
|
||||
UpdateViewTransform();
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
|
|
@ -456,21 +453,89 @@ namespace MapControl
|
|||
drawingContext.DrawRectangle(Background, null, new Rect(RenderSize));
|
||||
}
|
||||
|
||||
protected override void OnViewTransformChanged(Map map)
|
||||
protected override void OnViewportChanged()
|
||||
{
|
||||
base.OnViewTransformChanged(map);
|
||||
base.OnViewportChanged();
|
||||
|
||||
if (ViewTransformChanged != null)
|
||||
if (ViewportChanged != null)
|
||||
{
|
||||
ViewTransformChanged(this, EventArgs.Empty);
|
||||
ViewportChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void OnTileLayersChanged()
|
||||
private void TileLayerCollectionChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
|
||||
{
|
||||
if (tileContainer.TileLayers != null &&
|
||||
tileContainer.TileLayers.Count > 0 &&
|
||||
tileContainer.TileLayers[0].HasDarkBackground)
|
||||
switch (eventArgs.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
tileContainer.AddTileLayers(eventArgs.NewStartingIndex, eventArgs.NewItems.Cast<TileLayer>());
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
tileContainer.RemoveTileLayers(eventArgs.OldStartingIndex, eventArgs.OldItems.Cast<TileLayer>());
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
tileContainer.RemoveTileLayers(eventArgs.OldStartingIndex, eventArgs.OldItems.Cast<TileLayer>());
|
||||
tileContainer.AddTileLayers(eventArgs.NewStartingIndex, eventArgs.NewItems.Cast<TileLayer>());
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
tileContainer.ClearTileLayers();
|
||||
if (eventArgs.NewItems != null)
|
||||
{
|
||||
tileContainer.AddTileLayers(0, eventArgs.NewItems.Cast<TileLayer>());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateMainTileLayer();
|
||||
}
|
||||
|
||||
private void TileLayersPropertyChanged(TileLayerCollection oldTileLayers, TileLayerCollection newTileLayers)
|
||||
{
|
||||
tileContainer.ClearTileLayers();
|
||||
|
||||
if (oldTileLayers != null)
|
||||
{
|
||||
oldTileLayers.CollectionChanged -= TileLayerCollectionChanged;
|
||||
}
|
||||
|
||||
if (newTileLayers != null)
|
||||
{
|
||||
newTileLayers.CollectionChanged += TileLayerCollectionChanged;
|
||||
tileContainer.AddTileLayers(0, newTileLayers);
|
||||
}
|
||||
|
||||
UpdateMainTileLayer();
|
||||
}
|
||||
|
||||
private TileLayerCollection CoerceTileLayersProperty(TileLayerCollection tileLayers)
|
||||
{
|
||||
if (tileLayers == null)
|
||||
{
|
||||
tileLayers = new TileLayerCollection();
|
||||
}
|
||||
|
||||
return tileLayers;
|
||||
}
|
||||
|
||||
private void MainTileLayerPropertyChanged(TileLayer mainTileLayer)
|
||||
{
|
||||
if (mainTileLayer != null)
|
||||
{
|
||||
if (TileLayers.Count == 0)
|
||||
{
|
||||
TileLayers.Add(mainTileLayer);
|
||||
}
|
||||
else if (TileLayers[0] != mainTileLayer)
|
||||
{
|
||||
TileLayers[0] = mainTileLayer;
|
||||
}
|
||||
}
|
||||
|
||||
if (mainTileLayer != null && mainTileLayer.HasDarkBackground)
|
||||
{
|
||||
if (DarkForeground != null)
|
||||
{
|
||||
|
|
@ -494,63 +559,34 @@ namespace MapControl
|
|||
Background = LightBackground;
|
||||
}
|
||||
}
|
||||
|
||||
if (TileLayersChanged != null)
|
||||
{
|
||||
TileLayersChanged(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
private void TileLayersPropertyChanged(TileLayerCollection tileLayers)
|
||||
{
|
||||
if (tileLayers != null)
|
||||
{
|
||||
tileContainer.TileLayers = tileLayers;
|
||||
MainTileLayer = tileLayers.Count > 0 ? tileLayers[0] : null;
|
||||
}
|
||||
}
|
||||
|
||||
private TileLayerCollection CoerceTileLayersProperty(TileLayerCollection tileLayers)
|
||||
{
|
||||
if (tileLayers == null)
|
||||
{
|
||||
tileLayers = new TileLayerCollection();
|
||||
}
|
||||
|
||||
return tileLayers;
|
||||
}
|
||||
|
||||
private void MainTileLayerPropertyChanged(TileLayer mainTileLayer)
|
||||
{
|
||||
if (mainTileLayer != null)
|
||||
{
|
||||
if (tileContainer.TileLayers.Count == 0)
|
||||
{
|
||||
tileContainer.TileLayers.Add(mainTileLayer);
|
||||
}
|
||||
else if (tileContainer.TileLayers[0] != mainTileLayer)
|
||||
{
|
||||
tileContainer.TileLayers[0] = mainTileLayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TileLayer CoerceMainTileLayerProperty(TileLayer mainTileLayer)
|
||||
{
|
||||
if (mainTileLayer == null && tileContainer.TileLayers.Count > 0)
|
||||
if (mainTileLayer == null && TileLayers.Count > 0)
|
||||
{
|
||||
mainTileLayer = tileContainer.TileLayers[0];
|
||||
mainTileLayer = TileLayers[0];
|
||||
}
|
||||
|
||||
return mainTileLayer;
|
||||
}
|
||||
|
||||
private void UpdateMainTileLayer()
|
||||
{
|
||||
TileLayer mainTileLayer = TileLayers.FirstOrDefault();
|
||||
|
||||
if (MainTileLayer != mainTileLayer)
|
||||
{
|
||||
MainTileLayer = mainTileLayer;
|
||||
}
|
||||
}
|
||||
|
||||
private void CenterPropertyChanged(Location center)
|
||||
{
|
||||
if (updateTransform)
|
||||
{
|
||||
ResetTransformOrigin();
|
||||
UpdateViewTransform();
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
if (centerAnimation == null)
|
||||
|
|
@ -600,7 +636,7 @@ namespace MapControl
|
|||
{
|
||||
if (updateTransform)
|
||||
{
|
||||
UpdateViewTransform();
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
if (zoomLevelAnimation == null)
|
||||
|
|
@ -649,7 +685,7 @@ namespace MapControl
|
|||
{
|
||||
if (updateTransform)
|
||||
{
|
||||
UpdateViewTransform();
|
||||
UpdateTransform();
|
||||
}
|
||||
|
||||
if (headingAnimation == null)
|
||||
|
|
@ -704,20 +740,20 @@ namespace MapControl
|
|||
return ((heading % 360d) + 360d) % 360d;
|
||||
}
|
||||
|
||||
private void UpdateViewTransform()
|
||||
private void UpdateTransform()
|
||||
{
|
||||
double scale;
|
||||
|
||||
if (transformOrigin != null)
|
||||
{
|
||||
scale = tileContainer.SetTransform(ZoomLevel, Heading, MapTransform.Transform(transformOrigin), viewportOrigin, RenderSize);
|
||||
scale = tileContainer.SetViewportTransform(ZoomLevel, Heading, MapTransform.Transform(transformOrigin), viewportOrigin, RenderSize);
|
||||
updateTransform = false;
|
||||
Center = ViewportPointToLocation(new Point(RenderSize.Width / 2d, RenderSize.Height / 2d));
|
||||
updateTransform = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
scale = tileContainer.SetTransform(ZoomLevel, Heading, MapTransform.Transform(Center), viewportOrigin, RenderSize);
|
||||
scale = tileContainer.SetViewportTransform(ZoomLevel, Heading, MapTransform.Transform(Center), viewportOrigin, RenderSize);
|
||||
}
|
||||
|
||||
scale *= MapTransform.RelativeScale(Center) / MeterPerDegree; // Pixels per meter at center latitude
|
||||
|
|
@ -728,7 +764,7 @@ namespace MapControl
|
|||
rotateTransform.Angle = Heading;
|
||||
scaleRotateTransform.Matrix = scaleTransform.Value * rotateTransform.Value;
|
||||
|
||||
OnViewTransformChanged(this);
|
||||
OnViewportChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,16 +7,17 @@ using System.Windows;
|
|||
|
||||
namespace MapControl
|
||||
{
|
||||
internal interface INotifyParentMapChanged
|
||||
{
|
||||
void ParentMapChanged(Map oldParentMap, Map newParentMap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base class for child elements of a MapPanel.
|
||||
/// </summary>
|
||||
public abstract class MapElement : FrameworkElement, INotifyParentMapChanged
|
||||
public abstract class MapElement : FrameworkElement
|
||||
{
|
||||
static MapElement()
|
||||
{
|
||||
MapPanel.ParentMapProperty.OverrideMetadata(typeof(MapElement),
|
||||
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, ParentMapPropertyChanged));
|
||||
}
|
||||
|
||||
protected MapElement()
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
|
|
@ -28,23 +29,26 @@ namespace MapControl
|
|||
get { return MapPanel.GetParentMap(this); }
|
||||
}
|
||||
|
||||
protected abstract void OnViewTransformChanged(Map parentMap);
|
||||
protected abstract void OnViewportChanged();
|
||||
|
||||
private void OnViewTransformChanged(object sender, EventArgs eventArgs)
|
||||
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
|
||||
{
|
||||
OnViewTransformChanged((Map)sender);
|
||||
}
|
||||
MapElement mapElement = obj as MapElement;
|
||||
|
||||
void INotifyParentMapChanged.ParentMapChanged(Map oldParentMap, Map newParentMap)
|
||||
{
|
||||
if (oldParentMap != null)
|
||||
if (mapElement != null)
|
||||
{
|
||||
oldParentMap.ViewTransformChanged -= OnViewTransformChanged;
|
||||
}
|
||||
Map oldParentMap = eventArgs.OldValue as Map;
|
||||
Map newParentMap = eventArgs.NewValue as Map;
|
||||
|
||||
if (newParentMap != null)
|
||||
{
|
||||
newParentMap.ViewTransformChanged += OnViewTransformChanged;
|
||||
if (oldParentMap != null)
|
||||
{
|
||||
oldParentMap.ViewportChanged -= mapElement.OnViewportChanged;
|
||||
}
|
||||
|
||||
if (newParentMap != null)
|
||||
{
|
||||
newParentMap.ViewportChanged += mapElement.OnViewportChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,8 +125,9 @@ namespace MapControl
|
|||
return visual;
|
||||
}
|
||||
|
||||
protected override void OnViewTransformChanged(Map parentMap)
|
||||
protected override void OnViewportChanged()
|
||||
{
|
||||
Map parentMap = ParentMap;
|
||||
Rect bounds = parentMap.ViewportTransform.Inverse.TransformBounds(new Rect(parentMap.RenderSize));
|
||||
Location loc1 = parentMap.MapTransform.TransformBack(bounds.TopLeft);
|
||||
Location loc2 = parentMap.MapTransform.TransformBack(bounds.BottomRight);
|
||||
|
|
@ -195,7 +196,7 @@ namespace MapControl
|
|||
private void UpdateBrush()
|
||||
{
|
||||
pen.Brush = null;
|
||||
OnViewTransformChanged(ParentMap);
|
||||
OnViewportChanged();
|
||||
}
|
||||
|
||||
private static string CoordinateString(double value, string format, string hemispheres)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace MapControl
|
|||
/// coordinates. IsInsideMapBounds indicates if the viewport coordinates are located
|
||||
/// inside the visible part of the map.
|
||||
/// </summary>
|
||||
public class MapPanel : Panel, INotifyParentMapChanged
|
||||
public class MapPanel : Panel
|
||||
{
|
||||
public static readonly DependencyProperty ParentMapProperty = DependencyProperty.RegisterAttached(
|
||||
"ParentMap", typeof(Map), typeof(MapPanel),
|
||||
|
|
@ -102,8 +102,10 @@ namespace MapControl
|
|||
return finalSize;
|
||||
}
|
||||
|
||||
protected virtual void OnViewTransformChanged(Map parentMap)
|
||||
protected virtual void OnViewportChanged()
|
||||
{
|
||||
Map parentMap = ParentMap;
|
||||
|
||||
foreach (UIElement element in InternalChildren)
|
||||
{
|
||||
Location location = GetLocation(element);
|
||||
|
|
@ -115,31 +117,24 @@ namespace MapControl
|
|||
}
|
||||
}
|
||||
|
||||
private void OnViewTransformChanged(object sender, EventArgs eventArgs)
|
||||
{
|
||||
OnViewTransformChanged((Map)sender);
|
||||
}
|
||||
|
||||
void INotifyParentMapChanged.ParentMapChanged(Map oldParentMap, Map newParentMap)
|
||||
{
|
||||
if (oldParentMap != null && oldParentMap != this)
|
||||
{
|
||||
oldParentMap.ViewTransformChanged -= OnViewTransformChanged;
|
||||
}
|
||||
|
||||
if (newParentMap != null && newParentMap != this)
|
||||
{
|
||||
newParentMap.ViewTransformChanged += OnViewTransformChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs eventArgs)
|
||||
{
|
||||
INotifyParentMapChanged notifyChanged = obj as INotifyParentMapChanged;
|
||||
MapPanel mapPanel = obj as MapPanel;
|
||||
|
||||
if (notifyChanged != null)
|
||||
if (mapPanel != null)
|
||||
{
|
||||
notifyChanged.ParentMapChanged(eventArgs.OldValue as Map, eventArgs.NewValue as Map);
|
||||
Map oldParentMap = eventArgs.OldValue as Map;
|
||||
Map newParentMap = eventArgs.NewValue as Map;
|
||||
|
||||
if (oldParentMap != null && oldParentMap != mapPanel)
|
||||
{
|
||||
oldParentMap.ViewportChanged -= mapPanel.OnViewportChanged;
|
||||
}
|
||||
|
||||
if (newParentMap != null && newParentMap != mapPanel)
|
||||
{
|
||||
newParentMap.ViewportChanged += mapPanel.OnViewportChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,13 +156,13 @@ namespace MapControl
|
|||
AddVisualChild(visual);
|
||||
}
|
||||
|
||||
protected override void OnViewTransformChanged(Map parentMap)
|
||||
protected override void OnViewportChanged()
|
||||
{
|
||||
double scale = 1d;
|
||||
|
||||
if (TransformStroke)
|
||||
{
|
||||
scale = parentMap.CenterScale * Map.MeterPerDegree;
|
||||
scale = ParentMap.CenterScale * Map.MeterPerDegree;
|
||||
}
|
||||
|
||||
drawing.Pen.Thickness = scale * StrokeThickness;
|
||||
|
|
@ -175,12 +175,10 @@ namespace MapControl
|
|||
|
||||
protected void UpdateGeometry(bool closed)
|
||||
{
|
||||
Map parentMap = MapPanel.GetParentMap(this);
|
||||
|
||||
if (parentMap != null && Locations != null && Locations.Count > 0)
|
||||
if (ParentMap != null && Locations != null && Locations.Count > 0)
|
||||
{
|
||||
drawing.Geometry = CreateGeometry(parentMap, Locations, closed);
|
||||
OnViewTransformChanged(parentMap);
|
||||
drawing.Geometry = CreateGeometry(Locations, closed);
|
||||
OnViewportChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -190,28 +188,26 @@ namespace MapControl
|
|||
|
||||
private void UpdatePenThickness()
|
||||
{
|
||||
Map parentMap = MapPanel.GetParentMap(this);
|
||||
|
||||
if (parentMap != null)
|
||||
if (ParentMap != null)
|
||||
{
|
||||
OnViewTransformChanged(parentMap);
|
||||
OnViewportChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private Geometry CreateGeometry(Map parentMap, LocationCollection locations, bool closed)
|
||||
private Geometry CreateGeometry(LocationCollection locations, bool closed)
|
||||
{
|
||||
StreamGeometry geometry = new StreamGeometry
|
||||
{
|
||||
Transform = parentMap.ViewportTransform
|
||||
Transform = ParentMap.ViewportTransform
|
||||
};
|
||||
|
||||
using (StreamGeometryContext sgc = geometry.Open())
|
||||
{
|
||||
sgc.BeginFigure(parentMap.MapTransform.Transform(locations.First()), closed, closed);
|
||||
sgc.BeginFigure(ParentMap.MapTransform.Transform(locations.First()), closed, closed);
|
||||
|
||||
if (Locations.Count > 1)
|
||||
{
|
||||
sgc.PolyLineTo(parentMap.MapTransform.Transform(locations.Skip(1)), true, true);
|
||||
sgc.PolyLineTo(ParentMap.MapTransform.Transform(locations.Skip(1)), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
|
|
@ -23,44 +22,56 @@ namespace MapControl
|
|||
private double zoomLevel;
|
||||
private int tileZoomLevel;
|
||||
private Int32Rect tileGrid;
|
||||
private TileLayerCollection tileLayers;
|
||||
private readonly DispatcherTimer updateTimer;
|
||||
private readonly MatrixTransform viewportTransform = new MatrixTransform();
|
||||
|
||||
public readonly MatrixTransform ViewportTransform = new MatrixTransform();
|
||||
|
||||
public TileContainer()
|
||||
{
|
||||
updateTimer = new DispatcherTimer(TimeSpan.FromSeconds(0.5), DispatcherPriority.Background, UpdateTiles, Dispatcher);
|
||||
}
|
||||
|
||||
public TileLayerCollection TileLayers
|
||||
public void AddTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
||||
{
|
||||
get { return tileLayers; }
|
||||
set
|
||||
Matrix transform = GetVisualTransform();
|
||||
|
||||
foreach (TileLayer tileLayer in tileLayers)
|
||||
{
|
||||
if (tileLayers != null)
|
||||
if (string.IsNullOrEmpty(tileLayer.Name))
|
||||
{
|
||||
tileLayers.CollectionChanged -= TileLayersChanged;
|
||||
throw new ArgumentException("TileLayer.Name property must not be null or empty.");
|
||||
}
|
||||
|
||||
tileLayers = value;
|
||||
ClearChildren();
|
||||
|
||||
if (tileLayers != null)
|
||||
{
|
||||
tileLayers.CollectionChanged += TileLayersChanged;
|
||||
AddChildren(0, tileLayers);
|
||||
}
|
||||
|
||||
((Map)VisualParent).OnTileLayersChanged();
|
||||
Children.Insert(index++, tileLayer);
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
|
||||
public Transform ViewportTransform
|
||||
public void RemoveTileLayers(int index, IEnumerable<TileLayer> tileLayers)
|
||||
{
|
||||
get { return viewportTransform; }
|
||||
int count = 0;
|
||||
|
||||
foreach (TileLayer tileLayer in tileLayers)
|
||||
{
|
||||
tileLayer.ClearTiles();
|
||||
count++;
|
||||
}
|
||||
|
||||
Children.RemoveRange(index, count);
|
||||
}
|
||||
|
||||
public double SetTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
|
||||
public void ClearTileLayers()
|
||||
{
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.ClearTiles();
|
||||
}
|
||||
|
||||
Children.Clear();
|
||||
}
|
||||
|
||||
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
|
||||
{
|
||||
zoomLevel = mapZoomLevel;
|
||||
rotation = mapRotation;
|
||||
|
|
@ -75,16 +86,13 @@ namespace MapControl
|
|||
transform.Scale(scale, scale);
|
||||
transform.Translate(offset.X, offset.Y);
|
||||
transform.RotateAt(rotation, origin.X, origin.Y);
|
||||
viewportTransform.Matrix = transform;
|
||||
ViewportTransform.Matrix = transform;
|
||||
|
||||
transform = GetVisualTransform();
|
||||
|
||||
if (tileLayers != null)
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
foreach (TileLayer tileLayer in tileLayers)
|
||||
{
|
||||
tileLayer.TransformMatrix = transform;
|
||||
}
|
||||
tileLayer.TransformMatrix = transform;
|
||||
}
|
||||
|
||||
updateTimer.IsEnabled = true;
|
||||
|
|
@ -113,7 +121,7 @@ namespace MapControl
|
|||
int zoom = (int)Math.Floor(zoomLevel + 1d - zoomLevelSwitchOffset);
|
||||
int numTiles = 1 << zoom;
|
||||
double mapToTileScale = (double)numTiles / 360d;
|
||||
Matrix transform = viewportTransform.Matrix;
|
||||
Matrix transform = ViewportTransform.Matrix;
|
||||
transform.Invert(); // view to map coordinates
|
||||
transform.Translate(180d, -180d);
|
||||
transform.Scale(mapToTileScale, -mapToTileScale); // map coordinates to tile indices
|
||||
|
|
@ -142,77 +150,12 @@ namespace MapControl
|
|||
tileGrid = grid;
|
||||
transform = GetVisualTransform();
|
||||
|
||||
if (tileLayers != null)
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
foreach (TileLayer tileLayer in tileLayers)
|
||||
{
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TileLayersChanged(object sender, NotifyCollectionChangedEventArgs eventArgs)
|
||||
{
|
||||
switch (eventArgs.Action)
|
||||
{
|
||||
case NotifyCollectionChangedAction.Add:
|
||||
AddChildren(eventArgs.NewStartingIndex, eventArgs.NewItems);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Remove:
|
||||
RemoveChildren(eventArgs.OldStartingIndex, eventArgs.OldItems);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Move:
|
||||
case NotifyCollectionChangedAction.Replace:
|
||||
RemoveChildren(eventArgs.OldStartingIndex, eventArgs.OldItems);
|
||||
AddChildren(eventArgs.NewStartingIndex, eventArgs.NewItems);
|
||||
break;
|
||||
|
||||
case NotifyCollectionChangedAction.Reset:
|
||||
ClearChildren();
|
||||
if (eventArgs.NewItems != null)
|
||||
{
|
||||
AddChildren(0, eventArgs.NewItems);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
((Map)VisualParent).OnTileLayersChanged();
|
||||
}
|
||||
|
||||
private void AddChildren(int index, IList layers)
|
||||
{
|
||||
Matrix transform = GetVisualTransform();
|
||||
|
||||
foreach (TileLayer tileLayer in layers)
|
||||
{
|
||||
Children.Insert(index++, tileLayer);
|
||||
tileLayer.TransformMatrix = transform;
|
||||
tileLayer.UpdateTiles(tileZoomLevel, tileGrid);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveChildren(int index, IList layers)
|
||||
{
|
||||
foreach (TileLayer tileLayer in layers)
|
||||
{
|
||||
tileLayer.ClearTiles();
|
||||
}
|
||||
|
||||
Children.RemoveRange(index, layers.Count);
|
||||
}
|
||||
|
||||
private void ClearChildren()
|
||||
{
|
||||
foreach (TileLayer tileLayer in Children)
|
||||
{
|
||||
tileLayer.ClearTiles();
|
||||
}
|
||||
|
||||
Children.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ namespace MapControl
|
|||
tileImageLoader = new TileImageLoader(this);
|
||||
VisualEdgeMode = EdgeMode.Aliased;
|
||||
VisualTransform = new MatrixTransform();
|
||||
Name = string.Empty;
|
||||
MinZoomLevel = 1;
|
||||
MaxZoomLevel = 18;
|
||||
MaxParallelDownloads = 8;
|
||||
|
|
@ -59,7 +58,7 @@ namespace MapControl
|
|||
|
||||
tileImageLoader.CancelGetTiles();
|
||||
|
||||
if (VisualParent != null && TileSource != null)
|
||||
if (TileSource != null)
|
||||
{
|
||||
SelectTiles();
|
||||
RenderTiles();
|
||||
|
|
@ -76,11 +75,11 @@ namespace MapControl
|
|||
|
||||
private void SelectTiles()
|
||||
{
|
||||
TileContainer tileContainer = VisualParent as TileContainer;
|
||||
int maxZoomLevel = Math.Min(zoomLevel, MaxZoomLevel);
|
||||
int minZoomLevel = maxZoomLevel;
|
||||
ContainerVisual parent = Parent as ContainerVisual;
|
||||
|
||||
if (tileContainer != null && tileContainer.TileLayers.IndexOf(this) == 0)
|
||||
if (parent != null && parent.Children.IndexOf(this) == 0)
|
||||
{
|
||||
minZoomLevel = MinZoomLevel;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
<local:SampleItemCollection x:Key="Polylines"/>
|
||||
<local:SampleItemCollection x:Key="Points"/>
|
||||
<local:SampleItemCollection x:Key="Pushpins"/>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||
<DataTemplate x:Key="PolylineItemTemplate">
|
||||
<map:MapPolyline Locations="{Binding Locations}" Stroke="Red" StrokeThickness="3"/>
|
||||
</DataTemplate>
|
||||
|
|
@ -64,6 +65,7 @@
|
|||
</Style>
|
||||
<Style x:Key="PushpinItemStyle" TargetType="map:MapItem">
|
||||
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
|
||||
<Setter Property="Visibility" Value="{Binding (map:MapPanel.IsInsideMapBounds), Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Self}}"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="VerticalAlignment" Value="Bottom"/>
|
||||
<Setter Property="Template">
|
||||
|
|
@ -85,10 +87,10 @@
|
|||
<RowDefinition/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<map:Map Name="map" IsManipulationEnabled="True" Margin="2" FontSize="10"
|
||||
<map:Map Name="map" IsManipulationEnabled="True" Margin="2" FontSize="10"
|
||||
LightForeground="Black" LightBackground="White" DarkForeground="White" DarkBackground="#FF3F3F3F"
|
||||
Center="53.5,8.2" ZoomLevel="11"
|
||||
MainTileLayer="{Binding ElementName=tileLayerComboBox, Path=SelectedItem}"
|
||||
MainTileLayer="{Binding SelectedItem, ElementName=tileLayerComboBox}"
|
||||
ManipulationInertiaStarting="MapManipulationInertiaStarting"
|
||||
MouseMove="MapMouseMove" MouseLeave="MapMouseLeave">
|
||||
<map:MapGraticule Opacity="0.6"/>
|
||||
|
|
@ -100,9 +102,10 @@
|
|||
<map:MapItemsControl ItemsSource="{StaticResource Pushpins}"
|
||||
ItemContainerStyle="{StaticResource PushpinItemStyle}"
|
||||
IsSynchronizedWithCurrentItem="True"/>
|
||||
<map:Pushpin Location="53.5,8.2" Background="Yellow" Foreground="Blue">N 53° 30' E 8° 12'</map:Pushpin>
|
||||
<map:Pushpin Location="53.5,8.2" Background="Yellow" Foreground="Blue" Content="N 53° 30' E 8° 12'"
|
||||
Visibility="{Binding (map:MapPanel.IsInsideMapBounds), Converter={StaticResource BooleanToVisibilityConverter}, RelativeSource={RelativeSource Self}}"/>
|
||||
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="2,0,0,0" FontSize="10"
|
||||
Text="{Binding ElementName=map, Path=MainTileLayer.Description}"/>
|
||||
Text="{Binding MainTileLayer.Description, ElementName=map}"/>
|
||||
</map:Map>
|
||||
<Grid Grid.Row="1" Margin="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
|
|
@ -112,9 +115,9 @@
|
|||
<TextBlock Name="mouseLocation" Margin="4" VerticalAlignment="Center"/>
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Slider Name="zoomSlider" ToolTip="Zoom Level" Margin="4,0,4,0" Width="100" Minimum="1" Maximum="20" SmallChange="0.01"
|
||||
Value="{Binding ElementName=map, Path=TargetZoomLevel}" />
|
||||
Value="{Binding TargetZoomLevel, ElementName=map}" />
|
||||
<Slider Name="headingSlider" ToolTip="Heading" Margin="4,0,4,0" Width="100" Minimum="0" Maximum="360" SmallChange="10" LargeChange="45"
|
||||
Value="{Binding ElementName=map, Path=TargetHeading}"/>
|
||||
Value="{Binding TargetHeading, ElementName=map}"/>
|
||||
<CheckBox ToolTip="Map Overlay" Margin="4,0,4,0" VerticalAlignment="Center" Content="Seamarks" Click="SeamarksClick"/>
|
||||
<ComboBox Name="tileLayerComboBox" ToolTip="Main Tile Layer" Margin="4,0,4,0" DisplayMemberPath="Name" SelectedIndex="0">
|
||||
<ComboBox.Items>
|
||||
|
|
@ -129,7 +132,11 @@
|
|||
<map:TileLayer Name="MapQuest OSM" Description="MapQuest OSM - © {y} MapQuest & OpenStreetMap Contributors"
|
||||
TileSource="http://otile{n}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png"/>
|
||||
|
||||
<!--<map:TileLayer Name="Google Maps" Description="Google Maps - © {y} Google"
|
||||
<!-- Note: The providers of the below TileLayers do not allow access to their
|
||||
map content without using their APIs (i.e. Google Maps API or Bing Maps API).
|
||||
Hence the declarations below are for demonstration purpose only. -->
|
||||
|
||||
<map:TileLayer Name="Google Maps" Description="Google Maps - © {y} Google"
|
||||
TileSource="http://mt{i}.google.com/vt/x={x}&y={y}&z={z}" MaxZoomLevel="20"/>
|
||||
<map:TileLayer Name="Google Images" Description="Google Maps - © {y} Google"
|
||||
TileSource="http://khm{i}.google.com/kh/v=113&x={x}&y={y}&z={z}" MaxZoomLevel="20" HasDarkBackground="True"/>
|
||||
|
|
@ -138,9 +145,9 @@
|
|||
<map:TileLayer Name="Bing Images" Description="Bing Maps - © {y} Microsoft Corporation"
|
||||
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/a{q}.jpeg?g=0" MaxZoomLevel="20" HasDarkBackground="True"/>
|
||||
<map:TileLayer Name="Bing Hybrid" Description="Bing Maps - © {y} Microsoft Corporation"
|
||||
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/h{q}.jpeg?g=0&stl=h" MaxZoomLevel="20" HasDarkBackground="True"/>-->
|
||||
TileSource="http://ecn.t{i}.tiles.virtualearth.net/tiles/h{q}.jpeg?g=0&stl=h" MaxZoomLevel="20" HasDarkBackground="True"/>
|
||||
|
||||
<!-- The TileLayer below uses an ImageTileSource that bypasses caching of map tile images -->
|
||||
<!-- The TileLayer below uses an ImageTileSource, which bypasses caching of map tile images -->
|
||||
|
||||
<map:TileLayer Name="OSM Uncached" Description="© {y} OpenStreetMap Contributors, CC-BY-SA">
|
||||
<map:TileLayer.TileSource>
|
||||
|
|
|
|||
Loading…
Reference in a new issue