Example #1
0
void
PlaneGeometry::InitializeStandardPlane(
  mitk::ScalarType width, ScalarType height,
  const VnlVector &rightVector, const VnlVector &downVector,
  const Vector3D *spacing )
{
  assert(width > 0);
  assert(height > 0);

  VnlVector rightDV = rightVector; rightDV.normalize();
  VnlVector downDV  = downVector;  downDV.normalize();
  VnlVector normal  = vnl_cross_3d(rightVector, downVector);
  normal.normalize();

  if(spacing!=NULL)
  {
    rightDV *= (*spacing)[0];
    downDV  *= (*spacing)[1];
    normal  *= (*spacing)[2];
  }

  AffineTransform3D::Pointer transform = AffineTransform3D::New();
  Matrix3D matrix;
  matrix.GetVnlMatrix().set_column(0, rightDV);
  matrix.GetVnlMatrix().set_column(1, downDV);
  matrix.GetVnlMatrix().set_column(2, normal);
  transform->SetMatrix(matrix);
  transform->SetOffset(m_IndexToWorldTransform->GetOffset());

  ScalarType bounds[6] = { 0, width, 0, height, 0, 1 };
  this->SetBounds( bounds );

  this->SetIndexToWorldTransform( transform );
}
Example #2
0
  void PlaneGeometry::EnsurePerpendicularNormal( mitk::AffineTransform3D *transform )
  {
    /** \brief ensure column(2) of indexToWorldTransform-matrix to be perpendicular to plane, keep length and handedness. */

    VnlVector normal = vnl_cross_3d( transform->GetMatrix().GetVnlMatrix().get_column(0),
                                     transform->GetMatrix().GetVnlMatrix().get_column(1) );
    normal.normalize(); // Now normal is a righthand normal unit vector, perpendicular to the plane.

    ScalarType len = transform->GetMatrix().GetVnlMatrix().get_column(2).two_norm();
    if (len==0) { len = 1; }
    normal *= len;

    // Get the existing normal vector zed:
    vnl_vector_fixed<double, 3> zed = transform->GetMatrix().GetVnlMatrix().get_column(2);

    /** If det(matrix)<0, multiply normal vector by (-1) to keep geometry lefthanded. */
    if( vnl_determinant( transform->GetMatrix().GetVnlMatrix()) < 0 )
    {
      MITK_DEBUG << "EnsurePerpendicularNormal(): Lefthanded geometry preserved, rh-normal: [ " << normal << " ],";
      normal *= (-1.0);
      MITK_DEBUG << "lh-normal: [ " << normal << " ], original vector zed is: [ " << zed << " ]";
    }


    // Now lets compare and only replace if necessary and only then warn the user:

    // float epsilon is precise enough here, but we need to respect numerical condition:
    // Higham, N., 2002, Accuracy and Stability of Numerical Algorithms,
    // SIAM, page 37, 2nd edition:
    double feps = std::numeric_limits<float>::epsilon();
    double zedsMagnitude = zed.two_norm();
    feps = feps * zedsMagnitude * 2;

    /** Check if normal (3. column) was perpendicular: If not, replace with calculated normal vector: */
    if( normal != zed )
    {
      vnl_vector_fixed<double, 3> parallel;
      for ( unsigned int i = 0; i<3 ; ++i )
      {
        parallel[i] = normal[i] / zed[i]; // Remember linear algebra: checking for parallelity.
      }
      // Checking if really not paralell i.e. non-colinear vectors by comparing these floating point numbers:
      if(    (parallel[0]+feps < parallel[1] || feps+parallel[1] < parallel[0])
          && (parallel[0]+feps < parallel[2] || feps+parallel[2] < parallel[0]) )
      {
        MITK_WARN << "EnsurePerpendicularNormal(): Plane geometry was _/askew/_, so here it gets rectified by substituting"
                  << " the 3rd column of the indexToWorldMatrix with an appropriate normal vector: [ " << normal
                  << " ], original vector zed was: [ " << zed << " ].";

        Matrix3D matrix = transform->GetMatrix();
        matrix.GetVnlMatrix().set_column( 2, normal );
        transform->SetMatrix( matrix );
      }
    }
    else
    {
      // Nothing to do, 3rd column of indexToWorldTransformMatrix already was perfectly perpendicular.
    }
  }
