diff --git a/Core/Code/DataManagement/mitkBaseGeometry.cpp b/Core/Code/DataManagement/mitkBaseGeometry.cpp index 13164835ed..58ad8440a6 100644 --- a/Core/Code/DataManagement/mitkBaseGeometry.cpp +++ b/Core/Code/DataManagement/mitkBaseGeometry.cpp @@ -1,1088 +1,1089 @@ /*=================================================================== 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 #include "mitkBaseGeometry.h" #include "mitkVector.h" #include "mitkMatrixConvert.h" #include #include #include "mitkRotationOperation.h" #include "mitkRestorePlanePositionOperation.h" #include "mitkApplyTransformMatrixOperation.h" #include "mitkPointOperation.h" #include "mitkInteractionConst.h" #include "mitkModifiedLock.h" mitk::BaseGeometry::BaseGeometry(): Superclass(), mitk::OperationActor(), m_FrameOfReferenceID(0), m_IndexToWorldTransformLastModified(0), m_ImageGeometry(false), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false) { m_VtkMatrix = vtkMatrix4x4::New(); m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New(); m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix); Initialize(); } mitk::BaseGeometry::BaseGeometry(const BaseGeometry& other): Superclass(), mitk::OperationActor(), //m_TimeBounds(other.m_TimeBounds), m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified), m_Origin(other.m_Origin), m_ImageGeometry(other.m_ImageGeometry), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false) { m_VtkMatrix = vtkMatrix4x4::New(); m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New(); m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix); other.InitializeGeometry(this); } mitk::BaseGeometry::~BaseGeometry() { m_VtkMatrix->Delete(); m_VtkIndexToWorldTransform->Delete(); } const mitk::Point3D& mitk::BaseGeometry::GetOrigin() const { return m_Origin; } void mitk::BaseGeometry::SetOrigin(const Point3D & origin) { mitk::ModifiedLock lock(this); if(origin!=GetOrigin()) { m_Origin = origin; m_IndexToWorldTransform->SetOffset(m_Origin.GetVectorFromOrigin()); Modified(); TransferItkToVtkTransform(); } } void mitk::BaseGeometry::TransferItkToVtkTransform() { mitk::ModifiedLock lock(this); // copy m_IndexToWorldTransform into m_VtkIndexToWorldTransform TransferItkTransformToVtkMatrix(m_IndexToWorldTransform.GetPointer(), m_VtkMatrix); m_VtkIndexToWorldTransform->Modified(); } static void CopySpacingFromTransform(mitk::AffineTransform3D* transform, mitk::Vector3D& spacing) { mitk::AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix; vnlmatrix = transform->GetMatrix().GetVnlMatrix(); spacing[0]=vnlmatrix.get_column(0).magnitude(); spacing[1]=vnlmatrix.get_column(1).magnitude(); spacing[2]=vnlmatrix.get_column(2).magnitude(); } void mitk::BaseGeometry::Initialize() { float b[6] = {0,1,0,1,0,1}; SetFloatBounds(b); if(m_IndexToWorldTransform.IsNull()) m_IndexToWorldTransform = TransformType::New(); else m_IndexToWorldTransform->SetIdentity(); CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing); vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin); m_VtkMatrix->Identity(); //m_TimeBounds[0]=ScalarTypeNumericTraits::NonpositiveMin(); m_TimeBounds[1]=ScalarTypeNumericTraits::max(); m_FrameOfReferenceID = 0; m_ImageGeometry = false; this->PostInitialize(); } void mitk::BaseGeometry::PostInitializeGeometry(BaseGeometry * newGeometry) const { newGeometry->m_ImageGeometry = m_ImageGeometry; } void mitk::BaseGeometry::SetFloatBounds(const float bounds[6]) { mitk::BoundingBox::BoundsArrayType b; const float *input = bounds; int i=0; for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6 ;++i) *it++ = (mitk::ScalarType)*input++; SetBounds(b); } void mitk::BaseGeometry::SetFloatBounds(const double bounds[6]) { mitk::BoundingBox::BoundsArrayType b; const double *input = bounds; int i=0; for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6 ;++i) *it++ = (mitk::ScalarType)*input++; SetBounds(b); } /** Initialize the geometry */ void mitk::BaseGeometry::InitializeGeometry(BaseGeometry* newGeometry) const { newGeometry->SetBounds(m_BoundingBox->GetBounds()); // we have to create a new transform!! //newGeometry->SetTimeBounds(m_TimeBounds); newGeometry->SetFrameOfReferenceID(GetFrameOfReferenceID()); if(m_IndexToWorldTransform) { TransformType::Pointer indexToWorldTransform = m_IndexToWorldTransform->Clone(); newGeometry->SetIndexToWorldTransform(indexToWorldTransform); } this->PostInitializeGeometry(newGeometry); } void mitk::BaseGeometry::PostInitialize() { } /** Set the bounds */ void mitk::BaseGeometry::SetBounds(const BoundsArrayType& bounds) { mitk::ModifiedLock lock(this); PreSetBounds(bounds); m_BoundingBox = BoundingBoxType::New(); BoundingBoxType::PointsContainer::Pointer pointscontainer = BoundingBoxType::PointsContainer::New(); BoundingBoxType::PointType p; BoundingBoxType::PointIdentifier pointid; for(pointid=0; pointid<2;++pointid) { unsigned int i; for(i=0; iInsertElement(pointid, p); } m_BoundingBox->SetPoints(pointscontainer); m_BoundingBox->ComputeBoundingBox(); this->Modified(); } void mitk::BaseGeometry::PreSetBounds(const BoundsArrayType& /*bounds*/){}; void mitk::BaseGeometry::SetIndexToWorldTransform(mitk::AffineTransform3D* transform) { mitk::ModifiedLock lock(this); PreSetIndexToWorldTransform(transform); m_IndexToWorldTransform = transform; CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing); vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin); TransferItkToVtkTransform(); Modified(); PostSetIndexToWorldTransform(transform); } void mitk::BaseGeometry::PreSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} void mitk::BaseGeometry::PostSetIndexToWorldTransform(mitk::AffineTransform3D* /*transform*/) {} const mitk::BaseGeometry::BoundsArrayType mitk::BaseGeometry::GetBounds() const { assert(m_BoundingBox.IsNotNull()); return m_BoundingBox->GetBounds(); } bool mitk::BaseGeometry::IsValid() const { return true; } void mitk::BaseGeometry::SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing ) { PreSetSpacing(aSpacing); _SetSpacing(aSpacing, enforceSetSpacing); } void mitk::BaseGeometry::PreSetSpacing(const mitk::Vector3D& /*aSpacing*/) {} void mitk::BaseGeometry::_SetSpacing(const mitk::Vector3D& aSpacing, bool enforceSetSpacing){ if(mitk::Equal(m_Spacing, aSpacing) == false || enforceSetSpacing) { assert(aSpacing[0]>0 && aSpacing[1]>0 && aSpacing[2]>0); m_Spacing = aSpacing; AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix; vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix(); mitk::VnlVector col; col = vnlmatrix.get_column(0); col.normalize(); col*=aSpacing[0]; vnlmatrix.set_column(0, col); col = vnlmatrix.get_column(1); col.normalize(); col*=aSpacing[1]; vnlmatrix.set_column(1, col); col = vnlmatrix.get_column(2); col.normalize(); col*=aSpacing[2]; vnlmatrix.set_column(2, col); Matrix3D matrix; matrix = vnlmatrix; AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetMatrix(matrix); transform->SetOffset(m_IndexToWorldTransform->GetOffset()); SetIndexToWorldTransform(transform.GetPointer()); } } mitk::Vector3D mitk::BaseGeometry::GetAxisVector(unsigned int direction) const { Vector3D frontToBack; frontToBack.SetVnlVector(m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction)); frontToBack *= GetExtent(direction); return frontToBack; } mitk::ScalarType mitk::BaseGeometry::GetExtent(unsigned int direction) const { assert(m_BoundingBox.IsNotNull()); if (direction>=m_NDimensions) mitkThrow() << "Direction is too big. This geometry is for 3D Data"; BoundsArrayType bounds = m_BoundingBox->GetBounds(); return bounds[direction*2+1]-bounds[direction*2]; } bool mitk::BaseGeometry::Is2DConvertable() { bool isConvertableWithoutLoss = true; do { if (this->GetSpacing()[2] != 1) { isConvertableWithoutLoss = false; break; } if (this->GetOrigin()[2] != 0) { isConvertableWithoutLoss = false; break; } mitk::Vector3D col0, col1, col2; col0.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0)); col1.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1)); col2.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)); if ((col0[2] != 0) || (col1[2] != 0) || (col2[0] != 0) || (col2[1] != 0) || (col2[2] != 1)) { isConvertableWithoutLoss = false; break; } } while (0); return isConvertableWithoutLoss; } mitk::Point3D mitk::BaseGeometry::GetCenter() const { assert(m_BoundingBox.IsNotNull()); return m_IndexToWorldTransform->TransformPoint(m_BoundingBox->GetCenter()); } double mitk::BaseGeometry::GetDiagonalLength2() const { Vector3D diagonalvector = GetCornerPoint()-GetCornerPoint(false, false, false); return diagonalvector.GetSquaredNorm(); } //##Documentation //## @brief Get the length of the diagonal of the bounding-box in mm //## double mitk::BaseGeometry::GetDiagonalLength() const { return sqrt(GetDiagonalLength2()); } mitk::Point3D mitk::BaseGeometry::GetCornerPoint(int id) const { assert(id >= 0); assert(this->IsBoundingBoxNull()==false); BoundingBox::BoundsArrayType bounds = this->GetBoundingBox()->GetBounds(); Point3D cornerpoint; switch(id) { case 0: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[4]); break; case 1: FillVector3D(cornerpoint, bounds[0],bounds[2],bounds[5]); break; case 2: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[4]); break; case 3: FillVector3D(cornerpoint, bounds[0],bounds[3],bounds[5]); break; case 4: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[4]); break; case 5: FillVector3D(cornerpoint, bounds[1],bounds[2],bounds[5]); break; case 6: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[4]); break; case 7: FillVector3D(cornerpoint, bounds[1],bounds[3],bounds[5]); break; default: { itkExceptionMacro(<<"A cube only has 8 corners. These are labeled 0-7."); } } if(m_ImageGeometry) { // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the // bounding box. The bounding box itself is no image, so it is corner-based FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5); } return this->GetIndexToWorldTransform()->TransformPoint(cornerpoint); } mitk::Point3D mitk::BaseGeometry::GetCornerPoint(bool xFront, bool yFront, bool zFront) const { assert(this->IsBoundingBoxNull()==false); BoundingBox::BoundsArrayType bounds = this->GetBoundingBox()->GetBounds(); Point3D cornerpoint; cornerpoint[0] = (xFront ? bounds[0] : bounds[1]); cornerpoint[1] = (yFront ? bounds[2] : bounds[3]); cornerpoint[2] = (zFront ? bounds[4] : bounds[5]); if(m_ImageGeometry) { // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the // bounding box. The bounding box itself is no image, so it is corner-based FillVector3D(cornerpoint, cornerpoint[0]-0.5, cornerpoint[1]-0.5, cornerpoint[2]-0.5); } return this->GetIndexToWorldTransform()->TransformPoint(cornerpoint); } mitk::ScalarType mitk::BaseGeometry::GetExtentInMM(int direction) const { return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction).magnitude()*GetExtent(direction); } void mitk::BaseGeometry::SetExtentInMM(int direction, ScalarType extentInMM) { mitk::ModifiedLock lock(this); ScalarType len = GetExtentInMM(direction); if(fabs(len - extentInMM)>=mitk::eps) { AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix; vnlmatrix = m_IndexToWorldTransform->GetMatrix().GetVnlMatrix(); if(len>extentInMM) vnlmatrix.set_column(direction, vnlmatrix.get_column(direction)/len*extentInMM); else vnlmatrix.set_column(direction, vnlmatrix.get_column(direction)*extentInMM/len); Matrix3D matrix; matrix = vnlmatrix; m_IndexToWorldTransform->SetMatrix(matrix); TransferItkToVtkTransform(); Modified(); } PostSetExtentInMM(direction,extentInMM); } void mitk::BaseGeometry::PostSetExtentInMM(int /*direction*/, ScalarType /*extentInMM*/){}; bool mitk::BaseGeometry::IsInside(const mitk::Point3D& p) const { mitk::Point3D index; WorldToIndex(p, index); return IsIndexInside(index); } bool mitk::BaseGeometry::IsIndexInside(const mitk::Point3D& index) const { bool inside = false; //if it is an image geometry, we need to convert the index to discrete values //this is done by applying the rounding function also used in WorldToIndex (see line 323) if (m_ImageGeometry) { mitk::Point3D discretIndex; discretIndex[0]=itk::Math::RoundHalfIntegerUp( index[0] ); discretIndex[1]=itk::Math::RoundHalfIntegerUp( index[1] ); discretIndex[2]=itk::Math::RoundHalfIntegerUp( index[2] ); inside = this->GetBoundingBox()->IsInside(discretIndex); //we have to check if the index is at the upper border of each dimension, // because the boundingbox is not centerbased if (inside) { const BoundingBox::BoundsArrayType& bounds = this->GetBoundingBox()->GetBounds(); if((discretIndex[0] == bounds[1]) || (discretIndex[1] == bounds[3]) || (discretIndex[2] == bounds[5])) inside = false; } } else inside = this->GetBoundingBox()->IsInside(index); return inside; } void mitk::BaseGeometry::WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const { BackTransform(pt_mm, pt_units); } void mitk::BaseGeometry::WorldToIndex( const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const { BackTransform( vec_mm, vec_units); } void mitk::BaseGeometry::BackTransform(const mitk::Vector3D& in, mitk::Vector3D& out) const { // Get WorldToIndex transform if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime()) { m_InvertedTransform = TransformType::New(); if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() )) { itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." ); } m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime(); } // Check for valid matrix inversion const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix(); if(inverse.GetVnlMatrix().has_nans()) { itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl << inverse ); } // Transform vector for (unsigned int i = 0; i < 3; i++) { out[i] = 0.0; for (unsigned int j = 0; j < 3; j++) { out[i] += inverse[i][j]*in[j]; } } } void mitk::BaseGeometry::BackTransform(const mitk::Point3D &in, mitk::Point3D& out) const { ScalarType temp[3]; unsigned int i, j; const TransformType::OffsetType& offset = m_IndexToWorldTransform->GetOffset(); // Remove offset for (j = 0; j < 3; j++) { temp[j] = in[j] - offset[j]; } // Get WorldToIndex transform if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime()) { m_InvertedTransform = TransformType::New(); if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() )) { itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." ); } m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime(); } // Check for valid matrix inversion const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix(); if(inverse.GetVnlMatrix().has_nans()) { itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl << inverse ); } // Transform point for (i = 0; i < 3; i++) { out[i] = 0.0; for (j = 0; j < 3; j++) { out[i] += inverse[i][j]*temp[j]; } } } mitk::VnlVector mitk::BaseGeometry::GetOriginVnl() const { return const_cast(this)->m_Origin.GetVnlVector(); } vtkLinearTransform* mitk::BaseGeometry::GetVtkTransform() const { return (vtkLinearTransform*)m_VtkIndexToWorldTransform; } void mitk::BaseGeometry::SetIdentity() { mitk::ModifiedLock lock(this); m_IndexToWorldTransform->SetIdentity(); m_Origin.Fill(0); CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing); Modified(); TransferItkToVtkTransform(); } void mitk::BaseGeometry::TransferVtkToItkTransform() { TransferVtkMatrixToItkTransform(m_VtkMatrix, m_IndexToWorldTransform.GetPointer()); CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing); vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin); TransferItkToVtkTransform(); } void mitk::BaseGeometry::Compose( const mitk::BaseGeometry::TransformType * other, bool pre ) { mitk::ModifiedLock lock(this); m_IndexToWorldTransform->Compose(other, pre); CopySpacingFromTransform(m_IndexToWorldTransform, m_Spacing); vtk2itk(m_IndexToWorldTransform->GetOffset(), m_Origin); Modified(); TransferItkToVtkTransform(); } void mitk::BaseGeometry::Compose( const vtkMatrix4x4 * vtkmatrix, bool pre ) { mitk::BaseGeometry::TransformType::Pointer itkTransform = mitk::BaseGeometry::TransformType::New(); TransferVtkMatrixToItkTransform(vtkmatrix, itkTransform.GetPointer()); Compose(itkTransform, pre); } void mitk::BaseGeometry::Translate(const Vector3D & vector) { if((vector[0] != 0) || (vector[1] != 0) || (vector[2] != 0)) { this->SetOrigin(m_Origin + vector); } } void mitk::BaseGeometry::IndexToWorld(const mitk::Point3D &pt_units, mitk::Point3D &pt_mm) const { pt_mm = m_IndexToWorldTransform->TransformPoint(pt_units); } void mitk::BaseGeometry::IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const { vec_mm = m_IndexToWorldTransform->TransformVector(vec_units); } #include void mitk::BaseGeometry::ExecuteOperation(Operation* operation) { mitk::ModifiedLock lock(this); vtkTransform *vtktransform = vtkTransform::New(); vtktransform->SetMatrix(m_VtkMatrix); switch (operation->GetOperationType()) { case OpNOTHING: break; case OpMOVE: { mitk::PointOperation *pointOp = dynamic_cast(operation); if (pointOp == NULL) { //mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000); return; } mitk::Point3D newPos = pointOp->GetPoint(); ScalarType data[3]; vtktransform->GetPosition(data); vtktransform->PostMultiply(); vtktransform->Translate(newPos[0], newPos[1], newPos[2]); vtktransform->PreMultiply(); break; } case OpSCALE: { mitk::PointOperation *pointOp = dynamic_cast(operation); if (pointOp == NULL) { //mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000); return; } mitk::Point3D newScale = pointOp->GetPoint(); ScalarType data[3]; /* calculate new scale: newscale = oldscale * (oldscale + scaletoadd)/oldscale */ data[0] = 1 + (newScale[0] / GetMatrixColumn(0).magnitude()); data[1] = 1 + (newScale[1] / GetMatrixColumn(1).magnitude()); data[2] = 1 + (newScale[2] / GetMatrixColumn(2).magnitude()); mitk::Point3D center = const_cast(m_BoundingBox.GetPointer())->GetCenter(); ScalarType pos[3]; vtktransform->GetPosition(pos); vtktransform->PostMultiply(); vtktransform->Translate(-pos[0], -pos[1], -pos[2]); vtktransform->Translate(-center[0], -center[1], -center[2]); vtktransform->PreMultiply(); vtktransform->Scale(data[0], data[1], data[2]); vtktransform->PostMultiply(); vtktransform->Translate(+center[0], +center[1], +center[2]); vtktransform->Translate(pos[0], pos[1], pos[2]); vtktransform->PreMultiply(); break; } case OpROTATE: { mitk::RotationOperation *rotateOp = dynamic_cast(operation); if (rotateOp == NULL) { //mitk::StatusBar::GetInstance()->DisplayText("received wrong type of operation!See mitkAffineInteractor.cpp", 10000); return; } Vector3D rotationVector = rotateOp->GetVectorOfRotation(); Point3D center = rotateOp->GetCenterOfRotation(); ScalarType angle = rotateOp->GetAngleOfRotation(); vtktransform->PostMultiply(); vtktransform->Translate(-center[0], -center[1], -center[2]); vtktransform->RotateWXYZ(angle, rotationVector[0], rotationVector[1], rotationVector[2]); vtktransform->Translate(center[0], center[1], center[2]); vtktransform->PreMultiply(); break; } case OpRESTOREPLANEPOSITION: { //Copy necessary to avoid vtk warning vtkMatrix4x4* matrix = vtkMatrix4x4::New(); TransferItkTransformToVtkMatrix(dynamic_cast(operation)->GetTransform().GetPointer(), matrix); vtktransform->SetMatrix(matrix); + matrix->Delete(); break; } case OpAPPLYTRANSFORMMATRIX: { ApplyTransformMatrixOperation *applyMatrixOp = dynamic_cast< ApplyTransformMatrixOperation* >( operation ); vtktransform->SetMatrix(applyMatrixOp->GetMatrix()); break; } default: vtktransform->Delete(); return; } m_VtkMatrix->DeepCopy(vtktransform->GetMatrix()); TransferVtkToItkTransform(); Modified(); vtktransform->Delete(); } mitk::VnlVector mitk::BaseGeometry::GetMatrixColumn(unsigned int direction) const { return m_IndexToWorldTransform->GetMatrix().GetVnlMatrix().get_column(direction); } mitk::BoundingBox::Pointer mitk::BaseGeometry::CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D* transform) const { mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New(); mitk::BoundingBox::PointIdentifier pointid=0; unsigned char i; if(transform!=NULL) { mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New(); transform->GetInverse(inverse); for(i=0; i<8; ++i) pointscontainer->InsertElement( pointid++, inverse->TransformPoint( GetCornerPoint(i) )); } else { for(i=0; i<8; ++i) pointscontainer->InsertElement( pointid++, GetCornerPoint(i) ); } mitk::BoundingBox::Pointer result = mitk::BoundingBox::New(); result->SetPoints(pointscontainer); result->ComputeBoundingBox(); return result; } //void mitk::BaseGeometry::SetTimeBounds(const TimeBounds& timebounds) //{ // mitk::ModifiedLock lock(this); // // if(m_TimeBounds != timebounds) // { // m_TimeBounds = timebounds; // Modified(); // } // PostSetTimeBounds(timebounds); //} // //void mitk::BaseGeometry::PostSetTimeBounds(const TimeBounds& timebounds) //{} const std::string mitk::BaseGeometry::GetTransformAsString( TransformType* transformType ) { std::ostringstream out; out << '['; for( int i=0; i<3; ++i ) { out << '['; for( int j=0; j<3; ++j ) out << transformType->GetMatrix().GetVnlMatrix().get(i, j) << ' '; out << ']'; } out << "]["; for( int i=0; i<3; ++i ) out << transformType->GetOffset()[i] << ' '; out << "]\0"; return out.str(); } void mitk::BaseGeometry::SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4* vtkmatrix) { m_VtkMatrix->DeepCopy(vtkmatrix); TransferVtkToItkTransform(); } void mitk::BaseGeometry::WorldToIndex(const mitk::Point3D & /*atPt3d_mm*/, const mitk::Vector3D &vec_mm, mitk::Vector3D &vec_units) const { MITK_WARN<<"Warning! Call of the deprecated function BaseGeometry::WorldToIndex(point, vec, vec). Use BaseGeometry::WorldToIndex(vec, vec) instead!"; //BackTransform(atPt3d_mm, vec_mm, vec_units); this->WorldToIndex(vec_mm, vec_units); } void mitk::BaseGeometry::IndexToWorld(const mitk::Point3D &/*atPt3d_units*/, const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const { MITK_WARN<<"Warning! Call of the deprecated function BaseGeometry::IndexToWorld(point, vec, vec). Use BaseGeometry::IndexToWorld(vec, vec) instead!"; //vec_mm = m_IndexToWorldTransform->TransformVector(vec_units); this->IndexToWorld(vec_units, vec_mm); } void mitk::BaseGeometry::BackTransform(const mitk::Point3D &/*at*/, const mitk::Vector3D &in, mitk::Vector3D& out) const { MITK_INFO<<"Warning! Call of the deprecated function BaseGeometry::BackTransform(point, vec, vec). Use BaseGeometry::BackTransform(vec, vec) instead!"; //// Get WorldToIndex transform //if (m_IndexToWorldTransformLastModified != m_IndexToWorldTransform->GetMTime()) //{ // m_InvertedTransform = TransformType::New(); // if (!m_IndexToWorldTransform->GetInverse( m_InvertedTransform.GetPointer() )) // { // itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed." ); // } // m_IndexToWorldTransformLastModified = m_IndexToWorldTransform->GetMTime(); //} //// Check for valid matrix inversion //const TransformType::MatrixType& inverse = m_InvertedTransform->GetMatrix(); //if(inverse.GetVnlMatrix().has_nans()) //{ // itkExceptionMacro( "Internal ITK matrix inversion error, cannot proceed. Matrix was: " << std::endl // << m_IndexToWorldTransform->GetMatrix() << "Suggested inverted matrix is:" << std::endl // << inverse ); //} //// Transform vector //for (unsigned int i = 0; i < 3; i++) //{ // out[i] = 0.0; // for (unsigned int j = 0; j < 3; j++) // { // out[i] += inverse[i][j]*in[j]; // } //} this->BackTransform(in, out); } vtkMatrix4x4* mitk::BaseGeometry::GetVtkMatrix(){ return m_VtkMatrix; } bool mitk::BaseGeometry::IsBoundingBoxNull() const{ return m_BoundingBox.IsNull(); } bool mitk::BaseGeometry::IsIndexToWorldTransformNull() const{ return m_IndexToWorldTransform.IsNull(); } void mitk::BaseGeometry::ChangeImageGeometryConsideringOriginOffset( const bool isAnImageGeometry ) { // If Geometry is switched to ImageGeometry, you have to put an offset to the origin, because // imageGeometries origins are pixel-center-based // ... and remove the offset, if you switch an imageGeometry back to a normal geometry // For more information please see the Geometry documentation page if(m_ImageGeometry == isAnImageGeometry) return; const BoundingBox::BoundsArrayType& boundsarray = this->GetBoundingBox()->GetBounds(); Point3D originIndex; FillVector3D(originIndex, boundsarray[0], boundsarray[2], boundsarray[4]); if(isAnImageGeometry == true) FillVector3D( originIndex, originIndex[0] + 0.5, originIndex[1] + 0.5, originIndex[2] + 0.5 ); else FillVector3D( originIndex, originIndex[0] - 0.5, originIndex[1] - 0.5, originIndex[2] - 0.5 ); Point3D originWorld; originWorld = GetIndexToWorldTransform() ->TransformPoint( originIndex ); // instead could as well call IndexToWorld(originIndex,originWorld); SetOrigin(originWorld); this->SetImageGeometry(isAnImageGeometry); } //itk::LightObject::Pointer mitk::BaseGeometry::InternalClone() const //{ // Self::Pointer newGeometry = new Self(*this); // newGeometry->UnRegister(); // return newGeometry.GetPointer(); //} void mitk::BaseGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const { os << indent << " IndexToWorldTransform: "; if(this->IsIndexToWorldTransformNull()) os << "NULL" << std::endl; else { // from itk::MatrixOffsetTransformBase unsigned int i, j; os << std::endl; os << indent << "Matrix: " << std::endl; for (i = 0; i < 3; i++) { os << indent.GetNextIndent(); for (j = 0; j < 3; j++) { os << this->GetIndexToWorldTransform()->GetMatrix()[i][j] << " "; } os << std::endl; } os << indent << "Offset: " << this->GetIndexToWorldTransform()->GetOffset() << std::endl; os << indent << "Center: " << this->GetIndexToWorldTransform()->GetCenter() << std::endl; os << indent << "Translation: " << this->GetIndexToWorldTransform()->GetTranslation() << std::endl; os << indent << "Inverse: " << std::endl; for (i = 0; i < 3; i++) { os << indent.GetNextIndent(); for (j = 0; j < 3; j++) { os << this->GetIndexToWorldTransform()->GetInverseMatrix()[i][j] << " "; } os << std::endl; } // from itk::ScalableAffineTransform os << indent << "Scale : "; for (i = 0; i < 3; i++) { os << this->GetIndexToWorldTransform()->GetScale()[i] << " "; } os << std::endl; } os << indent << " BoundingBox: "; if(this->IsBoundingBoxNull()) os << "NULL" << std::endl; else { os << indent << "( "; for (unsigned int i=0; i<3; i++) { os << this->GetBoundingBox()->GetBounds()[2*i] << "," << this->GetBoundingBox()->GetBounds()[2*i+1] << " "; } os << " )" << std::endl; } os << indent << " Origin: " << this->GetOrigin() << std::endl; os << indent << " ImageGeometry: " << this->GetImageGeometry() << std::endl; os << indent << " Spacing: " << this->GetSpacing() << std::endl; //os << indent << " TimeBounds: " << this->GetTimeBounds() << std::endl; } void mitk::BaseGeometry::Modified() const{ if(!m_ModifiedLockFlag) Superclass::Modified(); else m_ModifiedCalledFlag = true; } bool mitk::Equal( const mitk::BaseGeometry::BoundingBoxType *leftHandSide, const mitk::BaseGeometry::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose ) { if(( leftHandSide == NULL) || ( rightHandSide == NULL )) { MITK_ERROR << "mitk::Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose ) does not with NULL pointer input."; return false; } return Equal( *leftHandSide, *rightHandSide, eps, verbose); } bool mitk::Equal( const mitk::BaseGeometry::BoundingBoxType& leftHandSide, const mitk::BaseGeometry::BoundingBoxType& rightHandSide, ScalarType eps, bool verbose ) { bool result = true; BaseGeometry::BoundsArrayType rightBounds = rightHandSide.GetBounds(); BaseGeometry::BoundsArrayType leftBounds = leftHandSide.GetBounds(); BaseGeometry::BoundsArrayType::Iterator itLeft = leftBounds.Begin(); for( BaseGeometry::BoundsArrayType::Iterator itRight = rightBounds.Begin(); itRight != rightBounds.End(); ++itRight) { if(( !mitk::Equal( *itLeft, *itRight, eps )) ) { if(verbose) { MITK_INFO << "[( Geometry3D::BoundingBoxType )] bounds are not equal."; MITK_INFO << "rightHandSide is " << setprecision(12) << *itRight << " : leftHandSide is " << *itLeft << " and tolerance is " << eps; } result = false; } itLeft++; } return result; } bool mitk::Equal(const mitk::BaseGeometry *leftHandSide, const mitk::BaseGeometry *rightHandSide, ScalarType eps, bool verbose) { if(( leftHandSide == NULL) || ( rightHandSide == NULL )) { MITK_ERROR << "mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType eps, bool verbose) does not with NULL pointer input."; return false; } return Equal( *leftHandSide, *rightHandSide, eps, verbose); } bool mitk::Equal(const mitk::BaseGeometry& leftHandSide, const mitk::BaseGeometry& rightHandSide, ScalarType eps, bool verbose) { bool result = true; //Compare spacings if( !mitk::Equal( leftHandSide.GetSpacing(), rightHandSide.GetSpacing(), eps ) ) { if(verbose) { MITK_INFO << "[( Geometry3D )] Spacing differs."; MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetSpacing() << " : leftHandSide is " << leftHandSide.GetSpacing() << " and tolerance is " << eps; } result = false; } //Compare Origins if( !mitk::Equal( leftHandSide.GetOrigin(), rightHandSide.GetOrigin(), eps ) ) { if(verbose) { MITK_INFO << "[( Geometry3D )] Origin differs."; MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetOrigin() << " : leftHandSide is " << leftHandSide.GetOrigin() << " and tolerance is " << eps; } result = false; } //Compare Axis and Extents for( unsigned int i=0; i<3; ++i) { if( !mitk::Equal( leftHandSide.GetAxisVector(i), rightHandSide.GetAxisVector(i), eps)) { if(verbose) { MITK_INFO << "[( Geometry3D )] AxisVector #" << i << " differ"; MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetAxisVector(i) << " : leftHandSide is " << leftHandSide.GetAxisVector(i) << " and tolerance is " << eps; } result = false; } if( !mitk::Equal( leftHandSide.GetExtent(i), rightHandSide.GetExtent(i), eps) ) { if(verbose) { MITK_INFO << "[( Geometry3D )] Extent #" << i << " differ"; MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetExtent(i) << " : leftHandSide is " << leftHandSide.GetExtent(i) << " and tolerance is " << eps; } result = false; } } //Compare ImageGeometry Flag if( rightHandSide.GetImageGeometry() != leftHandSide.GetImageGeometry() ) { if(verbose) { MITK_INFO << "[( Geometry3D )] GetImageGeometry is different."; MITK_INFO << "rightHandSide is " << rightHandSide.GetImageGeometry() << " : leftHandSide is " << leftHandSide.GetImageGeometry(); } result = false; } //Compare BoundingBoxes if( !mitk::Equal( *leftHandSide.GetBoundingBox(), *rightHandSide.GetBoundingBox(), eps, verbose) ) { result = false; } //Compare IndexToWorldTransform Matrix if( !mitk::Equal( *leftHandSide.GetIndexToWorldTransform(), *rightHandSide.GetIndexToWorldTransform(), eps, verbose) ) { result = false; } return result; } bool mitk::Equal(const BaseGeometry::TransformType *leftHandSide, const BaseGeometry::TransformType *rightHandSide, ScalarType eps, bool verbose ) { if(( leftHandSide == NULL) || ( rightHandSide == NULL )) { MITK_ERROR << "mitk::Equal(const Geometry3D::TransformType *leftHandSide, const Geometry3D::TransformType *rightHandSide, ScalarType eps, bool verbose ) does not with NULL pointer input."; return false; } return Equal( *leftHandSide, *rightHandSide, eps, verbose); } bool mitk::Equal(const BaseGeometry::TransformType& leftHandSide, const BaseGeometry::TransformType& rightHandSide, ScalarType eps, bool verbose ) { //Compare IndexToWorldTransform Matrix if( !mitk::MatrixEqualElementWise( leftHandSide.GetMatrix(), rightHandSide.GetMatrix() ) ) { if(verbose) { MITK_INFO << "[( Geometry3D::TransformType )] Index to World Transformation matrix differs."; MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetMatrix() << " : leftHandSide is " << leftHandSide.GetMatrix() << " and tolerance is " << eps; } return false; } return true; } diff --git a/Core/Code/Testing/mitkAffineTransformBaseTest.cpp b/Core/Code/Testing/mitkAffineTransformBaseTest.cpp index 2766b1dc67..97e5ffbff7 100644 --- a/Core/Code/Testing/mitkAffineTransformBaseTest.cpp +++ b/Core/Code/Testing/mitkAffineTransformBaseTest.cpp @@ -1,185 +1,196 @@ /*=================================================================== 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 "mitkNumericTypes.h" #include "itkScalableAffineTransform.h" #include "mitkMatrixConvert.h" #include "mitkTestingMacros.h" using namespace mitk; static Vector3D offset; static Matrix3D rotation; static Point3D originalPoint; static double originalPointDouble[4]; -static vtkMatrix4x4* homogenMatrix; +static vtkMatrix4x4* homogenMatrix = 0; -static vtkMatrix4x4* expectedHomogenousMatrix; +static vtkMatrix4x4* expectedHomogenousMatrix = 0; static const double expectedPointAfterTransformation[] = {2, 4, 4, 1}; static void Setup() { originalPoint[0] = 1.0; originalPoint[1] = 0.0; originalPoint[2] = 0.0; for (int i = 0; i < 3; i++) originalPointDouble[i] = originalPoint[i]; // same point as the Point3D version originalPointDouble[3] = 1; // homogenous extension offset[0] = 2.0; offset[1] = 3.0; offset[2] = 4.0; // 90� rotation rotation.Fill(0); rotation[0][1] = -1; rotation[1][0] = 1; // prepare a Matrix which shall be set later to a specific // homogen matrix by TransferItkTransformToVtkMatrix // this makes sure, that the initialization to the identity does not // overshadow any bugs in TransferItkTransformToVtkMatrix // (it actually did that by "helping out" TransferItkTransformToVtkMatrix // by setting the (3,3) element to 1). homogenMatrix = vtkMatrix4x4::New(); for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) homogenMatrix->SetElement(i,j, i+j*j); // just some not trivial value // set the expected homogenous matrix result expectedHomogenousMatrix = vtkMatrix4x4::New(); expectedHomogenousMatrix->Zero(); expectedHomogenousMatrix->SetElement(0,1,-1); expectedHomogenousMatrix->SetElement(1,0,1); expectedHomogenousMatrix->SetElement(0,3,2); expectedHomogenousMatrix->SetElement(1,3,3); expectedHomogenousMatrix->SetElement(2,3,4); expectedHomogenousMatrix->SetElement(3,3,1); } +static void TearDown() +{ + if (homogenMatrix) homogenMatrix->Delete(); + if (expectedHomogenousMatrix) expectedHomogenousMatrix->Delete(); +} + /** * This first test basically assures that we understand the usage of AffineTransform3D correct. * Meaning that the rotation is set by SetMatrix and the translation is set by SetOffset */ static void testIfPointIsTransformedAsExpected(void) { Setup(); /** construct the transformation */ AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetOffset(offset); transform->SetMatrix(rotation); TransferItkTransformToVtkMatrix(transform.GetPointer(), homogenMatrix); /** Let a point be transformed by the AffineTransform3D */ Point3D pointTransformedByAffineTransform3D = transform->TransformPoint(originalPoint); /** assert that the transformation was successful */ bool pointCorrect = true; for (int i = 0; i < 3; i++) // only first three since no homogenous coordinates pointCorrect &= Equal(pointTransformedByAffineTransform3D[i], expectedPointAfterTransformation[i]); MITK_TEST_CONDITION(pointCorrect, "Point has been correctly transformed by AffineTranform3D") + + TearDown(); } /** * This test ensures that the function TransferItkTransformToVtkMatrix translates the AffineTransform3D * correctly to a VtkMatrix4x4 */ static void testTransferItkTransformToVtkMatrix(void) { Setup(); AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetOffset(offset); transform->SetMatrix(rotation); TransferItkTransformToVtkMatrix(transform.GetPointer(), homogenMatrix); bool allElementsEqual = true; for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) allElementsEqual &= Equal(homogenMatrix->GetElement(i,j), expectedHomogenousMatrix->GetElement(i,j)); MITK_TEST_CONDITION(allElementsEqual, "Homogenous Matrix is set as expected") + + TearDown(); } /** * This test basically is just a sanity check and should be PASSED exactly when both * testTransferItkTransformToVtkMatrix and testIfPointIsTransformedAsExpected are PASSED. * Tests if we get the same * result by using the AffineTransform3D to transform a point or the vtkMatrix4x4 which we got by applying * the TransferItkTransformToVtkMatrix function. This test e.g. ensures we made no mistake in our * reference results. * */ static void testIfBothTransformationsProduceSameResults(void) { Setup(); /** * create both a AffineTransform3D * and let this AffineTransform describe also a homogenous 4x4 Matrix vtkMatrix * by using our transfer method */ AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform->SetOffset(offset); transform->SetMatrix(rotation); TransferItkTransformToVtkMatrix(transform.GetPointer(), homogenMatrix); /** Let a point be transformed by the AffineTransform3D and by homogenMatrix */ Point3D pointTransformedByAffineTransform3D = transform->TransformPoint(originalPoint); double* pointTransformedByHomogenous= homogenMatrix->MultiplyDoublePoint(originalPointDouble); /* check if results match */ bool pointsMatch = true; for (int i = 0; i < 3; i++) // only first three since no homogenous coordinates pointsMatch &= Equal(pointTransformedByAffineTransform3D[i], pointTransformedByHomogenous[i]); bool homogenousComponentCorrect = Equal(1, pointTransformedByHomogenous[3]); MITK_TEST_CONDITION(pointsMatch && homogenousComponentCorrect, "Point transformed by AffineTransform and homogenous coordinates match") + TearDown(); } /** * This test shall ensure and document the basic functionality of the * itk AffineTransformation functionality and test some basic transformation functionalities provided by mitk. */ int mitkAffineTransformBaseTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN("AffineTransformationBaseTest"); testIfPointIsTransformedAsExpected(); testTransferItkTransformToVtkMatrix(); testIfBothTransformationsProduceSameResults(); MITK_TEST_END(); } diff --git a/Core/Code/Testing/mitkBaseGeometryTest.cpp b/Core/Code/Testing/mitkBaseGeometryTest.cpp index cd7e9b205e..ba6996bca2 100644 --- a/Core/Code/Testing/mitkBaseGeometryTest.cpp +++ b/Core/Code/Testing/mitkBaseGeometryTest.cpp @@ -1,1250 +1,1253 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include #include #include #include #include #include "mitkOperationActor.h" #include #include "mitkVector.h" #include #include #include "itkScalableAffineTransform.h" #include #include #include #include "mitkRotationOperation.h" #include "mitkInteractionConst.h" #include #include class vtkMatrix4x4; class vtkMatrixToLinearTransform; class vtkLinearTransform; typedef itk::BoundingBox BoundingBox; typedef itk::BoundingBox BoundingBoxType; typedef BoundingBoxType::BoundsArrayType BoundsArrayType; typedef BoundingBoxType::Pointer BoundingBoxPointer; // Dummy instance of abstract base class class DummyTestClass : public mitk::BaseGeometry { public: DummyTestClass(){}; DummyTestClass(const DummyTestClass& other) : BaseGeometry(other){}; ~DummyTestClass(){}; mitkClassMacro(DummyTestClass, mitk::BaseGeometry); itkNewMacro(Self); mitkNewMacro1Param(Self, const Self&); itk::LightObject::Pointer InternalClone() const { Self::Pointer newGeometry = new Self(*this); newGeometry->UnRegister(); return newGeometry.GetPointer(); } virtual void PrintSelf(std::ostream& os, itk::Indent indent) const{}; }; class mitkBaseGeometryTestSuite : public mitk::TestFixture { // List of Tests CPPUNIT_TEST_SUITE(mitkBaseGeometryTestSuite); //Constructor MITK_TEST(TestConstructors); MITK_TEST(TestInitialize); //Set MITK_TEST(TestSetOrigin); MITK_TEST(TestSetBounds); MITK_TEST(TestSetFloatBounds); MITK_TEST(TestSetFloatBoundsDouble); MITK_TEST(TestSetFrameOfReferenceID); MITK_TEST(TestSetIndexToWorldTransform); MITK_TEST(TestSetIndexToWorldTransform_WithPointerToSameTransform); MITK_TEST(TestSetSpacing); MITK_TEST(TestTransferItkToVtkTransform); MITK_TEST(TestSetIndexToWorldTransformByVtkMatrix); MITK_TEST(TestSetIdentity); MITK_TEST(TestSetImageGeometry); //Equal MITK_TEST(Equal_CloneAndOriginal_ReturnsTrue); MITK_TEST(Equal_DifferentOrigin_ReturnsFalse); MITK_TEST(Equal_DifferentIndexToWorldTransform_ReturnsFalse); MITK_TEST(Equal_DifferentSpacing_ReturnsFalse); MITK_TEST(Equal_InputIsNull_ReturnsFalse); MITK_TEST(Equal_DifferentBoundingBox_ReturnsFalse); //other Functions MITK_TEST(TestComposeTransform); MITK_TEST(TestComposeVtkMatrix); MITK_TEST(TestTranslate); MITK_TEST(TestIndexToWorld); MITK_TEST(TestExecuteOperation); MITK_TEST(TestCalculateBoundingBoxRelToTransform); //MITK_TEST(TestSetTimeBounds); MITK_TEST(TestIs2DConvertable); MITK_TEST(TestGetCornerPoint); MITK_TEST(TestExtentInMM); MITK_TEST(TestGetAxisVector); MITK_TEST(TestGetCenter); MITK_TEST(TestGetDiagonalLength); MITK_TEST(TestGetExtent); MITK_TEST(TestIsInside); MITK_TEST(TestGetMatrixColumn); CPPUNIT_TEST_SUITE_END(); // Used Variables private: mitk::Point3D aPoint; float aFloatSpacing[3]; mitk::Vector3D aSpacing; mitk::AffineTransform3D::Pointer aTransform; BoundingBoxPointer aBoundingBox; mitk::AffineTransform3D::MatrixType aMatrix; mitk::Point3D anotherPoint; mitk::Vector3D anotherSpacing; BoundingBoxPointer anotherBoundingBox; BoundingBoxPointer aThirdBoundingBox; mitk::AffineTransform3D::Pointer anotherTransform; mitk::AffineTransform3D::Pointer aThirdTransform; mitk::AffineTransform3D::MatrixType anotherMatrix; mitk::AffineTransform3D::MatrixType aThirdMatrix; DummyTestClass::Pointer aDummyGeometry; DummyTestClass::Pointer anotherDummyGeometry; public: // Set up for variables void setUp() { mitk::FillVector3D(aFloatSpacing, 1,1,1); mitk::FillVector3D(aSpacing, 1,1,1); mitk::FillVector3D(aPoint, 0,0,0); //Transform aTransform = mitk::AffineTransform3D::New(); aTransform->SetIdentity(); aMatrix.SetIdentity(); anotherTransform = mitk::AffineTransform3D::New(); anotherMatrix.SetIdentity(); anotherMatrix(1,1) = 2; anotherTransform->SetMatrix( anotherMatrix ); aThirdTransform = mitk::AffineTransform3D::New(); aThirdMatrix.SetIdentity(); aThirdMatrix(1,1) = 7; aThirdTransform->SetMatrix( aThirdMatrix ); //Bounding Box float bounds[6] = {0,1,0,1,0,1}; mitk::BoundingBox::BoundsArrayType b; const float *input = bounds; int j=0; for(mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); j < 6 ;++j) *it++ = (mitk::ScalarType)*input++; aBoundingBox = BoundingBoxType::New(); BoundingBoxType::PointsContainer::Pointer pointscontainer = BoundingBoxType::PointsContainer::New(); BoundingBoxType::PointType p; BoundingBoxType::PointIdentifier pointid; for(pointid=0; pointid<2;++pointid) { unsigned int i; for(i=0; i<3; ++i) { p[i] = bounds[2*i+pointid]; } pointscontainer->InsertElement(pointid, p); } aBoundingBox->SetPoints(pointscontainer); aBoundingBox->ComputeBoundingBox(); anotherBoundingBox = BoundingBoxType::New(); p[0]=11; p[1]=12; p[2]=13; pointscontainer->InsertElement(1, p); anotherBoundingBox->SetPoints(pointscontainer); anotherBoundingBox->ComputeBoundingBox(); aThirdBoundingBox = BoundingBoxType::New(); p[0]=22; p[1]=23; p[2]=24; pointscontainer->InsertElement(1, p); aThirdBoundingBox->SetPoints(pointscontainer); aThirdBoundingBox->ComputeBoundingBox(); mitk::FillVector3D(anotherPoint, 2,3,4); mitk::FillVector3D(anotherSpacing, 5,6.5,7); aDummyGeometry = DummyTestClass::New(); aDummyGeometry->Initialize(); anotherDummyGeometry = aDummyGeometry->Clone(); } void tearDown() { aDummyGeometry = NULL; anotherDummyGeometry = NULL; } // Test functions void TestSetOrigin() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(mitk::Equal(anotherPoint,dummy->GetOrigin())); //undo changes, new and changed object need to be the same! dummy->SetOrigin(aPoint); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetImageGeometry() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetImageGeometry(true); CPPUNIT_ASSERT(dummy->GetImageGeometry()); //undo changes, new and changed object need to be the same! dummy->SetImageGeometry(false); CPPUNIT_ASSERT(dummy->GetImageGeometry()==false); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetFloatBounds(){ float bounds[6] = {0,11,0,12,0,13}; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, true)); //Wrong bounds, test needs to fail bounds[1]=7; dummy->SetFloatBounds(bounds); CPPUNIT_ASSERT((mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, false))==false); //undo changes, new and changed object need to be the same! float originalBounds[6] = {0,1,0,1,0,1}; dummy->SetFloatBounds(originalBounds); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetBounds(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetBounds(anotherBoundingBox->GetBounds()); CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, true)); //Test needs to fail now dummy->SetBounds(aThirdBoundingBox->GetBounds()); CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, false)==false); //undo changes, new and changed object need to be the same! dummy->SetBounds(aBoundingBox->GetBounds()); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetFloatBoundsDouble(){ double bounds[6] = {0,11,0,12,0,13}; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, true)); //Test needs to fail now bounds[3]=7; dummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal( dummy->GetBoundingBox(), anotherBoundingBox, mitk::eps, false)==false); //undo changes, new and changed object need to be the same! double originalBounds[6] = {0,1,0,1,0,1}; dummy->SetFloatBounds(originalBounds); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetFrameOfReferenceID() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetFrameOfReferenceID(5); CPPUNIT_ASSERT(dummy->GetFrameOfReferenceID()==5); //undo changes, new and changed object need to be the same! dummy->SetFrameOfReferenceID(0); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetIndexToWorldTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,true)); //Test needs to fail now dummy->SetIndexToWorldTransform(aThirdTransform); CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,false)==false); //undo changes, new and changed object need to be the same! dummy->SetIndexToWorldTransform(aTransform); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetIndexToWorldTransform_WithPointerToSameTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetOrigin(anotherPoint); dummy->SetIndexToWorldTransform(anotherTransform); dummy->SetSpacing(anotherSpacing); mitk::AffineTransform3D::Pointer testTransfrom = dummy->GetIndexToWorldTransform(); mitk::Vector3D modifiedPoint = anotherPoint.GetVectorFromOrigin() *2.; testTransfrom->SetOffset(modifiedPoint); dummy->SetIndexToWorldTransform(testTransfrom); CPPUNIT_ASSERT(mitk::Equal(modifiedPoint, dummy->GetOrigin().GetVectorFromOrigin())); } void TestSetIndexToWorldTransformByVtkMatrix() { vtkMatrix4x4* vtkmatrix; vtkmatrix = vtkMatrix4x4::New(); vtkmatrix->Identity(); vtkmatrix->SetElement(1,1,2); DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix); CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,true)); //test needs to fail now vtkmatrix->SetElement(1,1,7); dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix); CPPUNIT_ASSERT(mitk::Equal(anotherTransform,dummy->GetIndexToWorldTransform(),mitk::eps,false)==false); //undo changes, new and changed object need to be the same! vtkmatrix->SetElement(1,1,1); dummy->SetIndexToWorldTransformByVtkMatrix(vtkmatrix); + vtkmatrix->Delete(); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetIdentity() { DummyTestClass::Pointer dummy = DummyTestClass::New(); //Change IndextoWorldTransform and Origin dummy->SetIndexToWorldTransform(anotherTransform); dummy->SetOrigin(anotherPoint); //Set Identity should reset ITWT and Origin dummy->SetIdentity(); CPPUNIT_ASSERT(mitk::Equal(aTransform,dummy->GetIndexToWorldTransform(),mitk::eps,true)); CPPUNIT_ASSERT(mitk::Equal(aPoint,dummy->GetOrigin())); CPPUNIT_ASSERT(mitk::Equal(aSpacing,dummy->GetSpacing())); //new and changed object need to be the same! DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestSetSpacing() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetSpacing(anotherSpacing); CPPUNIT_ASSERT(mitk::Equal(anotherSpacing,dummy->GetSpacing())); //undo changes, new and changed object need to be the same! dummy->SetSpacing(aSpacing); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestTransferItkToVtkTransform() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); //calls TransferItkToVtkTransform mitk::AffineTransform3D::Pointer dummyTransform = dummy->GetIndexToWorldTransform(); CPPUNIT_ASSERT(mitk::MatrixEqualElementWise( anotherMatrix, dummyTransform->GetMatrix() )); } void TestConstructors() { //test standard constructor DummyTestClass::Pointer dummy1 = DummyTestClass::New(); bool test = dummy1->IsValid(); CPPUNIT_ASSERT(test == true); CPPUNIT_ASSERT(dummy1->GetFrameOfReferenceID() == 0); CPPUNIT_ASSERT(dummy1->GetIndexToWorldTransformLastModified() == 0); CPPUNIT_ASSERT(mitk::Equal(dummy1->GetSpacing(), aSpacing)); CPPUNIT_ASSERT(mitk::Equal(dummy1->GetOrigin(), aPoint)); CPPUNIT_ASSERT(dummy1->GetImageGeometry()==false); CPPUNIT_ASSERT(mitk::Equal( dummy1->GetIndexToWorldTransform(), aTransform, mitk::eps, true)); CPPUNIT_ASSERT(mitk::Equal( dummy1->GetBoundingBox(), aBoundingBox, mitk::eps, true)); DummyTestClass::Pointer dummy2 = DummyTestClass::New(); dummy2->SetOrigin(anotherPoint); float bounds[6] = {0,11,0,12,0,13}; dummy2->SetFloatBounds(bounds); dummy2->SetIndexToWorldTransform(anotherTransform); dummy2->SetSpacing(anotherSpacing); DummyTestClass::Pointer dummy3 = DummyTestClass::New(*dummy2); CPPUNIT_ASSERT(mitk::Equal(dummy3,dummy2,mitk::eps,true)); } //Equal Tests void Equal_CloneAndOriginal_ReturnsTrue() { CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,true)); } void Equal_DifferentOrigin_ReturnsFalse() { anotherDummyGeometry->SetOrigin(anotherPoint); CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false); } void Equal_DifferentIndexToWorldTransform_ReturnsFalse() { anotherDummyGeometry->SetIndexToWorldTransform(anotherTransform); CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false); } void Equal_DifferentSpacing_ReturnsFalse() { anotherDummyGeometry->SetSpacing(anotherSpacing); CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false); } void Equal_InputIsNull_ReturnsFalse() { DummyTestClass::Pointer geometryNull = NULL; MITK_INFO<<"Test, if a Null pointer throws an error. The next line needs to display an error."; CPPUNIT_ASSERT( mitk::Equal(geometryNull, anotherDummyGeometry, mitk::eps,false)==false); } void Equal_DifferentBoundingBox_ReturnsFalse() { //create different bounds to make the comparison false mitk::ScalarType bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; anotherDummyGeometry->SetBounds(bounds); CPPUNIT_ASSERT( mitk::Equal(aDummyGeometry, anotherDummyGeometry, mitk::eps,false)==false); } void TestComposeTransform(){ //Create Transformations to set and compare mitk::AffineTransform3D::Pointer transform1; transform1 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix1; matrix1.SetIdentity(); matrix1(1,1) = 2; transform1->SetMatrix( matrix1 ); //Spacing = 2 mitk::AffineTransform3D::Pointer transform2; transform2 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix2; matrix2.SetIdentity(); matrix2(1,1) = 2; transform2->SetMatrix( matrix2 ); //Spacing = 2 mitk::AffineTransform3D::Pointer transform3; transform3 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix3; matrix3.SetIdentity(); matrix3(1,1) = 4; transform3->SetMatrix( matrix3 ); //Spacing = 4 mitk::AffineTransform3D::Pointer transform4; transform4 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix4; matrix4.SetIdentity(); matrix4(1,1) = 0.25; transform4->SetMatrix( matrix4 ); //Spacing = 0.25 //Vector to compare spacing mitk::Vector3D expectedSpacing; expectedSpacing.Fill(1.0); expectedSpacing[1] = 4; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(transform1); //Spacing = 2 dummy->Compose(transform2); //Spacing = 4 CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing)); CPPUNIT_ASSERT(mitk::Equal(transform3,dummy->GetIndexToWorldTransform(),mitk::eps,true)); // 4=4 //undo changes, new and changed object need to be the same! dummy->Compose(transform4); //Spacing = 1 DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); // 1=1 } void TestComposeVtkMatrix(){ //Create Transformations to set and compare mitk::AffineTransform3D::Pointer transform1; transform1 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix1; matrix1.SetIdentity(); matrix1(1,1) = 2; transform1->SetMatrix( matrix1 ); //Spacing = 2 vtkMatrix4x4* vtkmatrix2; vtkmatrix2 = vtkMatrix4x4::New(); vtkmatrix2->Identity(); vtkmatrix2->SetElement(1,1,2); //Spacing = 2 mitk::AffineTransform3D::Pointer transform3; transform3 = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType matrix3; matrix3.SetIdentity(); matrix3(1,1) = 4; transform3->SetMatrix( matrix3 ); //Spacing = 4 vtkMatrix4x4* vtkmatrix4; vtkmatrix4 = vtkMatrix4x4::New(); vtkmatrix4->Identity(); vtkmatrix4->SetElement(1,1,0.25); //Spacing = 0.25 //Vector to compare spacing mitk::Vector3D expectedSpacing; expectedSpacing.Fill(1.0); expectedSpacing[1] = 4; DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(transform1); //Spacing = 2 dummy->Compose(vtkmatrix2); //Spacing = 4 + vtkmatrix2->Delete(); CPPUNIT_ASSERT(mitk::Equal(transform3,dummy->GetIndexToWorldTransform(),mitk::eps,true)); // 4=4 CPPUNIT_ASSERT(mitk::Equal(dummy->GetSpacing(), expectedSpacing)); //undo changes, new and changed object need to be the same! dummy->Compose(vtkmatrix4); //Spacing = 1 + vtkmatrix4->Delete(); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); // 1=1 } void TestTranslate(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(mitk::Equal(anotherPoint,dummy->GetOrigin())); //use some random values for translation mitk::Vector3D translationVector; translationVector.SetElement(0, 17.5f); translationVector.SetElement(1, -32.3f); translationVector.SetElement(2, 4.0f); //compute ground truth mitk::Point3D tmpResult = anotherPoint + translationVector; dummy->Translate(translationVector); CPPUNIT_ASSERT( mitk::Equal( dummy->GetOrigin(), tmpResult )); //undo changes translationVector*=-1; dummy->Translate(translationVector); CPPUNIT_ASSERT( mitk::Equal( dummy->GetOrigin(), anotherPoint )); //undo changes, new and changed object need to be the same! translationVector.SetElement(0, -1 * anotherPoint[0]); translationVector.SetElement(1, -1 * anotherPoint[1]); translationVector.SetElement(2, -1 * anotherPoint[2]); dummy->Translate(translationVector); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } // a part of the test requires axis-parallel coordinates int testIndexAndWorldConsistency(DummyTestClass::Pointer dummyGeometry) { //Testing consistency of index and world coordinate systems mitk::Point3D origin = dummyGeometry->GetOrigin(); mitk::Point3D dummyPoint; //Testing index->world->index conversion consistency dummyGeometry->WorldToIndex(origin, dummyPoint); dummyGeometry->IndexToWorld(dummyPoint, dummyPoint); CPPUNIT_ASSERT(mitk::EqualArray(dummyPoint, origin, 3, mitk::eps, true)); //Testing WorldToIndex(origin, mitk::Point3D)==(0,0,0) mitk::Point3D globalOrigin; mitk::FillVector3D(globalOrigin, 0,0,0); mitk::Point3D originContinuousIndex; dummyGeometry->WorldToIndex(origin, originContinuousIndex); CPPUNIT_ASSERT(mitk::EqualArray(originContinuousIndex, globalOrigin, 3, mitk::eps, true)); //Testing WorldToIndex(origin, itk::Index)==(0,0,0) itk::Index<3> itkindex; dummyGeometry->WorldToIndex(origin, itkindex); itk::Index<3> globalOriginIndex; mitk::vtk2itk(globalOrigin, globalOriginIndex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true)); //Testing WorldToIndex(origin-0.5*spacing, itk::Index)==(0,0,0) mitk::Vector3D halfSpacingStep = dummyGeometry->GetSpacing()*0.5; mitk::Matrix3D rotation; mitk::Point3D originOffCenter = origin-halfSpacingStep; dummyGeometry->WorldToIndex(originOffCenter, itkindex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true)); //Testing WorldToIndex(origin+0.5*spacing-eps, itk::Index)==(0,0,0) originOffCenter = origin+halfSpacingStep; originOffCenter -= 0.0001; dummyGeometry->WorldToIndex( originOffCenter, itkindex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, globalOriginIndex, 3, mitk::eps, true)); //Testing WorldToIndex(origin+0.5*spacing, itk::Index)==(1,1,1)"); originOffCenter = origin+halfSpacingStep; itk::Index<3> global111; mitk::FillVector3D(global111, 1,1,1); dummyGeometry->WorldToIndex( originOffCenter, itkindex); CPPUNIT_ASSERT(mitk::EqualArray(itkindex, global111, 3, mitk::eps, true)); //Testing WorldToIndex(GetCenter())==BoundingBox.GetCenter mitk::Point3D center = dummyGeometry->GetCenter(); mitk::Point3D centerContIndex; dummyGeometry->WorldToIndex(center, centerContIndex); mitk::BoundingBox::ConstPointer boundingBox = dummyGeometry->GetBoundingBox(); mitk::BoundingBox::PointType centerBounds = boundingBox->GetCenter(); CPPUNIT_ASSERT(mitk::Equal(centerContIndex,centerBounds)); //Testing GetCenter()==IndexToWorld(BoundingBox.GetCenter) center = dummyGeometry->GetCenter(); mitk::Point3D centerBoundsInWorldCoords; dummyGeometry->IndexToWorld(centerBounds, centerBoundsInWorldCoords); CPPUNIT_ASSERT(mitk::Equal(center,centerBoundsInWorldCoords)); //Test using random point, //Testing consistency of index and world coordinate systems mitk::Point3D point; mitk::FillVector3D(point,3.5,-2,4.6); //Testing index->world->index conversion consistency dummyGeometry->WorldToIndex(point, dummyPoint); dummyGeometry->IndexToWorld(dummyPoint, dummyPoint); CPPUNIT_ASSERT(mitk::EqualArray(dummyPoint, point, 3, mitk::eps, true)); return EXIT_SUCCESS; } int testIndexAndWorldConsistencyForVectors(DummyTestClass::Pointer dummyGeometry) { //Testing consistency of index and world coordinate systems for vectors mitk::Vector3D xAxisMM = dummyGeometry->GetAxisVector(0); mitk::Vector3D xAxisContinuousIndex; mitk::Point3D p, pIndex, origin; origin = dummyGeometry->GetOrigin(); p[0] = xAxisMM[0]+origin[0]; p[1] = xAxisMM[1]+origin[1]; p[2] = xAxisMM[2]+origin[2]; dummyGeometry->WorldToIndex(p,pIndex); dummyGeometry->WorldToIndex(xAxisMM,xAxisContinuousIndex); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[0], pIndex[0])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[1], pIndex[1])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[2], pIndex[2])); dummyGeometry->IndexToWorld(xAxisContinuousIndex,xAxisContinuousIndex); dummyGeometry->IndexToWorld(pIndex,p); CPPUNIT_ASSERT(xAxisContinuousIndex == xAxisMM); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[0], p[0]-origin[0])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[1], p[1]-origin[1])); CPPUNIT_ASSERT(mitk::Equal(xAxisContinuousIndex[2], p[2]-origin[2])); //Test consictency for random vector mitk::Vector3D vector; mitk::FillVector3D(vector, 2.5,-3.2,8.1); mitk::Vector3D vectorContinuousIndex; p[0] = vector[0]+origin[0]; p[1] = vector[1]+origin[1]; p[2] = vector[2]+origin[2]; dummyGeometry->WorldToIndex(p,pIndex); dummyGeometry->WorldToIndex(vector,vectorContinuousIndex); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[0], pIndex[0])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[1], pIndex[1])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[2], pIndex[2])); dummyGeometry->IndexToWorld(vectorContinuousIndex,vectorContinuousIndex); dummyGeometry->IndexToWorld(pIndex,p); CPPUNIT_ASSERT(vectorContinuousIndex == vector); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[0], p[0]-origin[0])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[1], p[1]-origin[1])); CPPUNIT_ASSERT(mitk::Equal(vectorContinuousIndex[2], p[2]-origin[2])); return EXIT_SUCCESS; } int testIndexAndWorldConsistencyForIndex(DummyTestClass::Pointer dummyGeometry) { //Testing consistency of index and world coordinate systems // creating testing data itk::Index<4> itkIndex4, itkIndex4b; itk::Index<3> itkIndex3, itkIndex3b; itk::Index<2> itkIndex2, itkIndex2b; itk::Index<3> mitkIndex, mitkIndexb; itkIndex4[0] = itkIndex4[1] = itkIndex4[2] = itkIndex4[3] = 4; itkIndex3[0] = itkIndex3[1] = itkIndex3[2] = 6; itkIndex2[0] = itkIndex2[1] = 2; mitkIndex[0] = mitkIndex[1] = mitkIndex[2] = 13; // check for constistency mitk::Point3D point; dummyGeometry->IndexToWorld(itkIndex2,point); dummyGeometry->WorldToIndex(point,itkIndex2b); CPPUNIT_ASSERT( ((itkIndex2b[0] == itkIndex2[0]) && (itkIndex2b[1] == itkIndex2[1]))); //Testing itk::index<2> for IndexToWorld/WorldToIndex consistency dummyGeometry->IndexToWorld(itkIndex3,point); dummyGeometry->WorldToIndex(point,itkIndex3b); CPPUNIT_ASSERT( ((itkIndex3b[0] == itkIndex3[0]) && (itkIndex3b[1] == itkIndex3[1]) && (itkIndex3b[2] == itkIndex3[2]))); //Testing itk::index<3> for IndexToWorld/WorldToIndex consistency dummyGeometry->IndexToWorld(itkIndex4,point); dummyGeometry->WorldToIndex(point,itkIndex4b); CPPUNIT_ASSERT( ((itkIndex4b[0] == itkIndex4[0]) && (itkIndex4b[1] == itkIndex4[1]) && (itkIndex4b[2] == itkIndex4[2]) && (itkIndex4b[3] == 0))); //Testing itk::index<3> for IndexToWorld/WorldToIndex consistency dummyGeometry->IndexToWorld(mitkIndex,point); dummyGeometry->WorldToIndex(point,mitkIndexb); CPPUNIT_ASSERT( ((mitkIndexb[0] == mitkIndex[0]) && (mitkIndexb[1] == mitkIndex[1]) && (mitkIndexb[2] == mitkIndex[2]))); //Testing mitk::Index for IndexToWorld/WorldToIndex consistency return EXIT_SUCCESS; } void TestIndexToWorld(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); //Geometry must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); //Test with other geometries dummy->SetOrigin(anotherPoint); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); dummy->SetIndexToWorldTransform(anotherTransform); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); dummy->SetOrigin(anotherPoint); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); dummy->SetSpacing(anotherSpacing); testIndexAndWorldConsistency(dummy); testIndexAndWorldConsistencyForVectors(dummy); testIndexAndWorldConsistencyForIndex(dummy); } void TestExecuteOperation(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); //Do same Operations with new Dummy and compare DummyTestClass::Pointer newDummy = DummyTestClass::New(); //Test operation Nothing mitk::Operation* opN = new mitk::Operation(mitk::OpNOTHING); dummy->ExecuteOperation(opN); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); //Test operation Move mitk::PointOperation* opP = new mitk::PointOperation(mitk::OpMOVE,anotherPoint); dummy->ExecuteOperation(opP); CPPUNIT_ASSERT(mitk::Equal(anotherPoint,dummy->GetOrigin())); newDummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); //Test operation Scale, Scale sets spacing to scale+1 mitk::Point3D spacing; spacing[0]=anotherSpacing[0]-1.; spacing[1]=anotherSpacing[1]-1.; spacing[2]=anotherSpacing[2]-1.; mitk::PointOperation* opS = new mitk::PointOperation(mitk::OpSCALE,spacing); dummy->ExecuteOperation(opS); CPPUNIT_ASSERT(mitk::Equal(anotherSpacing,dummy->GetSpacing())); newDummy->SetSpacing(anotherSpacing); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); //change Geometry to test more cases dummy->SetIndexToWorldTransform(anotherTransform); dummy->SetSpacing(anotherSpacing); //Testing a rotation of the geometry double angle = 35.0; mitk::Vector3D rotationVector; mitk::FillVector3D( rotationVector, 1, 0, 0 ); mitk::Point3D center = dummy->GetCenter(); mitk::RotationOperation* opR = new mitk::RotationOperation( mitk::OpROTATE, center, rotationVector, angle ); dummy->ExecuteOperation(opR); mitk::Matrix3D rotation; mitk::GetRotation(dummy, rotation); mitk::Vector3D voxelStep=rotation*anotherSpacing; mitk::Vector3D voxelStepIndex; dummy->WorldToIndex(voxelStep, voxelStepIndex); mitk::Vector3D expectedVoxelStepIndex; expectedVoxelStepIndex.Fill(1); CPPUNIT_ASSERT(mitk::Equal(voxelStepIndex,expectedVoxelStepIndex)); delete opR; delete opN; delete opS; delete opP; } void TestCalculateBoundingBoxRelToTransform(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetExtentInMM(0,15); dummy->SetExtentInMM(1,20); dummy->SetExtentInMM(2,8); mitk::BoundingBox::Pointer dummyBoundingBox = dummy->CalculateBoundingBoxRelativeToTransform(anotherTransform); mitk::BoundingBox::PointsContainer::Pointer pointscontainer=mitk::BoundingBox::PointsContainer::New(); mitk::BoundingBox::PointIdentifier pointid=0; unsigned char i; mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New(); anotherTransform->GetInverse(inverse); for(i=0; i<8; ++i) pointscontainer->InsertElement( pointid++, inverse->TransformPoint( dummy->GetCornerPoint(i) )); mitk::BoundingBox::Pointer result = mitk::BoundingBox::New(); result->SetPoints(pointscontainer); result->ComputeBoundingBox(); CPPUNIT_ASSERT(mitk::Equal(result,dummyBoundingBox,mitk::eps,true)); //dummy still needs to be unchanged, except for extend DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetExtentInMM(0,15); newDummy->SetExtentInMM(1,20); newDummy->SetExtentInMM(2,8); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } //void TestSetTimeBounds(){ // mitk::TimeBounds timeBounds; // timeBounds[0] = 1; // timeBounds[1] = 9; // DummyTestClass::Pointer dummy = DummyTestClass::New(); // dummy->SetTimeBounds(timeBounds); // mitk::TimeBounds timeBounds2 = dummy->GetTimeBounds(); // CPPUNIT_ASSERT(timeBounds[0]==timeBounds2[0]); // CPPUNIT_ASSERT(timeBounds[1]==timeBounds2[1]); // //undo changes, new and changed object need to be the same! // timeBounds[0]=mitk::ScalarTypeNumericTraits::NonpositiveMin(); // timeBounds[1]=mitk::ScalarTypeNumericTraits::max(); // DummyTestClass::Pointer newDummy = DummyTestClass::New(); // CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); //} void TestIs2DConvertable(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); //new initialized geometry is 2D convertable CPPUNIT_ASSERT(dummy->Is2DConvertable()); //Wrong Spacing needs to fail dummy->SetSpacing(anotherSpacing); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); //undo dummy->SetSpacing(aSpacing); CPPUNIT_ASSERT(dummy->Is2DConvertable()); //Wrong Origin needs to fail dummy->SetOrigin(anotherPoint); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); //undo dummy->SetOrigin(aPoint); CPPUNIT_ASSERT(dummy->Is2DConvertable()); //third dimension must not be transformed mitk::AffineTransform3D::Pointer dummyTransform = mitk::AffineTransform3D::New(); mitk::AffineTransform3D::MatrixType dummyMatrix; dummyMatrix.SetIdentity(); dummyTransform->SetMatrix( dummyMatrix ); dummy->SetIndexToWorldTransform(dummyTransform); //identity matrix is 2DConvertable CPPUNIT_ASSERT(dummy->Is2DConvertable()); dummyMatrix(0,2) = 3; dummyTransform->SetMatrix( dummyMatrix ); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); dummyMatrix.SetIdentity(); dummyMatrix(1,2) = 0.4; dummyTransform->SetMatrix( dummyMatrix ); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); dummyMatrix.SetIdentity(); dummyMatrix(2,2) = 3; dummyTransform->SetMatrix( dummyMatrix ); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); dummyMatrix.SetIdentity(); dummyMatrix(2,1) = 3; dummyTransform->SetMatrix( dummyMatrix ); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); dummyMatrix.SetIdentity(); dummyMatrix(2,0) = 3; dummyTransform->SetMatrix( dummyMatrix ); CPPUNIT_ASSERT(dummy->Is2DConvertable()==false); //undo changes, new and changed object need to be the same! dummyMatrix.SetIdentity(); dummyTransform->SetMatrix( dummyMatrix ); DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestGetCornerPoint(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); double bounds[6] = {0,11,0,12,0,13}; dummy->SetFloatBounds(bounds); mitk::Point3D corner, refCorner; //Corner 0 mitk::FillVector3D(refCorner,bounds[0],bounds[2],bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(0); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(true,true,true); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 1 mitk::FillVector3D(refCorner,bounds[0],bounds[2],bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(1); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(true,true,false); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 2 mitk::FillVector3D(refCorner,bounds[0],bounds[3],bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(2); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(true,false,true); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 3 mitk::FillVector3D(refCorner,bounds[0],bounds[3],bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(3); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(true,false,false); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 4 mitk::FillVector3D(refCorner,bounds[1],bounds[2],bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(4); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(false,true,true); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 5 mitk::FillVector3D(refCorner,bounds[1],bounds[2],bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(5); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(false,true,false); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 6 mitk::FillVector3D(refCorner,bounds[1],bounds[3],bounds[4]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(6); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(false,false,true); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Corner 7 mitk::FillVector3D(refCorner,bounds[1],bounds[3],bounds[5]); refCorner = anotherTransform->TransformPoint(refCorner); corner=dummy->GetCornerPoint(7); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); corner=dummy->GetCornerPoint(false,false,false); CPPUNIT_ASSERT(mitk::Equal(refCorner,corner)); //Wrong Corner needs to fail CPPUNIT_ASSERT_THROW(dummy->GetCornerPoint(20),itk::ExceptionObject); //dummy geometry must not have changed! DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetIndexToWorldTransform(anotherTransform); newDummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestExtentInMM() { DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetExtentInMM(0,50); CPPUNIT_ASSERT(mitk::Equal(50.,dummy->GetExtentInMM(0))); //Vnl Matrix has changed. The next line only works because the spacing is 1! CPPUNIT_ASSERT(mitk::Equal(50.,dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude())); //Smaller extent than original dummy->SetExtentInMM(0,5); CPPUNIT_ASSERT(mitk::Equal(5.,dummy->GetExtentInMM(0))); CPPUNIT_ASSERT(mitk::Equal(5.,dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0).magnitude())); dummy->SetExtentInMM(1,4); CPPUNIT_ASSERT(mitk::Equal(4.,dummy->GetExtentInMM(1))); CPPUNIT_ASSERT(mitk::Equal(4.,dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1).magnitude())); dummy->SetExtentInMM(2,2.5); CPPUNIT_ASSERT(mitk::Equal(2.5,dummy->GetExtentInMM(2))); CPPUNIT_ASSERT(mitk::Equal(2.5,dummy->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2).magnitude())); } void TestGetAxisVector(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); double bounds[6] = {0,11,0,12,0,13}; dummy->SetFloatBounds(bounds); mitk::Vector3D vector; mitk::FillVector3D(vector,bounds[1],0,0); dummy->IndexToWorld(vector,vector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(0),vector)); mitk::FillVector3D(vector,0,bounds[3],0); dummy->IndexToWorld(vector,vector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(1),vector)); mitk::FillVector3D(vector,0,0,bounds[5]); dummy->IndexToWorld(vector,vector); CPPUNIT_ASSERT(mitk::Equal(dummy->GetAxisVector(2),vector)); } void TestGetCenter(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); double bounds[6] = {0,11,2,12,1,13}; dummy->SetFloatBounds(bounds); mitk::Point3D refCenter; for( int i=0;i<3;i++) refCenter.SetElement(i,( bounds[2 * i] + bounds[2 * i + 1] ) / 2.0); dummy->IndexToWorld(refCenter,refCenter); CPPUNIT_ASSERT(mitk::Equal(dummy->GetCenter(),refCenter)); } void TestGetDiagonalLength(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); double bounds[6] = {1,3,5,8,7.5,11.5}; dummy->SetFloatBounds(bounds); //3-1=2, 8-5=3, 11.5-7.5=4; 2^2+3^2+4^2 = 29 double expectedLength = sqrt(29.); CPPUNIT_ASSERT(mitk::Equal(expectedLength, dummy->GetDiagonalLength(), mitk::eps, true)); CPPUNIT_ASSERT(mitk::Equal(29., dummy->GetDiagonalLength2(), mitk::eps, true)); //dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestGetExtent(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); double bounds[6] = {1,3,5,8,7.5,11.5}; dummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal(2.,dummy->GetExtent(0))); CPPUNIT_ASSERT(mitk::Equal(3.,dummy->GetExtent(1))); CPPUNIT_ASSERT(mitk::Equal(4.,dummy->GetExtent(2))); //dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestIsInside(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); double bounds[6] = {1,3,5,8,7.5,11.5}; dummy->SetFloatBounds(bounds); mitk::Point3D insidePoint; mitk::Point3D outsidePoint; mitk::FillVector3D(insidePoint,2,6,7.6); mitk::FillVector3D(outsidePoint,0,9,8.2); CPPUNIT_ASSERT(dummy->IsIndexInside(insidePoint)); CPPUNIT_ASSERT(false==dummy->IsIndexInside(outsidePoint)); dummy->IndexToWorld(insidePoint,insidePoint); dummy->IndexToWorld(outsidePoint,outsidePoint); CPPUNIT_ASSERT(dummy->IsInside(insidePoint)); CPPUNIT_ASSERT(false==dummy->IsInside(outsidePoint)); //dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetFloatBounds(bounds); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } void TestInitialize() { //test standard constructor DummyTestClass::Pointer dummy1 = DummyTestClass::New(); DummyTestClass::Pointer dummy2 = DummyTestClass::New(); dummy2->SetOrigin(anotherPoint); dummy2->SetBounds(anotherBoundingBox->GetBounds()); //mitk::TimeBounds timeBounds; //timeBounds[0] = 1; //timeBounds[1] = 9; //dummy2->SetTimeBounds(timeBounds); dummy2->SetIndexToWorldTransform(anotherTransform); dummy2->SetSpacing(anotherSpacing); dummy1->InitializeGeometry(dummy2); CPPUNIT_ASSERT(mitk::Equal(dummy1,dummy2,mitk::eps,true)); dummy1->Initialize(); DummyTestClass::Pointer dummy3 = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy3,dummy1,mitk::eps,true)); } void TestGetMatrixColumn(){ DummyTestClass::Pointer dummy = DummyTestClass::New(); dummy->SetIndexToWorldTransform(anotherTransform); mitk::Vector3D testVector,refVector; testVector.SetVnlVector(dummy->GetMatrixColumn(0)); mitk::FillVector3D(refVector,1,0,0); CPPUNIT_ASSERT(testVector==refVector); testVector.SetVnlVector(dummy->GetMatrixColumn(1)); mitk::FillVector3D(refVector,0,2,0); CPPUNIT_ASSERT(testVector==refVector); testVector.SetVnlVector(dummy->GetMatrixColumn(2)); mitk::FillVector3D(refVector,0,0,1); CPPUNIT_ASSERT(testVector==refVector); //dummy must not have changed DummyTestClass::Pointer newDummy = DummyTestClass::New(); newDummy->SetIndexToWorldTransform(anotherTransform); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } /* void (){ DummyTestClass::Pointer dummy = DummyTestClass::New(); CPPUNIT_ASSERT(); //undo changes, new and changed object need to be the same! DummyTestClass::Pointer newDummy = DummyTestClass::New(); CPPUNIT_ASSERT(mitk::Equal(dummy,newDummy,mitk::eps,true)); } */ };//end class mitkBaseGeometryTestSuite MITK_TEST_SUITE_REGISTRATION(mitkBaseGeometry) diff --git a/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp b/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp index 21f4f3d702..fc1c9c2a0b 100644 --- a/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp +++ b/Core/Code/Testing/mitkClippedSurfaceBoundsCalculatorTest.cpp @@ -1,484 +1,485 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include #include "mitkClippedSurfaceBoundsCalculator.h" #include "mitkGeometry3D.h" #include "mitkPlaneGeometry.h" #include "mitkNumericTypes.h" static void CheckPlanesInsideBoundingBoxOnlyOnOneSlice(mitk::BaseGeometry::Pointer geometry3D) { //Check planes which are inside the bounding box mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator(); mitk::Image::Pointer image = mitk::Image::New(); image->Initialize( mitk::MakePixelType(), *(geometry3D.GetPointer()) ); //Check planes which are only on one slice: //Slice 0 mitk::Point3D origin; origin[0] = 511; origin[1] = 0; origin[2] = 0; mitk::Vector3D normal; mitk::FillVector3D(normal, 0, 0, 1); mitk::PlaneGeometry::Pointer planeOnSliceZero = mitk::PlaneGeometry::New(); planeOnSliceZero->InitializePlane(origin, normal); calculator->SetInput( planeOnSliceZero , image); calculator->Update(); mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice"); MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 0, "Check if plane is on slice 0"); //Slice 3 origin[2] = 3; mitk::PlaneGeometry::Pointer planeOnSliceThree = mitk::PlaneGeometry::New(); planeOnSliceThree->InitializePlane(origin, normal); planeOnSliceThree->SetImageGeometry(false); calculator->SetInput( planeOnSliceThree , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice"); MITK_TEST_CONDITION(minMax.first == 3 && minMax.second == 3, "Check if plane is on slice 3"); //Slice 17 origin[2] = 17; mitk::PlaneGeometry::Pointer planeOnSliceSeventeen = mitk::PlaneGeometry::New(); planeOnSliceSeventeen->InitializePlane(origin, normal); calculator->SetInput( planeOnSliceSeventeen , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice"); MITK_TEST_CONDITION(minMax.first == 17 && minMax.second == 17, "Check if plane is on slice 17"); //Slice 20 origin[2] = 19; mitk::PlaneGeometry::Pointer planeOnSliceTwenty = mitk::PlaneGeometry::New(); planeOnSliceTwenty->InitializePlane(origin, normal); calculator->SetInput( planeOnSliceTwenty , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == minMax.second, "Check if plane is only on one slice"); MITK_TEST_CONDITION(minMax.first == 19 && minMax.second == 19, "Check if plane is on slice 19"); delete calculator; } static void CheckPlanesInsideBoundingBox(mitk::BaseGeometry::Pointer geometry3D) { //Check planes which are inside the bounding box mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator(); mitk::Image::Pointer image = mitk::Image::New(); image->Initialize( mitk::MakePixelType(), *(geometry3D.GetPointer()) ); //Check planes which are only on one slice: //Slice 0 mitk::Point3D origin; origin[0] = 511; // Set to 511.9 so that the intersection point is inside the bounding box origin[1] = 0; origin[2] = 0; mitk::Vector3D normal; mitk::FillVector3D(normal, 1, 0, 0); mitk::PlaneGeometry::Pointer planeSagittalOne = mitk::PlaneGeometry::New(); planeSagittalOne->InitializePlane(origin, normal); calculator->SetInput( planeSagittalOne , image); calculator->Update(); mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19"); //Slice 3 origin[0] = 256; MITK_INFO << "Case1 origin: " << origin; mitk::PlaneGeometry::Pointer planeSagittalTwo = mitk::PlaneGeometry::New(); planeSagittalTwo->InitializePlane(origin, normal); MITK_INFO << "PlaneNormal: " << planeSagittalTwo->GetNormal(); MITK_INFO << "PlaneOrigin: " << planeSagittalTwo->GetOrigin(); calculator->SetInput( planeSagittalTwo , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_INFO << "min: " << minMax.first << " max: " << minMax.second; MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19"); //Slice 17 origin[0] = 0; // Set to 0.1 so that the intersection point is inside the bounding box mitk::PlaneGeometry::Pointer planeOnSliceSeventeen = mitk::PlaneGeometry::New(); planeOnSliceSeventeen->InitializePlane(origin, normal); calculator->SetInput( planeOnSliceSeventeen , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19"); //Crooked planes: origin[0] = 0; origin[1] = 507; origin[2] = 0; normal[0] = 1; normal[1] = -1; normal[2] = 1; mitk::PlaneGeometry::Pointer planeCrookedOne = mitk::PlaneGeometry::New(); planeCrookedOne->InitializePlane(origin, normal); calculator->SetInput( planeCrookedOne , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_INFO << "min: " << minMax.first << " max: " << minMax.second; MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 4, "Check if plane is from slice 0 to slice 4 with inclined plane"); origin[0] = 512; origin[1] = 0; origin[2] = 16; mitk::PlaneGeometry::Pointer planeCrookedTwo = mitk::PlaneGeometry::New(); planeCrookedTwo->InitializePlane(origin, normal); calculator->SetInput( planeCrookedTwo , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_INFO << "min: " << minMax.first << " max: " << minMax.second; MITK_TEST_CONDITION(minMax.first == 17 && minMax.second == 19, "Check if plane is from slice 17 to slice 19 with inclined plane"); origin[0] = 511; origin[1] = 0; origin[2] = 0; normal[1] = 0; normal[2] = 0.04; mitk::PlaneGeometry::Pointer planeCrookedThree = mitk::PlaneGeometry::New(); planeCrookedThree->InitializePlane(origin, normal); calculator->SetInput( planeCrookedThree , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_INFO << "min: " << minMax.first << " max: " << minMax.second; MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19 with inclined plane"); delete calculator; } static void CheckPlanesOutsideOfBoundingBox(mitk::BaseGeometry::Pointer geometry3D) { //Check planes which are outside of the bounding box mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator(); mitk::Image::Pointer image = mitk::Image::New(); image->Initialize( mitk::MakePixelType(), *(geometry3D.GetPointer()) ); //In front of the bounding box mitk::Point3D origin; origin[0] = 511; origin[1] = 0; origin[2] = -5; mitk::Vector3D normal; mitk::FillVector3D(normal, 0, 0, 1); mitk::PlaneGeometry::Pointer planeInFront = mitk::PlaneGeometry::New(); planeInFront->InitializePlane(origin, normal); calculator->SetInput( planeInFront , image); calculator->Update(); mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == std::numeric_limits::max(), "Check if min value hasn't been set"); MITK_TEST_CONDITION(minMax.second == std::numeric_limits::min(), "Check if max value hasn't been set"); //Behind the bounding box origin[2] = 515; mitk::PlaneGeometry::Pointer planeBehind = mitk::PlaneGeometry::New(); planeBehind->InitializePlane(origin, normal); calculator->SetInput( planeBehind , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == std::numeric_limits::max(), "Check if min value hasn't been set"); MITK_TEST_CONDITION(minMax.second == std::numeric_limits::min(), "Check if max value hasn't been set"); //Above origin[1] = 515; mitk::FillVector3D(normal, 0, 1, 0); mitk::PlaneGeometry::Pointer planeAbove = mitk::PlaneGeometry::New(); planeAbove->InitializePlane(origin, normal); calculator->SetInput( planeAbove , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == std::numeric_limits::max(), "Check if min value hasn't been set"); MITK_TEST_CONDITION(minMax.second == std::numeric_limits::min(), "Check if max value hasn't been set"); //Below origin[1] = -5; mitk::PlaneGeometry::Pointer planeBelow = mitk::PlaneGeometry::New(); planeBelow->InitializePlane(origin, normal); calculator->SetInput( planeBelow , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == std::numeric_limits::max(), "Check if min value hasn't been set"); MITK_TEST_CONDITION(minMax.second == std::numeric_limits::min(), "Check if max value hasn't been set"); //Left side origin[0] = -5; mitk::FillVector3D(normal, 1, 0, 0); mitk::PlaneGeometry::Pointer planeLeftSide = mitk::PlaneGeometry::New(); planeLeftSide->InitializePlane(origin, normal); calculator->SetInput( planeLeftSide , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == std::numeric_limits::max(), "Check if min value hasn't been set"); MITK_TEST_CONDITION(minMax.second == std::numeric_limits::min(), "Check if max value hasn't been set"); //Right side origin[1] = 515; mitk::PlaneGeometry::Pointer planeRightSide = mitk::PlaneGeometry::New(); planeRightSide->InitializePlane(origin, normal); calculator->SetInput( planeRightSide , image); calculator->Update(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMax.first == std::numeric_limits::max(), "Check if min value hasn't been set"); MITK_TEST_CONDITION(minMax.second == std::numeric_limits::min(), "Check if max value hasn't been set"); delete calculator; } static void CheckIntersectionPointsOfTwoGeometry3D(mitk::BaseGeometry::Pointer firstGeometry3D, mitk::BaseGeometry::Pointer secondGeometry3D) { mitk::ClippedSurfaceBoundsCalculator* calculator = new mitk::ClippedSurfaceBoundsCalculator(); mitk::Image::Pointer firstImage = mitk::Image::New(); firstImage->Initialize( mitk::MakePixelType(), *(firstGeometry3D.GetPointer()) ); calculator->SetInput( secondGeometry3D, firstImage); calculator->Update(); mitk::ClippedSurfaceBoundsCalculator::OutputType minMax = calculator->GetMinMaxSpatialDirectionZ(); minMax = calculator->GetMinMaxSpatialDirectionZ(); MITK_INFO << "min: " << minMax.first << " max: " << minMax.second; MITK_TEST_CONDITION(minMax.first == 0 && minMax.second == 19, "Check if plane is from slice 0 to slice 19"); + delete calculator; } static void CheckIntersectionWithPointCloud( mitk::BaseGeometry::Pointer geometry3D ) { //Check planes which are inside the bounding box mitk::Image::Pointer image = mitk::Image::New(); image->Initialize( mitk::MakePixelType(), *(geometry3D.GetPointer()) ); { mitk::Point3D pnt1, pnt2; pnt1[0] = 3; pnt1[1] = 5; pnt1[2] = 3; pnt2[0] = 8; pnt2[1] = 3; pnt2[2] = 8; mitk::ClippedSurfaceBoundsCalculator::PointListType pointlist; pointlist.push_back( pnt1 ); pointlist.push_back( pnt2 ); mitk::ClippedSurfaceBoundsCalculator calculator; calculator.SetInput( pointlist, image ); calculator.Update(); mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxZ = calculator.GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMaxZ.first == 3 && minMaxZ.second == 8, "Check if points span from slice 3 to slice 8 in axial"); mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxX = calculator.GetMinMaxSpatialDirectionX(); MITK_TEST_CONDITION(minMaxX.first == 3 && minMaxX.second == 5, "Check if points span from slice 3 to slice 5 in sagittal"); } { mitk::Point3D pnt1, pnt2; pnt1.Fill( -3 ); pnt2.Fill( 600 ); mitk::ClippedSurfaceBoundsCalculator::PointListType pointlist; pointlist.push_back( pnt1 ); pointlist.push_back( pnt2 ); mitk::ClippedSurfaceBoundsCalculator calculator; calculator.SetInput( pointlist, image ); calculator.Update(); mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxZ = calculator.GetMinMaxSpatialDirectionZ(); MITK_TEST_CONDITION(minMaxZ.first == 0 && minMaxZ.second == 19, "Check if points are correctly clipped to slice 0 and slice 19 in axial"); mitk::ClippedSurfaceBoundsCalculator::OutputType minMaxX = calculator.GetMinMaxSpatialDirectionX(); MITK_TEST_CONDITION(minMaxX.first == 0 && minMaxX.second == 511, "Check if points are correctly clipped to slice 0 and slice 511 in sagittal"); } } int mitkClippedSurfaceBoundsCalculatorTest(int, char* []) { // always start with this! MITK_TEST_BEGIN("ClippedSurfaceBoundsCalculator"); /** The class mitkClippedSurfaceBoundsCalculator calculates the intersection points of a PlaneGeometry and a Geometry3D. * This unittest checks if the correct min and max values for the three spatial directions (x, y, z) * are calculated. To test this we define artifical PlaneGeometries and Geometry3Ds and test different * scenarios: * * 1. planes which are inside the bounding box of a 3D geometry but only on one slice * 2. planes which are outside of the bounding box * 3. planes which are inside the bounding box but over more than one slice * * Note: Currently rotated geometries are not tested! */ /********************* Define Geometry3D ***********************/ //Define origin: mitk::Point3D origin; origin[0] = 511; origin[1] = 0; origin[2] = 0; //Define normal: mitk::Vector3D normal; mitk::FillVector3D(normal, 0, 0, 1); //Initialize PlaneGeometry: mitk::PlaneGeometry::Pointer planeGeometry = mitk::PlaneGeometry::New(); planeGeometry->InitializePlane(origin, normal); //Set Bounds: mitk::BoundingBox::BoundsArrayType bounds = planeGeometry->GetBounds(); bounds[0] = 0; bounds[1] = 512; bounds[2] = 0; bounds[3] = 512; bounds[4] = 0; bounds[5] = 1; planeGeometry->SetBounds(bounds); //Initialize SlicedGeometry3D: mitk::SlicedGeometry3D::Pointer slicedGeometry3D = mitk::SlicedGeometry3D::New(); slicedGeometry3D->InitializeEvenlySpaced(dynamic_cast(planeGeometry.GetPointer()), 20); mitk::BaseGeometry::Pointer geometry3D = dynamic_cast< mitk::BaseGeometry* > ( slicedGeometry3D.GetPointer() ); geometry3D->SetImageGeometry(true); //Define origin for second Geometry3D; mitk::Point3D origin2; origin2[0] = 511; origin2[1] = 60; origin2[2] = 0; //Define normal: mitk::Vector3D normal2; mitk::FillVector3D(normal2, 0, 1, 0); //Initialize PlaneGeometry: mitk::PlaneGeometry::Pointer planeGeometry2 = mitk::PlaneGeometry::New(); planeGeometry2->InitializePlane(origin2, normal2); //Initialize SlicedGeometry3D: mitk::SlicedGeometry3D::Pointer secondSlicedGeometry3D = mitk::SlicedGeometry3D::New(); secondSlicedGeometry3D->InitializeEvenlySpaced(dynamic_cast(planeGeometry2.GetPointer()), 20); mitk::BaseGeometry::Pointer secondGeometry3D = dynamic_cast< mitk::BaseGeometry* > ( secondSlicedGeometry3D.GetPointer() ); secondGeometry3D->SetImageGeometry(true); /***************************************************************/ CheckPlanesInsideBoundingBoxOnlyOnOneSlice(geometry3D); CheckPlanesOutsideOfBoundingBox(geometry3D); CheckPlanesInsideBoundingBox(geometry3D); CheckIntersectionPointsOfTwoGeometry3D(geometry3D, secondGeometry3D); CheckIntersectionWithPointCloud( geometry3D ); /** ToDo: * test also rotated 3D geometry! */ MITK_TEST_END(); } diff --git a/Core/Code/Testing/mitkLookupTableTest.cpp b/Core/Code/Testing/mitkLookupTableTest.cpp index bc9189ec54..8ab1f93045 100644 --- a/Core/Code/Testing/mitkLookupTableTest.cpp +++ b/Core/Code/Testing/mitkLookupTableTest.cpp @@ -1,183 +1,187 @@ /*=================================================================== 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 #include "mitkTestingMacros.h" #include #include #include #include class mitkLookupTableTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkLookupTableTestSuite); MITK_TEST(TestCreateLookupTable); MITK_TEST(TestSetVtkLookupTable); MITK_TEST(TestSetOpacity); MITK_TEST(TestCreateColorTransferFunction); MITK_TEST(TestCreateOpacityTransferFunction); MITK_TEST(TestCreateGradientTransferFunction); CPPUNIT_TEST_SUITE_END(); private: mitk::LookupTable::Pointer m_LookupTable; public: void TestCreateLookupTable() { // let's create an object of our class mitk::LookupTable::Pointer myLookupTable = mitk::LookupTable::New(); // first test: did this work? // it makes no sense to continue without an object. CPPUNIT_ASSERT_MESSAGE("Testing instantiation", myLookupTable.IsNotNull()); } void TestSetVtkLookupTable () { mitk::LookupTable::Pointer myLookupTable = mitk::LookupTable::New(); // create a vtkLookupTable and add two values vtkLookupTable *lut = vtkLookupTable::New(); lut->SetTableValue(0, 0.5, 0.5, 0.5, 1.0); lut->SetTableValue(1, 0.5, 0.5, 0.5, 0.5); lut->Build(); myLookupTable->SetVtkLookupTable(lut); // check if the same lookuptable is returned vtkLookupTable *lut2 = myLookupTable->GetVtkLookupTable(); CPPUNIT_ASSERT_MESSAGE("Input and output table are not equal",lut == lut2); lut->Delete(); } void TestSetOpacity() { mitk::LookupTable::Pointer myLookupTable = mitk::LookupTable::New(); // create a vtkLookupTable and add two values vtkLookupTable *lut = vtkLookupTable::New(); lut->SetRange(0, 200); lut->SetAlphaRange(0.0, 1.0); lut->Build(); myLookupTable->SetVtkLookupTable(lut); myLookupTable->ChangeOpacityForAll(0.7f); for (int i = 0; i < lut->GetNumberOfTableValues(); ++i) { CPPUNIT_ASSERT_MESSAGE("Opacity not set for all", mitk::Equal(0.7, lut->GetOpacity(i), 0.01, true)); } vtkIdType tableIndex = 10; myLookupTable->ChangeOpacity(tableIndex, 1.0); double rgba[4]; lut->GetTableValue(tableIndex, rgba); CPPUNIT_ASSERT_MESSAGE("Opacity not set for value", mitk::Equal(1.0, rgba[3], 0.01, true)); + lut->Delete(); } void TestCreateColorTransferFunction () { mitk::LookupTable::Pointer myLookupTable = mitk::LookupTable::New(); // create a vtkLookupTable and add two values vtkLookupTable *lut = vtkLookupTable::New(); lut->SetRange(0, 255); lut->Build(); myLookupTable->SetVtkLookupTable(lut); vtkSmartPointer colorTransferFunction = myLookupTable->CreateColorTransferFunction(); CPPUNIT_ASSERT(colorTransferFunction != 0); vtkIdType numberOfTableEntries = lut->GetNumberOfTableValues(); double rgbaTable[4]; double rgbaFunction[4]; for (int i = 0; i < numberOfTableEntries; ++i) { lut->GetIndexedColor(i, rgbaTable); colorTransferFunction->GetIndexedColor(i, rgbaFunction); CPPUNIT_ASSERT_MESSAGE("Wrong color of transfer function", mitk::Equal(rgbaTable[0], rgbaFunction[0], 0.000001, true) && mitk::Equal(rgbaTable[1], rgbaFunction[1], 0.000001, true) && mitk::Equal(rgbaTable[2], rgbaFunction[2], 0.000001, true) ); } + lut->Delete(); } void TestCreateOpacityTransferFunction () { mitk::LookupTable::Pointer myLookupTable = mitk::LookupTable::New(); // create a vtkLookupTable and add two values vtkLookupTable *lut = vtkLookupTable::New(); lut->SetAlphaRange(0, 1.0); lut->Build(); myLookupTable->SetVtkLookupTable(lut); vtkSmartPointer opacityTransferFunction = myLookupTable->CreateOpacityTransferFunction(); CPPUNIT_ASSERT(opacityTransferFunction != 0); int funcSize = opacityTransferFunction->GetSize(); double *table = new double[funcSize]; double rgba[4]; opacityTransferFunction->GetTable(0, 1, funcSize, table); for (int i = 0; i < funcSize; ++i) { lut->GetIndexedColor(i, rgba); CPPUNIT_ASSERT_MESSAGE("Wrong opacity of transfer function", mitk::Equal(table[i], rgba[3], 0.000001, true) ); } + lut->Delete(); delete [] table; } void TestCreateGradientTransferFunction () { mitk::LookupTable::Pointer myLookupTable = mitk::LookupTable::New(); // create a vtkLookupTable and add two values vtkLookupTable *lut = vtkLookupTable::New(); lut->SetAlphaRange(0, 0.73); lut->Build(); myLookupTable->SetVtkLookupTable(lut); vtkSmartPointer gradientTransferFunction = myLookupTable->CreateGradientTransferFunction(); CPPUNIT_ASSERT(gradientTransferFunction != 0); int funcSize = gradientTransferFunction->GetSize(); double *table = new double[funcSize]; double rgba[4]; gradientTransferFunction->GetTable(0, 1, funcSize, table); for (int i = 0; i < funcSize; ++i) { lut->GetIndexedColor(i, rgba); CPPUNIT_ASSERT_MESSAGE("Wrong opacity of transfer function", mitk::Equal(table[i], rgba[3], 0.000001, true) ); } + lut->Delete(); delete [] table; } }; MITK_TEST_SUITE_REGISTRATION(mitkLookupTable) diff --git a/Core/Code/Testing/vtkMitkThickSlicesFilterTest.cpp b/Core/Code/Testing/vtkMitkThickSlicesFilterTest.cpp index 70e327d5d5..7975d10b56 100644 --- a/Core/Code/Testing/vtkMitkThickSlicesFilterTest.cpp +++ b/Core/Code/Testing/vtkMitkThickSlicesFilterTest.cpp @@ -1,172 +1,174 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include #include "mitkImageWriteAccessor.h" #include "mitkImage.h" #include #include #include class vtkMitkThickSlicesFilterTestHelper { public: static mitk::Image::Pointer CreateTestImage( int min, int max ) { mitk::PixelType pixelType( mitk::MakeScalarPixelType() ); mitk::Image::Pointer testImage = mitk::Image::New(); unsigned int* dim = new unsigned int[3]; dim[0] = 10; dim[1] = 10; dim[2] = max+1-min; testImage->Initialize( pixelType, 3, dim ); size_t buffer_size = dim[0] * dim[1] * sizeof(unsigned char); for( int i=min; i<=max; ++i ) { mitk::ImageWriteAccessor writeAccess( testImage, testImage->GetSliceData( i-min ) ); memset( writeAccess.GetData(), i, buffer_size ); } return testImage; } static void EvaluateResult( unsigned char expectedValue, vtkImageData* image, const char* projection ) { MITK_TEST_CONDITION_REQUIRED( image->GetDimensions()[0] == 10 && image->GetDimensions()[1] == 10 && image->GetDimensions()[2] == 1, "Resulting image has correct size" ); unsigned char* value = static_cast( image->GetScalarPointer(0,0,0) ); MITK_INFO << "Evaluating projection mode: " << projection; MITK_INFO << "expected value: " << static_cast( expectedValue ); MITK_INFO << "actual value: " << static_cast( value[0] ); MITK_TEST_CONDITION_REQUIRED( value[0] == expectedValue, "Resulting image has correct pixel-value" ); } }; /** * Test for vtkMitkThickSlicesFilter. * */ int vtkMitkThickSlicesFilterTest(int argc, char** const argv) { // always start with this! MITK_TEST_BEGIN("vtkMitkThickSlicesFilterTest") vtkMitkThickSlicesFilter* thickSliceFilter = vtkMitkThickSlicesFilter::New(); ////////////////////////////////////////////////////////////////////////// // Image looks like: // 000000000 // 111111111 // 222222222 mitk::Image::Pointer testImage1 = vtkMitkThickSlicesFilterTestHelper::CreateTestImage( 0, 2 ); thickSliceFilter->SetInputData( testImage1->GetVtkImageData() ); // MaxIP thickSliceFilter->SetThickSliceMode( 0 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 2, thickSliceFilter->GetOutput(), "MaxIP" ); // Sum thickSliceFilter->SetThickSliceMode( 1 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 1, thickSliceFilter->GetOutput(), "Sum" ); // Weighted thickSliceFilter->SetThickSliceMode( 2 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 1, thickSliceFilter->GetOutput(), "Weighted" ); // MinIP thickSliceFilter->SetThickSliceMode( 3 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 0, thickSliceFilter->GetOutput(), "MinIP" ); // Mean thickSliceFilter->SetThickSliceMode( 4 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 1, thickSliceFilter->GetOutput(), "Mean" ); ////////////////////////////////////////////////////////////////////////// // Image looks like: // 333333333 // 444444444 // 555555555 // 666666666 // 777777777 // 888888888 mitk::Image::Pointer testImage2 = vtkMitkThickSlicesFilterTestHelper::CreateTestImage( 3, 8 ); thickSliceFilter->SetInputData( testImage2->GetVtkImageData() ); // MaxIP thickSliceFilter->SetThickSliceMode( 0 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 8, thickSliceFilter->GetOutput(), "MaxIP" ); // Sum thickSliceFilter->SetThickSliceMode( 1 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 5, thickSliceFilter->GetOutput(), "Sum" ); // Weighted thickSliceFilter->SetThickSliceMode( 2 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 4, thickSliceFilter->GetOutput(), "Weighted" ); // MinIP thickSliceFilter->SetThickSliceMode( 3 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 3, thickSliceFilter->GetOutput(), "MinIP" ); // Mean thickSliceFilter->SetThickSliceMode( 4 ); thickSliceFilter->Modified(); thickSliceFilter->Update(); vtkMitkThickSlicesFilterTestHelper::EvaluateResult( 6, thickSliceFilter->GetOutput(), "Mean" ); + thickSliceFilter->Delete(); + MITK_TEST_END() } diff --git a/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp b/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp index 4ab901d78a..036f4b98ec 100644 --- a/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp +++ b/Modules/IGT/TrackingDevices/mitkTrackingVolumeGenerator.cpp @@ -1,150 +1,153 @@ /*=================================================================== 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 "mitkTrackingVolumeGenerator.h" #include "mitkSTLFileReader.h" #include "mitkStandardFileLocations.h" #include "mitkConfig.h" #include #include #include #include #include #include #include #include #include #include #include #include mitk::TrackingVolumeGenerator::TrackingVolumeGenerator() { m_Data = mitk::DeviceDataUnspecified; } void mitk::TrackingVolumeGenerator::SetTrackingDevice (mitk::TrackingDevice::Pointer tracker) { this->m_Data = mitk::GetFirstCompatibleDeviceDataForLine(tracker->GetType()); } void mitk::TrackingVolumeGenerator::GenerateData() { mitk::Surface::Pointer output = this->GetOutput(); //the surface wich represents the tracking volume std::string filepath = ""; // Full path to file (wil be resolved later) std::string filename = this->m_Data.VolumeModelLocation; // Name of the file or possibly a magic String, e.g. "cube" MITK_INFO << "volume: " << filename; // See if filename matches a magic string. if (filename.compare("cube") == 0){ vtkSmartPointer cubeSource = vtkSmartPointer::New(); double bounds[6]; bounds[0] = bounds[2] = bounds[4] = -400.0; // initialize bounds to -400 ... +400 cube. This is the default value of the bounds[1] = bounds[3] = bounds[5] = 400.0; // virtual tracking device, but it can be changed. In that case, // the tracking volume polydata has to be updated manually cubeSource->SetBounds(bounds); cubeSource->Update(); output->SetVtkPolyData(cubeSource->GetOutput()); //set the vtkCubeSource as polyData of the surface return; } if (filename.compare("") == 0) // empty String means no model, return empty output { - output->SetVtkPolyData(vtkPolyData::New()); //initialize with empty poly data (otherwise old surfaces may be returned) => so an empty surface is returned + // initialize with empty poly data (otherwise old surfaces may be returned) => so an empty surface is returned + vtkPolyData *emptyPolyData = vtkPolyData::New(); + output->SetVtkPolyData(emptyPolyData); + emptyPolyData->Delete(); return; } // from here on, we assume that filename contains an actual filename and not a magic string us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource moduleResource = module->GetResource(filename); bool isCompressed = moduleResource.IsCompressed(); // Create ResourceStream from Resource us::ModuleResourceStream resStream(moduleResource,std::ios_base::binary); ofstream tmpOutputStream; std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile(tmpOutputStream); if (!isCompressed) { tmpOutputStream << resStream.rdbuf(); } else { resStream.seekg(0, std::ios::end); std::ios::pos_type length = resStream.tellg(); resStream.seekg(0, std::ios::beg); char* data = new char[length]; resStream.read(data, length); tmpOutputStream.close(); tmpOutputStream.open(tmpFilePath.c_str(), std::ios_base::binary | std::ios_base::out); tmpOutputStream.write(data, length); tmpOutputStream.flush(); delete[] data; } tmpOutputStream.close(); //filepath = mitk::StandardFileLocations::GetInstance()->FindFile(filename.c_str()); if (tmpFilePath.empty()) { MITK_ERROR << ("Volume Generator could not find the specified file " + filename); return; } mitk::STLFileReader::Pointer stlReader = mitk::STLFileReader::New(); stlReader->SetFileName( tmpFilePath.c_str() ); stlReader->Update(); std::remove(tmpFilePath.c_str()); if ( stlReader->GetOutput() == NULL) { MITK_ERROR << "Error while reading file"; return ; } output->SetVtkPolyData( stlReader->GetOutput()->GetVtkPolyData());//set the visible trackingvolume } void mitk::TrackingVolumeGenerator::SetTrackingDeviceType(mitk::TrackingDeviceType deviceType) { m_Data = mitk::GetFirstCompatibleDeviceDataForLine(deviceType); } mitk::TrackingDeviceType mitk::TrackingVolumeGenerator::GetTrackingDeviceType() const { return m_Data.Line; } void mitk::TrackingVolumeGenerator::SetTrackingDeviceData(mitk::TrackingDeviceData deviceData) { m_Data= deviceData; } mitk::TrackingDeviceData mitk::TrackingVolumeGenerator::GetTrackingDeviceData() const { return m_Data; }