/*============================================================================= NOTE: THIS FILE IS A HANDMADE WRAPPER FOR THE ManagedITK PROJECT. Project: ManagedITK Program: Insight Segmentation & Registration Toolkit Module: itkManagedQuaternion.cxx Language: C++/CLI Author: Dan Mueller $Date: 2007-04-11 16:26:16 +1000 (Wed, 11 Apr 2007) $ $Revision: 128 $ Copyright (c) Queensland University of Technology (QUT) 2007. All rights reserved. Portions of this code are covered under the ITK and VTK copyright. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =============================================================================*/ #pragma once #pragma warning( disable : 4635 ) // Disable warnings about XML doc comments #ifndef __itkManagedQuaternion_cxx #define __itkManagedQuaternion_cxx // Include some useful ManagedITK files #include "itkManagedObject.cxx" #include "itkManagedPoint.cxx" #include "itkManagedVector.cxx" // Use some managed namespaces #using #using using namespace System; using namespace System::IO; using namespace System::Reflection; using namespace System::Diagnostics; using namespace System::Collections::Generic; namespace itk { #define itkQuaternionValueType System::Double /// ///This class is a managed replacement for itk::Quaternion. /// /// ///The class does not provide many quaternion operations, it is ///only a basic wrapper for the actual XYZW data. /// public ref class itkQuaternion { protected: itkQuaternionValueType m_X; itkQuaternionValueType m_Y; itkQuaternionValueType m_Z; itkQuaternionValueType m_W; public: /// ///Default constructor. The Quaternion is initialised to the identity. /// itkQuaternion ( ) { this->SetIdentity(); } /// ///Component constructor. The Quaternion is initialised to the given XYZW components. /// itkQuaternion ( itkQuaternionValueType x, itkQuaternionValueType y, itkQuaternionValueType z, itkQuaternionValueType w ) { this->Set( x, y, z, w ); } ///Get the X component. property itkQuaternionValueType X { virtual itkQuaternionValueType get() { return m_X; } } ///Get the Y component. property itkQuaternionValueType Y { virtual itkQuaternionValueType get() { return m_Y; } } ///Get the Z component. property itkQuaternionValueType Z { virtual itkQuaternionValueType get() { return m_Z; } } ///Get the W component. property itkQuaternionValueType W { virtual itkQuaternionValueType get() { return m_W; } } /// ///Gets the scalar (W) part. /// property itkQuaternionValueType Scalar { virtual itkQuaternionValueType get() { return m_W; } } ///Compute the tensor. property itkQuaternionValueType Tensor { virtual itkQuaternionValueType get() { return Math::Sqrt( m_X*m_X + m_Y*m_Y + m_Z*m_Z + m_W*m_W ); } } ///Compute the axis of rotation. property itkVector^ Axis { virtual itkVector^ get() { itkVector^ axis = gcnew itkVector(3U); itkQuaternionValueType vectorNorm = Math::Sqrt( m_X*m_X + m_Y*m_Y + m_Z*m_Z ); if (Math::Abs(vectorNorm) < Double::Epsilon) { axis[0] = 0.0; axis[1] = 0.0; axis[2] = 0.0; } else { axis[0] = m_X / vectorNorm; axis[1] = m_Y / vectorNorm; axis[2] = m_Z / vectorNorm; } return axis; } } /// ///Gets the right (vector) part of the Quaternion. ///It is called Right because it is equivalent to a right angle rotation. /// property itkVector^ Right { virtual itkVector^ get() { itkVector^ right = gcnew itkVector(3U); right[0] = m_X; right[1] = m_Y; right[2] = m_Z; return right; } } /// ///Returns the rotation angle in radians. /// property itkQuaternionValueType Angle { virtual itkQuaternionValueType get() { itkQuaternionValueType vectorNorm = Math::Sqrt( m_X*m_X + m_Y*m_Y + m_Z*m_Z ); itkQuaternionValueType angle = 2.0 * Math::Atan2( vectorNorm, m_W ); return angle; } } /// ///Normalize the Quaternion. /// virtual void Normalize( ) { itkQuaternionValueType tensor = this->Tensor; if (Math::Abs(tensor) < Double::Epsilon) throw gcnew ApplicationException( "Attempted to normalize an itkQuaternion with zero tensor." ); m_X /= tensor; m_Y /= tensor; m_Z /= tensor; m_W /= tensor; } ///Set the Quaternion using the given XYZW components. virtual void Set( itkQuaternionValueType x, itkQuaternionValueType y, itkQuaternionValueType z, itkQuaternionValueType w ) { m_X = x; m_Y = y; m_Z = z; m_W = w; } /// ///Set the Quaternion using a vector and angle. ///The unit vector parallel to the given vector will be used. ///The angle is expected in radians. /// virtual void Set( itkVector^ axis, itkQuaternionValueType angle ) { itkQuaternionValueType vectorNorm = axis->GetNorm(); itkQuaternionValueType cosangle2 = Math::Cos( angle/2.0 ); itkQuaternionValueType sinangle2 = Math::Sin( angle/2.0 ); itkQuaternionValueType factor = sinangle2 / vectorNorm; m_X = axis[0] * factor; m_Y = axis[1] * factor; m_Z = axis[2] * factor; m_W = cosangle2; } ///Set the Quaternion as a rotation around the X-axis. virtual void SetRotationAroundX( itkQuaternionValueType angle ) { itkQuaternionValueType sinangle2 = Math::Sin( angle/2.0 ); itkQuaternionValueType cosangle2 = Math::Cos( angle/2.0 ); m_X = sinangle2; m_Y = 0.0; m_Z = 0.0; m_W = cosangle2; } ///Set the Quaternion as a rotation around the Y-axis. virtual void SetRotationAroundY( itkQuaternionValueType angle ) { itkQuaternionValueType sinangle2 = Math::Sin( angle/2.0 ); itkQuaternionValueType cosangle2 = Math::Cos( angle/2.0 ); m_X = 0.0; m_Y = sinangle2; m_Z = 0.0; m_W = cosangle2; } ///Set the Quaternion as a rotation around the Z-axis. virtual void SetRotationAroundZ( itkQuaternionValueType angle ) { itkQuaternionValueType sinangle2 = Math::Sin( angle/2.0 ); itkQuaternionValueType cosangle2 = Math::Cos( angle/2.0 ); m_X = 0.0; m_Y = 0.0; m_Z = sinangle2; m_W = cosangle2; } ///Set the Quaternion as identity ie. [0,0,0,1]. virtual void SetIdentity( ) { m_X = 0.0; m_Y = 0.0; m_Z = 0.0; m_W = 1.0; } }; // end ref class } // end namespace itk #endif