How could I do all of this in a more effective way?
An alternative approach using LineScaledCoordinate
from GraphUtilities
:
Needs["GraphUtilities`"]
p = {{0, 0}, {5, 8.07774721}, {10, 4.24499363}, {20, 9.28880172}};
n = 30;
pts = LineScaledCoordinate[p, N@(#/n)] & /@ Range[0, n];
ListPlot[{p, pts}, PlotStyle -> {Blue, Directive[PointSize[Medium], Red]},
Joined -> {True, False}]
Update:
Even simpler alternative is to use MeshFunctions -> {"ArcLength"}
:
ListPlot[p, Joined -> True, MeshFunctions -> {"ArcLength"},
Mesh -> (n-1), MeshStyle -> Directive[Red, PointSize[Medium]]]
Perhaps something like this, except with the number of points you actually wanted:
p = {{0, 0}, {5, 8.07774721}, {10, 4.24499363}, {20, 9.28880172}};
n = 30;
partialPath =
EuclideanDistance[p[[# + 1]], p[[#]]] & /@ Range[Length[p] - 1] // N;
nparts = n*partialPath/Total[partialPath] // Round;
check = TrueQ[n == Total@nparts]
s1 = Table[
Subdivide[p[[i, 1]], p[[i + 1, 1]], nparts[[i]]], {i, 1,
Length[p] - 1}];
s2 = Table[
Subdivide[p[[i, 2]], p[[i + 1, 2]], nparts[[i]]], {i, 1,
Length[p] - 1}];
s = Transpose[{Flatten@s1, Flatten@s2}];
Graphics[{Blue, PointSize[0.02], Point[s],
Red, PointSize[0.02], Point[p]}]
The list s
will contain some redundant points. One way to remove the redundancy is to use s = Union[s]
. A side effect of Union
, however, is that it returns a sorted list. The redundant points are given by p[[2;;-2]]
so they could be removed using DeleteCases
.