using System; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using Geocoding; using Geocoding.Google; using InABox.Core; using Syncfusion.UI.Xaml.Maps; using Address = InABox.Core.Address; using Point = System.Windows.Point; namespace InABox.Wpf.DynamicGrid; public class GoogleImageryLayer : ImageryLayer { protected override string GetUri(int X, int Y, int Scale) { var link = $"https://mt1.google.com/vt/lyrs=m@221097413,3&x={X}&y={Y}&z={Scale}"; return link; } } public partial class GeofenceEditor : Window { public Address Address { get; private set; } GeoFenceDefinition _definition = null; public GeofenceEditor(Address address, bool canEdit) { Address = address; _definition = Serialization.Deserialize(address.Geofence) ?? new GeoFenceDefinition(); InitializeComponent(); SetGeometry.Visibility = canEdit ? Visibility.Visible : Visibility.Collapsed; SetRadius.Visibility = canEdit ? Visibility.Visible : Visibility.Collapsed; SearchBar.Visibility = canEdit ? Visibility.Visible : Visibility.Collapsed; Street.Text = address.Street; City.Text = address.City; State.Text = address.State; PostCode.Text = Address.PostCode; if (canEdit && string.IsNullOrWhiteSpace(Address.Geofence)) Task.Run(CheckAddress); else SetupMap(); } private async Task CheckAddress() { IGeocoder geocoder = new GoogleGeocoder(CoreUtils.GoogleAPIKey); var matches = await geocoder.GeocodeAsync($"{Address.Street}, {Address.City} {Address.State} {Address.PostCode} Australia"); var match = matches.FirstOrDefault(); Address.Location.Longitude = match?.Coordinates.Longitude ?? 0.0; Address.Location.Latitude = match?.Coordinates.Latitude ?? 0.0; SquareFence(20.0); Address.Geofence = Serialization.Serialize(_definition); Dispatcher.BeginInvoke(SetupMap); } private void SquareFence(double side) { _definition.Coordinates.Clear(); _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(0-(side/2.0),0-(side/2.0))); _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(0-(side/2.0),side/2.0)); _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(side/2.0,side/2.0)); _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(side/2.0,0-(side/2.0))); _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(0-(side/2.0),0-(side/2.0))); } private void SetupMap() { ImageryLayer.Center = new Point(Address.Location.Latitude, Address.Location.Longitude); ImageryLayer.Markers = new CoreObservableCollection([new MapMarker() { Latitude = $"{Address.Location.Latitude:F15}", Longitude = $"{Address.Location.Longitude:F15}" }]); RadiusSlider.ValueChanged -= RadiusSliderChanged; RadiusSlider.Value = 20.0; if (_definition.Coordinates.Count < 4) SquareFence(20.0); RadiusSlider.ValueChanged += RadiusSliderChanged; UpdateMap(); } private void RadiusSliderChanged(object sender, RoutedPropertyChangedEventArgs e) { RecalculateSquareFence(); UpdateMap(); } private void RecalculateSquareFence() { SquareFence(RadiusSlider.Value); Address.Geofence = Serialization.Serialize(_definition); } private void UpdateMap() { Polygon.Points = new ObservableCollection(_definition.Coordinates.Select(p => new Point(p.Latitude, p.Longitude))); } private void ZoomIn_OnClick(object sender, RoutedEventArgs e) { Map.MaxZoom = Math.Min(20, Map.ZoomLevel + 1); Map.ZoomLevel = Math.Min(20, Map.ZoomLevel + 1); UpdateMap(); } private void ZoomOut_OnClick(object sender, RoutedEventArgs e) { Map.MinZoom= Math.Max(5, Map.ZoomLevel - 1); Map.ZoomLevel = Math.Max(5, Map.ZoomLevel - 1); UpdateMap(); } private bool _polygon = false; private bool _square = false; private void SetGeometry_OnClick(object sender, RoutedEventArgs e) { if (!_polygon) { _square = false; SetRadius.Background = System.Windows.Media.Brushes.Silver; RadiusSlider.Visibility = Visibility.Collapsed; _polygon = true; _definition.Coordinates.Clear(); UpdateMap(); SetGeometry.Background = System.Windows.Media.Brushes.Yellow; } else { _polygon = false; SetGeometry.Background = System.Windows.Media.Brushes.Silver; } } private void Map_OnMouseUp(object sender, MouseButtonEventArgs e) { var point = Mouse.GetPosition(Map); var latlon = ImageryLayer.GetLatLonFromPoint(point); var geopoint = new GeoPoint(latlon.Y, latlon.X); if (!_polygon) return; if (!_definition.Coordinates.Any()) _definition.Coordinates.Add(geopoint.Copy()); _definition.Coordinates.Insert(_definition.Coordinates.Count - 1, geopoint.Copy()); Address.Geofence = Serialization.Serialize(_definition); UpdateMap(); e.Handled = true; } private void SetRadius_OnClick(object sender, RoutedEventArgs e) { if (!_square) { _polygon = false; SetGeometry.Background = System.Windows.Media.Brushes.Silver; _square = true; RadiusSlider.ValueChanged -= RadiusSliderChanged; RadiusSlider.Value = 20.0; SquareFence(20.0); RadiusSlider.ValueChanged += RadiusSliderChanged; RadiusSlider.Visibility = Visibility.Visible; RecalculateSquareFence(); UpdateMap(); SetRadius.Background = System.Windows.Media.Brushes.Yellow; } else { _square = false; RadiusSlider.Visibility = Visibility.Collapsed; SetRadius.Background = System.Windows.Media.Brushes.Silver; } } private void SearchAddress_Click(object sender, RoutedEventArgs e) { Task.Run(CheckAddress); } }