Version 1.5.0: Finally fixed the RenderTransform issue in MapRectangle.

This commit is contained in:
ClemensF 2013-10-13 16:32:51 +02:00
parent 2d64d9aa78
commit 1501df5030
23 changed files with 104 additions and 193 deletions

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

22
MapControl/Freezable.cs Normal file
View file

@ -0,0 +1,22 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Xaml;
#else
using System.Windows;
#endif
namespace MapControl
{
internal static class Freezable
{
/// <summary>
/// Provides WPF compatibility.
/// </summary>
public static void Freeze(this DependencyObject obj)
{
}
}
}

View file

@ -64,6 +64,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AnimationEx.Silverlight.cs" />
<Compile Include="Freezable.cs" />
<Compile Include="Int32Rect.cs" />
<Compile Include="Location.cs" />
<Compile Include="LocationCollection.cs" />
@ -75,7 +76,6 @@
<Compile Include="MapGraticule.cs" />
<Compile Include="MapGraticule.Silverlight.WinRT.cs" />
<Compile Include="MapImage.cs" />
<Compile Include="MapImage.Silverlight.WinRT.cs" />
<Compile Include="MapItem.Silverlight.WinRT.cs" />
<Compile Include="MapItemsControl.Silverlight.WinRT.cs" />
<Compile Include="MapPanel.cs" />
@ -85,7 +85,6 @@
<Compile Include="MapPolyline.cs" />
<Compile Include="MapPolyline.Silverlight.WinRT.cs" />
<Compile Include="MapPath.Silverlight.WinRT.cs" />
<Compile Include="MapRectangle.Silverlight.WinRT.cs" />
<Compile Include="MapTransform.cs" />
<Compile Include="MatrixEx.cs" />
<Compile Include="MercatorTransform.cs" />

View file

@ -56,7 +56,6 @@
</Compile>
<Compile Include="MapBase.WPF.cs" />
<Compile Include="MapImage.cs" />
<Compile Include="MapImage.WPF.cs" />
<Compile Include="MapImageLayer.cs" />
<Compile Include="MapItem.WPF.cs" />
<Compile Include="MapItemsControl.WPF.cs" />
@ -67,7 +66,6 @@
<Compile Include="MapRectangle.cs" />
<Compile Include="MapPath.cs" />
<Compile Include="MapPath.WPF.cs" />
<Compile Include="MapRectangle.WPF.cs" />
<Compile Include="MapTransform.cs" />
<Compile Include="MercatorTransform.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View file

@ -1,29 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Xaml.Media;
#else
using System.Windows.Media;
#endif
namespace MapControl
{
public partial class MapImage
{
private void SourceChanged(ImageSource image)
{
var imageTransform = new MatrixTransform
{
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
};
Fill = new ImageBrush
{
ImageSource = image,
RelativeTransform = imageTransform
};
}
}
}

View file

@ -1,30 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace MapControl
{
public partial class MapImage
{
private void SourceChanged(ImageSource image)
{
var bitmap = image as BitmapSource;
if (bitmap != null)
{
var imageTransform = new ScaleTransform(1d, -1d);
imageTransform.Freeze();
bitmap = new TransformedBitmap(bitmap, imageTransform);
bitmap.Freeze();
image = bitmap;
}
Fill = new ImageBrush { ImageSource = image };
}
}
}

View file

@ -15,8 +15,18 @@ namespace MapControl
/// <summary>
/// Fills a rectangular area with an ImageBrush from the Source property.
/// </summary>
public partial class MapImage : MapRectangle
public class MapImage : MapRectangle
{
private static readonly MatrixTransform imageTransform = new MatrixTransform
{
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
};
static MapImage()
{
imageTransform.Freeze();
}
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(MapImage),
new PropertyMetadata(null, (o, e) => ((MapImage)o).SourceChanged((ImageSource)e.NewValue)));
@ -26,5 +36,17 @@ namespace MapControl
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
private void SourceChanged(ImageSource image)
{
var imageBrush = new ImageBrush
{
ImageSource = image,
RelativeTransform = imageTransform
};
imageBrush.Freeze();
Fill = imageBrush;
}
}
}

View file

@ -15,6 +15,9 @@ using System.ComponentModel;
namespace MapControl
{
/// <summary>
/// A polyline or polygon created from a collection of Locations.
/// </summary>
public partial class MapPolyline : MapPath
{
#if NETFX_CORE

View file

@ -1,33 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.Foundation;
using Windows.UI.Xaml.Media;
#else
using System.Windows;
using System.Windows.Media;
#endif
namespace MapControl
{
public partial class MapRectangle
{
private void SetGeometry(Rect rect)
{
var geometry = (RectangleGeometry)Data;
geometry.Rect = rect;
RenderTransform = ParentMap.ViewportTransform;
}
private void ClearGeometry()
{
var geometry = (RectangleGeometry)Data;
geometry.ClearValue(RectangleGeometry.RectProperty);
ClearValue(RenderTransformProperty);
}
}
}

View file

@ -1,64 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;
using System.Windows.Media;
namespace MapControl
{
public partial class MapRectangle
{
static MapRectangle()
{
StrokeThicknessProperty.OverrideMetadata(
typeof(MapRectangle), new FrameworkPropertyMetadata(0d));
FillProperty.OverrideMetadata(
typeof(MapRectangle), new FrameworkPropertyMetadata(FillPropertyChanged));
}
private void SetGeometry(Rect rect)
{
// Instead of setting RenderTransform as done in the Silverlight and
// WinRT versions, the ViewportTransform is applied to the Transform
// properties of the Geometry and the Fill Brush. In WPF, setting the
// RenderTransform property results in incorrect hit testing.
var geometry = (RectangleGeometry)Data;
geometry.Rect = rect;
geometry.Transform = ParentMap.ViewportTransform;
SetBrushTransform(Fill as TileBrush);
}
private void ClearGeometry()
{
var geometry = (RectangleGeometry)Data;
geometry.ClearValue(RectangleGeometry.RectProperty);
geometry.ClearValue(Geometry.TransformProperty);
}
private void SetBrushTransform(TileBrush tileBrush)
{
if (tileBrush != null && Data != null)
{
var geometry = (RectangleGeometry)Data;
tileBrush.ViewportUnits = BrushMappingMode.Absolute;
tileBrush.Viewport = geometry.Rect;
tileBrush.Transform = geometry.Transform;
}
}
private static void FillPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != e.OldValue)
{
((MapRectangle)o).SetBrushTransform(e.NewValue as TileBrush);
}
}
}
}

