123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- using System;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Net.Http;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Input;
- using System.Windows.Media;
- using Geocoding;
- using Geocoding.Google;
- using InABox.Clients;
- using InABox.Core;
- using Nominatim.API.Geocoders;
- using Nominatim.API.Models;
- using Nominatim.API.Web;
- using Syncfusion.UI.Xaml.Maps;
- using Address = InABox.Core.Address;
- using Point = System.Windows.Point;
- namespace InABox.Wpf.DynamicGrid;
- public partial class GeofenceEditor : Window
- {
- public Address Address { get; private set; }
-
- GeoFenceDefinition _definition = null;
- private ImageryLayer ImageryLayer;
- public MapPolygon Polygon;
-
- public GeofenceEditor(Address address, bool canEdit)
- {
- Address = address;
- _definition = Serialization.Deserialize<GeoFenceDefinition>(address.Geofence) ?? new GeoFenceDefinition();
-
- InitializeComponent();
- ImageryLayer = string.IsNullOrWhiteSpace(CoreUtils.GoogleAPIKey)
- ? new ImageryLayer()
- : new GoogleImageryLayer() { Type = GoogleImageryLayerType.Satellite };
- ImageryLayer.Radius = 10;
-
- Map.Layers.Add(ImageryLayer);
- Polygon = new MapPolygon()
- {
- Fill = new SolidColorBrush(Colors.LightSalmon) { Opacity = 0.5 },
- Stroke = new SolidColorBrush(Colors.Firebrick),
- StrokeThickness = 0.75,
- };
- var layer = new SubShapeFileLayer() { MapElements = new ObservableCollection<MapElement>([Polygon]) };
- ImageryLayer.SubShapeFileLayers = new ObservableCollection<SubShapeFileLayer>([layer]);
-
- 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;
- Title = $"Geofence Editor ({(string.IsNullOrWhiteSpace(CoreUtils.GoogleAPIKey) ? "OSM" : "Google")})";
- if (canEdit && string.IsNullOrWhiteSpace(Address.Geofence))
- Task.Run(CheckAddress);
- else
- SetupMap();
-
- }
-
- private class HttpClientFactory : IHttpClientFactory
- {
- private static HttpClient? _client;
- public HttpClient CreateClient(string name)
- {
-
- _client ??= new HttpClient();
- return _client;
- }
- }
-
- private static HttpClientFactory? _httpClientFactory = null;
- private async Task CheckAddress()
- {
- if (!string.IsNullOrWhiteSpace(CoreUtils.GoogleAPIKey))
- {
-
- IGeocoder geocoder = new GoogleGeocoder(CoreUtils.GoogleAPIKey);
- try
- {
- var matches =
- await geocoder.GeocodeAsync(
- $"{Address.Street}, {Address.City} {Address.State} {Address.PostCode} Australia");
- var match = matches.FirstOrDefault();
- if (match != null)
- {
- Address.Location.Longitude = match.Coordinates.Longitude;
- Address.Location.Latitude = match.Coordinates.Latitude;
-
- if (match is GoogleAddress gAdd)
- {
- _definition.Coordinates.Clear();
- _definition.Coordinates.Add(new GeoPoint(gAdd.Bounds.NorthEast.Latitude,
- gAdd.Bounds.NorthEast.Longitude));
- _definition.Coordinates.Add(new GeoPoint(gAdd.Bounds.NorthEast.Latitude,
- gAdd.Bounds.SouthWest.Longitude));
- _definition.Coordinates.Add(new GeoPoint(gAdd.Bounds.SouthWest.Latitude,
- gAdd.Bounds.SouthWest.Longitude));
- _definition.Coordinates.Add(new GeoPoint(gAdd.Bounds.SouthWest.Latitude,
- gAdd.Bounds.NorthEast.Longitude));
- _definition.Coordinates.Add(new GeoPoint(gAdd.Bounds.NorthEast.Latitude,
- gAdd.Bounds.NorthEast.Longitude));
- }
- else
- SquareFence(20.0);
-
- Address.Geofence = Serialization.Serialize(_definition);
- }
- else
- {
- Address.Location.Longitude = 0.0;
- Address.Location.Latitude = 0.0;
- Address.Geofence = string.Empty;
- }
- }
- catch (Exception e)
- {
- Logger.Send(LogType.Error, ClientFactory.UserID, $"{e.Message}\n{e.StackTrace}");
- }
- }
- else
- {
- _httpClientFactory ??= new HttpClientFactory();
- NominatimWebInterface intf = new NominatimWebInterface(_httpClientFactory);
-
- var searcher = new ForwardGeocoder(intf);
- var request = new ForwardGeocodeRequest()
- {
- StreetAddress = Address.Street,
- City = Address.City,
- // County="",
- State = Address.State,
- PostalCode = Address.PostCode,
- Country = "AU",
- //queryString = $"{Address.Street}, {Address.City}, {Address.State}, {Address.PostCode} Australia",
- //BreakdownAddressElements = true,
- ShowExtraTags = true,
- ShowAlternativeNames = true,
- ShowGeoJSON = true,
- };
- try
- {
- var matches = await searcher.Geocode(request);
- var match = matches.FirstOrDefault();
- if (match != null)
- {
- Address.Location.Longitude = match.Longitude;
- Address.Location.Latitude = match.Latitude;
- if (match.BoundingBox.HasValue)
- {
- var bbox = match.BoundingBox.Value;
- _definition.Coordinates.Clear();
- _definition.Coordinates.Add(new GeoPoint(bbox.minLatitude, bbox.minLongitude));
- _definition.Coordinates.Add(new GeoPoint(bbox.minLatitude, bbox.maxLongitude));
- _definition.Coordinates.Add(new GeoPoint(bbox.maxLatitude, bbox.maxLongitude));
- _definition.Coordinates.Add(new GeoPoint(bbox.maxLatitude, bbox.minLongitude));
- _definition.Coordinates.Add(new GeoPoint(bbox.minLatitude, bbox.minLongitude));
- }
- else
- SquareFence(20.0);
- Address.Geofence = Serialization.Serialize(_definition);
- }
- else
- {
- Address.Location.Longitude = 0.0;
- Address.Location.Latitude = 0.0;
- Address.Geofence = string.Empty;
- }
- }
-
- catch (Exception e)
- {
- Logger.Send(LogType.Error, ClientFactory.UserID, $"{e.Message}\n{e.StackTrace}");
- }
-
- }
- 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()
- {
- CenterMap();
- RadiusSlider.ValueChanged -= RadiusSliderChanged;
- RadiusSlider.Value = 20.0;
- if (_definition.Coordinates.Count < 4)
- SquareFence(20.0);
- RadiusSlider.ValueChanged += RadiusSliderChanged;
- UpdateMap();
- }
- private void CenterMap()
- {
- ImageryLayer.Center = new Point(Address.Location.Latitude, Address.Location.Longitude);
- ImageryLayer.Markers = new CoreObservableCollection<MapMarker>([new MapMarker()
- {
- Latitude = $"{Address.Location.Latitude:F15}",
- Longitude = $"{Address.Location.Longitude:F15}"
- }]);
- }
- private void RadiusSliderChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
- {
- RecalculateSquareFence();
- UpdateMap();
- }
- private void RecalculateSquareFence()
- {
- SquareFence(RadiusSlider.Value);
- Address.Geofence = Serialization.Serialize(_definition);
- }
- private void UpdateMap()
- {
-
- Polygon.Points = new ObservableCollection<Point>(_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 enum GeoFenceAction
- {
- None,
- Polygon,
- Square,
- Coordinates
- }
- private GeoFenceAction _action = GeoFenceAction.None;
- private void UpdateButtons(GeoFenceAction action)
- {
- _action = action;
- SetGeometry.IsEnabled = action == GeoFenceAction.None || action == GeoFenceAction.Polygon;
- SetGeometry.Background = action == GeoFenceAction.Polygon
- ? Brushes.Yellow
- : Brushes.Silver;
- SetRadius.IsEnabled = action == GeoFenceAction.None || action == GeoFenceAction.Square;
- SetRadius.Background = action == GeoFenceAction.Square
- ? Brushes.Yellow
- : Brushes.Silver;
- RadiusSlider.Visibility = action == GeoFenceAction.Square
- ? Visibility.Visible
- : Visibility.Collapsed;
- SetCoordinates.IsEnabled = action == GeoFenceAction.None || action == GeoFenceAction.Coordinates;
- SetCoordinates.Background = action == GeoFenceAction.Coordinates
- ? Brushes.Yellow
- : Brushes.Silver;
- }
-
- private void SetGeometry_OnClick(object sender, RoutedEventArgs e)
- {
- if (_action == GeoFenceAction.Polygon)
- UpdateButtons(GeoFenceAction.None);
- else
- {
- UpdateButtons(GeoFenceAction.Polygon);
- _definition.Coordinates.Clear();
- UpdateMap();
- }
- }
- 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 (_action == GeoFenceAction.Polygon)
- {
- 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;
- }
- else if (_action == GeoFenceAction.Coordinates)
- {
- Address.Location.Latitude = geopoint.Latitude;
- Address.Location.Longitude = geopoint.Longitude;
- CenterMap();
- UpdateMap();
- e.Handled = true;
- }
- }
- private void SetRadius_OnClick(object sender, RoutedEventArgs e)
- {
- if (_action == GeoFenceAction.Square)
- UpdateButtons(GeoFenceAction.None);
- else
- {
- UpdateButtons(GeoFenceAction.Square);
- RadiusSlider.ValueChanged -= RadiusSliderChanged;
- RadiusSlider.Value = 20.0;
- SquareFence(20.0);
- RadiusSlider.ValueChanged += RadiusSliderChanged;
- RecalculateSquareFence();
- UpdateMap();
- }
- }
- private void SearchAddress_Click(object sender, RoutedEventArgs e)
- {
- Task.Run(CheckAddress);
- }
- private void SetCoordinates_OnClick(object sender, RoutedEventArgs e)
- {
- if (_action == GeoFenceAction.Coordinates)
- UpdateButtons(GeoFenceAction.None);
- else
- UpdateButtons(GeoFenceAction.Coordinates);
- }
- }
|