Skip to main content
4 of 7
Fixed typos
Michael E2
  • 244.7k
  • 18
  • 351
  • 774

The interpolation overshoots the next point and reverses direction.

ParametricPlot[{line[[1]][tt], line[[2]][tt]}, {tt, 0.2, 0.3}, 
 Epilog -> {Point[points[[All, 1 ;; 2]]]}]

Mathematica graphics

You can reduce the interpolation order to 1 or use a centripetal parametrization parametrizeCurve from J.M.'s answer.

parametrizeCurve[pts_List, a : (_?NumericQ) : 1/2] := 
 FoldList[Plus, 0, Normalize[(Norm /@ Differences[pts])^a, Total]] /; 
  MatrixQ[pts, NumericQ]


tvals = parametrizeCurve[points];
line = Interpolation[Transpose[{tvals, #}]] & /@ Transpose@points;

s[t_?NumericQ] := 
  NIntegrate[Norm[{line[[1]][tt], line[[2]][tt]}], 
   Evaluate @ DeleteDuplicates @
     Flatten[{tt, 0, Select[tvals, 0 < # < t &], t}]];

ParametricPlot[Evaluate@{s[ss], line[[3]][ss]}, {ss, 0, 1}, 
 PlotRange -> {{0, All}, {0, All}}, AspectRatio -> 1/2, 
 Epilog -> {Point@Table[{s[ss], line[[3]][ss]}, {ss, 0, 1, 0.1}]}]

Mathematica graphics

Including the interpolation grid points tvals in NIntegrate speeds up the integration. For a really fast implementation use

s = NDSolveValue[{ss'[t] == Norm[{line[[1]][t], line[[2]][t]}], ss[0] == 0}, ss, {t, 0, 1}]

which constructs an InterpolatingFunction for the arc length.

Michael E2
  • 244.7k
  • 18
  • 351
  • 774