【问题标题】:Find out if point is part of curve (spline, splipy)找出点是否是曲线的一部分(样条线,slipy)
【发布时间】:2022-10-30 23:23:58
【问题描述】:

我有一些 3D 点曲线的坐标,我通过这些坐标放置样条曲线,如下所示:

from splipy import curve_factory
pts = [...] #3D coordinate points
curve = curve_factory.curve(pts)

我知道我可以通过在一定长度后评估它来获得沿曲线的 3D 点:

point_on_curve = curve.evaluate(t)
print(point_on_curve) #outputs coordinates: (x y z) 

然而,是否有可能以相反的方式做到这一点?是否有函数/方法可以告诉我某个点是否是曲线的一部分?或者如果它几乎是曲线的一部分?就像是:

curve.func(point) #output: True

或者

curve.func(point) #output: distance to curve 0.0001 --> also part of curve 

谢谢!

【问题讨论】:

    标签: geometry point curve spline


    【解决方案1】:

    我通过ventusff 找到了这个script,它执行优化以找到您调用t 的参数值(在脚本中是u),它给出了样条线上最接近外部点的点.

    我在代码下方报告了一些更改,以使您更清楚。我定义了一个等于 0.001 的容差。 优化求解器及其参数值的选择需要一点研究。我现在没有足够的时间来做这件事,但你可以尝试一下。

    在这种情况下,SciPy 用于样条生成和评估,但您可以轻松地将其替换为 slipy。优化是使用 SciPy 执行的有趣部分。

    import matplotlib.pyplot as plt
    import numpy as np
    from scipy.interpolate import splprep, splev
    from scipy.spatial.distance import euclidean
    from scipy.optimize import fmin_bfgs
    
    points_count = 40
    phi = np.linspace(0, 2. * np.pi, points_count)
    k = np.linspace(0, 2, points_count)
    r = 0.5 + np.cos(phi)
    x, y, z = r * np.cos(phi), r * np.sin(phi), k
    
    tck, u = splprep([x, y, z], s=1)
    points = splev(u, tck)
    
    idx = np.random.randint(low=0, high=40)
    noise = np.random.normal(scale=0.01)
    external_point = np.array([points[0][idx], points[1][idx], points[2][idx]]) + noise
    
    
    def distance_to_point(u_):
        s = splev(u_, tck)
        return euclidean(external_point, [s[0][0], s[1][0], s[2][0]])
    
    
    closest_u = fmin_bfgs(distance_to_point, x0=np.array([0.0]), gtol=1e-8)
    closest_point = splev(closest_u, tck)
    
    tol = 1e-3
    if euclidean(external_point, [closest_point[0][0], closest_point[1][0], closest_point[2][0]]) < tol:
        print("The point is very close to the spline.")
    
    ax = plt.figure().add_subplot(projection='3d')
    ax.plot(points[0], points[1], points[2], "r-", label="Spline")
    ax.plot(external_point[0], external_point[1], external_point[2], "bo", label="External Point")
    ax.plot(closest_point[0], closest_point[1], closest_point[2], "go", label="Closest Point")
    plt.legend()
    plt.show()
    

    该脚本绘制如下图:

    并打印以下输出:

    Current function value: 0.000941
    Iterations: 5
    Function evaluations: 75
    Gradient evaluations: 32
    The point is very close to the spline.
    

    【讨论】:

    • 非常感谢!这看起来很不错
    猜你喜欢
    • 1970-01-01
    • 2015-10-03
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多