View file

@ -16,8 +16,21 @@ namespace MapControl
/// <summary>
/// Fills a rectangular area defined by South, North, West and East with a Brush.
/// </summary>
public partial class MapRectangle : MapPath
public class MapRectangle : MapPath
{
private const double geometryScale = 1e6;
private static readonly ScaleTransform geometryScaleTransform = new ScaleTransform
{
ScaleX = 1d / geometryScale,
ScaleY = 1d / geometryScale
};
static MapRectangle()
{
geometryScaleTransform.Freeze();
}
public static readonly DependencyProperty SouthProperty = DependencyProperty.Register(
"South", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateData()));
@ -66,6 +79,8 @@ namespace MapControl
protected override void UpdateData()
{
var geometry = (RectangleGeometry)Data;
if (ParentMap != null &&
!double.IsNaN(South) && !double.IsNaN(North) &&
!double.IsNaN(West) && !double.IsNaN(East) &&
@ -74,11 +89,21 @@ namespace MapControl
var p1 = ParentMap.MapTransform.Transform(new Location(South, West));
var p2 = ParentMap.MapTransform.Transform(new Location(North, East));
SetGeometry(new Rect(p1.X, p1.Y, p2.X - p1.X, p2.Y - p1.Y));
// Create a scaled RectangleGeometry due to inaccurate hit testing in WPF.
// See http://stackoverflow.com/a/19335624/1136211
geometry.Rect = new Rect(p1.X * geometryScale, p1.Y * geometryScale,
(p2.X - p1.X) * geometryScale, (p2.Y - p1.Y) * geometryScale);
var transform = new TransformGroup();
transform.Children.Add(geometryScaleTransform); // revert scaling
transform.Children.Add(ParentMap.ViewportTransform);
RenderTransform = transform;
}
else
{
ClearGeometry();
geometry.ClearValue(RectangleGeometry.RectProperty);
ClearValue(RenderTransformProperty);
}
}
}

View file

@ -15,8 +15,8 @@ using System.Windows;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -17,9 +17,9 @@ namespace MapControl
{
internal partial class TileContainer : Panel
{
private void SetViewportTransform(Matrix transform)
private Matrix GetViewportTransformMatrix(Matrix transform)
{
ViewportTransform.Matrix = transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
return transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
}
/// <summary>

View file

@ -9,10 +9,11 @@ namespace MapControl
{
internal partial class TileContainer : ContainerVisual
{
private void SetViewportTransform(Matrix transform)
private Matrix GetViewportTransformMatrix(Matrix transform)
{
transform.RotateAt(rotation, viewportOrigin.X, viewportOrigin.Y);
ViewportTransform.Matrix = transform;
return transform;
}
/// <summary>

View file

@ -101,7 +101,7 @@ namespace MapControl
tileLayerOffset.X = transformOffsetX - 180d * scale;
tileLayerOffset.Y = transformOffsetY - 180d * scale;
SetViewportTransform(new Matrix(scale, 0d, 0d, -scale, transformOffsetX, transformOffsetY));
ViewportTransform.Matrix = GetViewportTransformMatrix(new Matrix(scale, 0d, 0d, -scale, transformOffsetX, transformOffsetY));
if (Math.Sign(mapOrigin.X) != Math.Sign(oldMapOriginX) && Math.Abs(mapOrigin.X) > 90d)
{

View file

@ -36,6 +36,9 @@
<Compile Include="..\AnimationEx.WinRT.cs">
<Link>AnimationEx.WinRT.cs</Link>
</Compile>
<Compile Include="..\Freezable.cs">
<Link>Freezable.cs</Link>
</Compile>
<Compile Include="..\Int32Rect.cs">
<Link>Int32Rect.cs</Link>
</Compile>
@ -63,9 +66,6 @@
<Compile Include="..\MapImage.cs">
<Link>MapImage.cs</Link>
</Compile>
<Compile Include="..\MapImage.Silverlight.WinRT.cs">
<Link>MapImage.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapItem.Silverlight.WinRT.cs">
<Link>MapItem.Silverlight.WinRT.cs</Link>
</Compile>
@ -93,9 +93,6 @@
<Compile Include="..\MapRectangle.cs">
<Link>MapRectangle.cs</Link>
</Compile>
<Compile Include="..\MapRectangle.Silverlight.WinRT.cs">
<Link>MapRectangle.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapTransform.cs">
<Link>MapTransform.cs</Link>
</Compile>

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]

View file

@ -8,8 +8,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.4.2")]
[assembly: AssemblyFileVersion("1.4.2")]
[assembly: AssemblyVersion("1.5.0")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]