diff --git a/code/core/rttbBaseType.h b/code/core/rttbBaseType.h index a761712..4e98c88 100644 --- a/code/core/rttbBaseType.h +++ b/code/core/rttbBaseType.h @@ -1,604 +1,610 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #ifndef __BASE_TYPE_NEW_H #define __BASE_TYPE_NEW_H #include #include #include #include #include #include #include #include namespace rttb { const double errorConstant = 1e-5; const double reducedErrorConstant = 0.0001; using UnsignedIndex1D = unsigned short; /*! @class UnsignedIndex3D @brief 3D index. */ class UnsignedIndex3D: public boost::numeric::ublas::vector { public: UnsignedIndex3D() : boost::numeric::ublas::vector(3,0) {} UnsignedIndex3D(const UnsignedIndex1D value) : boost::numeric::ublas::vector(3, value) {} UnsignedIndex3D(const UnsignedIndex1D xValue, const UnsignedIndex1D yValue, const UnsignedIndex1D zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const UnsignedIndex1D x() const { return (*this)(0); } const UnsignedIndex1D y() const { return (*this)(1); } const UnsignedIndex1D z() const { return (*this)(2); } friend bool operator==(const UnsignedIndex3D& gi1, const UnsignedIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const UnsignedIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; using UnsignedIndexList = std::list; using FileNameString = std::string; using ContourGeometricTypeString = std::string; using WorldCoordinate = double; /*! @class WorldCoordinate3D @brief 3D coordinate in real world coordinates like in DICOM to define ImagePositionPatient. */ class WorldCoordinate3D: public boost::numeric::ublas::vector { public: WorldCoordinate3D() : boost::numeric::ublas::vector(3,0) {} WorldCoordinate3D(const WorldCoordinate value) : boost::numeric::ublas::vector(3, value) {} WorldCoordinate3D(const WorldCoordinate xValue, const WorldCoordinate yValue, const WorldCoordinate zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } WorldCoordinate3D(const WorldCoordinate3D& w): boost::numeric::ublas::vector(3) { (*this)(0) = w.x(); (*this)(1) = w.y(); (*this)(2) = w.z(); } const WorldCoordinate x() const { return (*this)(0); } const WorldCoordinate y() const { return (*this)(1); } const WorldCoordinate z() const { return (*this)(2); } //vector cross product (not included in boost.ublas) WorldCoordinate3D cross(WorldCoordinate3D aVector) const { WorldCoordinate3D result; WorldCoordinate x = (*this)(0); WorldCoordinate y = (*this)(1); WorldCoordinate z = (*this)(2); result(0) = y * aVector(2) - z * aVector(1); result(1) = z * aVector(0) - x * aVector(2); result(2) = x * aVector(1) - y * aVector(0); return result; } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()) + " " + std::to_string(z()); return s; } WorldCoordinate3D& operator=(const WorldCoordinate3D& wc) { (*this)(0) = wc.x(); (*this)(1) = wc.y(); (*this)(2) = wc.z(); return (*this); } WorldCoordinate3D& operator=(const boost::numeric::ublas::vector wc) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } WorldCoordinate3D operator-(const boost::numeric::ublas::vector wc) { return WorldCoordinate3D((*this)(0) - wc(0), (*this)(1) - wc(1), (*this)(2) - wc(2)); } WorldCoordinate3D operator+(const boost::numeric::ublas::vector wc) { return WorldCoordinate3D((*this)(0) + wc(0), (*this)(1) + wc(1), (*this)(2) + wc(2)); } friend bool operator==(const WorldCoordinate3D& wc1, const WorldCoordinate3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const WorldCoordinate3D& another, double errorConstantWC = 1e-5) const { if (size() != another.size()) { return false; } double dist = norm_2(*this - another); return dist < errorConstantWC; } friend std::ostream& operator<<(std::ostream& s, const WorldCoordinate3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /* ! @brief continuous index */ using DoubleVoxelGridIndex3D = rttb::WorldCoordinate3D; using ImageSize = rttb::UnsignedIndex3D; using GridVolumeType = double; /*! @class SpacingVectorType3D @brief 3D spacing vector. @pre values of this vector may not be negative. */ class SpacingVectorType3D: public boost::numeric::ublas::vector { public: SpacingVectorType3D() : boost::numeric::ublas::vector(3,0) {} SpacingVectorType3D(const GridVolumeType value) : boost::numeric::ublas::vector(3, - value) {} + value) + { + if (value < 0) { + throw std::invalid_argument("received negative value"); + } + } + SpacingVectorType3D(const GridVolumeType xValue, const GridVolumeType yValue, const GridVolumeType zValue) - : boost::numeric::ublas::vector(3, xValue) + : boost::numeric::ublas::vector(3) { + if (xValue < 0 || yValue < 0 || zValue < 0) { + throw std::invalid_argument("received negative value"); + } + (*this)(0) = xValue; (*this)(1) = yValue; (*this)(2) = zValue; } - SpacingVectorType3D(const SpacingVectorType3D& w): boost::numeric::ublas::vector(3) - { - (*this)(0) = w.x(); - (*this)(1) = w.y(); - (*this)(2) = w.z(); - } + + SpacingVectorType3D(const SpacingVectorType3D& w) : SpacingVectorType3D(w.x(), w.y(), w.z()) { } const GridVolumeType x() const { return (*this)(0); } const GridVolumeType y() const { return (*this)(1); } const GridVolumeType z() const { return (*this)(2); } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()) + " " + std::to_string(z()); return s; } SpacingVectorType3D& operator=(const SpacingVectorType3D& wc) { (*this)(0) = wc.x(); (*this)(1) = wc.y(); (*this)(2) = wc.z(); return (*this); } SpacingVectorType3D& operator=(const WorldCoordinate3D& wc) { (*this)(0) = GridVolumeType(wc.x()); (*this)(1) = GridVolumeType(wc.y()); (*this)(2) = GridVolumeType(wc.z()); return (*this); } SpacingVectorType3D& operator=(const boost::numeric::ublas::vector wc) { (*this)(0) = wc(0); (*this)(1) = wc(1); (*this)(2) = wc(2); return (*this); } friend bool operator==(const SpacingVectorType3D& wc1, const SpacingVectorType3D& wc2) { if (wc1.size() != wc2.size()) { return false; } for (size_t i = 0; i < wc1.size(); i++) { if (wc1(i) != wc2(i)) { return false; } } return true; } bool equalsAlmost(const SpacingVectorType3D& another, double errorConstantSV = 1e-5) const { if ((*this).size() != another.size()) { return false; } double dist = norm_2(*this - another); return dist < errorConstantSV; } friend std::ostream& operator<<(std::ostream& s, const SpacingVectorType3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class OrientationMatrix @brief Used to store image orientation information */ class OrientationMatrix : public boost::numeric::ublas::matrix { public: /*! The default constructor generates a 3x3 unit matrix */ OrientationMatrix() : boost::numeric::ublas::matrix(3, 3, 0) { for (std::size_t m = 0; m < (*this).size1(); m++) { (*this)(m, m) = 1; } } OrientationMatrix(const WorldCoordinate value) : boost::numeric::ublas::matrix(3, 3, value) {} bool equalsAlmost(const OrientationMatrix& anOrientationMatrix, double errorConstantOM=1e-5) const { if (anOrientationMatrix.size1() == (*this).size1()) { if (anOrientationMatrix.size2() == (*this).size2()) { for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { if ((std::abs((*this)(m, n) - anOrientationMatrix(m, n)) > errorConstantOM)) { return false; } } }// end element comparison } else { return false; } } else { return false; } return true; } friend bool operator==(const OrientationMatrix& om1, const OrientationMatrix& om2) { return om1.equalsAlmost(om2, 0.0); } friend std::ostream& operator<<(std::ostream& s, const OrientationMatrix& anOrientationMatrix) { s << "[ "; for (std::size_t m = 0; m < anOrientationMatrix.size1(); m++) { s << "[ "; for (std::size_t n = 0; n < anOrientationMatrix.size2(); n++) { if (n == 0) { s << anOrientationMatrix(m, n); } else { s << ", " << anOrientationMatrix(m, n); } } s << " ]"; } s << " ]"; return s; } }; /*! base for 2D and 3D VoxelIndex; Therefore required beside VoxelGridID */ using GridIndexType = unsigned int; /*! @class VoxelGridIndex3D @brief 3D voxel grid index in a discret geometry (matrix/image). @details analogous to DICOM where ImagePositionPatient gives the position of the center of the first coordinate (0/0/0) */ class VoxelGridIndex3D: public boost::numeric::ublas::vector { public: VoxelGridIndex3D() : boost::numeric::ublas::vector(3,0) {} VoxelGridIndex3D(const GridIndexType value) : boost::numeric::ublas::vector(3, value) {} VoxelGridIndex3D(const GridIndexType xValue, const GridIndexType yValue, const GridIndexType zValue) : boost::numeric::ublas::vector(3, xValue) { (*this)(1) = yValue; (*this)(2) = zValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const GridIndexType z() const { return (*this)(2); } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()) + " " + std::to_string(z()); return s; } VoxelGridIndex3D& operator=(const UnsignedIndex3D& ui) { (*this)(0) = ui(0); (*this)(1) = ui(1); (*this)(2) = ui(2); return (*this); } friend bool operator==(const VoxelGridIndex3D& gi1, const VoxelGridIndex3D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex3D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << ", " << aVector(2) << " ]"; return s; } }; /*! @class VoxelGridIndex3D @brief 2D voxel grid index. */ class VoxelGridIndex2D: public boost::numeric::ublas::vector { public: VoxelGridIndex2D() : boost::numeric::ublas::vector(2,0) {} VoxelGridIndex2D(const GridIndexType value) : boost::numeric::ublas::vector(2, value) {} VoxelGridIndex2D(const GridIndexType xValue, const GridIndexType yValue) : boost::numeric::ublas::vector(2, xValue) { (*this)(1) = yValue; } const GridIndexType x() const { return (*this)(0); } const GridIndexType y() const { return (*this)(1); } const std::string toString() const { std::string s = std::to_string(x()) + " " + std::to_string(y()); return s; } friend bool operator==(const VoxelGridIndex2D& gi1, const VoxelGridIndex2D& gi2) { if (gi1.size() != gi2.size()) { return false; } for (size_t i = 0; i < gi1.size(); i++) { if (gi1(i) != gi2(i)) { return false; } } return true; } friend std::ostream& operator<<(std::ostream& s, const VoxelGridIndex2D& aVector) { s << "[ " << aVector(0) << ", " << aVector(1) << " ]"; return s; } }; using GridSizeType = long; using VoxelGridID = int; //starts from 0 and is continuously counting all positions on the grid using VoxelGridDimensionType = unsigned int; typedef double FractionType, DVHVoxelNumber; typedef double DoseCalcType, DoseTypeGy, GenericValueType, DoseVoxelVolumeType, VolumeType, GridVolumeType, PercentType, VoxelNumberType, BEDType, LQEDType; using IDType = std::string; using StructureLabel = std::string; struct DVHRole { enum Type { TargetVolume = 1, HealthyTissue = 2, WholeVolume = 4, UserDefined = 128 } Type; }; struct DVHType { enum Type { Differential = 1, Cumulative = 2 } Type; }; using FileNameType = std::string; using PolygonType = std::vector; using PolygonSequenceType = std::vector; using IndexValueType = double; using DoseStatisticType = double; using DICOMRTFileNameString = std::string; using Uint16 = unsigned short; typedef std::string XMLString, StatisticsString; }//end: namespace rttb #endif diff --git a/testing/core/BaseTypeTest.cpp b/testing/core/BaseTypeTest.cpp index 4c180ed..911b582 100644 --- a/testing/core/BaseTypeTest.cpp +++ b/testing/core/BaseTypeTest.cpp @@ -1,274 +1,277 @@ // ----------------------------------------------------------------------- // RTToolbox - DKFZ radiotherapy quantitative evaluation library // // Copyright (c) German Cancer Research Center (DKFZ), // Software development for Integrated Diagnostics and Therapy (SIDT). // ALL RIGHTS RESERVED. // See rttbCopyright.txt or // http://www.dkfz.de/en/sidt/projects/rttb/copyright.html // // 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. // //------------------------------------------------------------------------ /*! // @file // @version $Revision$ (last changed revision) // @date $Date$ (last change date) // @author $Author$ (last changed by) */ #include "litCheckMacros.h" #include "rttbBaseType.h" namespace rttb { namespace testing { /*! @brief BaseTypeTests - tests the API for the classes in baseType 1) UnsignedIndex3D 2) WorldCoordinate3D 3) SpacingVectorType3D 4) OrientationMatrix 5) VoxelGridIndex3D 6) VoxelGridIndex2D */ int BaseTypeTest(int argc, char* argv[]) { PREPARE_DEFAULT_TEST_REPORTING; //1) UnsignedIndex3D CHECK_NO_THROW(UnsignedIndex3D ui); UnsignedIndex3D emptyUnsignedIndex3D; CHECK_EQUAL(emptyUnsignedIndex3D.x(), 0); CHECK_EQUAL(emptyUnsignedIndex3D.y(), 0); CHECK_EQUAL(emptyUnsignedIndex3D.z(), 0); CHECK_NO_THROW(UnsignedIndex3D ui(5)); UnsignedIndex3D sameValueUnsignedIndex(5); CHECK_EQUAL(sameValueUnsignedIndex.x(), 5); CHECK_EQUAL(sameValueUnsignedIndex.y(), 5); CHECK_EQUAL(sameValueUnsignedIndex.z(), 5); CHECK_NO_THROW(UnsignedIndex3D ui(5, 8, 42)); UnsignedIndex3D differentValueUnsignedIndex(5, 8, 42); CHECK_EQUAL(differentValueUnsignedIndex.x(), 5); CHECK_EQUAL(differentValueUnsignedIndex.y(), 8); CHECK_EQUAL(differentValueUnsignedIndex.z(), 42); UnsignedIndex3D threeDimensionalUnsignedIndexSame(5, 8, 42); UnsignedIndex3D threeDimensionalUnsignedIndexDifferent(1, 2, 3); CHECK(differentValueUnsignedIndex == threeDimensionalUnsignedIndexSame); CHECK_EQUAL(differentValueUnsignedIndex == threeDimensionalUnsignedIndexDifferent, false); CHECK_EQUAL(differentValueUnsignedIndex == sameValueUnsignedIndex, false); CHECK_EQUAL(emptyUnsignedIndex3D == sameValueUnsignedIndex, false); //2) WorldCoordinate3D CHECK_NO_THROW(WorldCoordinate3D wc); WorldCoordinate3D emptyWC3D; CHECK_EQUAL(emptyWC3D.x(), 0); CHECK_EQUAL(emptyWC3D.y(), 0); CHECK_EQUAL(emptyWC3D.z(), 0); CHECK_NO_THROW(WorldCoordinate3D wc(6.5)); WorldCoordinate3D sameValueWC3D(6.5); CHECK_EQUAL(sameValueWC3D.x(), 6.5); CHECK_EQUAL(sameValueWC3D.y(), 6.5); CHECK_EQUAL(sameValueWC3D.z(), 6.5); CHECK_NO_THROW(WorldCoordinate3D(5.8, 0.1, -2.7)); WorldCoordinate3D differentValueWC3D(5.8, 0.1, -2.7); CHECK_EQUAL(differentValueWC3D.x(), 5.8); CHECK_EQUAL(differentValueWC3D.y(), 0.1); CHECK_EQUAL(differentValueWC3D.z(), -2.7); CHECK_EQUAL(differentValueWC3D.toString(), "5.800000 0.100000 -2.700000"); WorldCoordinate3D differentValueWC3Dsecond(1.5, -3.9, 0.7); WorldCoordinate3D resultWC3DCrossTrue(-10.46, -8.11, -22.77); CHECK_NO_THROW(differentValueWC3D.cross(differentValueWC3Dsecond)); auto resultWC3DCrossComputed = differentValueWC3D.cross(differentValueWC3Dsecond); CHECK_CLOSE(resultWC3DCrossComputed.x(), resultWC3DCrossTrue.x(), errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.y(), resultWC3DCrossTrue.y(), errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.z(), resultWC3DCrossTrue.z(), errorConstant); CHECK_NO_THROW(differentValueWC3Dsecond.cross(differentValueWC3D)); auto resultWC3DCrossComputedOrder = differentValueWC3Dsecond.cross(differentValueWC3D); CHECK_CLOSE(resultWC3DCrossComputed.x(), resultWC3DCrossComputedOrder.x()*-1, errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.y(), resultWC3DCrossComputedOrder.y()*-1, errorConstant); CHECK_CLOSE(resultWC3DCrossComputed.z(), resultWC3DCrossComputedOrder.z()*-1, errorConstant); differentValueWC3D = differentValueWC3Dsecond; CHECK_EQUAL(differentValueWC3D.x(), 1.5); CHECK_EQUAL(differentValueWC3D.y(), -3.9); CHECK_EQUAL(differentValueWC3D.z(), 0.7); boost::numeric::ublas::vector wcUblas(3, 4.5); differentValueWC3D = wcUblas; CHECK_EQUAL(differentValueWC3D.x(), 4.5); CHECK_EQUAL(differentValueWC3D.y(), 4.5); CHECK_EQUAL(differentValueWC3D.z(), 4.5); WorldCoordinate3D WCresultMinus; CHECK_NO_THROW(WCresultMinus = differentValueWC3D- differentValueWC3Dsecond); CHECK_EQUAL(WCresultMinus.x(), differentValueWC3D.x()- differentValueWC3Dsecond.x()); CHECK_EQUAL(WCresultMinus.y(), differentValueWC3D.y() - differentValueWC3Dsecond.y()); CHECK_EQUAL(WCresultMinus.z(), differentValueWC3D.z() - differentValueWC3Dsecond.z()); WorldCoordinate3D WCresultPlus; CHECK_NO_THROW(WCresultPlus = differentValueWC3D + differentValueWC3Dsecond); CHECK_EQUAL(WCresultPlus.x(), differentValueWC3D.x() + differentValueWC3Dsecond.x()); CHECK_EQUAL(WCresultPlus.y(), differentValueWC3D.y() + differentValueWC3Dsecond.y()); CHECK_EQUAL(WCresultPlus.z(), differentValueWC3D.z() + differentValueWC3Dsecond.z()); WorldCoordinate3D sameAsWcUblas(4.5); CHECK_EQUAL(resultWC3DCrossTrue== differentValueWC3Dsecond, false); CHECK_EQUAL(differentValueWC3D == sameAsWcUblas, true); WorldCoordinate3D sameAsWcUblasAlmost(4.5+1e-6, 4.5-1e-6, 4.5+2e-7); CHECK_EQUAL(sameAsWcUblas.equalsAlmost(sameAsWcUblasAlmost), true); CHECK_EQUAL(sameAsWcUblas.equalsAlmost(resultWC3DCrossComputedOrder), false); //3) SpacingVectorType CHECK_NO_THROW(SpacingVectorType3D svt); SpacingVectorType3D emptySvt; CHECK_EQUAL(emptySvt.x(), 0); CHECK_EQUAL(emptySvt.y(), 0); CHECK_EQUAL(emptySvt.z(), 0); CHECK_NO_THROW(SpacingVectorType3D svt(1.5)); + CHECK_THROW(SpacingVectorType3D svt(-1.5)); SpacingVectorType3D sameValueSvt(1.5); CHECK_EQUAL(sameValueSvt.x(), 1.5); CHECK_EQUAL(sameValueSvt.y(), 1.5); CHECK_EQUAL(sameValueSvt.z(), 1.5); CHECK_NO_THROW(SpacingVectorType3D svt(1.5, 1.5, 0.5)); + CHECK_THROW(SpacingVectorType3D svt(1.5, -1.5, 0.5)); + CHECK_THROW(SpacingVectorType3D svt(-1.5, -1.5, -0.5)); SpacingVectorType3D differentValuesSvt(1.5, 1.5, 0.5); CHECK_EQUAL(differentValuesSvt.x(), 1.5); CHECK_EQUAL(differentValuesSvt.y(), 1.5); CHECK_EQUAL(differentValuesSvt.z(), 0.5); SpacingVectorType3D differentValuesSvtChanged(0.5, 0.5, 1.5); CHECK_NO_THROW(SpacingVectorType3D svt(differentValuesSvtChanged)); SpacingVectorType3D svtNew(differentValuesSvtChanged); CHECK_EQUAL(svtNew.x(), 0.5); CHECK_EQUAL(svtNew.y(), 0.5); CHECK_EQUAL(svtNew.z(), 1.5); CHECK_NO_THROW(svtNew = differentValuesSvt); CHECK_EQUAL(svtNew.x(), 1.5); CHECK_EQUAL(svtNew.y(), 1.5); CHECK_EQUAL(svtNew.z(), 0.5); CHECK_NO_THROW(svtNew = differentValueWC3D); CHECK_EQUAL(svtNew.x(), 4.5); CHECK_EQUAL(svtNew.y(), 4.5); CHECK_EQUAL(svtNew.z(), 4.5); boost::numeric::ublas::vector ublasVector(3, 0.5); CHECK_NO_THROW(svtNew = ublasVector); CHECK_EQUAL(svtNew.x(), 0.5); CHECK_EQUAL(svtNew.y(), 0.5); CHECK_EQUAL(svtNew.z(), 0.5); SpacingVectorType3D sameAsUblasVector(0.5); CHECK_EQUAL(svtNew== differentValuesSvtChanged, false); CHECK_EQUAL(svtNew == sameAsUblasVector, true); SpacingVectorType3D almostSameAsUblasVector(0.5+1e-6, 0.5-1e-6,0.5+2e-7); CHECK(svtNew.equalsAlmost(almostSameAsUblasVector)); CHECK_EQUAL(differentValuesSvtChanged.toString(), "0.500000 0.500000 1.500000"); //4) OrientationMatrix CHECK_NO_THROW(OrientationMatrix om); OrientationMatrix om; CHECK_EQUAL(om(0, 0), 1.0); CHECK_EQUAL(om(1, 1), 1.0); CHECK_EQUAL(om(2, 2), 1.0); CHECK_EQUAL(om(0, 1), 0.0); CHECK_EQUAL(om(0, 2), 0.0); CHECK_EQUAL(om(1, 0), 0.0); CHECK_EQUAL(om(1, 2), 0.0); CHECK_EQUAL(om(2, 0), 0.0); CHECK_EQUAL(om(2, 1), 0.0); CHECK_NO_THROW(OrientationMatrix omValue(0.1)); OrientationMatrix omValue(0.1); for (unsigned int i = 0; i < 3; i++) { for (unsigned int j = 0; j < 3; j++) { CHECK_EQUAL(omValue(i, j), 0.1); } } OrientationMatrix omValueAlmost(0.1+1e-6); CHECK_EQUAL(omValue.equalsAlmost(omValueAlmost), true); CHECK_EQUAL(omValue.equalsAlmost(om), false); OrientationMatrix omSame; CHECK_EQUAL(om == omSame, true); CHECK_EQUAL(omValue == omValueAlmost, false); //5) VoxelGridIndex3D CHECK_NO_THROW(VoxelGridIndex3D vgi); VoxelGridIndex3D vgi; CHECK_EQUAL(vgi.x(), 0); CHECK_EQUAL(vgi.y(), 0); CHECK_EQUAL(vgi.z(), 0); CHECK_NO_THROW(VoxelGridIndex3D vgiValue(2)); VoxelGridIndex3D vgiValue(2); CHECK_EQUAL(vgiValue.x(), 2); CHECK_EQUAL(vgiValue.y(), 2); CHECK_EQUAL(vgiValue.z(), 2); CHECK_NO_THROW(VoxelGridIndex3D vgiValueDifferent(2,3,5)); VoxelGridIndex3D vgiValueDifferent(2,3,5); CHECK_EQUAL(vgiValueDifferent.x(), 2); CHECK_EQUAL(vgiValueDifferent.y(), 3); CHECK_EQUAL(vgiValueDifferent.z(), 5); CHECK_EQUAL(vgiValueDifferent.toString(), "2 3 5"); CHECK_NO_THROW(vgiValueDifferent = threeDimensionalUnsignedIndexSame); CHECK_EQUAL(vgiValueDifferent.x(), 5); CHECK_EQUAL(vgiValueDifferent.y(), 8); CHECK_EQUAL(vgiValueDifferent.z(), 42); VoxelGridIndex3D vgiValueDifferentSame(5, 8, 42); CHECK_EQUAL(vgi==vgiValue, false); CHECK_EQUAL(vgiValueDifferentSame == vgiValueDifferent, true); //6) VoxelGridIndex2D CHECK_NO_THROW(VoxelGridIndex2D vgi); VoxelGridIndex2D vgi2D; CHECK_EQUAL(vgi2D.x(), 0); CHECK_EQUAL(vgi2D.y(), 0); CHECK_NO_THROW(VoxelGridIndex2D vgi2DValue(2)); VoxelGridIndex2D vgi2DValue(2); CHECK_EQUAL(vgi2DValue.x(), 2); CHECK_EQUAL(vgi2DValue.y(), 2); CHECK_NO_THROW(VoxelGridIndex2D vgi2DValueDifferent(2, 3)); VoxelGridIndex2D vgi2DValueDifferent(2, 3); CHECK_EQUAL(vgi2DValueDifferent.x(), 2); CHECK_EQUAL(vgi2DValueDifferent.y(), 3); CHECK_EQUAL(vgi2DValueDifferent.toString(), "2 3"); VoxelGridIndex2D vgi2DValueDifferentSame(2, 3); CHECK_EQUAL(vgi2D == vgi2DValueDifferent, false); CHECK_EQUAL(vgi2DValueDifferent == vgi2DValueDifferentSame, true); RETURN_AND_REPORT_TEST_SUCCESS; } }//testing }//rttb \ No newline at end of file