Python'da büyük daire mesafesi + çizgi oluşturma için hangi araçlar mevcuttur?


20

Python büyük bir daire mesafe oluşturmak için kullanmalıyım - hem bir sayı hem de tercihen bir istemci tarafı harita çizmek için kullanabileceğiniz bir tür 'eğri'. Eğrinin formatını umursamıyorum - ister WKT ister bir çift koordinat seti olsun - ama sadece verileri çıkarmak istiyorum.

Orada hangi araçlar var? Ne kullanmalıyım?

Yanıtlar:



8

Başkaları tarafından verilen cevaplar biraz daha zarif, ama burada temelleri sağlayan ultra basit, biraz unpythonic, biraz Python. İşlev iki koordinat çifti ve kullanıcı tarafından belirlenen sayıda segment alır. Harika bir daire yolu boyunca bir dizi ara nokta verir. Çıktı: KML olarak yazmaya hazır metin. Uyarılar: Kod antipodları dikkate almaz ve küresel bir dünya varsayar.

Alan Glennon'un kodu http://enj.com Temmuz 2010 (yazar bu kodu herkese açık alana yerleştirir. Kendi sorumluluğunuzdadır kullanın).

-

def tweensegs (boylam1, enlem1, boylam2, enlem2, sayı_sayısı):

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

8

GeographicLib bir python arayüzüne sahiptir :

Bu, bir elipsoid üzerindeki bilgisayar jeodeziklerini (büyük daireler elde etmek için düzleştirmeyi sıfıra ayarlayabilir) ve bir jeodezik üzerinde ara noktalar oluşturabilir (örnekteki "Çizgi" komutlarına bakın).

JFK'dan Changi Havalimanı'na (Singapur) jeodezik hattaki noktaları nasıl yazdıracağınız aşağıda açıklanmıştır:

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)
...

GeographicLib'in python bağlantı noktası şimdi pypi.python.org/pypi/geographiclib
cffk

Ayrıca bu makaleye bakınız: CFF Karney, Jeodezikler için Algoritmalar, J. Geod, DOI: dx.doi.org/10.1007/s00190-012-0578-z
cffk

7

pyproj , yol boyunca bir dizi nokta döndürecek Geod.npts işlevine sahiptir. Dizideki terminal noktalarını içermediğini unutmayın, bu nedenle bunları dikkate almanız gerekir:

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))

Teşekkürler! Burada iyi bilinen ve çok kullanılan bir kütüphane tarafından sağlanan çözüm :)
tdihp


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.