void Geometry2DDataVtkMapper3D::ProcessNode( DataNode * node, BaseRenderer* renderer,
                                               Surface * surface, LayerSortedActorList &layerSortedActors )
  {
    if ( node != NULL )
    {
      //we need to get the information from the 2D mapper to render the texture on the 3D plane
      ImageVtkMapper2D *imageMapper = dynamic_cast< ImageVtkMapper2D * >( node->GetMapper(1) ); //GetMapper(1) provides the 2D mapper for the data node

      //if there is a 2D mapper, which is not the standard image mapper...
      if(!imageMapper && node->GetMapper(1))
      { //... check if it is the composite mapper
        std::string cname(node->GetMapper(1)->GetNameOfClass());
        if(!cname.compare("CompositeMapper")) //string.compare returns 0 if the two strings are equal.
        {
          //get the standard image mapper.
          //This is a special case in MITK and does only work for the CompositeMapper.
          imageMapper = dynamic_cast<ImageVtkMapper2D* >( node->GetMapper(3) );
        }
      }

      if ( (node->IsVisible(renderer)) && imageMapper )
      {
        WeakPointerProperty::Pointer rendererProp =
            dynamic_cast< WeakPointerProperty * >(GetDataNode()->GetPropertyList()->GetProperty("renderer"));

        if ( rendererProp.IsNotNull() )
        {
          BaseRenderer::Pointer planeRenderer = dynamic_cast< BaseRenderer * >(rendererProp->GetWeakPointer().GetPointer());
          // Retrieve and update image to be mapped
          const ImageVtkMapper2D::LocalStorage* localStorage = imageMapper->GetLocalStorage(planeRenderer);

          if ( planeRenderer.IsNotNull() )
          {
            // perform update of imagemapper if needed (maybe the respective 2D renderwindow is not rendered/update before)
            imageMapper->Update(planeRenderer);

            // If it has not been initialized already in a previous pass,
            // generate an actor and a texture object to
            // render the image associated with the ImageVtkMapper2D.
            vtkActor *imageActor;
            vtkDataSetMapper *dataSetMapper = NULL;
            vtkTexture *texture;
            if ( m_ImageActors.count( imageMapper ) == 0 )
            {
              dataSetMapper = vtkDataSetMapper::New();
              //Enable rendering without copying the image.
              dataSetMapper->ImmediateModeRenderingOn();

              texture = vtkTexture::New();
              texture->RepeatOff();

              imageActor = vtkActor::New();
              imageActor->SetMapper( dataSetMapper );
              imageActor->SetTexture( texture );

              // Make imageActor the sole owner of the mapper and texture
              // objects
              dataSetMapper->UnRegister( NULL );
              texture->UnRegister( NULL );

              // Store the actor so that it may be accessed in following
              // passes.
              m_ImageActors[imageMapper].Initialize(imageActor, imageMapper, m_ImageMapperDeletedCommand);
            }
            else
            {
              // Else, retrieve the actor and associated objects from the
              // previous pass.
              imageActor = m_ImageActors[imageMapper].m_Actor;
              dataSetMapper = (vtkDataSetMapper *)imageActor->GetMapper();
              texture = imageActor->GetTexture();
            }

            // Set poly data new each time its object changes (e.g. when
            // switching between planar and curved geometries)
            if ( (dataSetMapper != NULL) && (dataSetMapper->GetInput() != surface->GetVtkPolyData()) )
            {
              dataSetMapper->SetInput( surface->GetVtkPolyData() );
            }

            //Check if the m_ReslicedImage is NULL.
            //This is the case when no image geometry is met by
            //the reslicer. In that case, the texture has to be
            //empty (black) and we don't have to do anything.
            //See fixed bug #13275
            if(localStorage->m_ReslicedImage != NULL)
            {
              bool binaryOutline = node->IsOn( "outline binary", renderer );
              if( binaryOutline )
              {
                texture->SetInput( localStorage->m_ReslicedImage );
              }
              else
              {
                texture->SetInput( localStorage->m_Texture->GetInput() );
              }
              // VTK (mis-)interprets unsigned char (binary) images as color images;
              // So, we must manually turn on their mapping through a (gray scale) lookup table;
              texture->SetMapColorScalarsThroughLookupTable( localStorage->m_Texture->GetMapColorScalarsThroughLookupTable() );

              //re-use properties from the 2D image mapper
              imageActor->SetProperty( localStorage->m_Actor->GetProperty() );
              imageActor->GetProperty()->SetAmbient(0.5);

              // Set texture interpolation on/off
              bool textureInterpolation = node->IsOn( "texture interpolation", renderer );
              texture->SetInterpolate( textureInterpolation );

              //get the lookuptable from the 2D image mapper
              texture->SetLookupTable( localStorage->m_Texture->GetLookupTable() );

              // Store this actor to be added to the actor assembly, sort
              // by layer
              int layer = 1;
              node->GetIntProperty( "layer", layer );
              layerSortedActors.insert(std::pair< int, vtkActor * >( layer, imageActor ) );
            }
          }
        }
      }
    }
  }
  void PlaneGeometryDataVtkMapper3D::ProcessNode(DataNode *node,
                                                 BaseRenderer *renderer,
                                                 Surface *surface,
                                                 LayerSortedActorList &layerSortedActors)
  {
    if (node != nullptr)
    {
      // we need to get the information from the 2D mapper to render the texture on the 3D plane
      ImageVtkMapper2D *imageMapper =
        dynamic_cast<ImageVtkMapper2D *>(node->GetMapper(1)); // GetMapper(1) provides the 2D mapper for the data node

      // if there is a 2D mapper, which is not the standard image mapper...
      if (!imageMapper && node->GetMapper(1))
      { //... check if it is the composite mapper
        std::string cname(node->GetMapper(1)->GetNameOfClass());
        if (!cname.compare("CompositeMapper")) // string.compare returns 0 if the two strings are equal.
        {
          // get the standard image mapper.
          // This is a special case in MITK and does only work for the CompositeMapper.
          imageMapper = dynamic_cast<ImageVtkMapper2D *>(node->GetMapper(3));
        }
      }

      if ((node->IsVisible(renderer)) && imageMapper)
      {
        WeakPointerProperty::Pointer rendererProp =
          dynamic_cast<WeakPointerProperty *>(GetDataNode()->GetPropertyList()->GetProperty("renderer"));

        if (rendererProp.IsNotNull())
        {
          BaseRenderer::Pointer planeRenderer =
            dynamic_cast<BaseRenderer *>(rendererProp->GetWeakPointer().GetPointer());
          // Retrieve and update image to be mapped
          const ImageVtkMapper2D::LocalStorage *localStorage = imageMapper->GetLocalStorage(planeRenderer);

          if (planeRenderer.IsNotNull())
          {
            // perform update of imagemapper if needed (maybe the respective 2D renderwindow is not rendered/update
            // before)
            imageMapper->Update(planeRenderer);

            // If it has not been initialized already in a previous pass,
            // generate an actor and a texture object to
            // render the image associated with the ImageVtkMapper2D.
            vtkActor *imageActor;
            vtkDataSetMapper *dataSetMapper = nullptr;
            vtkTexture *texture;
            if (m_ImageActors.count(imageMapper) == 0)
            {
              dataSetMapper = vtkDataSetMapper::New();
              // Enable rendering without copying the image.
              dataSetMapper->ImmediateModeRenderingOn();

              texture = vtkNeverTranslucentTexture::New();
              texture->RepeatOff();

              imageActor = vtkActor::New();
              imageActor->SetMapper(dataSetMapper);
              imageActor->SetTexture(texture);
              imageActor->GetProperty()->SetOpacity(
                0.999); // HACK! otherwise VTK wouldn't recognize this as translucent
                        // surface (if LUT values map to alpha < 255
              // improvement: apply "opacity" property onle HERE and also in 2D image mapper. DO NOT change LUT to
              // achieve
              // translucent images (see method ChangeOpacity in image mapper 2D)

              // Make imageActor the sole owner of the mapper and texture
              // objects
              dataSetMapper->UnRegister(nullptr);
              texture->UnRegister(nullptr);

              // Store the actor so that it may be accessed in following
              // passes.
              m_ImageActors[imageMapper].Initialize(imageActor, imageMapper, m_ImageMapperDeletedCommand);
            }
            else
            {
              // Else, retrieve the actor and associated objects from the
              // previous pass.
              imageActor = m_ImageActors[imageMapper].m_Actor;
              dataSetMapper = (vtkDataSetMapper *)imageActor->GetMapper();
              texture = imageActor->GetTexture();
            }

            // Set poly data new each time its object changes (e.g. when
            // switching between planar and curved geometries)
            if ((dataSetMapper != nullptr) && (dataSetMapper->GetInput() != surface->GetVtkPolyData()))
            {
              dataSetMapper->SetInputData(surface->GetVtkPolyData());
            }

            dataSetMapper->Update();

            // Check if the m_ReslicedImage is nullptr.
            // This is the case when no image geometry is met by
            // the reslicer. In that case, the texture has to be
            // empty (black) and we don't have to do anything.
            // See fixed bug #13275
            if (localStorage->m_ReslicedImage != nullptr)
            {
              texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort());

              // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter)
              texture->MapColorScalarsThroughLookupTableOff();

              // re-use properties from the 2D image mapper
              imageActor->SetProperty(localStorage->m_Actor->GetProperty());
              imageActor->GetProperty()->SetAmbient(0.5);

              // Set texture interpolation on/off
              bool textureInterpolation = node->IsOn("texture interpolation", renderer);
              texture->SetInterpolate(textureInterpolation);

              // Store this actor to be added to the actor assembly, sort
              // by layer
              int layer = 1;
              node->GetIntProperty("layer", layer);
              layerSortedActors.insert(std::pair<int, vtkActor *>(layer, imageActor));
            }
          }
        }
      }
    }
  }