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.

Based on this description of 3D graphics and the associated Wolfram Training video, I anticipated that using the mouse to rotate the graphic below would rotate around the point where the three cylinders intersect:

axis = {EdgeForm[], Specularity[White, 10],
   FaceForm[Red], Cylinder[{{0, 0, 0}, {0, 0, .5}}, 0.01],
   FaceForm[Blue], Cylinder[{{0, 0, 0}, {0, .5, 0}}, 0.01],
   FaceForm[Green], Cylinder[{{0, 0, 0}, {.5, 0, 0}}, 0.01]
   };
Graphics3D[axis, Boxed -> True, ViewCenter -> {0, 0, 0}, 
 RotationAction -> "Clip", ViewAngle -> 65 Degree]

So far so good. When I make a slight adjustment to the graphic, though, the (for lack of a better term) swivel point has moved to what appears to be {-0.5,-0.5,-0.5}.

Graphics3D[{axis, Opacity[0.5], Sphere[{0, 0, 0}, 0.5]}, 
 ViewCenter -> {0, 0, 0}, RotationAction -> "Clip", 
 ViewAngle -> 65 Degree]

Can someone enlighten me as to my misinterpretation of ViewCenter and how I can get the second object to rotate around {0,0,0} when using the mouse?

share|improve this question
    
Better term for "swivel point" is "pivot point –  m_goldberg Jul 4 '13 at 16:23
    
A good explanation of the concepts is in the answer by Yu-Sung Chang to this question –  Jens Jul 4 '13 at 19:32
    
@Jens I agree, that's what the first link in my question is (although I had forgotten how to link to a specific answer). –  bobthechemist Jul 4 '13 at 21:12
    
Sorry, I must have overlooked your link... –  Jens Jul 5 '13 at 2:13

3 Answers 3

up vote 4 down vote accepted

Try using ViewVector, it can take both scaled and unscaled coordinates.

Graphics3D[{axis, Opacity[.5], Sphere[{0, 0, 0}, 0.5]}, 
  ViewVector -> {Scaled@{1.3, -2.4, 2}, {0., 0., 0.}}, 
  RotationAction -> "Clip", 
  ViewAngle -> 65 Degree]

The expression Scaled@{1.3, -2.4, 2} is the default for ViewPoint.

share|improve this answer

I believe the key detail from the documentation is:

The setting for ViewCenter is given in scaled coordinates, which run from 0 to 1 across each dimension of the bounding box.

share|improve this answer
    
Yes, the OP should use ViewCenter -> {.5, .5, .5}, to get what he wants. –  m_goldberg Jul 4 '13 at 15:35
1  
I really don't like the current functionalities available to zoom and rotate 3D plots. Is it just me? Why hasn't WR used the same paradigms used on most CAD softwares: a pivot point (ViewCenter), that appears when MouseOver, and that we can displace by mouse (3d Locator) and snap it to the nearest object on the scene. And similar applies to zoom. (currently, rotating and zooming the same scene is completely impossible to manage) –  P. Fonseca Jul 4 '13 at 16:14
    
@m_goldberg not quite, I would like the pivot point to be the unscaled {0,0,0} in both images; I'm thinking along the lines of a reverse ImageScaled. –  bobthechemist Jul 4 '13 at 16:14
    
@bobthechemist this happens to me a lot. I mean, the need to pivot around a very precise coordinate. –  P. Fonseca Jul 4 '13 at 16:16

I'm not a fan of answering my own question, but I think this might be helpful. After being told to read the documentation closely and realizing that ViewCenter, I want a way to provide absolute coordinates to ViewCenter. I can do this with a RescaleTransform if I know the coordinate extremes a priori. This is true for the contrived example given in the question but not in my real-world problem. I then came across this answer that describes a method for extracting absolute coordinates from a Graphics or Graphics3D object. Putting all this together, I have come up with the following:

plotRange[plot : (_Graphics | _Graphics3D)] := 
 Quiet@Last@
   Last@Reap[
     Rasterize[
      Show[plot, PlotRangePadding -> None, Axes -> True, 
       Ticks -> (Sow[{##}] &), DisplayFunction -> Identity], 
      ImageResolution -> 1]]

axis = {EdgeForm[], Specularity[White, 10], FaceForm[Red], 
   Cylinder[{{0, 0, 0}, {0, 0, .5}}, 0.01], FaceForm[Blue], 
   Cylinder[{{0, 0, 0}, {0, .5, 0}}, 0.01], FaceForm[Green], 
   Cylinder[{{0, 0, 0}, {.5, 0, 0}}, 0.01]};

obj1 = {axis, Opacity[0.5], Sphere[{0, 0, 0}, 0.5]};
obj2 = {axis, Opacity[0.5], Sphere[{0.5, 0.5, 0.5}, 0.5]};

With[{obj = obj2},
 Graphics3D[obj, Boxed -> True, 
  ViewCenter -> 
   RescalingTransform[
     plotRange[Graphics3D@obj], {{0, 1}, {0, 1}, {0, 1}}][{0, 0, 0}],
  RotationAction -> "Clip", ViewAngle -> 45 Degree]]

This is not a very elegant hack (is that an oxymoron?) but it seems to work for the few examples I've tried so far.

share|improve this answer

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.