コード例 #1
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: 0r/MITK
  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.
    }
  }
コード例 #2
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: AGrafmint/MITK
void
PlaneGeometry::InitializeStandardPlane( const VnlVector& rightVector,
  const VnlVector &downVector, const Vector3D *spacing )
{
  ScalarType width  = rightVector.magnitude();
  ScalarType height = downVector.magnitude();

  InitializeStandardPlane( width, height, rightVector, downVector, spacing );
}
コード例 #3
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: AGrafmint/MITK
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);
}
コード例 #4
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: AGrafmint/MITK
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);
}
コード例 #5
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: 0r/MITK
  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);
  }
コード例 #6
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: AGrafmint/MITK
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 );
}
コード例 #7
0
ファイル: mitkPlaneGeometry.cpp プロジェクト: 0r/MITK
  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 );
  }
コード例 #8
0
void mitk::ExtrudedContour::BuildGeometry()
{
  if(m_Contour.IsNull())
    return;

//  Initialize(1);

  Vector3D nullvector; nullvector.Fill(0.0);
  float xProj[3];
  unsigned int i;
  unsigned int numPts = 20; //m_Contour->GetNumberOfPoints();
  mitk::Contour::PathPointer path = m_Contour->GetContourPath();
  mitk::Contour::PathType::InputType cstart = path->StartOfInput();
  mitk::Contour::PathType::InputType cend   = path->EndOfInput();
  mitk::Contour::PathType::InputType cstep  = (cend-cstart)/numPts;
  mitk::Contour::PathType::InputType ccur;

  // Part I: guarantee/calculate legal vectors

  m_Vector.Normalize();
  itk2vtk(m_Vector, m_Normal);
  // check m_Vector
  if(mitk::Equal(m_Vector, nullvector) || m_AutomaticVectorGeneration)
  {
    if ( m_AutomaticVectorGeneration == false)
      itkWarningMacro("Extrusion vector is 0 ("<< m_Vector << "); trying to use normal of polygon");

    vtkPoints *loopPoints = vtkPoints::New();
    //mitk::Contour::PointsContainerIterator pointsIt = m_Contour->GetPoints()->Begin();
    double vtkpoint[3];

    unsigned int i=0;
    for(i=0, ccur=cstart; i<numPts; ++i, ccur+=cstep)
    {
      itk2vtk(path->Evaluate(ccur), vtkpoint);
      loopPoints->InsertNextPoint(vtkpoint);
    }

    // Make sure points define a loop with a m_Normal
    vtkPolygon::ComputeNormal(loopPoints, m_Normal);
    loopPoints->Delete();

    vtk2itk(m_Normal, m_Vector);
    if(mitk::Equal(m_Vector, nullvector))
    {
      itkExceptionMacro("Cannot calculate normal of polygon");
    }
  }
  // check m_RightVector
  if((mitk::Equal(m_RightVector, nullvector)) || (mitk::Equal(m_RightVector*m_Vector, 0.0)==false))
  {
    if(mitk::Equal(m_RightVector, nullvector))
    {
      itkDebugMacro("Right vector is 0. Calculating.");
    }
    else
    {
      itkWarningMacro("Right vector ("<<m_RightVector<<") not perpendicular to extrusion vector "<<m_Vector<<": "<<m_RightVector*m_Vector);
    }
    // calculate a legal m_RightVector
    if( mitk::Equal( m_Vector[1], 0.0f ) == false )
    {
      FillVector3D( m_RightVector, 1.0f, -m_Vector[0]/m_Vector[1], 0.0f );
      m_RightVector.Normalize();
    }
    else
    {
      FillVector3D( m_RightVector, 0.0f, 1.0f, 0.0f );
    }
  }

  // calculate down-vector
  VnlVector rightDV = m_RightVector.GetVnlVector(); rightDV.normalize(); vnl2vtk(rightDV, m_Right);
  VnlVector downDV  = vnl_cross_3d( m_Vector.GetVnlVector(), rightDV ); downDV.normalize();  vnl2vtk(downDV,  m_Down);

  // Part II: calculate plane as base for extrusion, project the contour
  // on this plane and store as polygon for IsInside test and BoundingBox calculation

  // initialize m_ProjectionPlane, yet with origin at 0
  m_ProjectionPlane->InitializeStandardPlane(rightDV, downDV);

  // create vtkPolygon from contour and simultaneously determine 2D bounds of
  // contour projected on m_ProjectionPlane
  //mitk::Contour::PointsContainerIterator pointsIt = m_Contour->GetPoints()->Begin();
  m_Polygon->Points->Reset();
  m_Polygon->Points->SetNumberOfPoints(numPts);
  m_Polygon->PointIds->Reset();
  m_Polygon->PointIds->SetNumberOfIds(numPts);
  mitk::Point2D pt2d;
  mitk::Point3D pt3d;
  mitk::Point2D min, max;
  min.Fill(ScalarTypeNumericTraits::max());
  max.Fill(ScalarTypeNumericTraits::min());
  xProj[2]=0.0;
  for(i=0, ccur=cstart; i<numPts; ++i, ccur+=cstep)
  {
    pt3d.CastFrom(path->Evaluate(ccur));
    m_ProjectionPlane->Map(pt3d, pt2d);
    xProj[0]=pt2d[0];
    if(pt2d[0]<min[0]) min[0]=pt2d[0];
    if(pt2d[0]>max[0]) max[0]=pt2d[0];
    xProj[1]=pt2d[1];
    if(pt2d[1]<min[1]) min[1]=pt2d[1];
    if(pt2d[1]>max[1]) max[1]=pt2d[1];
    m_Polygon->Points->SetPoint(i, xProj);
    m_Polygon->PointIds->SetId(i, i);
  }
  // shift parametric origin to (0,0)
  for(i=0; i<numPts; ++i)
  {
    double * pt = this->m_Polygon->Points->GetPoint(i);

    pt[0]-=min[0]; pt[1]-=min[1];
    itkDebugMacro( << i << ": (" << pt[0] << "," << pt[1] << "," << pt[2] << ")" );
  }
  this->m_Polygon->GetBounds(m_ProjectedContourBounds);
  //m_ProjectedContourBounds[4]=-1.0; m_ProjectedContourBounds[5]=1.0;

  // calculate origin (except translation along the normal) and bounds
  // of m_ProjectionPlane:
  //  origin is composed of the minimum x-/y-coordinates of the polygon,
  //  bounds from the extent of the polygon, both after projecting on the plane
  mitk::Point3D origin;
  m_ProjectionPlane->Map(min, origin);
  ScalarType bounds[6]={0, max[0]-min[0], 0, max[1]-min[1], 0, 1};
  m_ProjectionPlane->SetBounds(bounds);
  m_ProjectionPlane->SetOrigin(origin);

  // Part III: initialize geometry
  if(m_ClippingGeometry.IsNotNull())
  {
    ScalarType min_dist=ScalarTypeNumericTraits::max(), max_dist=ScalarTypeNumericTraits::min(), dist;
    unsigned char i;
    for(i=0; i<8; ++i)
    {
      dist = m_ProjectionPlane->SignedDistance( m_ClippingGeometry->GetCornerPoint(i) );
      if(dist<min_dist) min_dist=dist;
      if(dist>max_dist) max_dist=dist;
    }
    //incorporate translation along the normal into origin
    origin = origin+m_Vector*min_dist;
    m_ProjectionPlane->SetOrigin(origin);
    bounds[5]=max_dist-min_dist;
  }
  else
    bounds[5]=20;

  itk2vtk(origin, m_Origin);

  mitk::Geometry3D::Pointer g3d = GetGeometry( 0 );
  assert( g3d.IsNotNull() );
  g3d->SetBounds(bounds);
  g3d->SetIndexToWorldTransform(m_ProjectionPlane->GetIndexToWorldTransform());
  g3d->TransferItkToVtkTransform();

  ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New();
  timeGeometry->Initialize(g3d,1);
  SetTimeGeometry(timeGeometry);

}