mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Fixed moving transform center across dateline.
This commit is contained in:
parent
7fbbf66acb
commit
afc93704d9
|
|
@ -30,12 +30,6 @@ namespace MapControl
|
|||
East = east;
|
||||
}
|
||||
|
||||
public BoundingBox(BoundingBox boundingBox, double longitudeOffset)
|
||||
: this(boundingBox.South, boundingBox.West + longitudeOffset,
|
||||
boundingBox.North, boundingBox.East + longitudeOffset)
|
||||
{
|
||||
}
|
||||
|
||||
public double West { get; set; }
|
||||
|
||||
public double East { get; set; }
|
||||
|
|
|
|||
|
|
@ -272,7 +272,8 @@ namespace MapControl
|
|||
|
||||
/// <summary>
|
||||
/// Sets a temporary center point in view coordinates for scaling and rotation transformations.
|
||||
/// This center point is automatically reset when the Center property is set by application code.
|
||||
/// This center point is automatically reset when the Center property is set by application code
|
||||
/// or by the methods TranslateMap, TransformMap, ZoomMap and ZoomToBounds.
|
||||
/// </summary>
|
||||
public void SetTransformCenter(Point center)
|
||||
{
|
||||
|
|
@ -728,6 +729,7 @@ namespace MapControl
|
|||
|
||||
private void UpdateTransform(bool resetTransformCenter = false, bool projectionChanged = false)
|
||||
{
|
||||
var transformCenterChanged = false;
|
||||
var viewScale = ViewTransform.ZoomLevelToScale(ZoomLevel);
|
||||
var projection = MapProjection;
|
||||
|
||||
|
|
@ -762,6 +764,9 @@ namespace MapControl
|
|||
|
||||
if (resetTransformCenter)
|
||||
{
|
||||
// check if transform center moved across the dateline
|
||||
transformCenterChanged = Math.Abs(center.Longitude - transformCenter.Longitude) > 180d;
|
||||
|
||||
ResetTransformCenter();
|
||||
|
||||
projection.Center = ProjectionCenter ?? Center;
|
||||
|
|
@ -778,9 +783,11 @@ namespace MapControl
|
|||
|
||||
SetViewScale(ViewTransform.Scale);
|
||||
|
||||
OnViewportChanged(new ViewportChangedEventArgs(projectionChanged, Center.Longitude - centerLongitude));
|
||||
|
||||
// check if view center moved across the dateline
|
||||
transformCenterChanged = transformCenterChanged || Math.Abs(Center.Longitude - centerLongitude) > 180d;
|
||||
centerLongitude = Center.Longitude;
|
||||
|
||||
OnViewportChanged(new ViewportChangedEventArgs(projectionChanged, transformCenterChanged));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,11 +171,11 @@ namespace MapControl
|
|||
|
||||
base.OnViewportChanged(e);
|
||||
|
||||
await UpdateImageAsync();
|
||||
await UpdateImageAsync(); // update immediately
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustBoundingBox(e.LongitudeOffset);
|
||||
ValidateBoundingBox();
|
||||
|
||||
base.OnViewportChanged(e);
|
||||
|
||||
|
|
@ -233,21 +233,30 @@ namespace MapControl
|
|||
BoundingBox = ParentMap.ViewRectToBoundingBox(rect);
|
||||
}
|
||||
|
||||
private void AdjustBoundingBox(double longitudeOffset)
|
||||
private void ValidateBoundingBox()
|
||||
{
|
||||
if (Math.Abs(longitudeOffset) > 180d && BoundingBox != null)
|
||||
if (BoundingBox != null)
|
||||
{
|
||||
var offset = 360d * Math.Sign(longitudeOffset);
|
||||
var offset = ParentMap.Center.Longitude - BoundingBox.Center.Longitude;
|
||||
|
||||
BoundingBox = new BoundingBox(BoundingBox, offset);
|
||||
|
||||
foreach (var image in Children.OfType<Image>())
|
||||
if (Math.Abs(offset) > 180d)
|
||||
{
|
||||
var imageBoundingBox = GetBoundingBox(image);
|
||||
offset = 360d * Math.Sign(offset);
|
||||
|
||||
if (imageBoundingBox != null)
|
||||
BoundingBox = new BoundingBox(
|
||||
BoundingBox.South, BoundingBox.West + offset,
|
||||
BoundingBox.North, BoundingBox.East + offset);
|
||||
|
||||
foreach (var image in Children.OfType<Image>())
|
||||
{
|
||||
SetBoundingBox(image, new BoundingBox(imageBoundingBox, offset));
|
||||
var imageBbox = GetBoundingBox(image);
|
||||
|
||||
if (imageBbox != null)
|
||||
{
|
||||
SetBoundingBox(image, new BoundingBox(
|
||||
imageBbox.South, imageBbox.West + offset,
|
||||
imageBbox.North, imageBbox.East + offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// Licensed under the Microsoft Public License (Ms-PL)
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
#if WINUI
|
||||
using Windows.Foundation;
|
||||
|
|
@ -125,11 +126,11 @@ namespace MapControl
|
|||
|
||||
protected override Task UpdateTileLayer()
|
||||
{
|
||||
var update = false;
|
||||
var updateTiles = false;
|
||||
|
||||
if (ParentMap == null || ParentMap.MapProjection.Type != MapProjectionType.WebMercator)
|
||||
{
|
||||
update = TileMatrix != null;
|
||||
updateTiles = TileMatrix != null;
|
||||
TileMatrix = null;
|
||||
}
|
||||
else
|
||||
|
|
@ -137,36 +138,33 @@ namespace MapControl
|
|||
if (TileSource != TileImageLoader.TileSource)
|
||||
{
|
||||
Tiles = new TileCollection(); // clear all
|
||||
update = true;
|
||||
updateTiles = true;
|
||||
}
|
||||
|
||||
if (SetTileMatrix())
|
||||
{
|
||||
SetRenderTransform();
|
||||
update = true;
|
||||
updateTiles = true;
|
||||
}
|
||||
|
||||
SetRenderTransform();
|
||||
}
|
||||
|
||||
if (update)
|
||||
{
|
||||
UpdateTiles();
|
||||
|
||||
return TileImageLoader.LoadTiles(Tiles, TileSource, SourceName);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
return updateTiles ? UpdateTiles() : Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override void SetRenderTransform()
|
||||
{
|
||||
// tile matrix origin in pixels
|
||||
//
|
||||
var tileMatrixOrigin = new Point(TileSize * TileMatrix.XMin, TileSize * TileMatrix.YMin);
|
||||
if (TileMatrix != null)
|
||||
{
|
||||
// tile matrix origin in pixels
|
||||
//
|
||||
var tileMatrixOrigin = new Point(TileSize * TileMatrix.XMin, TileSize * TileMatrix.YMin);
|
||||
|
||||
var tileMatrixScale = ViewTransform.ZoomLevelToScale(TileMatrix.ZoomLevel);
|
||||
var tileMatrixScale = ViewTransform.ZoomLevelToScale(TileMatrix.ZoomLevel);
|
||||
|
||||
((MatrixTransform)RenderTransform).Matrix =
|
||||
ParentMap.ViewTransform.GetTileLayerTransform(tileMatrixScale, MapTopLeft, tileMatrixOrigin);
|
||||
((MatrixTransform)RenderTransform).Matrix =
|
||||
ParentMap.ViewTransform.GetTileLayerTransform(tileMatrixScale, MapTopLeft, tileMatrixOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
private bool SetTileMatrix()
|
||||
|
|
@ -199,7 +197,7 @@ namespace MapControl
|
|||
return true;
|
||||
}
|
||||
|
||||
private void UpdateTiles()
|
||||
private Task UpdateTiles()
|
||||
{
|
||||
var tiles = new TileCollection();
|
||||
|
||||
|
|
@ -241,6 +239,8 @@ namespace MapControl
|
|||
{
|
||||
Children.Add(tile.Image);
|
||||
}
|
||||
|
||||
return TileImageLoader.LoadTiles(tiles, TileSource, SourceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,9 +201,9 @@ namespace MapControl
|
|||
|
||||
private async void OnViewportChanged(object sender, ViewportChangedEventArgs e)
|
||||
{
|
||||
if (Children.Count == 0 || e.ProjectionChanged || Math.Abs(e.LongitudeOffset) > 180d)
|
||||
if (Children.Count == 0 || e.ProjectionChanged || e.TransformCenterChanged)
|
||||
{
|
||||
await Update(); // update immediately when projection has changed or center has moved across 180° longitude
|
||||
await Update(); // update immediately
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,22 +8,23 @@ namespace MapControl
|
|||
{
|
||||
public class ViewportChangedEventArgs : EventArgs
|
||||
{
|
||||
public ViewportChangedEventArgs(bool projectionChanged = false, double longitudeOffset = 0d)
|
||||
public ViewportChangedEventArgs(bool projectionChanged = false, bool transformCenterChanged = false)
|
||||
{
|
||||
ProjectionChanged = projectionChanged;
|
||||
LongitudeOffset = longitudeOffset;
|
||||
TransformCenterChanged = transformCenterChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the map projection has changed. Used to control when a MapTileLayer or MapImageLayer
|
||||
/// should be updated immediately, or MapPath Data in projected map coordinates should be recalculated.
|
||||
/// Indicates that the map projection has changed. Used to control when
|
||||
/// a MapTileLayer or a MapImageLayer should be updated immediately,
|
||||
/// or MapPath Data in projected map coordinates should be recalculated.
|
||||
/// </summary>
|
||||
public bool ProjectionChanged { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the map center longitude value from the previous viewport.
|
||||
/// Used to detect if the map center has moved across 180° longitude.
|
||||
/// Indicates that the view transform center has moved across the dateline.
|
||||
/// Used to control when a MapTileLayer should be updated immediately.
|
||||
/// </summary>
|
||||
public double LongitudeOffset { get; }
|
||||
public bool TransformCenterChanged { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,14 +94,11 @@ namespace MapControl
|
|||
return UpdateTiles(null);
|
||||
}
|
||||
|
||||
if (UpdateChildLayers(tileMatrixSet))
|
||||
{
|
||||
SetRenderTransform();
|
||||
var updateTiles = UpdateChildLayers(tileMatrixSet);
|
||||
|
||||
return UpdateTiles(tileMatrixSet);
|
||||
}
|
||||
SetRenderTransform();
|
||||
|
||||
return Task.CompletedTask;
|
||||
return updateTiles ? UpdateTiles(tileMatrixSet) : Task.CompletedTask;
|
||||
}
|
||||
|
||||
protected override void SetRenderTransform()
|
||||
|
|
|
|||
Loading…
Reference in a new issue