# Entfernung

Entfernung und Kurswinkel integrieren — Großkreisberechnungen zwischen Flughäfen oder Koordinaten.



Lauffähige Beispiele für Berechnungen der [Großkreisentfernung](https://en.wikipedia.org/wiki/Great-circle_distance) mit dem Endpoint [Entfernung](/docs/v31/distance). Behandelt werden Messungen einzelner Routen und Vergleiche mehrerer Routen für die Netzplanung.

| # | Frage                                                                       | Verwendete Daten |
| - | --------------------------------------------------------------------------- | ---------------- |
| 1 | Großkreisentfernung zwischen zwei Flughäfen für die Routenplanung           | Entfernung       |
| 2 | Entfernungsvergleich mehrerer Routen: Routen ab EGLL nach Entfernung ordnen | Entfernung       |

<DocRequirements>
  <DocRequirementAuth />
</DocRequirements>

### Installation [#install]

Die folgenden Skripte verwenden `requests` für API-Aufrufe und `rich` für die Terminalausgabe. Einmalig installieren:

```bash
pip install requests rich
```

***

### 1. Routenentfernung zwischen zwei Flughäfen [#1-route-distance-between-two-airports]

**Frage:** Wie groß ist die [Großkreisentfernung](https://en.wikipedia.org/wiki/Great-circle_distance) zwischen KJFK und KLAX, und wie lautet der Anfangskurs?

```python
import os

import requests
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_distance(from_icao: str, to_icao: str) -> dict | None:
    r = requests.get(
        f"{BASE}/distance",
        headers=HEADERS,
        params={"from_icao": from_icao, "to_icao": to_icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def main() -> None:
    data = fetch_distance("KJFK", "KLAX")
    if not data:
        console.print("[yellow]No distance data returned.[/]")
        return

    table = Table(title="Route Distance")
    table.add_column("Field", style="cyan", min_width=22)
    table.add_column("Value")

    table.add_row("Origin", data.get("from_airport_name", data.get("from_icao", "—")))
    table.add_row("Destination", data.get("to_airport_name", data.get("to_icao", "—")))
    table.add_row("Distance (nm)", f"{data.get('distance_nm', '—')} nm")
    table.add_row("Distance (km)", f"{data.get('distance_km', '—')} km")
    table.add_row("Distance (mi)", f"{data.get('distance_mi', '—')} mi")
    table.add_row("Initial bearing", f"{data.get('bearing_deg', '—')}° true")

    console.print(table)
    console.print(Panel(
        "Distance shown is great-circle (shortest path on a sphere). "
        "Actual filed routes are typically longer due to airways, wind routing, and restricted airspace.",
        title="Note",
        style="dim",
    ))


if __name__ == "__main__":
    main()
```

**Ausgabe:** Eine Tabelle mit den Namen von Abflug- und Zielflughafen, der Entfernung in Seemeilen, Kilometern und Landmeilen sowie dem rechtweisenden Anfangskurs. Ein Hinweis stellt klar, dass die [Großkreisentfernung](https://en.wikipedia.org/wiki/Great-circle_distance) von tatsächlich aufgegebenen Flugrouten abweicht.

***

### 2. Entfernungsrangliste mehrerer Routen ab EGLL [#2-multi-route-distance-ranking-from-egll]

**Frage:** Welche von vier Routen ab London Heathrow sind die kürzesten und welche die längsten?

Ruft alle Routen parallel ab und sortiert sie anschließend aufsteigend nach Seemeilen.

```python
import os
import concurrent.futures

import requests
from rich.console import Console
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"

ORIGIN = "EGLL"
DESTINATIONS: list[tuple[str, str]] = [
    ("KJFK", "New York"),
    ("OMDB", "Dubai"),
    ("YSSY", "Sydney"),
    ("RJTT", "Tokyo"),
]


def fetch_distance(from_icao: str, to_icao: str) -> dict | None:
    r = requests.get(
        f"{BASE}/distance",
        headers=HEADERS,
        params={"from_icao": from_icao, "to_icao": to_icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def main() -> None:
    results: list[tuple[str, str, dict]] = []

    with concurrent.futures.ThreadPoolExecutor(max_workers=4) as ex:
        futures = {
            ex.submit(fetch_distance, ORIGIN, icao): (icao, city)
            for icao, city in DESTINATIONS
        }
        for fut, (icao, city) in futures.items():
            data = fut.result()
            if data:
                results.append((icao, city, data))

    results.sort(key=lambda x: x[2].get("distance_nm", float("inf")))

    table = Table(title=f"Routes from {ORIGIN} — sorted by distance")
    table.add_column("Destination", style="cyan")
    table.add_column("City")
    table.add_column("Distance (nm)", justify="right")
    table.add_column("Distance (km)", justify="right")
    table.add_column("Bearing", justify="right")

    for icao, city, data in results:
        table.add_row(
            icao,
            city,
            str(data.get("distance_nm", "—")),
            str(data.get("distance_km", "—")),
            f"{data.get('bearing_deg', '—')}°",
        )

    console.print(table)


if __name__ == "__main__":
    main()
```

**Ausgabe:** Eine Tabelle mit vier Routen ab EGLL, aufsteigend nach Seemeilen sortiert, mit ICAO-Code des Ziels, Stadtname, Entfernung in nm und km sowie Anfangskurs.
