Here is an arc-length reparametrization in terms of a function tfn
that maps the arclength along the B-spline curve 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];
(* g defined as in OP *)
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]
Aspect ratio
If you want a different aspect ratio other than Automatic
, 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];
(* g defined as in OP *)
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"]]]]
Here is another way based on my answer to this question:
Different MeshStyle for different functionsDifferent MeshStyle for different functions
It used to not work on Windows, but I'm not sure about whether that is so for V10.
ParametricPlot[g[t], {t, 0, 1},
PlotStyle -> {Directive[CapForm["Round"], Dashing[{0, 0.06}],
Thickness[0.02]], Directive[]}, AspectRatio -> 1/GoldenRatio]