Example #3
0
void
PlaneGeometry::SetMatrixByVectors( const VnlVector &rightVector,
  const VnlVector &downVector, ScalarType thickness )
{
  VnlVector normal = vnl_cross_3d(rightVector, downVector);
  normal.normalize();
  normal *= thickness;

  AffineTransform3D::Pointer transform = AffineTransform3D::New();
  Matrix3D matrix;
  matrix.GetVnlMatrix().set_column(0, rightVector);
  matrix.GetVnlMatrix().set_column(1, downVector);
  matrix.GetVnlMatrix().set_column(2, normal);
  transform->SetMatrix(matrix);
  transform->SetOffset(m_IndexToWorldTransform->GetOffset());
  SetIndexToWorldTransform(transform);
}
Example #4
0
  void
  PlaneGeometry::SetMatrixByVectors( const VnlVector &rightVector,
                                     const VnlVector &downVector, ScalarType thickness /* = 1.0 */ )
  {
    VnlVector normal = vnl_cross_3d(rightVector, downVector);
    normal.normalize();
    normal *= thickness;
    // Crossproduct vnl_cross_3d is always righthanded, but that is okay here
    // because in this method we create a new IndexToWorldTransform and
    // a negative thickness could still make it lefthanded.

    AffineTransform3D::Pointer transform = AffineTransform3D::New();
    Matrix3D matrix;
    matrix.GetVnlMatrix().set_column(0, rightVector);
    matrix.GetVnlMatrix().set_column(1, downVector);
    matrix.GetVnlMatrix().set_column(2, normal);
    transform->SetMatrix(matrix);
    transform->SetOffset(this->GetIndexToWorldTransform()->GetOffset());
    SetIndexToWorldTransform(transform);
  }
Example #5
0
unsigned int mitk::PlanePositionManagerService::AddNewPlanePosition ( const Geometry2D* plane, unsigned int sliceIndex )
{
    for (unsigned int i = 0; i < m_PositionList.size(); ++i)
    {
        if (m_PositionList[i] != 0)
        {
            bool isSameMatrix(true);
            bool isSameOffset(true);
            isSameOffset =  mitk::Equal(m_PositionList[i]->GetTransform()->GetOffset(), plane->GetIndexToWorldTransform()->GetOffset());
            if(!isSameOffset || sliceIndex != m_PositionList[i]->GetPos())
                continue;
            isSameMatrix = mitk::MatrixEqualElementWise(m_PositionList[i]->GetTransform()->GetMatrix(), plane->GetIndexToWorldTransform()->GetMatrix());
            if(isSameMatrix)
                return i;
        }

    }

    AffineTransform3D::Pointer transform = AffineTransform3D::New();
    Matrix3D matrix;
    matrix.GetVnlMatrix().set_column(0, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0));
    matrix.GetVnlMatrix().set_column(1, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1));
    matrix.GetVnlMatrix().set_column(2, plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2));
    transform->SetMatrix(matrix);
    transform->SetOffset(plane->GetIndexToWorldTransform()->GetOffset());

    mitk::Vector3D direction;
    direction[0] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[0];
    direction[1] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[1];
    direction[2] = plane->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2)[2];
    direction.Normalize();

    mitk::RestorePlanePositionOperation* newOp = new mitk::RestorePlanePositionOperation (OpRESTOREPLANEPOSITION, plane->GetExtent(0),
                                                                                          plane->GetExtent(1), plane->GetSpacing(), sliceIndex, direction, transform);

    m_PositionList.push_back( newOp );
    return GetNumberOfPlanePositions()-1;
}
Example #6
0
  void
  PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width, ScalarType height,
                                          const VnlVector &rightVector, const VnlVector &downVector,
                                          const Vector3D *spacing )
  {
    assert(width > 0);
    assert(height > 0);

    VnlVector rightDV = rightVector; rightDV.normalize();
    VnlVector downDV  = downVector;  downDV.normalize();
    VnlVector normal  = vnl_cross_3d(rightVector, downVector);
    normal.normalize();
    // Crossproduct vnl_cross_3d is always righthanded, but that is okay here
    // because in this method we create a new IndexToWorldTransform and
    // spacing with 1 or 3 negative components could still make it lefthanded.

    if(spacing!=nullptr)
    {
      rightDV *= (*spacing)[0];
      downDV  *= (*spacing)[1];
      normal  *= (*spacing)[2];
    }

    AffineTransform3D::Pointer transform = AffineTransform3D::New();
    Matrix3D matrix;
    matrix.GetVnlMatrix().set_column(0, rightDV);
    matrix.GetVnlMatrix().set_column(1, downDV);
    matrix.GetVnlMatrix().set_column(2, normal);
    transform->SetMatrix(matrix);
    transform->SetOffset(this->GetIndexToWorldTransform()->GetOffset());

    ScalarType bounds[6] = { 0, width, 0, height, 0, 1 };
    this->SetBounds( bounds );

    this->SetIndexToWorldTransform( transform );
  }
