Files
Oleksandr Bezdieniezhnykh b0fffa6d42 [AZ-284] Autodev baseline + testability refactor
Phase A baseline outputs from /autodev (Steps 1-5):
- Problem & solution docs (_docs/00_problem, _docs/01_solution)
- Codebase documentation (_docs/02_document) incl. architecture,
  module-layout, glossary, system-flows, baseline compliance scan
- Test specs (blackbox, performance, resilience, security, resource,
  traceability matrix)
- Test task decomposition (_docs/02_tasks/todo): AZ-285..AZ-290
- Testability refactor (_docs/04_refactoring/01-testability-refactoring):
  - TC-01 Move DownloadedTileInfoV2 + new ExistingTileInfo to Common.DTO
  - TC-02 Replace dead ISatelliteDownloader API with real signatures
  - TC-03 GoogleMapsDownloaderV2 implements ISatelliteDownloader
  - TC-04 TileService depends on ISatelliteDownloader (mockable)
  - TC-05 DI + endpoints use ISatelliteDownloader
- Test runner scripts (scripts/run-tests.sh, run-performance-tests.sh)
- Autodev state pointer (_docs/_autodev_state.md)

Prepares the codebase for AZ-285..AZ-290 unit/integration test work.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 04:44:08 +03:00

2.6 KiB

Module: Common/Utils/GeoUtils

Purpose

Static geographic computation utilities: coordinate conversions, distance calculations (Haversine), bearing computation, point interpolation, and bounding box calculation.

Public Interface

All methods are static on GeoUtils:

  • WorldToTilePos(GeoPoint point, int zoom) → (int x, int y): converts lat/lon to slippy map tile coordinates at given zoom
  • TileToWorldPos(int x, int y, int zoom) → GeoPoint: converts tile coordinates back to lat/lon (NW corner of tile)
  • ToRadians(double degrees) → double
  • ToDegrees(double radians) → double
  • DirectionTo(this GeoPoint p1, GeoPoint p2) → Direction (extension method): Haversine distance + forward azimuth between two points
  • GoDirection(this GeoPoint startPoint, Direction direction) → GeoPoint (extension method): destination point given start + bearing + distance
  • GetBoundingBox(GeoPoint center, double radiusM) → (minLat, maxLat, minLon, maxLon): axis-aligned bounding box around a center point
  • CalculateIntermediatePoints(GeoPoint start, GeoPoint end, double maxSpacingMeters) → List<GeoPoint>: generates evenly-spaced points along a great-circle path (returns empty if distance ≤ maxSpacing)
  • CalculateDistance(GeoPoint p1, GeoPoint p2) → double: convenience wrapper around DirectionTo().Distance
  • CalculateCenter(GeoPoint northWest, GeoPoint southEast) → GeoPoint: simple midpoint
  • CalculatePolygonDiagonalDistance(GeoPoint northWest, GeoPoint southEast) → double: diagonal distance of a bounding box

Internal Logic

  • Earth radius constant: 6378137 meters (WGS-84 semi-major axis)
  • Distance calculation uses the Haversine formula
  • Bearing uses atan2 of longitude/latitude components
  • CalculateIntermediatePoints divides the segment into equal sub-segments, each ≤ maxSpacingMeters
  • Tile conversion follows the standard Web Mercator / slippy map tile numbering scheme

Dependencies

  • SatelliteProvider.Common.DTO.GeoPoint
  • SatelliteProvider.Common.DTO.Direction

Consumers

  • GoogleMapsDownloaderV2WorldToTilePos, TileToWorldPos, GetBoundingBox
  • TileService — indirectly via downloader
  • RegionServiceWorldToTilePos for tile stitching
  • RouteServiceCalculateIntermediatePoints, CalculateDistance
  • RouteProcessingServiceWorldToTilePos for map stitching
  • SatTile constructor — TileToWorldPos
  • Program.cs (ServeTile handler) — TileToWorldPos

Data Models

None.

Configuration

None.

External Integrations

None (pure math).

Security

None.

Tests

No dedicated unit tests for GeoUtils.