diff --git a/Core/Code/DataManagement/mitkVector.h b/Core/Code/DataManagement/mitkVector.h index 598c2a5411..29883739ee 100644 --- a/Core/Code/DataManagement/mitkVector.h +++ b/Core/Code/DataManagement/mitkVector.h @@ -1,448 +1,457 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKVECTOR_H_HEADER_INCLUDED_C1EBD0AD #define MITKVECTOR_H_HEADER_INCLUDED_C1EBD0AD // this is needed for memcopy in ITK // can be removed when fixed in ITK #include #include #include #include #include #include #include #include #include #include #ifndef DOXYGEN_SKIP namespace mitk { typedef float ScalarType; typedef itk::Matrix Matrix3D; typedef itk::Matrix Matrix4D; typedef vnl_matrix_fixed VnlMatrix3D; typedef itk::Transform Transform3D; typedef vnl_vector VnlVector; typedef vnl_vector_ref VnlVectorRef; typedef itk::Point Point2D; typedef itk::Point Point3D; typedef itk::Point Point4D; typedef itk::Point Point2I; typedef itk::Point Point3I; typedef itk::Point Point4I; typedef itk::Vector Vector2D; typedef itk::Vector Vector3D; typedef itk::Index<3> Index3D; typedef itk::ContinuousIndex ContinuousIndex3D; typedef vnl_quaternion Quaternion; //##Documentation //##@brief enumeration of the type a point can be enum PointSpecificationType { PTUNDEFINED = 0, PTSTART, PTCORNER, PTEDGE, PTEND }; typedef itk::NumericTraits ScalarTypeNumericTraits; MITK_CORE_EXPORT extern const ScalarType eps; MITK_CORE_EXPORT extern const ScalarType sqrteps; MITK_CORE_EXPORT extern const double large; template class VectorTraits { public: typedef T ValueType; }; template <> class VectorTraits { public: typedef ScalarType ValueType; }; template<> class VectorTraits { public: typedef double ValueType; }; template<> class VectorTraits< itk::Index<5> > { public: typedef itk::Index<5>::IndexValueType ValueType; }; template<> class VectorTraits< itk::Index<3> > { public: typedef itk::Index<3>::IndexValueType ValueType; }; template<> class VectorTraits< long int [3]> { public: typedef long int ValueType; }; template<> class VectorTraits< float [3]> { public: typedef float ValueType; }; template<> class VectorTraits< double [3]> { public: typedef double ValueType; }; template<> class VectorTraits< vnl_vector_fixed > { public: typedef ScalarType ValueType; }; template<> class VectorTraits< long unsigned int[3]> { public: typedef long unsigned int ValueType; }; template<> class VectorTraits< unsigned int *> { public: typedef unsigned int ValueType; }; template<> class VectorTraits< ScalarType[4] > { public: typedef ScalarType ValueType; }; template<> class VectorTraits< itk::Vector > { public: typedef float ValueType; }; template<> class VectorTraits< itk::Point > { public: typedef float ValueType; }; template<> class VectorTraits< itk::Point > { public: typedef float ValueType; }; template<> class VectorTraits< itk::Vector > { public: typedef double ValueType; }; template<> class VectorTraits< itk::Point > { public: typedef double ValueType; }; template<> class VectorTraits< itk::Vector > { public: typedef int ValueType; }; template<> class VectorTraits< itk::Point > { public: typedef int ValueType; }; template inline void itk2vtk(const Tin& in, Tout& out) { out[0]=(typename VectorTraits::ValueType)(in[0]); out[1]=(typename VectorTraits::ValueType)(in[1]); out[2]=(typename VectorTraits::ValueType)(in[2]); } template inline void vtk2itk(const Tin& in, Tout& out) { out[0]=(typename VectorTraits::ValueType)(in[0]); out[1]=(typename VectorTraits::ValueType)(in[1]); out[2]=(typename VectorTraits::ValueType)(in[2]); } template inline void FillVector3D(Tout& out, ScalarType x, ScalarType y, ScalarType z) { out[0] = (typename VectorTraits::ValueType)x; out[1] = (typename VectorTraits::ValueType)y; out[2] = (typename VectorTraits::ValueType)z; } template inline void FillVector4D(Tout& out, ScalarType x, ScalarType y, ScalarType z, ScalarType t) { out[0] = (typename VectorTraits::ValueType)x; out[1] = (typename VectorTraits::ValueType)y; out[2] = (typename VectorTraits::ValueType)z; out[3] = (typename VectorTraits::ValueType)t; } template inline void vnl2vtk(const vnl_vector& in, Tout *out) { unsigned int i; for(i=0; i inline void vtk2vnl(const Tin *in, vnl_vector& out) { unsigned int i; for(i=0; i inline void vtk2vnlref(const Tin *in, vnl_vector_ref& out) { unsigned int i; for(i=0; i inline void vnl2vtk(const vnl_vector_fixed& in, Tout *out) { unsigned int i; for(i=0; i inline void vtk2vnl(const Tin *in, vnl_vector_fixed& out) { unsigned int i; for(i=0; i itk::Vector operator+(const itk::Vector &vector, const itk::Point &point) { itk::Vector sub; for( unsigned int i=0; i inline itk::Vector& operator+=(itk::Vector &vector, const itk::Point &point) { for( unsigned int i=0; i itk::Vector operator-(const itk::Vector &vector, const itk::Point &point) { itk::Vector sub; for( unsigned int i=0; i inline itk::Vector& operator-=(itk::Vector &vector, const itk::Point &point) { for( unsigned int i=0; i inline bool MatrixEqualRMS(const vnl_matrix_fixed& matrix1,const vnl_matrix_fixed& matrix2,mitk::ScalarType epsilon=mitk::eps) { if ( (matrix1.rows() == matrix2.rows()) && (matrix1.cols() == matrix2.cols()) ) { vnl_matrix_fixed differenceMatrix = matrix1-matrix2; if (differenceMatrix.rms() inline bool MatrixEqualRMS(const itk::Matrix& matrix1,const itk::Matrix& matrix2,mitk::ScalarType epsilon=mitk::eps) { return mitk::MatrixEqualRMS(matrix1.GetVnlMatrix(),matrix2.GetVnlMatrix(),epsilon); } /*! \brief Check for element-wise matrix equality with a user defined accuracy. \param matrix1 first vnl matrix \param matrix2 second vnl matrix \epsilon user defined accuracy bounds */ template inline bool MatrixEqualElementWise(const vnl_matrix_fixed& matrix1,const vnl_matrix_fixed& matrix2,mitk::ScalarType epsilon=mitk::eps) { if ( (matrix1.rows() == matrix2.rows()) && (matrix1.cols() == matrix2.cols()) ) { for( unsigned int r=0; repsilon) { return false; } } } return true; } else { return false; } } /*! \brief Check for element-wise matrix equality with a user defined accuracy. \param matrix1 first itk matrix \param matrix2 second itk matrix \epsilon user defined accuracy bounds */ template inline bool MatrixEqualElementWise(const itk::Matrix& matrix1,const itk::Matrix& matrix2,mitk::ScalarType epsilon=mitk::eps) { return mitk::MatrixEqualElementWise(matrix1.GetVnlMatrix(),matrix2.GetVnlMatrix(),epsilon); } template inline bool Equal(const itk::Vector& vector1, const itk::Vector& vector2, TCoordRep eps=mitk::eps) { typename itk::Vector::VectorType diff = vector1-vector2; for (unsigned int i=0; ieps || diff[i]<-eps) return false; return true; } template inline bool Equal(const itk::Point& vector1, const itk::Point& vector2, TCoordRep eps=mitk::eps) { typename itk::Point::VectorType diff = vector1-vector2; for (unsigned int i=0; ieps || diff[i]<-eps) return false; return true; } inline bool Equal(const mitk::VnlVector& vector1, const mitk::VnlVector& vector2, ScalarType eps=mitk::eps) { mitk::VnlVector diff = vector1-vector2; for (unsigned int i=0; ieps || diff[i]<-eps) return false; return true; } inline bool Equal(double scalar1, double scalar2, ScalarType eps=mitk::eps) { return fabs(scalar1-scalar2) < eps; } template inline bool Equal(const vnl_vector_fixed & vector1, const vnl_vector_fixed& vector2, TCoordRep eps=mitk::eps) { vnl_vector_fixed diff = vector1-vector2; - return diff.squared_magnitude() < mitk::eps; + bool returnValue = true; + for( unsigned int i=0; ieps || diff[i]<-eps) + { + returnValue = false; + } + } + + return returnValue; } template inline void TransferMatrix(const itk::Matrix& in, itk::Matrix& out) { for (unsigned int i = 0; i < in.RowDimensions; ++i) for (unsigned int j = 0; j < in.ColumnDimensions; ++j) out[i][j] = in[i][j]; } } // namespace mitk #endif //DOXYGEN_SKIP /* * This part of the code has been shifted here to avoid compiler clashes * caused by including before the declaration of * the Equal() methods above. This problem occurs when using MSVC and is * probably related to a compiler bug. */ #include namespace mitk { typedef itk::AffineGeometryFrame::TransformType AffineTransform3D; } #define mitkSetConstReferenceMacro(name,type) \ virtual void Set##name (const type & _arg) \ { \ itkDebugMacro("setting " << #name " to " << _arg ); \ if (this->m_##name != _arg) \ { \ this->m_##name = _arg; \ this->Modified(); \ } \ } #define mitkSetVectorMacro(name,type) \ mitkSetConstReferenceMacro(name,type) #define mitkGetVectorMacro(name,type) \ itkGetConstReferenceMacro(name,type) #endif /* MITKVECTOR_H_HEADER_INCLUDED_C1EBD0AD */ diff --git a/Core/Code/Testing/mitkVectorTest.cpp b/Core/Code/Testing/mitkVectorTest.cpp index 5718a58413..f5ed207d5c 100644 --- a/Core/Code/Testing/mitkVectorTest.cpp +++ b/Core/Code/Testing/mitkVectorTest.cpp @@ -1,125 +1,137 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include int mitkVectorTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN("mitkVector"); // test itk vector equality methods itk::Vector itkVector_1; itkVector_1[0] = 4.6; itkVector_1[1] = 9.76543; itkVector_1[2] = 746.09; itk::Vector itkVector_2; itk::Vector itkVector_3; for (int i=0; i<3; i++) { itkVector_2[i] = itkVector_1[i] - mitk::eps*1.1; itkVector_3[i] = itkVector_1[i] - mitk::eps*0.9; } - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(itkVector_1,itkVector_1), "Test vector equality using the same vector with mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(!mitk::Equal(itkVector_1,itkVector_2), "Test vector equality using different vectors with an element-wise difference greater than mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(itkVector_1,itkVector_3), "Test vector equality using different vectors with an element-wise difference less than mitk::eps"); + MITK_TEST_CONDITION(mitk::Equal(itkVector_1,itkVector_1), "Test vector equality using the same vector with mitk::eps"); + MITK_TEST_CONDITION(!mitk::Equal(itkVector_1,itkVector_2), "Test vector equality using different vectors with an element-wise difference greater than mitk::eps"); + MITK_TEST_CONDITION( mitk::Equal(itkVector_1, itkVector_2, mitk::eps*1.2f), "Vectors are equal for higher epsilon tolerance ( 1.2 * mitk::eps )"); + MITK_TEST_CONDITION(mitk::Equal(itkVector_1,itkVector_3), "Test vector equality using different vectors with an element-wise difference less than mitk::eps"); // test itk point equality methods itk::Point itkPoint_1; itk::Point itkPoint_2; itk::Point itkPoint_3; for (int i=0; i<3; i++) { itkPoint_1[i] = itkVector_1[i]; itkPoint_2[i] = itkVector_2[i]; itkPoint_3[i] = itkVector_3[i]; } - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(itkPoint_1,itkPoint_1), "Test point equality using the same point with mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(!mitk::Equal(itkPoint_1,itkPoint_2), "Test point equality using different points with an element-wise difference greater than mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(itkPoint_1,itkPoint_3), "Test point equality using different points with an element-wise difference less than mitk::eps"); + MITK_TEST_CONDITION(mitk::Equal(itkPoint_1,itkPoint_1), "Test point equality using the same point with mitk::eps"); + MITK_TEST_CONDITION(!mitk::Equal(itkPoint_1,itkPoint_2), "Test point equality using different points with an element-wise difference greater than mitk::eps"); + MITK_TEST_CONDITION( mitk::Equal(itkPoint_1, itkPoint_2, mitk::eps * 1.2f), "Points are equal for higher epsilon tolerance ( 1.2 * mitk::eps )"); + MITK_TEST_CONDITION(mitk::Equal(itkPoint_1,itkPoint_3), "Test point equality using different points with an element-wise difference less than mitk::eps"); // test mitk vnl vector equality methods mitk::VnlVector mitk_vnl_vector_1(3); mitk::VnlVector mitk_vnl_vector_2(3); mitk::VnlVector mitk_vnl_vector_3(3); for (int i=0; i<3; i++) { mitk_vnl_vector_1.put(i,itkVector_1[i]); mitk_vnl_vector_2.put(i,itkVector_2[i]); mitk_vnl_vector_3.put(i,itkVector_1[i]); } - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(mitk_vnl_vector_1,mitk_vnl_vector_1), "Test mitk vnl vector equality using the same mitk vnl vector with mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(!mitk::Equal(mitk_vnl_vector_1,mitk_vnl_vector_2), "Test mitk vnl vector equality using different mitk vnl vectors with an element-wise difference greater than mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(mitk_vnl_vector_1,mitk_vnl_vector_3), "Test mitk vnl vector equality using different mitk vnl vectors with an element-wise difference less than mitk::eps"); + + MITK_TEST_CONDITION(mitk::Equal(mitk_vnl_vector_1,mitk_vnl_vector_1), "Test mitk vnl vector equality using the same mitk vnl vector with mitk::eps"); + MITK_TEST_CONDITION(!mitk::Equal(mitk_vnl_vector_1,mitk_vnl_vector_2), "Test mitk vnl vector equality using different mitk vnl vectors with an element-wise difference greater than mitk::eps"); + MITK_TEST_CONDITION( mitk::Equal(mitk_vnl_vector_1, mitk_vnl_vector_2, mitk::eps*1.2), "Vnl vectors are equal for higher epsilon tolerance ( 1.2 * mitk::eps )"); + MITK_TEST_CONDITION(mitk::Equal(mitk_vnl_vector_1,mitk_vnl_vector_3), "Test mitk vnl vector equality using different mitk vnl vectors with an element-wise difference less than mitk::eps"); + // test vnl_vector equality method - vnl_vector_fixed vnlVector_1; + typedef mitk::ScalarType VnlValueType; + vnl_vector_fixed vnlVector_1; vnlVector_1[3] = 56.98; vnlVector_1[4] = 22.32; vnlVector_1[5] = 1.00; - vnlVector_1[6] = 119.02; - vnl_vector_fixed vnlVector_2; - vnl_vector_fixed vnlVector_3; + vnlVector_1[6] = 746.09; + vnl_vector_fixed vnlVector_2; + vnl_vector_fixed vnlVector_3; for (int i=0; i<7; i++) { if (i<3) { vnlVector_1.put(i,itkVector_1[i]); } - vnlVector_2[i] = vnlVector_1[i]- sqrt(mitk::eps/6.9); - vnlVector_3[i] = vnlVector_1[i]- sqrt(mitk::eps/7.1); + + vnlVector_2[i] = vnlVector_1[i] - mitk::eps * 1.1f; + vnlVector_3[i] = vnlVector_1[i] - mitk::eps * 0.9f; } - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(vnlVector_1,vnlVector_1), "Test vnl vector equality using the same vnl vector with mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(!mitk::Equal(vnlVector_1,vnlVector_2), "Test vnl vector equality using different vnl vectors with an element-wise difference greater than mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(vnlVector_1,vnlVector_3), "Test vnl vector equality using different vnl vectors with an element-wise difference less than mitk::eps"); + + MITK_TEST_CONDITION( (mitk::Equal(vnlVector_1,vnlVector_1)), "vnl_fixed : v_1 == v_1 "); + // the v_2 is constructed so that the equality test fails for mitk::eps, the norm of the difference between the vectors is 7 * eps/6.9 + MITK_TEST_CONDITION(!(mitk::Equal(vnlVector_1,vnlVector_2)), "vnl_fixed : v_1 != v_2 with mitk::eps "); + // increase the epsilon value used for testing equality - should now pass ( 1.2 * mitk::eps > 7 * mitk::eps/6.9 ) + MITK_TEST_CONDITION( (mitk::Equal(vnlVector_1,vnlVector_2, mitk::eps*1.2f)) , "vnl_fixed : v_1 == v_2 with eps = 1.2 * mitk::eps "); + MITK_TEST_CONDITION( (mitk::Equal(vnlVector_1,vnlVector_3, mitk::eps)), "vnl_fixed : v_1 == v_3 with eps = 0.8 * mitk::eps "); + MITK_TEST_CONDITION(!(mitk::Equal(vnlVector_1,vnlVector_3, mitk::eps*0.8f)), "vnl_fixed : v_1 != v_3 with eps = 0.8 * mitk::eps "); // test scalar equality method double scalar1 = 0.5689; double scalar2 = scalar1 + mitk::eps; double scalar3 = scalar1 + mitk::eps*0.95; - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(scalar1,scalar1), "Test scalar equality using the same scalar with mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(!mitk::Equal(scalar1,scalar2), "Test scalar equality using the different scalars with a difference greater than mitk::eps"); - MITK_TEST_CONDITION_REQUIRED(mitk::Equal(scalar1,scalar3), "Test scalar equality using the different scalars with a difference less than mitk::eps"); + MITK_TEST_CONDITION(mitk::Equal(scalar1,scalar1), "Test scalar equality using the same scalar with mitk::eps"); + MITK_TEST_CONDITION(!mitk::Equal(scalar1,scalar2), "Test scalar equality using the different scalars with a difference greater than mitk::eps"); + MITK_TEST_CONDITION(mitk::Equal(scalar1,scalar3), "Test scalar equality using the different scalars with a difference less than mitk::eps"); // test matrix equality methods vnl_matrix_fixed vnlMatrix3x3_1; vnlMatrix3x3_1(0,0) = 1.1; vnlMatrix3x3_1(0,1) = 0.4; vnlMatrix3x3_1(0,2) = 5.3; vnlMatrix3x3_1(1,0) = 2.7; vnlMatrix3x3_1(1,1) = 3578.56418; vnlMatrix3x3_1(1,2) = 123.56; vnlMatrix3x3_1(2,0) = 546.89; vnlMatrix3x3_1(2,1) = 0.0001; vnlMatrix3x3_1(2,2) = 1.0; vnl_matrix_fixed vnlMatrix3x3_2; vnlMatrix3x3_2(0,0) = 1.1000009; vnlMatrix3x3_2(0,1) = 0.4000009; vnlMatrix3x3_2(0,2) = 5.3000009; vnlMatrix3x3_2(1,0) = 2.7000009; vnlMatrix3x3_2(1,1) = 3578.5641809; vnlMatrix3x3_2(1,2) = 123.5600009; vnlMatrix3x3_2(2,0) = 546.8900009; vnlMatrix3x3_2(2,1) = 0.0001009; vnlMatrix3x3_2(2,2) = 1.0000009; mitk::ScalarType epsilon = 0.000001; - MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualElementWise(vnlMatrix3x3_1,vnlMatrix3x3_1,0.0),"Test for matrix equality with given epsilon=0.0 and exactly the same matrix elements"); - MITK_TEST_CONDITION_REQUIRED(!mitk::MatrixEqualElementWise(vnlMatrix3x3_1,vnlMatrix3x3_2,0.0),"Test for matrix equality with given epsilon=0.0 and slightly different matrix elements"); - MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualElementWise(vnlMatrix3x3_1,vnlMatrix3x3_2,epsilon),"Test for matrix equality with given epsilon and slightly different matrix elements"); - MITK_TEST_CONDITION_REQUIRED(!mitk::MatrixEqualRMS(vnlMatrix3x3_1,vnlMatrix3x3_2,0.0),"Test for matrix equality with given epsilon=0.0 and slightly different matrix elements"); - MITK_TEST_CONDITION_REQUIRED(mitk::MatrixEqualRMS(vnlMatrix3x3_1,vnlMatrix3x3_2,epsilon),"Test for matrix equality with given epsilon and slightly different matrix elements"); + MITK_TEST_CONDITION(mitk::MatrixEqualElementWise(vnlMatrix3x3_1,vnlMatrix3x3_1,0.0),"Test for matrix equality with given epsilon=0.0 and exactly the same matrix elements"); + MITK_TEST_CONDITION(!mitk::MatrixEqualElementWise(vnlMatrix3x3_1,vnlMatrix3x3_2,0.0),"Test for matrix equality with given epsilon=0.0 and slightly different matrix elements"); + MITK_TEST_CONDITION(mitk::MatrixEqualElementWise(vnlMatrix3x3_1,vnlMatrix3x3_2,epsilon),"Test for matrix equality with given epsilon and slightly different matrix elements"); + MITK_TEST_CONDITION(!mitk::MatrixEqualRMS(vnlMatrix3x3_1,vnlMatrix3x3_2,0.0),"Test for matrix equality with given epsilon=0.0 and slightly different matrix elements"); + MITK_TEST_CONDITION(mitk::MatrixEqualRMS(vnlMatrix3x3_1,vnlMatrix3x3_2,epsilon),"Test for matrix equality with given epsilon and slightly different matrix elements"); MITK_TEST_END(); }