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 as
I 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.57294
Total[EuclideanDistance @@@ Partition[steps, 2, 1]]
Out ==> 4.53213
So 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]