Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I want to draw a solid or partially transparent hemisphere above a partially transparent cuboid object in Graphics3D. However, I do not know how to do this s.t. only half the sphere is drawn. Here's what the object looks like with the full sphere:

SphereOpacity = 0.5;
CuboidOpacity = 0.5;
SphereColor = Blue;
CuboidColor = Orange;
Graphics3D[{SphereColor, Opacity[SphereOpacity], Sphere[{0, 0, 0.5}, 0.5], 
            CuboidColor, Opacity[CuboidOpacity], Cuboid[{-5, -5, 0}, {5, 5, 0.5}]}, 
            Boxed -> False
]

enter image description here

How might I proceed to "remove" the bottom half the sphere embedded in the cuboid primitive? In general, is there a way to not render/draw parts of a graphics primitive conditioned intersection with another primitive?

share|improve this question
    
One method (using RegionFunction) is shown here. –  whuber May 10 '13 at 22:11
    
If you're interested in this type of geometry, you might enjoy Yu-sung Chan's presentation. –  cormullion May 10 '13 at 23:04
    
@cormullion Thanks, I'd love to take a look but your link doesn't quite work? –  QuadraticU May 10 '13 at 23:15
    
This seems related: mathematica.stackexchange.com/q/3186/121 –  Mr.Wizard May 11 '13 at 9:28

6 Answers 6

up vote 5 down vote accepted
ParametricPlot3D[{Cos[u] Sin[v], Sin[u] Sin[v], Cos[v]}, 
                 {u, 0, π}, {v, 0, π},             
                 Mesh -> None, 
                 Boxed -> False, 
                 Axes -> None
]

some hemisphere

r = 0.5;
d = {0, 0, 0.5}
sphere = ParametricPlot3D[r {Cos[u] Sin[v], Sin[u] Sin[v], Cos[v]} + d, 
            {u, -π/2, π/2}, {v, -π/2, π/2}, 
            Mesh -> None, Boxed -> False, Axes -> None][[1]];

SphereOpacity = 0.5;
CuboidOpacity = 0.5;
SphereColor = Blue;
CuboidColor = Orange;
Graphics3D[{SphereColor, Opacity[SphereOpacity], sphere, CuboidColor, 
            Opacity[CuboidOpacity], Cuboid[{-5, -5, 0}, {5, 5, 0.5}]}, 
           Boxed -> False]

hemisphere and box

share|improve this answer
    
+1 -- but it's a little bit harder to use this technique to draw an arbitrary hemisphere. :-) –  whuber May 10 '13 at 22:50
    
@whuber Not with help of GeometricTransformation, I'd say. –  Sjoerd C. de Vries May 10 '13 at 22:55
    
@SjoerdC.deVries Just for the sake of future readers, you mean GeometricTransformation right? In any case this is great! –  QuadraticU May 10 '13 at 23:14
    
@QuadraticU Roger that –  Sjoerd C. de Vries May 10 '13 at 23:30

To show that there's more than one way to skin a cat, here's another primitive-based method, using NURBS surfaces to render a hemisphere:

