Realizzare grandi archi circolari che sembrano belli sulla mappa di Web Mercator?


11

Sto cercando di creare una mappa, con i dati che indicano alcuni voli e voglio utilizzare Great Circle Arcs, per collegare la sorgente e le destinazioni.

Fondamentalmente, voglio fare qualcosa di simile alla famosa mappa di Facebook: inserisci qui la descrizione dell'immagine

Ho usato le funzioni fornite in questo post: https://gis.stackexchange.com/a/5205/442 , (ovvero questo articolo del blog: http://anitagraser.com/2011/08/20/visualizing-global-connections / ) e potrei ottenere le righe, ma attraversano la International Date Line, oltre che raggrupparsi, ai poli:

inserisci qui la descrizione dell'immagine

@underdark, ha menzionato nel blogpost collegato che queste linee devono essere divise, ma non so come dividerle automaticamente in PostGIS.

Inoltre, è necessario risolvere anche il raggruppamento delle linee vicino ai poli.

Come posso fare entrambi, quando ho le posizioni dei punti per l'inizio e la fine di questi voli?


Potresti usare una proiezione polare?
Ian Turton

2
Ho fornito alcuni esempi qui: gis.stackexchange.com/questions/133026/… . Nota che eqdc non fornisce veri e propri circoli, ma aeqd lo fa.
AndreJ

Risposte:



8

È possibile calcolare la geodetica. Dicendo che vuoi mostrare il geodetico da A a B, potresti prima calcolare la distanza e l'azimut da A a B (problema geodetico inverso) e quindi calcolare i punti da A a diversi punti tra A e B (problema geodetico diretto). Ho aggiunto un semplice script in Python usando GeographicLib semplicemente facendo uscire le cose in GeoJSON:

from geographiclib.geodesic import Geodesic
from geojson import MultiLineString

def geodesic(lat1, lon1, lat2, lon2, steps):
    inverse = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
    linestrings = []
    coordinates = []

    for i in range(0, steps + 1):
        direct = Geodesic.WGS84.Direct(inverse['lat1'], inverse['lon1'], inverse['azi1'], (i / float(steps)) * inverse['s12'])
        if len(coordinates) > 0:
            if (coordinates[-1][0] < -90 and direct['lon2'] > 90) or (coordinates[-1][0] > 90 and direct['lon2'] < -90):
                linestrings.append(coordinates)
                coordinates = []
        coordinates.append((direct['lon2'], direct['lat2']))

    linestrings.append(coordinates)
    geojson = MultiLineString(linestrings)
    return geojson

linestrings = []

# San Francisco: 37.7793, -122.4192
# Bangalore: 12.9, 77.616667
for linestring in geodesic(37.7793, -122.4192, 12.95, 77.616667, 100)['coordinates']:
    linestrings.append(linestring)

# Boston: 42.357778, -71.059444
# Bangalore: 12.9, 77.616667
for linestring in geodesic(42.357778, -71.059444, 12.95, 77.616667, 100)['coordinates']:
    linestrings.append(linestring)

print(MultiLineString(linestrings))

Il risultato è il vero geodetico tra i punti in WGS-84. Naturalmente, puoi quindi trasformare le coordinate in qualsiasi proiezione di cui hai bisogno. Il risultato visualizzato su geojson.io è simile al seguente:

inserisci qui la descrizione dell'immagine


2
Vedi geographiclib.sourceforge.net/html/python/… per un modo alternativo (e più veloce!) Di farlo con GeographicLib. Notare anche l'uso del flag LONG_UNROLL per garantire la continuità delle lunghezze.
Cffk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.