请参阅此图以获取说明: 。两条红色曲线通过两次使用样条函数进行插值。现在我需要找到将蓝色点与两条红色曲线对齐的水平位移。结果必须如下所示: .
是否可以找到属于某个样条曲线的某个给定 y 坐标的 x 坐标?那么这可以很容易地解决。
编辑:简单地改变 x 和 y 轴并没有帮助,因为样条曲线并没有为两条曲线之一提供良好的曲线。
Edit2:我忘了说时间很重要。我正在寻找一个非常快速的解决方案。
设xBlue
和yBlue
是蓝点的坐标(n×1 向量),并且yRedFun
是样条逼近函数,因此yRedFun(x)
将返回插值的红线x
。例如yRedFun
,可能是匿名函数句柄@(x) ppval(pp,x)
。也许您需要稍微外推红线,以便在所有 xBlue 上定义 yRedFun。
我们现在可以定义一个最小化函数:
cost = @(deltaX) norm( yBlue - arrayfun(yRedFun, xBlue + deltaX) )
它的最小值可以通过deltaX = fminsearch(cost, 0)
或找到deltaX = fzero(cost, 0)
。
虽然这可能是一种过于笼统的方法,但如果不需要快速性能,应该没问题。此外,由于蓝色和红色之间的拟合可能不准确,因此该方法将您试图最小化的规范形式化。
如果需要性能,可以使用下一个算法:
function deltaX = findDeltaX(xBlue, yBlue, yRedFun, precision)
deltaX = 0; % total delta
deltaDeltaX = Inf; % delta at each iteration
yRedFunDer = fnder(yRedFun);
while(abs(deltaDeltaX) > precision)
xRed = xBlue + deltaX;
yRed = fnval(yRedFun, xRed);
yRedDer = fnval(yRedFunDer, xRed);
deltaDeltaX = yRedDer \ (yRed - yBlue);
deltaX = deltaX + deltaDeltaX;
end
end
低导数的点可能会降低精度。在第一次迭代中,您可以选择N
具有最高导数的点并丢弃所有其他点。这也将提高性能。
[~, k] = sort(abs(yRedDer), 'descend');
k = k(1:N);
yRedDer = yRedDer(k);
xBlue = xBlue(k);
yBlue = yBlue(k);