diff --git a/MapControl.sln b/MapControl.sln
index e22a014f..0837cfbe 100644
--- a/MapControl.sln
+++ b/MapControl.sln
@@ -7,16 +7,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MapControl", "MapControl",
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleApps", "SampleApps", "{8F2103C2-78AF-4810-8FB9-67572F50C8FC}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfApplication", "SampleApps\WpfApplication\WpfApplication.csproj", "{F92DA93D-75DB-4308-A5F9-6B4C3908A675}"
-EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalApp", "SampleApps\UniversalApp\UniversalApp.csproj", "{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapControl.UWP", "MapControl\UWP\MapControl.UWP.csproj", "{9545F73C-9C35-4CF6-BAAE-19A0BAEBD344}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfCoreApp", "SampleApps\WpfCoreApp\WpfCoreApp.csproj", "{E9D15B9A-75F5-40A9-A582-9BFBB074C127}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MapControl.WPF", "MapControl\WPF\MapControl.WPF.csproj", "{62F1726B-3144-49F4-8BCC-94160A3B2186}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfApplication", "SampleApps\WpfApplication\WpfApplication.csproj", "{CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -29,22 +27,6 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|ARM.Build.0 = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|x64.ActiveCfg = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|x64.Build.0 = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|x86.ActiveCfg = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Debug|x86.Build.0 = Debug|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|Any CPU.Build.0 = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|ARM.ActiveCfg = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|ARM.Build.0 = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|x64.ActiveCfg = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|x64.Build.0 = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|x86.ActiveCfg = Release|Any CPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}.Release|x86.Build.0 = Release|Any CPU
{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1}.Debug|Any CPU.ActiveCfg = Debug|x64
{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1}.Debug|Any CPU.Build.0 = Debug|x64
{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1}.Debug|Any CPU.Deploy.0 = Debug|x64
@@ -85,22 +67,6 @@ Global
{9545F73C-9C35-4CF6-BAAE-19A0BAEBD344}.Release|x64.Build.0 = Release|Any CPU
{9545F73C-9C35-4CF6-BAAE-19A0BAEBD344}.Release|x86.ActiveCfg = Release|Any CPU
{9545F73C-9C35-4CF6-BAAE-19A0BAEBD344}.Release|x86.Build.0 = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|ARM.Build.0 = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|x64.ActiveCfg = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|x64.Build.0 = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|x86.ActiveCfg = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Debug|x86.Build.0 = Debug|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|Any CPU.Build.0 = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|ARM.ActiveCfg = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|ARM.Build.0 = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|x64.ActiveCfg = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|x64.Build.0 = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|x86.ActiveCfg = Release|Any CPU
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127}.Release|x86.Build.0 = Release|Any CPU
{62F1726B-3144-49F4-8BCC-94160A3B2186}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62F1726B-3144-49F4-8BCC-94160A3B2186}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62F1726B-3144-49F4-8BCC-94160A3B2186}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -117,16 +83,31 @@ Global
{62F1726B-3144-49F4-8BCC-94160A3B2186}.Release|x64.Build.0 = Release|Any CPU
{62F1726B-3144-49F4-8BCC-94160A3B2186}.Release|x86.ActiveCfg = Release|Any CPU
{62F1726B-3144-49F4-8BCC-94160A3B2186}.Release|x86.Build.0 = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|ARM.Build.0 = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|x64.Build.0 = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Debug|x86.Build.0 = Debug|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|ARM.ActiveCfg = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|ARM.Build.0 = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|x64.ActiveCfg = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|x64.Build.0 = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|x86.ActiveCfg = Release|Any CPU
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
{AA62B4AA-1CA3-4C20-BEB7-B824D0FC4BD1} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
{9545F73C-9C35-4CF6-BAAE-19A0BAEBD344} = {52AECE49-F314-4F76-98F2-FA800F07824B}
- {E9D15B9A-75F5-40A9-A582-9BFBB074C127} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
{62F1726B-3144-49F4-8BCC-94160A3B2186} = {52AECE49-F314-4F76-98F2-FA800F07824B}
+ {CA60DFDB-0BE1-40F6-B575-CDC797A40E2E} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {458346DD-B23F-4FDC-8F9D-A10F1882A4DB}
diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs
index ce4d785f..6a9b7ee1 100644
--- a/MapControl/Shared/MapBase.cs
+++ b/MapControl/Shared/MapBase.cs
@@ -69,12 +69,12 @@ namespace MapControl
private DoubleAnimation zoomLevelAnimation;
private DoubleAnimation headingAnimation;
private Location transformCenter;
- private Point viewportCenter;
+ private Point viewCenter;
private double centerLongitude;
private bool internalPropertyChange;
///
- /// Raised when the current viewport has changed.
+ /// Raised when the current map viewport has changed.
///
public event EventHandler ViewportChanged;
@@ -224,59 +224,56 @@ namespace MapControl
}
///
- /// Gets the transformation from cartesian map coordinates to viewport coordinates.
+ /// Gets the scaling factor from cartesian map coordinates to view coordinates,
+ /// i.e. pixels per meter, as a read-only dependency property.
+ ///
+ public double ViewScale
+ {
+ get { return (double)GetValue(ViewScaleProperty); }
+ private set { SetViewScale(value); }
+ }
+
+ ///
+ /// Gets the ViewTransform instance that is used to transform between cartesian map coordinates
+ /// and view coordinates.
///
public ViewTransform ViewTransform { get; } = new ViewTransform();
///
- /// Gets the transformation from cartesian map coordinates to viewport coordinates as MatrixTransform.
+ /// Gets a MatrixTransform that can be used to transform from cartesian map coordinates
+ /// to view coordinates.
///
- public MatrixTransform ViewportTransform { get; } = new MatrixTransform();
+ public MatrixTransform MapToViewTransform { get; } = new MatrixTransform();
///
- /// Gets the scaling transformation from meters to viewport coordinates at the Center location.
+ /// Gets the horizontal and vertical scaling factors from cartesian map coordinates to view
+ /// coordinates at the specified location, i.e. pixels per meter.
///
- public ScaleTransform ScaleTransform { get; } = new ScaleTransform();
-
- ///
- /// Gets the transformation that rotates by the value of the Heading property.
- ///
- public RotateTransform RotateTransform { get; } = new RotateTransform();
-
- ///
- /// Gets the combination of ScaleTransform and RotateTransform
- ///
- public TransformGroup ScaleRotateTransform
+ public Vector GetScale(Location location)
{
- get
- {
- var transform = new TransformGroup();
- transform.Children.Add(ScaleTransform);
- transform.Children.Add(RotateTransform);
- return transform;
- }
+ return ViewTransform.Scale * MapProjection.GetRelativeScale(location);
}
///
- /// Transforms a Location in geographic coordinates to a Point in viewport coordinates.
+ /// Transforms a Location in geographic coordinates to a Point in view coordinates.
///
- public Point LocationToViewportPoint(Location location)
+ public Point LocationToView(Location location)
{
return ViewTransform.MapToView(MapProjection.LocationToMap(location));
}
///
- /// Transforms a Point in viewport coordinates to a Location in geographic coordinates.
+ /// Transforms a Point in view coordinates to a Location in geographic coordinates.
///
- public Location ViewportPointToLocation(Point point)
+ public Location ViewToLocation(Point point)
{
return MapProjection.MapToLocation(ViewTransform.ViewToMap(point));
}
///
- /// Transforms a Rect in viewport coordinates to a BoundingBox in geographic coordinates.
+ /// Transforms a Rect in view coordinates to a BoundingBox in geographic coordinates.
///
- public BoundingBox ViewportRectToBoundingBox(Rect rect)
+ public BoundingBox ViewRectToBoundingBox(Rect rect)
{
var p1 = ViewTransform.ViewToMap(new Point(rect.X, rect.Y));
var p2 = ViewTransform.ViewToMap(new Point(rect.X, rect.Y + rect.Height));
@@ -292,13 +289,13 @@ namespace MapControl
}
///
- /// Sets a temporary center point in viewport coordinates for scaling and rotation transformations.
+ /// 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.
///
public void SetTransformCenter(Point center)
{
- transformCenter = ViewportPointToLocation(center);
- viewportCenter = center;
+ transformCenter = ViewToLocation(center);
+ viewCenter = center;
}
///
@@ -307,11 +304,11 @@ namespace MapControl
public void ResetTransformCenter()
{
transformCenter = null;
- viewportCenter = new Point(RenderSize.Width / 2d, RenderSize.Height / 2d);
+ viewCenter = new Point(RenderSize.Width / 2d, RenderSize.Height / 2d);
}
///
- /// Changes the Center property according to the specified translation in viewport coordinates.
+ /// Changes the Center property according to the specified translation in view coordinates.
///
public void TranslateMap(Vector translation)
{
@@ -323,21 +320,21 @@ namespace MapControl
if (translation.X != 0d || translation.Y != 0d)
{
- Center = ViewportPointToLocation(viewportCenter - translation);
+ Center = ViewToLocation(viewCenter - translation);
}
}
///
/// Changes the Center, Heading and ZoomLevel properties according to the specified
- /// viewport coordinate translation, rotation and scale delta values. Rotation and scaling
- /// is performed relative to the specified center point in viewport coordinates.
+ /// view coordinate translation, rotation and scale delta values. Rotation and scaling
+ /// is performed relative to the specified center point in view coordinates.
///
public void TransformMap(Point center, Vector translation, double rotation, double scale)
{
if (rotation != 0d || scale != 1d)
{
- transformCenter = ViewportPointToLocation(center);
- viewportCenter = center + translation;
+ transformCenter = ViewToLocation(center);
+ viewCenter = center + translation;
if (rotation != 0d)
{
@@ -363,7 +360,7 @@ namespace MapControl
///
/// Sets the value of the TargetZoomLevel property while retaining the specified center point
- /// in viewport coordinates.
+ /// in view coordinates.
///
public void ZoomMap(Point center, double zoomLevel)
{
@@ -378,16 +375,15 @@ namespace MapControl
///
/// Sets the TargetZoomLevel and TargetCenter properties so that the specified bounding box
- /// fits into the current viewport. The TargetHeading property is set to zero.
+ /// fits into the current view. The TargetHeading property is set to zero.
///
public void ZoomToBounds(BoundingBox boundingBox)
{
var rect = MapProjection.BoundingBoxToRect(boundingBox);
var center = new Point(rect.X + rect.Width / 2d, rect.Y + rect.Height / 2d);
- var scale = Math.Min(RenderSize.Width / rect.Width, RenderSize.Height / rect.Height)
- * MapProjection.Wgs84MetersPerDegree * 360d / 256d;
+ var scale = Math.Min(RenderSize.Width / rect.Width, RenderSize.Height / rect.Height);
- TargetZoomLevel = Math.Log(scale, 2d);
+ TargetZoomLevel = ViewTransform.ScaleToZoomLevel(scale);
TargetCenter = MapProjection.MapToLocation(center);
TargetHeading = 0d;
}
@@ -703,16 +699,19 @@ namespace MapControl
private void UpdateTransform(bool resetTransformCenter = false, bool projectionChanged = false)
{
var projection = MapProjection;
- var viewportScale = 256d * Math.Pow(2d, ZoomLevel) / (360d * MapProjection.Wgs84MetersPerDegree);
- var center = transformCenter ?? Center;
projection.Center = ProjectionCenter ?? Center;
- ViewTransform.SetTransform(projection.LocationToMap(center), viewportCenter, viewportScale, Heading);
+ var center = transformCenter ?? Center;
+ var mapCenter = projection.LocationToMap(center);
+
+ var viewScale = ViewTransform.ZoomLevelToScale(ZoomLevel);
+
+ ViewTransform.SetTransform(mapCenter, viewCenter, viewScale, Heading);
if (transformCenter != null)
{
- center = ViewportPointToLocation(new Point(RenderSize.Width / 2d, RenderSize.Height / 2d));
+ center = ViewToLocation(new Point(RenderSize.Width / 2d, RenderSize.Height / 2d));
center.Longitude = Location.NormalizeLongitude(center.Longitude);
if (center.Latitude < -projection.MaxLatitude || center.Latitude > projection.MaxLatitude)
@@ -733,18 +732,14 @@ namespace MapControl
ResetTransformCenter();
projection.Center = ProjectionCenter ?? center;
+ mapCenter = projection.LocationToMap(center);
- ViewTransform.SetTransform(projection.LocationToMap(center), viewportCenter, viewportScale, Heading);
+ ViewTransform.SetTransform(mapCenter, viewCenter, viewScale, Heading);
}
}
- ViewportTransform.Matrix = ViewTransform.MapToViewMatrix;
-
- var scale = projection.GetRelativeScale(center);
- ScaleTransform.ScaleX = scale.X * ViewTransform.Scale;
- ScaleTransform.ScaleY = scale.Y * ViewTransform.Scale;
-
- RotateTransform.Angle = ViewTransform.Rotation;
+ ViewScale = ViewTransform.Scale;
+ MapToViewTransform.Matrix = ViewTransform.MapToViewMatrix;
OnViewportChanged(new ViewportChangedEventArgs(projectionChanged, Center.Longitude - centerLongitude));
diff --git a/MapControl/Shared/MapImageLayer.cs b/MapControl/Shared/MapImageLayer.cs
index a8f92ba7..722f2a28 100644
--- a/MapControl/Shared/MapImageLayer.cs
+++ b/MapControl/Shared/MapImageLayer.cs
@@ -23,11 +23,14 @@ using System.Windows.Threading;
namespace MapControl
{
///
- /// Map image layer. Fills the entire viewport with a map image, e.g. provided by a Web Map Service.
+ /// Map image layer. Fills the viewport with a single map image, e.g. provided by a Web Map Service.
/// The image must be provided by the abstract GetImageAsync method.
///
public abstract class MapImageLayer : MapPanel, IMapLayer
{
+ public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
+ nameof(Description), typeof(string), typeof(MapImageLayer), new PropertyMetadata(null));
+
public static readonly DependencyProperty MinLatitudeProperty = DependencyProperty.Register(
nameof(MinLatitude), typeof(double), typeof(MapImageLayer), new PropertyMetadata(double.NaN));
@@ -53,9 +56,6 @@ namespace MapControl
public static readonly DependencyProperty UpdateWhileViewportChangingProperty = DependencyProperty.Register(
nameof(UpdateWhileViewportChanging), typeof(bool), typeof(MapImageLayer), new PropertyMetadata(false));
- public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
- nameof(Description), typeof(string), typeof(MapImageLayer), new PropertyMetadata(null));
-
public static readonly DependencyProperty MapBackgroundProperty = DependencyProperty.Register(
nameof(MapBackground), typeof(Brush), typeof(MapImageLayer), new PropertyMetadata(null));
@@ -74,6 +74,16 @@ namespace MapControl
updateTimer.Tick += async (s, e) => await UpdateImageAsync();
}
+ ///
+ /// Description of the MapImageLayer.
+ /// Used to display copyright information on top of the map.
+ ///
+ public string Description
+ {
+ get { return (string)GetValue(DescriptionProperty); }
+ set { SetValue(DescriptionProperty, value); }
+ }
+
///
/// Optional minimum latitude value. Default is NaN.
///
@@ -120,9 +130,9 @@ namespace MapControl
}
///
- /// Relative size of the map image in relation to the current viewport size.
+ /// Relative size of the map image in relation to the current view size.
/// Setting a value greater than one will let MapImageLayer request images that
- /// are larger than the viewport, in order to support smooth panning.
+ /// are larger than the view, in order to support smooth panning.
///
public double RelativeImageSize
{
@@ -148,16 +158,6 @@ namespace MapControl
set { SetValue(UpdateWhileViewportChangingProperty, value); }
}
- ///
- /// Description of the MapImageLayer.
- /// Used to display copyright information on top of the map.
- ///
- public string Description
- {
- get { return (string)GetValue(DescriptionProperty); }
- set { SetValue(DescriptionProperty, value); }
- }
-
///
/// Optional foreground brush.
/// Sets MapBase.Foreground if not null and the MapImageLayer is the base map layer.
@@ -258,7 +258,7 @@ namespace MapControl
var y = (ParentMap.RenderSize.Height - height) / 2d;
var rect = new Rect(x, y, width, height);
- BoundingBox = ParentMap.ViewportRectToBoundingBox(rect);
+ BoundingBox = ParentMap.ViewRectToBoundingBox(rect);
if (BoundingBox != null)
{
diff --git a/MapControl/Shared/MapItemsControl.cs b/MapControl/Shared/MapItemsControl.cs
index c67461d5..8a5f1f41 100644
--- a/MapControl/Shared/MapItemsControl.cs
+++ b/MapControl/Shared/MapItemsControl.cs
@@ -74,7 +74,7 @@ namespace MapControl
{
SelectItems(item =>
{
- var pos = MapPanel.GetViewportPosition(ContainerFromItem(item));
+ var pos = MapPanel.GetViewPosition(ContainerFromItem(item));
return pos.HasValue && predicate(pos.Value);
});
}
@@ -116,10 +116,10 @@ namespace MapControl
}
else if (shiftKey && SelectedItem != null)
{
- // Extended with Shift -> select items in viewport rectangle
+ // Extended with Shift -> select items in view rectangle
- var p1 = MapPanel.GetViewportPosition(ContainerFromItem(SelectedItem));
- var p2 = MapPanel.GetViewportPosition(mapItem);
+ var p1 = MapPanel.GetViewPosition(ContainerFromItem(SelectedItem));
+ var p2 = MapPanel.GetViewPosition(mapItem);
if (p1.HasValue && p2.HasValue)
{
diff --git a/MapControl/Shared/MapPanel.cs b/MapControl/Shared/MapPanel.cs
index 8b400c4c..ca335af4 100644
--- a/MapControl/Shared/MapPanel.cs
+++ b/MapControl/Shared/MapPanel.cs
@@ -58,9 +58,9 @@ namespace MapControl
element.SetValue(BoundingBoxProperty, value);
}
- public static Point? GetViewportPosition(FrameworkElement element)
+ public static Point? GetViewPosition(FrameworkElement element)
{
- return (Point?)element.GetValue(ViewportPositionProperty);
+ return (Point?)element.GetValue(ViewPositionProperty);
}
public MapBase ParentMap
@@ -118,9 +118,9 @@ namespace MapControl
if (location != null)
{
- var viewportPosition = ArrangeElement(element, location);
+ var viewPosition = ArrangeElement(element, location);
- SetViewportPosition(element, viewportPosition);
+ SetViewPosition(element, viewPosition);
}
else
{
@@ -135,7 +135,7 @@ namespace MapControl
ArrangeElement(element, finalSize);
}
- SetViewportPosition(element, null);
+ SetViewPosition(element, null);
}
}
}
@@ -145,13 +145,13 @@ namespace MapControl
private Point ArrangeElement(FrameworkElement element, Location location)
{
- var pos = parentMap.LocationToViewportPoint(location);
+ var pos = parentMap.LocationToView(location);
if (parentMap.MapProjection.IsNormalCylindrical &&
(pos.X < 0d || pos.X > parentMap.RenderSize.Width ||
pos.Y < 0d || pos.Y > parentMap.RenderSize.Height))
{
- pos = parentMap.LocationToViewportPoint(new Location(
+ pos = parentMap.LocationToView(new Location(
location.Latitude,
Location.NearestLongitude(location.Longitude, parentMap.Center.Longitude)));
}
@@ -210,7 +210,7 @@ namespace MapControl
var location = projection.MapToLocation(center);
location.Longitude = Location.NearestLongitude(location.Longitude, parentMap.Center.Longitude);
- pos = parentMap.LocationToViewportPoint(location);
+ pos = parentMap.LocationToView(location);
}
rect.Width *= parentMap.ViewTransform.Scale;
@@ -229,14 +229,15 @@ namespace MapControl
element.Arrange(rect);
var rotateTransform = element.RenderTransform as RotateTransform;
+ var rotation = parentMap.ViewTransform.Rotation;
if (rotateTransform != null)
{
- rotateTransform.Angle = parentMap.Heading;
+ rotateTransform.Angle = rotation;
}
- else if (parentMap.Heading != 0d)
+ else if (rotation != 0d)
{
- rotateTransform = new RotateTransform { Angle = parentMap.Heading };
+ rotateTransform = new RotateTransform { Angle = rotation };
element.RenderTransform = rotateTransform;
element.RenderTransformOrigin = new Point(0.5, 0.5);
}
diff --git a/MapControl/Shared/MapPath.cs b/MapControl/Shared/MapPath.cs
new file mode 100644
index 00000000..638b8cfe
--- /dev/null
+++ b/MapControl/Shared/MapPath.cs
@@ -0,0 +1,142 @@
+// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
+// © 2020 Clemens Fischer
+// Licensed under the Microsoft Public License (Ms-PL)
+
+#if WINDOWS_UWP
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Media;
+#else
+using System.Windows;
+using System.Windows.Media;
+#endif
+
+namespace MapControl
+{
+ ///
+ /// A path element with a Data property that holds a Geometry in cartesian map coordinates
+ /// or view coordinates. Cartesian coordinates can optionally be relative to an origin Location.
+ ///
+ public partial class MapPath : IMapElement
+ {
+ public static readonly DependencyProperty LocationProperty = DependencyProperty.Register(
+ nameof(Location), typeof(Location), typeof(MapPath),
+ new PropertyMetadata(null, (o, e) => ((MapPath)o).LocationOrViewportChanged()));
+
+ private MapBase parentMap;
+ private MatrixTransform dataTransform;
+ private double longitudeOffset;
+
+ public MapPath()
+ {
+ MapPanel.InitMapElement(this);
+ }
+
+ ///
+ /// Gets or sets a Location that is used as
+ /// - either the origin point of a geometry specified in cartesian map units (meters)
+ /// - or as an optional value to constrain the view position of MapPaths with multiple
+ /// Locations (like MapPolyline or MapPolygon) to the visible map viewport, as done
+ /// for elements where the MapPanel.Location property is set.
+ ///
+ public Location Location
+ {
+ get { return (Location)GetValue(LocationProperty); }
+ set { SetValue(LocationProperty, value); }
+ }
+
+ public MapBase ParentMap
+ {
+ get { return parentMap; }
+ set
+ {
+ if (parentMap != null)
+ {
+ parentMap.ViewportChanged -= OnViewportChanged;
+ }
+
+ parentMap = value;
+
+ if (parentMap != null)
+ {
+ parentMap.ViewportChanged += OnViewportChanged;
+ }
+
+ LocationOrViewportChanged();
+ }
+ }
+
+ private void OnViewportChanged(object sender, ViewportChangedEventArgs e)
+ {
+ LocationOrViewportChanged();
+ }
+
+ private void LocationOrViewportChanged()
+ {
+ longitudeOffset = 0d;
+
+ if (parentMap != null && parentMap.MapProjection.IsNormalCylindrical && Location != null)
+ {
+ var viewPos = LocationToView(Location);
+
+ if (viewPos.X < 0d || viewPos.X > parentMap.RenderSize.Width ||
+ viewPos.Y < 0d || viewPos.Y > parentMap.RenderSize.Height)
+ {
+ longitudeOffset = Location.NearestLongitude(Location.Longitude, parentMap.Center.Longitude) - Location.Longitude;
+ }
+ }
+
+ UpdateData();
+ }
+
+ protected virtual void UpdateData()
+ {
+ if (parentMap != null && Data != null)
+ {
+ if (dataTransform == null)
+ {
+ Data.Transform = dataTransform = new MatrixTransform();
+ }
+
+ if (Location != null)
+ {
+ var viewPos = LocationToView(Location);
+ var scale = parentMap.GetScale(Location);
+ var matrix = new Matrix(scale.X, 0, 0, scale.Y, 0, 0);
+ matrix.Rotate(parentMap.Heading);
+ matrix.Translate(viewPos.X, viewPos.Y);
+ dataTransform.Matrix = matrix;
+ }
+ else
+ {
+ dataTransform.Matrix = parentMap.ViewTransform.MapToViewMatrix;
+ }
+ }
+ }
+
+ protected Point LocationToMap(Location location)
+ {
+ if (longitudeOffset != 0d)
+ {
+ location = new Location(location.Latitude, location.Longitude + longitudeOffset);
+ }
+
+ var point = parentMap.MapProjection.LocationToMap(location);
+
+ if (point.Y == double.PositiveInfinity)
+ {
+ point.Y = 1e9;
+ }
+ else if (point.X == double.NegativeInfinity)
+ {
+ point.Y = -1e9;
+ }
+
+ return point;
+ }
+
+ protected Point LocationToView(Location location)
+ {
+ return parentMap.ViewTransform.MapToView(LocationToMap(location));
+ }
+ }
+}
diff --git a/MapControl/Shared/MapPolygon.cs b/MapControl/Shared/MapPolygon.cs
index c6a27933..06a18eef 100644
--- a/MapControl/Shared/MapPolygon.cs
+++ b/MapControl/Shared/MapPolygon.cs
@@ -17,7 +17,7 @@ namespace MapControl
///
/// A polygon defined by a collection of Locations.
///
- public class MapPolygon : MapShape
+ public class MapPolygon : MapPath
{
public static readonly DependencyProperty LocationsProperty = DependencyProperty.Register(
nameof(Locations), typeof(IEnumerable), typeof(MapPolygon),
@@ -35,6 +35,11 @@ namespace MapControl
set { SetValue(LocationsProperty, value); }
}
+ public MapPolygon()
+ {
+ Data = new PathGeometry();
+ }
+
protected override void UpdateData()
{
var figures = ((PathGeometry)Data).Figures;
diff --git a/MapControl/Shared/MapPolyline.cs b/MapControl/Shared/MapPolyline.cs
index 9605791e..a2df81db 100644
--- a/MapControl/Shared/MapPolyline.cs
+++ b/MapControl/Shared/MapPolyline.cs
@@ -17,7 +17,7 @@ namespace MapControl
///
/// A polyline defined by a collection of Locations.
///
- public class MapPolyline : MapShape
+ public class MapPolyline : MapPath
{
public static readonly DependencyProperty LocationsProperty = DependencyProperty.Register(
nameof(Locations), typeof(IEnumerable), typeof(MapPolyline),
@@ -35,6 +35,11 @@ namespace MapControl
set { SetValue(LocationsProperty, value); }
}
+ public MapPolyline()
+ {
+ Data = new PathGeometry();
+ }
+
protected override void UpdateData()
{
var figures = ((PathGeometry)Data).Figures;
diff --git a/MapControl/Shared/MapScale.cs b/MapControl/Shared/MapScale.cs
index 3a80e4b8..a2c8d36c 100644
--- a/MapControl/Shared/MapScale.cs
+++ b/MapControl/Shared/MapScale.cs
@@ -59,9 +59,10 @@ namespace MapControl
{
var size = new Size();
- if (ParentMap != null && ParentMap.ScaleTransform.ScaleX > 0d)
+ if (ParentMap != null)
{
- var length = MinWidth / ParentMap.ScaleTransform.ScaleX;
+ var scale = ParentMap.GetScale(ParentMap.Center).X;
+ var length = MinWidth / scale;
var magnitude = Math.Pow(10d, Math.Floor(Math.Log10(length)));
if (length / magnitude < 2d)
@@ -77,7 +78,7 @@ namespace MapControl
length = 10d * magnitude;
}
- size.Width = length * ParentMap.ScaleTransform.ScaleX + StrokeThickness + Padding.Left + Padding.Right;
+ size.Width = length * scale + StrokeThickness + Padding.Left + Padding.Right;
size.Height = 1.25 * FontSize + StrokeThickness + Padding.Top + Padding.Bottom;
var x1 = Padding.Left + StrokeThickness / 2d;
diff --git a/MapControl/Shared/MapShape.cs b/MapControl/Shared/MapShape.cs
deleted file mode 100644
index 3ef8fc01..00000000
--- a/MapControl/Shared/MapShape.cs
+++ /dev/null
@@ -1,125 +0,0 @@
-// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control
-// © 2020 Clemens Fischer
-// Licensed under the Microsoft Public License (Ms-PL)
-
-#if WINDOWS_UWP
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Media;
-#else
-using System.Windows;
-using System.Windows.Media;
-#endif
-
-namespace MapControl
-{
- ///
- /// Base class for MapPolyline and MapPolygon.
- ///
- public abstract partial class MapShape : IMapElement
- {
- public static readonly DependencyProperty LocationProperty = DependencyProperty.Register(
- nameof(Location), typeof(Location), typeof(MapShape),
- new PropertyMetadata(null, (o, e) => ((MapShape)o).LocationPropertyChanged()));
-
- ///
- /// Gets or sets an optional Location to constrain the viewport position to the visible
- /// map viewport, as done for elements where the MapPanel.Location property is set.
- ///
- public Location Location
- {
- get { return (Location)GetValue(LocationProperty); }
- set { SetValue(LocationProperty, value); }
- }
-
- private void LocationPropertyChanged()
- {
- if (parentMap != null)
- {
- UpdateData();
- }
- }
-
- private MapBase parentMap;
-
- public MapBase ParentMap
- {
- get { return parentMap; }
- set
- {
- if (parentMap != null)
- {
- parentMap.ViewportChanged -= OnViewportChanged;
- }
-
- parentMap = value;
-
- if (parentMap != null)
- {
- parentMap.ViewportChanged += OnViewportChanged;
- }
-
- UpdateData();
- }
- }
-
- private void OnViewportChanged(object sender, ViewportChangedEventArgs e)
- {
- UpdateData();
- }
-
- protected abstract void UpdateData();
-
- protected MapShape()
- : this(new PathGeometry())
- {
- }
-
- protected MapShape(Geometry data)
- {
- Data = data;
-
- MapPanel.InitMapElement(this);
- }
-
- protected Point LocationToMap(Location location)
- {
- var point = parentMap.MapProjection.LocationToMap(location);
-
- if (point.Y == double.PositiveInfinity)
- {
- point.Y = 1e9;
- }
- else if (point.X == double.NegativeInfinity)
- {
- point.Y = -1e9;
- }
-
- return point;
- }
-
- protected Point LocationToViewportPoint(Location location)
- {
- return parentMap.ViewTransform.MapToView(LocationToMap(location));
- }
-
- protected double GetLongitudeOffset()
- {
- var longitudeOffset = 0d;
-
- if (parentMap.MapProjection.IsNormalCylindrical && Location != null)
- {
- var viewportPosition = LocationToViewportPoint(Location);
-
- if (viewportPosition.X < 0d || viewportPosition.X > parentMap.RenderSize.Width ||
- viewportPosition.Y < 0d || viewportPosition.Y > parentMap.RenderSize.Height)
- {
- var nearestLongitude = Location.NearestLongitude(Location.Longitude, parentMap.Center.Longitude);
-
- longitudeOffset = nearestLongitude - Location.Longitude;
- }
- }
-
- return longitudeOffset;
- }
- }
-}
diff --git a/MapControl/Shared/MapTileLayer.cs b/MapControl/Shared/MapTileLayer.cs
index 6aa6a7d4..86d35ab1 100644
--- a/MapControl/Shared/MapTileLayer.cs
+++ b/MapControl/Shared/MapTileLayer.cs
@@ -17,7 +17,7 @@ using System.Windows.Media;
namespace MapControl
{
///
- /// Fills the map viewport with map tiles from a TileSource.
+ /// Fills the viewport with map tiles from a TileSource.
///
public class MapTileLayer : MapTileLayerBase
{
@@ -26,11 +26,6 @@ namespace MapControl
public static readonly Point TileMatrixTopLeft = new Point(
-180d * MapProjection.Wgs84MetersPerDegree, 180d * MapProjection.Wgs84MetersPerDegree);
- public static double TileMatrixScale(int zoomLevel)
- {
- return (TileSize << zoomLevel) / (360d * MapProjection.Wgs84MetersPerDegree);
- }
-
///
/// A default MapTileLayer using OpenStreetMap data.
///
@@ -117,18 +112,22 @@ namespace MapControl
//
var tileMatrixOrigin = new Point(TileSize * TileMatrix.XMin, TileSize * TileMatrix.YMin);
+ var tileMatrixScale = ViewTransform.ZoomLevelToScale(TileMatrix.ZoomLevel);
+
((MatrixTransform)RenderTransform).Matrix = ParentMap.ViewTransform.GetTileLayerTransform(
- TileMatrixScale(TileMatrix.ZoomLevel), TileMatrixTopLeft, tileMatrixOrigin);
+ tileMatrixScale, TileMatrixTopLeft, tileMatrixOrigin);
}
private bool SetTileMatrix()
{
var tileMatrixZoomLevel = (int)Math.Floor(ParentMap.ZoomLevel + 0.001); // avoid rounding issues
- // bounds in tile pixels from viewport size
+ var tileMatrixScale = ViewTransform.ZoomLevelToScale(tileMatrixZoomLevel);
+
+ // bounds in tile pixels from view size
//
var tileBounds = ParentMap.ViewTransform.GetTileMatrixBounds(
- TileMatrixScale(tileMatrixZoomLevel), TileMatrixTopLeft, ParentMap.RenderSize);
+ tileMatrixScale, TileMatrixTopLeft, ParentMap.RenderSize);
// tile column and row index bounds
//
diff --git a/MapControl/Shared/ViewTransform.cs b/MapControl/Shared/ViewTransform.cs
index dd7ff6cd..f7dc0663 100644
--- a/MapControl/Shared/ViewTransform.cs
+++ b/MapControl/Shared/ViewTransform.cs
@@ -2,6 +2,7 @@
// © 2020 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
+using System;
#if WINDOWS_UWP
using Windows.Foundation;
using Windows.UI.Xaml.Media;
@@ -13,22 +14,14 @@ using System.Windows.Media;
namespace MapControl
{
///
- /// Defines the transformation between cartesian map coordinates and viewport coordinates.
+ /// Defines the transformation between cartesian map coordinates in meters
+ /// and view coordinates in pixels.
///
public class ViewTransform
{
///
- /// Gets the transform matrix from cartesian map coordinates to viewport coordinates.
- ///
- public Matrix MapToViewMatrix { get; private set; }
-
- ///
- /// Gets the transform matrix from viewport coordinates to cartesian map coordinates.
- ///
- public Matrix ViewToMapMatrix { get; private set; }
-
- ///
- /// Gets the scaling factor from cartesian map coordinates to viewport coordinates.
+ /// Gets the scaling factor from cartesian map coordinates to view coordinates,
+ /// i.e. pixels per meter.
///
public double Scale { get; private set; }
@@ -38,7 +31,17 @@ namespace MapControl
public double Rotation { get; private set; }
///
- /// Transforms a Point from cartesian map coordinates to viewport coordinates.
+ /// Gets the transform matrix from cartesian map coordinates to view coordinates.
+ ///
+ public Matrix MapToViewMatrix { get; private set; }
+
+ ///
+ /// Gets the transform matrix from view coordinates to cartesian map coordinates.
+ ///
+ public Matrix ViewToMapMatrix { get; private set; }
+
+ ///
+ /// Transforms a Point from cartesian map coordinates to view coordinates.
///
public Point MapToView(Point point)
{
@@ -46,14 +49,14 @@ namespace MapControl
}
///
- /// Transforms a Point from viewport coordinates to cartesian map coordinates.
+ /// Transforms a Point from view coordinates to cartesian map coordinates.
///
public Point ViewToMap(Point point)
{
return ViewToMapMatrix.Transform(point);
}
- public void SetTransform(Point mapCenter, Point viewportCenter, double scale, double rotation)
+ public void SetTransform(Point mapCenter, Point viewCenter, double scale, double rotation)
{
Scale = scale;
Rotation = rotation;
@@ -61,7 +64,7 @@ namespace MapControl
var transform = new Matrix(Scale, 0d, 0d, -Scale, -Scale * mapCenter.X, Scale * mapCenter.Y);
transform.Rotate(Rotation);
- transform.Translate(viewportCenter.X, viewportCenter.Y);
+ transform.Translate(viewCenter.X, viewCenter.Y);
MapToViewMatrix = transform;
@@ -83,7 +86,7 @@ namespace MapControl
tileMatrixTopLeft.X + tileMatrixOrigin.X / tileMatrixScale,
tileMatrixTopLeft.Y - tileMatrixOrigin.Y / tileMatrixScale);
- // tile matrix origin in viewport coordinates
+ // tile matrix origin in view coordinates
//
var viewOrigin = MapToView(mapOrigin);
@@ -92,14 +95,14 @@ namespace MapControl
return transform;
}
- public Rect GetTileMatrixBounds(double tileMatrixScale, Point tileMatrixTopLeft, Size viewportSize)
+ public Rect GetTileMatrixBounds(double tileMatrixScale, Point tileMatrixTopLeft, Size viewSize)
{
var transformScale = tileMatrixScale / Scale;
var transform = new Matrix(transformScale, 0d, 0d, transformScale, 0d, 0d);
transform.Rotate(-Rotation);
- // viewport origin in map coordinates
+ // view origin in map coordinates
//
var origin = ViewToMap(new Point());
@@ -109,10 +112,20 @@ namespace MapControl
tileMatrixScale * (origin.X - tileMatrixTopLeft.X),
tileMatrixScale * (tileMatrixTopLeft.Y - origin.Y));
- // transform viewport bounds to tile pixel bounds
+ // transform view bounds to tile pixel bounds
//
return new MatrixTransform { Matrix = transform }
- .TransformBounds(new Rect(0d, 0d, viewportSize.Width, viewportSize.Height));
+ .TransformBounds(new Rect(0d, 0d, viewSize.Width, viewSize.Height));
+ }
+
+ public static double ZoomLevelToScale(double zoomLevel)
+ {
+ return 256d * Math.Pow(2d, zoomLevel) / (360d * MapProjection.Wgs84MetersPerDegree);
+ }
+
+ public static double ScaleToZoomLevel(double scale)
+ {
+ return Math.Log(scale * 360d * MapProjection.Wgs84MetersPerDegree / 256d, 2d);
}
}
}
diff --git a/MapControl/Shared/ViewportChangedEventArgs.cs b/MapControl/Shared/ViewportChangedEventArgs.cs
index e80a0572..46527a8a 100644
--- a/MapControl/Shared/ViewportChangedEventArgs.cs
+++ b/MapControl/Shared/ViewportChangedEventArgs.cs
@@ -16,7 +16,7 @@ namespace MapControl
///
/// Indicates if the map projection has changed, i.e. if a MapTileLayer or MapImageLayer should
- /// be updated immediately, or MapShape Data in cartesian map coordinates should be recalculated.
+ /// be updated immediately, or MapPath Data in cartesian map coordinates should be recalculated.
///
public bool ProjectionChanged { get; }
diff --git a/MapControl/Shared/WmtsTileMatrixLayer.cs b/MapControl/Shared/WmtsTileMatrixLayer.cs
index bf2c881b..86a6dc46 100644
--- a/MapControl/Shared/WmtsTileMatrixLayer.cs
+++ b/MapControl/Shared/WmtsTileMatrixLayer.cs
@@ -47,11 +47,11 @@ namespace MapControl
viewTransform.GetTileLayerTransform(TileMatrix.Scale, TileMatrix.TopLeft, tileMatrixOrigin);
}
- public bool SetBounds(ViewTransform viewTransform, Size viewportSize)
+ public bool SetBounds(ViewTransform viewTransform, Size viewSize)
{
- // bounds in tile pixels from viewport size
+ // bounds in tile pixels from view size
//
- var bounds = viewTransform.GetTileMatrixBounds(TileMatrix.Scale, TileMatrix.TopLeft, viewportSize);
+ var bounds = viewTransform.GetTileMatrixBounds(TileMatrix.Scale, TileMatrix.TopLeft, viewSize);
// tile column and row index bounds
//
diff --git a/MapControl/Shared/WorldMercatorProjection.cs b/MapControl/Shared/WorldMercatorProjection.cs
index 590cd835..4d3ddcdb 100644
--- a/MapControl/Shared/WorldMercatorProjection.cs
+++ b/MapControl/Shared/WorldMercatorProjection.cs
@@ -15,11 +15,11 @@ namespace MapControl
///
public class WorldMercatorProjection : MapProjection
{
- private static readonly double maxLatitude = YToLatitude(180d);
-
public static double ConvergenceTolerance = 1e-6;
public static int MaxIterations = 10;
+ private static readonly double maxLatitude = YToLatitude(180d);
+
public WorldMercatorProjection()
{
CrsId = "EPSG:3395";
diff --git a/MapControl/UWP/MapBase.UWP.cs b/MapControl/UWP/MapBase.UWP.cs
index b4b10375..02ed8374 100644
--- a/MapControl/UWP/MapBase.UWP.cs
+++ b/MapControl/UWP/MapBase.UWP.cs
@@ -39,6 +39,9 @@ namespace MapControl
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) => ((MapBase)o).CenterPointPropertyChanged((Windows.Foundation.Point)e.NewValue)));
@@ -62,6 +65,11 @@ namespace MapControl
};
}
+ private void SetViewScale(double scale)
+ {
+ SetValue(ViewScaleProperty, scale);
+ }
+
private void CenterPointPropertyChanged(Windows.Foundation.Point center)
{
CenterPointPropertyChanged(new Location(center.Y, center.X));
diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj
index 8760dd14..8858827e 100644
--- a/MapControl/UWP/MapControl.UWP.csproj
+++ b/MapControl/UWP/MapControl.UWP.csproj
@@ -107,6 +107,9 @@
MapPanel.cs
+
+ MapPath.cs
+
MapPolygon.cs
@@ -119,9 +122,6 @@
MapScale.cs
-
- MapShape.cs
-
MapTileLayer.cs
@@ -188,7 +188,7 @@
-
+
diff --git a/MapControl/UWP/MapGraticule.UWP.cs b/MapControl/UWP/MapGraticule.UWP.cs
index 0725ea7e..f5d61348 100644
--- a/MapControl/UWP/MapGraticule.UWP.cs
+++ b/MapControl/UWP/MapGraticule.UWP.cs
@@ -4,11 +4,9 @@
using System;
using Windows.Foundation;
-using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Shapes;
-using Windows.UI.Xaml.Data;
namespace MapControl
{
@@ -40,7 +38,7 @@ namespace MapControl
Children.Add(path);
}
- var bounds = map.ViewportRectToBoundingBox(new Rect(0d, 0d, map.RenderSize.Width, map.RenderSize.Height));
+ var bounds = map.ViewRectToBoundingBox(new Rect(0d, 0d, map.RenderSize.Width, map.RenderSize.Height));
var lineDistance = GetLineDistance();
var labelStart = new Location(
@@ -66,14 +64,14 @@ namespace MapControl
{
var figure = new PathFigure
{
- StartPoint = map.LocationToViewportPoint(new Location(lat, lineStart.Longitude)),
+ StartPoint = map.LocationToView(new Location(lat, lineStart.Longitude)),
IsClosed = false,
IsFilled = false
};
figure.Segments.Add(new LineSegment
{
- Point = map.LocationToViewportPoint(new Location(lat, lineEnd.Longitude))
+ Point = map.LocationToView(new Location(lat, lineEnd.Longitude))
});
geometry.Figures.Add(figure);
@@ -83,14 +81,14 @@ namespace MapControl
{
var figure = new PathFigure
{
- StartPoint = map.LocationToViewportPoint(new Location(lineStart.Latitude, lon)),
+ StartPoint = map.LocationToView(new Location(lineStart.Latitude, lon)),
IsClosed = false,
IsFilled = false
};
figure.Segments.Add(new LineSegment
{
- Point = map.LocationToViewportPoint(new Location(lineEnd.Latitude, lon))
+ Point = map.LocationToView(new Location(lineEnd.Latitude, lon))
});
geometry.Figures.Add(figure);
@@ -111,22 +109,18 @@ namespace MapControl
}
else
{
- var renderTransform = new TransformGroup();
- renderTransform.Children.Add(new TranslateTransform());
- renderTransform.Children.Add(map.RotateTransform);
- renderTransform.Children.Add(new TranslateTransform());
-
- label = new TextBlock { RenderTransform = renderTransform };
- if (FontFamily != null)
- {
- label.SetBinding(TextBlock.FontFamilyProperty, GetBinding(FontFamilyProperty, nameof(FontFamily)));
- }
+ label = new TextBlock { RenderTransform = new MatrixTransform() };
label.SetBinding(TextBlock.FontSizeProperty, GetBinding(FontSizeProperty, nameof(FontSize)));
label.SetBinding(TextBlock.FontStyleProperty, GetBinding(FontStyleProperty, nameof(FontStyle)));
label.SetBinding(TextBlock.FontStretchProperty, GetBinding(FontStretchProperty, nameof(FontStretch)));
label.SetBinding(TextBlock.FontWeightProperty, GetBinding(FontWeightProperty, nameof(FontWeight)));
label.SetBinding(TextBlock.ForegroundProperty, GetBinding(ForegroundProperty, nameof(Foreground)));
+ if (FontFamily != null)
+ {
+ label.SetBinding(TextBlock.FontFamilyProperty, GetBinding(FontFamilyProperty, nameof(FontFamily)));
+ }
+
Children.Add(label);
}
@@ -135,10 +129,6 @@ namespace MapControl
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));
-
- var translateTransform = (TranslateTransform)((TransformGroup)label.RenderTransform).Children[0];
- translateTransform.X = StrokeThickness / 2d + 2d;
- translateTransform.Y = -label.DesiredSize.Height / 2d;
}
while (Children.Count > childIndex)
@@ -153,10 +143,14 @@ namespace MapControl
{
var label = (TextBlock)Children[i];
var location = (Location)label.Tag;
- var viewportTransform = (TranslateTransform)((TransformGroup)label.RenderTransform).Children[2];
- var viewportPosition = map.LocationToViewportPoint(location);
- viewportTransform.X = viewportPosition.X;
- viewportTransform.Y = viewportPosition.Y;
+ 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)
diff --git a/MapControl/UWP/MapPanel.UWP.cs b/MapControl/UWP/MapPanel.UWP.cs
index be19e7f3..6a840151 100644
--- a/MapControl/UWP/MapPanel.UWP.cs
+++ b/MapControl/UWP/MapPanel.UWP.cs
@@ -20,8 +20,8 @@ namespace MapControl
public static readonly DependencyProperty ParentMapProperty = DependencyProperty.RegisterAttached(
"ParentMap", typeof(MapBase), typeof(MapPanel), new PropertyMetadata(null, ParentMapPropertyChanged));
- private static readonly DependencyProperty ViewportPositionProperty = DependencyProperty.RegisterAttached(
- "ViewportPosition", typeof(Point?), typeof(MapPanel), new PropertyMetadata(null));
+ private static readonly DependencyProperty ViewPositionProperty = DependencyProperty.RegisterAttached(
+ "ViewPosition", typeof(Point?), typeof(MapPanel), new PropertyMetadata(null));
public static void InitMapElement(FrameworkElement element)
{
@@ -61,9 +61,9 @@ namespace MapControl
?? FindParentMap(parent));
}
- private static void SetViewportPosition(FrameworkElement element, Point? viewportPosition)
+ private static void SetViewPosition(FrameworkElement element, Point? viewPosition)
{
- element.SetValue(ViewportPositionProperty, viewportPosition);
+ element.SetValue(ViewPositionProperty, viewPosition);
}
}
}
diff --git a/MapControl/UWP/MapShape.UWP.cs b/MapControl/UWP/MapPath.UWP.cs
similarity index 89%
rename from MapControl/UWP/MapShape.UWP.cs
rename to MapControl/UWP/MapPath.UWP.cs
index 9003ccbe..294da581 100644
--- a/MapControl/UWP/MapShape.UWP.cs
+++ b/MapControl/UWP/MapPath.UWP.cs
@@ -12,7 +12,7 @@ using Windows.UI.Xaml.Shapes;
namespace MapControl
{
- public abstract partial class MapShape : Path
+ public partial class MapPath : Path
{
protected void DataCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
@@ -40,13 +40,7 @@ namespace MapControl
{
if (locations != null && locations.Count() >= 2)
{
- var offset = GetLongitudeOffset();
- if (offset != 0d)
- {
- locations = locations.Select(loc => new Location(loc.Latitude, loc.Longitude + offset));
- }
-
- var points = locations.Select(loc => LocationToViewportPoint(loc)).ToList();
+ var points = locations.Select(loc => LocationToView(loc)).ToList();
if (closed)
{
points.Add(points[0]);
diff --git a/MapControl/UWP/Vector.UWP.cs b/MapControl/UWP/Vector.UWP.cs
index 988163a0..13dd882c 100644
--- a/MapControl/UWP/Vector.UWP.cs
+++ b/MapControl/UWP/Vector.UWP.cs
@@ -50,6 +50,16 @@ namespace MapControl
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;
diff --git a/MapControl/WPF/MapBase.WPF.cs b/MapControl/WPF/MapBase.WPF.cs
index 66754f4c..4eec0360 100644
--- a/MapControl/WPF/MapBase.WPF.cs
+++ b/MapControl/WPF/MapBase.WPF.cs
@@ -43,6 +43,11 @@ namespace MapControl
0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
(o, e) => ((MapBase)o).TargetHeadingPropertyChanged((double)e.NewValue)));
+ private static readonly DependencyPropertyKey ViewScalePropertyKey = DependencyProperty.RegisterReadOnly(
+ nameof(ViewScale), typeof(double), typeof(MapBase), new PropertyMetadata(0d));
+
+ public static readonly DependencyProperty ViewScaleProperty = ViewScalePropertyKey.DependencyProperty;
+
private static readonly DependencyProperty CenterPointProperty = DependencyProperty.Register(
"CenterPoint", typeof(Point), typeof(MapBase),
new PropertyMetadata(new Point(), (o, e) => ((MapBase)o).CenterPointPropertyChanged((Point)e.NewValue)));
@@ -61,6 +66,11 @@ namespace MapControl
UpdateTransform();
}
+ private void SetViewScale(double scale)
+ {
+ SetValue(ViewScalePropertyKey, scale);
+ }
+
private void CenterPointPropertyChanged(Point center)
{
CenterPointPropertyChanged(new Location(center.Y, center.X));
diff --git a/MapControl/WPF/MapGraticule.WPF.cs b/MapControl/WPF/MapGraticule.WPF.cs
index 5200671c..ad9ebfe0 100644
--- a/MapControl/WPF/MapGraticule.WPF.cs
+++ b/MapControl/WPF/MapGraticule.WPF.cs
@@ -56,7 +56,7 @@ namespace MapControl
private void DrawCylindricalGraticule(DrawingContext drawingContext, double lineDistance, string labelFormat)
{
- var boundingBox = ParentMap.ViewportRectToBoundingBox(new Rect(ParentMap.RenderSize));
+ var boundingBox = ParentMap.ViewRectToBoundingBox(new Rect(ParentMap.RenderSize));
var latLabelStart = Math.Ceiling(boundingBox.South / lineDistance) * lineDistance;
var lonLabelStart = Math.Ceiling(boundingBox.West / lineDistance) * lineDistance;
var latLabels = new List
- public class MapMultiPolygon : MapShape
+ public class MapMultiPolygon : MapPath
{
public static readonly DependencyProperty PolygonsProperty = DependencyProperty.Register(
nameof(Polygons), typeof(IEnumerable>), typeof(MapMultiPolygon),
@@ -31,6 +31,11 @@ namespace MapControl
set { SetValue(PolygonsProperty, value); }
}
+ public MapMultiPolygon()
+ {
+ Data = new PathGeometry();
+ }
+
protected override void UpdateData()
{
var figures = ((PathGeometry)Data).Figures;
diff --git a/MapControl/WPF/MapPanel.WPF.cs b/MapControl/WPF/MapPanel.WPF.cs
index 3ba9c49c..e91cedc1 100644
--- a/MapControl/WPF/MapPanel.WPF.cs
+++ b/MapControl/WPF/MapPanel.WPF.cs
@@ -20,11 +20,11 @@ namespace MapControl
"ParentMap", typeof(MapBase), typeof(MapPanel),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits, ParentMapPropertyChanged));
- private static readonly DependencyPropertyKey ViewportPositionPropertyKey = DependencyProperty.RegisterAttachedReadOnly(
- "ViewportPosition", typeof(Point?), typeof(MapPanel), new PropertyMetadata());
+ private static readonly DependencyPropertyKey ViewPositionPropertyKey = DependencyProperty.RegisterAttachedReadOnly(
+ "ViewPosition", typeof(Point?), typeof(MapPanel), new PropertyMetadata());
public static readonly DependencyProperty ParentMapProperty = ParentMapPropertyKey.DependencyProperty;
- public static readonly DependencyProperty ViewportPositionProperty = ViewportPositionPropertyKey.DependencyProperty;
+ public static readonly DependencyProperty ViewPositionProperty = ViewPositionPropertyKey.DependencyProperty;
public static MapBase GetParentMap(FrameworkElement element)
{
@@ -39,9 +39,9 @@ namespace MapControl
}
}
- private static void SetViewportPosition(FrameworkElement element, Point? viewportPosition)
+ private static void SetViewPosition(FrameworkElement element, Point? viewPosition)
{
- element.SetValue(ViewportPositionPropertyKey, viewportPosition);
+ element.SetValue(ViewPositionPropertyKey, viewPosition);
}
}
}
diff --git a/MapControl/WPF/MapShape.WPF.cs b/MapControl/WPF/MapPath.WPF.cs
similarity index 83%
rename from MapControl/WPF/MapShape.WPF.cs
rename to MapControl/WPF/MapPath.WPF.cs
index 0e13e898..3feeff47 100644
--- a/MapControl/WPF/MapShape.WPF.cs
+++ b/MapControl/WPF/MapPath.WPF.cs
@@ -12,9 +12,15 @@ using System.Windows.Shapes;
namespace MapControl
{
- public abstract partial class MapShape : Shape, IWeakEventListener
+ public partial class MapPath : Shape, IWeakEventListener
{
- public Geometry Data { get; }
+ public static readonly DependencyProperty DataProperty = Path.DataProperty.AddOwner(typeof(MapPath));
+
+ public Geometry Data
+ {
+ get { return (Geometry)GetValue(DataProperty); }
+ set { SetValue(DataProperty, value); }
+ }
protected override Geometry DefiningGeometry
{
@@ -48,13 +54,7 @@ namespace MapControl
{
if (locations != null && locations.Count() >= 2)
{
- var offset = GetLongitudeOffset();
- if (offset != 0d)
- {
- locations = locations.Select(loc => new Location(loc.Latitude, loc.Longitude + offset));
- }
-
- var points = locations.Select(loc => LocationToViewportPoint(loc));
+ var points = locations.Select(loc => LocationToView(loc));
var figure = new PathFigure
{
StartPoint = points.First(),
diff --git a/MapControlExtended.sln b/MapControlExtended.sln
index a0447fea..628515a8 100644
--- a/MapControlExtended.sln
+++ b/MapControlExtended.sln
@@ -29,7 +29,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MapProjections", "MapProjec
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapProjections.WPF", "MapProjections\WPF\MapProjections.WPF.csproj", "{426C21C0-5F14-491F-BCD1-6D2993510420}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfApplication", "SampleApps\WpfApplication\WpfApplication.csproj", "{F92DA93D-75DB-4308-A5F9-6B4C3908A675}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfApplication", "SampleApps\WpfApplication\WpfApplication.csproj", "{F92DA93D-75DB-4308-A5F9-6B4C3908A675}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MapProjections.UWP", "MapProjections\UWP\MapProjections.UWP.csproj", "{9EE69591-5EDC-45E3-893E-2F9A4B82D538}"
EndProject
@@ -45,8 +45,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteCache.UWP", "SQLiteCa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SQLiteCache.WPF", "SQLiteCache\WPF\SQLiteCache.WPF.csproj", "{0109C2F0-BA2C-420F-B2CA-DB5B29B1A349}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfCoreApp", "SampleApps\WpfCoreApp\WpfCoreApp.csproj", "{43380AAB-EE6E-40BF-90EB-FFD86F885CAF}"
-EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -347,26 +345,6 @@ Global
{0109C2F0-BA2C-420F-B2CA-DB5B29B1A349}.Release|x64.Build.0 = Release|Any CPU
{0109C2F0-BA2C-420F-B2CA-DB5B29B1A349}.Release|x86.ActiveCfg = Release|Any CPU
{0109C2F0-BA2C-420F-B2CA-DB5B29B1A349}.Release|x86.Build.0 = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|ARM.ActiveCfg = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|ARM.Build.0 = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|ARM64.Build.0 = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|x64.ActiveCfg = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|x64.Build.0 = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|x86.ActiveCfg = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Debug|x86.Build.0 = Debug|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|Any CPU.Build.0 = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|ARM.ActiveCfg = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|ARM.Build.0 = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|ARM64.ActiveCfg = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|ARM64.Build.0 = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|x64.ActiveCfg = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|x64.Build.0 = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|x86.ActiveCfg = Release|Any CPU
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -386,7 +364,6 @@ Global
{BE08B7BC-8C89-4837-BCE7-EDDDABEAB372} = {2FDC8B91-FB95-4C57-8183-63587FBFE180}
{56DFA7CF-F31D-45CE-9C36-DA8DBB8413B1} = {96FD1258-1597-48A2-8D64-1ADAE13E886A}
{0109C2F0-BA2C-420F-B2CA-DB5B29B1A349} = {96FD1258-1597-48A2-8D64-1ADAE13E886A}
- {43380AAB-EE6E-40BF-90EB-FFD86F885CAF} = {8F2103C2-78AF-4810-8FB9-67572F50C8FC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {458346DD-B23F-4FDC-8F9D-A10F1882A4DB}
diff --git a/SampleApps/ProjectionDemo/MainWindow.xaml.cs b/SampleApps/ProjectionDemo/MainWindow.xaml.cs
index 0c7e63ff..917c1d5a 100644
--- a/SampleApps/ProjectionDemo/MainWindow.xaml.cs
+++ b/SampleApps/ProjectionDemo/MainWindow.xaml.cs
@@ -66,7 +66,7 @@ namespace ProjectionDemo
var map = (MapBase)sender;
var pos = e.GetPosition(map);
- viewModel.PushpinLocation = map.ViewportPointToLocation(pos);
+ viewModel.PushpinLocation = map.ViewToLocation(pos);
}
}
diff --git a/SampleApps/UniversalApp/MainPage.xaml b/SampleApps/UniversalApp/MainPage.xaml
index 3c72eb44..d8b1f027 100644
--- a/SampleApps/UniversalApp/MainPage.xaml
+++ b/SampleApps/UniversalApp/MainPage.xaml
@@ -130,6 +130,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/SampleApps/WpfApplication/MainWindow.xaml b/SampleApps/WpfApplication/MainWindow.xaml
index f68b5e4e..67910c83 100644
--- a/SampleApps/WpfApplication/MainWindow.xaml
+++ b/SampleApps/WpfApplication/MainWindow.xaml
@@ -1,12 +1,11 @@
-
+
@@ -88,7 +87,7 @@
-
+
@@ -159,17 +158,17 @@
-
-
-
-
-
+
+
+
+
+
-
+
diff --git a/SampleApps/WpfApplication/MainWindow.xaml.cs b/SampleApps/WpfApplication/MainWindow.xaml.cs
index 6dc464d0..f73ca188 100644
--- a/SampleApps/WpfApplication/MainWindow.xaml.cs
+++ b/SampleApps/WpfApplication/MainWindow.xaml.cs
@@ -12,7 +12,7 @@ namespace WpfApplication
public MainWindow()
{
ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Test Application");
- //TileImageLoader.Cache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder);
+ TileImageLoader.Cache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder);
//TileImageLoader.Cache = new MapControl.Caching.FileDbCache(TileImageLoader.DefaultCacheFolder);
//TileImageLoader.Cache = new MapControl.Caching.SQLiteCache(TileImageLoader.DefaultCacheFolder);
//TileImageLoader.Cache = null;
@@ -26,7 +26,7 @@ namespace WpfApplication
{
//map.ZoomMap(e.GetPosition(map), Math.Floor(map.ZoomLevel + 1.5));
//map.ZoomToBounds(new BoundingBox(53, 7, 54, 9));
- map.TargetCenter = map.ViewportPointToLocation(e.GetPosition(map));
+ map.TargetCenter = map.ViewToLocation(e.GetPosition(map));
}
}
@@ -40,7 +40,7 @@ namespace WpfApplication
private void MapMouseMove(object sender, MouseEventArgs e)
{
- var location = map.ViewportPointToLocation(e.GetPosition(map));
+ var location = map.ViewToLocation(e.GetPosition(map));
var latitude = (int)Math.Round(location.Latitude * 60000d);
var longitude = (int)Math.Round(Location.NormalizeLongitude(location.Longitude) * 60000d);
var latHemisphere = 'N';
diff --git a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs b/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
deleted file mode 100644
index 82c6a4bf..00000000
--- a/SampleApps/WpfApplication/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("WPF Sample Application")]
-[assembly: AssemblyDescription("XAML Map Control WPF Sample Application")]
-[assembly: AssemblyProduct("XAML Map Control")]
-[assembly: AssemblyCompany("Clemens Fischer")]
-[assembly: AssemblyCopyright("Copyright © 2020 Clemens Fischer")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyVersion("5.0.0")]
-[assembly: AssemblyFileVersion("5.0.0")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCulture("")]
-[assembly: ComVisible(false)]
diff --git a/SampleApps/WpfApplication/WpfApplication.csproj b/SampleApps/WpfApplication/WpfApplication.csproj
index 70fba3cd..46dd1894 100644
--- a/SampleApps/WpfApplication/WpfApplication.csproj
+++ b/SampleApps/WpfApplication/WpfApplication.csproj
@@ -1,110 +1,41 @@
-
-
-
-
- Debug
- AnyCPU
- {F92DA93D-75DB-4308-A5F9-6B4C3908A675}
- WinExe
- Properties
- WpfApplication
- WpfApplication
- v4.6.2
- 512
- {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- 4
- true
-
-
-
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
-
-
- prompt
- 4
-
-
-
-
-
-
- 4.0
-
-
-
-
-
-
-
- MSBuild:Compile
- Designer
-
-
- MSBuild:Compile
- Designer
-
-
- MapLayers.cs
-
-
- MapViewModel.cs
-
-
- App.xaml
- Code
-
-
-
- MainWindow.xaml
- Code
-
-
-
-
-
- Code
-
-
-
-
-
-
-
-
- 10_535_330.jpg
-
-
-
-
- {62f1726b-3144-49f4-8bcc-94160a3b2186}
- MapControl.WPF
-
-
- {0109c2f0-ba2c-420f-b2ca-db5b29b1a349}
- SQLiteCache.WPF
-
-
-
-
+
+
+
+ WinExe
+ netcoreapp3.1;net48
+ true
+ WpfApplication
+ XAML Map Control
+ 5.0.0
+ XAML Map Control WPF Sample Application
+ Clemens Fischer
+ Copyright © 2020 Clemens Fischer
+
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SampleApps/WpfCoreApp/WpfCoreApp.csproj.user b/SampleApps/WpfApplication/WpfApplication.csproj.user
similarity index 79%
rename from SampleApps/WpfCoreApp/WpfCoreApp.csproj.user
rename to SampleApps/WpfApplication/WpfApplication.csproj.user
index 644b0a6f..a10cc1cc 100644
--- a/SampleApps/WpfCoreApp/WpfCoreApp.csproj.user
+++ b/SampleApps/WpfApplication/WpfApplication.csproj.user
@@ -1,6 +1,8 @@

-
+
+ netcoreapp3.1
+
Designer
diff --git a/SampleApps/WpfCoreApp/App.xaml b/SampleApps/WpfCoreApp/App.xaml
deleted file mode 100644
index dcc41a2c..00000000
--- a/SampleApps/WpfCoreApp/App.xaml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
diff --git a/SampleApps/WpfCoreApp/App.xaml.cs b/SampleApps/WpfCoreApp/App.xaml.cs
deleted file mode 100644
index 6105bf88..00000000
--- a/SampleApps/WpfCoreApp/App.xaml.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-using System.Windows;
-
-namespace WpfApplication
-{
- public partial class App : Application
- {
- }
-}
diff --git a/SampleApps/WpfCoreApp/LocationToVisibilityConverter.cs b/SampleApps/WpfCoreApp/LocationToVisibilityConverter.cs
deleted file mode 100644
index 0ba383c8..00000000
--- a/SampleApps/WpfCoreApp/LocationToVisibilityConverter.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows;
-using System.Windows.Data;
-using MapControl;
-
-namespace WpfCoreApp
-{
- public class LocationToVisibilityConverter : IMultiValueConverter
- {
- public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
- {
- var visibility = Visibility.Hidden;
-
- if (values.Length == 2 && values[0] is MapBase && values[1] is Point?)
- {
- var parentMap = (MapBase)values[0];
- var position = (Point?)values[1];
-
- if (position.HasValue &&
- position.Value.X >= 0d && position.Value.X <= parentMap.ActualWidth &&
- position.Value.Y >= 0d && position.Value.Y <= parentMap.ActualHeight)
- {
- visibility = Visibility.Visible;
- }
- }
-
- return visibility;
- }
-
- public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
- {
- throw new NotSupportedException();
- }
- }
-}
diff --git a/SampleApps/WpfCoreApp/MainWindow.xaml b/SampleApps/WpfCoreApp/MainWindow.xaml
deleted file mode 100644
index fab923dd..00000000
--- a/SampleApps/WpfCoreApp/MainWindow.xaml
+++ /dev/null
@@ -1,221 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/SampleApps/WpfCoreApp/MainWindow.xaml.cs b/SampleApps/WpfCoreApp/MainWindow.xaml.cs
deleted file mode 100644
index 4007acad..00000000
--- a/SampleApps/WpfCoreApp/MainWindow.xaml.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using System;
-using System.Globalization;
-using System.Windows;
-using System.Windows.Input;
-using MapControl;
-using ViewModel;
-
-namespace WpfCoreApp
-{
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- ImageLoader.HttpClient.DefaultRequestHeaders.Add("User-Agent", "XAML Map Control Test Application");
- //TileImageLoader.Cache = new MapControl.Caching.ImageFileCache(TileImageLoader.DefaultCacheFolder);
-
- InitializeComponent();
- }
-
- private void MapMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (e.ClickCount == 2)
- {
- //map.ZoomMap(e.GetPosition(map), Math.Floor(map.ZoomLevel + 1.5));
- //map.ZoomToBounds(new BoundingBox(53, 7, 54, 9));
- map.TargetCenter = map.ViewportPointToLocation(e.GetPosition(map));
- }
- }
-
- private void MapMouseRightButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (e.ClickCount == 2)
- {
- //map.ZoomMap(e.GetPosition(map), Math.Ceiling(map.ZoomLevel - 1.5));
- }
- }
-
- private void MapMouseMove(object sender, MouseEventArgs e)
- {
- var location = map.ViewportPointToLocation(e.GetPosition(map));
- var latitude = (int)Math.Round(location.Latitude * 60000d);
- var longitude = (int)Math.Round(Location.NormalizeLongitude(location.Longitude) * 60000d);
- var latHemisphere = 'N';
- var lonHemisphere = 'E';
-
- if (latitude < 0)
- {
- latitude = -latitude;
- latHemisphere = 'S';
- }
-
- if (longitude < 0)
- {
- longitude = -longitude;
- lonHemisphere = 'W';
- }
-
- mouseLocation.Text = string.Format(CultureInfo.InvariantCulture,
- "{0} {1:00} {2:00.000}\n{3} {4:000} {5:00.000}",
- latHemisphere, latitude / 60000, (latitude % 60000) / 1000d,
- lonHemisphere, longitude / 60000, (longitude % 60000) / 1000d);
- }
-
- private void MapMouseLeave(object sender, MouseEventArgs e)
- {
- mouseLocation.Text = string.Empty;
- }
-
- private void MapManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e)
- {
- e.TranslationBehavior.DesiredDeceleration = 0.001;
- }
-
- private void MapItemTouchDown(object sender, TouchEventArgs e)
- {
- var mapItem = (MapItem)sender;
- mapItem.IsSelected = !mapItem.IsSelected;
- e.Handled = true;
- }
-
- private void SeamarksChecked(object sender, RoutedEventArgs e)
- {
- map.Children.Insert(map.Children.IndexOf(mapGraticule), ((MapViewModel)DataContext).MapLayers.SeamarksLayer);
- }
-
- private void SeamarksUnchecked(object sender, RoutedEventArgs e)
- {
- map.Children.Remove(((MapViewModel)DataContext).MapLayers.SeamarksLayer);
- }
- }
-}
diff --git a/SampleApps/WpfCoreApp/OutlinedText.cs b/SampleApps/WpfCoreApp/OutlinedText.cs
deleted file mode 100644
index f36477c3..00000000
--- a/SampleApps/WpfCoreApp/OutlinedText.cs
+++ /dev/null
@@ -1,145 +0,0 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Media;
-
-namespace WpfCoreApp
-{
- public class OutlinedText : FrameworkElement
- {
- private GlyphRun glyphRun;
- private Geometry outline;
-
- public static readonly DependencyProperty TextProperty = TextBlock.TextProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty FontSizeProperty = TextBlock.FontSizeProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty FontFamilyProperty = TextBlock.FontFamilyProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty FontStyleProperty = TextBlock.FontStyleProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty FontWeightProperty = TextBlock.FontWeightProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty FontStretchProperty = TextBlock.FontStretchProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty ForegroundProperty = TextBlock.ForegroundProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata((o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty BackgroundProperty = TextBlock.BackgroundProperty.AddOwner(
- typeof(OutlinedText), new FrameworkPropertyMetadata(Brushes.White, (o, e) => ((OutlinedText)o).glyphRun = null) { AffectsMeasure = true });
-
- public static readonly DependencyProperty OutlineThicknessProperty = DependencyProperty.Register(
- "OutlineThickness", typeof(double), typeof(OutlinedText),
- new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => ((OutlinedText)o).glyphRun = null));
-
- public string Text
- {
- get { return (string)GetValue(TextProperty); }
- set { SetValue(TextProperty, value); }
- }
-
- public double FontSize
- {
- get { return (double)GetValue(FontSizeProperty); }
- set { SetValue(FontSizeProperty, value); }
- }
-
- public FontFamily FontFamily
- {
- get { return (FontFamily)GetValue(FontFamilyProperty); }
- set { SetValue(FontFamilyProperty, value); }
- }
-
- public FontStyle FontStyle
- {
- get { return (FontStyle)GetValue(FontStyleProperty); }
- set { SetValue(FontStyleProperty, value); }
- }
-
- public FontWeight FontWeight
- {
- get { return (FontWeight)GetValue(FontWeightProperty); }
- set { SetValue(FontWeightProperty, value); }
- }
-
- public FontStretch FontStretch
- {
- get { return (FontStretch)GetValue(FontStretchProperty); }
- set { SetValue(FontStretchProperty, value); }
- }
-
- public Brush Foreground
- {
- get { return (Brush)GetValue(ForegroundProperty); }
- set { SetValue(ForegroundProperty, value); }
- }
-
- public Brush Background
- {
- get { return (Brush)GetValue(BackgroundProperty); }
- set { SetValue(BackgroundProperty, value); }
- }
-
- public double OutlineThickness
- {
- get { return (double)GetValue(OutlineThicknessProperty); }
- set { SetValue(OutlineThicknessProperty, value); }
- }
-
- protected override Size MeasureOverride(Size availableSize)
- {
- return CheckGlyphRun() ? outline.Bounds.Size : new Size();
- }
-
- protected override void OnRender(DrawingContext drawingContext)
- {
- if (CheckGlyphRun())
- {
- var location = outline.Bounds.Location;
- drawingContext.PushTransform(new TranslateTransform(-location.X, -location.Y));
- drawingContext.DrawGeometry(Background, null, outline);
- drawingContext.DrawGlyphRun(Foreground, glyphRun);
- }
- }
-
- private bool CheckGlyphRun()
- {
- if (glyphRun == null)
- {
- if (string.IsNullOrEmpty(Text))
- {
- return false;
- }
-
- var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
- GlyphTypeface glyphTypeface;
-
- if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
- {
- return false;
- }
-
- var glyphIndices = new ushort[Text.Length];
- var advanceWidths = new double[Text.Length];
-
- for (int i = 0; i < Text.Length; i++)
- {
- var glyphIndex = glyphTypeface.CharacterToGlyphMap[Text[i]];
- glyphIndices[i] = glyphIndex;
- advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * FontSize;
- }
-
- glyphRun = new GlyphRun(glyphTypeface, 0, false, FontSize, 1f, glyphIndices, new Point(), advanceWidths, null, null, null, null, null, null);
-
- outline = glyphRun.BuildGeometry().GetWidenedPathGeometry(new Pen(null, OutlineThickness * 2d));
- }
-
- return true;
- }
- }
-}
diff --git a/SampleApps/WpfCoreApp/WpfCoreApp.csproj b/SampleApps/WpfCoreApp/WpfCoreApp.csproj
deleted file mode 100644
index fc396bd4..00000000
--- a/SampleApps/WpfCoreApp/WpfCoreApp.csproj
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
- WinExe
- netcoreapp3.1
- true
- WpfCoreApp
- XAML Map Control
- 5.0.0
- XAML Map Control WPF Sample Application
- Clemens Fischer
- Copyright © 2020 Clemens Fischer
-
-
-
- DEBUG
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file