## ADDED Requirements ### Requirement: Ellipsoid definition The system SHALL provide a way to define an ellipsoid from semi-major and semi-minor axes, deriving flattening and eccentricity automatically. #### Scenario: Define WGS84 ellipsoid - **WHEN** `defineEllipsoid(6378137, 6356752.314245)` is called - **THEN** the returned `Ellipsoid` has `semiMajorAxis = 6378137`, `semiMinorAxis = 6356752.314245`, and derived `flattening` and `eccentricity` within floating-point tolerance ### Requirement: Spherical coordinate conversion The system SHALL convert between spherical coordinates (latitude, longitude, altitude) and Cartesian vectors. #### Scenario: Convert spherical to Cartesian and back - **WHEN** a `SphericalCoord` with `latitude = 51.5074`, `longitude = -0.1278`, `altitude = 0` is converted to Cartesian via `sphericalToCartesian` using a WGS84 ellipsoid - **THEN** converting the result back via `cartesianToSpherical` yields the original coordinates within `0.0001` degrees ### Requirement: Great-circle distance The system SHALL compute great-circle distance between two spherical coordinates on a given ellipsoid. #### Scenario: Distance between London and Paris - **WHEN** `greatCircleDistance` is called with London (`51.5074, -0.1278`) and Paris (`48.8566, 2.3522`) on WGS84 - **THEN** the result is approximately `344000` metres ### Requirement: Vincenty distance The system SHALL compute geodesic distance using Vincenty's formulae for high precision. #### Scenario: Vincenty vs great-circle consistency - **WHEN** both `greatCircleDistance` and `vincentyDistance` are called for the same nearby points (< 100 km) - **THEN** the results differ by less than `0.1%` ### Requirement: Bearing and destination The system SHALL compute initial bearing between two points and compute a destination point given start, bearing, and distance. #### Scenario: Round-trip destination - **WHEN** `destination(start, bearing, distance, ellipsoid)` is called - **AND** `bearing` is computed from `start` to a known `end` - **THEN** the computed destination equals `end` within `0.0001` degrees ### Requirement: Bounding boxes The system SHALL provide bounding box creation, point containment, expansion, merging, and intersection. #### Scenario: Box contains point - **WHEN** a `BoundingBox` spanning `(-10, -10)` to `(10, 10)` is created - **THEN** `containsPoint(box, { latitude: 0, longitude: 0 })` returns `true` - **AND** `containsPoint(box, { latitude: 20, longitude: 0 })` returns `false` ### Requirement: Polygon operations The system SHALL provide point-in-polygon, polygon area, perimeter, and simplification. #### Scenario: Point inside a square polygon - **WHEN** a square polygon with vertices at `(0,0)`, `(0,10)`, `(10,10)`, `(10,0)` is defined - **THEN** `pointInPolygon({ latitude: 5, longitude: 5 }, polygon)` returns `true` - **AND** `pointInPolygon({ latitude: 15, longitude: 5 }, polygon)` returns `false` ### Requirement: Distance unit conversion The system SHALL convert distances between metres, kilometres, miles, and nautical miles. #### Scenario: Convert metres to kilometres - **WHEN** `convertDistance(1000, 'metre', 'kilometre')` is called - **THEN** the result equals `1` ### Requirement: No planet-specific constants The system SHALL NOT export any numeric constant for a specific celestial body. #### Scenario: Inspect geo exports - **WHEN** all exports from `@suaveplan/geo` are enumerated - **THEN** no export named `EARTH`, `MARS`, `MOON`, or similar exists - **AND** no hardcoded radius, mass, or orbital value for any body is present