Tìm kiếm một cách pythonic để tính chiều dài của một dòng dõi WKT


13

Tôi đã khá hài lòng với Tính Chiều dài LineStrings trong WGS84 trong Miles . Nó khiến tôi băn khoăn liệu có cách nào thuận tiện hơn, Pythonic để tính toán độ dài của một dòng WKT theo một SRID nhất định.

Tôi có ý nghĩ gì đó như:

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

Tôi đang tìm kiếm một câu trả lời chính xác, không phải là sin\cosxấp xỉ.

Có ý kiến ​​gì không?


Tomkralidis, đây là một trang web GIS. câu trả lời của bạn bỏ qua rằng đây là khoảng cách giữa các tọa độ không gian địa lý (tra cứu SRID). Bản thân nó không thể tính toán khoảng cách không gian địa lý vì nó không có kiến ​​thức về phép chiếu bản đồ.

Câu trả lời:


18

Các geopy mô-đun cung cấp các công thức Vincenty , cung cấp khoảng cách ellipsoid chính xác. Kết hợp điều này với wkttải trong Shapely và bạn có mã đơn giản hợp lý:

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, sẽ có +10 nếu tôi có thể. Tiết kiệm hàng giờ nhóm lập trình của tôi.
Adam Matan

Cách tiếp cận này có khác với câu trả lời @tomkralidis nếu tọa độ đầu vào đã có trong WGS-84 không?
LarsVegas

1
@LarsVegas có, Shapely chỉ xử lý tọa độ phẳng - vì vậy nó sẽ đo khoảng cách chính xác trong không gian được chiếu, nhưng không theo địa lý (ví dụ: WGS-1984).
scw 23/12/13

4

Bạn cũng có thể sử dụng thuộc tính độ dài của Shapely , tức là:

from shapely.wkt import loads

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

Lưu ý rằng độ dài cho ví dụ cụ thể này sẽ là vô nghĩa, vì nó là một hệ tọa độ địa lý (WGS84).
Mike T


2

Đến bữa tiệc muộn, nhưng với một đóng góp hy vọng hữu ích. Dựa trên câu trả lời của scw bằng cách sử dụng geopy, tôi đã viết một hàm nhỏ thực hiện phép tính cho một đối tượng LineString có hình dạng với nhiều tọa độ tùy ý. Nó sử dụng một pairstrình vòng lặp từ Stackoverflow.

Tính năng chính: các tài liệu dài hơn nhiều so với đoạn trích.

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
Điều này là sai: geopy.distance.distance chấp nhận tọa độ trong (y, x) nhưng một dòng có hình dạng là "một chuỗi có thứ tự từ 2 trở lên (x, y [, z])" vì vậy phải sử dụng hàm trợ giúp của geopy lonlat () .
Martin Burch

@MartinBurch: ouch, bạn nói đúng. Điều khó chịu thậm chí không phải là [, z], nhưng việc trao đổi đối số (y, x)thành (x, y)điều đó là cần thiết. Cảm ơn vì đã phát hiện ra nó. Bạn có thể cầu mắt xem bản chỉnh sửa này có vẻ ít lỗi hơn không?
ojdo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.