Reputation: 1395
See this graph for an illustration: . The two red curves are interpolated by using the spline function twice. Now I need to find the horizontal shift which aligns the blue points with the two red curves. The result has to look like this: .
Is it possible to find the x coordinates which belong to some given y coordinates for a spline? Then this could be solved very easy.
Edit: simply changes the x and y axis does not help, because than spline does not give a nice curve for one of the two curves.
Edit2: I forgot to mention that time is important. I'm looking for a very fast solution.
Upvotes: 0
Views: 615
Reputation: 241
Let xBlue
and yBlue
be the coordinates of the blue dots (n-by-1 vectors), and yRedFun
be the spline approximation function, so yRedFun(x)
will return the interpolated red line at x
. E.g. yRedFun
may be an anonymous function handle @(x) ppval(pp,x)
. Maybe you will need to slightly extrapolate the red line so the yRedFun will be defined on all the xBlue .
We now may define a minimization function:
cost = @(deltaX) norm( yBlue - arrayfun(yRedFun, xBlue + deltaX) )
Its minimum can be found by deltaX = fminsearch(cost, 0)
or deltaX = fzero(cost, 0)
.
Though this may be a too general approach, if fast performance is not needed, it should be OK. Also, as the fit between blue and red probably is not exact, the method formalizes the norm you are trying to minimize.
If performance is needed, the next algorithm may be used:
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
Points with low derivative may reduce precision. On the first iteration you may pick N
points with highest derivative and drop all the others. This will also improve performance.
[~, k] = sort(abs(yRedDer), 'descend');
k = k(1:N);
yRedDer = yRedDer(k);
xBlue = xBlue(k);
yBlue = yBlue(k);
Upvotes: 1