Code covered by the BSD License

Download apps, toolboxes, and other File Exchange content using Add-On Explorer in MATLAB.

### Highlights from interparc

4.89474
4.9 | 21 ratings Rate this file 106 Downloads (last 30 days) File Size: 6.81 KB File ID: #34874 Version: 1.3

# interparc

### John D'Errico (view profile)

01 Feb 2012 (Updated )

Distance based interpolation along a general curve in space

File Information
Description

A common request is to interpolate a set of points at fixed distances along some curve in space (2 or more dimensions.) The user typically has a set of points along a curve, some of which are closely spaced, others not so close, and they wish to create a new set which is uniformly spaced along the same curve.

When the interpolation is assumed to be piecewise linear, this is easy. However, if the curve is to be a spline, perhaps interpolated as a function of chordal arclength between the points, this gets a bit more difficult. A nice trick is to formulate the problem in terms of differential equations that describe the path along the curve. Then the interpolation can be done using an ODE solver.

As an example of use, I'll pick a random set of points around a circle in the plane, then generate a new set of points that are equally spaced in terms of arc length along the curve, so around the perimeter of the circle.

theta = sort(rand(15,1))*2*pi;
theta(end+1) = theta(1);
px = cos(theta);
py = sin(theta);

100 equally spaced points, using a spline interpolant.

pt = interparc(100,px,py,'spline');

% Plot the result
plot(px,py,'r*',pt(:,1),pt(:,2),'b-o')
axis([-1.1 1.1 -1.1 1.1])
axis equal
grid on
xlabel X
ylabel Y
title 'Points in blue are uniform in arclength around the circle'

You can now also return a function handle to evaluate the curve itself at any point. As well, CSAPE is an option for periodic (closed) curves, as long as it is available in your matlab installation.

[~,~,foft] = interparc([],px,py,'spline');
foft(0:0.25:1)
ans =
0.98319 0.18257
-0.19064 0.98151
-0.98493 -0.17486
0.18634 -0.98406
0.98319 0.18257

Acknowledgements
Required Products MATLAB
MATLAB release MATLAB 7.12 (R2011a)
Other requirements Earlier releases will work as well.
Tags for This File   Please login to tag files.
 Please login to add a comment or rating.
Comments and Ratings (43)
24 Jun 2016 Alexandr Buyval

### Alexandr Buyval (view profile)

John,
Thank you for this function. It exactly what I need.
Could you answer me how to get a curvature values along curve?

28 May 2016 John D'Errico

### John D'Errico (view profile)

:)

Comment only
28 May 2016 Toby Wenz

### Toby Wenz (view profile)

This is my favorite external Matlab function. I use it all the time in my research to resample datasets in order to make sure I can combine, plot and analyse them together.

12 May 2016 John D'Errico

### John D'Errico (view profile)

If for some x-values, you may or may not get multiple y values, then the problem becomes complicated.

You may want to break the problem down into separate sub-curves, where the branch of the curve is chosen so the function is now single valued on that domain. Then you can use any tool.

Comment only
11 May 2016 Jianwei Tu

### Jianwei Tu (view profile)

John,

Thank you for your reply. I actually have a relationship where some x have multiple y values. I was looking for a function similar to interp1 that does:

yinterp = thefunction(x,y,xgiven);

but I guess it does not make sense and could not be done according to what you just said.

Thanks anyway!

Jianwei

Comment only
11 May 2016 John D'Errico

### John D'Errico (view profile)

Jianwei,

If you have a problem with a single valued function of x, then you can just use a call to spline, pchip, or even just interp1. Just pass in the x values you want to interpolate at, and those tools can predict a result nicely.

If your relationship has multiple y values for any given x, then the above tools won't work. But then it won't make sense to be able to interpolate as a function of x then either.

So I'm not really sure why you would need interparc here.

Having said that, I suppose I can come up with a scenario. Consider a path in three dimensions, of the form

(x,y(x),z(x))

