Here is an arc-length reparametrization in terms of a function tfn
that maps the arclength to the parameter t
. It's important to use AspectRatio -> Automatic
to get the spacing even.
There are two truncation-error issues with parametrizing the full length of the curve. One is that the stopping point is found by stepping past the end of the curve. BSplineFunction
does not extrapolate, so I extended its derivative in dg
.The other is actually getting to the end of the curve. I dealt with it by over estimating the arclength and using WhenEvent
to stop the integration. The NIntegrate
used to get the total arclength is fast, so it is not very wasteful in this case. If NIntegate
were slower, one could overestimate the arclength in other ways, e.g. from list2
.
The domain of tfn
runs from 0 to the arclength. To get even spacing, I rescaled an even division of the unit interval to the domain of tfn
.
ClearAll[s, t];
dg[t_?NumericQ] := If[t - 1. <= 0, g'[t], g'[1]];
tfn = NDSolveValue[{t'[s] == 1/Norm[dg[t[s]]], t[0] == 0,
WhenEvent[t[s] == 1, "StopIntegration"]},
t, {s, 0, 1 + NIntegrate[Norm[g'[t]], {t, 0, 1}]}];
ListPlot[g /@ tfn[Rescale[Range[0, 1, 1/20], {0, 1}, First@tfn["Domain"]]],
AspectRatio -> Automatic]
If you want a different aspect ratio, such as the default 1/GoldenRatio
, then we have to adjust how the arclength is computed by scaling the derivative vector, e.g., by {1, 1/GoldenRatio}
.
ClearAll[s, t];
dg2[t_?NumericQ] := If[t - 1. <= 0, g'[t], g'[1]] {1, 1/GoldenRatio};
tfn2 = NDSolveValue[{t'[s] == 1/Norm[dg2[t[s]]], t[0] == 0,
WhenEvent[t[s] == 1, "StopIntegration"]},
t, {s, 0, 1 + NIntegrate[Norm[dg2[t]], {t, 0, 1}]}]
ListPlot[g /@ tfn2[Rescale[Range[0, 1, 1/20], {0, 1}, First@tfn2["Domain"]]]]