How to use pchip to interpolate between data points in cartesian coordinate format

4 views (last 30 days)
I am trying to use pchip to interpolate between a series of data points. My data are spatial (lat/long) but have been converted into meters in a projected cartesian coordinate system (UTM 31N- i.e. x= 431804m, y=4571664m).
The code that I am using is below, but for some reason I get error messages when trying to create objects 't' and 'p'. long_m is a 1xcolumn matrix of longitude in meters, lat_m is a 1xcolumn matrix of latitude in meters, 0.01667= 1/60th in decimal, specifying that I want to end up 60 times more data points than I have now via the interpolation:
x=long_m;
y=lat_m;
t=x(1,1):0.016667:x(211,1);
p=pchip(x,y,t);
Output message:
t =
Empty matrix: 1-by-0
p =
Empty matrix: 1-by-0
I thought that the function would return a string of numbers that relate to my interpolated points, but instead I end up with an empty 't' matrix and an empty 'p' matrix. What am I doing wrong?
Some example data is below:
x= [518666 521872 519984 519591 518800];
y= [4694989 4667173 4644884 4645622 4647104];
I am new to matlab (although I have knowledge of programming language from R), so any advice would be greatly appreciated.

Accepted Answer

Kelly Kearney
Kelly Kearney on 26 Aug 2013
The all-increasing or all-decreasing issue you're encountering isn't a restriction of pchip, but rather of the : operator. If you try to define a vector with a positive step size but decreasing values, you'll get an empty vector. For example:
>> 5:1:2
ans =
Empty matrix: 1-by-0
I'm guessing that what you're really after in this case is a parametric interpolation, where you "fill in" points in both the x- and y-direction.
% Some fake data
theta = linspace(0, 2*pi, 10);
x = cos(theta);
y = sin(theta);
% Interpolate
told = 1:10;
tnew = linspace(1,10,50);
xnew = pchip(told, x, t);
ynew = pchip(told, y, t);
% Plot
plot(x,y,'-b.', xnew, ynew, '-ro');
You can get more sophisticated to evenly space your final points, but this gives you there general idea.
  3 Comments
Kelly Kearney
Kelly Kearney on 26 Aug 2013
To approximate that, use the same idea as above, but define told based on distance along the curve:
d = sqrt((x(2:end) - x(1:end-1)).^2 + (y(2:end) - y(1:end-1)).^2);
told = [0 cumsum(d)];
tnew = linspace(0, max(told), 50);
Note that the key to this method isn't the use of linspace as opposed to :; I could have gotten approximately the same results by saying
tnew = 0:0.125:1;
The key is that I'm using a third variable ( t ) to represent "distance along the curve," and then interpolating both x and y against that.

Sign in to comment.

More Answers (1)

Shashank Prasanna
Shashank Prasanna on 23 Aug 2013
Edited: Shashank Prasanna on 23 Aug 2013
This works perfectly fine for me:
>> x= [518666 521872 519984 519591 518800];
>> y= [4694989 4667173 4644884 4645622 4647104];
>> p=pchip(x,y,x)
p =
4694989 4667173 4644884 4645622 4647104
p=pchip(x,y,x(1):0.01:x(end));
  7 Comments
Shashank Prasanna
Shashank Prasanna on 26 Aug 2013
Rhiannon, your Y can be increasing or decreasing. You can always sort your X which is meant to be increasing on the X axis. Your Y could be anything and PCHIP will happily interpolate for new X.
[sortX, idx] = sort(X);
sortY = Y(idx);
This way you can always take the sorted X to interpolate
newY = pchip(sortX,sortY,sortX(1):0.01:sortX(end));
And this doesn't change your data or results at all.
Rhiannon
Rhiannon on 26 Aug 2013
Thanks Shashank for responding again. Unfortunately, I cannot sort my data into another order as data points are temporally related, which I now realise I didn't specify in my original question (apologies). However, linspace() seems to be a solution to the problem, so I'm giving that a go. Thanks for taking the time to help!

Sign in to comment.

Categories

Find more on Interpolation in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!