# Computing arch length of a spline curve

GROUPS:
 Vitaliy Kaurov 5 Votes I have a project where I need to color spline curves according to their arch length. How can I find spline arch length efficiently? Spline is a parametric curve, so arch length is defined asI see two ways to do this. One is to use NIntegrate (I heard that Integrate will not return a closed form solution). The other way is to discretize manually and add lengths of line segments:We start from some points and a BSplineFunction:pts = {{1, 1}, {2, -1}, {3, 0}, {2, 1}, {1, 0}};f = BSplineFunction[pts];Then we sample BSplineFunction to get close points along its curve:steps = Table[f[t], {t, 0, 1, .1}];Show[Graphics[{Red, Point[pts], Green, Line[pts], Orange, PointSize[.02], Point[steps], Green}],     ParametricPlot[f[t], {t, 0, 1}], Axes -> False]Now we can see that even we that few points along the curve values of integral and sum are close:NIntegrate[Norm[D[f[t], t]], {t, 0, 1}]Out ==> 4.57294Total[EuclideanDistance @@@ Partition[steps, 2, 1]]Out ==> 4.53213So my questions are the following:Do our spline functions contain somehow information about arch their length? Will NIntegrate method always work or will it break for some splines (at pinching curve points for example)? Are there more efficient numeric methods? As much as I know symbolic solution is not known in closed form – is this true? I was trying to break NIntegrate with this app, but could not (at least with MaxRecursion -> 12).  Manipulate[  BSF = BSplineFunction[pt, SplineClosed -> clsd];  SPS = Table[BSF[t], {t, 0, 1, stp}];    Show[   Graphics[{Red, PointSize[.015], Point[SPS]}],   ParametricPlot[BSF[t], {t, 0, 1}, PlotStyle -> Black],   PlotRange -> 1, ImageSize -> 400 {1, 1}, Axes -> False,   BaseStyle -> Directive[FontSize -> 15, Blue, Bold],  Epilog ->   {Text["INTEGRAL = " <>           ToString[NIntegrate[Norm[D[BSF[t], t]], {t, 0, 1}, MaxRecursion -> 12]], {-.55, -.95}],    Text["SUM = " <> ToString [Total[EuclideanDistance @@@ Partition[SPS, 2, 1]]], {.25, -.95}]}], {{pt, .8 Tuples[{0, 1, -1}, 2]}, Locator, LocatorAutoCreate -> True}, Row[{Control@{{clsd, False, "Closed?"}, {False, True}}, Spacer[20],       Control@{{stp, .01, "step"}, .001, .1}}], FrameMargins -> 0, SaveDefinitions -> True]
6 years ago
4 Replies
 Carl Woll 7 Votes I like to use NDSolve to do these kinds of computations:In[118]:= nds=NDSolve[{s'[t] == Norm[f'[t]], s[0]==0},s,{t,0,1}];arclength=s/.First@nds;In[120]:= arclength[1]Out[120]= 4.57294
6 years ago
 This is a very nice approach, Carl, thank you. I found it to be more robust than integration for a large number of points.
6 years ago
 Ulises Cervantes Pimentel 8 Votes By the way, Plot and ParametricPlot/ParametricPlot3D for curves, can take as MeshFunctions the values "ArcLength" and "CurveLength". So, for example:pts = {{1, 1}, {2, -1}, {3, 0}, {2, 1}, {1, 0}};BSF = BSplineFunction[pts]mpoints = Table[t, {t, 0, 5, 0.5}]ParametricPlot[BSF[t], {t, 0, 1}, MeshFunctions -> {"CurveLength"}, Mesh -> {mpoints}, MeshStyle -> {PointSize[0.02], Red}]will create mesh points at the corresponding curve lengths, so from the plot we see that the length is a little bigger than 4.5.Now, try:mpoints = Table[t, {t, 0, 1, 0.1}]ParametricPlot[BSF[t], {t, 0, 1}, MeshFunctions -> {"ArcLength"}, Mesh -> {mpoints}, MeshStyle -> {PointSize[0.02], Red}]In this case the curve length is normlized between (0,1). We do not have a MeshScaling option, that is why we use "CurveLength" vs "ArcLength".These predefined mesh functions allow for very simple examples, like your own dashing styles:mpoints = Table[t, {t, 0, 1, 0.05}];ParametricPlot[BSF[t], {t, 0, 1}, MeshFunctions -> {"ArcLength"}, Mesh -> {mpoints}, MeshStyle -> {PointSize[0.015], Blue}, MeshShading -> {Red, Green}]Hope this helps.
6 years ago
 Vitaliy Kaurov 1 Vote With the release of computational geometry we can simply do RegionMeasure: pts = {{1, 1}, {2, -1}, {3, 0}, {2, 1}, {1, 0}}; RegionMeasure[DiscretizeGraphics[Graphics[BSplineCurve[pts]]]] (*4.435030548461937*) `