# Am I missing the point of ViewCenter?

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?

• Better term for "swivel point" is "pivot point Jul 4, 2013 at 16:23
• A good explanation of the concepts is in the answer by Yu-Sung Chang to this question
– Jens
Jul 4, 2013 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). Jul 4, 2013 at 21:12
– Jens
Jul 5, 2013 at 2:13

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.

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.

• Yes, the OP should use ViewCenter -> {.5, .5, .5}, to get what he wants. Jul 4, 2013 at 15:35
• 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) Jul 4, 2013 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. Jul 4, 2013 at 16:14
• @bobthechemist this happens to me a lot. I mean, the need to pivot around a very precise coordinate. Jul 4, 2013 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.