Quels outils en Python sont disponibles pour créer une grande distance cercle + ligne?

20

J'ai besoin d'utiliser Python pour créer une grande distance circulaire - à la fois un nombre et de préférence une sorte de `` courbe '' que je peux utiliser pour dessiner une carte côté client. Je ne me soucie pas du format de la courbe - que ce soit WKT ou un ensemble de paires de coordonnées - mais je veux juste sortir les données.

Quels outils existe-t-il? Que dois-je utiliser?

Christopher Schmidt
la source

Réponses:

8

Les réponses fournies par d'autres sont un peu plus élégantes, mais voici un morceau de Python ultra simple, quelque peu antipythonique, qui fournit les bases. La fonction prend deux paires de coordonnées et un nombre de segments spécifié par l'utilisateur. Il donne un ensemble de points intermédiaires le long d'un grand cercle. Sortie: texte prêt à être écrit en KML. Mises en garde: Le code ne considère pas les antipodes et suppose une terre sphérique.

Code par Alan Glennon http://enj.com juillet 2010 (l'auteur place ce code dans le domaine public. À vos risques et périls).

-

def tweensegs (longitude1, latitude1, longitude2, latitude2, num_of_segments):

import math

ptlon1 = longitude1
ptlat1 = latitude1
ptlon2 = longitude2
ptlat2 = latitude2

numberofsegments = num_of_segments
onelessthansegments = numberofsegments - 1
fractionalincrement = (1.0/onelessthansegments)

ptlon1_radians = math.radians(ptlon1)
ptlat1_radians = math.radians(ptlat1)
ptlon2_radians = math.radians(ptlon2)
ptlat2_radians = math.radians(ptlat2)

distance_radians=2*math.asin(math.sqrt(math.pow((math.sin((ptlat1_radians-ptlat2_radians)/2)),2) + math.cos(ptlat1_radians)*math.cos(ptlat2_radians)*math.pow((math.sin((ptlon1_radians-ptlon2_radians)/2)),2)))
# 6371.009 represents the mean radius of the earth
# shortest path distance
distance_km = 6371.009 * distance_radians

mylats = []
mylons = []

# write the starting coordinates
mylats.append([])
mylons.append([])
mylats[0] = ptlat1
mylons[0] = ptlon1 

f = fractionalincrement
icounter = 1
while (icounter <  onelessthansegments):
        icountmin1 = icounter - 1
        mylats.append([])
        mylons.append([])
        # f is expressed as a fraction along the route from point 1 to point 2
        A=math.sin((1-f)*distance_radians)/math.sin(distance_radians)
        B=math.sin(f*distance_radians)/math.sin(distance_radians)
        x = A*math.cos(ptlat1_radians)*math.cos(ptlon1_radians) + B*math.cos(ptlat2_radians)*math.cos(ptlon2_radians)
        y = A*math.cos(ptlat1_radians)*math.sin(ptlon1_radians) +  B*math.cos(ptlat2_radians)*math.sin(ptlon2_radians)
        z = A*math.sin(ptlat1_radians) + B*math.sin(ptlat2_radians)
        newlat=math.atan2(z,math.sqrt(math.pow(x,2)+math.pow(y,2)))
        newlon=math.atan2(y,x)
        newlat_degrees = math.degrees(newlat)
        newlon_degrees = math.degrees(newlon)
        mylats[icounter] = newlat_degrees
        mylons[icounter] = newlon_degrees
        icounter += 1
        f = f + fractionalincrement

# write the ending coordinates
mylats.append([])
mylons.append([])
mylats[onelessthansegments] = ptlat2
mylons[onelessthansegments] = ptlon2

# Now, the array mylats[] and mylons[] have the coordinate pairs for intermediate points along the geodesic
# My mylat[0],mylat[0] and mylat[num_of_segments-1],mylat[num_of_segments-1] are the geodesic end points

# write a kml of the results
zipcounter = 0
kmlheader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http://www.opengis.net/kml/2.2\"><Document><name>LineString.kml</name><open>1</open><Placemark><name>unextruded</name><LineString><extrude>1</extrude><tessellate>1</tessellate><coordinates>"
print kmlheader
while (zipcounter < numberofsegments):
        outputstuff = repr(mylons[zipcounter]) + "," + repr(mylats[zipcounter]) + ",0 "
        print outputstuff
        zipcounter += 1
kmlfooter = "</coordinates></LineString></Placemark></Document></kml>"
print kmlfooter
glennon
la source
8

GeographicLib possède une interface python :

Cela peut calculer des géodésiques sur un ellipsoïde (mettre l'aplatissement à zéro pour obtenir de grands cercles) et générer des points intermédiaires sur une géodésique (voir les commandes "Ligne" dans l'exemple).

Voici comment imprimer des points sur la ligne géodésique de JFK à l'aéroport de Changi (Singapour):

from geographiclib.geodesic import Geodesic
geod = Geodesic.WGS84

g = geod.Inverse(40.6, -73.8, 1.4, 104)
l = geod.Line(g['lat1'], g['lon1'], g['azi1'])
num = 15  # 15 intermediate steps

for i in range(num+1):
    pos = l.Position(i * g['s12'] / num)
    print(pos['lat2'], pos['lon2'])

->
(40.60, -73.8)
(49.78, -72.99)
(58.95, -71.81)
(68.09, -69.76)
(77.15, -65.01)
(85.76, -40.31)
(83.77, 80.76)
(74.92, 94.85)
...
cffk
la source
Le port python de GeographicLib est maintenant disponible sur pypi.python.org/pypi/geographiclib
cffk
Voir aussi cet article: CFF Karney, Algorithms for Geodesics, J. Geod, DOI: dx.doi.org/10.1007/s00190-012-0578-z
cffk
7

pyproj a la fonction Geod.npts qui retournera un tableau de points le long du chemin. Notez qu'il n'inclut pas les points terminaux dans le tableau, vous devez donc les prendre en compte:

import pyproj
# calculate distance between points
g = pyproj.Geod(ellps='WGS84')
(az12, az21, dist) = g.inv(startlong, startlat, endlong, endlat)

# calculate line string along path with segments <= 1 km
lonlats = g.npts(startlong, startlat, endlong, endlat,
                 1 + int(dist / 1000))

# npts doesn't include start/end points, so prepend/append them
lonlats.insert(0, (startlong, startlat))
lonlats.append((endlong, endlat))
scruss
la source
Merci! Solution fournie par une bibliothèque bien connue et massivement utilisée ici :)
tdihp
-2

Je n'ai pas utilisé ce package, mais il semble intéressant, et une solution possible: http://trac.gispython.org/lab/wiki/Shapely

Hugo Estrada
la source
7
AFAIK, galbé ne fait pas de calculs sphéroïdaux:Shapely is a Python package for set-theoretic analysis and manipulation of **planar** features
fmark