diff --git a/Core/Code/DataManagement/mitkTypes.h b/Core/Code/DataManagement/mitkTypes.h index d8541e7fc5..b9754f6b8f 100644 --- a/Core/Code/DataManagement/mitkTypes.h +++ b/Core/Code/DataManagement/mitkTypes.h @@ -1,260 +1,277 @@ /*=================================================================== 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 #include "mitkTypeBasics.h" #include "mitkTypedefs.h" #include "mitkPoint.h" // TODO SW: should not be included here, maybe generate one "general datatype include" like mitkPrimitives.h #include "mitkVector.h" #include "mitkMatrix.h" #include "mitkOldTypeConversions.h" #ifndef DOXYGEN_SKIP namespace mitk { template 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 \param 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 \param 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(ScalarType scalar1, ScalarType 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; bool returnValue = true; for( unsigned int i=0; ieps || diff[i]<-eps) { returnValue = false; } } return returnValue; } +/** + * Compares two ArrayTypes of size size. + * ArrayTypes are all Objects/Types who have a [] operator. Pay attention not to set size higher + * than the actual size of the ArrayType. For POD arrays like float array[4] this will memory corruption. + */ +template + inline bool EqualArray(TArrayType1& arrayType1, TArrayType2& arrayType2, int size, ScalarType eps = mitk::eps) +{ + bool isEqual = true; + for (int var = 0; var < size; ++var) + { + isEqual = isEqual && Equal(arrayType1[var], arrayType2[var], eps); + } + return isEqual; +} + } // 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/DataManagement/mitkVector.h b/Core/Code/DataManagement/mitkVector.h index e63760cffd..51858ff4de 100644 --- a/Core/Code/DataManagement/mitkVector.h +++ b/Core/Code/DataManagement/mitkVector.h @@ -1,111 +1,125 @@ /*=================================================================== 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_ #define MITKVECTOR_H_ #include #include #include #include "mitkTypeBasics.h" #include "mitkLogMacros.h" namespace mitk { template class Vector : public itk::Vector { public: /** Default constructor has nothing to do. */ Vector() : itk::Vector() {} /** * Constructor to convert from mitk::Vector to mitk::Vector. * Can convert nonidentical types. * E.g. use this to convert from mitk::Vector to mitk::Vector */ template Vector(const Vector& r) : itk::Vector(r) {} /** * Constructor to convert from itk::Vector to mitk::Vector. * Can convert nonidentical types. * E.g. use this to convert from itk::Vector to mitk::Vector */ template Vector(const itk::Vector& r) : itk::Vector(r) {} Vector(const TCoordRep r[NVectorDimension]) : itk::Vector(r) {} /** * Constructor to initialize entire vector to one value. */ - Vector(const TCoordRep & v):itk::Vector(v) - {} + Vector(const TCoordRep & v) + : itk::Vector(v) {} /** * Attention: vnlVector should have same size as NVectorDimension, otherwise * 1. elements will be lost in case vnlVector is bigger. * 2. elements will be set to 0 in case this is bigger. * In both cases, MITK_WARN warnings will be issued. */ Vector(const vnl_vector& vnlVector) : itk::Vector() { this->Fill(0); if (vnlVector.size() < NVectorDimension) MITK_WARN << "Attention: conversion of vnl_vector to mitk::Vector:" << "the mitk::Vector has more elements than the vnl_vector. Remaining elements will be set to 0."; if (NVectorDimension < vnlVector.size()) MITK_WARN << "Attention: conversion of vnl_vector to mitk::Vector:" << "the vnl_vector has more elements than the mitk::Vector. vnlVector[NVectorDimension .. vnlVector.size()] will be lost."; for (int var = 0; (var < NVectorDimension) && (var < vnlVector.size()); ++var) { this->SetElement(var, vnlVector.get(var)); } }; - Vector(const vnl_vector_fixed vnlVectorFixed) + /** + * Convert a vnl_vector_fixed to a mitk::Vector of the same size and coordinate representation. + * TODO SW: allow different coordinate representations. + */ + Vector(const vnl_vector_fixed vnlVectorFixed) : itk::Vector(vnlVectorFixed.data_block()){}; /** * Warning: Array must have same dimension as Vector */ void CopyToArray(ScalarType array_p[NVectorDimension]) const { for (int i = 0; i < this->GetVectorDimension(); i++) { array_p[i] = this->GetElement(i); } } - }; + + /** + * User defined conversion of mitk::Vector to vnl_vector_fixed + */ + operator vnl_vector_fixed& () const + { + vnl_vector_fixed vnlVectorFixed(this->GetVnlVector()); + return vnlVectorFixed; + } + + }; // end mitk::Vector typedef Vector Vector2D; typedef Vector Vector3D; typedef Vector Vector4D; -} +} // end namespace mitk #endif /* MITKVECTOR_H_ */ diff --git a/Core/Code/Testing/mitkTypeVectorConversionTest.cpp b/Core/Code/Testing/mitkTypeVectorConversionTest.cpp index f9186aaea8..61a07a2ae9 100644 --- a/Core/Code/Testing/mitkTypeVectorConversionTest.cpp +++ b/Core/Code/Testing/mitkTypeVectorConversionTest.cpp @@ -1,225 +1,208 @@ /*=================================================================== 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 "itkVector.h" #include #include #include "vnl/vnl_math.h" #include "mitkTestingMacros.h" #include "mitkTypeBasics.h" #include "mitkVector.h" #include "mitkTypes.h" // for Equals using namespace mitk; /** * these private variables are used in the test functions * * The variable which should be copied into is set to its original value. * The value which should be copied is set to valuesToCopy. * * Then the copying takes place. The test is successful, if the variable which * should be copied into holds the valuesToCopy afterwards and is equal to the * vector which should be copied. */ static const ScalarType originalValues[] = {1.123456789987, 2.789456321456, 3.123654789987456}; static const float originalValuesFloat[] = {1.123456789987, 2.789456321456, 3.123654789987456}; static const ScalarType valuesToCopy[] = {4.654789123321, 5.987456789321, 6.321654987789546}; static const float valuesToCopyFloat[] = {4.654789123321, 5.987456789321, 6.321654987789546}; static void Test_mitk2mitk_DifferntTypeCompatibility(void) { mitk::Vector floatVector3D = originalValuesFloat; mitk::Vector doubleVector3D = valuesToCopy; floatVector3D = doubleVector3D; MITK_TEST_CONDITION(floatVector3D == doubleVector3D, "mitk double vector assigned to mitk float vector") - - // test for correct values needs a little more love than in other cases - // since Equal cannot compare arrays/vectors of different type - bool correctValuesAssigned = true; - for (int var = 0; var < 3; ++var) { - correctValuesAssigned = correctValuesAssigned - && Equal(floatVector3D[var], valuesToCopy[var], vnl_math::float_eps * 10.0); - } - MITK_TEST_CONDITION(correctValuesAssigned, "correct values were assigned within float accuracy") + MITK_TEST_CONDITION(EqualArray(floatVector3D, valuesToCopy, 3, vnl_math::float_eps * 10.), "correct values were assigned within float accuracy") } static void Test_itk2mitk_Compatibility(void) { Vector3D vector3D = originalValues; itk::Vector itkVector = valuesToCopy; vector3D = itkVector; MITK_TEST_CONDITION(vector3D == itkVector, "itk vector assigned to mitk vector") MITK_TEST_CONDITION(vector3D == valuesToCopy, "correct values were assigned") } static void Test_itk2mitk_floatCompatibility(void) { Vector3D vector3D = originalValues; itk::Vector itkVector = valuesToCopyFloat; vector3D = itkVector; MITK_TEST_CONDITION(vector3D == itkVector, "itk float vector assigned to mitk double vector") - - // test for correct values needs a little more love than in other cases - // since Equal cannot compare arrays/vectors of different type - bool correctValuesAssigned = true; - for (int var = 0; var < 3; ++var) { - correctValuesAssigned = correctValuesAssigned - && Equal(vector3D[var], valuesToCopyFloat[var]); - } - MITK_TEST_CONDITION(correctValuesAssigned, "correct values were assigned") + MITK_TEST_CONDITION(EqualArray(vector3D, valuesToCopyFloat, 3), "correct values were assigned") } static void Test_mitk2itk_Compatibility(void) { Vector3D vector3D = valuesToCopy; itk::Vector itkVector = originalValues; itkVector = vector3D; MITK_TEST_CONDITION(vector3D == itkVector, "mitk vector assigned to itk vector") MITK_TEST_CONDITION(itkVector == valuesToCopy, "correct values were assigned") } static void Test_mitk2itk_floatCompatibility(void) { itk::Vector itkDoubleVector = originalValues; mitk::Vector mitkFloatVector = valuesToCopyFloat; itkDoubleVector = mitkFloatVector; MITK_TEST_CONDITION(itkDoubleVector == mitkFloatVector, "mitk float vector assigned to itk double vector") - - // test for correct values needs a little more love than in other cases - // since Equal cannot compare arrays/vectors of different type - bool correctValuesAssigned = true; - for (int var = 0; var < 3; ++var) { - correctValuesAssigned = correctValuesAssigned - && Equal(itkDoubleVector[var], valuesToCopyFloat[var]); - } - MITK_TEST_CONDITION(correctValuesAssigned, "correct values were assigned") + MITK_TEST_CONDITION(EqualArray(itkDoubleVector, valuesToCopyFloat, 3), "correct values were assigned") } - - static void Test_vnl2mitk_VectorFixedCompatibility() { - mitk::Vector3D vector3D = originalValues; vnl_vector_fixed vnlVectorFixed(valuesToCopy); vector3D = vnlVectorFixed; MITK_TEST_CONDITION( vector3D.GetVnlVector() == vnlVectorFixed, "vnl_vector_fixed assigned to mitk vector") MITK_TEST_CONDITION( vector3D == valuesToCopy, "correct values were assigned" ) } + +static void Test_mitk2vnl_VectorFixedCompatibility() +{ + vnl_vector_fixed vnlVectorFixed(originalValues); + mitk::Vector3D vector3D = valuesToCopy; + + vnlVectorFixed = vector3D; + + MITK_TEST_CONDITION( vnlVectorFixed == vector3D.GetVnlVector(), "mitk vector assigned to vnl_vector_fixed") + MITK_TEST_CONDITION( EqualArray(vnlVectorFixed, valuesToCopy, 3), "correct values were assigned" ) +} + + static void Test_vnl2mitk_VectorCompatibility() { mitk::Vector3D vector3D = originalValues; vnl_vector vnlVector(3); vnlVector.set(valuesToCopy); vector3D = vnlVector; MITK_TEST_CONDITION( vector3D.GetVnlVector() == vnlVector, "vnl_vector assigned to mitk vector") MITK_TEST_CONDITION( vector3D == valuesToCopy, "correct values were assigned" ) } /** - * tests if constructing a mitk::Vector using a shorter in size vnl_vector is handled properly + * tests if constructing a mitk::Vector using a shorter in size vnl_vector is handled properly. + * Attention: + * say you have a mitk::Vector holding {1, 2, 3}. + * Now you assign a vnl_vector holdin {4, 5}. + * + * The result will be {4, 5, 0}, not {4, 5, 3} */ -static void Test_vnl2mitk_ShortVectorCompatibility() +static void Test_vnl2mitk_ShorterVectorCompatibility() { ScalarType shorterValuesToCopy[] = {4.12345678910, 5.10987654321}; mitk::Vector3D vector3D = originalValues; vnl_vector vnlVector(2); vnlVector.set(shorterValuesToCopy); vector3D = vnlVector; - bool correctValuesInVector3D = true; - for (int var = 0; var < 2; ++var) { - correctValuesInVector3D = correctValuesInVector3D && - (vector3D[var] && shorterValuesToCopy[var]); - } - correctValuesInVector3D = correctValuesInVector3D && (vector3D[2] == 0.0); + bool firstTwoElementsCopied = EqualArray(vector3D, vnlVector, 2); + bool lastElementIs0 = (vector3D[2] == 0.0); - MITK_TEST_CONDITION(correctValuesInVector3D, "shorter vnl vector correctly assigned to mitk vector" ) + MITK_TEST_CONDITION( + firstTwoElementsCopied && lastElementIs0, "shorter vnl vector correctly assigned to mitk vector" ) } /** * tests if constructing a mitk::Vector using a large in size vnl_vector is handled properly */ -static void Test_vnl2mitk_LargeVectorCompatibility() +static void Test_vnl2mitk_LargerVectorCompatibility() { ScalarType largerValuesToCopy[] = {4.12345678910, 5.10987654321, 6.123456789132456, 7.123456987789456}; mitk::Vector3D vector3D = originalValues; vnl_vector vnlVector(4); vnlVector.set(largerValuesToCopy); vector3D = vnlVector; - bool correctValuesInVector3D = true; - for (int var = 0; var < 3; ++var) { - correctValuesInVector3D = correctValuesInVector3D && - (vector3D[var] && largerValuesToCopy[var]); - } - - MITK_TEST_CONDITION(correctValuesInVector3D, "larger vnl vector correctly assigned to mitk vector" ) + MITK_TEST_CONDITION(EqualArray(vector3D, largerValuesToCopy, 3), "larger vnl vector correctly assigned to mitk vector" ) } /** * Test the conversions from and to the mitk vector type */ int mitkTypeVectorConversionTest(int /*argc*/ , char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("VectorConversionTest") Test_mitk2mitk_DifferntTypeCompatibility(); Test_itk2mitk_Compatibility(); Test_itk2mitk_floatCompatibility(); Test_mitk2itk_Compatibility(); Test_mitk2itk_floatCompatibility(); Test_vnl2mitk_VectorFixedCompatibility(); + Test_mitk2vnl_VectorFixedCompatibility(); Test_vnl2mitk_VectorCompatibility(); - Test_vnl2mitk_ShortVectorCompatibility(); - Test_vnl2mitk_LargeVectorCompatibility(); + Test_vnl2mitk_ShorterVectorCompatibility(); + Test_vnl2mitk_LargerVectorCompatibility(); MITK_TEST_END() }