With[{r = 1}, 
     Graphics3D[{EdgeForm[],
                 BSplineSurface[Outer[Append[First[#1] #2, Last[#1]] &, 
                       r {{0, 1}, {1, 1}, {1, 0}},
                       {{1, 0}, {1, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {1, -1}, {1, 0}}, 1], 
                                SplineClosed -> {False, True}, SplineDegree -> 2, 
                                SplineKnots -> {{0, 0, 0, 1, 1, 1},
                                                {0, 0, 0, 1/4, 1/2, 1/2, 3/4, 1, 1, 1}}, 
                                SplineWeights -> Outer[Times, {1, 1/Sqrt[2], 1},
                                                       {1, 1/2, 1/2, 1, 1/2, 1/2, 1}]]},
                Boxed -> False]]

another hemisphere

Change r to vary the radius; the control points in the first argument of BSplineSurface[] can be translated and rotated, if the hemisphere needs to be positioned/oriented differently.

If you're interested in this sort of thing, you can refer to work by Piegl and Tiller, e.g. this paper and their book.


Here's another NURBS representation of a hemisphere:

With[{r = 1}, 
     Graphics3D[{EdgeForm[], 
                 BSplineSurface[Outer[Insert[First[#1] #2, Last[#1], 2] &, 
                                      r {{0, -1}, {1, -1}, {1, 1}, {0, 1}},
                                      {{-1, 0}, {-1, 1}, {1, 1}, {1, 0}}, 1],
                                SplineDegree -> 2, 
                                SplineKnots -> {{0, 0, 0, 1/2, 1, 1, 1},
                                                {0, 0, 0, 1/2, 1, 1, 1}},
                                SplineWeights -> Outer[Times, {1, 1/2, 1/2, 1},
                                                              {1, 1/2, 1/2, 1}]]}, 
                Boxed -> False]]

another hemisphere

share|improve this answer
    
Is there a way to get rid of the blemish? –  Mr.Wizard May 12 '13 at 19:26
    
I haven't figured out how. Weirdly, if I use B-splines for the full sphere, I don't see nasty spots at the poles. –  J. M. May 12 '13 at 19:28
    
Too bad; this method is smoother than the Tube method which shows facets. –  Mr.Wizard May 12 '13 at 19:32
    
Okay, I found an alternative; the (antipodal) blemishes are now at the rim, but that might be more acceptable to some. –  J. M. May 13 '13 at 2:07

This peculiar method works in Mathematica versions 7 (thanks, Mr. Wizard!) and 8, but apparently no longer in version 9 (per rm):

Graphics3D[{CapForm["Round"], Tube[{{0, 0, 0}, {0, 0, 0}}, {0, 1}]}, Boxed -> False]

half a ball

(I know CapForm["Round"] can be omitted, since it's the default; I just wanted to indicate that it's the reason for this behavior.)

Replace the 1 with your desired radius. As has been noted, if you need to put your hemispheres into an arbitrary position/orientation, GeometricTransformation[] comes in handy.


A workaround suggested by Anon for version 9 involves a slight perturbation of one of the endpoints, like so:

With[{r = 1, ε = $MachineEpsilon},
     Graphics3D[{CapForm["Round"], Tube[{{0, 0, 0}, {0, 0, ε r}}, {0, r}]}, 
                Boxed -> False]]
share|improve this answer
    
No, it doesn't work in v9... –  rm -rf May 11 '13 at 2:29
    
What does the result look like, then? –  J. M. May 11 '13 at 2:30
    
Just a blank image –  rm -rf May 11 '13 at 2:31
2  
Well, it just doesn't work with two identical points... but using e.g. Tube[{{0, 0, 0}, {10^(-10), 0, 0}}, {0, 1}] one can get the right shape even in v9 –  Pickett May 11 '13 at 11:24
1  
@J.M. Yes, they all give a blank image. The perturbation works though, except for "Butt", which gives a blank image. –  rm -rf May 11 '13 at 13:30

Since no-one has done a RegionPlot3D, I'll do one.

RegionPlot3D[
   x^2 + y^2 + z^2 <= 1
   &&
   z >= 0 ||  
   (-5 < x < 5) && (-5 < y < 5) && (-0.5 < z < 0),
 {x, -2, 2}, {y, -2, 2}, {z, -2, 2},
 Mesh -> None,
 PlotPoints -> 120, 
 PlotStyle -> Directive[Orange, Specularity[Yellow, 12], Opacity[0.8]],
 Boxed -> False,
 Lighting -> {{"Directional", White, {{5, 5, 4}, {2, 2, 0}}}},
 BoundaryStyle -> None, 
 ImageSize -> 600,
 Axes -> False]

plot

RegionPlot3D plots always seem to have that 'home-made' look about them...

share|improve this answer
    
(+1) That gave me another idea: Image3D... –  Jens May 11 '13 at 21:51

Here is another simple way to draw a hemisphere that makes use of the symmetry axis:

hemisphere = 
  First@RevolutionPlot3D[Sqrt[1 - r^2], {r, 0, 1}, Mesh -> None];

Here you can vary the option PlotPoints if needed, to get a more or less dense polygon mesh.

I also extract the contents of the Graphics3D object before using it. This needs to be done whenever you plan to combine the result of a Plot3D-related function with other objects in a single Graphics3D (and be able to do translations, rotations, etc. on the individual objects). To show how it works, here is an example:

plant = First@ExampleData[{"Geometry3D", "PottedPlant"}];

Graphics3D[{
  Translate[
   Scale[Rotate[
     {Brown,
      hemisphere},
     {{0, 0, -1}, {0, 0, 1}}], 25],
   {0, 0, 28}],
  {Darker[Green], plant}
  },
 Lighting -> "Neutral",
 Boxed -> False]

pottedplant

Edit: a raster based approach in version 9

Motivated by cormullion's answer, here is another way:

data3D = With[{reso = .05},
   Table[Boole[x^2 + y^2 + z^2 <= 1
          && 
       z >= 0 || (-5 < x < 5) && (-5 < y < 5) && (-0.5 < z < 
         0)], {x, -2, 2, reso}, {y, -2, 2, reso}, {z, -2, 2, reso}]
   ];

Image3D[data3D]

image3d

The Image3D command is not available before version 9, and its rasterized output may not be desirable - but it has a certain appeal in that you get something similar to a RegionPlot3D, but with a more volumetric appearance.

share|improve this answer

Using whuber's method, we can generate a hemisphere with elevation $\alpha$ and horizon $\theta$ using ContourPlot as follows:

α = 0;
θ = 0;

normal = Cross[{Cos[θ], Sin[θ], 0}, {Cos[α] (-Sin[θ]), Cos[α] Cos[θ], Sin[α]}];

ContourPlot3D[x^2 + y^2 + z^2, {x, -1, 1}, {y, -1, 1}, {z, -1, 1},
 Contours -> {1}, ContourStyle -> Opacity[0.5], Mesh -> None, 
 RegionFunction -> Function[{x, y, z}, normal.{x, y, z} >= 0]]
share|improve this answer
    
This was a bit too long to leave as a comment. –  QuadraticU May 10 '13 at 23:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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