Đơn vị của thuộc tính chiều dài hình là gì?


11

Tôi đang thực hiện một phép tính rất đơn giản về độ dài của một đa tuyến bằng cách sử dụng hình dạng:

from shapely.geometry import LineString
... 
xy_list = [map(float,e) for e in xy_intm]
line = LineString(xy_list)
s = '%s,%s,%s' % (fr,to,line.length)

Tọa độ của tôi là trong WGS84. Tôi dường như không thể tìm thấy bất kỳ thông tin nào về thuộc tính độ dài của shapely. Đơn vị của thuộc tính chiều dài là gì? Có một cách dễ dàng để chuyển đổi sang km hoặc mét?


Bạn có thể cung cấp tọa độ và chiều dài cho hai hình dạng mẫu?
Vince

Câu trả lời:


13

Như alfaciano nói một cách dễ hiểu, khoảng cách là Khoảng cách Euclide hoặc Khoảng cách tuyến tính giữa hai điểm trên một mặt phẳng và không phải là khoảng cách Vòng tròn lớn giữa hai điểm trên một mặt cầu.

from shapely.geometry import Point
import math


point1 = Point(50.67,4.62)
point2 = Point(51.67, 4.64)

# Euclidean Distance
def Euclidean_distance(point1,point2):
     return math.sqrt((point2.x()-point1.x())**2 + (point2.y()-point1.y())**2)

print Euclidean_distance(point1,point2)
1.00019998 # distance in degrees (coordinates of the points in degrees)

# with Shapely
print point1.distance(point2)
1.0001999800039989 #distance in degrees (coordinates of the points in degrees)

Đối với khoảng cách vòng tròn lớn, bạn cần sử dụng thuật toán làm định luật cosin hoặc công thức Haversine (xem tại sao luật cosin thích hợp hơn haversine khi tính khoảng cách giữa hai điểm kinh độ vĩ độ? ) Hoặc sử dụng mô-đun pyproj mà thực hiện tính toán trắc địa.

# law of cosines
distance = math.acos(math.sin(math.radians(point1.y))*math.sin(math.radians(point2.y))+math.cos(math.radians(point1.y))*math.cos(math.radians(point2.y))*math.cos(math.radians(point2.x)-math.radians(point1.x)))*6371
print "{0:8.4f}".format(distance)
110.8544 # in km
# Haversine formula
dLat = math.radians(point2.y) - math.radians(point1.y)
dLon = math.radians(point2.x) - math.radians(point1.x)
a = math.sin(dLat/2) * math.sin(dLat/2) + math.cos(math.radians(point1.y)) * math.cos(math.radians(point2.y)) * math.sin(dLon/2) * math.sin(dLon/2)
distance = 6371 * 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
print "{0:8.4f}".format(distance)distance
110.8544 #in km

# with pyproj
import pyproj
geod = pyproj.Geod(ellps='WGS84')
angle1,angle2,distance = geod.inv(point1.x, point1.y, point2.x, point2.y)
print "{0:8.4f}".format(distance/1000)
110.9807 #in km

Bạn có thể kiểm tra kết quả tại Máy tính Khoảng cách Vĩ độ

nhập mô tả hình ảnh ở đây


Câu trả lời tuyệt vời, Gene! Rất cám ơn lời giải thích rất chi tiết của bạn.
Antonio Falciano

1
Thật vậy, câu trả lời tuyệt vời. Nếu tôi không nhầm thì có một gói trăn khác được gọi là geopyđã thực hiện một khoảng cách vòng tròn lớn và tính toán khoảng cách Vincenty.
LarsVegas

Dưới đây là một số chi tiết về tính toán khoảng cách trắc địa với geopy.
Antonio Falciano

13

Hệ thống tọa độ

[...] Shapely không hỗ trợ chuyển đổi hệ tọa độ. Tất cả các hoạt động trên hai hoặc nhiều tính năng đều cho rằng các tính năng tồn tại trong cùng mặt phẳng Cartesian.

Nguồn: http://toblerity.org/shapely/manual.html#coordine-systems

shapelyhoàn toàn thuyết bất khả tri trong tham chiếu đến SRS, nó khá rõ ràng rằng thuộc tính chiều dài được thể hiện trong cùng một đơn vị tọa độ của chuỗi đường của bạn, tức là độ. Trong thực tế:

>>> from shapely.geometry import LineString
>>> line = LineString([(0, 0), (1, 1)])
>>> line.length
1.4142135623730951

Thay vào đó, nếu bạn muốn thể hiện độ dài tính bằng mét, bạn phải chuyển đổi hình học của mình từ WGS84 sang SRS được chiếu bằng pyproj (hoặc, tốt hơn, thực hiện phép tính khoảng cách trắc địa, xem câu trả lời của Gene). Cụ thể, kể từ phiên bản 1.2.18 ( shapely.__version__), shapelyhỗ trợ các hàm biến đổi hình học ( http://toblerity.org/shapely/shapely.html#module-shapely.ops ) mà chúng ta có thể sử dụng kết hợp với nó pyproj. Đây là một ví dụ nhanh:

from shapely.geometry import LineString
from shapely.ops import transform
from functools import partial
import pyproj

line1 = LineString([(15.799406, 40.636069), (15.810173,40.640246)])
print str(line1.length) + " degrees"
# 0.0115488362184 degrees

# Geometry transform function based on pyproj.transform
project = partial(
    pyproj.transform,
    pyproj.Proj(init='EPSG:4326'),
    pyproj.Proj(init='EPSG:32633'))

line2 = transform(project, line1)
print str(line2.length) + " meters"
# 1021.77585965 meters
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.