diff --git a/Core/Code/DataManagement/mitkVector.h b/Core/Code/DataManagement/mitkVector.h index 51858ff4de..6acd492e6a 100644 --- a/Core/Code/DataManagement/mitkVector.h +++ b/Core/Code/DataManagement/mitkVector.h @@ -1,125 +1,178 @@ /*=================================================================== 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. */ + /** + * @brief Default constructor has nothing to do. + */ Vector() : itk::Vector() {} /** - * Constructor to convert from mitk::Vector to mitk::Vector. - * Can convert nonidentical types. + * @brief Copy constructor. + * Can convert nonidentical coordinate representations. * E.g. use this to convert from mitk::Vector to mitk::Vector */ - template - Vector(const Vector& r) + template + Vector(const Vector& r) : itk::Vector(r) {} /** - * Constructor to convert from itk::Vector to mitk::Vector. - * Can convert nonidentical types. + * @brief Constructor to convert from itk::Vector to mitk::Vector. + * Can convert non-identical coordinate representations. * E.g. use this to convert from itk::Vector to mitk::Vector */ - template - Vector(const itk::Vector& r) + template + Vector(const itk::Vector& r) : itk::Vector(r) {} - Vector(const TCoordRep r[NVectorDimension]) - : itk::Vector(r) {} +// /** +// * @brief convert an array of the same data type to Vector. +// * @param r the array. Attention: must have NVectorDimension valid arguments! +// */ +// Vector(const TCoordRep r[NVectorDimension]) +// : itk::Vector(r) {} + + /** + * @brief convert an array of a different data type to Vector + * @param r the array. Attention: must have NVectorDimension valid arguments! + */ + template + Vector(const TOtherCoordRep r[NVectorDimension]) + : itk::Vector() + { // TODO SW: very strange: you could leave the following lines and gcc would still copy the array! + for (int var = 0; var < 3; ++var) { + this->SetElement(var, static_cast(r[var])); + } + } /** * Constructor to initialize entire vector to one value. */ Vector(const TCoordRep & v) : itk::Vector(v) {} /** + * @brief Constructor for vnl_vectors. + * Can convert non-identical coordinate representations. * 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) + template + 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)); + this->SetElement(var, static_cast(vnlVector.get(var))); } - }; + } + + template + Vector& operator=(const Vector& otherVector) + { + for (int var = 0; (var < NVectorDimension) && (var < NOtherVectorDimension); ++var) { + this->SetElement(var, static_cast(otherVector[var])); + } + return *this; + } + /** - * Convert a vnl_vector_fixed to a mitk::Vector of the same size and coordinate representation. - * TODO SW: allow different coordinate representations. + * @brief Convert a vnl_vector_fixed to a mitk::Vector of the same size. + * Can convert non-identical coordinate representations. */ - Vector(const vnl_vector_fixed vnlVectorFixed) - : itk::Vector(vnlVectorFixed.data_block()){}; + template + Vector(const vnl_vector_fixed vnlVectorFixed) + : itk::Vector() + { + for (int var = 0; var < 3; ++var) { + this->SetElement(var, static_cast(vnlVectorFixed[var])); + } + }; + + template + Vector& operator=(const vnl_vector_fixed& vnlVectorFixed) + { + for (int var = 0; (var < NVectorDimension) && (var < NOtherVectorDimension); ++var) { + this->SetElement(var, static_cast(vnlVectorFixed[var])); + } + return *this; + } + /** - * Warning: Array must have same dimension as Vector + * @brief User defined conversion of mitk::Vector to vnl_vector_fixed */ - void CopyToArray(ScalarType array_p[NVectorDimension]) const + template + operator vnl_vector_fixed () const { - for (int i = 0; i < this->GetVectorDimension(); i++) - { - array_p[i] = this->GetElement(i); - } + Vector convertedVector = *this; + vnl_vector_fixed vnlVectorFixed(convertedVector.GetVnlVector()); + return vnlVectorFixed; } + /** - * User defined conversion of mitk::Vector to vnl_vector_fixed + * @brief Copies the array array_p to this Vector. + * Warning: Array must have same dimension as Vector */ - operator vnl_vector_fixed& () const + template + void CopyToArray(TOtherCoordRep array_p[NVectorDimension]) const { - vnl_vector_fixed vnlVectorFixed(this->GetVnlVector()); - return vnlVectorFixed; + for (int i = 0; i < this->GetVectorDimension(); i++) + { + array_p[i] = static_cast(this->GetElement(i)); + } } }; // 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 61a07a2ae9..7707faa11e 100644 --- a/Core/Code/Testing/mitkTypeVectorConversionTest.cpp +++ b/Core/Code/Testing/mitkTypeVectorConversionTest.cpp @@ -1,208 +1,336 @@ /*=================================================================== 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_pod2mitk(void) +{ + mitk::Vector3D vector3D = valuesToCopy; + + MITK_TEST_CONDITION(EqualArray(vector3D, valuesToCopy, 3), "pod copied into vector of same type") +} + +static void Test_pod2mitk_DifferentType(void) +{ + mitk::Vector3D vector3D = valuesToCopyFloat; + + MITK_TEST_CONDITION(EqualArray(vector3D, valuesToCopyFloat, 3, vnl_math::float_eps), "float pod copied into double vector") +} + + +static void Test_mitk2pod(void) +{ + ScalarType podArray[3]; + mitk::Vector3D vector3D = valuesToCopy; + + vector3D.CopyToArray(podArray); + + MITK_TEST_CONDITION(EqualArray(podArray, vector3D, 3), "mitk vector copied into pod array") +} + +static void Test_mitk2pod_DifferentType(void) +{ + float podArray[3]; + mitk::Vector3D vector3D = valuesToCopy; + + vector3D.CopyToArray(podArray); + + MITK_TEST_CONDITION(EqualArray(podArray, vector3D, 3, vnl_math::float_eps*10.0), "mitk vector copied into pod array with different type") +} + +static void Test_oneElement2mitk(void) +{ + double twos[] = {2.0, 2.0, 2.0}; + mitk::Vector vector3D(2.0); + + MITK_TEST_CONDITION(EqualArray(vector3D, twos, 3), "one values initializes all elements to this value") +} + +static void Test_oneElement2mitk_DifferentType(void) +{ + float twos[] = {2.0, 2.0, 2.0}; + mitk::Vector vector3D(2.0F); + + MITK_TEST_CONDITION(EqualArray(vector3D, twos, 3), "one values initializes all elements to this value: value has different type than vector.") +} -static void Test_mitk2mitk_DifferntTypeCompatibility(void) +static void Test_mitk2mitk_DifferentType(void) { mitk::Vector floatVector3D = originalValuesFloat; mitk::Vector doubleVector3D = valuesToCopy; floatVector3D = doubleVector3D; MITK_TEST_CONDITION(floatVector3D == doubleVector3D, "mitk double vector assigned to mitk float vector") - MITK_TEST_CONDITION(EqualArray(floatVector3D, valuesToCopy, 3, vnl_math::float_eps * 10.), "correct values were assigned within float accuracy") + MITK_TEST_CONDITION(EqualArray(floatVector3D, valuesToCopy, 3, vnl_math::float_eps * 10.0), "correct values were assigned within float accuracy") +} + +static void Test_mitk2mitk_ShorterVectorAssigned(void) +{ + mitk::Vector3D vector3D = originalValues; + mitk::Vector2D vector2D = valuesToCopy; + + vector3D = vector2D; + + bool firstTwoElementsCopied = EqualArray(vector3D, vector2D, 2); + bool lastElementIsUntouched = (vector3D[2] == originalValues[2]); + + MITK_TEST_CONDITION(firstTwoElementsCopied, "shorter mitk vector correctly assigned to mitk vector: first two elements were copied" ) + MITK_TEST_CONDITION(lastElementIsUntouched, "shorter mitk vector correctly assigned to mitk vector: last element was untoched") + } -static void Test_itk2mitk_Compatibility(void) +static void Test_itk2mitk(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) +static void Test_itk2mitk_DifferentType(void) { Vector3D vector3D = originalValues; itk::Vector itkVector = valuesToCopyFloat; vector3D = itkVector; MITK_TEST_CONDITION(vector3D == itkVector, "itk float vector assigned to mitk double vector") MITK_TEST_CONDITION(EqualArray(vector3D, valuesToCopyFloat, 3), "correct values were assigned") } -static void Test_mitk2itk_Compatibility(void) +static void Test_mitk2itk(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) +static void Test_mitk2itk_DifferentType(void) { itk::Vector itkDoubleVector = originalValues; mitk::Vector mitkFloatVector = valuesToCopyFloat; itkDoubleVector = mitkFloatVector; MITK_TEST_CONDITION(itkDoubleVector == mitkFloatVector, "mitk float vector assigned to itk double vector") MITK_TEST_CONDITION(EqualArray(itkDoubleVector, valuesToCopyFloat, 3), "correct values were assigned") } -static void Test_vnl2mitk_VectorFixedCompatibility() +static void Test_vnlfixed2mitk(void) { 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_vnlfixed2mitk_DifferentType(void) +{ + mitk::Vector vector3D = originalValues; + vnl_vector_fixed vnlVectorFixed(valuesToCopyFloat); + + vector3D = vnlVectorFixed; + + MITK_TEST_CONDITION( EqualArray(vector3D, vnlVectorFixed, 3), "vnl_vector_fixed float assigned to mitk vector double") + MITK_TEST_CONDITION( EqualArray(vector3D, valuesToCopyFloat, 3), "correct values were assigned" ) +} -static void Test_mitk2vnl_VectorFixedCompatibility() +static void Test_mitk2vnlfixed(void) { 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_mitk2vnlfixed_DifferentType(void) +{ + vnl_vector_fixed vnlVectorFixed(originalValuesFloat); + mitk::Vector vector3D = valuesToCopy; + + vnlVectorFixed = vector3D; + + MITK_TEST_CONDITION( EqualArray(vnlVectorFixed, vector3D, 3, vnl_math::float_eps * 10.0), "mitk vector assigned to vnl_vector_fixed") + MITK_TEST_CONDITION( EqualArray(vnlVectorFixed, valuesToCopy, 3, vnl_math::float_eps * 10.0), "correct values were assigned" ) +} + -static void Test_vnl2mitk_VectorCompatibility() +static void Test_vnl2mitk() { 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" ) } +static void Test_vnl2mitk_DifferentType() +{ + + mitk::Vector vector3D = originalValues; + vnl_vector vnlVector(3); + vnlVector.set(valuesToCopyFloat); + + vector3D = vnlVector; + + MITK_TEST_CONDITION( EqualArray(vector3D, vnlVector, 3, vnl_math::float_eps * 10.0), "vnl_vector assigned to mitk vector") + MITK_TEST_CONDITION( EqualArray(vector3D, valuesToCopy, 3, vnl_math::float_eps * 10.0), "correct values were assigned" ) +} + /** * 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_ShorterVectorCompatibility() +static void Test_vnl2mitk_ShorterVectorInConstructor() { - ScalarType shorterValuesToCopy[] = {4.12345678910, 5.10987654321}; - mitk::Vector3D vector3D = originalValues; vnl_vector vnlVector(2); - vnlVector.set(shorterValuesToCopy); + vnlVector.set(valuesToCopy); - vector3D = vnlVector; + mitk::Vector3D vector3D = vnlVector; bool firstTwoElementsCopied = EqualArray(vector3D, vnlVector, 2); bool lastElementIs0 = (vector3D[2] == 0.0); MITK_TEST_CONDITION( - firstTwoElementsCopied && lastElementIs0, "shorter vnl vector correctly assigned to mitk vector" ) + firstTwoElementsCopied && lastElementIs0, "shorter vnl vector correctly copied to mitk vector" ) } +//static void Test_vnl2mitk_ShorterVectorAssigned() +//{ +// mitk::Vector3D vector3D = originalValues; +// vnl_vector vnlVector(2); +// vnlVector.set(valuesToCopy); +// +// vector3D = vnlVector; +// +// bool firstTwoElementsCopied = EqualArray(vector3D, vnlVector, 2); +// bool lastElementUnchanged = (vector3D[2] == originalValues[2]); +// +// MITK_TEST_CONDITION( +// firstTwoElementsCopied && lastElementUnchanged, "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_LargerVectorCompatibility() +static void Test_vnl2mitk_LargerVectorConstructor() { ScalarType largerValuesToCopy[] = {4.12345678910, 5.10987654321, 6.123456789132456, 7.123456987789456}; mitk::Vector3D vector3D = originalValues; vnl_vector vnlVector(4); vnlVector.set(largerValuesToCopy); vector3D = vnlVector; 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_pod2mitk(); + Test_pod2mitk_DifferentType(); + + Test_mitk2pod(); + Test_mitk2pod_DifferentType(); + + Test_oneElement2mitk(); + Test_oneElement2mitk_DifferentType(); + + Test_mitk2mitk_DifferentType(); + Test_mitk2mitk_ShorterVectorAssigned(); + + Test_itk2mitk(); + Test_itk2mitk_DifferentType(); - Test_itk2mitk_Compatibility(); - Test_itk2mitk_floatCompatibility(); + Test_mitk2itk(); + Test_mitk2itk_DifferentType(); - Test_mitk2itk_Compatibility(); - Test_mitk2itk_floatCompatibility(); + Test_vnlfixed2mitk(); + Test_vnlfixed2mitk_DifferentType(); - Test_vnl2mitk_VectorFixedCompatibility(); - Test_mitk2vnl_VectorFixedCompatibility(); + Test_mitk2vnlfixed(); + Test_mitk2vnlfixed_DifferentType(); - Test_vnl2mitk_VectorCompatibility(); - Test_vnl2mitk_ShorterVectorCompatibility(); - Test_vnl2mitk_LargerVectorCompatibility(); + Test_vnl2mitk(); + Test_vnl2mitk_DifferentType(); + Test_vnl2mitk_ShorterVectorInConstructor(); + //Test_vnl2mitk_ShorterVectorAssigned(); + Test_vnl2mitk_LargerVectorConstructor(); MITK_TEST_END() }