# How can i calculate the length of curve?

153 views (last 30 days)

Show older comments

Hi,

I have a curve which includes X (meter) and Y (meter) data. Is there any way to obtain the length of curve easily?

Thanks a lot,

X=[96.0741000000000,97.1940000000000,98.3139000000000,99.4338000000000,100.553700000000,101.673600000000,102.793500000000,103.913400000000,105.033300000000,106.153200000000,107.273100000000,108.393000000000,109.512900000000,110.632800000000,111.752700000000,112.872600000000,113.992500000000,115.112400000000,116.232300000000]

Y=[-4.13836296940031,-4.10455468315876,-4.05645426203322,-3.99617782198545,-3.92344322326347,-3.83385191481492,-3.73582865974161,-3.61740402741020,-3.49399064332423,-3.35231953224592,-3.20552503148528,-3.04892626846560,-2.88658570885772,-2.72091440408539,-2.55226630046971,-2.38425597793465,-2.21787687713447,-2.05656258174384,-1.89889800700337]

### Answers (6)

Stephen23
on 30 Jan 2023

Edited: Stephen23
on 30 Jan 2023

A very simple approach is to download John D'Errico's excellent ARCLENGTH function:

X = -1:.01:1;

Y = sqrt(1-X.^2);

L = arclength(X,Y,'spline')

L-pi

For the sample curve, this gives a more accurate solution.

##### 5 Comments

Stephen23
on 25 Jan 2024

Some more comparisons with ARCLENGTH:

a = linspace(0, 2*pi, 1E+3);

X = cos(a);

Y = sin(a);

dX = gradient(X);

dY = gradient(Y);

Len = cumtrapz(hypot(dX,dY));

Len(end) - 2*pi

sum(hypot(dX,dY)) - 2*pi

arclength(X,Y,'spline') - 2*pi

Also with unequal spacing:

X = logspace(-10,0,200);

Y = sqrt(1-X.^2);

dX = gradient(X);

dY = gradient(Y);

Len = cumtrapz(hypot(dX,dY));

Len(end) - pi/2

sum(hypot(dX,dY)) - pi/2

arclength(X,Y,'spline') - pi/2

And with vertical lines:

X = ones(1,200);

Y = logspace(-10,1,200);

dX = gradient(X);

dY = gradient(Y);

Len = cumtrapz(hypot(dX,dY));

Len(end) - 10

sum(hypot(dX,dY)) - 10

arclength(X,Y,'spline') - 10

Ankit
on 26 Aug 2022

Edited: Ankit
on 26 Aug 2022

X=[96.0741000000000,97.1940000000000,98.3139000000000,99.4338000000000,100.553700000000,101.673600000000,102.793500000000,103.913400000000,105.033300000000,106.153200000000,107.273100000000,108.393000000000,109.512900000000,110.632800000000,111.752700000000,112.872600000000,113.992500000000,115.112400000000,116.232300000000];

Y=[-4.13836296940031,-4.10455468315876,-4.05645426203322,-3.99617782198545,-3.92344322326347,-3.83385191481492,-3.73582865974161,-3.61740402741020,-3.49399064332423,-3.35231953224592,-3.20552503148528,-3.04892626846560,-2.88658570885772,-2.72091440408539,-2.55226630046971,-2.38425597793465,-2.21787687713447,-2.05656258174384,-1.89889800700337];

len_curve = sum(vecnorm(diff( [X(:),Y(:)] ),2,2));

% the 2-norm along the rows of a matrix: vecnorm(A,2,2) , where A is a

% vector

% diff: Difference and approximate derivative.

##### 2 Comments

Star Strider
on 26 Aug 2022

Possibly —

X=[96.0741000000000,97.1940000000000,98.3139000000000,99.4338000000000,100.553700000000,101.673600000000,102.793500000000,103.913400000000,105.033300000000,106.153200000000,107.273100000000,108.393000000000,109.512900000000,110.632800000000,111.752700000000,112.872600000000,113.992500000000,115.112400000000,116.232300000000];

Y=[-4.13836296940031,-4.10455468315876,-4.05645426203322,-3.99617782198545,-3.92344322326347,-3.83385191481492,-3.73582865974161,-3.61740402741020,-3.49399064332423,-3.35231953224592,-3.20552503148528,-3.04892626846560,-2.88658570885772,-2.72091440408539,-2.55226630046971,-2.38425597793465,-2.21787687713447,-2.05656258174384,-1.89889800700337]

dX = gradient(X); % Numerical Derivative

dY = gradient(Y); % Numerical Derivative

Len = cumtrapz(X,hypot(dX,dY)) % Integrate The Hypotenuse Of The Numerical Derivatives Of The Segments

figure

plot(X, Y, '.-')

hold on

plot(X, Len, '.-')

hold off

grid

.

##### 7 Comments

Star Strider
on 29 Jan 2023

My code calculates the trapezoidal integral of the gradients (numerical derivatives) of ‘X’ and ‘Y’.

Star Strider
on 25 Jan 2024

Following up —

In light of @Torsten’s Comment, using cumtrapz is correct, however including the independent variable as the first argument to it in this instance may not be —

