Esempio n. 1
0
bool mitk::SegTool2D::DetermineAffectedImageSlice( const Image* image, const PlaneGeometry* plane, int& affectedDimension, int& affectedSlice )
{
  assert(image);
  assert(plane);

  // compare normal of plane to the three axis vectors of the image
  Vector3D normal       = plane->GetNormal();
  Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0);
  Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1);
  Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2);

  normal.Normalize();
  imageNormal0.Normalize();
  imageNormal1.Normalize();
  imageNormal2.Normalize();

  imageNormal0.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal0.Get_vnl_vector()) );
  imageNormal1.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal1.Get_vnl_vector()) );
  imageNormal2.Set_vnl_vector( vnl_cross_3d<ScalarType>(normal.Get_vnl_vector(),imageNormal2.Get_vnl_vector()) );

  double eps( 0.00001 );
  // axial
  if ( imageNormal2.GetNorm() <= eps )
  {
    affectedDimension = 2;
  }
  // sagittal
  else if ( imageNormal1.GetNorm() <= eps )
  {
    affectedDimension = 1;
  }
  // frontal
  else if ( imageNormal0.GetNorm() <= eps )
  {
    affectedDimension = 0;
  }
  else
  {
    affectedDimension = -1; // no idea
    return false;
  }

  // determine slice number in image
  Geometry3D* imageGeometry = image->GetGeometry(0);
  Point3D testPoint = imageGeometry->GetCenter();
  Point3D projectedPoint;
  plane->Project( testPoint, projectedPoint );

  Point3D indexPoint;

  imageGeometry->WorldToIndex( projectedPoint, indexPoint );
  affectedSlice = ROUND( indexPoint[affectedDimension] );
  MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice;

  // check if this index is still within the image
  if ( affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)) ) return false;

  return true;
}
Esempio n. 2
0
mitk::ScalarType mitk::Cone::GetVolume()
{
  Geometry3D* geometry = GetTimeSlicedGeometry();
  return   geometry->GetExtentInMM(0) * 0.5
    * geometry->GetExtentInMM(2) * 0.5
    * vnl_math::pi / 3.0
    * geometry->GetExtentInMM(1);
}
Esempio n. 3
0
bool mitk::AffineInteractor::ExecuteAction(Action* action, mitk::StateEvent const* stateEvent)
{
  bool ok = false;

  TimeSlicedGeometry* inputtimegeometry = GetData()->GetTimeSlicedGeometry();
  if (inputtimegeometry == NULL)
    return false;

  Geometry3D* geometry = inputtimegeometry->GetGeometry3D(m_TimeStep);

  mitk::DisplayPositionEvent const *event = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
  switch (action->GetActionId())
  {
  case AcCHECKELEMENT:
    {
      mitk::Point3D worldPoint = event->GetWorldPosition();
      /* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */
      mitk::BoolProperty::Pointer selected;
      mitk::ColorProperty::Pointer color;
      std::auto_ptr<StateEvent> newStateEvent;

      selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));

      if ( selected.IsNull() ) {
        selected = mitk::BoolProperty::New();
        m_DataNode->GetPropertyList()->SetProperty("selected", selected);
      }

      color = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("color"));

      if ( color.IsNull() ) {
        color = mitk::ColorProperty::New();
        m_DataNode->GetPropertyList()->SetProperty("color", color);
      }

      if (this->CheckSelected(worldPoint, m_TimeStep))
      {
        newStateEvent.reset(new mitk::StateEvent(EIDYES, stateEvent->GetEvent()));
        selected->SetValue(true);
        color->SetColor(1.0, 1.0, 0.0);
      }
      else
      {
        newStateEvent.reset(new mitk::StateEvent(EIDNO, stateEvent->GetEvent()));
        selected = mitk::BoolProperty::New(false);
        color->SetColor(0.0, 0.0, 1.0);

        /*
        mitk::BoundingObject* b = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
        if(b != NULL)
        {
          color = (b->GetPositive())? mitk::ColorProperty::New(0.0, 0.0, 1.0) : mitk::ColorProperty::New(1.0, 0.0, 0.0);  // if deselected, a boundingobject is colored according to its positive/negative state
        }
        else
          color = mitk::ColorProperty::New(1.0, 1.0, 1.0);   // if deselcted and no bounding object, color is white
        */
      }

      /* write new state (selected/not selected) to the property */
      this->HandleEvent( newStateEvent.get() );
      ok = true;
      break;
    }
  case AcADD:
    {
      mitk::Point3D worldPoint = event->GetWorldPosition();
      std::auto_ptr<StateEvent> newStateEvent;
      if (this->CheckSelected(worldPoint, m_TimeStep))
      {
        newStateEvent.reset(new mitk::StateEvent(EIDYES, event));
        m_DataNode->GetPropertyList()->SetProperty("selected", mitk::BoolProperty::New(true));  // TODO: Generate an Select Operation and send it to the undo controller ?
      }
      else  // if not selected, do nothing (don't deselect)
      {
        newStateEvent.reset(new mitk::StateEvent(EIDNO, event));
      }
      //call HandleEvent to leave the guard-state
      this->HandleEvent( newStateEvent.get() );
      ok = true;
      break;
    }
  case AcTRANSLATESTART:
  case AcROTATESTART:
  case AcSCALESTART:
    {
      m_LastMousePosition = event->GetWorldPosition();
      ok = true;
      break;
    }
  case AcTRANSLATE:
    {
      mitk::Point3D newPosition;
      newPosition = event->GetWorldPosition();
      newPosition -=  m_LastMousePosition.GetVectorFromOrigin();        // compute difference between actual and last mouse position
      m_LastMousePosition = event->GetWorldPosition();               // save current mouse position as last position

      /* create operation with position difference */
      mitk::PointOperation* doOp = new mitk::PointOperation(OpMOVE, newPosition, 0); // Index is not used here
      if (m_UndoEnabled)  //write to UndoMechanism
      {
        mitk::Point3D oldPosition=geometry->GetCornerPoint(0);

        PointOperation* undoOp = new mitk::PointOperation(OpMOVE, oldPosition, 0);
        OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
        m_UndoController->SetOperationEvent(operationEvent);
      }
      /* execute the Operation */
      geometry->ExecuteOperation(doOp);

      if (!m_UndoEnabled)
        delete doOp;

      ok = true;
      break;
    }
  case AcTRANSLATEEND:
    {
      m_UndoController->SetOperationEvent(new UndoStackItem("Move object"));
      m_DataNode->InvokeEvent(TranslateEvent());
      break;
    }
  case AcROTATE:
    {
      mitk::Point3D p = event->GetWorldPosition();

      mitk::Vector3D newPosition = p.GetVectorFromOrigin();

      mitk::Point3D dataPosition = geometry->GetCenter();

      newPosition = newPosition - dataPosition.GetVectorFromOrigin();  // calculate vector from center of the data object to the current mouse position

      mitk::Vector3D startPosition = m_LastMousePosition.GetVectorFromOrigin() - dataPosition.GetVectorFromOrigin();  // calculate vector from center of the data object to the last mouse position

      /* calculate rotation axis (by calculating the cross produkt of the vectors) */
      mitk::Vector3D rotationaxis;
      rotationaxis[0] =  startPosition[1] * newPosition[2] - startPosition[2] * newPosition[1];
      rotationaxis[1] =  startPosition[2] * newPosition[0] - startPosition[0] * newPosition[2];
      rotationaxis[2] =  startPosition[0] * newPosition[1] - startPosition[1] * newPosition[0];

      /* calculate rotation angle in degrees */
      mitk::ScalarType angle = atan2((mitk::ScalarType)rotationaxis.GetNorm(), (mitk::ScalarType) (newPosition * startPosition)) * (180/vnl_math::pi);
      m_LastMousePosition = p; // save current mouse position as last mouse position

      /* create operation with center of rotation, angle and axis and send it to the geometry and Undo controller */
      mitk::RotationOperation* doOp = new mitk::RotationOperation(OpROTATE, dataPosition, rotationaxis, angle);

      if (m_UndoEnabled)  //write to UndoMechanism
      {
        RotationOperation* undoOp = new mitk::RotationOperation(OpROTATE, dataPosition, rotationaxis, -angle);
        OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
        m_UndoController->SetOperationEvent(operationEvent);
      }
      /* execute the Operation */
      geometry->ExecuteOperation(doOp);

      if(!m_UndoEnabled)
        delete doOp;

      ok = true;
      break;
    }
  case AcROTATEEND:
    {
      m_UndoController->SetOperationEvent(new UndoStackItem("Rotate object"));
      m_DataNode->InvokeEvent(RotateEvent());
      break;
    }
  case AcSCALE:
    {
      mitk::Point3D p = event->GetWorldPosition();

      mitk::Vector3D v = p - m_LastMousePosition;
      /* calculate scale changes */
      mitk::Point3D newScale;
      newScale[0] = (geometry->GetAxisVector(0) * v) / geometry->GetExtentInMM(0);  // Scalarprodukt of normalized Axis
      newScale[1] = (geometry->GetAxisVector(1) * v) / geometry->GetExtentInMM(1);  // and direction vector of mouse movement
      newScale[2] = (geometry->GetAxisVector(2) * v) / geometry->GetExtentInMM(2);  // is the length of the movement vectors
      // projection onto the axis
      /* convert movement to local object coordinate system and mirror it to the positive quadrant */
      Vector3D start;
      Vector3D end;
      mitk::ScalarType convert[3];
      itk2vtk(m_LastMousePosition, convert);
      geometry->GetVtkTransform()->GetInverse()->TransformPoint(convert, convert);  // transform start point to local object coordinates
      start[0] = fabs(convert[0]);  start[1] = fabs(convert[1]);  start[2] = fabs(convert[2]);  // mirror it to the positive quadrant
      itk2vtk(p, convert);
      geometry->GetVtkTransform()->GetInverse()->TransformPoint(convert, convert);  // transform end point to local object coordinates
      end[0] = fabs(convert[0]);  end[1] = fabs(convert[1]);  end[2] = fabs(convert[2]);  // mirror it to the positive quadrant

      /* check if mouse movement is towards or away from the objects axes and adjust scale factors accordingly */
      Vector3D vLocal = start - end;
      newScale[0] = (vLocal[0] > 0.0) ? -fabs(newScale[0]) : +fabs(newScale[0]);
      newScale[1] = (vLocal[1] > 0.0) ? -fabs(newScale[1]) : +fabs(newScale[1]);
      newScale[2] = (vLocal[2] > 0.0) ? -fabs(newScale[2]) : +fabs(newScale[2]);

      m_LastMousePosition = p;  // update lastPosition for next mouse move

      /* generate Operation and send it to the receiving geometry */
      PointOperation* doOp = new mitk::PointOperation(OpSCALE, newScale, 0); // Index is not used here
      if (m_UndoEnabled)  //write to UndoMechanism
      {
        mitk::Point3D oldScaleData;
        oldScaleData[0] = -newScale[0];
        oldScaleData[1] = -newScale[1];
        oldScaleData[2] = -newScale[2];

        PointOperation* undoOp = new mitk::PointOperation(OpSCALE, oldScaleData, 0);
        OperationEvent *operationEvent = new OperationEvent(geometry, doOp, undoOp);
        m_UndoController->SetOperationEvent(operationEvent);
      }
      /* execute the Operation */
      geometry->ExecuteOperation(doOp);

      if(!m_UndoEnabled)
        delete doOp;

      /* Update Volume Property with new value */
      /*
      mitk::BoundingObject* b = dynamic_cast<mitk::BoundingObject*>(m_DataNode->GetData());
      if (b != NULL)
      {
        m_DataNode->GetPropertyList()->SetProperty("volume", FloatProperty::New(b->GetVolume()));
        //MITK_INFO << "Volume of Boundingobject is " << b->GetVolume()/1000.0 << " ml" << std::endl;
      }
      */
      ok = true;
      break;
    }
  case AcSCALEEND:
    {
      m_UndoController->SetOperationEvent(new UndoStackItem("Scale object"));
      m_DataNode->InvokeEvent(ScaleEvent());
      break;
    }
  default:
    ok = Superclass::ExecuteAction(action, stateEvent);//, objectEventId, groupEventId);
  }
  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
  return ok;
}
  void Geometry2DDataVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer)
  {
    SetVtkMapperImmediateModeRendering(m_EdgeMapper);
    SetVtkMapperImmediateModeRendering(m_BackgroundMapper);

    // Remove all actors from the assembly, and re-initialize it with the
    // edge actor
    m_ImageAssembly->GetParts()->RemoveAllItems();

    if ( !this->IsVisible(renderer) )
    {
      // visibility has explicitly to be set in the single actors
      // due to problems when using cell picking:
      // even if the assembly is invisible, the renderer contains
      // references to the assemblies parts. During picking the
      // visibility of each part is checked, and not only for the
      // whole assembly.
      m_ImageAssembly->VisibilityOff();
      m_EdgeActor->VisibilityOff();
      return;
    }

    // visibility has explicitly to be set in the single actors
    // due to problems when using cell picking:
    // even if the assembly is invisible, the renderer contains
    // references to the assemblies parts. During picking the
    // visibility of each part is checked, and not only for the
    // whole assembly.
    m_ImageAssembly->VisibilityOn();
    m_EdgeActor->VisibilityOn();

    Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput());

    if (input.IsNotNull() && (input->GetGeometry2D() != NULL))
    {
      SmartPointerProperty::Pointer surfacecreatorprop;
      surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(GetDataNode()->GetProperty("surfacegeometry", renderer));

      if ( (surfacecreatorprop.IsNull())
        || (surfacecreatorprop->GetSmartPointer().IsNull())
        || ((m_SurfaceCreator = dynamic_cast<Geometry2DDataToSurfaceFilter*>
             (surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull() ) )
        {
        m_SurfaceCreator->PlaceByGeometryOn();
        surfacecreatorprop = SmartPointerProperty::New( m_SurfaceCreator );
        GetDataNode()->SetProperty("surfacegeometry", surfacecreatorprop);
      }

      m_SurfaceCreator->SetInput(input);

      int res;
      if (GetDataNode()->GetIntProperty("xresolution", res, renderer))
      {
        m_SurfaceCreator->SetXResolution(res);
      }
      if (GetDataNode()->GetIntProperty("yresolution", res, renderer))
      {
        m_SurfaceCreator->SetYResolution(res);
      }

      double tubeRadius = 1.0; // Radius of tubular edge surrounding plane

      // Clip the Geometry2D with the reference geometry bounds (if available)
      if ( input->GetGeometry2D()->HasReferenceGeometry() )
      {
        Geometry3D *referenceGeometry =
            input->GetGeometry2D()->GetReferenceGeometry();

        BoundingBox::PointType boundingBoxMin, boundingBoxMax;
        boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum();
        boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum();

        if ( referenceGeometry->GetImageGeometry() )
        {
          for ( unsigned int i = 0; i < 3; ++i )
          {
            boundingBoxMin[i] -= 0.5;
            boundingBoxMax[i] -= 0.5;
          }
        }

        m_SurfaceCreatorPointsContainer->CreateElementAt( 0 ) = boundingBoxMin;
        m_SurfaceCreatorPointsContainer->CreateElementAt( 1 ) = boundingBoxMax;

        m_SurfaceCreatorBoundingBox->ComputeBoundingBox();

        m_SurfaceCreator->SetBoundingBox( m_SurfaceCreatorBoundingBox );

        tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0;
      }

      // If no reference geometry is available, clip with the current global
      // bounds
      else if (m_DataStorage.IsNotNull())
      {
        m_SurfaceCreator->SetBoundingBox(m_DataStorage->ComputeVisibleBoundingBox(NULL, "includeInBoundingBox"));
        tubeRadius = sqrt( m_SurfaceCreator->GetBoundingBox()->GetDiagonalLength2() ) / 450.0;
      }

      // Calculate the surface of the Geometry2D
      m_SurfaceCreator->Update();
      Surface *surface = m_SurfaceCreator->GetOutput();

      // Check if there's something to display, otherwise return
      if ( (surface->GetVtkPolyData() == 0 )
        || (surface->GetVtkPolyData()->GetNumberOfCells() == 0) )
        {
        m_ImageAssembly->VisibilityOff();
        return;
      }

      // add a graphical representation of the surface normals if requested
      DataNode* node = this->GetDataNode();
      bool displayNormals = false;
      bool colorTwoSides = false;
      bool invertNormals = false;
      node->GetBoolProperty("draw normals 3D", displayNormals, renderer);
      node->GetBoolProperty("color two sides", colorTwoSides, renderer);
      node->GetBoolProperty("invert normals", invertNormals, renderer);

      //if we want to draw the display normals or render two sides we have to get the colors
      if( displayNormals || colorTwoSides )
      {
        //get colors
        float frontColor[3] = { 0.0, 0.0, 1.0 };
        node->GetColor( frontColor, renderer, "front color" );
        float backColor[3] = { 1.0, 0.0, 0.0 };
        node->GetColor( backColor, renderer, "back color" );

        if ( displayNormals )
        {
          m_NormalsTransformer->SetInput( surface->GetVtkPolyData() );
          m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) );

          m_FrontHedgeHog->SetInput( m_NormalsTransformer->GetOutput() );
          m_FrontHedgeHog->SetVectorModeToUseNormal();
          m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 );

          m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] );

          m_BackHedgeHog->SetInput( m_NormalsTransformer->GetOutput() );
          m_BackHedgeHog->SetVectorModeToUseNormal();
          m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 );

          m_BackNormalsActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] );

          //if there is no actor added yet, add one
          if ( !m_NormalsActorAdded )
          {
            m_Prop3DAssembly->AddPart( m_FrontNormalsActor );
            m_Prop3DAssembly->AddPart( m_BackNormalsActor );
            m_NormalsActorAdded = true;
          }
        }
        //if we don't want to display normals AND there is an actor added remove the actor
        else if ( m_NormalsActorAdded )
        {
          m_Prop3DAssembly->RemovePart( m_FrontNormalsActor );
          m_Prop3DAssembly->RemovePart( m_BackNormalsActor );
          m_NormalsActorAdded = false;
        }

        if ( colorTwoSides )
        {
          if ( !invertNormals )
          {
            m_BackgroundActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] );
            m_BackgroundActor->GetBackfaceProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] );
          }
          else
          {
            m_BackgroundActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] );
            m_BackgroundActor->GetBackfaceProperty()->SetColor( backColor[0], backColor[1], backColor[2] );
          }
        }
      }

      // Add black background for all images (which may be transparent)
      m_BackgroundMapper->SetInput( surface->GetVtkPolyData() );
      m_ImageAssembly->AddPart( m_BackgroundActor );

      LayerSortedActorList layerSortedActors;

      // Traverse the data tree to find nodes resliced by ImageMapperGL2D
      mitk::NodePredicateOr::Pointer p = mitk::NodePredicateOr::New();
      //use a predicate to get all data nodes which are "images" or inherit from mitk::Image
      mitk::TNodePredicateDataType< mitk::Image >::Pointer predicateAllImages = mitk::TNodePredicateDataType< mitk::Image >::New();
      mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetSubset(predicateAllImages);
      //process all found images
      for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it)
      {

        DataNode *node = it->Value();
        if (node != NULL)
          this->ProcessNode(node, renderer, surface, layerSortedActors);
      }

      // Add all image actors to the assembly, sorted according to
      // layer property
      LayerSortedActorList::iterator actorIt;
      for ( actorIt = layerSortedActors.begin(); actorIt != layerSortedActors.end(); ++actorIt )
      {
        m_ImageAssembly->AddPart( actorIt->second );
      }

      // Configurate the tube-shaped frame: size according to the surface
      // bounds, color as specified in the plane's properties
      vtkPolyData *surfacePolyData = surface->GetVtkPolyData();
      m_Cleaner->SetInput(surfacePolyData);
      m_EdgeTransformer->SetTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) );

      // Adjust the radius according to extent
      m_EdgeTuber->SetRadius( tubeRadius );

      // Get the plane's color and set the tube properties accordingly
      ColorProperty::Pointer colorProperty;
      colorProperty = dynamic_cast<ColorProperty*>(this->GetDataNode()->GetProperty( "color" ));
      if ( colorProperty.IsNotNull() )
      {
        const Color& color = colorProperty->GetColor();
        m_EdgeActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue());
      }
      else
      {
        m_EdgeActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 );
      }

      m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) );
    }

    VtkRepresentationProperty* representationProperty;
    this->GetDataNode()->GetProperty(representationProperty, "material.representation", renderer);
    if ( representationProperty != NULL )
      m_BackgroundActor->GetProperty()->SetRepresentation( representationProperty->GetVtkRepresentation() );
  }
