Esempio n. 1
0
mitk::BaseGeometry::BaseGeometry(const BaseGeometry& other) : Superclass(), mitk::OperationActor(),
m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified),
m_ImageGeometry(other.m_ImageGeometry), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false)
{
  m_GeometryTransform = new GeometryTransformHolder(*other.GetGeometryTransformHolder());
  other.InitializeGeometry(this);
}
static IntensityProfile::Pointer ComputeIntensityProfile(Image::Pointer image, itk::PolyLineParametricPath<3>::Pointer path)
{
  IntensityProfile::Pointer intensityProfile = IntensityProfile::New();
  itk::PolyLineParametricPath<3>::InputType input = path->StartOfInput();
  BaseGeometry* imageGeometry = image->GetGeometry();
  const PixelType pixelType = image->GetPixelType();

  IntensityProfile::MeasurementVectorType measurementVector;
  itk::PolyLineParametricPath<3>::OffsetType offset;
  Point3D worldPoint;
  itk::Index<3> index;

  do
  {
    imageGeometry->IndexToWorld(path->Evaluate(input), worldPoint);
    imageGeometry->WorldToIndex(worldPoint, index);

    mitkPixelTypeMultiplex3(ReadPixel, pixelType, image, index, measurementVector.GetDataPointer());
    intensityProfile->PushBack(measurementVector);

    offset = path->IncrementInput(input);
  } while ((offset[0] | offset[1] | offset[2]) != 0);

  return intensityProfile;
}
Esempio n. 3
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.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal0.GetVnlVector()) );
  imageNormal1.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal1.GetVnlVector()) );
  imageNormal2.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal2.GetVnlVector()) );

  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
  BaseGeometry* 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. 4