X=[96.0741000000000,97.1940000000000,98.3139000000000,99.4338000000000,100.553700000000,101.673600000000,102.793500000000,103.913400000000,105.033300000000,106.153200000000,107.273100000000,108.393000000000,109.512900000000,110.632800000000,111.752700000000,112.872600000000,113.992500000000,115.112400000000,116.232300000000];

Y=[-4.13836296940031,-4.10455468315876,-4.05645426203322,-3.99617782198545,-3.92344322326347,-3.83385191481492,-3.73582865974161,-3.61740402741020,-3.49399064332423,-3.35231953224592,-3.20552503148528,-3.04892626846560,-2.88658570885772,-2.72091440408539,-2.55226630046971,-2.38425597793465,-2.21787687713447,-2.05656258174384,-1.89889800700337];

dX = gradient(X); % Numerical Derivative

dY = gradient(Y); % Numerical Derivative

Len = cumtrapz(hypot(dX,dY)); % Integrate The Hypotenuse Of The Numerical Derivatives Of The Segments

Len_end = Len(end)

figure

plot(X, Y, '.-', 'DisplayName','Data')

hold on

plot(X, Len, '.-', 'DisplayName','Length')

hold off

grid

title('Provided Data')

legend('Location','best')

axis('equal')

axis('padded')

a = linspace(0, 2*pi, 1E+3);

X = cos(a);

Y = sin(a);

dX = gradient(X); % Numerical Derivative

dY = gradient(Y); % Numerical Derivative

Len = cumtrapz(hypot(dX,dY)); % Integrate The Hypotenuse Of The Numerical Derivatives Of The Segments

Len_end = Len(end)

figure

plot(X, Y, '.-', 'DisplayName','Data')

hold on

plot(X, Len, '.-', 'DisplayName','Length')

hold off

grid

title('Circle (Radius = 1)')

legend('Location','best')

axis('equal')

axis('padded')

My code is unchanged, however it now includes a second data set (the circle) whose result can be checked.

.

Torsten
on 26 Aug 2022

Edited: Torsten
on 26 Aug 2022

I'd say Ankit's solution is the more intuitive.

But Star Strider's solution should be second-order accurate while Ankit's is only first-order accurate.

Y=[-4.13836296940031,-4.10455468315876,-4.05645426203322,-3.99617782198545,-3.92344322326347,-3.83385191481492,-3.73582865974161,-3.61740402741020,-3.49399064332423,-3.35231953224592,-3.20552503148528,-3.04892626846560,-2.88658570885772,-2.72091440408539,-2.55226630046971,-2.38425597793465,-2.21787687713447,-2.05656258174384,-1.89889800700337];

length = 0;

for i = 1:numel(X)-1

length = length + sqrt((X(i+1)-X(i))^2 + (Y(i+1)-Y(i))^2);

end

length

##### 0 Comments

Tamas Rozsa
on 29 Jan 2023

Edited: Tamas Rozsa
on 30 Jan 2023

dX = gradient(X);

dY = gradient(Y);

% option 1

Len = cumsum(hypot(dX,dY)) % if sublengths of all segments also needed

% option 2

Len = sum(hypot(dX,dY)) % if only total length needed

As @Star Strider also highlighted in comment, gradient() may be substituted with diff(), but gradient() may give more satisfactory (i.e., smoother) result in most cases. [UPDATE: in some cases, and depending on the actual use-case]

Unlike @Star Strider's original answer, this code gives correct result even in case of arbitrary spacing in the input data as well as in case of vertical line segments.

##### 3 Comments

Tamas Rozsa
on 30 Jan 2023

Because it also depends on the input data.

My main message was not really about the accuracy, but to point out that @Star Strider's solution is buggy and shall never be used by anyone in that way.

It accidentally gave kinda fair result for the OP input data, but fails heavily e.g. in the two scenarios I've mentioned:

- arbitrary spacing, e.g.:

X = logspace(-10,0,200);

Y = sqrt(1-X.^2);

(result is 0.11 instead of ca. 1.57 (pi/2))

- vertical line segments, e.g.:

X = ones(1,200);

Y = logspace(-10,1,200);

(result is 0 instead of ca. 10).

The accuracy is another topic; diff() is indeed better here than gradient().

Walter Roberson
on 21 Jul 2023

No, you cannot really get the length of a curve defined by a finite list of points. A finite list of 2D points does not define a curve: a finite list of 2D points defines a polygon at best (possibly a self-interesecting one.)

In order to get a curve length, you either have to be given a curve equation, or else you have to be willing to approximate the true curve length by using a model. The model might over-estimate or under-estimate the true curve length.

Mathematically it is impossible to be given a finite set of points that are finitely expressed, and use them to come up with "the" defining curve. Mathematically given any finite set of points that are finitely expressed, there are an uncountable infinity of curves that go through the given points. (Allowing for the possibility that there is noise or round-off or truncation error in the list of coordinates does not increase the number of possible curves, as uncountable infinity is the largest infinity already until you get into abstractions such as Aleph-One )

The answers posted by the other participants are either finding total segment lengths (treating the point list as a polygon whose perimeter is to be found), or else are using different models of how to interpolate the points into a curve. They produce different results because they use different interpolation methods. That does not make any of them "wrong", just different. Unless you know the form of the original function, you just have to accept that the problem is under-specified.

##### 0 Comments

### See Also

### Community Treasure Hunt

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

Start Hunting!