从线串中提取最近点索引到给定点?
Extract nearest point index from a linestring to a given point?
让我们将线串视为点列表,我将其命名为 trail。我需要检测哪个点离这条小径足够近。我有另一个名为兴趣点的线串,我需要 return 距离线串最近的索引点。我想提一下,这些兴趣点不包含在路径线串中,因此我将通过提供该兴趣点以某种方式评估这条路径中的索引点。得到的兴趣点将取路径列表中存在的值。
[编辑]:
我会用普通数字来转换这道题。我觉得这很容易。
输入列表 [0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]。
输入数:3.30
我很容易看出条件:list[n] < number < list[n+1]
然后我可以查看费用:
cost1 = 数字 - 列表[n]
cost2 = list[n+1] - number.
那我就可以得到N的index if (cost1 < cost2) return N else return N+1.
[重要]:
点对象不能与数字进行比较,这让我陷入了盲点。
如果您只需要这样做一次,或者速度并不是很重要,并且您的轨迹不会自行回环,因此检测最近的两点可能不同于检测它们之间的线段,那就很简单了。
首先,你需要一个点的距离平方公式(这代替了普通数字的差异):
def dSq(x0: Double, y0: Double, x1: Double, y1: Double) =
(x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)
请注意,除了您必须计算额外的平方根外,使用普通距离而不是距离平方并没有真正的优势。 (但请随意 def d(...) = sqrt(dSq(...))
并改用它。)
现在您找到了从轨迹到目标点的距离:
val ds = trace.map(p => dSq(target.x, target.y, p.x, p.y))
你找到点对之间的距离:
val pairDs = ds.sliding(2).map(xx => xx(0) + xx(1))
然后找到其中最小的索引:
val smallest = pairDs.min
val index = pairDs.indexWhere(_ == smallest)
那么在你原来的列表中,这两个点是index
和index+1
。
或者,您可以找到最近的单个点,然后通过比较它们的距离来决定是要下一个还是上一个。 (再次注意,所有这些都是不精确的——要真正做到正确,您必须计算该点最接近两点之间线段的点,这是一个更长的公式。)
如果您必须经常这样做,那么您会希望有一种更快的方法来忽略不相关的大距离。一种常见的方法是在迹线上放置一个网格,然后在每个网格元素内创建子迹线。然后,当给定一个兴趣点时,您首先查找它的网格位置,然后在网格内执行相同的搜索技巧。 (您可能还需要搜索 8 个相邻的邻居,具体取决于您如何裁剪网格内的点。)
让我们将线串视为点列表,我将其命名为 trail。我需要检测哪个点离这条小径足够近。我有另一个名为兴趣点的线串,我需要 return 距离线串最近的索引点。我想提一下,这些兴趣点不包含在路径线串中,因此我将通过提供该兴趣点以某种方式评估这条路径中的索引点。得到的兴趣点将取路径列表中存在的值。
[编辑]:
我会用普通数字来转换这道题。我觉得这很容易。
输入列表 [0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]。 输入数:3.30
我很容易看出条件:list[n] < number < list[n+1] 然后我可以查看费用:
cost1 = 数字 - 列表[n] cost2 = list[n+1] - number.
那我就可以得到N的index if (cost1 < cost2) return N else return N+1.
[重要]:
点对象不能与数字进行比较,这让我陷入了盲点。
如果您只需要这样做一次,或者速度并不是很重要,并且您的轨迹不会自行回环,因此检测最近的两点可能不同于检测它们之间的线段,那就很简单了。
首先,你需要一个点的距离平方公式(这代替了普通数字的差异):
def dSq(x0: Double, y0: Double, x1: Double, y1: Double) =
(x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0)
请注意,除了您必须计算额外的平方根外,使用普通距离而不是距离平方并没有真正的优势。 (但请随意 def d(...) = sqrt(dSq(...))
并改用它。)
现在您找到了从轨迹到目标点的距离:
val ds = trace.map(p => dSq(target.x, target.y, p.x, p.y))
你找到点对之间的距离:
val pairDs = ds.sliding(2).map(xx => xx(0) + xx(1))
然后找到其中最小的索引:
val smallest = pairDs.min
val index = pairDs.indexWhere(_ == smallest)
那么在你原来的列表中,这两个点是index
和index+1
。
或者,您可以找到最近的单个点,然后通过比较它们的距离来决定是要下一个还是上一个。 (再次注意,所有这些都是不精确的——要真正做到正确,您必须计算该点最接近两点之间线段的点,这是一个更长的公式。)
如果您必须经常这样做,那么您会希望有一种更快的方法来忽略不相关的大距离。一种常见的方法是在迹线上放置一个网格,然后在每个网格元素内创建子迹线。然后,当给定一个兴趣点时,您首先查找它的网格位置,然后在网格内执行相同的搜索技巧。 (您可能还需要搜索 8 个相邻的邻居,具体取决于您如何裁剪网格内的点。)