我想使用MATLAB函数来查找点和曲线之间的最小长度?该曲线由一个不太平滑的复杂函数描述。所以我希望使用matlab的现有工具来计算它。你碰巧认识一个吗?
答案 0 :(得分:5)
当有人说“复杂”时,答案总是很复杂,因为我从来不知道你到底有什么。所以我将描述一些基本的想法。
如果曲线是已知的非线性函数,则使用符号工具箱开始。例如,考虑函数y = x ^ 3-3 * x + 5,以及x,y平面中的点(x0,y0)=(4,3)。
记下距离的平方。欧几里德距离很容易写。
(x - x0)^2 + (y - y0)^2 = (x - 4)^2 + (x^3 - 3*x + 5 - 3)^2
因此,在MATLAB中,我将使用符号工具箱进行部分操作。最小距离必须位于一阶导数的根部。
sym x
distpoly = (x - 4)^2 + (x^3 - 3*x + 5 - 3)^2;
r = roots(diff(distpoly))
r =
-1.9126
-1.2035
1.4629
0.82664 + 0.55369i
0.82664 - 0.55369i
我对复杂的根源不感兴趣。
r(imag(r) ~= 0) = []
r =
-1.9126
-1.2035
1.4629
哪一个是距离平方的最小值?
subs(P,r(1))
ans =
35.5086
subs(P,r(2))
ans =
42.0327
subs(P,r(3))
ans =
6.9875
这是距离的平方,这里最小化列表中的最后一个根。鉴于x的最小位置,我们当然可以通过替换y(x)= x ^ 3-3 * x + 5的表达式找到y。
subs('x^3-3*x+5',r(3))
ans =
3.7419
因此,如果曲线可以用如上所述的简单函数形式编写,那么相当容易。对于仅从平面中的一组点知道的曲线,您可以使用我的distance2curve实用程序。它可以在最接近给定点的n维中找到空间曲线样条插值上的点。
对于其他曲线,例如椭圆,解决方案可能最容易通过转换为极坐标来解决,其中椭圆很容易以参数形式写成极角的函数。完成后,按照我之前的步骤编写距离,然后求解导数的根。
要解决的一个困难案例是功能被描述为不太平滑。这是噪音还是不可微分的曲线?例如,三次样条曲线在某种程度上“不太平滑”。分段线性函数在断点处甚至更不平滑。如果你实际上只有一组数据点中有一点噪音,你必须决定是否消除噪音。您希望基本上找到平滑近似的最近点,还是在寻找插值曲线上的最近点?
对于数据点列表,如果您的目标是不进行任何平滑,那么使用线性插值可以选择我的distance2curve实用程序。如果你想自己进行计算,如果你有足够的数据点,你可以通过简单地选择最接近的数据点来找到一个很好的近似值,但如果你的数据间距不是很近,那么这可能是一个很差的近似值。
如果您的问题不属于其中一个类,您仍然可以使用各种方法解决问题,但我需要了解有关该问题的更多细节以获得更多帮助。
答案 1 :(得分:3)
有两种方法可以解决这个问题。
如果您的曲线相当平滑并且您不需要太高的精度,那么简单的方法就是在密集的点数处评估您的曲线并简单地找到最小距离:
t = (0:0.1:100)';
minDistance = sqrt( min( sum( bxsfun(@minus, [x(t),y(t)], yourPoint).^2,2)));
更难的方法是尽量减少描述距离的t
(或x
)函数
distance = @(t)sum( (yourPoint - [x(t),y(t)]).^2 );
%# you can use the minimum distance from above as a decent starting guess
tAtMin = fminsearch(distance,minDistance);
minDistanceFitte = distance(tAtMin);