0
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);
}
  void PlaneGeometryDataVtkMapper3D::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();

    bool visible = true;
    GetDataNode()->GetVisibility(visible, renderer, "visible");

    if ( !visible )
    {
      // 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();
    bool drawEdges = true;
    this->GetDataNode()->GetBoolProperty("draw edges", drawEdges, renderer);
    m_EdgeActor->SetVisibility(drawEdges);

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

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

      if ( (surfacecreatorprop.IsNull())
        || (surfacecreatorprop->GetSmartPointer().IsNull())
        || ((m_SurfaceCreator = dynamic_cast<PlaneGeometryDataToSurfaceFilter*>
             (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 PlaneGeometry with the reference geometry bounds (if available)
      if ( input->GetPlaneGeometry()->HasReferenceGeometry() )
      {
        BaseGeometry *referenceGeometry =
            input->GetPlaneGeometry()->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 PlaneGeometry
      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->SetInputData( surface->GetVtkPolyData() );
          m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) );

          m_FrontHedgeHog->SetInputConnection(m_NormalsTransformer->GetOutputPort() );
          m_FrontHedgeHog->SetVectorModeToUseNormal();
          m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 );
          m_FrontHedgeHog->Update();

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

          m_BackHedgeHog->SetInputConnection( m_NormalsTransformer->GetOutputPort() );
          m_BackHedgeHog->SetVectorModeToUseNormal();
          m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 );
          m_BackHedgeHog->Update();

          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->SetInputData( surface->GetVtkPolyData() );
      m_ImageAssembly->AddPart( m_BackgroundActor );

      LayerSortedActorList layerSortedActors;

      // Traverse the data tree to find nodes resliced by ImageMapperGL2D
      //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->SetInputData(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. 6
0
std::string
mitk::TestDICOMLoading::DumpImageInformation( const Image* image )
{
  std::stringstream result;

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

  SetDefaultLocale();

  // basic image data
  DumpLine( "Pixeltype",    ComponentTypeToString(image->GetPixelType().GetComponentType()) );
  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";
  const TimeGeometry* timeGeometry = image->GetTimeGeometry();
  BaseGeometry* geometry = timeGeometry->GetGeometryForTimeStep(0);
  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 = timeGeometry->GetTimeBounds();
      for (unsigned int i = 0; i < 2; ++i)
          result << timeBounds[i] << " ";
      result << "\n";


    }
  }

  ResetUserLocale();

  return result.str();
}
bool mitk::MoveBaseDataInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent )
{
  bool ok = false;

  /*Each case must watch the type of the event!*/
  switch (action->GetActionId())
  {
  case AcDONOTHING:
    ok = true;
    break;
  case AcCHECKELEMENT:
    /*
    * picking: Answer the question if the given position within stateEvent is close enough to select an object
    * send yes if close enough and no if not picked
    */
    {
      mitk::DisplayPositionEvent const *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent());
      if (posEvent == nullptr)
      {
        MITK_WARN<<"Wrong usage of mitkMoveBaseDataInteractor! Aborting interaction!\n";
        return false;
      }

      mitk::Point3D worldPoint = posEvent->GetWorldPosition();
      /* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */

      std::auto_ptr<StateEvent> newStateEvent;
      const BaseGeometry* geometry = GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep );
      if (geometry->IsInside(worldPoint))
        newStateEvent.reset(new mitk::StateEvent(EIDYES, stateEvent->GetEvent()));
      else
        newStateEvent.reset(new mitk::StateEvent(EIDNO, stateEvent->GetEvent()));

      /* write new state (selected/not selected) to the property */
      this->HandleEvent( newStateEvent.get() );

    ok = true;
    break;
    }
  case AcSELECT:
    // select the data
    {
      mitk::BoolProperty::Pointer selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));
      if ( selected.IsNull() )
      {
        selected = mitk::BoolProperty::New();
        m_DataNode->GetPropertyList()->SetProperty("selected", selected);
      }

      mitk::ColorProperty::Pointer selectedColor = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.SelectedColor"));
      if ( selectedColor.IsNotNull() )
      {
        m_DataNode->GetPropertyList()->SetProperty("color", selectedColor);
      }
      selected->SetValue(true);

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

      ok = true;
      break;
    }
  case AcDESELECT:
    //deselect the data
    {
      mitk::BoolProperty::Pointer selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected"));
      if ( selected.IsNull() )
      {
        selected = mitk::BoolProperty::New();
        m_DataNode->GetPropertyList()->SetProperty("selected", selected);
      }

      mitk::ColorProperty::Pointer deselectedColor =
              dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.DeselectedColor"));
      if ( deselectedColor.IsNotNull() )
      {
        m_DataNode->GetPropertyList()->SetProperty("color", deselectedColor);
      }

      selected = mitk::BoolProperty::New(false);

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

      ok = true;
      break;
    }
  case AcMOVE:
    {
      //modify Geometry from data as given in parameters or in event
      mitk::IntProperty* xP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_X"));
      mitk::IntProperty* yP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_Y"));
      mitk::IntProperty* zP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_Z"));
      if (xP == nullptr || yP == nullptr || zP == nullptr)
      {
        MITK_WARN<<"No properties returned\n!";
        return false;
      }
      mitk::Vector3D movementVector;
      movementVector.SetElement(0, (float) xP->GetValue());
      movementVector.SetElement(1, (float) yP->GetValue());
      movementVector.SetElement(2, (float) zP->GetValue());

      BaseGeometry* geometry = m_DataNode->GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep );
      geometry->Translate(movementVector);

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

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

      ok = true;
      break;
    }

  default:
    return Superclass::ExecuteAction( action, stateEvent );
  }

  return ok;
}
void mitk::SurfaceToImageFilter::Stencil3DImage(int time)
{
  mitk::Image::Pointer output = this->GetOutput();
  mitk::Image::Pointer binaryImage = mitk::Image::New();

  unsigned int size = sizeof(unsigned char);
  if (m_MakeOutputBinary)
    binaryImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *this->GetImage()->GetTimeGeometry(),1,1);
  else
  {
    binaryImage->Initialize(this->GetImage()->GetPixelType(), *this->GetImage()->GetTimeGeometry(),1,1);
    size = this->GetImage()->GetPixelType().GetSize();
  }

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

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

  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 );
  if(polydata)
  {
    vtkSmartPointer<vtkTransformPolyDataFilter> move = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
    move->SetInputData(polydata);
    move->ReleaseDataFlagOn();

    vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
    BaseGeometry* geometry = surfaceTimeGeometry->GetGeometryForTimeStep( surfaceTimeStep );
    if(!geometry)
    {
      geometry = GetInput()->GetGeometry();
    }
    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.
    BaseGeometry* imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time);
    transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse());
    move->SetTransform(transform);

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

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

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

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

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

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

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

    output->SetVolume( stencil->GetOutput()->GetScalarPointer(), time );
    MITK_INFO << "stencil ref count: " << stencil->GetReferenceCount() << std::endl;
  }
  else
  {
    memset( accessor.GetData(), 0, size );
    output->SetVolume(accessor.GetData(),time);
  }

}
void mitk::PlaneGeometryDataToSurfaceFilter::GenerateOutputInformation()
{
  mitk::PlaneGeometryData::ConstPointer input = this->GetInput();
  mitk::Surface::Pointer output = this->GetOutput();

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

  Point3D origin;
  Point3D right, bottom;

  vtkPolyData *planeSurface = nullptr;




  // Does the PlaneGeometryData contain an AbstractTransformGeometry?
  if ( mitk::AbstractTransformGeometry *abstractGeometry =
    dynamic_cast< AbstractTransformGeometry * >( input->GetPlaneGeometry() ) )
  {
    // 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();
      BaseGeometry *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->GetPlaneGeometry()->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();
  }
    // Does the PlaneGeometryData contain a PlaneGeometry?
  else if ( dynamic_cast< PlaneGeometry * >( input->GetPlaneGeometry() ) != nullptr )
  {
    mitk::PlaneGeometry *planeGeometry =
      dynamic_cast< PlaneGeometry * >( input->GetPlaneGeometry() );

    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();
      BaseGeometry *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()
      );

      BaseGeometry *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()
      );
    }
  }

  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();
}