# 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
- `GoogleMapsDownloaderV2` — `WorldToTilePos`, `TileToWorldPos`, `GetBoundingBox`
- `TileService` — indirectly via downloader
- `RegionService` — `WorldToTilePos` for tile stitching
- `RouteService` — `CalculateIntermediatePoints`, `CalculateDistance`
- `RouteProcessingService` — `WorldToTilePos` 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.
