using SatelliteProvider.Common.DTO; using SatelliteProvider.Common.Utils; namespace SatelliteProvider.Services.RouteManagement; public class GeofenceGridCalculator { public IReadOnlyList GenerateRegions(GeoPoint northWest, GeoPoint southEast, double regionSizeMeters) { ArgumentNullException.ThrowIfNull(northWest); ArgumentNullException.ThrowIfNull(southEast); if (regionSizeMeters <= 0) { throw new ArgumentOutOfRangeException(nameof(regionSizeMeters), "Region size must be positive"); } var midLon = (northWest.Lon + southEast.Lon) / 2; var midLat = (northWest.Lat + southEast.Lat) / 2; var heightMeters = GeoUtils.CalculateDistance( new GeoPoint(northWest.Lat, midLon), new GeoPoint(southEast.Lat, midLon)); var widthMeters = GeoUtils.CalculateDistance( new GeoPoint(midLat, northWest.Lon), new GeoPoint(midLat, southEast.Lon)); var numLatSteps = Math.Max(1, (int)Math.Ceiling(heightMeters / regionSizeMeters)); var numLonSteps = Math.Max(1, (int)Math.Ceiling(widthMeters / regionSizeMeters)); var latStep = (northWest.Lat - southEast.Lat) / numLatSteps; var lonStep = (southEast.Lon - northWest.Lon) / numLonSteps; var regions = new List(numLatSteps * numLonSteps); for (int latIdx = 0; latIdx < numLatSteps; latIdx++) { for (int lonIdx = 0; lonIdx < numLonSteps; lonIdx++) { var lat = northWest.Lat - (latIdx + 0.5) * latStep; var lon = northWest.Lon + (lonIdx + 0.5) * lonStep; regions.Add(new GeoPoint(lat, lon)); } } return regions; } }