
I'm trying to rotate a model about a specified axis and origin (preferably in global coordinates). I would like the rotation to be applied on top of whatever transformations have been applied already. I've looked at the documentation, including the programmer's FAQ and the source code for ConstrainedMove. I couldn't figure out how to do this, so I wrote the following function based on the ConstrainedMove code to do the rotation relative to another model: def rotate_around_model_axis(ref_model, model, origin, axis, angle_deg): mvo = apply(chimera.Vector, origin) vo = ref_model.openState.xform.apply(mvo) mva = apply(chimera.Vector, axis) va = ref_model.openState.xform.apply(mva) xf = chimera.Xform() xf.translate(vo) xf.rotate(va, angle_deg) xf.translate(-vo) model.openState.globalXform(xf) But, this doesn't seem to work as I'd intended. Is there a way to do this? Also, I'm a little confused about the coordinate system. It seems like the concept of a global coordinate system may not apply in Chimera the way I'm used to (like in Amira for example) since the camera is fixed. Is this true, or am I totally lost? Thanks in advance for any help you can provide. Jordan

Hi Jordan, I see one mistake in your code, related to a confusing aspect of Chimera transform objects. mvo = apply(chimera.Vector, origin) vo = ref_model.openState.xform.apply(mvo) Here you use Xform.apply(Vector). Xform is a rotation and a translation but when applied to a Vector you get only the rotation applied. That is what you want if you are reorienting an axis, but not if you are repositioning the origin. The Xform.apply(Point) method applies both the rotation and translation. So you want: mvo = apply(chimera.Point, origin) vo = ref_model.openState.xform.apply(mvo) In fact, that apply() call is old style Python and I would use: mvo = chimera.Point(*origin) vo = ref_model.openState.xform.apply(mvo) The * in front of the argument means each element of the sequence origin is passed as a separate argument. This change messes up the translate() lines further down: xf.translate(vo) xf.rotate(va, angle_deg) xf.translate(-vo) The Xform.translate(Vector) requires a Vector argument not a Point. So I'd change that to use Xform.translate(x,y,z) as follows xf.translate(vo.x, vo.y, vo.z) xf.rotate(va, angle_deg) xf.translate(-vo.x, -vo.y, -vo.z) An important detail to note is that the transform xf when applied to a point first translates by -vo, then rotates, the translates by +vo. That is the order is backwards from the above function calls that created the transform. (In the ContrainedMove code there is an incorrect comment about translate(u) actually translating by -u -- I didn't realize what was going on when I wrote that code.) If I understand your code correctly you are specifying a line (origin and axis) to rotate about in the coordinate system of ref_model, then expressing that line in Chimera global coordinates, and then rotating the second model about that line. There are so many pits to fall into with the Xform / Vector / Point Chimera code. And there is not documentation for it, other than reading the source code. This is especially excruciating because it is hard to even find the source code. I looked at Chimera source code file chimera/libs/_chimera/pyinterface to see the Python interface to the C++ Xform, Vector, and Point objects. And then when I needed to actually look at the Xform C++ code I found that in otf/lib/geom3d/Xform.cpp which is in the Chimera foreign source code distribution (200 Mb) in a tar ball: chimera/foreign/otf/otf.tar.gz This source code is available from the Chimera web site. Could we make it any more difficult for you? It's a shameful mess. Feel free to ask further questions. There is a Chimera developers mailing list chimera-dev@cgl.ucsf.edu that is more appropriate for coding questions. Tom

On 4/11/06, Jordan Benjamin <jordan.benjamin@gmail.com> wrote:
I'm trying to rotate a model about a specified axis and origin (preferably in global coordinates). I would like the rotation to be applied on top of whatever transformations have been applied already. I've looked at the documentation, including the programmer's FAQ and the source code for ConstrainedMove. I couldn't figure out how to do this, so I wrote the following function based on the ConstrainedMove code to do the rotation relative to another model:
def rotate_around_model_axis(ref_model, model, origin, axis, angle_deg): mvo = apply(chimera.Vector, origin) vo = ref_model.openState.xform.apply(mvo) mva = apply(chimera.Vector, axis) va = ref_model.openState.xform.apply(mva)
xf = chimera.Xform() xf.translate(vo) xf.rotate(va, angle_deg) xf.translate(-vo)
model.openState.globalXform(xf)
But, this doesn't seem to work as I'd intended. Is there a way to do this? Also, I'm a little confused about the coordinate system. It seems like the concept of a global coordinate system may not apply in Chimera the way I'm used to (like in Amira for example) since the camera is fixed. Is this true, or am I totally lost? Thanks in advance for any help you can provide.
I have very similar code that works. How you derive "vo" seems a bit strange to me, but it may be that I don't fully understand what you are doing. I edited the code so it makes a little sense alone. Basically I rotate modelB by modelA's rotation. xf = modelA.openState.xform centerVec = modelB.bbox()[1].center().toVector() delta = chimera.Xform() delta.translate(centerVec) delta.rotate(*xf.getRotation()) centerVec.negate() delta.translate(centerVec) modelB.openState.globalXform(delta) Good luck and I feel your pain. I remember doing a lot of hacking before I got my desired results. - Charlie
participants (3)
-
Charlie Moad
-
Jordan Benjamin
-
Thomas Goddard