Mencari cara pythonic untuk menghitung panjang linestring WKT

13

Saya cukup tidak puas dengan Menghitung Panjang Linestrings di WGS84 di Miles . Itu membuat saya bertanya-tanya apakah ada cara Pythonic yang lebih nyaman untuk menghitung panjang linestring WKT menurut SRID yang diberikan.

Ada dalam pikiran saya sesuatu seperti:

srid="WGS84"
line="LINESTRING(3.0 4.0, 3.1 4.1)"
print length(line, srid)

Saya mencari jawaban yang akurat, bukan sin\cosperkiraan.

Ada ide?

Adam Matan
sumber
tomkralidis, ini adalah situs web GIS. jawaban Anda mengabaikan bahwa ini adalah jarak antara koordinat geospasial (lihat SRID). bentuk itu sendiri tidak dapat menghitung jarak geospasial karena tidak memiliki pengetahuan tentang proyeksi peta.

Jawaban:

18

The geopy modul menyediakan rumus Vincenty , yang menyediakan jarak ellipsoid akurat. Sandingkan ini dengan wktpemuatan di Shapely, dan Anda memiliki kode yang cukup sederhana:

from geopy import distance
from shapely.wkt import loads

line_wkt="LINESTRING(3.0 4.0, 3.1 4.1)"

# a number of other elipsoids are supported
distance.VincentyDistance.ELLIPSOID = 'WGS-84'
d = distance.distance

line = loads(line_wkt)

# convert the coordinates to xy array elements, compute the distance
dist = d(line.xy[0], line.xy[1])

print dist.meters
scw
sumber
1
+1, akan memiliki +10 jika saya bisa. Menyimpan jam pemrograman tim saya.
Adam Matan
Apakah pendekatan ini berbeda dari jawaban @tomkralidis jika koordinat input sudah dalam WGS-84?
LarsVegas
1
@ LarsVegas ya, Shapely hanya menangani koordinat planar - sehingga ia akan mengukur jarak secara akurat di ruang yang diproyeksikan, tetapi tidak secara geografis (mis. WGS-1984).
scw
4

Anda juga bisa menggunakan properti panjang Shapely , yaitu:

from shapely.wkt import loads

l=loads('LINESTRING(3.0 4.0, 3.1 4.1)')
print l.length
tomkralidis
sumber
Perhatikan bahwa panjang untuk contoh khusus ini tidak akan berarti, karena merupakan sistem koordinat geografis (WGS84).
Mike T
2

Terlambat ke pesta, tapi dengan kontribusi semoga bermanfaat. Membangun jawaban scw menggunakan geopy, saya menulis sebuah fungsi kecil yang melakukan perhitungan untuk objek LineString yang indah dengan banyak koordinat sembarang. Ini menggunakan pairsiterator dari Stackoverflow.

Fitur utama: dokumen jauh lebih panjang dari potongan.

def line_length(line):
    """Calculate length of a line in meters, given in geographic coordinates.
    Args:
        line: a shapely LineString object with WGS 84 coordinates
    Returns:
        Length of line in meters
    """
    # Swap shapely (lonlat) to geopy (latlon) points
    latlon = lambda lonlat: (lonlat[1], lonlat[0])
    total_length = sum(distance(latlon(a), latlon(b)).meters
                       for (a, b) in pairs(line.coords))
    return round(total_length, 0)


def pairs(lst):
    """Iterate over a list in overlapping pairs without wrap-around.

    Args:
        lst: an iterable/list

    Returns:
        Yields a pair of consecutive elements (lst[k], lst[k+1]) of lst. Last 
        call yields the last two elements.

    Example:
        lst = [4, 7, 11, 2]
        pairs(lst) yields (4, 7), (7, 11), (11, 2)

    Source:
        /programming/1257413/1257446#1257446
    """
    i = iter(lst)
    prev = i.next()
    for item in i:
        yield prev, item
        prev = item
ojdo
sumber
1
Ini salah: geopy.distance.distance menerima koordinat dalam (y, x) tetapi linestring yang indah adalah "urutan berurutan 2 atau lebih (x, y [, z])" sehingga fungsi helper geografi lonlat () harus digunakan .
Martin Burch
@ MartinBurch: aduh, kau benar. Hal jahat bahkan bukan [, z], tapi argumen pertukaran (y, x)untuk (x, y)yang diperlukan. Terima kasih telah melihatnya. Bisakah Anda melihat apakah pengeditan ini terlihat tidak terlalu bug?
ojdo