Simbody  3.4 (development)
CoordinateAxis.h
Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_COORDINATE_AXIS_H_ 
00002 #define SimTK_SimTKCOMMON_COORDINATE_AXIS_H_ 
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00030 #include "SimTKcommon/internal/common.h"
00031 #include <cassert>
00032 
00033 namespace SimTK {
00034 
00053 class CoordinateAxis {
00054 public:
00057     explicit CoordinateAxis( int i ) : m_myAxisId(i) {assertIndexIsInRange(i);}
00058 
00060     operator int() const {return m_myAxisId;}
00061 
00066     CoordinateAxis getNextAxis() const 
00067     {   return CoordinateAxis((m_myAxisId+1) % 3); }
00068 
00073     CoordinateAxis getPreviousAxis() const 
00074     {   return CoordinateAxis((m_myAxisId+2) % 3); }
00075 
00083     CoordinateAxis getThirdAxis( const CoordinateAxis& axis2 ) const { 
00084        assert( isDifferentAxis(axis2) );
00085        CoordinateAxis nextAxis = getNextAxis();
00086        return nextAxis.isDifferentAxis(axis2) ? nextAxis : axis2.getNextAxis();
00087     }
00088 
00090     bool isXAxis() const {return m_myAxisId == 0;}
00092     bool isYAxis() const {return m_myAxisId == 1;}
00094     bool isZAxis() const {return m_myAxisId == 2;}
00097     bool isNextAxis( const CoordinateAxis& axis2 ) const
00098     {   return int(getNextAxis()) == int(axis2); }
00101     bool isPreviousAxis( const CoordinateAxis& axis2 ) const
00102     {   return int(getPreviousAxis()) == int(axis2); }
00105     bool isSameAxis( const CoordinateAxis& axis2 ) const
00106     {   return m_myAxisId == int(axis2); }
00108     bool areAllSameAxes( const CoordinateAxis& axis2, 
00109                          const CoordinateAxis &axis3 ) const       
00110     {   return isSameAxis(axis2) && isSameAxis(axis3); }
00113     bool isDifferentAxis( const CoordinateAxis& axis2 ) const                                   
00114     {   return m_myAxisId != int(axis2); }
00118     bool areAllDifferentAxes( const CoordinateAxis& axis2, 
00119                               const CoordinateAxis& axis3 ) const  
00120     {   return isDifferentAxis(axis2) && isDifferentAxis(axis3) 
00121                && axis2.isDifferentAxis(axis3); }
00125     bool isForwardCyclical( const CoordinateAxis& axis2 ) const                                
00126     {   return isNextAxis(axis2); }
00130     bool isReverseCyclical( const CoordinateAxis& axis2 ) const                                 
00131     {   return isPreviousAxis(axis2); }
00132 
00136     int dotProduct(  const CoordinateAxis& axis2 ) const
00137     {   return isSameAxis(axis2) ? 1 : 0; }
00143     int crossProductSign( const CoordinateAxis& axis2 ) const
00144     {   return isSameAxis(axis2) ? 0 : (isNextAxis(axis2) ? 1 : -1); }
00152     CoordinateAxis crossProductAxis( const CoordinateAxis& axis2 ) const
00153     {   return isSameAxis(axis2) ? CoordinateAxis(m_myAxisId) 
00154                                  : getThirdAxis(axis2); }
00162     CoordinateAxis crossProduct( const CoordinateAxis& axis2, int& sign ) const
00163     {   sign = crossProductSign(axis2); return crossProductAxis(axis2); }
00164 
00167     static const CoordinateAxis& getCoordinateAxis( int i );
00168 
00172     static bool  isIndexInRange( int i )        { return 0<=i && i<=2; }
00175     static void  assertIndexIsInRange( int i )  { assert( isIndexInRange(i) ); } 
00176 
00177     // Forward declarations for subsequent helper classes
00178     class XCoordinateAxis; class YCoordinateAxis; class ZCoordinateAxis;
00179 protected: // turn off doxygen here; these aren't for users
00181     class XTypeAxis{};
00182     class YTypeAxis{};
00183     class ZTypeAxis{};
00184 
00185     CoordinateAxis( const XTypeAxis& ) : m_myAxisId(0) {}
00186     CoordinateAxis( const YTypeAxis& ) : m_myAxisId(1) {}
00187     CoordinateAxis( const ZTypeAxis& ) : m_myAxisId(2) {}
00189 private:            
00190 
00191     int m_myAxisId;
00192 };
00193 
00194 
00195 // Helper classes that allow compile time recognition of axis directions.
00196 class CoordinateAxis::XCoordinateAxis : public CoordinateAxis {
00197   public: XCoordinateAxis() : CoordinateAxis(XTypeAxis()) {}
00198 };
00199 class CoordinateAxis::YCoordinateAxis : public CoordinateAxis {
00200   public: YCoordinateAxis() : CoordinateAxis(YTypeAxis()) {}
00201 };
00202 class CoordinateAxis::ZCoordinateAxis : public CoordinateAxis {
00203   public: ZCoordinateAxis() : CoordinateAxis(ZTypeAxis()) {}
00204 };
00205 
00208 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::XCoordinateAxis  XAxis;
00211 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::YCoordinateAxis  YAxis;
00214 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::ZCoordinateAxis  ZAxis;
00215 
00216 inline const CoordinateAxis& CoordinateAxis::getCoordinateAxis(int i) {
00217     assertIndexIsInRange(i);
00218     return (i==0 ? static_cast<const CoordinateAxis&>(XAxis) 
00219          : (i==1 ? static_cast<const CoordinateAxis&>(YAxis) 
00220                  : static_cast<const CoordinateAxis&>(ZAxis)));
00221 }
00222 
00224 inline bool operator==(const CoordinateAxis& a1, const CoordinateAxis& a2)
00225 {   return a1.isSameAxis(a2); }
00226 
00228 inline bool operator!=(const CoordinateAxis& a1, const CoordinateAxis& a2)
00229 {   return a1.isDifferentAxis(a2); }
00230 
00231 
00246 class CoordinateDirection {
00247 public:
00250     class Negative {};
00251 
00254     CoordinateDirection(const CoordinateAxis& axis)
00255     :   m_axis(axis), m_direction(1) {}
00256 
00259     CoordinateDirection(const CoordinateAxis& axis, Negative)
00260     :   m_axis(axis), m_direction(-1) {}
00261 
00269     CoordinateDirection(const CoordinateAxis& axis, int direction)
00270     :   m_axis(axis), m_direction(direction) 
00271     {   assert(direction==1 || direction==-1); }
00272 
00276     CoordinateAxis getAxis() const {return m_axis;}
00279     int getDirection() const {return m_direction;}
00280 
00283     bool hasSameAxis(const CoordinateDirection& dir2) const
00284     {   return m_axis.isSameAxis(dir2.getAxis()); }
00285 
00289     bool isSameAxisAndDirection(const CoordinateDirection& dir2) const
00290     {   return m_axis==dir2.getAxis() && m_direction==dir2.getDirection(); }
00291 
00295     int dotProduct(  const CoordinateDirection& dir2 ) const
00296     {   if (m_axis != dir2.getAxis()) return 0;
00297         return m_direction == dir2.getDirection() ? 1 : -1; }
00298 
00304     int crossProductSign( const CoordinateDirection& dir2 ) const
00305     {   if (m_axis == dir2.getAxis()) return 0;
00306         return m_axis.crossProductSign(dir2.getAxis())
00307                * m_direction * dir2.getDirection(); }
00308 
00316     CoordinateAxis crossProductAxis( const CoordinateDirection& dir2 ) const
00317     {   return m_axis.crossProductAxis(dir2.getAxis()); }
00318 
00326     CoordinateAxis crossProduct( const CoordinateDirection& dir2, 
00327                                  int&                       sign ) const
00328     {   sign = crossProductSign(dir2); return crossProductAxis(dir2); }
00329 
00330     // Local class declarations for helper classes.
00331     class NegXDirection; class NegYDirection; class NegZDirection;
00332 private:
00333     CoordinateAxis m_axis;      // XAxis, YAxis, or ZAxis
00334     int            m_direction; // 1 or -1
00335 };
00336 
00337 
00338 // Helper classes that allow compile time recognition of negative axis
00339 // directions.
00340 class CoordinateDirection::NegXDirection : public CoordinateDirection {
00341   public: NegXDirection() : CoordinateDirection(XAxis,Negative()) {}
00342 };
00343 class CoordinateDirection::NegYDirection : public CoordinateDirection {
00344   public: NegYDirection() : CoordinateDirection(YAxis,Negative()) {}
00345 };
00346 class CoordinateDirection::NegZDirection : public CoordinateDirection {
00347   public: NegZDirection() : CoordinateDirection(ZAxis,Negative()) {}
00348 };
00349 
00350 // Predefine constants for the negative X,Y,Z directions.
00351 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegXDirection  
00352     NegXAxis; 
00353 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegYDirection  
00354     NegYAxis; 
00355 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegZDirection  
00356     NegZAxis; 
00357 
00359 inline bool operator==(const CoordinateDirection& d1, 
00360                        const CoordinateDirection& d2)
00361 {   return d1.isSameAxisAndDirection(d2); }
00362 
00364 inline bool operator!=(const CoordinateDirection& d1, 
00365                        const CoordinateDirection& d2)
00366 {   return !d1.isSameAxisAndDirection(d2); }
00367 
00370 inline const CoordinateDirection::NegXDirection&
00371 operator-(const CoordinateAxis::XCoordinateAxis&){return NegXAxis;}
00374 inline const CoordinateDirection::NegYDirection&
00375 operator-(const CoordinateAxis::YCoordinateAxis&){return NegYAxis;}
00378 inline const CoordinateDirection::NegZDirection&
00379 operator-(const CoordinateAxis::ZCoordinateAxis&){return NegZAxis;}
00380 
00383 inline CoordinateDirection
00384 operator-(const CoordinateAxis& axis)
00385 {   return CoordinateDirection(axis,CoordinateDirection::Negative()); }
00386 
00389 inline CoordinateDirection
00390 operator+(const CoordinateAxis& axis)
00391 {   return CoordinateDirection(axis); }
00392 
00395 inline const CoordinateAxis::XCoordinateAxis&
00396 operator-(const CoordinateDirection::NegXDirection&){return XAxis;}
00399 inline const CoordinateAxis::YCoordinateAxis&
00400 operator-(const CoordinateDirection::NegYDirection&){return YAxis;}
00403 inline const CoordinateAxis::ZCoordinateAxis&
00404 operator-(const CoordinateDirection::NegZDirection&){return ZAxis;}
00405 
00408 inline CoordinateDirection
00409 operator-(const CoordinateDirection& dir)
00410 {   return CoordinateDirection(dir.getAxis(), -dir.getDirection()); }
00411 
00412 }  // End of namespace
00413 
00414 #endif // SimTK_SimTKCOMMON_COORDINATE_AXIS_H_
00415 
00416 
00417 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines