WKT linestring'in uzunluğunu hesaplamak için pythonic bir yol mu arıyorsunuz?


13

Mil cinsinden WGS84'te Linestring Uzunluklarını Hesaplamaktan oldukça memnun kalmadım . Belirli bir SRID'ye göre bir WKT linestring'in uzunluğunu hesaplamanın daha uygun, Pythonic bir yolu olup olmadığını merak ettim.

Aklımda bir şey var:

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

Yaklaşmalar değil doğru bir cevap arıyorum sin\cos.

Herhangi bir fikir?


tomkralidis, bu bir CBS web sitesidir. cevabınız bunun jeo-uzamsal koordinatlar arasındaki mesafe olduğunu göz ardı eder (SRID'ye bakın). Harita projeksiyonu hakkında bilgisi olmadığı için kendi içinde düzgün bir şekilde jeo-uzamsal mesafeleri hesaplayamaz.

Yanıtlar:


18

Geopy modülü içerir VINCENTY formül doğru elipsoid mesafeler sağlar. Bunu wktShapely'deki yükleme ile birleştirin ve oldukça basit bir kodunuz var:

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

1
+1, yapabilseydim +10 olurdu. Ekibim saatlerce program kaydetti.
Adam Matan

Giriş koordinatları zaten WGS-84 içindeyse, bu yaklaşım @ tomkralidis yanıtından farklı mıdır?
LarsVegas

1
@LarsVegas evet, Shapely yalnızca düzlemsel koordinatları işler - bu nedenle, yansıtılan alandaki mesafeleri doğru bir şekilde ölçer, ancak coğrafi olarak değil (örn. WGS-1984).
scw

4

Ayrıca Shapely'nin length özelliğini de kullanabilirsiniz :

from shapely.wkt import loads

l=loads('LINESTRING(3.0 4.0, 3.1 4.1)')
print l.length

Bu belirli örneğin uzunluğunun, coğrafi bir koordinat sistemi (WGS84) olduğu için anlamsız olacağını unutmayın.
Mike T


2

Partiye geç ama umarım faydalı bir katkı ile. Bina SCW cevabı kullanarak geopy, ben keyfi olarak birçok koordinatlarla bir biçimli LineString nesnesi için hesaplama yapan küçük bir fonksiyon yazdım. pairsStackoverflow bir yineleyici kullanır .

Ana özellik: docstrings snippet'lerden çok daha uzundur.

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

1
Bu yanlış: geopy.distance.distance (y, x) koordinatlarını kabul eder, ancak düzgün bir linestleme "2 veya daha fazla sıralı bir sıra (x, y [, z])" dir, bu nedenle geopy'nin yardımcı işlevi lonlat () kullanılmalıdır .
Martin Burch

@MartinBurch: ah, haklısın. Pis şey bile değil [, z], ama argüman takas (y, x)için (x, y)gereklidir. Tespit ettiğiniz için teşekkürler. Bu düzenlemenin daha az hata yapmış görünüp görünmediğine göz atabilir misiniz?
ojdo
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.