12
$\begingroup$

I have a set of Graphics3D primitives (here, spheres) which I would like to assign either:

  1. One of a subset of colors, e.g. {Green, Red}
  2. A random color over some RGB interval

Writing something like:

Graphics3D[{RGBColor[RandomInteger[{0, 1}], RandomInteger[{0, 1}], RandomInteger[{0, 1}]],
            Sphere[{#[[1]], #[[2]], #[[3]]}, #[[4]]] & /@ SphereList...

...appears to only assign one random color to all of the spheres.

I can force this to work by generating a string that explicitly specifies a random color for each sphere, but is there a simpler way to make this work?

$\endgroup$
2
  • 1
    $\begingroup$ Related / relevant (and a classic): mathematica.stackexchange.com/q/1900/131 $\endgroup$
    – Yves Klett
    Mar 19, 2013 at 13:42
  • $\begingroup$ you know your original works just fine, except by using randominteger[0,1] you end up with only 8 colors $\endgroup$
    – george2079
    Mar 19, 2013 at 21:02

5 Answers 5

14
$\begingroup$

A cute way to do this is by using Riffle with an Unevaluated second argument:

spherelist =  Sphere[{##2}, Abs[0.2 #]] & @@@ RandomReal[{-1, 1}, {50, 4}];

Graphics3D @ Riffle[spherelist, Unevaluated[Random[] // Hue], {1, -2, 2}]

enter image description here

For random red or green use RandomChoice:

Graphics3D @ Riffle[spherelist, Unevaluated[RandomChoice[{Red, Green}]], {1, -2, 2}]

enter image description here

$\endgroup$
1
  • $\begingroup$ how can we fine all the balls in an unit cube? $\endgroup$
    – ABCDEMMM
    Jun 14, 2020 at 2:31
4
$\begingroup$

Not very effective, but useful if you go for postprocessing of existing Graphics primitives:

spheres = 

  Sphere[#[[1 ;; 3]], #[[4]]/2] & /@ RandomReal[{-1, 1}, {10, 4}];

Graphics3D[spheres]

Mathematica graphics

Graphics3D[spheres] /. s_Sphere :> Sequence[RGBColor[RandomReal[{0, 1}, 3]], s]

Mathematica graphics

Repeated evalutation will yield individual coloring.

$\endgroup$
1
  • $\begingroup$ how can we fine all the balls in an unit cube? $\endgroup$
    – ABCDEMMM
    Jun 14, 2020 at 2:32
3
$\begingroup$

Based on your code (using RandomInteger), you could include the "Color-generation" in the pure function, so that any time you map the function on the sphere-list, a new random sample is drawn:

Graphics3D[{RGBColor[RandomInteger[{0, 1}], RandomInteger[{0, 1}], 
 RandomInteger[{0, 1}]], 
 Sphere[{#[[1]], #[[2]], #[[3]]}, #[[4]]]} & /@ 
 RandomReal[5, {10, 4}]]

enter image description here

and likewise:

Graphics3D[{RandomChoice[{Red, Green}], 
Sphere[{#[[1]], #[[2]], #[[3]]}, #[[4]]]} & /@ 
RandomReal[5, {10, 4}]]

for red/green:

enter image description here

$\endgroup$
3
$\begingroup$

With V10 we can use RandomColor

Graphics3D[Table[{RandomColor[],
   Sphere[RandomReal[{.1, .9}, 3], RandomReal[{0.03, 0.08}]]}, {50}],
 Lighting -> "Neutral"]

enter image description here

Graphics3D[Table[{RandomColor[1, ColorSpace -> "LUV"],
   Sphere[RandomReal[{.1, .9}, 3], RandomReal[{0.03, 0.08}]]}, {50}],
 Lighting -> "Neutral"]

enter image description here

$\endgroup$
2
$\begingroup$

You need to have a function that returns a list, where the first element is the color and the second element the sphere. Then you apply that function to your list of spheres.

coloredSphere[coordinates_] := {RGBColor[Sequence @@ RandomInteger[{0, 1}, 3]], 
    Sphere[coordinates[[;; 3]], coordinates[[4]]]};

Graphics3D[coloredSphere /@ listOfSpheres]

enter image description here

Also, you might want to use RandomReal instead of RandomInteger, but that's up to you.

Edit: The Flatten inside Graphics3D is not even necessary, as I realized by reading the other reply.

$\endgroup$
1
  • $\begingroup$ ...always that much better with added Graphics3D... $\endgroup$
    – Yves Klett
    Mar 19, 2013 at 13:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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