Tôi quay trở lại vấn đề này vì nó rất giống với Làm thế nào để tôi tìm thấy dòng vectơ trong QGIS hoặc GRASS? và nó có thể được giải quyết bằng Python theo cùng một cách:
1) Khoảng cách Haversine
Người ta có thể tìm thấy rất nhiều tập lệnh bằng cách tìm kiếm khoảng cách Haversine với Python trên Internet và tôi chọn một trong số chúng trong Công thức Haversine trong Python (Mang và Khoảng cách giữa hai điểm GPS)
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(math.radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
c = 2 * math.asin(math.sqrt(a))
km = 6367 * c
return km
Chúng tôi có một loạt các dòng (điểm) trong tệp phải được xử lý theo cặp (điểm 1 - điểm 2) để tính khoảng cách. Để làm điều này, chúng ta sẽ sử dụng một trình vòng lặp đơn giản từ Hầu hết các cách pythonic để lấy phần tử trước đó
def offset(iterable):
prev = None
for elem in iterable:
yield prev, elem
prev = elem
Bây giờ có thể đọc tệp (ví dụ về Kerrie) theo cặp dòng / điểm
import csv
with open('testhavers.csv', 'rb') as f:
reader = csv.DictReader(f)
for pair in offset(reader):
print pair
(None, {'LAT': '10.08527', 'LON': '124.59833', 'ID': '1', 'TIME': '21:24:37'})
({'LAT': '10.08527', 'LON': '124.59833', 'ID': '1', 'TIME': '21:24:37'},
{'LAT': '10.08523', 'LON': '124.59830', 'ID': '2', 'TIME': '21:25:07'})
({'LAT': '10.08523', 'LON': '124.59830', 'ID': '2', 'TIME': '21:25:07'},
{'LAT': '10.08526', 'LON': '124.59832', 'ID': '3', 'TIME': '21:25:37'})
({'LAT': '10.08526', 'LON': '124.59832', 'ID': '3', 'TIME': '21:25:37'},
{'LAT': '10.08526', 'LON': '124.59831', 'ID': '4', 'TIME': '21:26:07'})
Sau đó, tạo một shapefile chứa các trường ban đầu của tệp csv và một trường mới cho khoảng cách với các mô-đun Python Shapely và Fiona của Sean Gillies:
import fiona
from shapely.geometry import Point, mapping
# creation of the schema of the shapefile (geometry and fields)
schema = { 'geometry': 'Point', 'properties':{'ID': 'int', 'LAT':'float', 'LON':'float', 'TIME':'str','distance' : 'float'}}
# creation of the shapefile:
with fiona.collection("result.shp", "w", "ESRI Shapefile", schema) as output:
# reading the csv file
with open('testhavers.csv', 'rb') as f:
reader = csv.DictReader(f)
# we need here to eliminate the first pair of point with None
for i, pair in enumerate(offset(reader)):
if i == 0: (pair with None)
# writing of the point geometry and the attributes
point = Point(float(pair[1]['LON']), float(pair[1]['LAT']))
dist = 0 # None
output.write({'properties': {'ID':int(pair[1]['ID']),'LAT':float(pair[1]['LAT']),'LON':float(pair[1]['LON']), 'TIME':pair[1]['TIME'],'distance': dist},'geometry': mapping(point)})
else:
# writing of the point geometry and the attributes
point = Point(float(pair[1]['LON']), float(pair[1]['LAT']))
# Haversine distance between pairs of points
dist = haversine(float(pair[0]['LON']), float(pair[0]['LAT']), float(pair[1]['LON']),float(pair[1]['LAT']))
output.write({'properties': {'ID':int(pair[1]['ID']),'LAT':float(pair[1]['LAT']),'LON':float(pair[1]['LON']), 'TIME':pair[1]['TIME'],'distance': dist},'geometry': mapping(point)})
và kết quả:
Cũng có thể làm điều đó với PyQGIS nhưng nó phức tạp hơn Fiona, sử dụng từ điển đơn giản để tạo ra shapefiles.
Bạn có thể sử dụng một hàm khác để tính khoảng cách Haversine ( Tại sao định luật cosin thích hợp hơn haversine khi tính khoảng cách giữa hai điểm kinh độ vĩ độ? ) Mà không có vấn đề gì, chỉ có sự thay đổi tính toán khoảng cách, không phải là quá trình tạo ra shapefile.