Example #7
0
void
PlaneGeometry::EnsurePerpendicularNormal(mitk::AffineTransform3D *transform)
{
  //ensure row(2) of transform to be perpendicular to plane, keep length.
  VnlVector normal = vnl_cross_3d(
    transform->GetMatrix().GetVnlMatrix().get_column(0),
    transform->GetMatrix().GetVnlMatrix().get_column(1) );

  normal.normalize();
  ScalarType len = transform->GetMatrix()
    .GetVnlMatrix().get_column(2).two_norm();

  if (len==0) len = 1;
  normal*=len;
  Matrix3D matrix = transform->GetMatrix();
  matrix.GetVnlMatrix().set_column(2, normal);
  transform->SetMatrix(matrix);
}
Example #8
0
void
PlaneGeometry::ExecuteOperation( Operation *operation )
{
  vtkTransform *transform = vtkTransform::New();
  transform->SetMatrix( m_VtkMatrix );

  switch ( operation->GetOperationType() )
  {
  case OpORIENT:
    {
      mitk::PlaneOperation *planeOp = dynamic_cast< mitk::PlaneOperation * >( operation );
      if ( planeOp == NULL )
      {
        return;
      }

      Point3D center = planeOp->GetPoint();

      Vector3D orientationVector = planeOp->GetNormal();
      Vector3D defaultVector;
      FillVector3D( defaultVector, 0.0, 0.0, 1.0 );

      Vector3D rotationAxis = itk::CrossProduct( orientationVector, defaultVector );
      //vtkFloatingPointType rotationAngle = acos( orientationVector[2] / orientationVector.GetNorm() );

      vtkFloatingPointType rotationAngle = atan2( (double) rotationAxis.GetNorm(), (double) (orientationVector * defaultVector) );
      rotationAngle *= 180.0 / vnl_math::pi;

      transform->PostMultiply();
      transform->Identity();
      transform->Translate( center[0], center[1], center[2] );
      transform->RotateWXYZ( rotationAngle, rotationAxis[0], rotationAxis[1], rotationAxis[2] );
      transform->Translate( -center[0], -center[1], -center[2] );
      break;
    }
  case OpRESTOREPLANEPOSITION:
    {
      RestorePlanePositionOperation *op = dynamic_cast< mitk::RestorePlanePositionOperation* >(operation);
      if(op == NULL)
      {
        return;
      }

      AffineTransform3D::Pointer transform2 = AffineTransform3D::New();
      Matrix3D matrix;
      matrix.GetVnlMatrix().set_column(0, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(0));
      matrix.GetVnlMatrix().set_column(1, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(1));
      matrix.GetVnlMatrix().set_column(2, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(2));
      transform2->SetMatrix(matrix);
      Vector3D offset = op->GetTransform()->GetOffset();
      transform2->SetOffset(offset);

      this->SetIndexToWorldTransform(transform2);
      ScalarType bounds[6] = {0, op->GetWidth(), 0, op->GetHeight(), 0 ,1 };
      this->SetBounds(bounds);
      TransferItkToVtkTransform();
      this->Modified();
      transform->Delete();
      return;

    }
  default:
    Superclass::ExecuteOperation( operation );
    transform->Delete();
    return;
  }

  m_VtkMatrix->DeepCopy(transform->GetMatrix());
  this->TransferVtkToItkTransform();
  this->Modified();
  transform->Delete();
}