Equidistant points on a polyline
You need what is sometimes called a reparametrization by arc length. Since the velocity is piecewise constant, it might done as follows:
p = RandomReal[{-1, 1}, {20, 2}];
f = BSplineFunction[p, SplineDegree -> 1, SplineClosed -> True];
arclengths = Accumulate[Norm /@ Subtract @@@ Partition[p, 2, 1, 1]];
totalarclength = Last[arclengths];
t = Interpolation[
Transpose@{Prepend[arclengths, 0.], Range[0, 1, 1/Length[p]]},
InterpolationOrder -> 1];
Graphics[{Point[p], Opacity[.2],
Point[(f[t[#]]) & /@ Range[0, totalarclength, totalarclength/1000]]}]
Or one could use calculus to find t
as in the link in Vitaliy Kaurov's comment that I just noticed, or in this alternative way:
v[t_?NumericQ] := Norm[f'[t]];
t = NDSolveValue[{tt'[s] == 1/v[tt[s]], tt[0] == 0}, tt, {s, 0, totalarclength}];
p = RandomReal[{-1, 1}, {5, 2}];
f = BSplineFunction[p, SplineDegree -> 1, SplineClosed -> True];
A very simple approach:
np[u_, dt_] := u + dt/ Norm[D[f[t], t]] /. t -> u;
ListPlot[Table[f[t], {t, NestWhileList[np[#, .03] &, 0, # < 1 &]}], AspectRatio -> 1]
Testing that the points are equidistant:
ListLinePlot[EuclideanDistance @@@
Partition[Table[f[t], {t, NestWhileList[np[#, .03] &, 0, # < 1 &]}], 2, 1],
AxesOrigin -> {0, 0}]
The only small exceptions are at the original points, as expected.
Edit
For a higher degree interpolation:
p = RandomReal[{-1, 1}, {7, 2}];
f = BSplineFunction[p, SplineDegree -> 5, SplineClosed -> True];
GraphicsRow@{
ListPlot[Table[f[t], {t, NestWhileList[np[#, .003] &, 0, # < 1 &]}], AspectRatio -> 1],
ListLinePlot[EuclideanDistance @@@
Partition[Table[f[t], {t, NestWhileList[np[#, .003] &, 0, # < 1 &]}], 2, 1],
AxesOrigin -> {0, 0}, PlotRange -> All]}