Fazendo grandes arcos circulares que ficam bem no mapa do Web Mercator?

11

Estou tentando criar um mapa, com dados indicando alguns vôos, e quero usar o Great Circle Arcs, para conectar a fonte e os destinos.

Basicamente, eu quero fazer algo semelhante ao famoso mapa do Facebook: insira a descrição da imagem aqui

Eu usei as funções fornecidas neste post: https://gis.stackexchange.com/a/5205/442 , (ou seja, este artigo de blog: http://anitagraser.com/2011/08/20/visualizing-global-connections / ) e eu pude pegar linhas, mas elas cruzam a Linha Internacional de Data, bem como agrupam-se, nos pólos:

insira a descrição da imagem aqui

O @underdark mencionou no blog vinculado que essas linhas precisam ser divididas, mas não sei como dividi-las automaticamente no PostGIS.

Além disso, o agrupamento das linhas próximas aos pólos também precisa ser resolvido.

Como faço para ambos, quando tenho os locais dos pontos para o início e o término desses voos?

Devdatta Tengshe
fonte
Você poderia usar uma projeção polar?
Ian Turton
2
Dei alguns exemplos aqui: gis.stackexchange.com/questions/133026/… . Observe que o eqdc não fornece grandes círculos verdadeiros, mas o aeqd fornece.
21416 AndreJ

Respostas:

5

Os princípios contidos neste post são transferidos para o PostGIS de uso geral.

http://blog.cartodb.com/jets-and-datelines/

Basicamente, use ST_Segmentizena geografia e um pouco de mágica para cortar linhas de cruzamento de linhas de data.

Paul Ramsey
fonte
8

Você pode calcular a geodésica. Dizendo que deseja mostrar a geodésica de A a B, você pode primeiro calcular a distância e o azimute de A a B (problema geodésico inverso) e depois calcular pontos de A a vários pontos entre A e B (problema geodésico direto). Eu adicionei um script simples em Python usando GeographicLib apenas exibindo o material em 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))

O resultado é a verdadeira geodésica entre os pontos no WGS-84. Obviamente, você pode transformar as coordenadas em qualquer projeção necessária. O resultado visualizado no geojson.io se parece com o seguinte:

insira a descrição da imagem aqui

sema
fonte
2
Consulte geographiclib.sourceforge.net/html/python/… para obter uma maneira alternativa (e mais rápida!) De fazer isso com o GeographicLib. Observe também o usado do sinalizador LONG_UNROLL para garantir a continuidade das longitudes.
Cffk 17/03/19