So y and z are both functions of x. Now, you might wish to interpolate points along that curve for given values of x. But that is still easy to do. Again, just use spline models for each of y(x) and z(x).

So I'm not sure what you might be looking for.

Comment only
10 May 2016 Jianwei Tu

### Jianwei Tu (view profile)

John, is it possible to use interparc to generate a series of data points with user defined x values? Thanks, Jianwei

03 May 2016 Mario Marín

### Mario Marín (view profile)

28 Mar 2016 Joe Passman

10 Feb 2016 Jack

### Jack (view profile)

Another terrific and very useful routine from John D'Errico!

26 Jan 2016 Nadim

### Nadim (view profile)

I need a similar function that runs on Fortran. Does anyone know where I can find such a function. Thanks!

Comment only
03 Nov 2015 Kevin J. Delaney

### Kevin J. Delaney (view profile)

Fantastic! Just what I needed.

09 Sep 2015 Christopher Thissen

### Christopher Thissen (view profile)

Very helpful - thanks!

23 Jul 2015 Leonardo

### Leonardo (view profile)

Dear John,
thank you for your code. I would like to ask you..
It is in your plan to implement an upgrading also for the interpolating method "cscvn()" for closed curves ?
Thank you in advance.

Comment only
02 Jul 2015 navid alemi

### navid alemi (view profile)

Thanks alot.

09 Apr 2015 Harel

### Harel (view profile)

05 Sep 2014 Maximilian

### Maximilian (view profile)

Works perfect! Thanks!

21 Jul 2014 Justin

### Justin (view profile)

This is amazing. Basically matlab magic.

Running on MATLAB 7.8(R2009a)

03 Jul 2014 Steve

### Steve (view profile)

very nice, works great for my 2D-points!

11 Jun 2014 Thomas

### Thomas (view profile)

Very good code BTW.

03 Jun 2014 John D'Errico

### John D'Errico (view profile)

It is never obvious, because the error often results from some language construct of which the older MATLAB release has no understanding. So it throws some strange error.

Comment only
03 Jun 2014 Blaise

### Blaise (view profile)

hey,

I have upgraded to 2014A and that fixes it. sorry to bother you, should have checked this myself

blaise

Comment only
02 Jun 2014 John D'Errico

### John D'Errico (view profile)

Every time someone tells me that some code of mine fails to run on their machine with a strange looking error, especially when they have called it in a normal way, my first guess is they are trying to run it with too old of a MATLAB release.

INTERPARC was written on MATLAB 2011a. If your release is significantly older than that, I imagine this is the problem. If not, then I can only guess you have some conflicting code on your search path, perhaps you wrote something called spline.m?

Comment only
02 Jun 2014 Blaise

### Blaise (view profile)

hello,

I have just downloaded the code and tried to run it with the code taken from above:

theta = sort(rand(15,1))*2*pi;
theta(end+1) = theta(1);
px = cos(theta);
py = sin(theta);
pt = interparc(100,px,py,'spline');

however i get the error message:

??? Reference to non-existent field 'coefs'.

Error in ==> interparc at 317
nc = numel(spl{i}.coefs);

Error in ==> test at 13
pt = interparc(100,px,py,'spline');

Just before executing the line spl is a 1*2 cell array, with the second cell being empty and the first one is a structure (with one field, dim=1).

I was surprised since the code looks working well for everyone else.

Anybody knows what goes wrong?

Best,
Blaise

Comment only
23 May 2014 John D'Errico

### John D'Errico (view profile)

Alias, sorry. Never published, not by me at least. The idea is a basic one though.

1. Compute the cumulative linear arclength (t) along the curve. This is simply the distance along the curve using a connect-the-dots (piecewise linear) function.

2. Fit an interpolating spline through the points in each dimension, as a function of that cumulative linear arclength. This is the classic approach to fitting a curve through a completely general set of points in any number of dimensions, especially if that curve may be a closed one. Thus I generate the curves {x(t), y(t), z(t),...}. Many tools in MATLAB use this same scheme to fit interpolating splines through arbitrarily shaped curves.

