简体   繁体   中英

MATLAB spline: evaluate along y axis

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.

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 . Eg 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);  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM