1 #ifndef SimTK_SimTKCOMMON_TRANSFORM_H
2 #define SimTK_SimTKCOMMON_TRANSFORM_H
3 
4 /* -------------------------------------------------------------------------- *
5  *                       Simbody(tm): SimTKcommon                             *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from           *
8  * Simbios, the NIH National Center for Physics-Based Simulation of           *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
11  *                                                                            *
12  * Portions copyright (c) 2005-14 Stanford University and the Authors.        *
13  * Authors: Michael Sherman                                                   *
14  * Contributors: Paul Mitiguy                                                 *
15  *                                                                            *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
17  * not use this file except in compliance with the License. You may obtain a  *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
19  *                                                                            *
20  * Unless required by applicable law or agreed to in writing, software        *
21  * distributed under the License is distributed on an "AS IS" BASIS,          *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
23  * See the License for the specific language governing permissions and        *
24  * limitations under the License.                                             *
25  * -------------------------------------------------------------------------- */
26 
27 //-----------------------------------------------------------------------------
28 #include "SimTKcommon/SmallMatrix.h"
29 #include "SimTKcommon/internal/BigMatrix.h"
30 #include "SimTKcommon/internal/UnitVec.h"
31 #include "SimTKcommon/internal/Quaternion.h"
32 #include "SimTKcommon/internal/Rotation.h"
33 //-----------------------------------------------------------------------------
34 #include <iosfwd>  // Forward declaration of iostream
35 //-----------------------------------------------------------------------------
36 
37 
38 //-----------------------------------------------------------------------------
39 namespace SimTK {
40 
41 //-----------------------------------------------------------------------------
42 // Forward declarations (everything is templatized by precision).
43 template <class P> class Transform_;
44 template <class P> class InverseTransform_;
45 
46 typedef Transform_<Real>    Transform;
47 typedef Transform_<float>   fTransform;
48 typedef Transform_<double>  dTransform;
49 
50 
51 //-----------------------------------------------------------------------------
52 /**
53  * This class represents the rotate-and-shift transform which gives the
54  * location and orientation of a new frame F in a base (reference) frame
55  * B. A frame is an orthogonal, right-handed set of three axes, and an
56  * origin point. A transform X from frame B to F consists of 3 perpendicular
57  * unit vectors defining F's axes as viewed from B (that is, as expressed in
58  * the basis formed by B's axes), and a vector from B's origin point Bo to F's
59  * origin point Fo. Note that the meaning of "B" comes from the context in
60  * which the transform is used. We use the phrase "frame F is in frame B" to
61  * describe the above relationship, that is, "in" means both measured from
62  * and expressed in.
63  *
64  * The axis vectors constitute a Rotation_. They are ordered 1-2-3 or x-y-z
65  * as you prefer, with z = x X y, making a right-handed set. These axes are
66  * arranged as columns of a 3x3 rotation matrix R_BF = [ x y z ] which is a
67  * direction cosine (rotation) matrix useful for conversions between frame
68  * B and F. (The columns of R_BF are F's coordinate axes, expressed in B.) For
69  * example, given a vector vF expressed in the F frame, that same vector
70  * re-expressed in B is given by vB = R_BF*vF. F's origin point OF is
71  * stored as the translation vector p_BF=(Fo-Bo) and expressed in B.
72  *
73  * Transform is designed to behave as much as possible like the computer
74  * graphics 4x4 affine transform X which would be arranged like this:
75  * <pre>
76  *
77  *         [       |   ]
78  *     X = [   R   | p ]    R is a 3x3 orthogonal rotation matrix
79  *         [.......|...]    p is a 3x1 translation vector
80  *         [ 0 0 0   1 ]
81  * </pre>
82  *
83  * These can be composed directly by matrix multiplication, but more
84  * importantly they have a particularly simple inverse:
85  * <pre>
86  *
87  *    -1   [       |    ]
88  *   X   = [  ~R   | p* ]   ~R is R transpose, p* = ~R(-p).
89  *         [.......|....]
90  *         [ 0 0 0   1  ]
91  * </pre>
92  *
93  * This inverse is so simple that we compute it simply by defining another
94  * type, InverseTransform_, which is identical to %Transform_ in memory but
95  * behaves as though it contains the inverse. That way we invert just by
96  * changing point of view (recasting) rather than computing.
97  *
98  * This is a "POD" (plain old data) class with a well-defined memory
99  * layout on which a client of this class may depend: There are
100  * exactly 4 consecutive, packed 3-vectors in the order x,y,z,p.
101  * That is, this class is equivalent to an array of 12 Reals with
102  * the order x1,x2,x3,y1,y2,y3,z1,z2,z3,p1,p2,p3. It is expressly allowed
103  * to reinterpret Transform objects in any appropriate manner that depends
104  * on this memory layout.
105  */
106 //-----------------------------------------------------------------------------
107 template <class P>
108 class Transform_ {
109 public:
110     /// Default constructor gives an identity transform.
Transform_()111     Transform_() : R_BF(),  p_BF(0) { }
112 
113     /// Combine a rotation and a translation into a transform.
Transform_(const Rotation_<P> & R,const Vec<3,P> & p)114     Transform_( const Rotation_<P>& R, const Vec<3,P>& p ) : R_BF(R), p_BF(p) { }
115 
116     /// Construct or default-convert a rotation into a transform
117     /// containing that rotation and zero translation.
Transform_(const Rotation_<P> & R)118     Transform_( const Rotation_<P>& R ) : R_BF(R), p_BF(0) { }
119 
120     /// Construct or default-convert a translation (expressed as a Vec3)
121     /// into a transform with that translation and a zero rotation.
Transform_(const Vec<3,P> & p)122     Transform_( const Vec<3,P>& p ) : R_BF(),  p_BF(p) { }
123 
124     // default copy, assignment, destructor
125 
126     /// Assignment from InverseTransform. This means that the
127     /// transform we're assigning to must end up with the same @em meaning
128     /// as the inverse transform X has, so we'll need to end up with:
129     ///   @li  p == X.p()
130     ///   @li  R == X.R()
131     ///
132     /// Cost: one frame conversion and a negation, 18 flops.
133     // (Definition is below after InverseTransform is declared.)
134     inline Transform_&  operator=( const InverseTransform_<P>& X );
135 
136     /// Add an offset to the position vector in this %Transform. Cost
137     /// is 3 flops.
138     template <int S>
139     Transform_& operator+=(const Vec<3,P,S>& offset_B)
140     {   p_BF += offset_B; return *this; }
141 
142     /// Subtract an offset from the position vector in this %Transform. Cost
143     /// is 3 flops.
144     template <int S>
145     Transform_& operator-=(const Vec<3,P,S>& offset_B)
146     {   p_BF -= offset_B; return *this; }
147 
148     /// Assign a new value to this transform, explicitly providing
149     /// the rotation and translation separately. We return a reference to
150     /// the now-modified transform as though this were an assignment operator.
set(const Rotation_<P> & R,const Vec<3,P> & p)151     Transform_&  set( const Rotation_<P>& R, const Vec<3,P>& p ) { p_BF=p; R_BF=R; return *this; }
152 
153     /// By zero we mean "zero transform", i.e., an identity rotation
154     /// and zero translation. We return a reference to the now-modified
155     /// transform as though this were an assignment operator.
setToZero()156     Transform_&  setToZero()  { R_BF.setRotationToIdentityMatrix();  p_BF = P(0);  return *this; }
157 
158     /// This fills both the rotation and translation with NaNs. Note: this is
159     /// @em not the same as a default-constructed transform, which is a
160     /// legitimate identity transform instead. We return a reference to the now-modified
161     /// transform as though this were an assignment operator.
setToNaN()162     Transform_&  setToNaN()  { R_BF.setRotationToNaN();  p_BF.setToNaN();  return *this; }
163 
164     /// Return a read-only inverse of the current Transform_<P>, simply by casting it to
165     /// the InverseTransform_<P> type. Zero cost.
invert()166     const InverseTransform_<P>&  invert() const  { return *reinterpret_cast<const InverseTransform_<P>*>(this); }
167 
168     /// Return a writable (lvalue) inverse of the current transform, simply by casting it to
169     /// the InverseTransform_<P> type. That is, this is an lvalue. Zero cost.
updInvert()170     InverseTransform_<P>&  updInvert()  { return *reinterpret_cast<InverseTransform_<P>*>(this); }
171 
172     /// Overload transpose operator to mean inversion. @see invert
173     const InverseTransform_<P>&  operator~() const  {return invert();}
174 
175     /// Overload transpose operator to mean inversion. @see updInvert
176     InverseTransform_<P>&        operator~()        {return updInvert();}
177 
178     /// Compose the current transform (X_BF) with the given one. That is,
179     /// return X_BY=X_BF*X_FY. Cost is 63 flops.
compose(const Transform_ & X_FY)180     Transform_ compose(const Transform_& X_FY) const {
181         return Transform_( R_BF * X_FY.R(),  p_BF + R_BF * X_FY.p() );
182     }
183 
184     /// Compose the current transform (X_BF) with one that is supplied
185     /// as an InverseTransform_ (typically as a result of applying
186     /// the "~" operator to a transform). That is, return
187     /// X_BY=X_BF*X_FY, but now X_FY is represented as ~X_YF. Cost
188     /// is an extra 18 flops to calculate X_FY.p(), total 81 flops.
189     // (Definition is below after InverseTransform_ is declared.)
190     inline Transform_  compose( const InverseTransform_<P>& X_FY ) const;
191 
192     /// %Transform a vector expressed in our "F" frame to our "B" frame.
193     /// Note that this involves rotation only; it is independent of
194     /// the translation stored in this transform. Cost is 15 flops.
xformFrameVecToBase(const Vec<3,P> & vF)195     Vec<3,P>  xformFrameVecToBase( const Vec<3,P>& vF ) const {return R_BF*vF;}
196 
197     /// %Transform a vector expressed in our "B" frame to our "F" frame.
198     /// Note that this involves rotation only; it is independent of
199     /// the translation stored in this transform. Cost is 15 flops.
xformBaseVecToFrame(const Vec<3,P> & vB)200     Vec<3,P>  xformBaseVecToFrame( const Vec<3,P>& vB ) const  { return ~R_BF*vB; }
201 
202     /// %Transform a point (station) measured from and expressed in
203     /// our "F" frame to that same point but measured from and
204     /// expressed in our "B" frame. Cost is 18 flops.
shiftFrameStationToBase(const Vec<3,P> & sF)205     Vec<3,P>  shiftFrameStationToBase( const Vec<3,P>& sF ) const
206     {   return p_BF + xformFrameVecToBase(sF); }
207 
208     /// %Transform a point (station) measured from and expressed in
209     /// our "B" frame to that same point but measured from and
210     /// expressed in our "F" frame. Cost is 18 flops.
shiftBaseStationToFrame(const Vec<3,P> & sB)211     Vec<3,P>  shiftBaseStationToFrame( const Vec<3,P>& sB ) const
212     {   return xformBaseVecToFrame(sB - p_BF); }
213 
214     /// Return a read-only reference to the contained rotation R_BF.
R()215     const Rotation_<P>&  R() const  { return R_BF; }
216 
217     /// Return a writable (lvalue) reference to the contained rotation R_BF.
updR()218     Rotation_<P>&  updR()           { return R_BF; }
219 
220     /// Return a read-only reference to the x direction (unit vector)
221     /// of the F frame, expressed in the B frame.
x()222     const typename Rotation_<P>::ColType&  x() const  { return R().x(); }
223     /// Return a read-only reference to the y direction (unit vector)
224     /// of the F frame, expressed in the B frame.
y()225     const typename Rotation_<P>::ColType&  y() const  { return R().y(); }
226     /// Return a read-only reference to the z direction (unit vector)
227     /// of the F frame, expressed in the B frame.
z()228     const typename Rotation_<P>::ColType&  z() const  { return R().z(); }
229 
230     /// Return a read-only reference to the inverse (transpose) of
231     /// our contained rotation, that is R_FB.
RInv()232     const InverseRotation_<P>&  RInv() const  { return ~R_BF; }
233 
234     /// Return a writable (lvalue) reference to the inverse (transpose) of
235     /// our contained rotation, that is R_FB.
updRInv()236     InverseRotation_<P>&  updRInv()  { return ~R_BF; }
237 
238     /// Return a read-only reference to our translation vector p_BF.
p()239     const Vec<3,P>&  p() const  { return p_BF; }
240 
241     /// Return a writable (lvalue) reference to our translation vector p_BF.
242     /// Caution: if you write through this reference you update the transform.
updP()243     Vec<3,P>&  updP()  { return p_BF; }
244 
245     /// Assign a new value to our translation vector. We expect the
246     /// supplied vector @p p to be expressed in our B frame. A reference
247     /// to the now-modified transform is returned as though this were
248     /// an assignment operator.
setP(const Vec<3,P> & p)249     Transform_<P>&  setP( const Vec<3,P>& p )  { p_BF=p; return *this; }
250 
251     /// Calculate the inverse of the translation vector in this transform.
252     /// The returned vector will be the negative of the original and will
253     /// be expressed in the F frame rather than our B frame. Cost is 18 flops.
pInv()254     Vec<3,P>  pInv() const  { return -(~R_BF*p_BF); }
255 
256     /// Assign a value to the @em inverse of our translation vector.
257     /// That is, we're given a vector in F which we invert and reexpress
258     /// in B to store it in p, so that we get the original argument back if
259     /// we ask for the inverse of p. Sorry, can't update pInv as an lvalue, but here we
260     /// want -(~R_BF*p_BF)=p_FB => p_BF=-(R_BF*p_FB) so we can calculate
261     /// it in 18 flops. A reference to the now-modified transform is returned
262     /// as though this were an assignment operator.
setPInv(const Vec<3,P> & p_FB)263     Transform_<P>&  setPInv( const Vec<3,P>& p_FB )  { p_BF = -(R_BF*p_FB); return *this; }
264 
265     /// Recast this transform as a read-only 3x4 matrix. This is a zero-cost
266     /// reinterpretation of the data; the first three columns are the
267     /// columns of the rotation and the last column is the translation.
asMat34()268     const Mat<3,4,P>&  asMat34() const  { return Mat<3,4,P>::getAs(reinterpret_cast<const P*>(this)); }
269 
270     /// Less efficient version of asMat34(); copies into return variable.
toMat34()271     Mat<3,4,P>  toMat34() const  { return asMat34(); }
272 
273     /// Return the equivalent 4x4 transformation matrix.
toMat44()274     Mat<4,4,P> toMat44() const {
275         Mat<4,4,P> tmp;
276         tmp.template updSubMat<3,4>(0,0) = asMat34();
277         tmp[3]                  = Row<4,P>(0,0,0,1);
278         return tmp;
279     }
280 
281     // OBSOLETE -- alternate name for p
T()282     const Vec<3,P>& T() const {return p();}
updT()283     Vec<3,P>&  updT()  {return updP();}
284 
285 private:
286     //TODO: these might not pack correctly; should use an array of 12 Reals.
287     Rotation_<P> R_BF;   // rotation matrix that expresses F's axes in R
288     Vec<3,P>     p_BF;   // location of F's origin measured from B's origin, expressed in B
289 };
290 
291 
292 //-----------------------------------------------------------------------------
293 /**
294  * %Transform from frame B to frame F, but with the internal representation
295  * inverted. That is, we store R*,p* here but the transform this represents is
296  * <pre>
297  *
298  *             B F    [       |   ]
299  *      X_BF =  X   = [   R   | p ]   where R=~(R*), p = - ~(R*)(p*).
300  *                    [.......|...]
301  *                    [ 0 0 0   1 ]
302  * </pre>
303  */
304 //-----------------------------------------------------------------------------
305 template <class P>
306 class InverseTransform_ {
307 public:
308     /// Default constructor produces an identity transform.
InverseTransform_()309     InverseTransform_() : R_FB(), p_FB(0) { }
310 
311     // default copy, assignment, destructor
312 
313     /// Implicit conversion from %InverseTransform_ to Transform_.
314     operator Transform_<P>() const  { return Transform_<P>( R(), p() ); }
315 
316     // Assignment from Transform_. This means that the inverse
317     // transform we're assigning to must end up with the same meaning
318     // as the inverse transform X has, so we'll need:
319     //          p* == X.pInv()
320     //          R* == X.RInv()
321     // Cost: one frame conversion and a negation for pInv, 18 flops.
322     InverseTransform_&  operator=( const Transform_<P>& X ) {
323         // Be careful to do this in the right order in case X and this
324         // are the same object, i.e. ~X = X which is weird but has
325         // the same meaning as X = ~X, i.e. invert X in place.
326         p_FB = X.pInv(); // This might change X.p ...
327         R_FB = X.RInv(); // ... but this doesn't depend on X.p.
328         return *this;
329     }
330 
331     // Inverting one of these just recasts it back to a Transform_<P>.
invert()332     const Transform_<P>&  invert() const  { return *reinterpret_cast<const Transform_<P>*>(this); }
updInvert()333     Transform_<P>&  updInvert()           { return *reinterpret_cast<Transform_<P>*>(this); }
334 
335     // Overload transpose to mean inversion.
336     const Transform_<P>&  operator~() const  { return invert(); }
337     Transform_<P>&        operator~()        { return updInvert(); }
338 
339     // Return X_BY=X_BF*X_FY, where X_BF (this) is represented here as ~X_FB. This
340     // costs exactly the same as a composition of two Transforms (63 flops).
compose(const Transform_<P> & X_FY)341     Transform_<P>  compose(const Transform_<P>& X_FY) const {
342         return Transform_<P>( ~R_FB * X_FY.R(),  ~R_FB *(X_FY.p() - p_FB) );
343     }
344     // Return X_BY=X_BF*X_FY, but now both xforms are represented by their inverses.
345     // This costs one extra vector transformation and a negation (18 flops) more
346     // than a composition of two Transforms, for a total of 81 flops.
compose(const InverseTransform_<P> & X_FY)347     Transform_<P>  compose(const InverseTransform_<P>& X_FY) const {
348         return Transform_<P>(  ~R_FB * X_FY.R(),  ~R_FB *(X_FY.p() - p_FB)  );
349     }
350 
351     // Forward and inverse vector transformations cost the same here as
352     // for a Transform_<P> (or for that matter, a Rotation_<P>): 15 flops.
xformFrameVecToBase(const Vec<3,P> & vF)353     Vec<3,P>  xformFrameVecToBase(const Vec<3,P>& vF) const {return ~R_FB*vF;}
xformBaseVecToFrame(const Vec<3,P> & vB)354     Vec<3,P>  xformBaseVecToFrame(const Vec<3,P>& vB) const {return  R_FB*vB;}
355 
356     // Forward and inverse station shift & transform cost the same here as for a Transform_<P>: 18 flops.
shiftFrameStationToBase(const Vec<3,P> & sF)357     Vec<3,P>  shiftFrameStationToBase(const Vec<3,P>& sF) const  { return ~R_FB*(sF-p_FB); }
shiftBaseStationToFrame(const Vec<3,P> & sB)358     Vec<3,P>  shiftBaseStationToFrame(const Vec<3,P>& sB) const  { return R_FB*sB + p_FB; }
359 
R()360     const InverseRotation_<P>&  R() const  {return ~R_FB;}
updR()361     InverseRotation_<P>&        updR()     {return ~R_FB;}
362 
x()363     const typename InverseRotation_<P>::ColType&  x() const  {return R().x();}
y()364     const typename InverseRotation_<P>::ColType&  y() const  {return R().y();}
z()365     const typename InverseRotation_<P>::ColType&  z() const  {return R().z();}
366 
RInv()367     const Rotation_<P>&  RInv() const  {return R_FB;}
updRInv()368     Rotation_<P>&        updRInv()     {return R_FB;}
369 
370     /// Calculate the actual translation vector at a cost of 18 flops.
371     /// It is better if you can just work with the %InverseTransform
372     /// directly since then you'll never have to pay this cost.
p()373     Vec<3,P>  p() const  { return -(~R_FB*p_FB); }
374 
375 
376     // no updP lvalue
377 
378     // Sorry, can't update translation as an lvalue, but here we
379     // want -(R_BF*p_FB)=p_BF => p_FB=-(R_FB*p_BF). Cost: 18 flops.
setP(const Vec<3,P> & p_BF)380     void  setP( const Vec<3,P>& p_BF )  { p_FB = -(R_FB*p_BF); }
381 
382     // Inverse translation is free.
pInv()383     const Vec<3,P>&  pInv() const              { return p_FB; }
setPInv(const Vec<3,P> & p)384     void         setPInv( const Vec<3,P>& p )  { p_FB = p; }
385 
386     /// For compatibility with Transform_<P>, but we don't provide an "as"
387     /// method here since the internal storage layout is somewhat odd.
toMat34()388     Mat<3,4,P>  toMat34() const  { return Transform_<P>(*this).asMat34(); }
389 
390     /// Return the equivalent 4x4 transformation matrix.
toMat44()391     Mat<4,4,P>  toMat44() const  { return Transform_<P>(*this).toMat44(); }
392 
393     // OBSOLETE -- alternate name for p.
T()394     Vec<3,P> T() const {return p();}
395 
396 private:
397     // DATA LAYOUT MUST BE IDENTICAL TO Transform_<P> !!
398     // TODO: redo packing here when it is done for Transform_<P>.
399     Rotation_<P> R_FB; // transpose of our rotation matrix, R_BF
400     Vec<3,P>     p_FB; // our translation is -(R_BF*p_FB)=-(~R_FB*p_FB)
401 };
402 
403 /// If we multiply a transform or inverse transform by a 3-vector, we treat
404 /// the vector as though it had a 4th element "1" appended, that is, it is
405 /// treated as a \e station rather than a \e vector. This way we use both
406 /// the rotational and translational components of the transform.
407 /// @relates Transform_
408 template <class P, int S> inline Vec<3,P>
409 operator*(const Transform_<P>& X_BF,        const Vec<3,P,S>& s_F)
410 {   return X_BF.shiftFrameStationToBase(s_F); }
411 template <class P, int S> inline Vec<3,P>
412 operator*(const InverseTransform_<P>& X_BF, const Vec<3,P,S>& s_F)
413 {   return X_BF.shiftFrameStationToBase(s_F); }
414 template <class P, int S> inline Vec<3,P>
415 operator*(const Transform_<P>& X_BF,        const Vec<3,negator<P>,S>& s_F)
416 {   return X_BF*Vec<3,P>(s_F); }
417 template <class P, int S> inline Vec<3,P>
418 operator*(const InverseTransform_<P>& X_BF, const Vec<3,negator<P>,S>& s_F)
419 {   return X_BF*Vec<3,P>(s_F); }
420 
421 /// Adding a 3-vector to a Transform produces a new shifted transform.
422 /// @relates Transform_
423 template <class P, int S> inline Transform_<P>
424 operator+(const Transform_<P>& X_BF, const Vec<3,P,S>& offset_B)
425 {   return Transform_<P>(X_BF) += offset_B; }
426 /// Adding a 3-vector to a Transform produces a new shifted transform.
427 /// @relates Transform_
428 template <class P, int S> inline Transform_<P>
429 operator+(const Vec<3,P,S>& offset_B, const Transform_<P>& X_BF)
430 {   return Transform_<P>(X_BF) += offset_B; }
431 
432 /// Subtracting a 3-vector from a Transform produces a new shifted transform.
433 /// @relates Transform_
434 template <class P, int S> inline Transform_<P>
435 operator-(const Transform_<P>& X_BF, const Vec<3,P,S>& offset_B)
436 {   return Transform_<P>(X_BF) -= offset_B; }
437 
438 //-----------------------------------------------------------------------------
439 /// If we multiply a transform or inverse transform by an augmented 4-vector,
440 /// we use the 4th element to decide how to treat it. The 4th element must be
441 /// 0 or 1. If 0 it is treated as a vector only and the translation is ignored.
442 /// If 1 it is treated as a station and rotated & shifted.
443 /// @relates Transform_
444 template <class P, int S> inline Vec<4,P>
445 operator*(const Transform_<P>& X_BF, const Vec<4,P,S>& a_F) {
446     assert(a_F[3]==0 || a_F[3]==1);
447     const Vec<3,P,S>& v_F = Vec<3,P,S>::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3
448 
449     Vec<4,P> out;
450     if( a_F[3] == 0 ) { Vec<3,P>::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F);      out[3] = 0; }
451     else              { Vec<3,P>::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F);  out[3] = 1; }
452     return out;
453 }
454 
455 template <class P, int S> inline Vec<4,P>
456 operator*(const InverseTransform_<P>& X_BF, const Vec<4,P,S>& a_F ) {
457     assert(a_F[3]==0 || a_F[3]==1);
458     const Vec<3,P,S>& v_F = Vec<3,P,S>::getAs(&a_F[0]); // recast the 1st 3 elements as Vec3
459 
460     Vec<4,P> out;
461     if( a_F[3] == 0 ) { Vec<3,P>::updAs(&out[0]) = X_BF.xformFrameVecToBase(v_F);      out[3] = 0; }
462     else              { Vec<3,P>::updAs(&out[0]) = X_BF.shiftFrameStationToBase(v_F);  out[3] = 1; }
463     return out;
464 }
465 template <class P, int S> inline Vec<4,P>
466 operator*(const Transform_<P>& X_BF,        const Vec<4,negator<P>,S>& s_F)  {return X_BF*Vec<4,P>(s_F);}
467 template <class P, int S> inline Vec<4,P>
468 operator*(const InverseTransform_<P>& X_BF, const Vec<4,negator<P>,S>& s_F)  {return X_BF*Vec<4,P>(s_F);}
469 //-----------------------------------------------------------------------------
470 
471 /// Multiplying a matrix or vector by a Transform_<P> applies it to each element
472 /// individually.
473 /// @relates Transform_
474 template <class P, class E> inline Vector_<E>
475 operator*(const Transform_<P>& X, const VectorBase<E>& v) {
476     Vector_<E> result(v.size());
477     for (int i = 0; i < v.size(); ++i)
478         result[i] = X*v[i];
479     return result;
480 }
481 template <class P, class E> inline Vector_<E>
482 operator*(const VectorBase<E>& v, const Transform_<P>& X) {
483     Vector_<E> result(v.size());
484     for (int i = 0; i < v.size(); ++i)
485         result[i] = X*v[i];
486     return result;
487 }
488 template <class P, class E> inline RowVector_<E>
489 operator*(const Transform_<P>& X, const RowVectorBase<E>& v) {
490     RowVector_<E> result(v.size());
491     for (int i = 0; i < v.size(); ++i)
492         result[i] = X*v[i];
493     return result;
494 }
495 template <class P, class E> inline RowVector_<E>
496 operator*(const RowVectorBase<E>& v, const Transform_<P>& X) {
497     RowVector_<E> result(v.size());
498     for (int i = 0; i < v.size(); ++i)
499         result[i] = X*v[i];
500     return result;
501 }
502 template <class P, class E> inline Matrix_<E>
503 operator*(const Transform_<P>& X, const MatrixBase<E>& v) {
504     Matrix_<E> result(v.nrow(), v.ncol());
505     for (int i = 0; i < v.nrow(); ++i)
506         for (int j = 0; j < v.ncol(); ++j)
507             result(i, j) = X*v(i, j);
508     return result;
509 }
510 template <class P, class E> inline Matrix_<E>
511 operator*(const MatrixBase<E>& v, const Transform_<P>& X) {
512     Matrix_<E> result(v.nrow(), v.ncol());
513     for (int i = 0; i < v.nrow(); ++i)
514         for (int j = 0; j < v.ncol(); ++j)
515             result(i, j) = X*v(i, j);
516     return result;
517 }
518 template <class P, int N, class E, int S> inline Vec<N,E>
519 operator*(const Transform_<P>& X, const Vec<N,E,S>& v) {
520     Vec<N,E> result;
521     for (int i = 0; i < N; ++i)
522         result[i] = X*v[i];
523     return result;
524 }
525 template <class P, int N, class E, int S> inline Vec<N,E>
526 operator*(const Vec<N,E,S>& v, const Transform_<P>& X) {
527     Vec<N,E> result;
528     for (int i = 0; i < N; ++i)
529         result[i] = X*v[i];
530     return result;
531 }
532 template <class P, int N, class E, int S> inline Row<N,E>
533 operator*(const Transform_<P>& X, const Row<N,E,S>& v) {
534     Row<N,E> result;
535     for (int i = 0; i < N; ++i)
536         result[i] = X*v[i];
537     return result;
538 }
539 template <class P, int N, class E, int S> inline Row<N,E>
540 operator*(const Row<N,E,S>& v, const Transform_<P>& X) {
541     Row<N,E> result;
542     for (int i = 0; i < N; ++i)
543         result[i] = X*v[i];
544     return result;
545 }
546 template <class P, int M, int N, class E, int CS, int RS> inline Mat<M,N,E>
547 operator*(const Transform_<P>& X, const Mat<M,N,E,CS,RS>& v) {
548     Mat<M,N,E> result;
549     for (int i = 0; i < M; ++i)
550         for (int j = 0; j < N; ++j)
551             result(i, j) = X*v(i, j);
552     return result;
553 }
554 template <class P, int M, int N, class E, int CS, int RS> inline Mat<M,N,E>
555 operator*(const Mat<M,N,E,CS,RS>& v, const Transform_<P>& X) {
556     Mat<M,N,E> result;
557     for (int i = 0; i < M; ++i)
558         for (int j = 0; j < N; ++j)
559             result(i, j) = X*v(i, j);
560     return result;
561 }
562 
563 // These Transform definitions had to wait for InverseTransform to be declared.
564 
565 template <class P> inline Transform_<P>&
566 Transform_<P>::operator=( const InverseTransform_<P>& X ) {
567     // Be careful to do this in the right order in case X and this
568     // are the same object, i.e. we're doing X = ~X, inverting X in place.
569     p_BF = X.p(); // This might change X.p ...
570     R_BF = X.R(); // ... but this doesn't depend on X.p.
571     return *this;
572 }
573 
574 template <class P> inline Transform_<P>
compose(const InverseTransform_<P> & X_FY)575 Transform_<P>::compose( const InverseTransform_<P>& X_FY ) const {
576     return Transform_<P>( R_BF * X_FY.R(), p_BF + R_BF * X_FY.p() );
577 }
578 
579 /// Composition of transforms. Operators are provided for all the combinations
580 /// of transform and inverse transform.
581 /// @relates Transform_
582 template <class P> inline Transform_<P>
583 operator*(const Transform_<P>& X1,        const Transform_<P>& X2)         {return X1.compose(X2);}
584 template <class P> inline Transform_<P>
585 operator*(const Transform_<P>& X1,        const InverseTransform_<P>& X2)  {return X1.compose(X2);}
586 template <class P> inline Transform_<P>
587 operator*(const InverseTransform_<P>& X1, const Transform_<P>& X2)         {return X1.compose(X2);}
588 template <class P> inline Transform_<P>
589 operator*(const InverseTransform_<P>& X1, const InverseTransform_<P>& X2)  {return X1.compose(X2);}
590 
591 /// Comparison operators return true only if the two transforms are bit
592 /// identical; that's not too useful.
593 /// @relates Transform_
594 template <class P> inline bool
595 operator==(const Transform_<P>& X1,        const Transform_<P>& X2)         {return X1.R()==X2.R() && X1.p()==X2.p();}
596 template <class P> inline bool
597 operator==(const InverseTransform_<P>& X1, const InverseTransform_<P>& X2)  {return X1.R()==X2.R() && X1.p()==X2.p();}
598 template <class P> inline bool
599 operator==(const Transform_<P>& X1,        const InverseTransform_<P>& X2)  {return X1.R()==X2.R() && X1.p()==X2.p();}
600 template <class P> inline bool
601 operator==(const InverseTransform_<P>& X1, const Transform_<P>& X2)         {return X1.R()==X2.R() && X1.p()==X2.p();}
602 
603 /// Generate formatted output of a Transform to an output stream.
604 /// @relates Transform_
605 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream&
606 operator<<(std::ostream&, const Transform_<P>&);
607 /// Generate formatted output of an InverseTransform to an output stream.
608 /// @relates InverseTransform_
609 template <class P> SimTK_SimTKCOMMON_EXPORT std::ostream&
610 operator<<(std::ostream&, const InverseTransform_<P>&);
611 
612 
613 
614 //------------------------------------------------------------------------------
615 }  // End of namespace SimTK
616 
617 //--------------------------------------------------------------------------
618 #endif // SimTK_SimTKCOMMON_TRANSFORM_H
619 //--------------------------------------------------------------------------
620 
621