13
$\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$ Commented 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$ Commented Mar 19, 2013 at 21:02

5 Answers 5

15
$\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$ Commented 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$ Commented 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$ Commented Mar 19, 2013 at 13:47

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.