diff --git a/MapControl/Avalonia/MapBase.Avalonia.cs b/MapControl/Avalonia/MapBase.Avalonia.cs index 968d0f41..d677d83a 100644 --- a/MapControl/Avalonia/MapBase.Avalonia.cs +++ b/MapControl/Avalonia/MapBase.Avalonia.cs @@ -21,13 +21,13 @@ namespace MapControl DependencyPropertyHelper.Register(nameof(AnimationEasing), new QuadraticEaseOut()); public static readonly StyledProperty CenterProperty = - DependencyPropertyHelper.Register(nameof(Center), new Location(), + DependencyPropertyHelper.Register(nameof(Center), new Location(0d, 0d), (map, oldValue, newValue) => map.CenterPropertyChanged(newValue), (map, value) => map.CoerceCenterProperty(value), true); public static readonly StyledProperty TargetCenterProperty = - DependencyPropertyHelper.Register(nameof(TargetCenter), new Location(), + DependencyPropertyHelper.Register(nameof(TargetCenter), new Location(0d, 0d), async (map, oldValue, newValue) => await map.TargetCenterPropertyChanged(newValue), (map, value) => map.CoerceCenterProperty(value), true); diff --git a/MapControl/Avalonia/MapContentControl.Avalonia.cs b/MapControl/Avalonia/MapContentControl.Avalonia.cs deleted file mode 100644 index 793e9b1c..00000000 --- a/MapControl/Avalonia/MapContentControl.Avalonia.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Avalonia; -using Avalonia.Controls; - -namespace MapControl -{ - /// - /// ContentControl placed on a MapPanel at a geographic location specified by the Location property. - /// - public class MapContentControl : ContentControl - { - public static readonly StyledProperty AutoCollapseProperty = - MapPanel.AutoCollapseProperty.AddOwner(); - - public static readonly StyledProperty LocationProperty = - MapPanel.LocationProperty.AddOwner(); - - /// - /// Gets/sets MapPanel.AutoCollapse. - /// - public bool AutoCollapse - { - get => GetValue(AutoCollapseProperty); - set => SetValue(AutoCollapseProperty, value); - } - - /// - /// Gets/sets MapPanel.Location. - /// - public Location Location - { - get => GetValue(LocationProperty); - set => SetValue(LocationProperty, value); - } - } - - /// - /// MapContentControl with a Pushpin Style. - /// - public class Pushpin : MapContentControl - { - } -} diff --git a/MapControl/Avalonia/MapItem.Avalonia.cs b/MapControl/Avalonia/MapItem.Avalonia.cs index d78a8275..f30774cc 100644 --- a/MapControl/Avalonia/MapItem.Avalonia.cs +++ b/MapControl/Avalonia/MapItem.Avalonia.cs @@ -1,22 +1,10 @@ -using Avalonia; -using Avalonia.Controls; +using Avalonia.Controls; using Avalonia.Input; namespace MapControl { public partial class MapItem { - public static readonly StyledProperty AutoCollapseProperty = - MapPanel.AutoCollapseProperty.AddOwner(); - - public static readonly StyledProperty LocationProperty = - MapPanel.LocationProperty.AddOwner(); - - static MapItem() - { - LocationProperty.Changed.AddClassHandler((item, e) => item.UpdateMapTransform()); - } - protected override void OnPointerPressed(PointerPressedEventArgs e) { if (e.Pointer.Type != PointerType.Mouse && diff --git a/MapControl/Avalonia/MapPanel.Avalonia.cs b/MapControl/Avalonia/MapPanel.Avalonia.cs index a4778b13..2ab72cfe 100644 --- a/MapControl/Avalonia/MapPanel.Avalonia.cs +++ b/MapControl/Avalonia/MapPanel.Avalonia.cs @@ -7,8 +7,8 @@ namespace MapControl public static readonly AttachedProperty AutoCollapseProperty = DependencyPropertyHelper.RegisterAttached("AutoCollapse", typeof(MapPanel)); - public static readonly AttachedProperty LocationProperty = - DependencyPropertyHelper.RegisterAttached("Location", typeof(MapPanel)); + public static readonly AttachedProperty LocationProperty = + DependencyPropertyHelper.RegisterAttached("Location", typeof(MapPanel)); public static readonly AttachedProperty BoundingBoxProperty = DependencyPropertyHelper.RegisterAttached("BoundingBox", typeof(MapPanel)); diff --git a/MapControl/Avalonia/MapPolypoint.Avalonia.cs b/MapControl/Avalonia/MapPolypoint.Avalonia.cs index 6f25d7ec..9dc6849a 100644 --- a/MapControl/Avalonia/MapPolypoint.Avalonia.cs +++ b/MapControl/Avalonia/MapPolypoint.Avalonia.cs @@ -14,7 +14,7 @@ namespace MapControl if (ParentMap != null && locations != null) { - var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault()); + var longitudeOffset = GetLongitudeOffset(locations); AddPolylinePoints(figures, locations, longitudeOffset, closed); } @@ -28,7 +28,7 @@ namespace MapControl if (ParentMap != null && polygons != null) { - var longitudeOffset = GetLongitudeOffset(Location); + var longitudeOffset = GetLongitudeOffset(polygons.FirstOrDefault()); foreach (var locations in polygons) { diff --git a/MapControl/Shared/Location.cs b/MapControl/Shared/Location.cs index 1c7a3108..e73b80f5 100644 --- a/MapControl/Shared/Location.cs +++ b/MapControl/Shared/Location.cs @@ -5,35 +5,20 @@ namespace MapControl { /// /// A geographic location with latitude and longitude values in degrees. - /// For calculations with azimuth and distance on great circles, see - /// https://en.wikipedia.org/wiki/Great_circle, - /// https://en.wikipedia.org/wiki/Great-circle_distance, - /// https://en.wikipedia.org/wiki/Great-circle_navigation. /// #if UWP || WINUI [Windows.Foundation.Metadata.CreateFromString(MethodName = "Parse")] #else [System.ComponentModel.TypeConverter(typeof(LocationConverter))] #endif - public class Location : IEquatable + public readonly struct Location(double latitude, double longitude) : IEquatable { - // Arithmetic mean radius (2*a + b) / 3 == (1 - f/3) * a. - // See https://en.wikipedia.org/wiki/Earth_radius#Arithmetic_mean_radius. - // - public const double Wgs84MeanRadius = (1d - MapProjection.Wgs84Flattening / 3d) * MapProjection.Wgs84EquatorialRadius; + public double Latitude { get; } = Math.Min(Math.Max(latitude, -90d), 90d); + public double Longitude => longitude; - public Location() - { - } + public static bool operator ==(Location loc1, Location loc2) => loc1.Equals(loc2); - public Location(double latitude, double longitude) - { - Latitude = Math.Min(Math.Max(latitude, -90d), 90d); - Longitude = longitude; - } - - public double Latitude { get; } - public double Longitude { get; } + public static bool operator !=(Location loc1, Location loc2) => !loc1.Equals(loc2); public bool LatitudeEquals(double latitude) => Math.Abs(Latitude - latitude) < 1e-9; @@ -41,9 +26,9 @@ namespace MapControl public bool Equals(double latitude, double longitude) => LatitudeEquals(latitude) && LongitudeEquals(longitude); - public bool Equals(Location location) => location != null && Equals(location.Latitude, location.Longitude); + public bool Equals(Location location) => Equals(location.Latitude, location.Longitude); - public override bool Equals(object obj) => Equals(obj as Location); + public override bool Equals(object obj) => obj is Location location && Equals(location); public override int GetHashCode() => Latitude.GetHashCode() ^ Longitude.GetHashCode(); @@ -81,8 +66,14 @@ namespace MapControl return x < 0d ? x + 180d : x - 180d; } + // Arithmetic mean radius (2*a + b) / 3 == (1 - f/3) * a. + // See https://en.wikipedia.org/wiki/Earth_radius#Arithmetic_mean_radius. + // + public const double Wgs84MeanRadius = (1d - MapProjection.Wgs84Flattening / 3d) * MapProjection.Wgs84EquatorialRadius; + /// /// Calculates great circle azimuth in degrees and distance in meters between this and the specified Location. + /// See https://en.wikipedia.org/wiki/Great-circle_navigation#Course. /// public (double, double) GetAzimuthDistance(Location location, double earthRadius = Wgs84MeanRadius) { @@ -108,6 +99,7 @@ namespace MapControl /// /// Calculates great distance in meters between this and the specified Location. + /// See https://en.wikipedia.org/wiki/Great-circle_navigation#Course. /// public double GetDistance(Location location, double earthRadius = Wgs84MeanRadius) { @@ -118,6 +110,7 @@ namespace MapControl /// /// Calculates the Location on a great circle at the specified azimuth in degrees and distance in meters from this Location. + /// See https://en.wikipedia.org/wiki/Great-circle_navigation#Finding_way-points. /// public Location GetLocation(double azimuth, double distance, double earthRadius = Wgs84MeanRadius) { diff --git a/MapControl/Shared/MapBase.cs b/MapControl/Shared/MapBase.cs index 763e3f6d..82ba1fa1 100644 --- a/MapControl/Shared/MapBase.cs +++ b/MapControl/Shared/MapBase.cs @@ -43,7 +43,7 @@ namespace MapControl DependencyPropertyHelper.Register(nameof(MapProjection), new WebMercatorProjection(), (map, oldValue, newValue) => map.MapProjectionPropertyChanged(newValue)); - private Location transformCenter; + private Location? transformCenter; private Point viewCenter; private double centerLongitude; private double maxLatitude = 85.05112878; // default WebMercatorProjection @@ -326,12 +326,7 @@ namespace MapControl private Location CoerceCenterProperty(Location center) { - if (center == null) - { - center = new Location(); - } - else if ( - center.Latitude < -maxLatitude || center.Latitude > maxLatitude || + if (center.Latitude < -maxLatitude || center.Latitude > maxLatitude || center.Longitude < -180d || center.Longitude > 180d) { center = new Location( @@ -391,7 +386,7 @@ namespace MapControl ViewTransform.SetTransform(mapCenter, viewCenter, viewScale, -Heading); - if (transformCenter != null) + if (transformCenter.HasValue) { var center = ViewToLocation(new Point(ActualWidth / 2d, ActualHeight / 2d)); var latitude = center.Latitude; @@ -419,7 +414,7 @@ namespace MapControl { // Check if transform center has moved across 180° longitude. // - transformCenterChanged = Math.Abs(center.Longitude - transformCenter.Longitude) > 180d; + transformCenterChanged = Math.Abs(center.Longitude - transformCenter.Value.Longitude) > 180d; ResetTransformCenter(); mapCenter = MapProjection.LocationToMap(center); ViewTransform.SetTransform(mapCenter, viewCenter, viewScale, -Heading); diff --git a/MapControl/Shared/MapContentControl.cs b/MapControl/Shared/MapContentControl.cs new file mode 100644 index 00000000..5b524853 --- /dev/null +++ b/MapControl/Shared/MapContentControl.cs @@ -0,0 +1,54 @@ +#if WPF +using System.Windows; +using System.Windows.Controls; +#elif UWP +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +#elif WINUI +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +#elif AVALONIA +using Avalonia.Controls; +#endif + +namespace MapControl +{ + /// + /// ContentControl placed on a MapPanel at a geographic location specified by the Location property. + /// + public partial class MapContentControl : ContentControl + { + public static readonly DependencyProperty LocationProperty = + DependencyPropertyHelper.Register(nameof(Location), default, + (control, oldValue, newValue) => MapPanel.SetLocation(control, newValue)); + + public static readonly DependencyProperty AutoCollapseProperty = + DependencyPropertyHelper.Register(nameof(AutoCollapse), false, + (control, oldValue, newValue) => MapPanel.SetAutoCollapse(control, newValue)); + + /// + /// Gets/sets MapPanel.Location. + /// + public Location Location + { + get => (Location)GetValue(LocationProperty); + set => SetValue(LocationProperty, value); + } + + /// + /// Gets/sets MapPanel.AutoCollapse. + /// + public bool AutoCollapse + { + get => (bool)GetValue(AutoCollapseProperty); + set => SetValue(AutoCollapseProperty, value); + } + } + + /// + /// MapContentControl with a Pushpin Style. + /// + public partial class Pushpin : MapContentControl + { + } +} diff --git a/MapControl/Shared/MapItem.cs b/MapControl/Shared/MapItem.cs index 16de22f5..eeba061a 100644 --- a/MapControl/Shared/MapItem.cs +++ b/MapControl/Shared/MapItem.cs @@ -1,10 +1,13 @@ #if WPF +using System.Windows; using System.Windows.Controls; using System.Windows.Media; #elif UWP +using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; #elif WINUI +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media; #elif AVALONIA @@ -19,14 +22,17 @@ namespace MapControl /// public partial class MapItem : ListBoxItem, IMapElement { - /// - /// Gets/sets MapPanel.AutoCollapse. - /// - public bool AutoCollapse - { - get => (bool)GetValue(AutoCollapseProperty); - set => SetValue(AutoCollapseProperty, value); - } + public static readonly DependencyProperty LocationProperty = + DependencyPropertyHelper.Register(nameof(Location), default, + (item, oldValue, newValue) => + { + MapPanel.SetLocation(item, newValue); + item.UpdateMapTransform(); + }); + + public static readonly DependencyProperty AutoCollapseProperty = + DependencyPropertyHelper.Register(nameof(AutoCollapse), false, + (item, oldValue, newValue) => MapPanel.SetAutoCollapse(item, newValue)); /// /// Gets/sets MapPanel.Location. @@ -37,6 +43,15 @@ namespace MapControl set => SetValue(LocationProperty, value); } + /// + /// Gets/sets MapPanel.AutoCollapse. + /// + public bool AutoCollapse + { + get => (bool)GetValue(AutoCollapseProperty); + set => SetValue(AutoCollapseProperty, value); + } + /// /// Implements IMapElement.ParentMap. /// @@ -94,7 +109,7 @@ namespace MapControl private void UpdateMapTransform() { - if (MapTransform != null && ParentMap != null && Location != null) + if (MapTransform != null && ParentMap != null) { MapTransform.Matrix = ParentMap.GetMapToViewTransform(Location); } diff --git a/MapControl/Shared/MapItemsControl.cs b/MapControl/Shared/MapItemsControl.cs index d7e73ab5..edf47c8f 100644 --- a/MapControl/Shared/MapItemsControl.cs +++ b/MapControl/Shared/MapItemsControl.cs @@ -68,7 +68,7 @@ namespace MapControl { var location = MapPanel.GetLocation(ContainerFromItem(item)); - return location != null && predicate(location); + return location.HasValue && predicate(location.Value); }); } diff --git a/MapControl/Shared/MapPanel.cs b/MapControl/Shared/MapPanel.cs index fcdf93ce..b12b750e 100644 --- a/MapControl/Shared/MapPanel.cs +++ b/MapControl/Shared/MapPanel.cs @@ -99,15 +99,15 @@ namespace MapControl /// /// Gets the Location of an element. /// - public static Location GetLocation(FrameworkElement element) + public static Location? GetLocation(FrameworkElement element) { - return (Location)element.GetValue(LocationProperty); + return (Location?)element.GetValue(LocationProperty); } /// /// Sets the Location of an element. /// - public static void SetLocation(FrameworkElement element, Location value) + public static void SetLocation(FrameworkElement element, Location? value) { element.SetValue(LocationProperty, value); } @@ -261,9 +261,9 @@ namespace MapControl { var location = GetLocation(element); - if (location != null) + if (location.HasValue) { - var position = SetViewPosition(element, GetViewPosition(location)); + var position = SetViewPosition(element, GetViewPosition(location.Value)); if (GetAutoCollapse(element)) { diff --git a/MapControl/Shared/MapPath.cs b/MapControl/Shared/MapPath.cs index 4f5211de..ef6dd13b 100644 --- a/MapControl/Shared/MapPath.cs +++ b/MapControl/Shared/MapPath.cs @@ -17,15 +17,15 @@ namespace MapControl public partial class MapPath : IMapElement { public static readonly DependencyProperty LocationProperty = - DependencyPropertyHelper.Register(nameof(Location), null, + DependencyPropertyHelper.Register(nameof(Location), default, (path, oldValue, newValue) => path.UpdateData()); /// - /// Gets or sets a Location that is used as - /// - either the origin point of a geometry specified in projected map coordinates (meters) - /// - or as an optional anchor point 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. + /// Gets or sets a Location that is either used as + /// - the origin point of a geometry specified in projected map coordinates (meters) or + /// - as an optional anchor point 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 { @@ -64,7 +64,7 @@ namespace MapControl protected virtual void UpdateData() { - if (ParentMap != null && Location != null && Data != null) + if (ParentMap != null && Data != null) { SetDataTransform(ParentMap.GetMapToViewTransform(Location)); } @@ -72,23 +72,6 @@ namespace MapControl MapPanel.SetLocation(this, Location); } - protected double GetLongitudeOffset(Location location) - { - var longitudeOffset = 0d; - - if (location != null != ParentMap.MapProjection.IsNormalCylindrical) - { - var position = ParentMap.LocationToView(location); - - if (!ParentMap.InsideViewBounds(position)) - { - longitudeOffset = ParentMap.NearestLongitude(location.Longitude) - location.Longitude; - } - } - - return longitudeOffset; - } - protected Point LocationToMap(Location location, double longitudeOffset) { var point = ParentMap.MapProjection.LocationToMap(location.Latitude, location.Longitude + longitudeOffset); diff --git a/MapControl/Shared/MapPolypoint.cs b/MapControl/Shared/MapPolypoint.cs index 2195d738..31c67796 100644 --- a/MapControl/Shared/MapPolypoint.cs +++ b/MapControl/Shared/MapPolypoint.cs @@ -1,5 +1,8 @@ using System.Collections; +using System.Collections.Generic; using System.Collections.Specialized; +using System.Linq; + #if WPF using System.Windows; using System.Windows.Media; @@ -37,6 +40,7 @@ namespace MapControl protected MapPolypoint() { Data = new PolypointGeometry(); + Location = new Location(0d, double.NaN); } protected void DataCollectionPropertyChanged(IEnumerable oldValue, IEnumerable newValue) @@ -58,5 +62,35 @@ namespace MapControl { UpdateData(); } + + protected double GetLongitudeOffset(IEnumerable locations) + { + if (!ParentMap.MapProjection.IsNormalCylindrical) + { + return 0d; + } + + Location location; + + if (!double.IsNaN(Location.Longitude)) + { + location = Location; + } + else if (locations != null && locations.Any()) + { + location = locations.First(); + } + else + { + return 0d; + } + + if (ParentMap.InsideViewBounds(ParentMap.LocationToView(location))) + { + return 0d; + } + + return ParentMap.NearestLongitude(location.Longitude) - location.Longitude; + } } } diff --git a/MapControl/WPF/MapBase.WPF.cs b/MapControl/WPF/MapBase.WPF.cs index 83c45030..2ed01030 100644 --- a/MapControl/WPF/MapBase.WPF.cs +++ b/MapControl/WPF/MapBase.WPF.cs @@ -15,13 +15,13 @@ namespace MapControl new QuadraticEase { EasingMode = EasingMode.EaseOut }); public static readonly DependencyProperty CenterProperty = - DependencyPropertyHelper.Register(nameof(Center), new Location(), + DependencyPropertyHelper.Register(nameof(Center), new Location(0d, 0d), (map, oldValue, newValue) => map.CenterPropertyChanged(newValue), (map, value) => map.CoerceCenterProperty(value), true); public static readonly DependencyProperty TargetCenterProperty = - DependencyPropertyHelper.Register(nameof(TargetCenter), new Location(), + DependencyPropertyHelper.Register(nameof(TargetCenter), new Location(0d, 0d), (map, oldValue, newValue) => map.TargetCenterPropertyChanged(newValue), (map, value) => map.CoerceCenterProperty(value), true); diff --git a/MapControl/WPF/MapContentControl.WPF.cs b/MapControl/WPF/MapContentControl.WPF.cs index 0c1e4f24..be911d1a 100644 --- a/MapControl/WPF/MapContentControl.WPF.cs +++ b/MapControl/WPF/MapContentControl.WPF.cs @@ -1,47 +1,16 @@ using System.Windows; -using System.Windows.Controls; namespace MapControl { - /// - /// ContentControl placed on a MapPanel at a geographic location specified by the Location property. - /// - public class MapContentControl : ContentControl + public partial class MapContentControl { - public static readonly DependencyProperty AutoCollapseProperty = - MapPanel.AutoCollapseProperty.AddOwner(typeof(MapContentControl)); - - public static readonly DependencyProperty LocationProperty = - MapPanel.LocationProperty.AddOwner(typeof(MapContentControl)); - static MapContentControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MapContentControl), new FrameworkPropertyMetadata(typeof(MapContentControl))); } - - /// - /// Gets/sets MapPanel.AutoCollapse. - /// - public bool AutoCollapse - { - get => (bool)GetValue(AutoCollapseProperty); - set => SetValue(AutoCollapseProperty, value); - } - - /// - /// Gets/sets MapPanel.Location. - /// - public Location Location - { - get => (Location)GetValue(LocationProperty); - set => SetValue(LocationProperty, value); - } } - /// - /// MapContentControl with a Pushpin Style. - /// - public class Pushpin : MapContentControl + public partial class Pushpin { static Pushpin() { diff --git a/MapControl/WPF/MapItem.WPF.cs b/MapControl/WPF/MapItem.WPF.cs index baffc5c7..75444644 100644 --- a/MapControl/WPF/MapItem.WPF.cs +++ b/MapControl/WPF/MapItem.WPF.cs @@ -6,13 +6,6 @@ namespace MapControl { public partial class MapItem { - public static readonly DependencyProperty AutoCollapseProperty = - MapPanel.AutoCollapseProperty.AddOwner(typeof(MapItem)); - - public static readonly DependencyProperty LocationProperty = - MapPanel.LocationProperty.AddOwner(typeof(MapItem), - new FrameworkPropertyMetadata(null, (o, e) => ((MapItem)o).UpdateMapTransform())); - static MapItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MapItem), new FrameworkPropertyMetadata(typeof(MapItem))); diff --git a/MapControl/WPF/MapPanel.WPF.cs b/MapControl/WPF/MapPanel.WPF.cs index 42da0b77..71ef2537 100644 --- a/MapControl/WPF/MapPanel.WPF.cs +++ b/MapControl/WPF/MapPanel.WPF.cs @@ -8,7 +8,7 @@ namespace MapControl DependencyPropertyHelper.RegisterAttached< bool>("AutoCollapse", typeof(MapPanel)); public static readonly DependencyProperty LocationProperty = - DependencyPropertyHelper.RegisterAttached("Location", typeof(MapPanel), null, + DependencyPropertyHelper.RegisterAttached("Location", typeof(MapPanel), null, FrameworkPropertyMetadataOptions.AffectsParentArrange); public static readonly DependencyProperty BoundingBoxProperty = diff --git a/MapControl/WPF/MapPolypoint.WPF.cs b/MapControl/WPF/MapPolypoint.WPF.cs index 6956dbdd..81f8fb69 100644 --- a/MapControl/WPF/MapPolypoint.WPF.cs +++ b/MapControl/WPF/MapPolypoint.WPF.cs @@ -13,7 +13,7 @@ namespace MapControl if (ParentMap != null && locations != null) { - var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault()); + var longitudeOffset = GetLongitudeOffset(locations); AddPolylinePoints(context, locations, longitudeOffset, closed); } @@ -25,7 +25,7 @@ namespace MapControl if (ParentMap != null && polygons != null) { - var longitudeOffset = GetLongitudeOffset(Location); + var longitudeOffset = GetLongitudeOffset(polygons.FirstOrDefault()); foreach (var locations in polygons) { diff --git a/MapControl/WinUI/MapBase.WinUI.cs b/MapControl/WinUI/MapBase.WinUI.cs index b15024bc..aa25e2ea 100644 --- a/MapControl/WinUI/MapBase.WinUI.cs +++ b/MapControl/WinUI/MapBase.WinUI.cs @@ -23,11 +23,11 @@ namespace MapControl new QuadraticEase { EasingMode = EasingMode.EaseOut }); public static readonly DependencyProperty CenterProperty = - DependencyPropertyHelper.Register(nameof(Center), new Location(), + DependencyPropertyHelper.Register(nameof(Center), new Location(0d, 0d), (map, oldValue, newValue) => map.CenterPropertyChanged(newValue)); public static readonly DependencyProperty TargetCenterProperty = - DependencyPropertyHelper.Register(nameof(TargetCenter), new Location(), + DependencyPropertyHelper.Register(nameof(TargetCenter), new Location(0d, 0d), (map, oldValue, newValue) => map.TargetCenterPropertyChanged(newValue)); public static readonly DependencyProperty MinZoomLevelProperty = diff --git a/MapControl/WinUI/MapContentControl.WinUI.cs b/MapControl/WinUI/MapContentControl.WinUI.cs index 71f0d4e2..02fd43cd 100644 --- a/MapControl/WinUI/MapContentControl.WinUI.cs +++ b/MapControl/WinUI/MapContentControl.WinUI.cs @@ -1,52 +1,21 @@ #if UWP using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data; #else using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Data; #endif namespace MapControl { - /// - /// ContentControl placed on a MapPanel at a geographic location specified by the Location property. - /// - public partial class MapContentControl : ContentControl + public partial class MapContentControl { - public static readonly DependencyProperty AutoCollapseProperty = - DependencyPropertyHelper.Register(nameof(AutoCollapse), false, - (control, oldValue, newValue) => MapPanel.SetAutoCollapse(control, newValue)); - - public static readonly DependencyProperty LocationProperty = - DependencyPropertyHelper.Register(nameof(Location), null, - (control, oldValue, newValue) => MapPanel.SetLocation(control, newValue)); - public MapContentControl() { DefaultStyleKey = typeof(MapContentControl); MapPanel.InitMapElement(this); } - /// - /// Gets/sets MapPanel.AutoCollapse. - /// - public bool AutoCollapse - { - get => (bool)GetValue(AutoCollapseProperty); - set => SetValue(AutoCollapseProperty, value); - } - - /// - /// Gets/sets MapPanel.Location. - /// - public Location Location - { - get => (Location)GetValue(LocationProperty); - set => SetValue(LocationProperty, value); - } - protected override void OnApplyTemplate() { base.OnApplyTemplate(); @@ -76,10 +45,7 @@ namespace MapControl } } - /// - /// MapContentControl with a Pushpin Style. - /// - public class Pushpin : MapContentControl + public partial class Pushpin : MapContentControl { public Pushpin() { diff --git a/MapControl/WinUI/MapItem.WinUI.cs b/MapControl/WinUI/MapItem.WinUI.cs index 99280ee4..d99928dc 100644 --- a/MapControl/WinUI/MapItem.WinUI.cs +++ b/MapControl/WinUI/MapItem.WinUI.cs @@ -16,18 +16,6 @@ namespace MapControl { public partial class MapItem { - public static readonly DependencyProperty AutoCollapseProperty = - DependencyPropertyHelper.Register(nameof(AutoCollapse), false, - (item, oldValue, newValue) => MapPanel.SetAutoCollapse(item, newValue)); - - public static readonly DependencyProperty LocationProperty = - DependencyPropertyHelper.Register(nameof(Location), null, - (item, oldValue, newValue) => - { - MapPanel.SetLocation(item, newValue); - item.UpdateMapTransform(); - }); - private Windows.Foundation.Point? pointerPressedPosition; public MapItem() diff --git a/MapControl/WinUI/MapPanel.WinUI.cs b/MapControl/WinUI/MapPanel.WinUI.cs index 0841b3de..5a352b77 100644 --- a/MapControl/WinUI/MapPanel.WinUI.cs +++ b/MapControl/WinUI/MapPanel.WinUI.cs @@ -14,7 +14,7 @@ namespace MapControl DependencyPropertyHelper.RegisterAttached("AutoCollapse", typeof(MapPanel)); public static readonly DependencyProperty LocationProperty = - DependencyPropertyHelper.RegisterAttached("Location", typeof(MapPanel), null, + DependencyPropertyHelper.RegisterAttached("Location", typeof(MapPanel), null, (element, oldValue, newValue) => (element.Parent as MapPanel)?.InvalidateArrange()); public static readonly DependencyProperty BoundingBoxProperty = diff --git a/MapControl/WinUI/MapPolypoint.WinUI.cs b/MapControl/WinUI/MapPolypoint.WinUI.cs index 2d52f56d..18ee4cf2 100644 --- a/MapControl/WinUI/MapPolypoint.WinUI.cs +++ b/MapControl/WinUI/MapPolypoint.WinUI.cs @@ -18,7 +18,7 @@ namespace MapControl if (ParentMap != null && locations != null) { - var longitudeOffset = GetLongitudeOffset(Location ?? locations.FirstOrDefault()); + var longitudeOffset = GetLongitudeOffset(locations); AddPolylinePoints(figures, locations, longitudeOffset, closed); } @@ -31,7 +31,7 @@ namespace MapControl if (ParentMap != null && polygons != null) { - var longitudeOffset = GetLongitudeOffset(Location); + var longitudeOffset = GetLongitudeOffset(polygons.FirstOrDefault()); foreach (var locations in polygons) { diff --git a/MapControl/WinUI/Rect.WinUI.cs b/MapControl/WinUI/Rect.WinUI.cs index 4596d449..e0678c5b 100644 --- a/MapControl/WinUI/Rect.WinUI.cs +++ b/MapControl/WinUI/Rect.WinUI.cs @@ -5,28 +5,12 @@ namespace MapControl /// /// Replaces Windows.Foundation.Rect for double floating point precision. /// - public readonly struct Rect : IEquatable + public readonly struct Rect(double x, double y, double width, double height) : IEquatable { - public Rect(double x, double y, double width, double height) - { - X = x; - Y = y; - Width = width; - Height = height; - } - - public Rect(Point p1, Point p2) - { - X = Math.Min(p1.X, p2.X); - Y = Math.Min(p1.Y, p2.Y); - Width = Math.Max(p1.X, p2.X) - X; - Height = Math.Max(p1.Y, p2.Y) - Y; - } - - public double X { get; } - public double Y { get; } - public double Width { get; } - public double Height { get; } + public double X => x; + public double Y => y; + public double Width => width; + public double Height => height; public static implicit operator Windows.Foundation.Rect(Rect r) => new(r.X, r.Y, r.Width, r.Height); diff --git a/SampleApps/AvaloniaApp/MainWindow.axaml.cs b/SampleApps/AvaloniaApp/MainWindow.axaml.cs index 72890242..0381cae3 100644 --- a/SampleApps/AvaloniaApp/MainWindow.axaml.cs +++ b/SampleApps/AvaloniaApp/MainWindow.axaml.cs @@ -63,12 +63,9 @@ namespace SampleApplication e.Pointer.Capture(map); var location = map.ViewToLocation(point.Position); - if (location != null) - { - map.Cursor = new Cursor(StandardCursorType.Cross); - measurementLine.IsVisible = true; - measurementLine.Locations = new LocationCollection(location); - } + map.Cursor = new Cursor(StandardCursorType.Cross); + measurementLine.IsVisible = true; + measurementLine.Locations = new LocationCollection(location); } } } @@ -88,23 +85,14 @@ namespace SampleApplication { var location = map.ViewToLocation(e.GetPosition(map)); - if (location != null) - { - mouseLocation.IsVisible = true; - mouseLocation.Text = GetLatLonText(location); + mouseLocation.IsVisible = true; + mouseLocation.Text = GetLatLonText(location); - var start = measurementLine.Locations?.FirstOrDefault(); - - if (start != null) - { - measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); - mouseLocation.Text += GetDistanceText(location.GetDistance(start)); - } - } - else + if (measurementLine.Locations != null) { - mouseLocation.IsVisible = false; - mouseLocation.Text = ""; + var start = measurementLine.Locations.First(); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); + mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } } diff --git a/SampleApps/WinUiApp/MainWindow.xaml.cs b/SampleApps/WinUiApp/MainWindow.xaml.cs index f4764a78..f2ca0ae9 100644 --- a/SampleApps/WinUiApp/MainWindow.xaml.cs +++ b/SampleApps/WinUiApp/MainWindow.xaml.cs @@ -59,11 +59,8 @@ namespace SampleApplication { var location = map.ViewToLocation(point.Position); - if (location != null) - { - measurementLine.Visibility = Visibility.Visible; - measurementLine.Locations = new LocationCollection(location); - } + measurementLine.Visibility = Visibility.Visible; + measurementLine.Locations = new LocationCollection(location); } else if (e.KeyModifiers.HasFlag(VirtualKeyModifiers.Control) && map.MapLayer is WmsImageLayer wmsLayer) { @@ -87,23 +84,14 @@ namespace SampleApplication var point = e.GetCurrentPoint(map); var location = map.ViewToLocation(point.Position); - if (location != null) - { - mouseLocation.Visibility = Visibility.Visible; - mouseLocation.Text = GetLatLonText(location); + mouseLocation.Visibility = Visibility.Visible; + mouseLocation.Text = GetLatLonText(location); - var start = measurementLine.Locations?.FirstOrDefault(); - - if (start != null) - { - measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); - mouseLocation.Text += GetDistanceText(location.GetDistance(start)); - } - } - else + if (measurementLine.Locations != null) { - mouseLocation.Visibility = Visibility.Collapsed; - mouseLocation.Text = ""; + var start = measurementLine.Locations.First(); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); + mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } } diff --git a/SampleApps/WpfApplication/MainWindow.xaml.cs b/SampleApps/WpfApplication/MainWindow.xaml.cs index edd2ac68..4ba8f9ad 100644 --- a/SampleApps/WpfApplication/MainWindow.xaml.cs +++ b/SampleApps/WpfApplication/MainWindow.xaml.cs @@ -80,7 +80,7 @@ namespace SampleApplication { var location = map.ViewToLocation(e.GetPosition(map)); - if (location != null && map.CaptureMouse()) + if (map.CaptureMouse()) { map.Cursor = Cursors.Cross; measurementLine.Visibility = Visibility.Visible; @@ -100,23 +100,14 @@ namespace SampleApplication { var location = map.ViewToLocation(e.GetPosition(map)); - if (location != null) - { - mouseLocation.Visibility = Visibility.Visible; - mouseLocation.Text = GetLatLonText(location); + mouseLocation.Visibility = Visibility.Visible; + mouseLocation.Text = GetLatLonText(location); - var start = measurementLine.Locations?.FirstOrDefault(); - - if (start != null) - { - measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); - mouseLocation.Text += GetDistanceText(location.GetDistance(start)); - } - } - else + if (measurementLine.Locations != null) { - mouseLocation.Visibility = Visibility.Collapsed; - mouseLocation.Text = ""; + var start = measurementLine.Locations.First(); + measurementLine.Locations = LocationCollection.GeodesicLocations(start, location); + mouseLocation.Text += GetDistanceText(location.GetDistance(start)); } }