Esempio n. 5
0
bool mitk::WiiMoteInteractor::FixedRotationAndTranslation(const mitk::WiiMoteAllDataEvent* wiiMoteEvent)
{

  Geometry3D* geometry = this->TransformCurrentDataInGeometry3D();

  m_OrientationX = wiiMoteEvent->GetOrientationX();
  m_OrientationY = wiiMoteEvent->GetOrientationY();
  m_OrientationZ = wiiMoteEvent->GetOrientationZ();

  ScalarType pitchSpeed = wiiMoteEvent->GetPitchSpeed();
  ScalarType rollSpeed = wiiMoteEvent->GetRollSpeed();
  ScalarType yawSpeed = wiiMoteEvent->GetYawSpeed();

  // angle x
  if(std::abs(pitchSpeed) < 200)
    pitchSpeed = 0;

  m_xAngle += (pitchSpeed / 1500);

  // angle y
  if(std::abs(rollSpeed) < 200)
    rollSpeed = 0;

  m_yAngle += (rollSpeed / 1500);

  // angle z
  if(std::abs(yawSpeed) < 200)
    yawSpeed = 0;

  m_zAngle += (yawSpeed / 1500);

  if(  std::abs(pitchSpeed) > 200
    || std::abs(rollSpeed) > 200
    || std::abs(yawSpeed) > 200)
  {
    m_InRotation = true;
    //// depending on a combination of the
    //// orientation the angleX wil be altered
    //// because the range from roll is limited
    //// range: -90° to 90° by the wiimote
    //if(wiiMoteEvent->GetOrientationZ() < 0)
    //{
    //  // value is positive
    //  if(wiiMoteEvent->GetOrientationX() > 0)
    //  {
    //    // the degree measured decreases after it reaches
    //    // in the "real" world the 90 degree angle
    //    // (rotation to the right side)
    //    // therefore it needs to artificially increased

    //    // measured value drops -> computated angle increases
    //    angleX = 90 - angleX;

    //    // now add the "new" angle to 90 degree threshold
    //    angleX += 90;
    //  }
    //  // value is negative
    //  else if(wiiMoteEvent->GetOrientationX() < 0)
    //  {
    //    // the degree measured increases after it reaches
    //    // in the "real" world -90 degree
    //    // (rotation to the left side)
    //    // therefore it needs to be artificially decreased
    //    // (example -90 -> -70, but -110 is needed)

    //    // measured value increases -> computated angle decreases
    //    angleX = 90 + angleX;

    //    // invert the algebraic sign, because it is the "negative"
    //    // side of the rotation
    //    angleX = -angleX;

    //    // now add the negative value to the -90 degree threshold
    //    // to decrease the value further
    //    angleX -= 90;
    //  }
    //  else if(wiiMoteEvent->GetOrientationX() == 0)
    //  {
    //    // i.e. wiimote is flipped upside down
    //    angleX = 180;
    //  }
    //}

    //rotation
    vtkTransform *vtkTransform = vtkTransform::New();

    //copy m_vtkMatrix to m_VtkIndexToWorldTransform
    geometry->TransferItkToVtkTransform();

    //////m_VtkIndexToWorldTransform as vtkLinearTransform*
    vtkTransform->SetMatrix(geometry->GetVtkTransform()->GetMatrix());

    // rotation from center is different
    // from rotation while translated
    // hence one needs the center of the object
    Point3D center = geometry->GetOrigin();

    vtkTransform->PostMultiply();
    vtkTransform->Translate(-center[0], -center[1], -center[2]);
    //vtkTransform->RotateWXYZ(angle, rotationVector[0], rotationVector[1], rotationVector[2]);

    vtkTransform->RotateX(m_xAngle);

    vtkTransform->RotateY(m_zAngle);

    vtkTransform->RotateZ(m_yAngle);

    vtkTransform->Translate(center[0], center[1], center[2]);
    vtkTransform->PreMultiply();

    geometry->SetIndexToWorldTransformByVtkMatrix(vtkTransform->GetMatrix());
    geometry->Modified();

    // indicate modification of data tree node
    m_DataNode->Modified();

    vtkTransform->Delete();

    //update rendering
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();

    return true;

  }
  else if(!m_InRotation)
  {
    float xValue = wiiMoteEvent->GetXAcceleration();
    float yValue = wiiMoteEvent->GetYAcceleration();
    float zValue = wiiMoteEvent->GetZAcceleration();

    float pitch = wiiMoteEvent->GetPitch();
    float roll = wiiMoteEvent->GetRoll();

    // substracts the proportionate force
    // applied by gravity depending on the
    // orientation

    float sinP = sin(pitch/180.0 * M_PI);
    float cosP = cos(pitch/180.0 * M_PI);
    float sinR = sin(roll/180.0 * M_PI);
    float cosR = cos(roll/180.0 * M_PI);

    // x acceleration
    if(m_OrientationZ >= 0)
      xValue = xValue - sinR * cosP;
    else
      xValue = xValue + sinR * cosP;

    // against drift
    if(std::abs(xValue) < 0.2)
      xValue = 0;

    // y acceleration
    yValue = yValue + sinP;

    // against drift
    if(std::abs(yValue) < 0.2)
      yValue = 0;

    // z acceleration
    zValue = zValue - cosP * cosR;

    // against drift
    if(std::abs(zValue) < 0.3)
      zValue = 0;

    // simple integration over time
    // resulting in velocity
    switch(m_TranslationMode)
    {
    case 1:
      m_xVelocity -= xValue;
      m_yVelocity -= yValue;
      m_zVelocity += zValue;


      // 1 = movement to the right
      // initially starts with negative acceleration
      // 2 = movement to the left
      // initially starts with positive acceleration
      if(  m_xVelocity > 0 && xValue > 0  // 1
        || m_xVelocity < 0 && xValue < 0) // 2
      {
        m_xVelocity += xValue;
      }
      else if( m_xVelocity > 0 && xValue < 0  // 1
        || m_xVelocity < 0 && xValue > 0)     // 2
      {
        m_xVelocity -= xValue;
      }
      break;

    case 3:

      m_yVelocity -= yValue;
      break;
    case 4:

      // 1 = movement up
      // initially starts with positive acceleration
      // 2 = movement down
      // initially starts with negative acceleration
      if(  m_zVelocity > 0 && zValue < 0  // 1
        || m_zVelocity < 0 && zValue > 0) // 2
      {
        m_zVelocity -= zValue;
      }
      else if(m_zVelocity > 0 && zValue > 0 // 1
        || m_zVelocity < 0 && zValue < 0)   // 2
      {
        m_zVelocity += zValue;
      }
      break;
    }

    // sets the mode of the translation
    // depending on the initial velocity
    if(  std::abs(m_xVelocity) > std::abs(m_yVelocity)
      && std::abs(m_xVelocity) > std::abs(m_zVelocity) )
    {
      m_TranslationMode = 2;
      m_yVelocity = 0;
      m_zVelocity = 0;
    }
    else if( std::abs(m_yVelocity) > std::abs(m_xVelocity)
      && std::abs(m_yVelocity) > std::abs(m_zVelocity) )
    {
      m_TranslationMode = 3;
      m_xVelocity = 0;
      m_zVelocity = 0;
    }
    else if(std::abs(m_zVelocity) > std::abs(m_xVelocity)
      && std::abs(m_zVelocity) > std::abs(m_yVelocity) )
    {
      m_TranslationMode = 4;
      m_xVelocity = 0;
      m_yVelocity = 0;
    }

    // translation
    mitk::Vector3D movementVector;
    movementVector.SetElement(0,m_xVelocity);
    movementVector.SetElement(1,m_yVelocity);
    movementVector.SetElement(2,m_zVelocity);

    geometry->Translate(movementVector);

    // indicate modification of data tree node
    m_DataNode->Modified();

    // update rendering
    mitk::RenderingManager::GetInstance()->RequestUpdateAll();

    return true;
  }

  return false;
}
void mitk::SurfaceToImageFilter::Stencil3DImage(int time)
{
  const mitk::TimeGeometry *surfaceTimeGeometry = GetInput()->GetTimeGeometry();
  const mitk::TimeGeometry *imageTimeGeometry = GetImage()->GetTimeGeometry();

  // Convert time step from image time-frame to surface time-frame
  mitk::TimePointType matchingTimePoint = imageTimeGeometry->TimeStepToTimePoint(time);
  mitk::TimeStepType surfaceTimeStep = surfaceTimeGeometry->TimePointToTimeStep(matchingTimePoint);

  vtkPolyData * polydata = ( (mitk::Surface*)GetInput() )->GetVtkPolyData( surfaceTimeStep );

  vtkSmartPointer<vtkTransformPolyDataFilter> move=vtkTransformPolyDataFilter::New();
  move->SetInputData(polydata);
  move->ReleaseDataFlagOn();

  vtkSmartPointer<vtkTransform> transform=vtkTransform::New();
  Geometry3D* geometry = surfaceTimeGeometry->GetGeometryForTimeStep( surfaceTimeStep );
  geometry->TransferItkToVtkTransform();
  transform->PostMultiply();
  transform->Concatenate(geometry->GetVtkTransform()->GetMatrix());
  // take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below.
  Geometry3D* imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time);
  imageGeometry->TransferItkToVtkTransform();
  transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse());
  move->SetTransform(transform);

  vtkSmartPointer<vtkPolyDataNormals> normalsFilter = vtkPolyDataNormals::New();
  normalsFilter->SetFeatureAngle(50);
  normalsFilter->SetConsistency(1);
  normalsFilter->SetSplitting(1);
  normalsFilter->SetFlipNormals(0);
  normalsFilter->ReleaseDataFlagOn();

  normalsFilter->SetInputConnection(move->GetOutputPort() );

  vtkSmartPointer<vtkPolyDataToImageStencil> surfaceConverter = vtkPolyDataToImageStencil::New();
  surfaceConverter->SetTolerance( 0.0 );
  surfaceConverter->ReleaseDataFlagOn();

  surfaceConverter->SetInputConnection( normalsFilter->GetOutputPort() );

  mitk::Image::Pointer binaryImage = mitk::Image::New();

  if (m_MakeOutputBinary)
  {
    binaryImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *this->GetImage()->GetTimeGeometry());

    unsigned int size = sizeof(unsigned char);
    for (unsigned int i = 0; i < binaryImage->GetDimension(); ++i)
      size *= binaryImage->GetDimension(i);

    mitk::ImageWriteAccessor accessor( binaryImage );
    memset( accessor.GetData(), 1, size );
  }

  vtkImageData *image = m_MakeOutputBinary
    ? binaryImage->GetVtkImageData(time)
    : const_cast<mitk::Image *>(this->GetImage())->GetVtkImageData(time);

  // Create stencil and use numerical minimum of pixel type as background value
  vtkSmartPointer<vtkImageStencil> stencil = vtkImageStencil::New();
  stencil->SetInputData(image);
  stencil->ReverseStencilOff();
  stencil->ReleaseDataFlagOn();
  stencil->SetStencilConnection(surfaceConverter->GetOutputPort());

  stencil->SetBackgroundValue(m_MakeOutputBinary ? 0 : m_BackgroundValue);
  stencil->Update();

  mitk::Image::Pointer output = this->GetOutput();
  output->SetVolume( stencil->GetOutput()->GetScalarPointer(), time );
  MITK_INFO << "stencil ref count: " << stencil->GetReferenceCount() << std::endl;
}
Esempio n. 7
0
std::string
mitk::TestDICOMLoading::DumpImageInformation( const Image* image )
{
  std::stringstream result;

  if (image == NULL) return result.str();

  SetDefaultLocale();

  // basic image data
  DumpLine( "Pixeltype",    TypeIDToString( (image->GetPixelType().GetTypeId()) ));
  DumpLine( "BitsPerPixel", image->GetPixelType().GetBpe() );
  DumpLine( "Dimension",    image->GetDimension() );

  result << "Dimensions: ";
  for (unsigned int dim = 0; dim < image->GetDimension(); ++dim)
    result << image->GetDimension(dim) << " ";
  result << "\n";

  // geometry data
  result << "Geometry: \n";
  Geometry3D* geometry = image->GetGeometry();
  if (geometry)
  {
    AffineTransform3D* transform = geometry->GetIndexToWorldTransform();
    if (transform)
    {
      result << "  " << "Matrix: ";
      const AffineTransform3D::MatrixType& matrix = transform->GetMatrix();
      for (unsigned int i = 0; i < 3; ++i)
        for (unsigned int j = 0; j < 3; ++j)
          result << matrix[i][j] << " ";
      result << "\n";

      result << "  " << "Offset: ";
      const AffineTransform3D::OutputVectorType& offset = transform->GetOffset();
      for (unsigned int i = 0; i < 3; ++i)
          result << offset[i] << " ";
      result << "\n";

      result << "  " << "Center: ";
      const AffineTransform3D::InputPointType& center = transform->GetCenter();
      for (unsigned int i = 0; i < 3; ++i)
          result << center[i] << " ";
      result << "\n";

      result << "  " << "Translation: ";
      const AffineTransform3D::OutputVectorType& translation = transform->GetTranslation();
      for (unsigned int i = 0; i < 3; ++i)
          result << translation[i] << " ";
      result << "\n";

      result << "  " << "Scale: ";
      const double* scale = transform->GetScale();
      for (unsigned int i = 0; i < 3; ++i)
          result << scale[i] << " ";
      result << "\n";

      result << "  " << "Origin: ";
      const Point3D& origin = geometry->GetOrigin();
      for (unsigned int i = 0; i < 3; ++i)
          result << origin[i] << " ";
      result << "\n";

      result << "  " << "Spacing: ";
      const Vector3D& spacing = geometry->GetSpacing();
      for (unsigned int i = 0; i < 3; ++i)
          result << spacing[i] << " ";
      result << "\n";

      result << "  " << "TimeBounds: ";
      const TimeBounds timeBounds = geometry->GetTimeBounds();
      for (unsigned int i = 0; i < 2; ++i)
          result << timeBounds[i] << " ";
      result << "\n";


    }
  }

  ResetUserLocale();

  return result.str();
}
void mitk::Geometry2DDataToSurfaceFilter::GenerateOutputInformation()
{
  mitk::Geometry2DData::ConstPointer input = this->GetInput();
  mitk::Surface::Pointer output = this->GetOutput();

  if ( input.IsNull() || (input->GetGeometry2D() == NULL)
    || (input->GetGeometry2D()->IsValid() == false)
    || (m_UseBoundingBox && (m_BoundingBox.IsNull() || (m_BoundingBox->GetDiagonalLength2() < mitk::eps))) )
  {
    return;
  }

  Point3D origin;
  Point3D right, bottom;

  vtkPolyData *planeSurface = NULL;


  // Does the Geometry2DData contain a PlaneGeometry?
  if ( dynamic_cast< PlaneGeometry * >( input->GetGeometry2D() ) != NULL )
  {
    mitk::PlaneGeometry *planeGeometry =
      dynamic_cast< PlaneGeometry * >( input->GetGeometry2D() );

    if ( m_PlaceByGeometry )
    {
      // Let the output use the input geometry to appropriately transform the
      // coordinate system.
      mitk::Geometry3D::TransformType *affineTransform =
        planeGeometry->GetIndexToWorldTransform();

      TimeGeometry *timeGeometry = output->GetTimeGeometry();
      Geometry3D *geometrie3d = timeGeometry->GetGeometryForTimeStep( 0 );
      geometrie3d->SetIndexToWorldTransform( affineTransform );
    }

    if ( !m_UseBoundingBox)
    {
      // We do not have a bounding box, so no clipping is required.

      if ( m_PlaceByGeometry )
      {
        // Derive coordinate axes and origin from input geometry extent
        origin.Fill( 0.0 );
        FillVector3D( right,  planeGeometry->GetExtent(0), 0.0, 0.0 );
        FillVector3D( bottom, 0.0, planeGeometry->GetExtent(1), 0.0 );
      }
      else
      {
        // Take the coordinate axes and origin directly from the input geometry.
        origin = planeGeometry->GetOrigin();
        right = planeGeometry->GetCornerPoint( false, true );
        bottom = planeGeometry->GetCornerPoint( true, false );
      }

      // Since the plane is planar, there is no need to subdivide the grid
      // (cf. AbstractTransformGeometry case)
      m_PlaneSource->SetXResolution( 1 );
      m_PlaneSource->SetYResolution( 1 );

      m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] );
      m_PlaneSource->SetPoint1( right[0], right[1], right[2] );
      m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] );

      m_PlaneSource->Update();
      planeSurface = m_PlaneSource->GetOutput();

    }
    else
    {
      // Set up a cube with the extent and origin of the bounding box. This
      // cube will be clipped by a plane later on. The intersection of the
      // cube and the plane will be the surface we are interested in. Note
      // that the bounding box needs to be explicitly specified by the user
      // of this class, since it is not necessarily clear from the data
      // available herein which bounding box to use. In most cases, this
      // would be the bounding box of the input geometry's reference
      // geometry, but this is not an inevitable requirement.
      mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum();
      mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum();
      mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter();

      m_CubeSource->SetXLength( boundingBoxMax[0] - boundingBoxMin[0] );
      m_CubeSource->SetYLength( boundingBoxMax[1] - boundingBoxMin[1] );
      m_CubeSource->SetZLength( boundingBoxMax[2] - boundingBoxMin[2] );
      m_CubeSource->SetCenter(
        boundingBoxCenter[0],
        boundingBoxCenter[1],
        boundingBoxCenter[2] );


      // Now we have to transform the cube, so that it will cut our plane
      // appropriately. (As can be seen below, the plane corresponds to the
      // z-plane in the coordinate system and is *not* transformed.) Therefore,
      // we get the inverse of the plane geometry's transform and concatenate
      // it with the transform of the reference geometry, if available.
      m_Transform->Identity();
      m_Transform->Concatenate(
        planeGeometry->GetVtkTransform()->GetLinearInverse()
      );

      Geometry3D *referenceGeometry = planeGeometry->GetReferenceGeometry();
      if ( referenceGeometry )
      {
        m_Transform->Concatenate(
          referenceGeometry->GetVtkTransform()
        );
      }

      // Transform the cube accordingly (s.a.)
      m_PolyDataTransformer->SetInputConnection( m_CubeSource->GetOutputPort() );
      m_PolyDataTransformer->SetTransform( m_Transform );

      // Initialize the plane to clip the cube with, as lying on the z-plane
      m_Plane->SetOrigin( 0.0, 0.0, 0.0 );
      m_Plane->SetNormal( 0.0, 0.0, 1.0 );

      // Cut the plane with the cube.
      m_PlaneCutter->SetInputConnection( m_PolyDataTransformer->GetOutputPort() );
      m_PlaneCutter->SetCutFunction( m_Plane );

      // The output of the cutter must be converted into appropriate poly data.
      m_PlaneStripper->SetInputConnection( m_PlaneCutter->GetOutputPort() );
      m_PlaneStripper->Update();

      if ( m_PlaneStripper->GetOutput()->GetNumberOfPoints() < 3 )
      {
        return;
      }

      m_PlanePolyData->SetPoints( m_PlaneStripper->GetOutput()->GetPoints() );
      m_PlanePolyData->SetPolys( m_PlaneStripper->GetOutput()->GetLines() );

      m_PlaneTriangler->SetInputData( m_PlanePolyData );


      // Get bounds of the resulting surface and use it to generate the texture
      // mapping information
      m_PlaneTriangler->Update();
      m_PlaneTriangler->GetOutput()->ComputeBounds();
      double *surfaceBounds =
        m_PlaneTriangler->GetOutput()->GetBounds();

      origin[0] = surfaceBounds[0];
      origin[1] = surfaceBounds[2];
      origin[2] = surfaceBounds[4];

      right[0] = surfaceBounds[1];
      right[1] = surfaceBounds[2];
      right[2] = surfaceBounds[4];

      bottom[0] = surfaceBounds[0];
      bottom[1] = surfaceBounds[3];
      bottom[2] = surfaceBounds[4];

      // Now we tell the data how it shall be textured afterwards;
      // description see above.
      m_TextureMapToPlane->SetInputConnection( m_PlaneTriangler->GetOutputPort() );
      m_TextureMapToPlane->AutomaticPlaneGenerationOn();
      m_TextureMapToPlane->SetOrigin( origin[0], origin[1], origin[2] );
      m_TextureMapToPlane->SetPoint1( right[0], right[1], right[2] );
      m_TextureMapToPlane->SetPoint2( bottom[0], bottom[1], bottom[2] );

      // Need to call update so that output data and bounds are immediately
      // available
      m_TextureMapToPlane->Update();


      // Return the output of this generation process
      planeSurface = dynamic_cast< vtkPolyData * >(
        m_TextureMapToPlane->GetOutput()
      );
    }
  }

  // Does the Geometry2DData contain an AbstractTransformGeometry?
  else if ( mitk::AbstractTransformGeometry *abstractGeometry =
    dynamic_cast< AbstractTransformGeometry * >( input->GetGeometry2D() ) )
  {
    // In the case of an AbstractTransformGeometry (which holds a possibly
    // non-rigid transform), we proceed slightly differently: since the
    // plane can be arbitrarily deformed, we need to transform it by the
    // abstract transform before clipping it. The setup for this is partially
    // done in the constructor.
    origin = abstractGeometry->GetPlane()->GetOrigin();
    right = origin + abstractGeometry->GetPlane()->GetAxisVector( 0 );
    bottom = origin + abstractGeometry->GetPlane()->GetAxisVector( 1 );

    // Define the plane
    m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] );
    m_PlaneSource->SetPoint1( right[0], right[1], right[2] );
    m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] );

    // Set the plane's resolution (unlike for non-deformable planes, the plane
    // grid needs to have a certain resolution so that the deformation has the
    // desired effect).
    if ( m_UseGeometryParametricBounds )
    {
      m_PlaneSource->SetXResolution(
        (int)abstractGeometry->GetParametricExtent(0)
      );
      m_PlaneSource->SetYResolution(
        (int)abstractGeometry->GetParametricExtent(1)
      );
    }
    else
    {
      m_PlaneSource->SetXResolution( m_XResolution );
      m_PlaneSource->SetYResolution( m_YResolution );
    }
    if ( m_PlaceByGeometry )
    {
      // Let the output use the input geometry to appropriately transform the
      // coordinate system.
      mitk::Geometry3D::TransformType *affineTransform =
        abstractGeometry->GetIndexToWorldTransform();

      TimeGeometry *timeGeometry = output->GetTimeGeometry();
      Geometry3D *g3d = timeGeometry->GetGeometryForTimeStep( 0 );
      g3d->SetIndexToWorldTransform( affineTransform );

      vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New();
      composedResliceTransform->Identity();
      composedResliceTransform->Concatenate(
        abstractGeometry->GetVtkTransform()->GetLinearInverse() );
      composedResliceTransform->Concatenate(
        abstractGeometry->GetVtkAbstractTransform()
        );
      // Use the non-rigid transform for transforming the plane.
      m_VtkTransformPlaneFilter->SetTransform(
        composedResliceTransform
      );
    }
    else
    {
      // Use the non-rigid transform for transforming the plane.
      m_VtkTransformPlaneFilter->SetTransform(
        abstractGeometry->GetVtkAbstractTransform()
      );
    }

    if ( m_UseBoundingBox )
    {
      mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum();
      mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum();
      //mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter();

      m_Box->SetXMin( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2] );
      m_Box->SetXMax( boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2] );
    }
    else
    {
      // Plane will not be clipped
      m_Box->SetXMin( -10000.0, -10000.0, -10000.0 );
      m_Box->SetXMax( 10000.0, 10000.0, 10000.0 );
    }

    m_Transform->Identity();
    m_Transform->Concatenate( input->GetGeometry2D()->GetVtkTransform() );
    m_Transform->PreMultiply();

    m_Box->SetTransform( m_Transform );

    m_PlaneClipper->SetInputConnection(m_VtkTransformPlaneFilter->GetOutputPort() );
    m_PlaneClipper->SetClipFunction( m_Box );
    m_PlaneClipper->GenerateClippedOutputOff(); // important to NOT generate normals data for clipped part
    m_PlaneClipper->InsideOutOn();
    m_PlaneClipper->SetValue( 0.0 );
    m_PlaneClipper->Update();

    planeSurface = m_PlaneClipper->GetOutput();
  }

  m_NormalsUpdater->SetInputData( planeSurface );
  m_NormalsUpdater->AutoOrientNormalsOn(); // that's the trick! Brings consistency between
                                          //  normals direction and front/back faces direction (see bug 1440)
  m_NormalsUpdater->ComputePointNormalsOn();
  m_NormalsUpdater->Update();

  output->SetVtkPolyData( m_NormalsUpdater->GetOutput() );
  output->CalculateBoundingBox();
}
void mitk::SurfaceToImageFilter::Stencil3DImage(int time)
{
  const mitk::TimeSlicedGeometry *surfaceTimeGeometry = GetInput()->GetTimeSlicedGeometry();
  const mitk::TimeSlicedGeometry *imageTimeGeometry = GetImage()->GetTimeSlicedGeometry();

  // Convert time step from image time-frame to surface time-frame
  int surfaceTimeStep = surfaceTimeGeometry->TimeStepToTimeStep( imageTimeGeometry, time );
  
  vtkPolyData * polydata = ( (mitk::Surface*)GetInput() )->GetVtkPolyData( surfaceTimeStep );

  vtkTransformPolyDataFilter * move=vtkTransformPolyDataFilter::New();
  move->SetInput(polydata);
  move->ReleaseDataFlagOn();

  vtkTransform *transform=vtkTransform::New();
  Geometry3D* geometry = surfaceTimeGeometry->GetGeometry3D( surfaceTimeStep );
  geometry->TransferItkToVtkTransform();
  transform->PostMultiply();
  transform->Concatenate(geometry->GetVtkTransform()->GetMatrix());
  // take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below.
  Geometry3D* imageGeometry = imageTimeGeometry->GetGeometry3D(time);
  imageGeometry->TransferItkToVtkTransform();
  transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse());
  move->SetTransform(transform);
  transform->Delete();

  vtkPolyDataNormals * normalsFilter = vtkPolyDataNormals::New();
  normalsFilter->SetFeatureAngle(50);
  normalsFilter->SetConsistency(1);
  normalsFilter->SetSplitting(1);
  normalsFilter->SetFlipNormals(0);
  normalsFilter->ReleaseDataFlagOn();

  normalsFilter->SetInput( move->GetOutput() );
  move->Delete();

  vtkPolyDataToImageStencil * surfaceConverter = vtkPolyDataToImageStencil::New();
  surfaceConverter->SetTolerance( 0.0 );
  surfaceConverter->ReleaseDataFlagOn();

  surfaceConverter->SetInput( normalsFilter->GetOutput() );
  normalsFilter->Delete();

  vtkImageData *image = const_cast< mitk::Image * >(this->GetImage())->GetVtkImageData( time );
  
  // Create stencil and use numerical minimum of pixel type as background value
  vtkImageStencil * stencil = vtkImageStencil::New();
  stencil->SetInput( image );
  stencil->ReverseStencilOff();
  stencil->ReleaseDataFlagOn();
  stencil->SetStencil( surfaceConverter->GetOutput() );
  surfaceConverter->Delete();

  if (m_MakeOutputBinary)
  {
    stencil->SetBackgroundValue( image->GetScalarTypeMin() );

    vtkImageThreshold * threshold = vtkImageThreshold::New();
    threshold->SetInput( stencil->GetOutput() );
    threshold->ThresholdByLower( image->GetScalarTypeMin() );
    threshold->ReplaceInOn();
    threshold->ReplaceOutOn();
    threshold->SetInValue( 0 );
    threshold->SetOutValue( 1 );
    threshold->SetOutputScalarTypeToUnsignedChar();
    threshold->Update();

    mitk::Image::Pointer output = this->GetOutput();
    output->SetVolume( threshold->GetOutput()->GetScalarPointer(), time );

    threshold->Delete();
  }
  else
  {
    stencil->SetBackgroundValue( m_BackgroundValue );
    stencil->Update();

    mitk::Image::Pointer output = this->GetOutput();
    output->SetVolume( stencil->GetOutput()->GetScalarPointer(), time );
    MITK_INFO << "stencil ref count: " << stencil->GetReferenceCount() << std::endl;
  }
  stencil->Delete();
}