3. Differentiate those spline functions, to get {x'(t),y'(t),z'(t), ...}. Since the functions are simply cubic polynomial segments, differentiation is trivial.

4. Integrate the cumulative arclength differential element,

sqrt(x'^2 + y'^2 + z'2 + ...)

Numerical integration is employed in this step, in this case an ODE solver is used, because ODE45 has the ability to integrate a function, finding where that function crosses a list of points of interest. That is important for interparc, since it must locate points along the curve at specific distances from the start point.

Comment only
23 May 2014 Alias Merzouk

### Alias Merzouk (view profile)

It's a good work Mr. John, this is exactly what I need. But can you give us some papers/references about the used interpolation methods ?

Comment only
13 May 2014 Pete

### Pete (view profile)

Superb.

*Extremely* useful, especially in conjunction with distance2curve.m and/or slmengine.m

I owe you many beers(!)

06 Feb 2014 Mayar

### Mayar (view profile)

Thank You Mr.John, you found my problem very well.
With regards

05 Feb 2014 John D'Errico

### John D'Errico (view profile)

Mayar -

I'm sorry, but you need to provide an example that fails. In fact, if I try to emulate what you SAID you did that fails, I have no problems at all.

x = [200 221 221 240];
y = [100 102 107 110];

interparc(10,x,y)
ans =
200 100
205.69 97.159
211.63 94.893
217.88 94.532
220.9 99.706
220.98 106.06
222.27 112.2
228.01 114.09
234.15 112.49
240 110

It is true that if there are two consecutive points that are identical for all the variables, then it will fail. That is, this sequence of points will cause an error:

x = [200 221 221 240];
y = [100 102 102 110];

If this is indeed your issue, and NOT what you actually stated, just drop the replicates of that point! The error message indicated exactly that. Learn how to use unique to solve that, or you can find my consolidator tool on the file exchange to help with floating point near replicates.

Comment only
04 Feb 2014 Mayar

### Mayar (view profile)

Dear:

this function is not working while we have two value for the same station. for instance i have two value of Z for the same station of x. ex: x=221.0 , z= 102 next value in the data set is x=221.0 , z= 107,
my data set contain such data, while i run this function, it give me error massage of " the data sites should be distinct", for t=1, and while i change t to vector suppose t=0:5:556 ( 556 end of data set), it give me again error of " all element of t must be 0<= t <=1 " . even I set the t as t=0:0.5:556.

wish you give me some instruction soon
with regards

Comment only
24 Dec 2013 John D'Errico

### John D'Errico (view profile)

There is no decoupling of the axes. Basic 2nd semester calc, or something like that. I won't claim it is obvious at all, since so many nice tricks in mathematics are only obvious after you see the trick. The arc length of a parametric curve is an integral of the sqrt of the sum of the squares of the first derivatives.

http://en.wikipedia.org/wiki/Arc_length

Since interparc wants to locate a specific point along that curve, it simply integrates that function using an ODE solver. A nice thing about the ODE solvers in MATLAB is they can identify the location where the integrated function crosses a point of interest.

The only decoupling of the axes is the use of splines on each dimension independently as a function of the linear chordal arc length. This allows me to define a parametric curve in an arbitrary number of dimensions, (x(t),y(t),z(t),...), and then form differentials at any point along that curve.

So we have the arc length as:

L = int(sqrt(x'^2 +y'^2 + ...))

where the differentials are with respect to t, the linear chordal arc length.

Comment only
24 Dec 2013 Mathew

### Mathew (view profile)

This program is really impressive. I wanted to understand the math a bit more since it seems to be unique relative to many other interpolation methods. From what I can understand for the spline case, is it using a cubic spline interpolation over each dimension independently, then using differential equations to solve for the length of the curve for each axis? For a curve in 3 dimensions, xyz, I am confused if it is decoupling each axis or it is solving them together.

If anyone understands how this actually works it would be great to hear.

Comment only
11 Nov 2013 Dinesh

### Dinesh (view profile)

Thanks so much John. It really helped me in my hard time. This program is very nice, it is fast also. Even if I input smaller number of points it adjust them to the required number of equally spaced points.

Thank you again.
Dinesh

Comment only
03 Mar 2013 Evgeny Pr

19 Jan 2013 Jon

### Jon (view profile)

John,

Thanks for the response! I've been playing with the linear interpolation and you're right--it's much faster. It also seems to be accurate enough for my model. Thanks for your input!

18 Jan 2013 John D'Errico

### John D'Errico (view profile)

Jon - you can gain considerable speed by use of the 'linear' method in the code, if you can afford the loss in accuracy. It will be MUCH faster (as much as 1000 times faster), because I do the interpolation for that method in a different way from the other methods.

Those smoother methods in this tool are forced to call an odsolver for the interpolation, so the time taken is much higher for those methods. The only possibility is that I might have offered a different ode solver than ode45, but it is the fastest solver for these problems in my tests.

Comment only
18 Jan 2013 Jon

### Jon (view profile)

Excellent code.

I have only one complaint, which is the code takes awhile to run. For some applications this doesn't matter much, but I'm trying to resample a stream centerline after each time step in a 100's of time steps numerical model, and run times have become too large for me to use this (at least with each iteration). Do you have any suggestions for speeding it up? I tried going line-by-line through the code to find the bottleneck, but I was unsuccessful.

16 Aug 2012 John D'Errico

### John D'Errico (view profile)

Iain - You may find pchip a better choice for that class of curve. However, you have a valid point that there is a problem for this curve when a spline is used. I've just sent in a new version that should do better. It should appear in the morning.

Comment only
15 Aug 2012 Iain

### Iain (view profile)

Hi John. It is only a problem when pushing the spline fit quite hard, i.e. when there is a big gap between data. Then t and ti are not necessarily close. Test data and program at: http://www.srcf.ucam.org/~icw26/interparc_temp/

Try with and without change suggested. Thanks again for the code, hope that helps.

15 Aug 2012 John D'Errico

### John D'Errico (view profile)

Iain - correct, there was a problem in recognizing contractions. I accidentally used strcmpi, not strncmpi. Fixed, and uploaded to appear when they process it.

As far as derivatives, there is no need to move the derivative evaluation into the loop. ppval is fully vectorized, so no explicit loop is needed for that part. In fact, putting it inside a loop will just slow things down. If you have found a case where this fails please let me know, but the code does run correctly in my tests, as I would expect.

Comment only
15 Aug 2012 Iain

### Iain (view profile)

Excellent function, just what I needed. Thanks.

Slight bug in evaluating dudt - the (nargout > 1) block should be moved into the i=1:nt loop, and evaluated at ti, i.e.

for i=1:nt
%stuff - then
if nargout > 1
for j = 1:ndim
dudt(i,j) = ppval(spld{j},ti);
end
end
end
Also does not accept contractions of 'spline' etc. as equivalent arclength function does.

26 Jul 2012 John D'Errico

### John D'Errico (view profile)

Prabhu - I don't know what you are doing to generate nans. Please send me an example that causes it to happen, as none of my tests generated NaNs.

With one exception. There is actually one case I can find where interparc returns NaN. That is when I passed in a vector with NaNs in it already. In that case, how would one expect it not to return NaN? What logical action should it do when one asks it to interpolate a curve that is undefined at some set of points?

Comment only
26 Jul 2012 Prabhu

### Prabhu (view profile)

John:
Thanks for this excellent code.
I'm facing one problem when I use this code. It works fine in most cases. But sometimes its churning NaNs as one of the points. Can you help me out with this issue?
Thanks

Comment only
Updates
04 Mar 2012 1.1

Add csape for periodic fits, and return a function handle for external evaluation.

15 Aug 2012 1.2

Fixed bug in recognizing contractions

16 Aug 2012 1.3

Fix for dudt at the proper points.

Contact us