【发布时间】:2021-03-17 15:46:05
【问题描述】:
我遇到了一道相对简单的数学题。我有一个在二维空间中有点的向量。还有一个使用样条表示的二维曲线。现在我想沿着法线向量移动这些点。点和曲线如图1所示。另外我想知道这些点与法线方向曲线之间的距离,如图所示。
我正在尝试解决 Python 和 numpy 库中的问题。不幸的是,我是一个初学者。有没有人对我有想法,我如何计算各个点和曲线之间法线方向的距离?
非常感谢
【问题讨论】:
我遇到了一道相对简单的数学题。我有一个在二维空间中有点的向量。还有一个使用样条表示的二维曲线。现在我想沿着法线向量移动这些点。点和曲线如图1所示。另外我想知道这些点与法线方向曲线之间的距离,如图所示。
我正在尝试解决 Python 和 numpy 库中的问题。不幸的是,我是一个初学者。有没有人对我有想法,我如何计算各个点和曲线之间法线方向的距离?
非常感谢
【问题讨论】:
在 2D 中,法线是任何与切线正交的向量。对于大多数流行的样条曲线,切线有一个封闭的形式。如果没有,可以用数值计算。
数值计算:对于函数p(s),它返回样条上的点作为标量s、tangent_at_s = (p(s + e) - p(s - e)) / (2 * e) 的函数,其中e 是一个很小但非零的数字。说1e-6。
你可以将tangent_at_s旋转90度得到一个法线向量。在 2D 中,这很简单:normal_at_s = [-tangent_at_s.y, tangent_at_s.x]。除以n的范数得到一个单位范数。
import numpy as np
def p(s):
'''p(s) returns an np.array of size 2. A point on the spline.
s + e is a different point for all s within the spline, and nonzero e.
'''
return a_point_on_the_spline
def get_unit_normal(p, s):
# Compute tangent by central differences. You can use a closed form tangent if you have it.
tangent_at_s = (p(s + e) - p(s - e)) / (2 * e)
normal_at_s = np.array([-tangent_at_s[1], tangent_at_s[0]])
unit_normal_at_s = normal_at_s / np.linalg.norm(normal_at_s)
my_normal = get_unit_normal(p, 0.1)
要沿法线向量平移p(s) 处的点,只需构造一个点p'(s) = p(s) + d_along_normal * get_unit_normal(p, s)。到原点的距离为norm(p'(s) - p(s))。
点和曲线之间的最短线段始终要么垂直于曲线,要么连接到曲线端点之一。您可以通过迭代曲线上几乎间隔的点,并找到曲线上与您的查询点的距离最小的点来计算一个合适的近似值。
为了更准确的估计,您可以检查大间距,然后使用牛顿法在曲线的小段中找到最小值。
【讨论】:
我将问题分为两个问题:1)找到曲线(点)的法线,2)找到直线和样条线的交点。
第一个很简单:取两个连续的点,找到phi = atan2((y2 - y1) / (x2 - x1)) - 它在x轴和切线之间的角度,psi = phi +- pi / 2是曲线和法线之间的角度,求解y1 = tan(psi) * x1 + b为b,你得到线方程@ 987654325@.
第二个更复杂。您可以在此question 中尝试解决方案。我会尝试沿着这条线找到两个点,该点高于和低于样条曲线并平分直到相交,但我不清楚找到这两个点的方法。或者,您可以尝试在直线的相对两侧找到两个样条点,然后在它们之间平分。
【讨论】: