GeofenceEditor.xaml.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using System.Collections.ObjectModel;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using System.Windows;
  6. using System.Windows.Input;
  7. using Geocoding;
  8. using Geocoding.Google;
  9. using InABox.Core;
  10. using Syncfusion.UI.Xaml.Maps;
  11. using Address = InABox.Core.Address;
  12. using Point = System.Windows.Point;
  13. namespace InABox.Wpf.DynamicGrid;
  14. public class GoogleImageryLayer : ImageryLayer
  15. {
  16. protected override string GetUri(int X, int Y, int Scale)
  17. {
  18. var link = $"https://mt1.google.com/vt/lyrs=m@221097413,3&x={X}&y={Y}&z={Scale}";
  19. return link;
  20. }
  21. }
  22. public partial class GeofenceEditor : Window
  23. {
  24. public Address Address { get; private set; }
  25. GeoFenceDefinition _definition = null;
  26. public GeofenceEditor(Address address, bool canEdit)
  27. {
  28. Address = address;
  29. _definition = Serialization.Deserialize<GeoFenceDefinition>(address.Geofence) ?? new GeoFenceDefinition();
  30. InitializeComponent();
  31. SetGeometry.Visibility = canEdit ? Visibility.Visible : Visibility.Collapsed;
  32. SetRadius.Visibility = canEdit ? Visibility.Visible : Visibility.Collapsed;
  33. SearchBar.Visibility = canEdit ? Visibility.Visible : Visibility.Collapsed;
  34. Street.Text = address.Street;
  35. City.Text = address.City;
  36. State.Text = address.State;
  37. PostCode.Text = Address.PostCode;
  38. if (canEdit && string.IsNullOrWhiteSpace(Address.Geofence))
  39. Task.Run(CheckAddress);
  40. else
  41. SetupMap();
  42. }
  43. private async Task CheckAddress()
  44. {
  45. IGeocoder geocoder = new GoogleGeocoder(CoreUtils.GoogleAPIKey);
  46. var matches = await geocoder.GeocodeAsync($"{Address.Street}, {Address.City} {Address.State} {Address.PostCode} Australia");
  47. var match = matches.FirstOrDefault();
  48. Address.Location.Longitude = match?.Coordinates.Longitude ?? 0.0;
  49. Address.Location.Latitude = match?.Coordinates.Latitude ?? 0.0;
  50. SquareFence(20.0);
  51. Address.Geofence = Serialization.Serialize(_definition);
  52. Dispatcher.BeginInvoke(SetupMap);
  53. }
  54. private void SquareFence(double side)
  55. {
  56. _definition.Coordinates.Clear();
  57. _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(0-(side/2.0),0-(side/2.0)));
  58. _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(0-(side/2.0),side/2.0));
  59. _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(side/2.0,side/2.0));
  60. _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(side/2.0,0-(side/2.0)));
  61. _definition.Coordinates.Add(new GeoPoint(Address.Location.Latitude, Address.Location.Longitude).Move(0-(side/2.0),0-(side/2.0)));
  62. }
  63. private void SetupMap()
  64. {
  65. ImageryLayer.Center = new Point(Address.Location.Latitude, Address.Location.Longitude);
  66. ImageryLayer.Markers = new CoreObservableCollection<MapMarker>([new MapMarker()
  67. {
  68. Latitude = $"{Address.Location.Latitude:F15}",
  69. Longitude = $"{Address.Location.Longitude:F15}"
  70. }]);
  71. RadiusSlider.ValueChanged -= RadiusSliderChanged;
  72. RadiusSlider.Value = 20.0;
  73. if (_definition.Coordinates.Count < 4)
  74. SquareFence(20.0);
  75. RadiusSlider.ValueChanged += RadiusSliderChanged;
  76. UpdateMap();
  77. }
  78. private void RadiusSliderChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
  79. {
  80. RecalculateSquareFence();
  81. UpdateMap();
  82. }
  83. private void RecalculateSquareFence()
  84. {
  85. SquareFence(RadiusSlider.Value);
  86. Address.Geofence = Serialization.Serialize(_definition);
  87. }
  88. private void UpdateMap()
  89. {
  90. Polygon.Points = new ObservableCollection<Point>(_definition.Coordinates.Select(p => new Point(p.Latitude, p.Longitude)));
  91. }
  92. private void ZoomIn_OnClick(object sender, RoutedEventArgs e)
  93. {
  94. Map.MaxZoom = Math.Min(20, Map.ZoomLevel + 1);
  95. Map.ZoomLevel = Math.Min(20, Map.ZoomLevel + 1);
  96. UpdateMap();
  97. }
  98. private void ZoomOut_OnClick(object sender, RoutedEventArgs e)
  99. {
  100. Map.MinZoom= Math.Max(5, Map.ZoomLevel - 1);
  101. Map.ZoomLevel = Math.Max(5, Map.ZoomLevel - 1);
  102. UpdateMap();
  103. }
  104. private bool _polygon = false;
  105. private bool _square = false;
  106. private void SetGeometry_OnClick(object sender, RoutedEventArgs e)
  107. {
  108. if (!_polygon)
  109. {
  110. _square = false;
  111. SetRadius.Background = System.Windows.Media.Brushes.Silver;
  112. RadiusSlider.Visibility = Visibility.Collapsed;
  113. _polygon = true;
  114. _definition.Coordinates.Clear();
  115. UpdateMap();
  116. SetGeometry.Background = System.Windows.Media.Brushes.Yellow;
  117. }
  118. else
  119. {
  120. _polygon = false;
  121. SetGeometry.Background = System.Windows.Media.Brushes.Silver;
  122. }
  123. }
  124. private void Map_OnMouseUp(object sender, MouseButtonEventArgs e)
  125. {
  126. var point = Mouse.GetPosition(Map);
  127. var latlon = ImageryLayer.GetLatLonFromPoint(point);
  128. var geopoint = new GeoPoint(latlon.Y, latlon.X);
  129. if (!_polygon)
  130. return;
  131. if (!_definition.Coordinates.Any())
  132. _definition.Coordinates.Add(geopoint.Copy());
  133. _definition.Coordinates.Insert(_definition.Coordinates.Count - 1, geopoint.Copy());
  134. Address.Geofence = Serialization.Serialize(_definition);
  135. UpdateMap();
  136. e.Handled = true;
  137. }
  138. private void SetRadius_OnClick(object sender, RoutedEventArgs e)
  139. {
  140. if (!_square)
  141. {
  142. _polygon = false;
  143. SetGeometry.Background = System.Windows.Media.Brushes.Silver;
  144. _square = true;
  145. RadiusSlider.ValueChanged -= RadiusSliderChanged;
  146. RadiusSlider.Value = 20.0;
  147. SquareFence(20.0);
  148. RadiusSlider.ValueChanged += RadiusSliderChanged;
  149. RadiusSlider.Visibility = Visibility.Visible;
  150. RecalculateSquareFence();
  151. UpdateMap();
  152. SetRadius.Background = System.Windows.Media.Brushes.Yellow;
  153. }
  154. else
  155. {
  156. _square = false;
  157. RadiusSlider.Visibility = Visibility.Collapsed;
  158. SetRadius.Background = System.Windows.Media.Brushes.Silver;
  159. }
  160. }
  161. private void SearchAddress_Click(object sender, RoutedEventArgs e)
  162. {
  163. Task.Run(CheckAddress);
  164. }
  165. }