Random points around the given curve
Using RandomPoint[]
with TubeMesh[]
(routines from here and here) does the job:
helix = First[Cases[Normal[ParametricPlot3D[{6 Cos[t], 6 Sin[t], t}, {t, -2 π, 4 π},
MaxRecursion -> 1, PlotPoints -> 75]],
Line[l_] :> l, ∞]];
tube = TubeMesh[helix, 1/2, "CapForm" -> "Round"];
BlockRandom[SeedRandom[42];
Graphics3D[{AbsolutePointSize[1], Point[RandomPoint[tube, 5000]]}]]
There are many ways to define a random collection of points that all fall within a distance 0.5 of the curve. If a uniform distribution within a "tube" of radius 0.5 surrounding the curve is what you want and have a newer version of Mathematica, then @J.M.'s answer is the way to go.
If you have an older version of Mathematica, here is a brute-force approach:
(* Random error about curve no farther than 0.5 *)
n = 1000;
(* Random points within a uniform box around curve *)
r0 = RandomVariate[UniformDistribution[{-0.5, 0.5}], 3 n];
rC = RandomVariate[UniformDistribution[{-0.5, 0.5}], 3 n];
rS = RandomVariate[UniformDistribution[{-0.5, 0.5}], 3 n];
(* Keep the first n points that are within 0.5 of the curve *)
error = Select[Transpose[{rC, rS, r0}], Norm[#] <= 0.5 &, n];
(* Random position along curve *)
rt = RandomVariate[UniformDistribution[{-2 π, 4 π}], n];
(* Show resulting cloud of points and curve *)
Show[ParametricPlot3D[{6 Cos[t], 6 Sin[t], t}, {t, -2 π, 4 π},
PlotTheme -> "Detailed", PlotStyle -> {Blue, Thickness[Large]},
Boxed -> False, PlotPoints -> 150],
ListPointPlot3D[Transpose[{6 Cos[rt], 6 Sin[rt], rt}] + error,
BoxRatios -> {1, 1, 1}]]
This answer is based on a different line of reasoning than my previous answer.
plot = ParametricPlot3D[{6 Cos[t], 6 Sin[t], t}, {t, -2 Pi,
4 Pi}, PlotTheme -> "Detailed",
PlotStyle -> {Red, Thickness[Large]}, Boxed -> False,
PlotPoints -> 150];
After inspecting FullForm @ plot
, one can extract a Line
with Cases[FullForm @ plot, _Line, Infinity]
and transform it to a Cylinder
(Tube
would be more straightforward, but it's not a Region
):
Show[plot /. Line[z_] :> Cylinder[Partition[z, 2, 1], 0.5], PlotRange -> All]
Looks good, so
reg = Cases[FullForm @ plot, _Line, Infinity] /.
Line[z_] :> Cylinder[Partition[z, 2, 1], 0.5] // First
and then
points = RandomPoint[reg, 1000];
to give
Show[plot, ListPointPlot3D @ points]
line = Cases[FullForm @ plot, _Line, Infinity][[1]];
dist = RegionDistance[line, #] & /@ points; // AbsoluteTiming
{63.0501, Null}
Histogram @ dist
The distance from the curve has a peculiar distribution, though.
Previous answer
Employing RandomPoint @ Ball
:
Clear[plot, data, line, dist]
f[t_] := {6 Cos[t], 6 Sin[t], t}
c = ParametricPlot3D[f[t], {t, -2 Pi, 4 Pi},
PlotTheme -> "Detailed", PlotStyle -> {Red, Thickness[Large]},
Boxed -> False, PlotPoints -> 150];
plot = ListPointPlot3D @ (data =
Table[RandomPoint @ Ball[f[t], 0.5], {t, -2 Pi, 4 Pi, 0.01}]);
Show[c, plot]
Checking the distance distribution:
line = Cases[FullForm @ c, _Line, Infinity][[1]];
dist = RegionDistance[line, #] & /@ data; // AbsoluteTiming
{120.033, Null}
Length @ dist
1885
Histogram @ dist