1
$\begingroup$

I'm trying to generate a plot of a few random straigth lines in 3D using the code below:

line[s_, x_, y_, z_, u_, phi_] := {
  x + s Sqrt[1 - u^2] Cos[phi],
  y + s Sqrt[1 - u^2] Sin[phi],
  z + s u
  }

x0[n_] := RandomReal[{-10, 10}];
y0[n_] := RandomReal[{-10, 10}];
z0[n_] := RandomReal[{-10, 10}];
u0[n_] := RandomReal[{-1, 1}];
phi0[n_] := RandomReal[{0, 2 Pi}];

severalLines[s_] := Table[
  line[s, x0[n], y0[n], z0[n], u0[n], phi0[n]], {n, 1, 4}]

linesGraphics = 
  ParametricPlot3D[severalLines[s], {s, -20, 20}, PlotPoints -> 2];

Show[linesGraphics,
 PlotRange -> {{-10, 10}, {-10, 10}, {-10, 10}},
 Axes -> True,
 Ticks -> None,
 AxesStyle -> Opacity[0.25],
 AxesOrigin -> {0, 0, 0},
 SphericalRegion -> True,
 Method -> {"RotationControl" -> "Globe"},
 ImageSize -> {700, 700}
 ]

This code gives a large pack of random lines and doesn't give just 4 random straight lines. What am I doing wrong with the random functions?

For a given line, the values of x0, y0, z0, u0 and phi0 should be random, but stay fixed for that line. The values should be different for a second line, and so on.

$\endgroup$
6
  • 1
    $\begingroup$ Your n_ argument isn't even used in the body of the functions e.g: x0[n_] := RandomReal[{-10, 10}]; $\endgroup$
    – flinty
    Nov 30 '20 at 15:06
  • 1
    $\begingroup$ try linesGraphics = ParametricPlot3D[Evaluate@severalLines[s], {s, -20, 20}, PlotPoints -> 2]? $\endgroup$
    – kglr
    Nov 30 '20 at 15:09
  • 4
    $\begingroup$ If all you want is a few random lines, consider the much simpler Graphics3D[{InfiniteLine /@ RandomReal[{-10, 10}, {4, 2, 3}]}] where 4 is the number of lines to generate, and {-10, 10} the range of coordinates. $\endgroup$
    – MarcoB
    Nov 30 '20 at 15:09
  • $\begingroup$ It's also very simple to create random lines with a uniform (in the sphere) direction distribution and finite random lengths and positions like this: pastebin.com/09sx1RbX $\endgroup$
    – flinty
    Nov 30 '20 at 15:15
  • $\begingroup$ another minimal change in your code: add the option MaxRecursion -> 0 in ParametricPlot3D[...] $\endgroup$
    – kglr
    Nov 30 '20 at 15:38
2
$\begingroup$

UseRandomPoint to generate points in a 3D-region. In this case it is a cuboid as shown in the figure below.

pts = RandomPoint[Cuboid[{-10, -10, -10}, {10, 10, 10}], {80, 2}];

Graphics3D[{
  {Black, PointSize[0.01], Point /@ pts}, (* optional *)
  {Thick, Hue[RandomReal[{0, 1}]], Line@#} & /@ pts
  }
 , Boxed -> True
 , BoxRatios -> {1, 1, 1}
 , Axes -> True
 ]

enter image description here

$\endgroup$
1
  • $\begingroup$ This is a fine solution assuming criteria for "random straight lines" are free - if the statistical properties implied by the original code are required it is a different question, though. On the original example all lines would be of same length. Also, in the case of original code, difference between line endpoint coodinates for a single coordinate follow uniform distribution, while the code above produces a triangular distribution (just to point out a trivial difference between solutions)... $\endgroup$
    – kirma
    Dec 29 '21 at 13:16
1
$\begingroup$

Okay, I just found the easy solution. I'm back at Mathematica after a long time, so I'm really rusty!

The solution is to add memorization with this code:

x0[n_] := x0[n] = RandomReal[{-10, 10}];
y0[n_] := y0[n] = RandomReal[{-10, 10}];
z0[n_] := z0[n] = RandomReal[{-10, 10}];
u0[n_] := u0[n] = RandomReal[{-1, 1}];
phi0[n_] := phi0[n] = RandomReal[{0, 2 Pi}];

It was really that simple. Doh!

$\endgroup$
1
$\begingroup$

I am not sure how useful this answer is -- I am mostly trying to utilize RandomTabularDataset.

(The only advantage of this approach compared to the codes in the question and answer by @Cham is that all parameters are seen "up-front", in a table.)

SeedRandom[8];
numberOfLines = 5;
dsTbl = 
  ResourceFunction["RandomTabularDataset"][{numberOfLines, Characters["xyzup"]}, "Generators" -> Join[Table[RandomReal[{-10, 10}, #] &, 3], {RandomReal[{-1, 1}, #] &, RandomReal[{0, 2 \[Pi]}, #] &}]]

enter image description here

Clear[ParLine, s];
ParLine[s_, pars_?AssociationQ] := {#x + s Sqrt[1 - #u^2] Cos[#p], #y + s Sqrt[1 - #u^2] Sin[#p], #z + s #u} &@pars;
ParLine[s, #] & /@ Normal[dsTbl]

(*{{-5.98607 + 0.544786 s, 9.5079 + 0.138432 s, 5.90568 + 0.82707 s},
{-2.53347 + 0.686134 s, -3.07295 + 0.727169 s, -6.31399 - 0.021085 s},
{-8.33192 + 0.0881647 s, -3.40842 - 0.805351 s, -5.89875 - 0.586206 s},
{-0.979458 - 0.196043 s, 2.68434 - 0.223576 s, -7.79644 - 0.954767 s},
{3.91067 + 0.828513 s, -6.02554 - 0.386902 s, -8.50724 - 0.404813 s}}*)
Clear[SeveralLines];
SeveralLines[s_] := ParLine[s, #] & /@ Normal[dsTbl];
ParametricPlot3D[SeveralLines[s], {s, -20, 20}, FaceGrids -> {{0, 0, -1}, {0, 1, 0}, {-1, 0, 0}}]

enter image description here

$\endgroup$
1
$\begingroup$

I interpreted the code as a geometric intent to generate uniformly randomly oriented displacements of length s from points uniformly distributed inside the {-10, -10, -10}, {10, 10, 10} cuboid.

I first sample the starting points in the cuboid, then add random points on a s-sized sphere as displacement vectors. This should correspond with the intent and the statistical properties of the original code. At least the code is much simpler than the original:

With[{n = 100},
  RandomPoint[Cuboid[{-10, -10, -10}, {10, 10, 10}], n] +
   s RandomPoint[Sphere[], n]] //
 ParametricPlot3D[#, {s, -20, 20}, BoxRatios -> Automatic] &

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.