如何从线串(地理坐标)中获取等距点
How to get equidistant points from a linestring (geographical coordinates)
我想根据特定数量的值对地理坐标进行重新采样,比方说,在以下情况下为 1663:
-78.0599088 -11.89402416
-78.04317744 -11.88622134
-78.0267798 -11.87700462
-78.010353 -11.8692050399999
-77.9953194 -11.86129017
-77.96128788 -11.8449840599999
-77.92870572 -11.82838707
-77.89554864 -11.8117820699999
-77.86357524 -11.79488952
-77.83013412 -11.77942518
-77.7978615599999 -11.76223743
-77.765589 -11.7456140699999
-77.73216732 -11.72927727
-77.6996085599999 -11.7117892799999
-77.6673594 -11.6965884599999
-77.63510052 -11.6819618399999
-77.6045808 -11.6618759099999
-77.57262108 -11.6432262
-77.5406624399999 -11.62628883
-77.5072638 -11.6099197199999
-77.4753066 -11.5923951899999
-77.4427813199999 -11.57658786
-77.4093902399999 -11.5599159
-77.38064244 -11.5446833099999
然而,这里棘手的部分是保持第一个和最后一个位置并使用开源软件工具(例如 GDAL、AWK、GMT 或其他 bash shell 命令行工具, 那太好了)。
例如,我正在寻找类似于 XTools Pro 的 "Equidistant points (fixed number)" 选项的东西:https://help.xtools.pro/pro/12.2/en/XTools_Pro_Components/Feature_conversions/Convert_Features_to_Points.htm
这是一个预期的输出,一条距离为 X 的线,根据第一个和最后一个位置创建了 7 个点(节点或顶点):
感谢任何支持。
以下答案假定您的坐标在球体上而不是在椭球体上。
您的输入包含在两点 p 和 q 之间的大圆上的一组点,经度和纬度坐标为是:
p = {φp,λp} = {-78.0599088, -11.89402416}
q = {φq,λq} = {-77.38064244, -11.5446833099999}
调用npp[=的单位向量76=]和nqq[=76=的单位向量],则其坐标为:
np = {cos(φp) cos(λp),cos(φp) sin(λp),sin(φp)}
nq = {cos(φq) cos(λq),cos(φq) sin(λq),sin(φq)}
调用α然后在np和[=之间的角度56=]nq
α = arccos(np·nq)
如果您现在想要 n 点等距分布在 p 和 q 之间,你必须将它们分开一个角度 Δα = α/(n-1).
这些点的坐标是:
ni = np cos(i Δα) + nr sin(i Δα)
nr = Normalized[nq - (nq·np) np] = (nq - cos(α) np) / sin(α)
for i ∈ [0,n-1]。以上理解为np[=的iΔα的简单旋转80=]在np-nr平面(np·nr = 0)
然后可以将这些坐标转换回经度和纬度,为您提供所有中间点。
备注:这是针对球体上的等距点,而不是椭圆体,例如WGS 84
备注:上面的对映点会失败
一个很好的公式是Ed William's Aviation Formulary
Python 成功了:
from shapely.geometry import LineString
import csv
with open('input_xy.txt') as fin:
reader = csv.reader(fin)
xy_floats = map(lambda x: (float(x[0]), float(x[1])), list(reader))
line = LineString(xy_floats)
num_points = 9 # includes first and last
new_points = [line.interpolate(i/float(num_points - 1), normalized=True) for i in range(num_points)]
with open('output_xy.txt', 'w') as fout:
writer = csv.writer(fout)
writer.writerows([ [point.x, point.y] for point in new_points])
希望这对其他人有帮助。
我想根据特定数量的值对地理坐标进行重新采样,比方说,在以下情况下为 1663:
-78.0599088 -11.89402416
-78.04317744 -11.88622134
-78.0267798 -11.87700462
-78.010353 -11.8692050399999
-77.9953194 -11.86129017
-77.96128788 -11.8449840599999
-77.92870572 -11.82838707
-77.89554864 -11.8117820699999
-77.86357524 -11.79488952
-77.83013412 -11.77942518
-77.7978615599999 -11.76223743
-77.765589 -11.7456140699999
-77.73216732 -11.72927727
-77.6996085599999 -11.7117892799999
-77.6673594 -11.6965884599999
-77.63510052 -11.6819618399999
-77.6045808 -11.6618759099999
-77.57262108 -11.6432262
-77.5406624399999 -11.62628883
-77.5072638 -11.6099197199999
-77.4753066 -11.5923951899999
-77.4427813199999 -11.57658786
-77.4093902399999 -11.5599159
-77.38064244 -11.5446833099999
然而,这里棘手的部分是保持第一个和最后一个位置并使用开源软件工具(例如 GDAL、AWK、GMT 或其他 bash shell 命令行工具, 那太好了)。
例如,我正在寻找类似于 XTools Pro 的 "Equidistant points (fixed number)" 选项的东西:https://help.xtools.pro/pro/12.2/en/XTools_Pro_Components/Feature_conversions/Convert_Features_to_Points.htm
这是一个预期的输出,一条距离为 X 的线,根据第一个和最后一个位置创建了 7 个点(节点或顶点):
感谢任何支持。
以下答案假定您的坐标在球体上而不是在椭球体上。
您的输入包含在两点 p 和 q 之间的大圆上的一组点,经度和纬度坐标为是:
p = {φp,λp} = {-78.0599088, -11.89402416} q = {φq,λq} = {-77.38064244, -11.5446833099999}
调用npp[=的单位向量76=]和nqq[=76=的单位向量],则其坐标为:
np = {cos(φp) cos(λp),cos(φp) sin(λp),sin(φp)} nq = {cos(φq) cos(λq),cos(φq) sin(λq),sin(φq)}
调用α然后在np和[=之间的角度56=]nq
α = arccos(np·nq)
如果您现在想要 n 点等距分布在 p 和 q 之间,你必须将它们分开一个角度 Δα = α/(n-1).
这些点的坐标是:
ni = np cos(i Δα) + nr sin(i Δα) nr = Normalized[nq - (nq·np) np] = (nq - cos(α) np) / sin(α)
for i ∈ [0,n-1]。以上理解为np[=的iΔα的简单旋转80=]在np-nr平面(np·nr = 0)
然后可以将这些坐标转换回经度和纬度,为您提供所有中间点。
备注:这是针对球体上的等距点,而不是椭圆体,例如WGS 84
备注:上面的对映点会失败
一个很好的公式是Ed William's Aviation Formulary
Python 成功了:
from shapely.geometry import LineString import csv with open('input_xy.txt') as fin: reader = csv.reader(fin) xy_floats = map(lambda x: (float(x[0]), float(x[1])), list(reader)) line = LineString(xy_floats) num_points = 9 # includes first and last new_points = [line.interpolate(i/float(num_points - 1), normalized=True) for i in range(num_points)] with open('output_xy.txt', 'w') as fout: writer = csv.writer(fout) writer.writerows([ [point.x, point.y] for point in new_points])
希望这对其他人有帮助。