Message Boards Message Boards

5
|
9678 Views
|
4 Replies
|
22 Total Likes
View groups...
Share
Share this post:

Computing arch length of a spline curve

Posted 12 years ago
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:
  1. Do our spline functions contain somehow information about arch their length?
  2. Will NIntegrate method always work or will it break for some splines (at pinching curve points for example)?
  3. Are there more efficient numeric methods?
  4. 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]

POSTED BY: Vitaliy Kaurov
4 Replies

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`*)
POSTED BY: Vitaliy Kaurov
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.
This is a very nice approach, Carl, thank you. I found it to be more robust than integration for a large number of points.
POSTED BY: Vitaliy Kaurov
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
POSTED BY: Carl Woll
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract