GeoFenceGrid.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Windows.Controls;
  6. using System.Windows.Media.Imaging;
  7. using Comal.Classes;
  8. using Google.Maps;
  9. using InABox.Clients;
  10. using InABox.Core;
  11. using InABox.DynamicGrid;
  12. using InABox.WPF;
  13. using Microsoft.Win32;
  14. using PRSDesktop.Forms;
  15. using Path = System.IO.Path;
  16. namespace PRSDesktop;
  17. public class GeoFenceGrid : DynamicDataGrid<GeoFence>
  18. {
  19. private static BitmapImage MAP = PRSDesktop.Resources.map.AsBitmapImage();
  20. protected override void Init()
  21. {
  22. base.Init();
  23. HiddenColumns.Add(x=>x.LastUpdate);
  24. HiddenColumns.Add(x=>x.MinX);
  25. HiddenColumns.Add(x=>x.MaxX);
  26. HiddenColumns.Add(x=>x.MinY);
  27. HiddenColumns.Add(x=>x.MaxY);
  28. HiddenColumns.Add(x=>x.Geometry);
  29. AddButton("Import", PRSDesktop.Resources.mapmarker.AsBitmapImage(), ImportGeoJSON);
  30. ActionColumns.Add(new DynamicImageColumn((r) => MAP, MapClick));
  31. }
  32. protected override void DoReconfigure(DynamicGridOptions options)
  33. {
  34. base.DoReconfigure(options);
  35. options.PageSize = 1000;
  36. options.RecordCount = true;
  37. }
  38. private bool MapClick(CoreRow? row)
  39. {
  40. if (row == null)
  41. return false;
  42. var longitude = (row.Get<GeoFence,double>(x=>x.MinX) + row.Get<GeoFence,double>(x=>x.MaxX)) / 2.0;
  43. var latitude = (row.Get<GeoFence,double>(x=>x.MinY) + row.Get<GeoFence,double>(x=>x.MaxY)) / 2.0;
  44. var timestamp = row.Get<GeoFence, DateTime>(x=>x.LastUpdate);
  45. var geometry = row.Get<GeoFence, string>(x=>x.Geometry);
  46. var form = new MapForm(latitude, longitude, timestamp, geometry);
  47. form.ShowDialog();
  48. return false;
  49. }
  50. private bool ImportGeoJSON(Button button, CoreRow[] rows)
  51. {
  52. OpenFileDialog ofd = new();
  53. ofd.Filter = "GeoJSON Files (*.geojson)|*.geojson";
  54. if (ofd.ShowDialog() == true)
  55. {
  56. Progress.ShowModal("Loading File", progress =>
  57. {
  58. var geojson = GeoJSONFile.Load(ofd.FileName);
  59. if (geojson != null)
  60. {
  61. var queue = geojson.Features?.ToQueue() ?? new Queue<GeoJSONFeature>();
  62. int fTotal = queue.Count;
  63. while (queue.Count > 0)
  64. {
  65. List<GeoFence> updates = new();
  66. var chunk = queue.Dequeue(1000).ToArray();
  67. progress.Report($"Processing {((fTotal - queue.Count)*100.0F/fTotal):F2}% complete)");
  68. var fulladdresses = chunk.Select(x=>x.Properties?.FullAddress() ?? string.Empty).Distinct().ToArray();
  69. var existing = Client.Query(new Filter<GeoFence>(x => x.FullAddress).InList(fulladdresses))
  70. .ToObjects<GeoFence>().ToList();
  71. foreach (var record in chunk)
  72. {
  73. if (record.Properties == null || record.Geometry == null)
  74. continue;
  75. string id = record.Properties.ID();
  76. string fulladdress = record.Properties.FullAddress();
  77. if (string.IsNullOrWhiteSpace(id) || string.IsNullOrWhiteSpace(fulladdress))
  78. continue;
  79. var update = existing.FirstOrDefault(x => string.Equals(x.FullAddress, fulladdress));
  80. if (update == null)
  81. {
  82. update = new GeoFence();
  83. update.FullAddress = fulladdress;
  84. existing.Add(update);
  85. }
  86. update.Street = record.Properties.Street();
  87. update.City = record.Properties.Suburb();
  88. update.State = record.Properties.State();
  89. update.Country = record.Properties.Country();
  90. update.PostCode = record.Properties.Postcode();
  91. var bounds = record.Geometry.Bounds();
  92. update.MinX = bounds.Item1.X;
  93. update.MinY = bounds.Item1.Y;
  94. update.MaxX = bounds.Item2.X;
  95. update.MaxY = bounds.Item2.Y;
  96. var geometry =
  97. Serialization.Deserialize<Dictionary<string, List<PointF>>>(update.Geometry) ?? new Dictionary<string, List<PointF>>();
  98. geometry[id] = record.Geometry.Points();
  99. update.Geometry = Serialization.Serialize(geometry);
  100. if (!updates.Contains(update) && (update.ID == Guid.Empty || update.IsChanged()))
  101. updates.Add(update);
  102. }
  103. if (updates.Any())
  104. Client.Save(updates, $"Loaded from {Path.GetFileName(ofd.FileName)}");
  105. }
  106. }
  107. });
  108. }
  109. return true;
  110. }
  111. }