Metadata-Version: 2.4
Name: distance_engine
Version: 0.1.0
Summary: Zero-dependency theoretical air distance calculations using Haversine and Vincenty.
Author: Jarvis
License-Expression: MIT
Keywords: distance,geodesy,aviation,haversine,vincenty
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# distance_engine

`distance_engine` is a production-oriented Python package for computing the theoretical geometric air distance between two coordinate points. It is designed for airport-to-airport distance use cases where your service layer already knows the coordinates and needs a clean, typed, zero-runtime-dependency engine.

This package calculates theoretical geometric distance only.

- It is not actual flown distance.
- It is not airline mileage-credit distance.
- It is not fare, routing, or frequent-flyer program logic.

## Supported Methods

### Haversine

Haversine treats the Earth as a sphere and uses the mean Earth radius. It is fast, simple, and useful when you want a solid approximation with minimal computational cost.

### Vincenty (inverse)

Vincenty uses an ellipsoidal Earth model and is more appropriate when theoretical airport-to-airport distance should be closer to the WGS-84 reference ellipsoid. This package uses WGS-84 by default.

Vincenty is iterative and can fail to converge for some extreme pairs, especially near-antipodal points. In that case, the package can either:

- raise `VincentyDidNotConvergeError`, or
- fall back to Haversine when `fallback_to_haversine=True`

When fallback is used, the returned result has:

- `method="vincenty_fallback_haversine"`
- `converged=False`
- `ellipsoid=None`

## Why No Third-Party Runtime Dependencies

`distance_engine` intentionally keeps runtime dependencies empty.

- Easier to audit
- Easier to vendor or embed
- Easier to integrate into backend services and scripts
- Lower long-term maintenance cost
- No dependency on heavyweight geospatial libraries when you only need these two formulas

Build and release tools such as `build` and `twine` are optional developer tooling only. They are not runtime dependencies of the package.

## Installation

### Local development install

```bash
python3.12 -m pip install -e .
```

### Future PyPI install

```bash
python3.12 -m pip install distance_engine
```

## Quick Start

### Python API

```python
from distance_engine import Point, distance, haversine_distance, vincenty_distance

origin = Point(1.35, 103.99)
destination = Point(51.47, -0.45)

result = distance(origin, destination)
print(result.kilometers)
print(result.miles)
print(result.nautical_miles)
print(result.initial_bearing_deg)
print(result.final_bearing_deg)

fast_result = haversine_distance(origin, destination)
precise_result = vincenty_distance(origin, destination)
```

### Tuple inputs

```python
from distance_engine import distance

result = distance((1.35, 103.99), (51.47, -0.45), method="haversine")
print(result.kilometers)
```

### Keyword coordinate inputs

```python
from distance_engine import distance

result = distance(
    lat1=1.35,
    lon1=103.99,
    lat2=51.47,
    lon2=-0.45,
    method="vincenty",
)
print(result.meters)
```

## CLI

Run the module directly:

```bash
python3.12 -m distance_engine \
  --lat1 1.35 \
  --lon1 103.99 \
  --lat2 51.47 \
  --lon2 -0.45 \
  --method vincenty
```

JSON output:

```bash
python3.12 -m distance_engine \
  --lat1 1.35 \
  --lon1 103.99 \
  --lat2 51.47 \
  --lon2 -0.45 \
  --method vincenty \
  --json
```

Fallback example:

```bash
python3.12 -m distance_engine \
  --lat1 0.0 \
  --lon1 0.0 \
  --lat2 0.5 \
  --lon2 179.7 \
  --method vincenty \
  --fallback-to-haversine
```

## Input And Output

Inputs are decimal-degree coordinates.

- Latitude must be within `[-90, 90]`
- Longitude is normalized into `[-180, 180]`

Returned `DistanceResult` contains:

- `meters`
- `kilometers`
- `miles`
- `nautical_miles`
- `method`
- `ellipsoid`
- `converged`
- `initial_bearing_deg`
- `final_bearing_deg`

## Limitations

- Theoretical geometric distance is not actual flown distance.
- Theoretical geometric distance is not frequent-flyer credited mileage.
- Haversine is a spherical approximation.
- Vincenty can fail to converge for some extreme point pairs.
- This package does not resolve airport codes or consult airport databases.
- This package does not model route restrictions, winds, ATC deviations, SID/STAR, or airway structure.

## Method Notes

Haversine computes the great-circle distance on a sphere using the mean Earth radius. It is appropriate when speed and simplicity matter more than ellipsoidal precision.

Vincenty inverse solves the geodesic distance on an ellipsoid iteratively. In this package it uses WGS-84 by default, which is often a better fit for airport-to-airport theoretical distance.

## Development

Run tests:

```bash
python3.12 -m unittest discover -s tests -v
```

Editable install:

```bash
python3.12 -m pip install -e .
```

## Build And Release

Install build tooling:

```bash
python3.12 -m pip install build twine
```

Build source and wheel distributions:

```bash
python3.12 -m build
```

Check the built distributions:

```bash
python3.12 -m twine check dist/*
```

Upload to TestPyPI:

```bash
python3.12 -m twine upload --repository testpypi dist/*
```

Upload to PyPI:

```bash
python3.12 -m twine upload dist/*
```

## Intended Integration Model

This package is the core distance engine only. A later business layer can sit on top of it to map airport codes to coordinates and then apply airline-specific rules, fare logic, or loyalty program behavior.
