求点到复杂铜的最小距离

2024-05-03 12:07:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一条复杂的曲线,定义为表中的一组点,如so(完整的表是here):

#  x   y
1.0577  12.0914
1.0501  11.9946
1.0465  11.9338
...

如果我使用命令打印此表:

plt.plot(x_data, y_data, c='b',lw=1.)
plt.scatter(x_data, y_data, marker='o', color='k', s=10, lw=0.2)

我得到以下信息:

enter image description here

我已经手动添加了红点和分段。我需要的是一种计算每个点的线段的方法,也就是:一种从这个二维空间中的给定点到插值曲线的最小距离的方法。

我不能使用到数据点本身(生成蓝色曲线的黑点)的距离,因为它们不是以相等的间隔定位的,有时它们很接近,有时它们相距很远,这深深地影响了我的结果。

因为这不是一个行为良好的曲线,我真的不知道我能做什么。我试过用UnivariateSpline插入它,但它返回的拟合度非常差:

# Sort data according to x.
temp_data = zip(x_data, y_data)
temp_data.sort()
# Unpack sorted data.
x_sorted, y_sorted = zip(*temp_data)

# Generate univariate spline.
s = UnivariateSpline(x_sorted, y_sorted, k=5)
xspl = np.linspace(0.8, 1.1, 100)
yspl = s(xspl)

# Plot.
plt.scatter(xspl, yspl, marker='o', color='r', s=10, lw=0.2)

enter image description here

我还尝试增加插值点的数量,但结果一团糟:

# Sort data according to x.
temp_data = zip(x_data, y_data)
temp_data.sort()
# Unpack sorted data.
x_sorted, y_sorted = zip(*temp_data)

t = np.linspace(0, 1, len(x_sorted))
t2 = np.linspace(0, 1, 100)    
# One-dimensional linear interpolation.
x2 = np.interp(t2, t, x_sorted)
y2 = np.interp(t2, t, y_sorted)
plt.scatter(x2, y2, marker='o', color='r', s=10, lw=0.2)

enter image description here

任何想法/建议都将非常感谢。


Tags: 方法datanppltziptemp曲线marker
3条回答

您可以尝试在曲线上的点对增量上计算点到线的距离,并找到最小值。这将从绘制的曲线引入一点误差,但误差应该很小,因为点之间相对较近。

http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line

曲线本质上是参数化的,即对于每个x,不需要唯一的y,反之亦然。所以不应该插值y(x)或x(y)形式的函数。相反,应该做两个插值,x(t)和y(t),其中t是对应点的索引。

然后使用scipy.optimize.fminbound来找到最佳t,使(x(t)-x0)^2+(y(t)-y0)^2最小,其中(x0,y0)是第一个图形中的红点。对于fminsearch,可以指定t的最小/最大界限为1len(x_data)

如果您愿意为此使用库,请查看shapelyhttps://github.com/Toblerity/Shapely

举个简单的例子(points.txt包含您在问题中链接到的数据):

import shapely.geometry as geom
import numpy as np

coords = np.loadtxt('points.txt')

line = geom.LineString(coords)
point = geom.Point(0.8, 10.5)

# Note that "line.distance(point)" would be identical
print point.distance(line)

作为一个交互式示例(这也会绘制所需的线段):

import numpy as np
import shapely.geometry as geom
import matplotlib.pyplot as plt

class NearestPoint(object):
    def __init__(self, line, ax):
        self.line = line
        self.ax = ax
        ax.figure.canvas.mpl_connect('button_press_event', self)

    def __call__(self, event):
        x, y = event.xdata, event.ydata
        point = geom.Point(x, y)
        distance = self.line.distance(point)
        self.draw_segment(point)
        print 'Distance to line:', distance

    def draw_segment(self, point):
        point_on_line = line.interpolate(line.project(point))
        self.ax.plot([point.x, point_on_line.x], [point.y, point_on_line.y], 
                     color='red', marker='o', scalex=False, scaley=False)
        fig.canvas.draw()

if __name__ == '__main__':
    coords = np.loadtxt('points.txt')

    line = geom.LineString(coords)

    fig, ax = plt.subplots()
    ax.plot(*coords.T)
    ax.axis('equal')
    NearestPoint(line, ax)
    plt.show()

enter image description here

注意,我添加了ax.axis('equal')shapely在数据所在的坐标系中操作。如果没有等轴图,视图将被扭曲,尽管shapely仍将找到最近的点,但在显示中它看起来不太正确:

enter image description here

相关问题 更多 >