diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
index 912b186306..a9d5ba8799 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.cpp
@@ -1,2039 +1,2023 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include "QmitkSlicesInterpolator.h"
 #include "QmitkRenderWindow.h"
 #include "QmitkRenderWindowWidget.h"
 
 #include "mitkApplyDiffImageOperation.h"
 #include "mitkColorProperty.h"
 #include "mitkCoreObjectFactory.h"
 #include "mitkDiffImageApplier.h"
 #include "mitkInteractionConst.h"
 #include "mitkLevelWindowProperty.h"
 #include "mitkOperationEvent.h"
 #include "mitkProgressBar.h"
 #include "mitkProperties.h"
 #include "mitkRenderingManager.h"
 #include "mitkSegTool2D.h"
 #include "mitkSliceNavigationController.h"
 #include "mitkSurfaceToImageFilter.h"
 #include <mitkTimeNavigationController.h>
 #include "mitkToolManager.h"
 #include "mitkUndoController.h"
 
 #include <mitkExtractSliceFilter.h>
 #include <mitkPlanarCircle.h>
 #include <mitkImageReadAccessor.h>
 #include <mitkImageTimeSelector.h>
 #include <mitkImageWriteAccessor.h>
 #include <mitkPlaneProposer.h>
 #include <mitkUnstructuredGridClusteringFilter.h>
 #include <mitkVtkImageOverwrite.h>
 #include <mitkShapeBasedInterpolationAlgorithm.h>
 #include <itkCommand.h>
 
 #include <mitkImageToContourFilter.h>
 #include <mitkImagePixelReadAccessor.h>
 
 //  Includes for the merge operation
 #include "mitkImageToContourFilter.h"
 #include <mitkLabelSetImage.h>
 
 #include <QCheckBox>
 #include <QCursor>
 #include <QMenu>
 #include <QMessageBox>
 #include <QPushButton>
 #include <QVBoxLayout>
 
 #include <vtkDoubleArray.h>
 #include <vtkFieldData.h>
 #include <vtkPolyVertex.h>
 #include <vtkUnstructuredGrid.h>
 #include <vtkPolyData.h>
 
 #include <array>
 #include <atomic>
 #include <thread>
 #include <vector>
 
 namespace
 {
   template <typename T = mitk::BaseData>
   itk::SmartPointer<T> GetData(const mitk::DataNode* dataNode)
   {
     return nullptr != dataNode
       ? dynamic_cast<T*>(dataNode->GetData())
       : nullptr;
   }
 }
 
 float SURFACE_COLOR_RGB[3] = {0.49f, 1.0f, 0.16f};
 
 const QmitkSlicesInterpolator::ActionToSliceDimensionMapType QmitkSlicesInterpolator::CreateActionToSlicer(const QList<QmitkRenderWindow*>& windows)
 {
   std::map<QAction *, mitk::SliceNavigationController *> actionToSliceDimension;
   for (auto* window : windows)
   {
     std::string windowName;
     auto renderWindowWidget = dynamic_cast<QmitkRenderWindowWidget*>(window->parentWidget());
     if (renderWindowWidget)
     {
       windowName = renderWindowWidget->GetCornerAnnotationText();
     }
     else
     {
       windowName = window->GetRenderer()->GetName();
     }
     auto slicer = window->GetSliceNavigationController();
     actionToSliceDimension[new QAction(QString::fromStdString(windowName), nullptr)] = slicer;
   }
 
   return actionToSliceDimension;
 }
 
 // Check whether the given contours are coplanar
 bool AreContoursCoplanar(mitk::SurfaceInterpolationController::ContourPositionInformation leftHandSide,
                       mitk::SurfaceInterpolationController::ContourPositionInformation rightHandSide)
 {
   // Here we check two things:
   // 1. Whether the normals of both contours are at least parallel
   // 2. Whether both contours lie in the same plane
 
   // Check for coplanarity:
   // a. Span a vector between two points one from each contour
   // b. Calculate dot product for the vector and one of the normals
   // c. If the dot is zero the two vectors are orthogonal and the contours are coplanar
 
   double vec[3];
   vec[0] = leftHandSide.ContourPoint[0] - rightHandSide.ContourPoint[0];
   vec[1] = leftHandSide.ContourPoint[1] - rightHandSide.ContourPoint[1];
   vec[2] = leftHandSide.ContourPoint[2] - rightHandSide.ContourPoint[2];
   double n[3];
   n[0] = rightHandSide.ContourNormal[0];
   n[1] = rightHandSide.ContourNormal[1];
   n[2] = rightHandSide.ContourNormal[2];
   double dot = vtkMath::Dot(n, vec);
 
   double n2[3];
   n2[0] = leftHandSide.ContourNormal[0];
   n2[1] = leftHandSide.ContourNormal[1];
   n2[2] = leftHandSide.ContourNormal[2];
 
   // The normals of both contours have to be parallel but not of the same orientation
   double lengthLHS = leftHandSide.ContourNormal.GetNorm();
   double lengthRHS = rightHandSide.ContourNormal.GetNorm();
   double dot2 = vtkMath::Dot(n, n2);
   bool contoursParallel = mitk::Equal(fabs(lengthLHS * lengthRHS), fabs(dot2), 0.001);
 
   if (mitk::Equal(dot, 0.0, 0.001) && contoursParallel)
     return true;
   else
     return false;
 }
 
 mitk::Image::Pointer ExtractSliceFromImage(mitk::Image* image,
                                           const mitk::PlaneGeometry * contourPlane,
                                           unsigned int timeStep)
 {
   vtkSmartPointer<mitkVtkImageOverwrite> reslice = vtkSmartPointer<mitkVtkImageOverwrite>::New();
   // set to false to extract a slice
   reslice->SetOverwriteMode(false);
   reslice->Modified();
 
   mitk::ExtractSliceFilter::Pointer extractor = mitk::ExtractSliceFilter::New(reslice);
   extractor->SetInput(image);
   extractor->SetTimeStep(timeStep);
   extractor->SetWorldGeometry(contourPlane);
   extractor->SetVtkOutputRequest(false);
   extractor->SetResliceTransformByGeometry(image->GetTimeGeometry()->GetGeometryForTimeStep(timeStep));
   extractor->Update();
   mitk::Image::Pointer slice = extractor->GetOutput();
   return slice;
 }
 
 
 template <unsigned int VImageDimension = 3>
 std::vector<mitk::Label::PixelType> GetPixelValuesPresentInImage(mitk::LabelSetImage* labelSetImage)
 {
   std::vector<mitk::Label::PixelType> pixelsPresent;
   mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage);
 
   std::size_t numberOfPixels = 1;
   for (size_t dim = 0; dim < VImageDimension; ++dim)
     numberOfPixels *= static_cast<std::size_t>(readAccessor.GetDimension(dim));
 
   auto src = readAccessor.GetData();
   for (std::size_t i = 0; i < numberOfPixels; ++i)
   {
     mitk::Label::PixelType pixelVal = *(src + i);
     if ( (std::find(pixelsPresent.begin(), pixelsPresent.end(), pixelVal) == pixelsPresent.end()) && (pixelVal != mitk::LabelSetImage::UnlabeledValue) )
       pixelsPresent.push_back(pixelVal);
   }
   return pixelsPresent;
 }
 
 
 template <unsigned int VImageDimension = 3>
 ModifyLabelActionTrigerred ModifyLabelProcessing(mitk::LabelSetImage* labelSetImage,
                           mitk::SurfaceInterpolationController::Pointer surfaceInterpolator,
                           unsigned int timePoint)
 {
-  auto currentLayerID = labelSetImage->GetActiveLayer();
+  auto currentLabelID = labelSetImage->GetActiveLabel()->GetValue();
   auto numTimeSteps = labelSetImage->GetTimeSteps();
 
   ModifyLabelActionTrigerred actionTriggered = ModifyLabelActionTrigerred::Null;
-  auto* currentContourList = surfaceInterpolator->GetContours(timePoint, currentLayerID);
+  auto* currentContourList = surfaceInterpolator->GetContours(timePoint, currentLabelID);
 
   while (nullptr == currentContourList)
   {
-    surfaceInterpolator->OnAddLayer();
-    currentContourList = surfaceInterpolator->GetContours(timePoint, currentLayerID);
+    currentContourList = surfaceInterpolator->GetContours(timePoint, currentLabelID);
   }
 
   mitk::LabelSetImage::Pointer labelSetImage2 = labelSetImage->Clone();
 
-  mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage2.GetPointer());
+  mitk::ImagePixelReadAccessor<mitk::LabelSetImage::LabelValueType, VImageDimension> readAccessor(labelSetImage2.GetPointer());
 
   for (auto& contour : *currentContourList)
   {
     mitk::Label::PixelType contourPixelValue;
 
     itk::Index<3> itkIndex;
     labelSetImage2->GetGeometry()->WorldToIndex(contour.ContourPoint, itkIndex);
     if (VImageDimension == 4)
     {
       itk::Index<VImageDimension> time3DIndex;
       for (size_t i = 0; i < itkIndex.size(); ++i)
         time3DIndex[i] = itkIndex[i];
       time3DIndex[3] = timePoint;
       contourPixelValue = readAccessor.GetPixelByIndexSafe(time3DIndex);
     }
     else if (VImageDimension == 3)
     {
       itk::Index<VImageDimension> geomIndex;
       for (size_t i = 0; i < itkIndex.size(); ++i)
         geomIndex[i] = itkIndex[i];
       contourPixelValue = readAccessor.GetPixelByIndexSafe(geomIndex);
     }
 
     if (contour.LabelValue != contourPixelValue)
     {
       if (contourPixelValue == 0)   //  Erase label
       {
         for (size_t t = 0; t < numTimeSteps; ++t)
-          surfaceInterpolator->RemoveContours(contour.LabelValue, t, currentLayerID);
+          surfaceInterpolator->RemoveContours(contour.LabelValue, t);
         actionTriggered = ModifyLabelActionTrigerred::Erase;
       }
       else
       {
         contour.LabelValue = contourPixelValue;
         actionTriggered = ModifyLabelActionTrigerred::Merge;
       }
     }
   }
   return actionTriggered;
 }
 
 QmitkSlicesInterpolator::QmitkSlicesInterpolator(QWidget *parent, const char * /*name*/)
   : QWidget(parent),
     m_Interpolator(mitk::SegmentationInterpolationController::New()),
     m_SurfaceInterpolator(mitk::SurfaceInterpolationController::GetInstance()),
     m_ToolManager(nullptr),
     m_Initialized(false),
     m_LastSNC(nullptr),
     m_LastSliceIndex(0),
     m_2DInterpolationEnabled(false),
     m_3DInterpolationEnabled(false),
     m_PreviousActiveLabelValue(0),
     m_CurrentActiveLabelValue(0),
     m_PreviousLayerIndex(0),
     m_CurrentLayerIndex(0),
     m_FirstRun(true)
 {
   m_GroupBoxEnableExclusiveInterpolationMode = new QGroupBox("Interpolation", this);
 
   QVBoxLayout *vboxLayout = new QVBoxLayout(m_GroupBoxEnableExclusiveInterpolationMode);
 
   m_EdgeDetector = mitk::FeatureBasedEdgeDetectionFilter::New();
   m_PointScorer = mitk::PointCloudScoringFilter::New();
 
   m_CmbInterpolation = new QComboBox(m_GroupBoxEnableExclusiveInterpolationMode);
   m_CmbInterpolation->addItem("Disabled");
   m_CmbInterpolation->addItem("2-Dimensional");
   m_CmbInterpolation->addItem("3-Dimensional");
   vboxLayout->addWidget(m_CmbInterpolation);
 
   m_BtnApply2D = new QPushButton("Confirm for single slice", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApply2D);
 
   m_BtnApplyForAllSlices2D = new QPushButton("Confirm for all slices", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApplyForAllSlices2D);
 
   m_BtnApply3D = new QPushButton("Confirm", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnApply3D);
 
   // T28261
   // m_BtnSuggestPlane = new QPushButton("Suggest a plane", m_GroupBoxEnableExclusiveInterpolationMode);
   // vboxLayout->addWidget(m_BtnSuggestPlane);
 
   m_BtnReinit3DInterpolation = new QPushButton("Reinit Interpolation", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_BtnReinit3DInterpolation);
 
   m_ChkShowPositionNodes = new QCheckBox("Show Position Nodes", m_GroupBoxEnableExclusiveInterpolationMode);
   vboxLayout->addWidget(m_ChkShowPositionNodes);
 
   this->HideAllInterpolationControls();
 
   connect(m_CmbInterpolation, SIGNAL(currentIndexChanged(int)), this, SLOT(OnInterpolationMethodChanged(int)));
   connect(m_BtnApply2D, SIGNAL(clicked()), this, SLOT(OnAcceptInterpolationClicked()));
   connect(m_BtnApplyForAllSlices2D, SIGNAL(clicked()), this, SLOT(OnAcceptAllInterpolationsClicked()));
   connect(m_BtnApply3D, SIGNAL(clicked()), this, SLOT(OnAccept3DInterpolationClicked()));
 
 
   connect(m_BtnReinit3DInterpolation, SIGNAL(clicked()), this, SLOT(OnReinit3DInterpolation()));
   connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SLOT(OnShowMarkers(bool)));
   connect(m_ChkShowPositionNodes, SIGNAL(toggled(bool)), this, SIGNAL(SignalShowMarkerNodes(bool)));
 
   QHBoxLayout *layout = new QHBoxLayout(this);
   layout->addWidget(m_GroupBoxEnableExclusiveInterpolationMode);
   this->setLayout(layout);
 
   itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command =
     itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationInfoChanged);
   InterpolationInfoChangedObserverTag = m_Interpolator->AddObserver(itk::ModifiedEvent(), command);
 
   itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::Pointer command2 =
     itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged);
   SurfaceInterpolationInfoChangedObserverTag = m_SurfaceInterpolator->AddObserver(itk::ModifiedEvent(), command2);
 
   auto command3 = itk::ReceptorMemberCommand<QmitkSlicesInterpolator>::New();
   command3->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnInterpolationAborted);
   InterpolationAbortedObserverTag = m_Interpolator->AddObserver(itk::AbortEvent(), command3);
 
   // feedback node and its visualization properties
   m_FeedbackNode = mitk::DataNode::New();
   mitk::CoreObjectFactory::GetInstance()->SetDefaultProperties(m_FeedbackNode);
 
   m_FeedbackNode->SetProperty("binary", mitk::BoolProperty::New(true));
   m_FeedbackNode->SetProperty("outline binary", mitk::BoolProperty::New(true));
   m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(255.0, 255.0, 0.0));
   m_FeedbackNode->SetProperty("texture interpolation", mitk::BoolProperty::New(false));
   m_FeedbackNode->SetProperty("layer", mitk::IntProperty::New(20));
   m_FeedbackNode->SetProperty("levelwindow", mitk::LevelWindowProperty::New(mitk::LevelWindow(0, 1)));
   m_FeedbackNode->SetProperty("name", mitk::StringProperty::New("Interpolation feedback"));
   m_FeedbackNode->SetProperty("opacity", mitk::FloatProperty::New(0.8));
   m_FeedbackNode->SetProperty("helper object", mitk::BoolProperty::New(true));
 
   m_InterpolatedSurfaceNode = mitk::DataNode::New();
   m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
   m_InterpolatedSurfaceNode->SetProperty("name", mitk::StringProperty::New("Surface Interpolation feedback"));
   m_InterpolatedSurfaceNode->SetProperty("opacity", mitk::FloatProperty::New(0.5));
   m_InterpolatedSurfaceNode->SetProperty("line width", mitk::FloatProperty::New(4.0f));
   m_InterpolatedSurfaceNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
   m_InterpolatedSurfaceNode->SetProperty("helper object", mitk::BoolProperty::New(true));
   m_InterpolatedSurfaceNode->SetVisibility(false);
 
   m_3DContourNode = mitk::DataNode::New();
   m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(0.0, 0.0, 0.0));
   m_3DContourNode->SetProperty("hidden object", mitk::BoolProperty::New(true));
   m_3DContourNode->SetProperty("name", mitk::StringProperty::New("Drawn Contours"));
   m_3DContourNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME));
   m_3DContourNode->SetProperty("material.wireframeLineWidth", mitk::FloatProperty::New(2.0f));
   m_3DContourNode->SetProperty("3DContourContainer", mitk::BoolProperty::New(true));
   m_3DContourNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false));
   m_3DContourNode->SetVisibility(false);
 
   QWidget::setContentsMargins(0, 0, 0, 0);
   if (QWidget::layout() != nullptr)
   {
     QWidget::layout()->setContentsMargins(0, 0, 0, 0);
   }
 
 
   // For running 3D Interpolation in background
   // create a QFuture and a QFutureWatcher
 
   connect(&m_Watcher, SIGNAL(started()), this, SLOT(StartUpdateInterpolationTimer()));
   connect(&m_Watcher, SIGNAL(finished()), this, SLOT(OnSurfaceInterpolationFinished()));
   connect(&m_Watcher, SIGNAL(finished()), this, SLOT(StopUpdateInterpolationTimer()));
   m_Timer = new QTimer(this);
   connect(m_Timer, SIGNAL(timeout()), this, SLOT(ChangeSurfaceColor()));
 }
 
 void QmitkSlicesInterpolator::SetDataStorage(mitk::DataStorage::Pointer storage)
 {
   if (m_DataStorage == storage)
   {
     return;
   }
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.RemoveListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
   }
 
   m_DataStorage = storage;
   m_SurfaceInterpolator->SetDataStorage(storage);
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.AddListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
   }
 }
 
+void QmitkSlicesInterpolator::SetActiveLabelValue(mitk::LabelSetImage::LabelValueType labelValue)
+{
+  bool changedValue = labelValue != this->m_CurrentActiveLabelValue;
+
+  this->m_CurrentActiveLabelValue = labelValue;
+
+  if (changedValue) this->OnActiveLabelChanged(labelValue);
+};
+
+
 mitk::DataStorage *QmitkSlicesInterpolator::GetDataStorage()
 {
   if (m_DataStorage.IsNotNull())
   {
     return m_DataStorage;
   }
   else
   {
     return nullptr;
   }
 }
 
 void QmitkSlicesInterpolator::InitializeWindow(QmitkRenderWindow* window)
 {
   auto slicer = window->GetSliceNavigationController();
 
   if (slicer == nullptr)
   {
     MITK_WARN << "Tried setting up interpolation for a render window that does not have a slice navigation controller set";
     return;
   }
 
   // Has to be initialized
   m_LastSNC = slicer;
 
   itk::MemberCommand<QmitkSlicesInterpolator>::Pointer deleteCommand =
     itk::MemberCommand<QmitkSlicesInterpolator>::New();
   deleteCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted);
   m_ControllerToDeleteObserverTag[slicer] = slicer->AddObserver(itk::DeleteEvent(), deleteCommand);
 
   itk::MemberCommand<QmitkSlicesInterpolator>::Pointer sliceChangedCommand =
     itk::MemberCommand<QmitkSlicesInterpolator>::New();
   sliceChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnSliceChanged);
   m_ControllerToSliceObserverTag[slicer] = slicer->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(nullptr, 0), sliceChangedCommand);
 }
 
 void QmitkSlicesInterpolator::Initialize(mitk::ToolManager *toolManager,
                                          const QList<QmitkRenderWindow*>& windows)
 {
   Q_ASSERT(!windows.empty());
 
   if (m_Initialized)
   {
     // remove old observers
     this->Uninitialize();
   }
 
   m_ToolManager = toolManager;
 
   if (m_ToolManager)
   {
     // set enabled only if a segmentation is selected
     mitk::DataNode *node = m_ToolManager->GetWorkingData(0);
     QWidget::setEnabled(node != nullptr);
 
     // react whenever the set of selected segmentation changes
     m_ToolManager->WorkingDataChanged +=
       mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
     m_ToolManager->ReferenceDataChanged += mitk::MessageDelegate<QmitkSlicesInterpolator>(
       this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
 
     auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
     itk::MemberCommand<QmitkSlicesInterpolator>::Pointer timeChangedCommand =
       itk::MemberCommand<QmitkSlicesInterpolator>::New();
     timeChangedCommand->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnTimeChanged);
     m_ControllerToTimeObserverTag =
       timeNavigationController->AddObserver(mitk::TimeNavigationController::TimeEvent(0), timeChangedCommand);
 
     m_TimePoint = timeNavigationController->GetSelectedTimePoint();
 
     // connect to the slice navigation controller. after each change, call the interpolator
     for (auto* window : windows)
     {
       this->InitializeWindow(window);
     }
 
     m_ActionToSlicerMap = CreateActionToSlicer(windows);
   }
 
   m_Initialized = true;
 }
 
 void QmitkSlicesInterpolator::Uninitialize()
 {
   if (m_ToolManager.IsNotNull())
   {
     m_ToolManager->WorkingDataChanged -=
       mitk::MessageDelegate<QmitkSlicesInterpolator>(this, &QmitkSlicesInterpolator::OnToolManagerWorkingDataModified);
     m_ToolManager->ReferenceDataChanged -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
       this, &QmitkSlicesInterpolator::OnToolManagerReferenceDataModified);
   }
 
   auto* timeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController();
   timeNavigationController->RemoveObserver(m_ControllerToTimeObserverTag);
 
 for (auto* slicer : m_ControllerToSliceObserverTag.keys())
   {
     slicer->RemoveObserver(m_ControllerToDeleteObserverTag.take(slicer));
     slicer->RemoveObserver(m_ControllerToSliceObserverTag.take(slicer));
   }
 
   this->ClearSegmentationObservers();
   m_ActionToSlicerMap.clear();
   m_ToolManager = nullptr;
 
   m_Initialized = false;
 }
 
 QmitkSlicesInterpolator::~QmitkSlicesInterpolator()
 {
   if (m_Initialized)
   {
     // remove old observers
     this->Uninitialize();
   }
 
   WaitForFutures();
 
   if (m_DataStorage.IsNotNull())
   {
     m_DataStorage->RemoveNodeEvent.RemoveListener(
       mitk::MessageDelegate1<QmitkSlicesInterpolator, const mitk::DataNode*>(this, &QmitkSlicesInterpolator::NodeRemoved)
     );
     if (m_DataStorage->Exists(m_3DContourNode))
       m_DataStorage->Remove(m_3DContourNode);
     if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
       m_DataStorage->Remove(m_InterpolatedSurfaceNode);
   }
 
   // remove observer
   m_Interpolator->RemoveObserver(InterpolationAbortedObserverTag);
   m_Interpolator->RemoveObserver(InterpolationInfoChangedObserverTag);
   m_SurfaceInterpolator->RemoveObserver(SurfaceInterpolationInfoChangedObserverTag);
 
-  m_SurfaceInterpolator->UnsetSelectedImage();
+  m_SurfaceInterpolator->SetCurrentInterpolationSession(nullptr);
 
   delete m_Timer;
 }
 
 /**
 External enableization...
 */
 void QmitkSlicesInterpolator::setEnabled(bool enable)
 {
   QWidget::setEnabled(enable);
 
   // Set the gui elements of the different interpolation modi enabled
   if (enable)
   {
     if (m_2DInterpolationEnabled)
     {
       this->Show2DInterpolationControls(true);
       m_Interpolator->Activate2DInterpolation(true);
     }
     else if (m_3DInterpolationEnabled)
     {
       this->Show3DInterpolationControls(true);
       this->Show3DInterpolationResult(true);
     }
   }
   // Set all gui elements of the interpolation disabled
   else
   {
     this->HideAllInterpolationControls();
     this->Show3DInterpolationResult(false);
   }
 }
 
 void QmitkSlicesInterpolator::On2DInterpolationEnabled(bool status)
 {
   OnInterpolationActivated(status);
   m_Interpolator->Activate2DInterpolation(status);
 }
 
 void QmitkSlicesInterpolator::On3DInterpolationEnabled(bool status)
 {
   On3DInterpolationActivated(status);
 }
 
 void QmitkSlicesInterpolator::OnInterpolationDisabled(bool status)
 {
   if (status)
   {
     OnInterpolationActivated(!status);
     On3DInterpolationActivated(!status);
     this->Show3DInterpolationResult(false);
   }
 }
 
 void QmitkSlicesInterpolator::HideAllInterpolationControls()
 {
   this->Show2DInterpolationControls(false);
   this->Show3DInterpolationControls(false);
 }
 
 void QmitkSlicesInterpolator::Show2DInterpolationControls(bool show)
 {
   m_BtnApply2D->setVisible(show);
   m_BtnApplyForAllSlices2D->setVisible(show);
 }
 
 void QmitkSlicesInterpolator::Show3DInterpolationControls(bool show)
 {
   m_BtnApply3D->setVisible(show);
 
   // T28261
   // m_BtnSuggestPlane->setVisible(show);
 
   m_ChkShowPositionNodes->setVisible(show);
   m_BtnReinit3DInterpolation->setVisible(show);
 }
 
 void QmitkSlicesInterpolator::OnInterpolationMethodChanged(int index)
 {
   switch (index)
   {
     case 0: // Disabled
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation");
       this->HideAllInterpolationControls();
       this->OnInterpolationActivated(false);
       this->On3DInterpolationActivated(false);
       this->Show3DInterpolationResult(false);
       m_Interpolator->Activate2DInterpolation(false);
       break;
 
     case 1: // 2D
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
       this->HideAllInterpolationControls();
       this->Show2DInterpolationControls(true);
       this->OnInterpolationActivated(true);
       this->On3DInterpolationActivated(false);
       this->Show3DInterpolationResult(false);
       m_Interpolator->Activate2DInterpolation(true);
       break;
 
     case 2: // 3D
       m_GroupBoxEnableExclusiveInterpolationMode->setTitle("Interpolation (Enabled)");
       this->HideAllInterpolationControls();
       this->Show3DInterpolationControls(true);
       this->OnInterpolationActivated(false);
       this->On3DInterpolationActivated(true);
       m_Interpolator->Activate2DInterpolation(false);
       break;
 
     default:
       MITK_ERROR << "Unknown interpolation method!";
       m_CmbInterpolation->setCurrentIndex(0);
       break;
   }
 }
 
 void QmitkSlicesInterpolator::OnShowMarkers(bool state)
 {
   mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers =
     m_DataStorage->GetSubset(mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true)));
 
   for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End();
        ++it)
   {
     it->Value()->SetProperty("helper object", mitk::BoolProperty::New(!state));
   }
 }
 
 void QmitkSlicesInterpolator::OnToolManagerWorkingDataModified()
 {
   this->ClearSegmentationObservers();
 
   if (m_ToolManager->GetWorkingData(0) != nullptr)
   {
     m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
     auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
     m_BtnReinit3DInterpolation->setEnabled(true);
     try {
       if (m_SegmentationObserverTags.find(labelSetImage) == m_SegmentationObserverTags.end())
       {
         auto command2 = itk::MemberCommand<QmitkSlicesInterpolator>::New();
         command2->SetCallbackFunction(this, &QmitkSlicesInterpolator::OnModifyLabelChanged);
         auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
         m_SegmentationObserverTags[workingImage] = workingImage->AddObserver(itk::ModifiedEvent(), command2);
       }
     }
     catch (const std::exception& e)
     {
       MITK_ERROR << "Error casting node data to LabelSetImage\n";
     }
   }
   else
   {
     // If no workingdata is set, remove the interpolation feedback
     this->GetDataStorage()->Remove(m_FeedbackNode);
     m_FeedbackNode->SetData(nullptr);
     this->GetDataStorage()->Remove(m_3DContourNode);
     m_3DContourNode->SetData(nullptr);
     this->GetDataStorage()->Remove(m_InterpolatedSurfaceNode);
     m_InterpolatedSurfaceNode->SetData(nullptr);
     m_BtnReinit3DInterpolation->setEnabled(false);
     m_CmbInterpolation->setCurrentIndex(0);
     return;
 
   }
   // Updating the current selected segmentation for the 3D interpolation
   this->SetCurrentContourListID();
 
   if (m_2DInterpolationEnabled)
   {
     OnInterpolationActivated(true); // re-initialize if needed
   }
 }
 
 void QmitkSlicesInterpolator::OnToolManagerReferenceDataModified()
 {
 }
 
 void QmitkSlicesInterpolator::OnTimeChanged(itk::Object *sender, const itk::EventObject &e)
 {
   if (!dynamic_cast<const mitk::TimeNavigationController::TimeEvent*>(&e))
   {
     return;
   }
 
   const auto* timeNavigationController = dynamic_cast<mitk::TimeNavigationController*>(sender);
   if (nullptr == timeNavigationController)
   {
     return;
   }
 
   m_TimePoint = timeNavigationController->GetSelectedTimePoint();
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_TimePoint != m_SurfaceInterpolator->GetCurrentTimePoint())
   {
     m_SurfaceInterpolator->SetCurrentTimePoint(m_TimePoint);
     if (m_3DInterpolationEnabled)
     {
       m_3DContourNode->SetData(nullptr);
       m_InterpolatedSurfaceNode->SetData(nullptr);
     }
     m_SurfaceInterpolator->Modified();
   }
 
   if (nullptr == m_LastSNC)
   {
     return;
   }
 
   if (TranslateAndInterpolateChangedSlice(m_LastSNC->GetCreatedWorldGeometry()))
   {
     m_LastSNC->GetRenderer()->RequestUpdate();
   }
 }
 
 void QmitkSlicesInterpolator::OnSliceChanged(itk::Object *sender, const itk::EventObject &e)
 {
   if (!dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e))
   {
     return;
   }
 
   auto sliceNavigationController = dynamic_cast<mitk::SliceNavigationController*>(sender);
   if (nullptr == sliceNavigationController)
   {
     return;
   }
 
   if(m_2DInterpolationEnabled)
   {
     this->On2DInterpolationEnabled(m_2DInterpolationEnabled);
   }  
 
   if (TranslateAndInterpolateChangedSlice(e, sliceNavigationController))
   {
     sliceNavigationController->GetRenderer()->RequestUpdate();
   }
 }
 
 bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const itk::EventObject& e,
   mitk::SliceNavigationController* sliceNavigationController)
 {
   const mitk::SliceNavigationController::GeometrySliceEvent* event =
     dynamic_cast<const mitk::SliceNavigationController::GeometrySliceEvent*>(&e);
 
   mitk::TimeGeometry* timeGeometry = event->GetTimeGeometry();
   m_LastSNC = sliceNavigationController;
 
   return this->TranslateAndInterpolateChangedSlice(timeGeometry);
 }
 
 bool QmitkSlicesInterpolator::TranslateAndInterpolateChangedSlice(const mitk::TimeGeometry* timeGeometry)
 {
   if (!m_2DInterpolationEnabled)
   {
     return false;
   }
 
   if (nullptr == timeGeometry)
   {
     return false;
   }
 
   if (!timeGeometry->IsValidTimePoint(m_TimePoint))
   {
     return false;
   }
 
   mitk::SlicedGeometry3D* slicedGeometry =
     dynamic_cast<mitk::SlicedGeometry3D*>(timeGeometry->GetGeometryForTimePoint(m_TimePoint).GetPointer());
   if (nullptr == slicedGeometry)
   {
     return false;
   }
 
   mitk::PlaneGeometry* plane = dynamic_cast<mitk::PlaneGeometry*>(slicedGeometry->GetPlaneGeometry(m_LastSNC->GetStepper()->GetPos()));
   if (nullptr == plane)
   {
     return false;
   }
 
   this->Interpolate(plane);
   return true;
 }
 
-void QmitkSlicesInterpolator::OnLayerChanged()
-{
-  auto* workingNode = m_ToolManager->GetWorkingData(0);
-
-  if (workingNode != nullptr)
-  {
-    m_3DContourNode->SetData(nullptr);
-    this->Show3DInterpolationResult(false);
-  }
-
-  if (m_3DInterpolationEnabled)
-  {
-    m_SurfaceInterpolator->Modified();
-  }
-  if (m_2DInterpolationEnabled)
-  {
-    m_FeedbackNode->SetData(nullptr);
-    this->OnInterpolationActivated(true);
-    m_LastSNC->SendSlice();
-  }
-  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
-  this->UpdateVisibleSuggestion();
-}
+//void QmitkSlicesInterpolator::OnLayerChanged()
+//{
+//  auto* workingNode = m_ToolManager->GetWorkingData(0);
+//
+//  if (workingNode != nullptr)
+//  {
+//    m_3DContourNode->SetData(nullptr);
+//    this->Show3DInterpolationResult(false);
+//  }
+//
+//  if (m_3DInterpolationEnabled)
+//  {
+//    m_SurfaceInterpolator->Modified();
+//  }
+//  if (m_2DInterpolationEnabled)
+//  {
+//    m_FeedbackNode->SetData(nullptr);
+//    this->OnInterpolationActivated(true);
+//    m_LastSNC->SendSlice();
+//  }
+//  mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+//  this->UpdateVisibleSuggestion();
+//}
 
 void QmitkSlicesInterpolator::Interpolate(mitk::PlaneGeometry *plane)
 {
   if (nullptr == m_ToolManager)
   {
     return;
   }
 
   mitk::DataNode* node = m_ToolManager->GetWorkingData(0);
   if (nullptr == node)
   {
     return;
   }
 
   m_Segmentation = dynamic_cast<mitk::Image*>(node->GetData());
   if (nullptr == m_Segmentation)
   {
     return;
   }
 
   if (!m_Segmentation->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot interpolate WorkingImage. Passed time point is not within the time bounds of WorkingImage. "
                  "Time point: "
               << m_TimePoint;
     return;
   }
 
   const auto timeStep = m_Segmentation->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
   int clickedSliceDimension = -1;
   int clickedSliceIndex = -1;
 
   // calculate real slice position, i.e. slice of the image
   mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, plane, clickedSliceDimension, clickedSliceIndex);
 
   mitk::Image::Pointer interpolation =
     m_Interpolator->Interpolate(clickedSliceDimension, clickedSliceIndex, plane, timeStep);
   m_FeedbackNode->SetData(interpolation);
 
   //  maybe just have a variable that stores the active label color.
   if (m_ToolManager)
   {
     auto* workingNode = m_ToolManager->GetWorkingData(0);
     if (workingNode != nullptr)
     {
-      auto* activeLabel = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabelSet()->GetActiveLabel();
+      auto* activeLabel = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabel();
       if (nullptr != activeLabel)
       {
         auto activeColor = activeLabel->GetColor();
         m_FeedbackNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
       }
     }
   }
 
   m_LastSliceIndex = clickedSliceIndex;
 }
 
 void QmitkSlicesInterpolator::OnSurfaceInterpolationFinished()
 {
   mitk::Surface::Pointer interpolatedSurface = m_SurfaceInterpolator->GetInterpolationResult();
 
   mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
 
   mitk::PlaneGeometry::Pointer slicingPlane = mitk::PlaneGeometry::New();
   mitk::Vector3D slicingPlaneNormalVector;
   FillVector3D(slicingPlaneNormalVector,0.0,1.0,0.0);
   mitk::Point3D origin;
   FillVector3D(origin, 0.0, 0.0, 0.0);
   slicingPlane->InitializePlane(origin, slicingPlaneNormalVector);
 
   if (interpolatedSurface.IsNotNull() && workingNode)
   {
     m_BtnApply3D->setEnabled(true);
 
     // T28261
     // m_BtnSuggestPlane->setEnabled(true);
 
     m_InterpolatedSurfaceNode->SetData(interpolatedSurface);
 
     m_3DContourNode->SetData(m_SurfaceInterpolator->GetContoursAsSurface());
 
     this->Show3DInterpolationResult(true);
 
     if (!m_DataStorage->Exists(m_InterpolatedSurfaceNode))
     {
       m_DataStorage->Add(m_InterpolatedSurfaceNode);
     }
   }
   else if (interpolatedSurface.IsNull())
   {
     m_BtnApply3D->setEnabled(false);
 
     // T28261
     // m_BtnSuggestPlane->setEnabled(false);
 
     if (m_DataStorage->Exists(m_InterpolatedSurfaceNode))
     {
       this->Show3DInterpolationResult(false);
     }
   }
 
   m_BtnReinit3DInterpolation->setEnabled(true);
 
   for (auto* slicer : m_ControllerToSliceObserverTag.keys())
   {
     slicer->GetRenderer()->RequestUpdate();
   }
   m_SurfaceInterpolator->ReinitializeInterpolation();
 }
 
 void QmitkSlicesInterpolator::OnAcceptInterpolationClicked()
 {
   auto* workingNode = m_ToolManager->GetWorkingData(0);
   auto* planeGeometry = m_LastSNC->GetCurrentPlaneGeometry();
   auto* interpolatedPreview = dynamic_cast<mitk::Image*>(m_FeedbackNode->GetData());
   if (nullptr == workingNode || nullptr == interpolatedPreview)
     return;
 
   auto* segmentationImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
   if (nullptr == segmentationImage)
     return;
 
   if (!segmentationImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the "
       "time bounds of segmentation. Time point: "
       << m_TimePoint;
     return;
   }
 
   const auto timeStep = segmentationImage->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
   auto interpolatedSlice = mitk::SegTool2D::GetAffectedImageSliceAs2DImage(planeGeometry, segmentationImage, timeStep)->Clone();
-  auto labelSet = segmentationImage->GetActiveLabelSet();
-  auto activeValue = labelSet->GetActiveLabel()->GetValue();
+  auto activeValue = segmentationImage->GetActiveLabel()->GetValue();
   mitk::TransferLabelContentAtTimeStep(
     interpolatedPreview,
     interpolatedSlice,
-    labelSet,
+    segmentationImage->GetConstLabelsByValue(segmentationImage->GetLabelValuesByGroup(segmentationImage->GetActiveLayer())),
     timeStep,
     0,
     mitk::LabelSetImage::UnlabeledValue,
     false,
     { {0, mitk::LabelSetImage::UnlabeledValue}, {1, activeValue} }
   );
 
   mitk::SegTool2D::WriteBackSegmentationResult(workingNode, planeGeometry, interpolatedSlice, timeStep);
   m_FeedbackNode->SetData(nullptr);
 }
 
 void QmitkSlicesInterpolator::AcceptAllInterpolations(mitk::SliceNavigationController *slicer)
 {
   /*
    * What exactly is done here:
    * 1. We create an empty diff image for the current segmentation
    * 2. All interpolated slices are written into the diff image
    * 3. Then the diffimage is applied to the original segmentation
    */
   if (m_Segmentation)
   {
     mitk::Image::Pointer segmentation3D = m_Segmentation;
     unsigned int timeStep = 0;
 
     if (4 == m_Segmentation->GetDimension())
     {
       const auto* geometry = m_Segmentation->GetTimeGeometry();
 
       if (!geometry->IsValidTimePoint(m_TimePoint))
       {
         MITK_WARN << "Cannot accept all interpolations. Time point selected by passed SliceNavigationController is not "
                      "within the time bounds of segmentation. Time point: "
                   << m_TimePoint;
         return;
       }
 
       mitk::Image::Pointer activeLabelImage;
       try
       {
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation);
-        activeLabelImage = labelSetImage->CreateLabelMask(labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue(), true, 0);
+        activeLabelImage = labelSetImage->CreateLabelMask(labelSetImage->GetActiveLabel()->GetValue());
       }
       catch (const std::exception& e)
       {
         MITK_ERROR << e.what() << " | NO LABELSETIMAGE IN WORKING NODE\n";
       }
 
       m_Interpolator->SetSegmentationVolume(activeLabelImage);
 
       timeStep = geometry->TimePointToTimeStep(m_TimePoint);
 
       auto timeSelector = mitk::ImageTimeSelector::New();
       timeSelector->SetInput(m_Segmentation);
       timeSelector->SetTimeNr(timeStep);
       timeSelector->Update();
 
       segmentation3D = timeSelector->GetOutput();
     }
 
     // Create an empty diff image for the undo operation
     auto diffImage = mitk::Image::New();
     diffImage->Initialize(segmentation3D);
 
     // Create scope for ImageWriteAccessor so that the accessor is destroyed right after use
     {
       mitk::ImageWriteAccessor accessor(diffImage);
 
       // Set all pixels to zero
       auto pixelType = mitk::MakeScalarPixelType<mitk::Tool::DefaultSegmentationDataType>();
 
       // For legacy purpose support former pixel type of segmentations (before multilabel)
       if (itk::IOComponentEnum::UCHAR == m_Segmentation->GetImageDescriptor()->GetChannelDescriptor().GetPixelType().GetComponentType())
         pixelType = mitk::MakeScalarPixelType<unsigned char>();
 
       memset(accessor.GetData(), 0, pixelType.GetSize() * diffImage->GetDimension(0) * diffImage->GetDimension(1) * diffImage->GetDimension(2));
     }
 
     // Since we need to shift the plane it must be clone so that the original plane isn't altered
     auto slicedGeometry = m_Segmentation->GetSlicedGeometry();
     auto planeGeometry = slicer->GetCurrentPlaneGeometry()->Clone();
     int sliceDimension = -1;
     int sliceIndex = -1;
 
     mitk::SegTool2D::DetermineAffectedImageSlice(m_Segmentation, planeGeometry, sliceDimension, sliceIndex);
 
     const auto numSlices = m_Segmentation->GetDimension(sliceDimension);
     mitk::ProgressBar::GetInstance()->AddStepsToDo(numSlices);
 
     std::atomic_uint totalChangedSlices;
 
     // Reuse interpolation algorithm instance for each slice to cache boundary calculations
     auto algorithm = mitk::ShapeBasedInterpolationAlgorithm::New();
 
     // Distribute slice interpolations to multiple threads
     const auto numThreads = std::min(std::thread::hardware_concurrency(), numSlices);
     // const auto numThreads = 1;
     std::vector<std::vector<unsigned int>> sliceIndices(numThreads);
 
     for (std::remove_const_t<decltype(numSlices)> sliceIndex = 0; sliceIndex < numSlices; ++sliceIndex)
       sliceIndices[sliceIndex % numThreads].push_back(sliceIndex);
 
     std::vector<std::thread> threads;
     threads.reserve(numThreads);
 
     // This lambda will be executed by the threads
     auto interpolate = [=, &interpolator = m_Interpolator, &totalChangedSlices](unsigned int threadIndex)
     {
       auto clonedPlaneGeometry = planeGeometry->Clone();
       auto origin = clonedPlaneGeometry->GetOrigin();
 
       //  Go through the sliced indices
       for (auto sliceIndex : sliceIndices[threadIndex])
       {
         slicedGeometry->WorldToIndex(origin, origin);
         origin[sliceDimension] = sliceIndex;
         slicedGeometry->IndexToWorld(origin, origin);
         clonedPlaneGeometry->SetOrigin(origin);
 
         auto interpolation = interpolator->Interpolate(sliceDimension, sliceIndex, clonedPlaneGeometry, timeStep, algorithm);
 
         if (interpolation.IsNotNull())
         {
           // Setting up the reslicing pipeline which allows us to write the interpolation results back into the image volume
           auto reslicer = vtkSmartPointer<mitkVtkImageOverwrite>::New();
 
           // Set overwrite mode to true to write back to the image volume
           reslicer->SetInputSlice(interpolation->GetSliceData()->GetVtkImageAccessor(interpolation)->GetVtkImageData());
           reslicer->SetOverwriteMode(true);
           reslicer->Modified();
 
           auto diffSliceWriter = mitk::ExtractSliceFilter::New(reslicer);
 
           diffSliceWriter->SetInput(diffImage);
           diffSliceWriter->SetTimeStep(0);
           diffSliceWriter->SetWorldGeometry(clonedPlaneGeometry);
           diffSliceWriter->SetVtkOutputRequest(true);
           diffSliceWriter->SetResliceTransformByGeometry(diffImage->GetTimeGeometry()->GetGeometryForTimeStep(0));
           diffSliceWriter->Modified();
           diffSliceWriter->Update();
 
           ++totalChangedSlices;
         }
 
         mitk::ProgressBar::GetInstance()->Progress();
       }
     };
     m_Interpolator->EnableSliceImageCache();
 
     //  Do the interpolation here.
     for (size_t threadIndex = 0; threadIndex < numThreads; ++threadIndex)
     {
       interpolate(threadIndex);
     }
 
     m_Interpolator->DisableSliceImageCache();
 
-    const mitk::Label::PixelType newDestinationLabel = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation)->GetActiveLabelSet()->GetActiveLabel()->GetValue();
+    const mitk::Label::PixelType newDestinationLabel = dynamic_cast<mitk::LabelSetImage *>(m_Segmentation)->GetActiveLabel()->GetValue();
 
     //  Do and Undo Operations
     if (totalChangedSlices > 0)
     {
       // Create do/undo operations
       auto* doOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
 
       auto* undoOp = new mitk::ApplyDiffImageOperation(mitk::OpTEST, m_Segmentation, diffImage, timeStep);
       undoOp->SetFactor(-1.0);
 
       auto comment = "Confirm all interpolations (" + std::to_string(totalChangedSlices) + ")";
       auto* undoStackItem = new mitk::OperationEvent(mitk::DiffImageApplier::GetInstanceForUndo(), doOp, undoOp, comment);
 
       mitk::OperationEvent::IncCurrGroupEventId();
       mitk::OperationEvent::IncCurrObjectEventId();
       mitk::UndoController::GetCurrentUndoModel()->SetOperationEvent(undoStackItem);
       mitk::DiffImageApplier::GetInstanceForUndo()->SetDestinationLabel(newDestinationLabel);
       // Apply the changes to the original image
       mitk::DiffImageApplier::GetInstanceForUndo()->ExecuteOperation(doOp);
     }
     m_FeedbackNode->SetData(nullptr);
   }
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::FinishInterpolation(mitk::SliceNavigationController *slicer)
 {
   // this redirect is for calling from outside
   if (slicer == nullptr)
     OnAcceptAllInterpolationsClicked();
   else
     AcceptAllInterpolations(slicer);
 }
 
 void QmitkSlicesInterpolator::OnAcceptAllInterpolationsClicked()
 {
   QMenu orientationPopup(this);
   for (auto it = m_ActionToSlicerMap.begin(); it != m_ActionToSlicerMap.end(); ++it)
   {
     orientationPopup.addAction(it->first);
   }
 
   connect(&orientationPopup, SIGNAL(triggered(QAction *)), this, SLOT(OnAcceptAllPopupActivated(QAction *)));
   orientationPopup.exec(QCursor::pos());
 }
 
 void QmitkSlicesInterpolator::OnAccept3DInterpolationClicked()
 {
   auto referenceImage = GetData<mitk::Image>(m_ToolManager->GetReferenceData(0));
 
   auto* segmentationDataNode = m_ToolManager->GetWorkingData(0);
 
   auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(segmentationDataNode->GetData());
-  auto activeLabelColor = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetColor();
-  std::string activeLabelName = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetName();
+  auto activeLabelColor = labelSetImage->GetActiveLabel()->GetColor();
+  std::string activeLabelName = labelSetImage->GetActiveLabel()->GetName();
 
   auto segmentation = GetData<mitk::Image>(segmentationDataNode);
 
   if (referenceImage.IsNull() || segmentation.IsNull())
     return;
 
   const auto* segmentationGeometry = segmentation->GetTimeGeometry();
 
   if (!referenceImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint) ||
       !segmentationGeometry->IsValidTimePoint(m_TimePoint))
   {
     MITK_WARN << "Cannot accept interpolation. Current time point is not within the time bounds of the patient image and segmentation.";
     return;
   }
 
   auto interpolatedSurface = GetData<mitk::Surface>(m_InterpolatedSurfaceNode);
 
   if (interpolatedSurface.IsNull())
     return;
 
   auto surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
 
   surfaceToImageFilter->SetImage(referenceImage);
   surfaceToImageFilter->SetMakeOutputBinary(true);
   surfaceToImageFilter->SetUShortBinaryPixelType(itk::IOComponentEnum::USHORT == segmentation->GetPixelType().GetComponentType());
   surfaceToImageFilter->SetInput(interpolatedSurface);
   surfaceToImageFilter->Update();
 
   mitk::Image::Pointer interpolatedSegmentation = surfaceToImageFilter->GetOutput();
   auto timeStep = segmentationGeometry->TimePointToTimeStep(m_TimePoint);
-  const mitk::Label::PixelType newDestinationLabel = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue();
+  const mitk::Label::PixelType newDestinationLabel = labelSetImage->GetActiveLabel()->GetValue();
 
   TransferLabelContentAtTimeStep(
     interpolatedSegmentation,
     labelSetImage,
-    labelSetImage->GetActiveLabelSet(),
+    labelSetImage->GetConstLabelsByValue(labelSetImage->GetLabelValuesByGroup(labelSetImage->GetActiveLayer())),
     timeStep,
     0,
     0,
     false,
     {{1, newDestinationLabel}},
     mitk::MultiLabelSegmentation::MergeStyle::Merge,
     mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks);
 
   this->Show3DInterpolationResult(false);
 
   std::string name = segmentationDataNode->GetName() + " 3D-interpolation - " + activeLabelName;
   mitk::TimeBounds timeBounds;
 
   if (1 < interpolatedSurface->GetTimeSteps())
   {
     name += "_t" + std::to_string(timeStep);
 
     auto* polyData = vtkPolyData::New();
     polyData->DeepCopy(interpolatedSurface->GetVtkPolyData(timeStep));
 
     auto surface = mitk::Surface::New();
     surface->SetVtkPolyData(polyData);
 
     interpolatedSurface = surface;
     timeBounds = segmentationGeometry->GetTimeBounds(timeStep);
   }
   else
   {
     timeBounds = segmentationGeometry->GetTimeBounds(0);
   }
 
   auto* surfaceGeometry = static_cast<mitk::ProportionalTimeGeometry*>(interpolatedSurface->GetTimeGeometry());
   surfaceGeometry->SetFirstTimePoint(timeBounds[0]);
   surfaceGeometry->SetStepDuration(timeBounds[1] - timeBounds[0]);
 
   // Typical file formats for surfaces do not save any time-related information. As a workaround at least for MITK scene files, we have the
   // possibility to seralize this information as properties.
 
   interpolatedSurface->SetProperty("ProportionalTimeGeometry.FirstTimePoint", mitk::FloatProperty::New(surfaceGeometry->GetFirstTimePoint()));
   interpolatedSurface->SetProperty("ProportionalTimeGeometry.StepDuration", mitk::FloatProperty::New(surfaceGeometry->GetStepDuration()));
 
   auto interpolatedSurfaceDataNode = mitk::DataNode::New();
 
   interpolatedSurfaceDataNode->SetData(interpolatedSurface);
   interpolatedSurfaceDataNode->SetName(name);
   interpolatedSurfaceDataNode->SetOpacity(0.7f);
 
   interpolatedSurfaceDataNode->SetColor(activeLabelColor);
   m_DataStorage->Add(interpolatedSurfaceDataNode, segmentationDataNode);
 }
 
 void QmitkSlicesInterpolator::OnReinit3DInterpolation()
 {
   //  Step 1. Load from the isContourPlaneGeometry nodes the contourNodes.
   mitk::NodePredicateProperty::Pointer pred =
     mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
   mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
     m_DataStorage->GetDerivations(m_ToolManager->GetWorkingData(0), pred);
 
   if (contourNodes->Size() != 0)
   {
     std::vector<const mitk::PlaneGeometry*> contourPlanes;
     std::vector<mitk::Surface::Pointer> contourList;
     if (m_ToolManager->GetWorkingData(0) != nullptr)
     {
       try
       {
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
         auto activeLayerID = labelSetImage->GetActiveLayer();
         if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
         {
           MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
           return;
         }
 
         //  Adding layer, label and timeStep information for the contourNodes.
         for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
         {
           auto contourNode = it->Value();
           auto layerID = dynamic_cast<mitk::UIntProperty *>(contourNode->GetProperty("layerID"))->GetValue();
           auto labelID = dynamic_cast<mitk::UShortProperty *>(contourNode->GetProperty("labelID"))->GetValue();
           auto timeStep = dynamic_cast<mitk::IntProperty *>(contourNode->GetProperty("timeStep"))->GetValue();
 
           auto px = dynamic_cast<mitk::DoubleProperty *>(contourNode->GetProperty("px"))->GetValue();
           auto py = dynamic_cast<mitk::DoubleProperty *>(contourNode->GetProperty("py"))->GetValue();
           auto pz = dynamic_cast<mitk::DoubleProperty *>(contourNode->GetProperty("pz"))->GetValue();
 
           // auto layerImage = labelSetImage->GetLayerImage(layerID);
 
           auto planeGeometry = dynamic_cast<mitk::PlanarFigure *>(contourNode->GetData())->GetPlaneGeometry();
           labelSetImage->SetActiveLayer(layerID);
           auto sliceImage = ExtractSliceFromImage(labelSetImage, planeGeometry, timeStep);
           labelSetImage->SetActiveLayer(activeLayerID);
           mitk::ImageToContourFilter::Pointer contourExtractor = mitk::ImageToContourFilter::New();
           contourExtractor->SetInput(sliceImage);
           contourExtractor->SetContourValue(labelID);
           contourExtractor->Update();
           mitk::Surface::Pointer contour = contourExtractor->GetOutput();
 
           if (contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
             continue;
 
           vtkSmartPointer<vtkIntArray> intArray = vtkSmartPointer<vtkIntArray>::New();
           intArray->InsertNextValue(labelID);
           intArray->InsertNextValue(layerID);
           intArray->InsertNextValue(timeStep);
           contour->GetVtkPolyData()->GetFieldData()->AddArray(intArray);
           vtkSmartPointer<vtkDoubleArray> doubleArray = vtkSmartPointer<vtkDoubleArray>::New();
           doubleArray->InsertNextValue(px);
           doubleArray->InsertNextValue(py);
           doubleArray->InsertNextValue(pz);
           contour->GetVtkPolyData()->GetFieldData()->AddArray(doubleArray);
           contour->DisconnectPipeline();
           contourList.push_back(contour);
           contourPlanes.push_back(planeGeometry);
         }
         labelSetImage->SetActiveLayer(activeLayerID);
         // size_t activeLayer = labelSetImage->GetActiveLayer();
         for (size_t l = 0; l < labelSetImage->GetNumberOfLayers(); ++l)
         {
           this->OnAddLabelSetConnection(l);
         }
         // labelSetImage->SetActiveLayer(activeLayer);
         m_SurfaceInterpolator->CompleteReinitialization(contourList, contourPlanes);
       }
       catch(const std::exception& e)
       {
         MITK_ERROR << "Exception thrown casting toolmanager working data to labelsetImage";
       }
     }
   }
   else
   {
     m_BtnApply3D->setEnabled(false);
     QMessageBox errorInfo;
     errorInfo.setWindowTitle("Reinitialize surface interpolation");
     errorInfo.setIcon(QMessageBox::Information);
     errorInfo.setText("No contours available for the selected segmentation!");
     errorInfo.exec();
   }
 }
 
 void QmitkSlicesInterpolator::OnAcceptAllPopupActivated(QAction *action)
 {
   try
   {
     auto iter = m_ActionToSlicerMap.find(action);
     if (iter != m_ActionToSlicerMap.end())
     {
       mitk::SliceNavigationController *slicer = iter->second;
       this->AcceptAllInterpolations(slicer);
     }
   }
   catch (...)
   {
     /* Showing message box with possible memory error */
     QMessageBox errorInfo;
     errorInfo.setWindowTitle("Interpolation Process");
     errorInfo.setIcon(QMessageBox::Critical);
     errorInfo.setText("An error occurred during interpolation. Possible cause: Not enough memory!");
     errorInfo.exec();
 
     // additional error message on std::cerr
     std::cerr << "Ill construction in " __FILE__ " l. " << __LINE__ << std::endl;
   }
 }
 
 void QmitkSlicesInterpolator::OnInterpolationActivated(bool on)
 {
   m_2DInterpolationEnabled = on;
 
   try
   {
     if (m_DataStorage.IsNotNull())
     {
       if (on && !m_DataStorage->Exists(m_FeedbackNode))
       {
         m_DataStorage->Add(m_FeedbackNode);
       }
     }
   }
   catch (...)
   {
     // don't care (double add/remove)
   }
 
   if (m_ToolManager)
   {
     mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
     mitk::DataNode *referenceNode = m_ToolManager->GetReferenceData(0);
     QWidget::setEnabled(workingNode != nullptr);
 
     m_BtnApply2D->setEnabled(on);
     m_FeedbackNode->SetVisibility(on);
 
     if (!on)
     {
       mitk::RenderingManager::GetInstance()->RequestUpdateAll();
       return;
     }
 
     if (workingNode)
     {
       auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
       if (nullptr == labelSetImage)
       {
         MITK_ERROR << "NO LABELSETIMAGE IN WORKING NODE\n";
         mitk::RenderingManager::GetInstance()->RequestUpdateAll();
         return;
       }
 
-      auto* activeLabel = labelSetImage->GetActiveLabelSet()->GetActiveLabel();
-      auto* segmentation = dynamic_cast<mitk::Image*>(workingNode->GetData());
+      const auto* activeLabel = labelSetImage->GetActiveLabel();
+      const auto* segmentation = dynamic_cast<mitk::Image*>(workingNode->GetData());
       if (nullptr != activeLabel && nullptr != segmentation)
       {
-        auto activeLabelImage = labelSetImage->CreateLabelMask(activeLabel->GetValue(), true, 0);
+        auto activeLabelImage = labelSetImage->CreateLabelMask(activeLabel->GetValue());
         m_Interpolator->SetSegmentationVolume(activeLabelImage);
 
         if (referenceNode)
         {
           mitk::Image *referenceImage = dynamic_cast<mitk::Image *>(referenceNode->GetData());
           m_Interpolator->SetReferenceVolume(referenceImage); // may be nullptr
         }
       }
     }
   }
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::Run3DInterpolation()
 {
   m_SurfaceInterpolator->Interpolate();
 }
 
 void QmitkSlicesInterpolator::StartUpdateInterpolationTimer()
 {
   m_Timer->start(500);
 }
 
 void QmitkSlicesInterpolator::StopUpdateInterpolationTimer()
 {
   if(m_ToolManager)
   {
-    auto* workingNode = m_ToolManager->GetWorkingData(0);
-    auto activeColor = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabelSet()->GetActiveLabel()->GetColor();
+    const auto* workingNode = m_ToolManager->GetWorkingData(0);
+    const auto activeColor = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData())->GetActiveLabel()->GetColor();
     m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
     m_3DContourNode->SetProperty("color", mitk::ColorProperty::New(activeColor));
   }
 
   m_Timer->stop();
 }
 
 void QmitkSlicesInterpolator::ChangeSurfaceColor()
 {
   float currentColor[3];
   m_InterpolatedSurfaceNode->GetColor(currentColor);
 
     m_InterpolatedSurfaceNode->SetProperty("color", mitk::ColorProperty::New(SURFACE_COLOR_RGB));
   m_InterpolatedSurfaceNode->Update();
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS);
 }
 
 void QmitkSlicesInterpolator::PrepareInputsFor3DInterpolation()
 {
   if (m_DataStorage.IsNotNull() && m_ToolManager && m_3DInterpolationEnabled)
   {
     auto *workingNode = m_ToolManager->GetWorkingData(0);
     if (workingNode != nullptr)
     {
       int ret = QMessageBox::Yes;
 
       if (m_SurfaceInterpolator->EstimatePortionOfNeededMemory() > 0.5)
       {
         QMessageBox msgBox;
         msgBox.setText("Due to short handed system memory the 3D interpolation may be very slow!");
         msgBox.setInformativeText("Are you sure you want to activate the 3D interpolation?");
         msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
         ret = msgBox.exec();
       }
 
       auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
-      auto activeLabel = labelSetImage->GetActiveLabelSet()->GetActiveLabel()->GetValue();
+      const auto activeLabel = labelSetImage->GetActiveLabel()->GetValue();
 
       m_SurfaceInterpolator->AddActiveLabelContoursForInterpolation(activeLabel);
 
       if (m_Watcher.isRunning())
         m_Watcher.waitForFinished();
 
       if (ret == QMessageBox::Yes)
       {
         //  Maybe set the segmentation node here
         m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
         m_Watcher.setFuture(m_Future);
       }
       else
       {
         m_CmbInterpolation->setCurrentIndex(0);
       }
     }
     else
     {
       QWidget::setEnabled(false);
       m_ChkShowPositionNodes->setEnabled(m_3DInterpolationEnabled);
     }
 
   }
   if (!m_3DInterpolationEnabled)
   {
     this->Show3DInterpolationResult(false);
     m_BtnApply3D->setEnabled(m_3DInterpolationEnabled);
     // T28261
     // m_BtnSuggestPlane->setEnabled(m_3DInterpolationEnabled);
   }
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::On3DInterpolationActivated(bool on)
 {
   m_3DInterpolationEnabled = on;
   try
   {
     // this->PrepareInputsFor3DInterpolation();
     m_SurfaceInterpolator->Modified();
   }
   catch (...)
   {
     MITK_ERROR << "Error with 3D surface interpolation!";
   }
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::EnableInterpolation(bool on)
 {
   // only to be called from the outside world
   // just a redirection to OnInterpolationActivated
   OnInterpolationActivated(on);
 }
 
 void QmitkSlicesInterpolator::Enable3DInterpolation(bool on)
 {
   // only to be called from the outside world
   // just a redirection to OnInterpolationActivated
   this->On3DInterpolationActivated(on);
 }
 
 void QmitkSlicesInterpolator::UpdateVisibleSuggestion()
 {
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::OnInterpolationInfoChanged(const itk::EventObject & /*e*/)
 {
   // something (e.g. undo) changed the interpolation info, we should refresh our display
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::OnInterpolationAborted(const itk::EventObject& /*e*/)
 {
   m_CmbInterpolation->setCurrentIndex(0);
   m_FeedbackNode->SetData(nullptr);
 }
 
 void QmitkSlicesInterpolator::OnSurfaceInterpolationInfoChanged(const itk::EventObject & /*e*/)
 {
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_3DInterpolationEnabled)
   {
     m_3DContourNode->SetData(nullptr);
     m_InterpolatedSurfaceNode->SetData(nullptr);
     auto* workingNode = m_ToolManager->GetWorkingData(0);
 
     if (workingNode == nullptr)
       return;
 
-    auto* labelSetImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
-    auto* label = labelSetImage->GetActiveLabelSet()->GetActiveLabel();
+    const auto* labelSetImage = dynamic_cast<mitk::LabelSetImage*>(workingNode->GetData());
+    const auto* label = labelSetImage->GetActiveLabel();
 
     if (label == nullptr)
       return;
 
     m_SurfaceInterpolator->AddActiveLabelContoursForInterpolation(label->GetValue());
     m_Future = QtConcurrent::run(this, &QmitkSlicesInterpolator::Run3DInterpolation);
     m_Watcher.setFuture(m_Future);
   }
 }
 
 void QmitkSlicesInterpolator::SetCurrentContourListID()
 {
   // New ContourList = hide current interpolation
   Show3DInterpolationResult(false);
 
   if (m_DataStorage.IsNotNull() && m_ToolManager && m_LastSNC)
   {
     mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0);
 
     try{
         auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
         for (size_t layerID = 0; layerID < labelSetImage->GetNumberOfLayers(); ++layerID)
         {
           this->OnAddLabelSetConnection(layerID);
         }
     }
     catch (std::exception &e)
     {
       MITK_ERROR << e.what() << "\n";
     }
 
     if (workingNode)
     {
       QWidget::setEnabled(true);
 
       // In case the time is not valid use 0 to access the time geometry of the working node
       unsigned int time_position = 0;
       if (!workingNode->GetData()->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
       {
         MITK_WARN << "Cannot accept interpolation. Time point selected by SliceNavigationController is not within the time bounds of WorkingImage. Time point: " << m_TimePoint;
         return;
       }
 
       //  Sets up the surface interpolator to accept
       time_position = workingNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
       mitk::Vector3D spacing = workingNode->GetData()->GetGeometry(time_position)->GetSpacing();
       double minSpacing = 100;
       double maxSpacing = 0;
       for (int i = 0; i < 3; i++)
       {
         if (spacing[i] < minSpacing)
         {
           minSpacing = spacing[i];
         }
         if (spacing[i] > maxSpacing)
         {
           maxSpacing = spacing[i];
         }
       }
 
       m_SurfaceInterpolator->SetMaxSpacing(maxSpacing);
       m_SurfaceInterpolator->SetMinSpacing(minSpacing);
       m_SurfaceInterpolator->SetDistanceImageVolume(50000);
 
-      mitk::Image::Pointer segmentationImage;
-
-      segmentationImage = dynamic_cast<mitk::Image *>(workingNode->GetData());
+      auto segmentationImage = dynamic_cast<mitk::LabelSetImage *>(workingNode->GetData());
       m_SurfaceInterpolator->SetCurrentInterpolationSession(segmentationImage);
       m_SurfaceInterpolator->SetCurrentTimePoint(m_TimePoint);
     }
     else
     {
       QWidget::setEnabled(false);
     }
   }
 }
 
 void QmitkSlicesInterpolator::Show3DInterpolationResult(bool status)
 {
   if (m_InterpolatedSurfaceNode.IsNotNull())
     m_InterpolatedSurfaceNode->SetVisibility(status);
 
   if (m_3DContourNode.IsNotNull())
   {
     auto allRenderWindows = mitk::BaseRenderer::GetAll3DRenderWindows();
     for (auto mapit = allRenderWindows.begin(); mapit != allRenderWindows.end(); ++mapit)
     {
       m_3DContourNode->SetVisibility(status, mapit->second);
     }
   }
 
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
 }
 
 void QmitkSlicesInterpolator::OnActiveLabelChanged(mitk::Label::PixelType)
 {
   m_3DContourNode->SetData(nullptr);
   m_FeedbackNode->SetData(nullptr);
   m_InterpolatedSurfaceNode->SetData(nullptr);
 
   if (m_Watcher.isRunning())
     m_Watcher.waitForFinished();
 
   if (m_3DInterpolationEnabled)
   {
     m_SurfaceInterpolator->Modified();
   }
 
   if (m_2DInterpolationEnabled)
   {
     m_FeedbackNode->SetData(nullptr);
     this->OnInterpolationActivated(true);
 
     m_LastSNC->SendSlice();
   }
   mitk::RenderingManager::GetInstance()->RequestUpdateAll();
   this->UpdateVisibleSuggestion();
 }
 
 void QmitkSlicesInterpolator::CheckSupportedImageDimension()
 {
   if (m_ToolManager->GetWorkingData(0))
   {
     m_Segmentation = dynamic_cast<mitk::Image *>(m_ToolManager->GetWorkingData(0)->GetData());
 
     if (m_3DInterpolationEnabled && m_Segmentation && ((m_Segmentation->GetDimension() != 3) || (m_Segmentation->GetDimension() != 4)) )
     {
       QMessageBox info;
       info.setWindowTitle("3D Interpolation Process");
       info.setIcon(QMessageBox::Information);
       info.setText("3D Interpolation is only supported for 3D/4D images at the moment!");
       info.exec();
       m_CmbInterpolation->setCurrentIndex(0);
     }
   }
 }
 
 void QmitkSlicesInterpolator::OnSliceNavigationControllerDeleted(const itk::Object *sender,
                                                                  const itk::EventObject & /*e*/)
 {
   // Don't know how to avoid const_cast here?!
   mitk::SliceNavigationController *slicer =
     dynamic_cast<mitk::SliceNavigationController *>(const_cast<itk::Object *>(sender));
   if (slicer)
   {
     m_ControllerToSliceObserverTag.remove(slicer);
     m_ControllerToDeleteObserverTag.remove(slicer);
   }
 }
 
 void QmitkSlicesInterpolator::WaitForFutures()
 {
   if (m_Watcher.isRunning())
   {
     m_Watcher.waitForFinished();
   }
 
   if (m_PlaneWatcher.isRunning())
   {
     m_PlaneWatcher.waitForFinished();
   }
 }
 
 void QmitkSlicesInterpolator::NodeRemoved(const mitk::DataNode* node)
 {
   if ((m_ToolManager && m_ToolManager->GetWorkingData(0) == node) ||
       node == m_3DContourNode ||
       node == m_FeedbackNode ||
       node == m_InterpolatedSurfaceNode)
   {
     WaitForFutures();
   }
 }
 
-void QmitkSlicesInterpolator::OnAddLabelSetConnection(unsigned int layerID)
-{
-  if (m_ToolManager->GetWorkingData(0) != nullptr)
-  {
-    try
-    {
-      auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
-      auto labelSet = workingImage->GetLabelSet(layerID);
-      labelSet->RemoveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
-        this, &QmitkSlicesInterpolator::OnRemoveLabel);
-      labelSet->ActiveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
-            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
-      workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<QmitkSlicesInterpolator>(
-        this, &QmitkSlicesInterpolator::OnLayerChanged);
-      m_SurfaceInterpolator->AddLabelSetConnection(layerID);
-    }
-    catch(const std::exception& e)
-    {
-      MITK_ERROR << e.what() << '\n';
-    }
-  }
-}
-
-
-
-void QmitkSlicesInterpolator::OnAddLabelSetConnection()
-{
-  if (m_ToolManager->GetWorkingData(0) != nullptr)
-  {
-    try
-    {
-      auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
-      workingImage->GetActiveLabelSet()->RemoveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
-        this, &QmitkSlicesInterpolator::OnRemoveLabel);
-      workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
-            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
-      workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<QmitkSlicesInterpolator>(
-        this, &QmitkSlicesInterpolator::OnLayerChanged);
-      m_SurfaceInterpolator->AddLabelSetConnection();
-    }
-    catch(const std::exception& e)
-    {
-      MITK_ERROR << e.what() << '\n';
-    }
-  }
-}
-
-void QmitkSlicesInterpolator::OnRemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID)
-{
-  size_t previousLayerID = labelSetImage->GetActiveLayer();
-  labelSetImage->SetActiveLayer(layerID);
-  labelSetImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
-        this, &QmitkSlicesInterpolator::OnRemoveLabel);
-  labelSetImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
-            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
-  labelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
-        this, &QmitkSlicesInterpolator::OnLayerChanged);
-  m_SurfaceInterpolator->RemoveLabelSetConnection(labelSetImage, layerID);
-  labelSetImage->SetActiveLayer(previousLayerID);
-}
-
-void QmitkSlicesInterpolator::OnRemoveLabelSetConnection()
-{
-  if (m_ToolManager->GetWorkingData(0) != nullptr)
-  {
-    try
-    {
-      auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_ToolManager->GetWorkingData(0)->GetData());
-      workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
-        this, &QmitkSlicesInterpolator::OnRemoveLabel);
-      workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
-            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
-      workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
-        this, &QmitkSlicesInterpolator::OnLayerChanged);
-    }
-    catch(const std::exception& e)
-    {
-      MITK_ERROR << e.what() << '\n';
-    }
-  }
-}
-
-void QmitkSlicesInterpolator::OnRemoveLabel(mitk::Label::PixelType /*removedLabelValue*/)
-{
-  if (m_ToolManager->GetWorkingData(0) != nullptr)
-  {
-    try
-    {
-      auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
-      auto currentLayerID = labelSetImage->GetActiveLayer();
-      auto numTimeSteps = labelSetImage->GetTimeGeometry()->CountTimeSteps();
-      for (size_t t = 0; t < numTimeSteps; ++t)
-      {
-        m_SurfaceInterpolator->RemoveContours(m_PreviousActiveLabelValue,t,currentLayerID);
-      }
-    }
-    catch(const std::exception& e)
-    {
-      MITK_ERROR << "Bad cast error for labelSetImage";
-    }
-  }
-}
+//void QmitkSlicesInterpolator::OnAddLabelSetConnection(unsigned int layerID)
+//{
+//  if (m_ToolManager->GetWorkingData(0) != nullptr)
+//  {
+//    try
+//    {
+//      auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
+//      auto labelSet = workingImage->GetLabelSet(layerID);
+//      labelSet->RemoveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
+//        this, &QmitkSlicesInterpolator::OnRemoveLabel);
+//      labelSet->ActiveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
+//            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
+//      workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<QmitkSlicesInterpolator>(
+//        this, &QmitkSlicesInterpolator::OnLayerChanged);
+//      m_SurfaceInterpolator->AddLabelSetConnection(layerID);
+//    }
+//    catch(const std::exception& e)
+//    {
+//      MITK_ERROR << e.what() << '\n';
+//    }
+//  }
+//}
+
+
+
+//void QmitkSlicesInterpolator::OnAddLabelSetConnection()
+//{
+//  if (m_ToolManager->GetWorkingData(0) != nullptr)
+//  {
+//    try
+//    {
+//      auto workingImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
+//      workingImage->GetActiveLabelSet()->RemoveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
+//        this, &QmitkSlicesInterpolator::OnRemoveLabel);
+//      workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
+//            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
+//      workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<QmitkSlicesInterpolator>(
+//        this, &QmitkSlicesInterpolator::OnLayerChanged);
+//      m_SurfaceInterpolator->AddLabelSetConnection();
+//    }
+//    catch(const std::exception& e)
+//    {
+//      MITK_ERROR << e.what() << '\n';
+//    }
+//  }
+//}
+
+//void QmitkSlicesInterpolator::OnRemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID)
+//{
+//  size_t previousLayerID = labelSetImage->GetActiveLayer();
+//  labelSetImage->SetActiveLayer(layerID);
+//  labelSetImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
+//        this, &QmitkSlicesInterpolator::OnRemoveLabel);
+//  labelSetImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
+//            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
+//  labelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
+//        this, &QmitkSlicesInterpolator::OnLayerChanged);
+//  m_SurfaceInterpolator->RemoveLabelSetConnection(labelSetImage, layerID);
+//  labelSetImage->SetActiveLayer(previousLayerID);
+//}
+
+//void QmitkSlicesInterpolator::OnRemoveLabelSetConnection()
+//{
+//  if (m_ToolManager->GetWorkingData(0) != nullptr)
+//  {
+//    try
+//    {
+//      auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_ToolManager->GetWorkingData(0)->GetData());
+//      workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator, mitk::Label::PixelType>(
+//        this, &QmitkSlicesInterpolator::OnRemoveLabel);
+//      workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<QmitkSlicesInterpolator,mitk::Label::PixelType>(
+//            this, &QmitkSlicesInterpolator::OnActiveLabelChanged);
+//      workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate<QmitkSlicesInterpolator>(
+//        this, &QmitkSlicesInterpolator::OnLayerChanged);
+//    }
+//    catch(const std::exception& e)
+//    {
+//      MITK_ERROR << e.what() << '\n';
+//    }
+//  }
+//}
 
 void QmitkSlicesInterpolator::OnModifyLabelChanged(const itk::Object *caller,
                                                       const itk::EventObject & /*event*/)
 {
   auto *tempImage = dynamic_cast<mitk::LabelSetImage *>(const_cast<itk::Object *>(caller) ) ;
   if( tempImage == nullptr)
   {
     MITK_ERROR << "Unable to cast caller to LabelSetImage.";
     return;
   }
 
   ModifyLabelActionTrigerred actionTriggered = ModifyLabelActionTrigerred::Null;
   if(m_ToolManager->GetWorkingData(0) != nullptr)
   {
     auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_ToolManager->GetWorkingData(0)->GetData());
     if (labelSetImage == tempImage)
     {
       if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(m_TimePoint))
       {
         MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
         return;
       }
       auto timeStep = labelSetImage->GetTimeGeometry()->TimePointToTimeStep(m_TimePoint);
 
-      auto numLayersInCurrentSegmentation = m_SurfaceInterpolator->GetNumberOfLayersInCurrentSegmentation();
-      //  This handles the add layer or remove layer operation.
-      if (labelSetImage->GetNumberOfLayers() != numLayersInCurrentSegmentation)
-      {
-        bool addLayer = (labelSetImage->GetNumberOfLayers() == (numLayersInCurrentSegmentation +1) );
-        bool removeLayer = (labelSetImage->GetNumberOfLayers() == (numLayersInCurrentSegmentation - 1) );
-
-        m_SurfaceInterpolator->SetNumberOfLayersInCurrentSegmentation(labelSetImage->GetNumberOfLayers());
-
-        if (addLayer)
-        {
-          m_SurfaceInterpolator->OnAddLayer();
-          this->OnAddLabelSetConnection();
-        }
-        if (removeLayer)
-        {
-          m_SurfaceInterpolator->OnRemoveLayer();
-        }
-        return;
-      }
+      //auto numLayersInCurrentSegmentation = m_SurfaceInterpolator->GetNumberOfLayersInCurrentSegmentation();
+      ////  This handles the add layer or remove layer operation.
+      //if (labelSetImage->GetNumberOfLayers() != numLayersInCurrentSegmentation)
+      //{
+      //  bool addLayer = (labelSetImage->GetNumberOfLayers() == (numLayersInCurrentSegmentation +1) );
+      //  bool removeLayer = (labelSetImage->GetNumberOfLayers() == (numLayersInCurrentSegmentation - 1) );
+
+      //  m_SurfaceInterpolator->SetNumberOfLayersInCurrentSegmentation(labelSetImage->GetNumberOfLayers());
+
+      //  if (addLayer)
+      //  {
+      //    m_SurfaceInterpolator->OnAddLayer();
+      //    this->OnAddLabelSetConnection();
+      //  }
+      //  if (removeLayer)
+      //  {
+      //    m_SurfaceInterpolator->OnRemoveLayer();
+      //  }
+      //  return;
+      //}
 
       //  Get the pixels present in the image.
       //  This portion of the code deals with the merge and erase labels operations.
       auto imageDimension = labelSetImage->GetDimension();
       if (imageDimension == 4)
       {
         actionTriggered = ModifyLabelProcessing<4>(labelSetImage, m_SurfaceInterpolator, timeStep);
       }
       else
       {
         actionTriggered = ModifyLabelProcessing<3>(labelSetImage, m_SurfaceInterpolator, timeStep);
       }
 
       if (actionTriggered == ModifyLabelActionTrigerred::Erase)
       {
         m_InterpolatedSurfaceNode->SetData(nullptr);
       }
 
-      auto currentLayerID = labelSetImage->GetActiveLayer();
+      auto currentLabelID = labelSetImage->GetActiveLabel()->GetValue();
       if (actionTriggered == ModifyLabelActionTrigerred::Merge)
       {
-        this->MergeContours(timeStep, currentLayerID);
+        this->MergeContours(timeStep, currentLabelID);
         m_SurfaceInterpolator->Modified();
       }
     }
   }
 }
 
 void QmitkSlicesInterpolator::MergeContours(unsigned int timeStep,
-                                            unsigned int layerID)
+                                            unsigned int labelID)
 {
-  auto* contours = m_SurfaceInterpolator->GetContours(timeStep, layerID);
+  auto* contours = m_SurfaceInterpolator->GetContours(timeStep, labelID);
 
   if (nullptr == contours)
     return;
 
   std::this_thread::sleep_for(std::chrono::milliseconds(1000));
 
-  for (size_t i = 0; i < contours->size(); ++i)
+  for (auto& contour1 : *contours)
   {
-    for (size_t j = i+1; j < contours->size(); ++j)
+    for (auto& contour2 : *contours)
     {
       //  And Labels are the same and Layers are the same.
-      bool areContoursCoplanar = AreContoursCoplanar((*contours)[i], (*contours)[j]);
+      bool areContoursCoplanar = AreContoursCoplanar(contour1, contour2);
 
-      if ( areContoursCoplanar  && ((*contours)[i].LabelValue == (*contours)[j].LabelValue) )
+      if ( areContoursCoplanar  && (contour1.LabelValue == contour2.LabelValue) )
       {
         //  Update the contour by re-extracting the slice from the corresponding plane.
-        mitk::Image::Pointer slice = ExtractSliceFromImage(m_Segmentation, (*contours)[i].Plane, timeStep);
+        mitk::Image::Pointer slice = ExtractSliceFromImage(m_Segmentation, contour1.Plane, timeStep);
         mitk::ImageToContourFilter::Pointer contourExtractor = mitk::ImageToContourFilter::New();
         contourExtractor->SetInput(slice);
-        contourExtractor->SetContourValue((*contours)[i].LabelValue);
+        contourExtractor->SetContourValue(contour1.LabelValue);
         contourExtractor->Update();
         mitk::Surface::Pointer contour = contourExtractor->GetOutput();
-        (*contours)[i].Contour = contour;
+        contour1.Contour = contour;
 
         //  Update the interior point of the contour
-        (*contours)[i].ContourPoint = m_SurfaceInterpolator->ComputeInteriorPointOfContour((*contours)[i],dynamic_cast<mitk::LabelSetImage *>(m_Segmentation));
+        contour1.ContourPoint = m_SurfaceInterpolator->ComputeInteriorPointOfContour(contour1,dynamic_cast<mitk::LabelSetImage *>(m_Segmentation));
 
-        //  Setting the contour polygon data to an empty vtkPolyData,
-        //  as source label is empty after merge operation.
-        (*contours)[j].Contour->SetVtkPolyData(vtkSmartPointer<vtkPolyData>::New());
+        //  marking the source contour for removal.
+        contour2.Pos = -2;
       }
     }
   }
 
   auto segmentationNode = m_SurfaceInterpolator->GetSegmentationImageNode();
 
   if (segmentationNode == nullptr)
   {
     MITK_ERROR << "segmentation Image Node not found\n";
   }
 
   auto isContourPlaneGeometry = mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
 
   mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
     m_DataStorage->GetDerivations(segmentationNode, isContourPlaneGeometry);
 
   //  Remove empty contour nodes.
   auto isContourEmpty = [] (const mitk::SurfaceInterpolationController::ContourPositionInformation& contour)
   {
-    return (contour.Contour->GetVtkPolyData()->GetNumberOfPoints() == 0);
+    return (contour.Pos == -2);
   };
 
   auto it = std::remove_if((*contours).begin(), (*contours).end(), isContourEmpty);
   (*contours).erase(it, (*contours).end());
 }
 
 void QmitkSlicesInterpolator::ClearSegmentationObservers()
 {
   auto dataIter = m_SegmentationObserverTags.begin();
   while (dataIter != m_SegmentationObserverTags.end())
   {
     auto labelSetImage = (*dataIter).first;
     labelSetImage->RemoveObserver((*dataIter).second);
     for (size_t layerID = 0; layerID < labelSetImage->GetNumberOfLayers(); ++layerID)
     {
       this->OnRemoveLabelSetConnection(labelSetImage, layerID);
     }
     ++dataIter;
   }
   m_SegmentationObserverTags.clear();
 }
diff --git a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h
index 331990c3ed..be88b270d1 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h
+++ b/Modules/SegmentationUI/Qmitk/QmitkSlicesInterpolator.h
@@ -1,428 +1,429 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef QmitkSlicesInterpolator_h
 #define QmitkSlicesInterpolator_h
 
 #include "mitkDataNode.h"
 #include "mitkDataStorage.h"
 #include "mitkSegmentationInterpolationController.h"
 #include "mitkSurfaceInterpolationController.h"
 #include "mitkToolManager.h"
 #include <MitkSegmentationUIExports.h>
 
 #include "mitkFeatureBasedEdgeDetectionFilter.h"
 #include "mitkPointCloudScoringFilter.h"
 
 #include <QWidget>
 #include <map>
 
 #include <QCheckBox>
 #include <QComboBox>
 #include <QFrame>
 #include <QGroupBox>
 #include <QRadioButton>
 
 #include "mitkVtkRepresentationProperty.h"
 #include "vtkProperty.h"
 
 // For running 3D interpolation in background
 #include <QFuture>
 #include <QFutureWatcher>
 #include <QTimer>
 #include <QtConcurrentRun>
 
 namespace mitk
 {
   class PlaneGeometry;
   class SliceNavigationController;
   class TimeNavigationController;
 }
 
 class QPushButton;
 class QmitkRenderWindow;
 
 enum ModifyLabelActionTrigerred
 {
   Null,
   Erase,
   Merge
 };
 
 /**
   \brief GUI for slices interpolation.
 
   \ingroup ToolManagerEtAl
   \ingroup Widgets
 
   \sa QmitkInteractiveSegmentation
   \sa mitk::SegmentationInterpolation
 
   While mitk::SegmentationInterpolation does the bookkeeping of interpolation
   (keeping track of which slices contain how much segmentation) and the algorithmic work,
   QmitkSlicesInterpolator is responsible to watch the GUI, to notice, which slice is currently
   visible. It triggers generation of interpolation suggestions and also triggers acception of
   suggestions.
 
   \todo show/hide feedback on demand
 
   Last contributor: $Author: maleike $
 */
 class MITKSEGMENTATIONUI_EXPORT QmitkSlicesInterpolator : public QWidget
 {
   Q_OBJECT
 
 public:
   QmitkSlicesInterpolator(QWidget *parent = nullptr, const char *name = nullptr);
 
   /**
     To be called once before real use.
     */
   void Initialize(mitk::ToolManager *toolManager, const QList<QmitkRenderWindow*>& windows);
 
   /**
    * @brief
    *
    */
   void Uninitialize();
 
   ~QmitkSlicesInterpolator() override;
 
   /**
    * @brief Set the Data Storage object
    *
    * @param storage
    */
   void SetDataStorage(mitk::DataStorage::Pointer storage);
 
   /**
    * @brief Get the Data Storage object
    *
    * @return mitk::DataStorage*
    */
   mitk::DataStorage *GetDataStorage();
 
+  void SetActiveLabelValue(mitk::LabelSetImage::LabelValueType labelValue);
 
   /**
     Just public because it is called by itk::Commands. You should not need to call this.
   */
   void OnToolManagerWorkingDataModified();
 
   /**
     Just public because it is called by itk::Commands. You should not need to call this.
   */
   void OnToolManagerReferenceDataModified();
 
   /**
    * @brief Reacts to the time changed event.
    *
    * @param sender
    */
   void OnTimeChanged(itk::Object *sender, const itk::EventObject &);
 
   /**
    * @brief Reacts to the slice changed event
    *
    * @param sender
    */
   void OnSliceChanged(itk::Object *sender, const itk::EventObject &);
 
 
   void OnSliceNavigationControllerDeleted(const itk::Object *sender, const itk::EventObject &);
 
   /**
     Just public because it is called by itk::Commands. You should not need to call this.
   */
   void OnInterpolationInfoChanged(const itk::EventObject &);
 
   /**
     Just public because it is called by itk::Commands. You should not need to call this.
   */
   void OnInterpolationAborted(const itk::EventObject &);
 
   /**
     Just public because it is called by itk::Commands. You should not need to call this.
   */
   void OnSurfaceInterpolationInfoChanged(const itk::EventObject &);
 
 
 private:
   /**
    * @brief Set the visibility of the 3d interpolation
    */
   void Show3DInterpolationResult(bool);
 
   /**
    * @brief Function that reacts to a change in the activeLabel of the working segmentation image.
    *
    */
   void OnActiveLabelChanged(mitk::Label::PixelType);
 
   /**
    * @brief Function that reacts to a change in the layer.
    *
    */
   void OnLayerChanged();
 
   /**
    * @brief Function that handles label removal from the segmentation image.
    *
    */
   void OnRemoveLabel(mitk::Label::PixelType removedLabelValue);
 
   /**
    * @brief Function that to changes in the segmentation image. It handles the layer removal, addition, label erasure,
    *
    */
   void OnModifyLabelChanged(const itk::Object *caller,
                               const itk::EventObject & /*event*/);
 
   /**
    * @brief Add the necessary subscribers to the label set image, for UI responsiveness.
    *        It deals with remove label, change active label, layer changes and change in the label.
    *
    */
   void OnAddLabelSetConnection();
 
   /**
    * @brief Add the necessary subscribers to the current LabelSetImage at the layer input, for UI responsiveness.
    *        It deals with remove label, change active label, layer changes and change in the label.
    *
    * @param layerID
    */
   void OnAddLabelSetConnection(unsigned int layerID);
 
   /**
    * @brief Remove the subscribers for the different events to the segmentation image.
    *
    */
   void OnRemoveLabelSetConnection();
 
   /**
    * @brief Merge contours for the current layerID and current timeStep.
    *
    * @param timeStep
    * @param layerID
    */
   void MergeContours(unsigned int timeStep, unsigned int layerID);
 
 
   /**
    * @brief Prepare Inputs for 3D Interpolation.
    *
    */
   void PrepareInputsFor3DInterpolation();
 
 signals:
 
   void SignalRememberContourPositions(bool);
   void SignalShowMarkerNodes(bool);
 
 public slots:
 
   virtual void setEnabled(bool);
   /**
     Call this from the outside to enable/disable interpolation
   */
   void EnableInterpolation(bool);
 
   void Enable3DInterpolation(bool);
 
   /**
     Call this from the outside to accept all interpolations
   */
   void FinishInterpolation(mitk::SliceNavigationController *slicer = nullptr);
 
 protected slots:
 
   /**
     Reaction to button clicks.
   */
   void OnAcceptInterpolationClicked();
 
   /*
     Opens popup to ask about which orientation should be interpolated
   */
   void OnAcceptAllInterpolationsClicked();
 
   /*
    Reaction to button clicks
   */
   void OnAccept3DInterpolationClicked();
 
   /**
    * @brief Reaction to reinit 3D Interpolation. Re-reads the plane geometries of the image
    *         that should have generated the
    *
    */
   void OnReinit3DInterpolation();
 
   /*
    * Will trigger interpolation for all slices in given orientation (called from popup menu of
    * OnAcceptAllInterpolationsClicked)
    */
   void OnAcceptAllPopupActivated(QAction *action);
 
   /**
     Called on activation/deactivation
   */
   void OnInterpolationActivated(bool);
 
   void On3DInterpolationActivated(bool);
 
   void OnInterpolationMethodChanged(int index);
 
   // Enhancement for 3D interpolation
   void On2DInterpolationEnabled(bool);
   void On3DInterpolationEnabled(bool);
   void OnInterpolationDisabled(bool);
   void OnShowMarkers(bool);
 
   void Run3DInterpolation();
 
   /**
    * @brief Function triggers when the surface interpolation thread completes running.
    *        It is responsible for retrieving the data, rendering it in the active color label,
    *        storing the surface information in the feedback node.
    *
    */
   void OnSurfaceInterpolationFinished();
 
   void StartUpdateInterpolationTimer();
 
   void StopUpdateInterpolationTimer();
 
   void ChangeSurfaceColor();
 
   /**
    * @brief Removes all observers to the labelSetImage at the layerID specified.
    *        Is used when changing the segmentation image.
    *
    * @param labelSetImage
    * @param layerID
    */
   void OnRemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID);
 
 protected:
 
   typedef std::map<QAction*, mitk::SliceNavigationController*> ActionToSliceDimensionMapType;
   const ActionToSliceDimensionMapType CreateActionToSlicer(const QList<QmitkRenderWindow*>& windows);
   ActionToSliceDimensionMapType m_ActionToSlicerMap;
 
   void AcceptAllInterpolations(mitk::SliceNavigationController *slicer);
 
   /**
     Retrieves the currently selected PlaneGeometry from a SlicedGeometry3D that is generated by a
     SliceNavigationController
     and calls Interpolate to further process this PlaneGeometry into an interpolation.
 
     \param e is a actually a mitk::SliceNavigationController::GeometrySliceEvent, sent by a SliceNavigationController
     \param sliceNavigationController the SliceNavigationController
         */
   bool TranslateAndInterpolateChangedSlice(const itk::EventObject &e,
                                            mitk::SliceNavigationController *sliceNavigationController);
 
   bool TranslateAndInterpolateChangedSlice(const mitk::TimeGeometry* timeGeometry);
   /**
     Given a PlaneGeometry, this method figures out which slice of the first working image (of the associated
     ToolManager)
     should be interpolated. The actual work is then done by our SegmentationInterpolation object.
    */
   void Interpolate(mitk::PlaneGeometry *plane);
 
   /**
     Called internally to update the interpolation suggestion. Finds out about the focused render window and requests an
     interpolation.
    */
   void UpdateVisibleSuggestion();
 
   void SetCurrentContourListID();
 
 private:
   void InitializeWindow(QmitkRenderWindow* window);
   void HideAllInterpolationControls();
   void Show2DInterpolationControls(bool show);
   void Show3DInterpolationControls(bool show);
   void CheckSupportedImageDimension();
   void WaitForFutures();
   void NodeRemoved(const mitk::DataNode* node);
   void ClearSegmentationObservers();
 
   mitk::SegmentationInterpolationController::Pointer m_Interpolator;
   mitk::SurfaceInterpolationController::Pointer m_SurfaceInterpolator;
 
   mitk::FeatureBasedEdgeDetectionFilter::Pointer m_EdgeDetector;
   mitk::PointCloudScoringFilter::Pointer m_PointScorer;
 
   mitk::ToolManager::Pointer m_ToolManager;
   bool m_Initialized;
 
   unsigned int m_ControllerToTimeObserverTag;
   QHash<mitk::SliceNavigationController *, int> m_ControllerToSliceObserverTag;
   QHash<mitk::SliceNavigationController *, int> m_ControllerToDeleteObserverTag;
 
   std::map<mitk::LabelSetImage *, unsigned long> m_SegmentationObserverTags;
 
   unsigned int InterpolationInfoChangedObserverTag;
   unsigned int SurfaceInterpolationInfoChangedObserverTag;
   unsigned int InterpolationAbortedObserverTag;
 
   QGroupBox *m_GroupBoxEnableExclusiveInterpolationMode;
   QComboBox *m_CmbInterpolation;
   QPushButton *m_BtnApply2D;
   QPushButton *m_BtnApplyForAllSlices2D;
   QPushButton *m_BtnApply3D;
 
   // T28261
   // QPushButton *m_BtnSuggestPlane;
 
   QCheckBox *m_ChkShowPositionNodes;
   QPushButton *m_BtnReinit3DInterpolation;
 
   mitk::DataNode::Pointer m_FeedbackNode;
   mitk::DataNode::Pointer m_InterpolatedSurfaceNode;
   mitk::DataNode::Pointer m_3DContourNode;
 
   mitk::Image *m_Segmentation;
 
   mitk::SliceNavigationController *m_LastSNC;
   unsigned int m_LastSliceIndex;
 
   mitk::TimePointType m_TimePoint;
 
   bool m_2DInterpolationEnabled;
   bool m_3DInterpolationEnabled;
 
   unsigned int m_numTimesLabelSetConnectionAdded;
 
   mitk::DataStorage::Pointer m_DataStorage;
 
   QFuture<void> m_Future;
   QFutureWatcher<void> m_Watcher;
 
   QFuture<void> m_ModifyFuture;
   QFutureWatcher<void> m_ModifyWatcher;
 
   QTimer *m_Timer;
 
   QFuture<void> m_PlaneFuture;
   QFutureWatcher<void> m_PlaneWatcher;
 
   mitk::Label::PixelType m_PreviousActiveLabelValue;
   mitk::Label::PixelType m_CurrentActiveLabelValue;
 
   unsigned int m_PreviousLayerIndex;
   unsigned int m_CurrentLayerIndex;
   bool m_FirstRun;
 };
 
 #endif
diff --git a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp
index 26418f9785..abc9d79f04 100644
--- a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp
+++ b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp
@@ -1,1097 +1,794 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include <mitkSurfaceInterpolationController.h>
 #include <mitkTestFixture.h>
 #include <mitkTestingMacros.h>
 
 #include <mitkImageTimeSelector.h>
 #include <mitkLabelSetImage.h>
 
 #include <vtkDebugLeaks.h>
 #include <vtkDoubleArray.h>
 #include <vtkFieldData.h>
 #include <vtkPolygon.h>
 #include <vtkRegularPolygonSource.h>
 
 class mitkSurfaceInterpolationControllerTestSuite : public mitk::TestFixture
 {
   CPPUNIT_TEST_SUITE(mitkSurfaceInterpolationControllerTestSuite);
   MITK_TEST(TestSingleton);
   MITK_TEST(TestSetCurrentInterpolationSession);
-  MITK_TEST(TestReplaceInterpolationSession);
   MITK_TEST(TestRemoveAllInterpolationSessions);
   MITK_TEST(TestRemoveInterpolationSession);
   MITK_TEST(TestOnSegmentationDeleted);
 
   MITK_TEST(TestSetCurrentInterpolationSession4D);
-  MITK_TEST(TestReplaceInterpolationSession4D);
   MITK_TEST(TestRemoveAllInterpolationSessions4D);
   MITK_TEST(TestRemoveInterpolationSession4D);
   MITK_TEST(TestOnSegmentationDeleted4D);
 
   /// \todo Workaround for memory leak in TestAddNewContour. Bug 18096.
   vtkDebugLeaks::SetExitError(0);
 
   MITK_TEST(TestAddNewContour);
   MITK_TEST(TestRemoveContour);
   CPPUNIT_TEST_SUITE_END();
 
 private:
   mitk::SurfaceInterpolationController::Pointer m_Controller;
 
 public:
   mitk::Image::Pointer createImage(unsigned int *dimensions)
   {
     mitk::Image::Pointer newImage = mitk::Image::New();
     // mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New();
     mitk::PixelType p_type = mitk::MakeScalarPixelType<unsigned char>();
     newImage->Initialize(p_type, 3, dimensions);
     return newImage;
   }
 
   mitk::LabelSetImage::Pointer createLabelSetImage(unsigned int *dimensions)
   {
     mitk::Image::Pointer image = createImage(dimensions);
     mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New();
     newImage->InitializeByLabeledImage(image);
     return newImage;
   }
 
   mitk::Image::Pointer createImage4D(unsigned int *dimensions)
   {
     mitk::Image::Pointer newImage = mitk::Image::New();
     mitk::PixelType p_type = mitk::MakeScalarPixelType<unsigned char>();
     newImage->Initialize(p_type, 4, dimensions);
     return newImage;
   }
 
   mitk::LabelSetImage::Pointer createLabelSetImage4D(unsigned int *dimensions)
   {
     mitk::Image::Pointer image = createImage4D(dimensions);
     mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New();
     newImage->InitializeByLabeledImage(image);
     return newImage;
   }
 
   void setUp() override
   {
     m_Controller = mitk::SurfaceInterpolationController::GetInstance();
     m_Controller->RemoveAllInterpolationSessions();
     m_Controller->SetCurrentTimePoint(0);
 
     vtkSmartPointer<vtkRegularPolygonSource> polygonSource = vtkSmartPointer<vtkRegularPolygonSource>::New();
     polygonSource->SetRadius(100);
     polygonSource->SetNumberOfSides(7);
     polygonSource->Update();
     mitk::Surface::Pointer surface = mitk::Surface::New();
     surface->SetVtkPolyData(polygonSource->GetOutput());
   }
 
   void TestSingleton()
   {
     mitk::SurfaceInterpolationController::Pointer controller2 = mitk::SurfaceInterpolationController::GetInstance();
     CPPUNIT_ASSERT_MESSAGE("SurfaceInterpolationController pointers are not equal!",
                            m_Controller.GetPointer() == controller2.GetPointer());
   }
 
   void TestSetCurrentInterpolationSession()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10};
     mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
 
     unsigned int dimensions2[] = {20, 10, 30};
     mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions2);
 
     // Test 1
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
 
-    MITK_ASSERT_EQUAL(
-      m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal");
-    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
+    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation() == segmentation_1.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
                            m_Controller->GetNumberOfInterpolationSessions() == 1);
 
     // Test 2
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
-    MITK_ASSERT_EQUAL(
-      m_Controller->GetCurrentSegmentation(), segmentation_2->Clone(), "Segmentation images are not equal");
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_2.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test 3
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
-    MITK_ASSERT_EQUAL(
-      m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal");
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_1.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test 4
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
-    MITK_ASSERT_EQUAL(
-      m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not equal");
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_1.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // // Test 5
     m_Controller->SetCurrentInterpolationSession(nullptr);
-    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().IsNull());
+    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation() == nullptr);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
   }
 
   mitk::PlaneGeometry::Pointer GetPlaneGeometry()
   {
     mitk::Point3D origin;
     mitk::Vector3D right, bottom, normal, spacing;
     mitk::ScalarType width, height;
     mitk::ScalarType widthInMM, heightInMM, thicknessInMM;
 
     auto planegeometry = mitk::PlaneGeometry::New();
     width = 100;
     widthInMM = width;
     height = 200;
     heightInMM = height;
     thicknessInMM = 1.0;
     mitk::FillVector3D(origin, 4.5, 7.3, 11.2);
     mitk::FillVector3D(right, widthInMM, 0, 0);
     mitk::FillVector3D(bottom, 0, heightInMM, 0);
     mitk::FillVector3D(normal, 0, 0, thicknessInMM);
     mitk::FillVector3D(spacing, 1.0, 1.0, thicknessInMM);
 
     planegeometry->InitializeStandardPlane(right, bottom);
     planegeometry->SetOrigin(origin);
     planegeometry->SetSpacing(spacing);
     return planegeometry;
   }
 
-  void TestReplaceInterpolationSession()
-  {
-    // Create segmentation image
-    unsigned int dimensions1[] = {10, 10, 10};
-    mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
-
-    m_Controller->SetCurrentInterpolationSession(segmentation_1);
-
-    // Create some contours
-    double center_1[3] = {1.25f, 3.43f, 4.44f};
-    double normal_1[3] = {0.25f, 1.76f, 0.93f};
-    vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
-    p_source->SetNumberOfSides(20);
-    p_source->SetCenter(center_1);
-    p_source->SetRadius(4);
-    p_source->SetNormal(normal_1);
-    p_source->Update();
-    vtkPolyData *poly_1 = p_source->GetOutput();
-    mitk::Surface::Pointer surf_1 = mitk::Surface::New();
-    surf_1->SetVtkPolyData(poly_1);
-    vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
-    int1Array->InsertNextValue(1);
-    int1Array->InsertNextValue(0);
-    int1Array->InsertNextValue(0);
-    surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
-    vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
-    double1Array->InsertNextValue(center_1[0]);
-    double1Array->InsertNextValue(center_1[1]);
-    double1Array->InsertNextValue(center_1[2]);
-    surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
-
-    double center_2[3] = {4.0f, 4.0f, 4.0f};
-    double normal_2[3] = {1.0f, 0.0f, 0.0f};
-    vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
-    p_source_2->SetNumberOfSides(80);
-    p_source_2->SetCenter(center_2);
-    p_source_2->SetRadius(4);
-    p_source_2->SetNormal(normal_2);
-    p_source_2->Update();
-    vtkPolyData *poly_2 = p_source_2->GetOutput();
-    mitk::Surface::Pointer surf_2 = mitk::Surface::New();
-    surf_2->SetVtkPolyData(poly_2);
-    vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
-    int2Array->InsertNextValue(1);
-    int2Array->InsertNextValue(0);
-    int2Array->InsertNextValue(0);
-    surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
-    vtkSmartPointer<vtkDoubleArray> doubleArray = vtkSmartPointer<vtkDoubleArray>::New();
-    doubleArray->InsertNextValue(center_2[0]);
-    doubleArray->InsertNextValue(center_2[1]);
-    doubleArray->InsertNextValue(center_2[2]);
-    surf_2->GetVtkPolyData()->GetFieldData()->AddArray(doubleArray);
-
-    std::vector<mitk::Surface::Pointer> surfaces;
-    surfaces.push_back(surf_1);
-    surfaces.push_back(surf_2);
-
-    const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
-    const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
-
-    std::vector<const mitk::PlaneGeometry*> planeGeometries;
-    planeGeometries.push_back(planeGeometry1);
-    planeGeometries.push_back(planeGeometry2);
-
-    // Add contours
-    m_Controller->AddNewContours(surfaces, planeGeometries, true);
-
-    // Check if all contours are there
-    mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1;
-
-    mitk::ScalarType n[3];
-    vtkPolygon::ComputeNormal(surf_1->GetVtkPolyData()->GetPoints(), n);
-    contourInfo1.ContourNormal = n;
-    contourInfo1.ContourPoint = center_1;
-
-    mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
-
-    vtkPolygon::ComputeNormal(surf_2->GetVtkPolyData()->GetPoints(), n);
-
-    contourInfo2.ContourNormal = n;
-    contourInfo2.ContourPoint = center_2;
-
-
-    const mitk::Surface *contour_1 = m_Controller->GetContour(contourInfo1);
-    const mitk::Surface *contour_2 = m_Controller->GetContour(contourInfo2);
-
-
-    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2);
-    CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
-                           mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true));
-    CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
-                           mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true));
-
-    CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
-                           m_Controller->GetNumberOfInterpolationSessions() == 1);
-
-    mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions1);
-    bool success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_2);
-
-    CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == true);
-    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
-
-    unsigned int dimensions2[] = {10, 20, 10};
-    mitk::Image::Pointer segmentation_3 = createLabelSetImage(dimensions2);
-    success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_3);
-    CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == false);
-    CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
-                           m_Controller->GetNumberOfInterpolationSessions() == 1);
-    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
-  }
-
   void TestRemoveAllInterpolationSessions()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10};
     auto segmentation_1 = createLabelSetImage(dimensions1);
 
     unsigned int dimensions2[] = {20, 10, 30};
     auto segmentation_2 = createLabelSetImage(dimensions2);
 
     // Test 1
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
     m_Controller->RemoveAllInterpolationSessions();
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
                            m_Controller->GetNumberOfInterpolationSessions() == 0);
   }
 
   void TestRemoveInterpolationSession()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10};
     mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
 
     unsigned int dimensions2[] = {20, 10, 30};
-    mitk::Image::Pointer segmentation_2 = createLabelSetImage(dimensions2);
+    mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions2);
 
     // Test 1
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test current segmentation should not be null if another one was removed
     m_Controller->RemoveInterpolationSession(segmentation_1);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
                            m_Controller->GetNumberOfInterpolationSessions() == 1);
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_2.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed",
-                           m_Controller->GetCurrentSegmentation().IsNotNull());
+                           m_Controller->GetCurrentSegmentation() != nullptr);
 
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test current segmentation should not be null if another one was removed
     m_Controller->RemoveInterpolationSession(segmentation_1);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
                            m_Controller->GetNumberOfInterpolationSessions() == 1);
     CPPUNIT_ASSERT_MESSAGE("Current segmentation is not null after session was removed",
-                           m_Controller->GetCurrentSegmentation().IsNull());
+                           m_Controller->GetCurrentSegmentation() == nullptr);
   }
 
   void TestOnSegmentationDeleted()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10};
     auto segmentation_1 = createLabelSetImage(dimensions1);
 
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
 
     segmentation_1 = nullptr;
 
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
                            m_Controller->GetNumberOfInterpolationSessions() == 0);
   }
 
   void TestAddNewContour()
   {
     // Create segmentation image
     unsigned int dimensions1[] = {10, 10, 10};
-    mitk::Image::Pointer segmentation_1 = createLabelSetImage(dimensions1);
+    auto segmentation_1 = createLabelSetImage(dimensions1);
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
 
     // Create some contours
     double center_1[3] = {1.25f, 3.43f, 4.44f};
     double normal_1[3] = {0.25f, 1.76f, 0.93f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source->SetNumberOfSides(20);
     p_source->SetCenter(center_1);
     p_source->SetRadius(4);
     p_source->SetNormal(normal_1);
     p_source->Update();
     vtkPolyData *poly_1 = p_source->GetOutput();
     mitk::Surface::Pointer surf_1 = mitk::Surface::New();
     surf_1->SetVtkPolyData(poly_1);
     vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
     int1Array->InsertNextValue(1);
     int1Array->InsertNextValue(0);
     int1Array->InsertNextValue(0);
     surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
     vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
     double1Array->InsertNextValue(center_1[0]);
     double1Array->InsertNextValue(center_1[1]);
     double1Array->InsertNextValue(center_1[2]);
     surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
 
     double center_2[3] = {4.0f, 4.0f, 4.0f};
     double normal_2[3] = {1.0f, 0.0f, 0.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_2->SetNumberOfSides(80);
     p_source_2->SetCenter(center_2);
     p_source_2->SetRadius(4);
     p_source_2->SetNormal(normal_2);
     p_source_2->Update();
     vtkPolyData *poly_2 = p_source_2->GetOutput();
     mitk::Surface::Pointer surf_2 = mitk::Surface::New();
     surf_2->SetVtkPolyData(poly_2);
     vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
     int2Array->InsertNextValue(1);
     int2Array->InsertNextValue(0);
     int2Array->InsertNextValue(0);
     surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
     vtkSmartPointer<vtkDoubleArray> double2Array = vtkSmartPointer<vtkDoubleArray>::New();
     double2Array->InsertNextValue(center_2[0]);
     double2Array->InsertNextValue(center_2[1]);
     double2Array->InsertNextValue(center_2[2]);
     surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array);
 
     double center_3[3] = {4.0f, 4.0f, 3.0f};
     double normal_3[3] = {0.0f, 0.0f, 1.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source_3 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_3->SetNumberOfSides(10);
     p_source_3->SetCenter(center_3);
     p_source_3->SetRadius(4);
     p_source_3->SetNormal(normal_3);
     p_source_3->Update();
     vtkPolyData *poly_3 = p_source_3->GetOutput();
     mitk::Surface::Pointer surf_3 = mitk::Surface::New();
     surf_3->SetVtkPolyData(poly_3);
     vtkSmartPointer<vtkIntArray> int3Array = vtkSmartPointer<vtkIntArray>::New();
     int3Array->InsertNextValue(1);
     int3Array->InsertNextValue(0);
     int3Array->InsertNextValue(0);
     surf_3->GetVtkPolyData()->GetFieldData()->AddArray(int3Array);
     vtkSmartPointer<vtkDoubleArray> double3Array = vtkSmartPointer<vtkDoubleArray>::New();
     double3Array->InsertNextValue(center_3[0]);
     double3Array->InsertNextValue(center_3[1]);
     double3Array->InsertNextValue(center_3[2]);
     surf_3->GetVtkPolyData()->GetFieldData()->AddArray(double3Array);
 
     std::vector<mitk::Surface::Pointer> surfaces;
     surfaces.push_back(surf_1);
     surfaces.push_back(surf_2);
     surfaces.push_back(surf_3);
 
     const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
     const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
     const mitk::PlaneGeometry * planeGeometry3 = GetPlaneGeometry();
 
     std::vector<const mitk::PlaneGeometry*> planeGeometries;
     planeGeometries.push_back(planeGeometry1);
     planeGeometries.push_back(planeGeometry2);
     planeGeometries.push_back(planeGeometry3);
 
     // Add contours
     m_Controller->AddNewContours(surfaces, planeGeometries, true);
 
     mitk::ScalarType n[3];
 
     // Check if all contours are there
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1;
     vtkPolygon::ComputeNormal(surf_1->GetVtkPolyData()->GetPoints(), n);
     contourInfo1.ContourNormal = n;
     contourInfo1.ContourPoint = center_1;
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
     vtkPolygon::ComputeNormal(surf_2->GetVtkPolyData()->GetPoints(), n);
     contourInfo2.ContourNormal = n;
     contourInfo2.ContourPoint = center_2;
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3;
     vtkPolygon::ComputeNormal(surf_3->GetVtkPolyData()->GetPoints(), n);
     contourInfo3.ContourNormal = n;
     contourInfo3.ContourPoint = center_3;
 
     const mitk::Surface *contour_1 = m_Controller->GetContour(contourInfo1);
     const mitk::Surface *contour_2 = m_Controller->GetContour(contourInfo2);
     const mitk::Surface *contour_3 = m_Controller->GetContour(contourInfo3);
 
-    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3);
+    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetContours(0,1)->size() == 3);
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true));
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true));
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_3->GetVtkPolyData()), 0.000001, true));
 
     // Create another segmentation image
     unsigned int dimensions2[] = {20, 20, 20};
     mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage(dimensions2);
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
 
     // Create some contours
     double center_4[3] = {10.0f, 10.0f, 10.0f};
     double normal_4[3] = {0.0f, 1.0f, 0.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source_4 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_4->SetNumberOfSides(8);
     p_source_4->SetCenter(center_4);
     p_source_4->SetRadius(5);
     p_source_4->SetNormal(normal_4);
     p_source_4->Update();
     vtkPolyData *poly_4 = p_source_4->GetOutput();
     mitk::Surface::Pointer surf_4 = mitk::Surface::New();
     surf_4->SetVtkPolyData(poly_4);
     vtkSmartPointer<vtkIntArray> int4Array = vtkSmartPointer<vtkIntArray>::New();
     int4Array->InsertNextValue(2);
     int4Array->InsertNextValue(0);
     int4Array->InsertNextValue(0);
     surf_4->GetVtkPolyData()->GetFieldData()->AddArray(int4Array);
     vtkSmartPointer<vtkDoubleArray> double4Array = vtkSmartPointer<vtkDoubleArray>::New();
     double4Array->InsertNextValue(center_4[0]);
     double4Array->InsertNextValue(center_4[1]);
     double4Array->InsertNextValue(center_4[2]);
     surf_4->GetVtkPolyData()->GetFieldData()->AddArray(double4Array);
 
     double center_5[3] = {3.0f, 10.0f, 10.0f};
     double normal_5[3] = {1.0f, 0.0f, 0.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source_5 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_5->SetNumberOfSides(16);
     p_source_5->SetCenter(center_5);
     p_source_5->SetRadius(8);
     p_source_5->SetNormal(normal_5);
     p_source_5->Update();
     vtkPolyData *poly_5 = p_source_5->GetOutput();
     mitk::Surface::Pointer surf_5 = mitk::Surface::New();
     surf_5->SetVtkPolyData(poly_5);
     vtkSmartPointer<vtkIntArray> int5Array = vtkSmartPointer<vtkIntArray>::New();
     int5Array->InsertNextValue(2);
     int5Array->InsertNextValue(0);
     int5Array->InsertNextValue(0);
     surf_5->GetVtkPolyData()->GetFieldData()->AddArray(int5Array);
     vtkSmartPointer<vtkDoubleArray> double5Array = vtkSmartPointer<vtkDoubleArray>::New();
     double5Array->InsertNextValue(center_5[0]);
     double5Array->InsertNextValue(center_5[1]);
     double5Array->InsertNextValue(center_5[2]);
     surf_5->GetVtkPolyData()->GetFieldData()->AddArray(double5Array);
 
     double center_6[3] = {10.0f, 10.0f, 3.0f};
     double normal_6[3] = {0.0f, 0.0f, 1.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source_6 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_6->SetNumberOfSides(100);
     p_source_6->SetCenter(center_6);
     p_source_6->SetRadius(5);
     p_source_6->SetNormal(normal_6);
     p_source_6->Update();
     vtkPolyData *poly_6 = p_source_6->GetOutput();
     mitk::Surface::Pointer surf_6 = mitk::Surface::New();
     surf_6->SetVtkPolyData(poly_6);
     vtkSmartPointer<vtkIntArray> int6Array = vtkSmartPointer<vtkIntArray>::New();
     int6Array->InsertNextValue(2);
     int6Array->InsertNextValue(0);
     int6Array->InsertNextValue(0);
     surf_6->GetVtkPolyData()->GetFieldData()->AddArray(int6Array);
     vtkSmartPointer<vtkDoubleArray> double6Array = vtkSmartPointer<vtkDoubleArray>::New();
     double6Array->InsertNextValue(center_6[0]);
     double6Array->InsertNextValue(center_6[1]);
     double6Array->InsertNextValue(center_6[2]);
     surf_6->GetVtkPolyData()->GetFieldData()->AddArray(double6Array);
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo4;
     vtkPolygon::ComputeNormal(surf_4->GetVtkPolyData()->GetPoints(), n);
     contourInfo4.ContourNormal = n;
     contourInfo4.ContourPoint = center_4;
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo5;
     vtkPolygon::ComputeNormal(surf_5->GetVtkPolyData()->GetPoints(), n);
     contourInfo5.ContourNormal = n;
     contourInfo5.ContourPoint = center_5;
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo6;
     vtkPolygon::ComputeNormal(surf_6->GetVtkPolyData()->GetPoints(), n);
     contourInfo6.ContourNormal = n;
     contourInfo6.ContourPoint = center_6;
 
     const mitk::PlaneGeometry * planeGeometry4 = GetPlaneGeometry();
     const mitk::PlaneGeometry * planeGeometry5 = GetPlaneGeometry();
     const mitk::PlaneGeometry * planeGeometry6 = GetPlaneGeometry();
 
     std::vector<mitk::Surface::Pointer> surfaces2;
     surfaces2.push_back(surf_4);
     surfaces2.push_back(surf_5);
     surfaces2.push_back(surf_6);
 
     std::vector<const mitk::PlaneGeometry*> planeGeometries2;
     planeGeometries2.push_back(planeGeometry4);
     planeGeometries2.push_back(planeGeometry5);
     planeGeometries2.push_back(planeGeometry6);
 
     m_Controller->AddNewContours(surfaces2, planeGeometries2, true);
 
     // Check if all contours are there
     auto contour_4 = m_Controller->GetContour(contourInfo4);
     auto contour_5 = m_Controller->GetContour(contourInfo5);
     auto contour_6 = m_Controller->GetContour(contourInfo6);
-    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3);
+    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetContours(0, 2)->size() == 3);
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_4->GetVtkPolyData()), *(contour_4->GetVtkPolyData()), 0.000001, true));
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_5->GetVtkPolyData()), *(contour_5->GetVtkPolyData()), 0.000001, true));
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_6->GetVtkPolyData()), *(contour_6->GetVtkPolyData()), 0.000001, true));
 
     // Modify some contours
     vtkSmartPointer<vtkRegularPolygonSource> p_source_7 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_7->SetNumberOfSides(200);
     p_source_7->SetCenter(3.0, 10.0, 10.0);
     p_source_7->SetRadius(5);
     p_source_7->SetNormal(1, 0, 0);
     p_source_7->Update();
     vtkPolyData *poly_7 = p_source_7->GetOutput();
     mitk::Surface::Pointer surf_7 = mitk::Surface::New();
     surf_7->SetVtkPolyData(poly_7);
     vtkSmartPointer<vtkIntArray> int7Array = vtkSmartPointer<vtkIntArray>::New();
     int7Array->InsertNextValue(2);
     int7Array->InsertNextValue(0);
     int7Array->InsertNextValue(0);
     surf_7->GetVtkPolyData()->GetFieldData()->AddArray(int7Array);
     vtkSmartPointer<vtkDoubleArray> double7Array = vtkSmartPointer<vtkDoubleArray>::New();
     double7Array->InsertNextValue(3.0);
     double7Array->InsertNextValue(10.0);
     double7Array->InsertNextValue(10.0);
     surf_7->GetVtkPolyData()->GetFieldData()->AddArray(double7Array);
 
 
     std::vector<mitk::Surface::Pointer> surfaces3;
     surfaces3.push_back(surf_7);
 
     const mitk::PlaneGeometry * planeGeometry7 = GetPlaneGeometry();
     std::vector<const mitk::PlaneGeometry*> planeGeometries3;
     planeGeometries3.push_back(planeGeometry7);
 
     m_Controller->AddNewContours(surfaces3, planeGeometries3, true);
 
     mitk::ScalarType center_7[3];
     center_7[0] = 3.0;
     center_7[1] = 10.0;
     center_7[2] = 10.0;
     vtkPolygon::ComputeNormal(surf_7->GetVtkPolyData()->GetPoints(), n);
     contourInfo5.ContourNormal = n;
     contourInfo5.ContourPoint = center_7;
 
     auto contour_7 = m_Controller->GetContour(contourInfo5);
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_7->GetVtkPolyData()), *(contour_7->GetVtkPolyData()), 0.000001, true));
 
     // Change session and test if all contours are available
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     auto contour_8 = m_Controller->GetContour(contourInfo1);
     auto contour_9 = m_Controller->GetContour(contourInfo2);
     auto contour_10 = m_Controller->GetContour(contourInfo3);
-    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 3);
+    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetContours(0, 2)->size() == 3);
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_8->GetVtkPolyData()), 0.000001, true));
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_9->GetVtkPolyData()), 0.000001, true));
     CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
                            mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_10->GetVtkPolyData()), 0.000001, true));
   }
 
   void TestRemoveContour()
   {
     // Create segmentation image
     unsigned int dimensions1[] = {12, 12, 12};
     mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage(dimensions1);
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
 
     // Create some contours
     double center_1[3] = {4.0f, 4.0f, 4.0f};
     double normal_1[3] = {0.0f, 1.0f, 0.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source->SetNumberOfSides(20);
     p_source->SetCenter(center_1);
     p_source->SetRadius(4);
     p_source->SetNormal(normal_1);
     p_source->Update();
     vtkPolyData *poly_1 = p_source->GetOutput();
     mitk::Surface::Pointer surf_1 = mitk::Surface::New();
     surf_1->SetVtkPolyData(poly_1);
     vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
     int1Array->InsertNextValue(1);
     int1Array->InsertNextValue(0);
     int1Array->InsertNextValue(0);
     surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
     vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
     double1Array->InsertNextValue(center_1[0]);
     double1Array->InsertNextValue(center_1[1]);
     double1Array->InsertNextValue(center_1[2]);
     surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
 
     double center_2[3] = {4.0f, 4.0f, 4.0f};
     double normal_2[3] = {1.0f, 0.0f, 0.0f};
     vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
     p_source_2->SetNumberOfSides(80);
     p_source_2->SetCenter(center_2);
     p_source_2->SetRadius(4);
     p_source_2->SetNormal(normal_2);
     p_source_2->Update();
     vtkPolyData *poly_2 = p_source_2->GetOutput();
     mitk::Surface::Pointer surf_2 = mitk::Surface::New();
     surf_2->SetVtkPolyData(poly_2);
     vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
     int2Array->InsertNextValue(1);
     int2Array->InsertNextValue(0);
     int2Array->InsertNextValue(0);
     surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
     vtkSmartPointer<vtkDoubleArray> double2Array = vtkSmartPointer<vtkDoubleArray>::New();
     double2Array->InsertNextValue(center_2[0]);
     double2Array->InsertNextValue(center_2[1]);
     double2Array->InsertNextValue(center_2[2]);
     surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array);
 
     std::vector<mitk::Surface::Pointer> surfaces;
     surfaces.push_back(surf_1);
     surfaces.push_back(surf_2);
 
     const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
     const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
     std::vector<const mitk::PlaneGeometry*> planeGeometries;
     planeGeometries.push_back(planeGeometry1);
     planeGeometries.push_back(planeGeometry2);
 
     m_Controller->AddNewContours(surfaces, planeGeometries, true);
     // // Add contours
-    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2);
+    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetContours(0, 1)->size() == 2);
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3;
     contourInfo3.Contour = surf_1->Clone();
     contourInfo3.ContourNormal = normal_1;
     contourInfo3.ContourPoint = center_1;
     // Shift the new contour so that it is different
     contourInfo3.ContourPoint += mitk::Vector(0.5);
 
     bool success = m_Controller->RemoveContour(contourInfo3);
     CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was unintentionally removed!",
-                           (m_Controller->GetNumberOfContours() == 2) && !success);
+                           (m_Controller->GetContours(0, 1)->size() == 2) && !success);
 
     mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
     contourInfo2.ContourNormal = normal_2;
     contourInfo2.ContourPoint = center_2;
     contourInfo2.Contour = surf_2;
     success = m_Controller->RemoveContour(contourInfo2);
     CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was not removed!",
-                           (m_Controller->GetNumberOfContours() == 1) && success);
+                           (m_Controller->GetContours(0, 1)->size() == 1) && success);
 
     // // Let's see if the other contour No. 1 is still there
     contourInfo3.ContourPoint -= mitk::Vector(0.5);
     const mitk::Surface *remainingContour = m_Controller->GetContour(contourInfo3);
     CPPUNIT_ASSERT_MESSAGE(
       "Remove failed - contour was accidentally removed!",
-      (m_Controller->GetNumberOfContours() == 1) &&
+      (m_Controller->GetContours(0, 1)->size() == 1) &&
         mitk::Equal(*(surf_1->GetVtkPolyData()), *(remainingContour->GetVtkPolyData()), 0.000001, true) && success);
   }
 
   bool AssertImagesEqual4D(mitk::LabelSetImage *img1, mitk::LabelSetImage *img2)
   {
     auto selector1 = mitk::ImageTimeSelector::New();
     selector1->SetInput(img1);
     selector1->SetChannelNr(0);
     auto selector2 = mitk::ImageTimeSelector::New();
     selector2->SetInput(img2);
     selector2->SetChannelNr(0);
 
     int numTs1 = img1->GetTimeSteps();
     int numTs2 = img2->GetTimeSteps();
     if (numTs1 != numTs2)
     {
       return false;
     }
 
     /*mitk::ImagePixelWriteAccessor<unsigned char,4> accessor( img1 );
     itk::Index<4> ind;
     ind[0] = 5;
     ind[1] = 5;
     ind[2] = 5;
     ind[3] = 2;
     accessor.SetPixelByIndex( ind, 7 );*/
 
     for (int ts = 0; ts < numTs1; ++ts)
     {
       selector1->SetTimeNr(ts);
       selector2->SetTimeNr(ts);
 
       selector1->Update();
       selector2->Update();
 
       mitk::Image::Pointer imgSel1 = selector1->GetOutput();
       mitk::Image::Pointer imgSel2 = selector2->GetOutput();
 
       MITK_ASSERT_EQUAL(imgSel1, imgSel2, "Segmentation images are not equal");
     }
 
     return true;
   }
 
   void TestSetCurrentInterpolationSession4D()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10, 5};
     mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
     // mitk::Image * segmentationImage_1 = dynamic_cast<mitk::Image *>(segmentation_1.GetPointer());
 
     unsigned int dimensions2[] = {20, 10, 30, 4};
     mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions2);
 
     // Test 1
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
-    auto currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
+    auto currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation());
     AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone());
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_1.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
                            m_Controller->GetNumberOfInterpolationSessions() == 1);
 
     // Test 2
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
     // MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_2->Clone(), "Segmentation images are not
     // equal");
-    currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
+    currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation());
     // AssertImagesEqual4D(currentSegmentation, segmentation_2->Clone());
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
                            currentSegmentation == segmentation_2.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test 3
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     // MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not
     // equal");
-    currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
+    currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation());
     AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone());
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_1.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test 4
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     // MITK_ASSERT_EQUAL(m_Controller->GetCurrentSegmentation(), segmentation_1->Clone(), "Segmentation images are not
     // equal");
-    currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation().GetPointer());
+    currentSegmentation = dynamic_cast<mitk::LabelSetImage *>(m_Controller->GetCurrentSegmentation());
     AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone());
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_1.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_1.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test 5
     m_Controller->SetCurrentInterpolationSession(nullptr);
-    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().IsNull());
+    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation()==nullptr);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
   }
 
-  void TestReplaceInterpolationSession4D()
-  {
-    // Create segmentation image
-    unsigned int dimensions1[] = {10, 10, 10, 5};
-    mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
-    m_Controller->SetCurrentInterpolationSession(segmentation_1);
-
-    m_Controller->SetCurrentTimePoint(0);
-
-    // Create some contours
-    double center_1[3] = {1.25f, 3.43f, 4.44f};
-    double normal_1[3] = {0.25f, 1.76f, 0.93f};
-    vtkSmartPointer<vtkRegularPolygonSource> p_source = vtkSmartPointer<vtkRegularPolygonSource>::New();
-    p_source->SetNumberOfSides(20);
-    p_source->SetCenter(center_1);
-    p_source->SetRadius(4);
-    p_source->SetNormal(normal_1);
-    p_source->Update();
-    vtkPolyData *poly_1 = p_source->GetOutput();
-    mitk::Surface::Pointer surf_1 = mitk::Surface::New();
-    surf_1->SetVtkPolyData(poly_1);
-    vtkSmartPointer<vtkIntArray> int1Array = vtkSmartPointer<vtkIntArray>::New();
-    int1Array->InsertNextValue(1);
-    int1Array->InsertNextValue(0);
-    int1Array->InsertNextValue(0);
-    surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array);
-    vtkSmartPointer<vtkDoubleArray> double1Array = vtkSmartPointer<vtkDoubleArray>::New();
-    double1Array->InsertNextValue(center_1[0]);
-    double1Array->InsertNextValue(center_1[1]);
-    double1Array->InsertNextValue(center_1[2]);
-    surf_1->GetVtkPolyData()->GetFieldData()->AddArray(double1Array);
-
-    double center_2[3] = {4.0f, 4.0f, 4.0f};
-    double normal_2[3] = {1.0f, 0.0f, 0.0f};
-    vtkSmartPointer<vtkRegularPolygonSource> p_source_2 = vtkSmartPointer<vtkRegularPolygonSource>::New();
-    p_source_2->SetNumberOfSides(80);
-    p_source_2->SetCenter(center_2);
-    p_source_2->SetRadius(4);
-    p_source_2->SetNormal(normal_2);
-    p_source_2->Update();
-    vtkPolyData *poly_2 = p_source_2->GetOutput();
-    mitk::Surface::Pointer surf_2 = mitk::Surface::New();
-    surf_2->SetVtkPolyData(poly_2);
-    vtkSmartPointer<vtkIntArray> int2Array = vtkSmartPointer<vtkIntArray>::New();
-    int2Array->InsertNextValue(1);
-    int2Array->InsertNextValue(0);
-    int2Array->InsertNextValue(0);
-    surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array);
-    vtkSmartPointer<vtkDoubleArray> double2Array = vtkSmartPointer<vtkDoubleArray>::New();
-    double2Array->InsertNextValue(center_2[0]);
-    double2Array->InsertNextValue(center_2[1]);
-    double2Array->InsertNextValue(center_2[2]);
-    surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array);
-
-
-    std::vector<mitk::Surface::Pointer> surfaces;
-    surfaces.push_back(surf_1);
-    surfaces.push_back(surf_2);
-
-    const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry();
-    const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry();
-    std::vector<const mitk::PlaneGeometry*> planeGeometries;
-    planeGeometries.push_back(planeGeometry1);
-    planeGeometries.push_back(planeGeometry2);
-    // Add contours
-    m_Controller->AddNewContours(surfaces, planeGeometries, true);
-
-
-    // Add contours for another timestep
-    m_Controller->SetCurrentTimePoint(2);
-
-    double center_3[3] = {1.3f, 3.5f, 4.6f};
-    double normal_3[3] = {0.20f, 1.6f, 0.8f};
-    vtkSmartPointer<vtkRegularPolygonSource> p_source_3 = vtkSmartPointer<vtkRegularPolygonSource>::New();
-    p_source_3->SetNumberOfSides(20);
-    p_source_3->SetCenter(center_3);
-    p_source_3->SetRadius(4);
-    p_source_3->SetNormal(normal_3);
-    p_source_3->Update();
-    vtkPolyData *poly_3 = p_source_3->GetOutput();
-    mitk::Surface::Pointer surf_3 = mitk::Surface::New();
-    surf_3->SetVtkPolyData(poly_3);
-    vtkSmartPointer<vtkIntArray> int3Array = vtkSmartPointer<vtkIntArray>::New();
-    int3Array->InsertNextValue(1);
-    int3Array->InsertNextValue(0);
-    int3Array->InsertNextValue(2);
-    surf_3->GetVtkPolyData()->GetFieldData()->AddArray(int3Array);
-    vtkSmartPointer<vtkDoubleArray> double3Array = vtkSmartPointer<vtkDoubleArray>::New();
-    double3Array->InsertNextValue(center_3[0]);
-    double3Array->InsertNextValue(center_3[1]);
-    double3Array->InsertNextValue(center_3[2]);
-    surf_3->GetVtkPolyData()->GetFieldData()->AddArray(double3Array);
-
-    double center_4[3] = {1.32f, 3.53f, 4.8f};
-    double normal_4[3] = {0.22f, 1.5f, 0.85f};
-    vtkSmartPointer<vtkRegularPolygonSource> p_source_4 = vtkSmartPointer<vtkRegularPolygonSource>::New();
-    p_source_4->SetNumberOfSides(20);
-    p_source_4->SetCenter(center_4);
-    p_source_4->SetRadius(4);
-    p_source_4->SetNormal(normal_4);
-    p_source_4->Update();
-    vtkPolyData *poly_4 = p_source_4->GetOutput();
-    mitk::Surface::Pointer surf_4 = mitk::Surface::New();
-    surf_4->SetVtkPolyData(poly_4);
-    vtkSmartPointer<vtkIntArray> int4Array = vtkSmartPointer<vtkIntArray>::New();
-    int4Array->InsertNextValue(1);
-    int4Array->InsertNextValue(0);
-    int4Array->InsertNextValue(2);
-    surf_4->GetVtkPolyData()->GetFieldData()->AddArray(int4Array);
-    vtkSmartPointer<vtkDoubleArray> double4Array = vtkSmartPointer<vtkDoubleArray>::New();
-    double4Array->InsertNextValue(center_4[0]);
-    double4Array->InsertNextValue(center_4[1]);
-    double4Array->InsertNextValue(center_4[2]);
-    surf_4->GetVtkPolyData()->GetFieldData()->AddArray(double4Array);
-
-
-    std::vector<mitk::Surface::Pointer> surfaces2;
-    surfaces2.push_back(surf_3);
-    surfaces2.push_back(surf_4);
-
-    const mitk::PlaneGeometry * planeGeometry3 = GetPlaneGeometry();
-    const mitk::PlaneGeometry * planeGeometry4 = GetPlaneGeometry();
-    std::vector<const mitk::PlaneGeometry*> planeGeometries2;
-    planeGeometries2.push_back(planeGeometry3);
-    planeGeometries2.push_back(planeGeometry4);
-    // Add contours
-    m_Controller->AddNewContours(surfaces2, planeGeometries2, true);
-
-    m_Controller->SetCurrentTimePoint(0);
-
-    // Check if all contours are there
-    mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo1;
-    contourInfo1.ContourNormal = normal_1;
-    contourInfo1.ContourPoint = center_1;
-
-    mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo2;
-    contourInfo2.ContourNormal = normal_2;
-    contourInfo2.ContourPoint = center_2;
-
-    mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo3;
-    mitk::ScalarType n[3];
-    vtkPolygon::ComputeNormal(surf_3->GetVtkPolyData()->GetPoints(), n);
-    contourInfo3.ContourNormal = n;
-    contourInfo3.ContourPoint = center_3;
-
-    mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo4;
-    // mitk::ScalarType n[3];
-    vtkPolygon::ComputeNormal(surf_4->GetVtkPolyData()->GetPoints(), n);
-    contourInfo4.ContourNormal = n;
-    contourInfo4.ContourPoint = center_4;
-
-    const mitk::Surface *contour_1 = m_Controller->GetContour(contourInfo1);
-    const mitk::Surface *contour_2 = m_Controller->GetContour(contourInfo2);
-
-    CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
-                           mitk::Equal(*(surf_1->GetVtkPolyData()), *(contour_1->GetVtkPolyData()), 0.000001, true));
-    CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
-                           mitk::Equal(*(surf_2->GetVtkPolyData()), *(contour_2->GetVtkPolyData()), 0.000001, true));
-
-    m_Controller->SetCurrentTimePoint(2);
-    const mitk::Surface *contour_3 = m_Controller->GetContour(contourInfo3);
-    const mitk::Surface *contour_4 = m_Controller->GetContour(contourInfo4);
-
-    CPPUNIT_ASSERT_MESSAGE("Wrong number of contours!", m_Controller->GetNumberOfContours() == 2);
-    CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
-                           mitk::Equal(*(surf_3->GetVtkPolyData()), *(contour_3->GetVtkPolyData()), 0.000001, true));
-    CPPUNIT_ASSERT_MESSAGE("Contours not equal!",
-                           mitk::Equal(*(surf_4->GetVtkPolyData()), *(contour_4->GetVtkPolyData()), 0.000001, true));
-
-    mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions1);
-    bool success = m_Controller->ReplaceInterpolationSession(segmentation_1, segmentation_2);
-
-    CPPUNIT_ASSERT_MESSAGE("Replace session failed!", success == true);
-    CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
-                           m_Controller->GetNumberOfInterpolationSessions() == 1);
-    CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
-  }
-
   void TestRemoveAllInterpolationSessions4D()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10, 4};
     mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
 
     unsigned int dimensions2[] = {20, 10, 30, 5};
     mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions2);
 
     // Test 1
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
     m_Controller->RemoveAllInterpolationSessions();
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
                            m_Controller->GetNumberOfInterpolationSessions() == 0);
   }
 
   void TestRemoveInterpolationSession4D()
   {
     // Create image for testing
     unsigned int dimensions1[] = {10, 10, 10, 3};
     mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
 
     unsigned int dimensions2[] = {20, 10, 30, 6};
     mitk::LabelSetImage::Pointer segmentation_2 = createLabelSetImage4D(dimensions2);
 
     // Test 1
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     m_Controller->SetCurrentInterpolationSession(segmentation_2);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test current segmentation should not be null if another one was removed
     m_Controller->RemoveInterpolationSession(segmentation_1);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
                            m_Controller->GetNumberOfInterpolationSessions() == 1);
     CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal",
-                           m_Controller->GetCurrentSegmentation().GetPointer() == segmentation_2.GetPointer());
+                           m_Controller->GetCurrentSegmentation() == segmentation_2.GetPointer());
     CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed",
-                           m_Controller->GetCurrentSegmentation().IsNotNull());
+                           m_Controller->GetCurrentSegmentation()!=nullptr);
 
     m_Controller->SetCurrentInterpolationSession(segmentation_1);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 2",
                            m_Controller->GetNumberOfInterpolationSessions() == 2);
 
     // Test current segmentation should not be null if another one was removed
     m_Controller->RemoveInterpolationSession(segmentation_1);
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 1",
                            m_Controller->GetNumberOfInterpolationSessions() == 1);
     CPPUNIT_ASSERT_MESSAGE("Current segmentation is not null after session was removed",
-                           m_Controller->GetCurrentSegmentation().IsNull());
+                           m_Controller->GetCurrentSegmentation()==nullptr);
   }
 
   void TestOnSegmentationDeleted4D()
   {
     {
       // Create image for testing
       unsigned int dimensions1[] = {10, 10, 10, 7};
       mitk::LabelSetImage::Pointer segmentation_1 = createLabelSetImage4D(dimensions1);
       m_Controller->SetCurrentInterpolationSession(segmentation_1);
       m_Controller->SetCurrentTimePoint(3);
     }
     CPPUNIT_ASSERT_MESSAGE("Number of interpolation session not 0",
                            m_Controller->GetNumberOfInterpolationSessions() == 0);
   }
 };
 MITK_TEST_SUITE_REGISTRATION(mitkSurfaceInterpolationController)
diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
index f939d7a447..cecea6c795 100644
--- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
+++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp
@@ -1,1406 +1,989 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #include <mitkSurfaceInterpolationController.h>
 
 #include <mitkCreateDistanceImageFromSurfaceFilter.h>
 #include <mitkComputeContourSetNormalsFilter.h>
 #include <mitkImageAccessByItk.h>
 #include <mitkImagePixelReadAccessor.h>
 #include <mitkImageTimeSelector.h>
 #include <mitkImageToSurfaceFilter.h>
 #include <mitkLabelSetImage.h>
 #include <mitkMemoryUtilities.h>
 #include <mitkNodePredicateDataUID.h>
 #include <mitkNodePredicateProperty.h>
 #include <mitkPlanarCircle.h>
 #include <mitkPlaneGeometry.h>
 #include <mitkReduceContourSetFilter.h>
 
 #include <vtkFieldData.h>
 #include <vtkMath.h>
 #include <vtkPolygon.h>
 
 // Check whether the given contours are coplanar
 bool ContoursCoplanar(mitk::SurfaceInterpolationController::ContourPositionInformation leftHandSide,
                       mitk::SurfaceInterpolationController::ContourPositionInformation rightHandSide)
 {
   // Here we check two things:
   // 1. Whether the normals of both contours are at least parallel
   // 2. Whether both contours lie in the same plane
 
   // Check for coplanarity:
   // a. Span a vector between two points one from each contour
   // b. Calculate dot product for the vector and one of the normals
   // c. If the dot is zero the two vectors are orthogonal and the contours are coplanar
 
   double vec[3];
   vec[0] = leftHandSide.ContourPoint[0] - rightHandSide.ContourPoint[0];
   vec[1] = leftHandSide.ContourPoint[1] - rightHandSide.ContourPoint[1];
   vec[2] = leftHandSide.ContourPoint[2] - rightHandSide.ContourPoint[2];
   double n[3];
   n[0] = rightHandSide.ContourNormal[0];
   n[1] = rightHandSide.ContourNormal[1];
   n[2] = rightHandSide.ContourNormal[2];
   double dot = vtkMath::Dot(n, vec);
 
   double n2[3];
   n2[0] = leftHandSide.ContourNormal[0];
   n2[1] = leftHandSide.ContourNormal[1];
   n2[2] = leftHandSide.ContourNormal[2];
 
   // The normals of both contours have to be parallel but not of the same orientation
   double lengthLHS = leftHandSide.ContourNormal.GetNorm();
   double lengthRHS = rightHandSide.ContourNormal.GetNorm();
   double dot2 = vtkMath::Dot(n, n2);
   bool contoursParallel = mitk::Equal(fabs(lengthLHS * lengthRHS), fabs(dot2), 0.001);
 
   if (mitk::Equal(dot, 0.0, 0.001) && contoursParallel)
     return true;
   else
     return false;
 }
 
 mitk::SurfaceInterpolationController::ContourPositionInformation CreateContourPositionInformation(
-  mitk::Surface::Pointer contour, const mitk::PlaneGeometry* planeGeometry)
+  const mitk::Surface* contour, const mitk::PlaneGeometry* planeGeometry)
 {
   mitk::SurfaceInterpolationController::ContourPositionInformation contourInfo;
   contourInfo.Contour = contour;
   mitk::ScalarType n[3];
   vtkPolygon::ComputeNormal(contour->GetVtkPolyData()->GetPoints(), n);
   contourInfo.ContourNormal = n;
   contourInfo.Pos = -1;
   contourInfo.TimeStep = std::numeric_limits<long unsigned int>::max();
-  contourInfo.Plane = const_cast<mitk::PlaneGeometry *>(planeGeometry);
+  contourInfo.Plane = planeGeometry;
 
   auto contourIntArray = vtkIntArray::SafeDownCast( contour->GetVtkPolyData()->GetFieldData()->GetAbstractArray(0) );
 
   if (contourIntArray->GetSize() < 2)
   {
     MITK_ERROR << "In CreateContourPositionInformation. The contourIntArray is empty.";
   }
   contourInfo.LabelValue = contourIntArray->GetValue(0);
-  contourInfo.LayerValue = contourIntArray->GetValue(1);
 
   if (contourIntArray->GetSize() >= 3)
   {
     contourInfo.TimeStep = contourIntArray->GetValue(2);
   }
 
-  contourInfo.SliceIndex = 0;
-
   return contourInfo;
 };
 
 mitk::SurfaceInterpolationController::SurfaceInterpolationController()
   : m_SelectedSegmentation(nullptr),
     m_CurrentTimePoint(0.),
-    m_ContourIndex(0),
-    m_ContourPosIndex(0),
-    m_NumberOfLayersInCurrentSegmentation(0),
-    m_PreviousActiveLabelValue(0),
-    m_CurrentActiveLabelValue(0),
-    m_PreviousLayerIndex(0),
-    m_CurrentLayerIndex(0)
+    m_ContourPosIndex(0)
 {
   m_DistanceImageSpacing = 0.0;
   m_ReduceFilter = ReduceContourSetFilter::New();
   m_NormalsFilter = ComputeContourSetNormalsFilter::New();
   m_InterpolateSurfaceFilter = CreateDistanceImageFromSurfaceFilter::New();
-  // m_TimeSelector = ImageTimeSelector::New();
 
   m_ReduceFilter->SetUseProgressBar(false);
   //  m_ReduceFilter->SetProgressStepSize(1);
   m_NormalsFilter->SetUseProgressBar(true);
   m_NormalsFilter->SetProgressStepSize(1);
   m_InterpolateSurfaceFilter->SetUseProgressBar(true);
   m_InterpolateSurfaceFilter->SetProgressStepSize(7);
 
   m_Contours = Surface::New();
 
   m_PolyData = vtkSmartPointer<vtkPolyData>::New();
   vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
   m_PolyData->SetPoints(points);
 
-  m_NumberOfConnectionsAdded = 0;
-
   m_InterpolationResult = nullptr;
   m_CurrentNumberOfReducedContours = 0;
 }
 
 mitk::SurfaceInterpolationController::~SurfaceInterpolationController()
 {
-  // Removing all observers
   this->RemoveObservers();
 }
 
 void mitk::SurfaceInterpolationController::RemoveObservers()
 {
   // Removing all observers
   auto dataIter = m_SegmentationObserverTags.begin();
   for (; dataIter != m_SegmentationObserverTags.end(); ++dataIter)
   {
     (*dataIter).first->RemoveObserver((*dataIter).second);
   }
   m_SegmentationObserverTags.clear();
+
+  if (m_SelectedSegmentation.IsNotNull())
+  {
+    m_SelectedSegmentation->RemoveLabelRemovedListener(mitk::MessageDelegate1<SurfaceInterpolationController, mitk::LabelSetImage::LabelValueType>(
+      this, &SurfaceInterpolationController::OnRemoveLabel));
+  }
 }
 
 mitk::SurfaceInterpolationController *mitk::SurfaceInterpolationController::GetInstance()
 {
   static mitk::SurfaceInterpolationController::Pointer m_Instance;
 
   if (m_Instance.IsNull())
   {
     m_Instance = SurfaceInterpolationController::New();
   }
   return m_Instance;
 }
 
 void mitk::SurfaceInterpolationController::AddNewContour(mitk::Surface::Pointer newContour)
 {
   if (newContour->GetVtkPolyData()->GetNumberOfPoints() > 0)
   {
     ContourPositionInformation contourInfo = CreateContourPositionInformation(newContour, nullptr);
     this->AddToInterpolationPipeline(contourInfo);
     this->Modified();
   }
 }
 
 void mitk::SurfaceInterpolationController::AddNewContours(const std::vector<mitk::Surface::Pointer>& newContours,
                                                           std::vector<const mitk::PlaneGeometry*>& contourPlanes,
                                                           bool reinitializationAction)
 {
   if (nullptr == m_SelectedSegmentation) return;
 
   if (newContours.size() != contourPlanes.size())
   {
     MITK_ERROR << "SurfaceInterpolationController::AddNewContours. contourPlanes and newContours are not of the same size.";
   }
 
   for (size_t i = 0; i < newContours.size(); ++i)
   {
     const auto &newContour = newContours[i];
 
     const mitk::PlaneGeometry * planeGeometry = contourPlanes[i];
     if (newContour->GetVtkPolyData()->GetNumberOfPoints() > 0)
     {
       auto contourInfo = CreateContourPositionInformation(newContour, planeGeometry);
       if (!reinitializationAction)
       {
-        contourInfo.ContourPoint = this->ComputeInteriorPointOfContour(contourInfo,
-                                              dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation) );
+        contourInfo.ContourPoint = this->ComputeInteriorPointOfContour(contourInfo, m_SelectedSegmentation);
       }
       else
       {
         auto vtkPolyData = contourInfo.Contour->GetVtkPolyData();
         auto pointVtkArray = vtkDoubleArray::SafeDownCast(vtkPolyData->GetFieldData()->GetAbstractArray(1));
         mitk::ScalarType *ptArr = new mitk::ScalarType[3];
         for (int i = 0; i < pointVtkArray->GetSize(); ++i)
           ptArr[i] = pointVtkArray->GetValue(i);
 
         mitk::Point3D pt3D;
         pt3D.FillPoint(ptArr);
         contourInfo.ContourPoint = pt3D;
       }
 
       this->AddToInterpolationPipeline(contourInfo, reinitializationAction);
     }
   }
   this->Modified();
 }
 
 mitk::DataNode* mitk::SurfaceInterpolationController::GetSegmentationImageNode()
 {
-    DataNode* segmentationNode = nullptr;
-    mitk::NodePredicateDataUID::Pointer dataUIDPredicate = mitk::NodePredicateDataUID::New(m_SelectedSegmentation->GetUID());
-    auto dataNodeObjects = m_DataStorage->GetSubset(dataUIDPredicate);
+  if (m_DataStorage.IsNull()) return nullptr;
+  if (m_SelectedSegmentation.IsNull()) return nullptr;
 
-    if (dataNodeObjects->Size() != 0)
-    {
-      for (auto it = dataNodeObjects->Begin(); it != dataNodeObjects->End(); ++it)
-      {
-        segmentationNode = it->Value();
-      }
-    }
-    else
+  DataNode* segmentationNode = nullptr;
+  mitk::NodePredicateDataUID::Pointer dataUIDPredicate = mitk::NodePredicateDataUID::New(m_SelectedSegmentation->GetUID());
+  auto dataNodeObjects = m_DataStorage->GetSubset(dataUIDPredicate);
+
+  if (dataNodeObjects->Size() != 0)
+  {
+    for (auto it = dataNodeObjects->Begin(); it != dataNodeObjects->End(); ++it)
     {
-      MITK_ERROR << "Unable to find the labelSetImage with the desired UID.";
+      segmentationNode = it->Value();
     }
-    return segmentationNode;
+  }
+  else
+  {
+    MITK_ERROR << "Unable to find the labelSetImage with the desired UID.";
+  }
+  return segmentationNode;
 }
 
 void mitk::SurfaceInterpolationController::AddPlaneGeometryNodeToDataStorage(const ContourPositionInformation& contourInfo)
 {
+  if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
+  {
+    MITK_ERROR << "Invalid time point requested in AddPlaneGeometryNodeToDataStorage.";
+    return;
+  }
+
   auto planeGeometry = contourInfo.Plane;
-  auto planeGeometryData = mitk::PlanarCircle::New();
-  planeGeometryData->SetPlaneGeometry(planeGeometry);
-  mitk::Point2D p1;
-  planeGeometry->Map(planeGeometry->GetCenter(), p1);
-  planeGeometryData->PlaceFigure(p1);
-  planeGeometryData->SetCurrentControlPoint(p1);
-  planeGeometryData->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
   if (planeGeometry)
   {
+    auto planeGeometryData = mitk::PlanarCircle::New();
+    planeGeometryData->SetPlaneGeometry(planeGeometry->Clone());
+    mitk::Point2D p1;
+    planeGeometry->Map(planeGeometry->GetCenter(), p1);
+    planeGeometryData->PlaceFigure(p1);
+    planeGeometryData->SetCurrentControlPoint(p1);
+    planeGeometryData->SetProperty("initiallyplaced", mitk::BoolProperty::New(true));
+
     auto segmentationNode = this->GetSegmentationImageNode();
     auto isContourPlaneGeometry = mitk::NodePredicateProperty::New("isContourPlaneGeometry", mitk::BoolProperty::New(true));
 
     mitk::DataStorage::SetOfObjects::ConstPointer contourNodes =
       m_DataStorage->GetDerivations(segmentationNode, isContourPlaneGeometry);
 
-    auto contourFound = false;
+    mitk::DataNode::Pointer contourPlaneGeometryDataNode;
 
     //  Go through the pre-existing contours and check if the contour position matches them.
     for (auto it = contourNodes->Begin(); it != contourNodes->End(); ++it)
     {
-      auto layerID = dynamic_cast<mitk::UIntProperty *>(it->Value()->GetProperty("layerID"))->GetValue();
       auto labelID = dynamic_cast<mitk::UShortProperty *>(it->Value()->GetProperty("labelID"))->GetValue();
       auto posID = dynamic_cast<mitk::IntProperty *>(it->Value()->GetProperty("position"))->GetValue();
-      bool sameLayer = (layerID == contourInfo.LayerValue);
       bool sameLabel = (labelID == contourInfo.LabelValue);
       bool samePos = (posID == contourInfo.Pos);
 
-      if (samePos & sameLabel & sameLayer)
+      if (samePos && sameLabel)
       {
-        contourFound = true;
-        it->Value()->SetData(planeGeometryData);
+        contourPlaneGeometryDataNode = it->Value();
         break;
       }
     }
 
-    if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
-    {
-      MITK_ERROR << "Invalid time point requested in AddPlaneGeometryNodeToDataStorage.";
-      return;
-    }
-
-    const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
-
     //  Go through the contourPlaneGeometry Data and add the segmentationNode to it.
-    if (!contourFound)
+    if (contourPlaneGeometryDataNode.IsNull())
     {
-      std::string contourName = "contourPlane " + std::to_string(m_ContourIndex);
+      const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
 
-      auto contourPlaneGeometryDataNode = mitk::DataNode::New();
+      std::string contourName = "contourPlane T " + std::to_string(currentTimeStep) + " L " + std::to_string(contourInfo.LabelValue) + "P " + std::to_string(contourInfo.Pos);
+
+      contourPlaneGeometryDataNode = mitk::DataNode::New();
       contourPlaneGeometryDataNode->SetData(planeGeometryData);
 
       //  No need to change properties
       contourPlaneGeometryDataNode->SetProperty("helper object", mitk::BoolProperty::New(false));
       contourPlaneGeometryDataNode->SetProperty("hidden object", mitk::BoolProperty::New(true));
       contourPlaneGeometryDataNode->SetProperty("isContourPlaneGeometry", mitk::BoolProperty::New(true));
       contourPlaneGeometryDataNode->SetVisibility(false);
 
       //  Need to change properties
       contourPlaneGeometryDataNode->SetProperty("name", mitk::StringProperty::New(contourName) );
-      contourPlaneGeometryDataNode->SetProperty("layerID", mitk::UIntProperty::New(contourInfo.LayerValue));
       contourPlaneGeometryDataNode->SetProperty("labelID", mitk::UShortProperty::New(contourInfo.LabelValue));
       contourPlaneGeometryDataNode->SetProperty("position", mitk::IntProperty::New(contourInfo.Pos));
       contourPlaneGeometryDataNode->SetProperty("timeStep", mitk::IntProperty::New(currentTimeStep));
 
       contourPlaneGeometryDataNode->SetProperty("px", mitk::DoubleProperty::New(contourInfo.ContourPoint[0]));
       contourPlaneGeometryDataNode->SetProperty("py", mitk::DoubleProperty::New(contourInfo.ContourPoint[1]));
       contourPlaneGeometryDataNode->SetProperty("pz", mitk::DoubleProperty::New(contourInfo.ContourPoint[2]));
 
       m_DataStorage->Add(contourPlaneGeometryDataNode, segmentationNode);
     }
+
+    contourPlaneGeometryDataNode->SetData(planeGeometryData);
+
   }
 }
 
 void mitk::SurfaceInterpolationController::AddToInterpolationPipeline(ContourPositionInformation& contourInfo, bool reinitializationAction)
 {
-  if (!m_SelectedSegmentation)
+  if (m_SelectedSegmentation.IsNull())
     return;
 
   if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
   {
     MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
     return;
   }
 
-  //  Get current time step either from the
-  auto GetCurrentTimeStep = [=](ContourPositionInformation contourInfo)
-  {
-    if (reinitializationAction)
-    {
-      return contourInfo.TimeStep;
-    }
-    return static_cast<size_t>(m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint));
-  };
-  const auto currentTimeStep = GetCurrentTimeStep(contourInfo);
-  auto GetContourLayerID = [=](ContourPositionInformation contourInfo)
-  {
-    unsigned int currentLayerID;
-    if(reinitializationAction)
-    {
-      if (contourInfo.LayerValue == std::numeric_limits<unsigned int>::max())
-      {
-        MITK_ERROR << "In mitk::SurfaceInterpolationController::AddToInterpolationPipeline. Problem in finding layerID";
-      }
-        currentLayerID = contourInfo.LayerValue;
-    }
-    else
-    {
-      try
-      {
-        currentLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
-      }
-      catch (const std::exception& e)
-      {
-        MITK_ERROR << "Unable to cast image to LabelSetImage. " << e.what() << '\n';
-      }
-    }
-    return currentLayerID;
-  };
-
-  unsigned int currentLayerID = GetContourLayerID(contourInfo);
-
-  ContourPositionInformationVec3D &currentImageContours = m_ListOfContours.at(m_SelectedSegmentation);
-  ContourPositionInformationVec2D &currentTimeStepContoursList = currentImageContours.at(currentTimeStep);
-  ContourPositionInformationList &currentContourList = currentTimeStepContoursList.at(currentLayerID);
-
-  int replacementIndex = -1;
-  int pos = -1;
-  mitk::Surface* newContour = contourInfo.Contour;
-
-  for (size_t i = 0; i < currentContourList.size(); i++)
+  if (contourInfo.Plane == nullptr)
   {
-    auto& contourFromList = currentContourList.at(i);
-    bool contoursAreCoplanar = ContoursCoplanar(contourInfo, contourFromList);
-    bool contoursHaveSameLabel = contourInfo.LabelValue == contourFromList.LabelValue;
-
-    //  Coplanar contours have the same "pos".
-    if (contoursAreCoplanar)
-    {
-      pos = contourFromList.Pos;
-      if (contoursHaveSameLabel)
-      {
-        replacementIndex = i;
-      }
-    }
+    MITK_ERROR << "contourInfo plane is null.";
+    return;
   }
-  //  The current contour has the same label and position as the current slice and a replacement is done.
-  if (replacementIndex != -1)
-  {
-    contourInfo.Pos = pos;
-    m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).at(replacementIndex) = contourInfo;
 
-    if (!reinitializationAction)
-    {
-      this->AddPlaneGeometryNodeToDataStorage(contourInfo);
-    }
+  if (contourInfo.Contour->GetVtkPolyData()->GetNumberOfPoints() == 0)
+  {
+    this->RemoveContour(contourInfo);
+    MITK_DEBUG << "contourInfo contour is empty.";
     return;
   }
 
-  //  Case that there is no contour in the current slice with the current label
-  if (pos == -1)
-    pos = m_ContourPosIndex++;
+  const auto currentTimeStep = reinitializationAction ? contourInfo.TimeStep : m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
 
-  m_ContourIndex++;
-  contourInfo.Pos = pos;
-  m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).push_back(contourInfo);
+  const auto currentLabelValue = reinitializationAction ? contourInfo.LabelValue : m_SelectedSegmentation->GetActiveLabel()->GetValue();
 
-  if (contourInfo.Plane == nullptr)
+  auto& currentImageContours = m_CPIMap[m_SelectedSegmentation];
+  auto& currentLabelContours = currentImageContours[currentLabelValue];
+  auto& currentContourList = currentLabelContours[currentTimeStep];
+
+  auto finding = std::find_if(currentContourList.begin(), currentContourList.end(), [contourInfo](const ContourPositionInformation& element) {return ContoursCoplanar(contourInfo, element); });
+
+  if (finding != currentContourList.end())
   {
-    MITK_ERROR << "contourInfo plane is null.";
+    contourInfo.Pos = finding->Pos;
+    *finding = contourInfo;
   }
-  if (!reinitializationAction)
+  else
   {
-    this->AddPlaneGeometryNodeToDataStorage(contourInfo);
+    contourInfo.Pos = currentContourList.size();
+    currentContourList.push_back(contourInfo);
   }
 
-  if (newContour->GetVtkPolyData()->GetNumberOfPoints() == 0)
+  if (!reinitializationAction)
   {
-    this->RemoveContour(contourInfo);
-    if  (m_ContourIndex > 0)
-      m_ContourIndex--;
-    if  (m_ContourIndex > 0)
-      m_ContourIndex--;
+    this->AddPlaneGeometryNodeToDataStorage(contourInfo);
   }
 }
 
 bool mitk::SurfaceInterpolationController::RemoveContour(ContourPositionInformation contourInfo)
 {
   if (!m_SelectedSegmentation)
   {
     return false;
   }
 
   if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
   {
     return false;
   }
 
   const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
-  unsigned int currentLayerID = 0;
-  try
-  {
-    currentLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
-  }
-  catch (const std::exception& e)
-  {
-    MITK_ERROR << e.what() << '\n';
-  }
+  const auto currentLabel = m_SelectedSegmentation->GetActiveLabel()->GetValue();
+  auto it = m_CPIMap.at(m_SelectedSegmentation).at(currentLabel).at(currentTimeStep).begin();
 
-  auto it = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).begin();
-  while (it != m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).end())
+  while (it != m_CPIMap.at(m_SelectedSegmentation).at(currentLabel).at(currentTimeStep).end())
   {
     const ContourPositionInformation &currentContour = (*it);
     if (ContoursCoplanar(currentContour, contourInfo))
     {
-      m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).erase(it);
+      m_CPIMap.at(m_SelectedSegmentation).at(currentLabel).at(currentTimeStep).erase(it);
       this->ReinitializeInterpolation();
       return true;
     }
     ++it;
   }
   return false;
 }
 
 const mitk::Surface *mitk::SurfaceInterpolationController::GetContour(const ContourPositionInformation &contourInfo)
 {
   if (!m_SelectedSegmentation)
   {
     return nullptr;
   }
 
   if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
   {
     return nullptr;
   }
   const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
-  const auto activeLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
-  const auto &contourList = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(activeLayerID);
+  const auto currentLabel = m_SelectedSegmentation->GetActiveLabel()->GetValue();
+  const auto &contourList = m_CPIMap.at(m_SelectedSegmentation).at(currentLabel).at(currentTimeStep);
 
   for (auto &currentContour : contourList)
   {
     if (ContoursCoplanar(contourInfo, currentContour))
     {
       return currentContour.Contour;
     }
   }
   return nullptr;
 }
 
-unsigned int mitk::SurfaceInterpolationController::GetNumberOfContours()
-{
-  if (!m_SelectedSegmentation)
-  {
-    return -1;
-  }
-
-  if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
-  {
-    return -1;
-  }
-  const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
-  auto contourDoubleList = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep);
-
-  unsigned int numContours = 0;
-  for (auto& contourList : contourDoubleList)
-  {
-
-    numContours += contourList.size();
-  }
-
-  return numContours;
-}
+//unsigned int mitk::SurfaceInterpolationController::GetNumberOfContours()
+//{
+//  if (!m_SelectedSegmentation)
+//  {
+//    return -1;
+//  }
+//
+//  if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
+//  {
+//    return -1;
+//  }
+//  const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
+//  auto contourDoubleList = m_CPIMap.at(m_SelectedSegmentation).at(currentTimeStep);
+//
+//  unsigned int numContours = 0;
+//  for (auto& contourList : contourDoubleList)
+//  {
+//
+//    numContours += contourList.size();
+//  }
+//
+//  return numContours;
+//}
 
 void mitk::SurfaceInterpolationController::AddActiveLabelContoursForInterpolation(mitk::Label::PixelType activeLabel)
 {
   this->ReinitializeInterpolation();
 
   if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
   {
     MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
     return;
   }
   const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
 
-  unsigned int currentLayerID = 0;
-  try
-  {
-    currentLayerID = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
-  }
-  catch (const std::exception& e)
+  auto& currentImageContours = m_CPIMap.at(m_SelectedSegmentation);
+
+  auto finding = currentImageContours.find(activeLabel);
+  if (finding == currentImageContours.end())
   {
-    MITK_ERROR << e.what() << '\n';
+    MITK_INFO << "Contours for label don't exist. Label value: " << activeLabel;
+    return;
   }
 
-  ContourPositionInformationVec3D &currentImageContours = m_ListOfContours.at(m_SelectedSegmentation);
+  auto currentLabelContoursMap = finding->second;
 
-  if (currentImageContours.size() <= currentTimeStep)
+  auto tsfinding = currentLabelContoursMap.find(currentTimeStep);
+  if (tsfinding == currentLabelContoursMap.end())
   {
     MITK_INFO << "Contours for current time step don't exist.";
     return;
   }
-  ContourPositionInformationVec2D &currentTimeStepContoursList = currentImageContours.at(currentTimeStep);
 
-  if (currentTimeStepContoursList.size() <= currentLayerID)
-  {
-    MITK_INFO << "Contours for current layer don't exist.";
-    return;
-  }
-  ContourPositionInformationList &currentContours = currentTimeStepContoursList.at(currentLayerID);
+  CPIVector& currentContours = tsfinding->second;
 
-  for (size_t i = 0; i < currentContours.size(); ++i)
+  unsigned int index = 0;
+  m_ReduceFilter->Reset();
+  for (const auto&  cpi : currentContours)
   {
-    if (currentContours.at(i).LabelValue == activeLabel)
-    {
-      m_ListOfInterpolationSessions.at(m_SelectedSegmentation).at(currentTimeStep).push_back(currentContours.at(i));
-      m_ReduceFilter->SetInput(m_ListOfInterpolationSessions.at(m_SelectedSegmentation).at(currentTimeStep).size()-1, currentContours.at(i).Contour);
-    }
+    m_ReduceFilter->SetInput(index, cpi.Contour);
+    ++index;
   }
 }
 
 void mitk::SurfaceInterpolationController::Interpolate()
 {
   if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
   {
     MITK_WARN << "No interpolation possible, currently selected timepoint is not in the time bounds of currently selected segmentation. Time point: " << m_CurrentTimePoint;
     m_InterpolationResult = nullptr;
     return;
   }
   const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
   m_ReduceFilter->Update();
   m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs();
 
   if (m_CurrentNumberOfReducedContours == 1)
   {
     vtkPolyData *tmp = m_ReduceFilter->GetOutput(0)->GetVtkPolyData();
     if (tmp == nullptr)
     {
       m_CurrentNumberOfReducedContours = 0;
     }
   }
 
   //  We use the timeSelector to get the segmentation image for the current segmentation.
   mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
   timeSelector->SetInput(m_SelectedSegmentation);
   timeSelector->SetTimeNr(currentTimeStep);
   timeSelector->SetChannelNr(0);
   timeSelector->Update();
 
   mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
   itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New();
   AccessFixedDimensionByItk_1(refSegImage, GetImageBase, 3, itkImage);
 
   m_NormalsFilter->SetSegmentationBinaryImage(refSegImage);
 
   for (size_t i = 0; i < m_CurrentNumberOfReducedContours; ++i)
   {
     mitk::Surface::Pointer reducedContour = m_ReduceFilter->GetOutput(i);
     reducedContour->DisconnectPipeline();
     m_NormalsFilter->SetInput(i, reducedContour);
     m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i));
   }
 
   if (m_CurrentNumberOfReducedContours < 2)
   {
     // If no interpolation is possible reset the interpolation result
     MITK_INFO << "Interpolation impossible: not enough contours.";
     m_InterpolationResult = nullptr;
     return;
   }
 
   // Setting up progress bar
   mitk::ProgressBar::GetInstance()->AddStepsToDo(10);
 
   // create a surface from the distance-image
   mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New();
   imageToSurfaceFilter->SetInput(m_InterpolateSurfaceFilter->GetOutput());
   imageToSurfaceFilter->SetThreshold(0);
   imageToSurfaceFilter->SetSmooth(true);
   imageToSurfaceFilter->SetSmoothIteration(1);
   imageToSurfaceFilter->Update();
 
   mitk::Surface::Pointer interpolationResult = mitk::Surface::New();
   interpolationResult->Expand(m_SelectedSegmentation->GetTimeSteps());
 
   auto geometry = m_SelectedSegmentation->GetTimeGeometry()->Clone();
   geometry->ReplaceTimeStepGeometries(mitk::Geometry3D::New());
   interpolationResult->SetTimeGeometry(geometry);
 
   interpolationResult->SetVtkPolyData(imageToSurfaceFilter->GetOutput()->GetVtkPolyData(), currentTimeStep);
   m_InterpolationResult = interpolationResult;
 
   m_DistanceImageSpacing = m_InterpolateSurfaceFilter->GetDistanceImageSpacing();
 
   auto* contoursGeometry = static_cast<mitk::ProportionalTimeGeometry*>(m_Contours->GetTimeGeometry());
   auto timeBounds = geometry->GetTimeBounds(currentTimeStep);
   contoursGeometry->SetFirstTimePoint(timeBounds[0]);
   contoursGeometry->SetStepDuration(timeBounds[1] - timeBounds[0]);
 
   // Last progress step
   mitk::ProgressBar::GetInstance()->Progress(20);
   m_InterpolationResult->DisconnectPipeline();
 }
 
 mitk::Surface::Pointer mitk::SurfaceInterpolationController::GetInterpolationResult()
 {
   return m_InterpolationResult;
 }
 
 mitk::Surface *mitk::SurfaceInterpolationController::GetContoursAsSurface()
 {
   return m_Contours;
 }
 
 
 void mitk::SurfaceInterpolationController::SetDataStorage(DataStorage::Pointer ds)
 {
   m_DataStorage = ds;
 }
 
 void mitk::SurfaceInterpolationController::SetMinSpacing(double minSpacing)
 {
   m_ReduceFilter->SetMinSpacing(minSpacing);
 }
 
 void mitk::SurfaceInterpolationController::SetMaxSpacing(double maxSpacing)
 {
   m_ReduceFilter->SetMaxSpacing(maxSpacing);
   m_NormalsFilter->SetMaxSpacing(maxSpacing);
 }
 
 void mitk::SurfaceInterpolationController::SetDistanceImageVolume(unsigned int distImgVolume)
 {
   m_InterpolateSurfaceFilter->SetDistanceImageVolume(distImgVolume);
 }
 
-mitk::Image::Pointer mitk::SurfaceInterpolationController::GetCurrentSegmentation()
+mitk::LabelSetImage* mitk::SurfaceInterpolationController::GetCurrentSegmentation()
 {
   return m_SelectedSegmentation;
 }
 
-mitk::Image *mitk::SurfaceInterpolationController::GetImage()
+mitk::Image *mitk::SurfaceInterpolationController::GetInterpolationImage()
 {
   return m_InterpolateSurfaceFilter->GetOutput();
 }
 
 double mitk::SurfaceInterpolationController::EstimatePortionOfNeededMemory()
 {
   double numberOfPointsAfterReduction = m_ReduceFilter->GetNumberOfPointsAfterReduction() * 3;
   double sizeOfPoints = pow(numberOfPointsAfterReduction, 2) * sizeof(double);
   double totalMem = mitk::MemoryUtilities::GetTotalSizeOfPhysicalRam();
   double percentage = sizeOfPoints / totalMem;
   return percentage;
 }
 
 unsigned int mitk::SurfaceInterpolationController::GetNumberOfInterpolationSessions()
 {
-  return m_ListOfInterpolationSessions.size();
+  return m_CPIMap.size();
 }
 
 template <typename TPixel, unsigned int VImageDimension>
 void mitk::SurfaceInterpolationController::GetImageBase(itk::Image<TPixel, VImageDimension> *input,
                                                         itk::ImageBase<3>::Pointer &result)
 {
   result->Graft(input);
 }
 
-void mitk::SurfaceInterpolationController::SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation)
+void mitk::SurfaceInterpolationController::SetCurrentInterpolationSession(mitk::LabelSetImage* currentSegmentationImage)
 {
-  this->SetCurrentInterpolationSession(segmentation);
-}
-
-void mitk::SurfaceInterpolationController::SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage)
-{
-  if (currentSegmentationImage.GetPointer() == m_SelectedSegmentation)
+  if (currentSegmentationImage == m_SelectedSegmentation)
   {
     return;
   }
 
-  if (currentSegmentationImage.IsNull())
+  if (m_SelectedSegmentation.IsNotNull())
   {
-    m_SelectedSegmentation = nullptr;
-    return;
+    m_SelectedSegmentation->RemoveLabelRemovedListener(mitk::MessageDelegate1<SurfaceInterpolationController, mitk::LabelSetImage::LabelValueType>(
+      this, &SurfaceInterpolationController::OnRemoveLabel));
   }
-  m_SelectedSegmentation = currentSegmentationImage.GetPointer();
 
-  try
+  m_SelectedSegmentation = currentSegmentationImage;
+
+  if (m_SelectedSegmentation.IsNotNull())
   {
-    auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
-    auto it = m_ListOfContours.find(currentSegmentationImage.GetPointer());
-    // If the session does not exist yet create a new ContourPositionPairList otherwise reinitialize the interpolation
-    // pipeline
-    if (it == m_ListOfContours.end())
+    auto it = m_CPIMap.find(currentSegmentationImage);
+    if (it == m_CPIMap.end())
     {
-      ContourPositionInformationVec3D newList;
-
-      auto numTimeSteps = labelSetImage->GetTimeGeometry()->CountTimeSteps();
-
-      for (size_t t = 0; t < numTimeSteps; ++t)
-      {
-        auto twoDList = ContourPositionInformationVec2D();
-        auto contourList = ContourPositionInformationList();
-        twoDList.push_back(contourList);
-        newList.push_back(twoDList);
-      }
-
-      m_ListOfContours[m_SelectedSegmentation] = newList;
-
-      m_InterpolationResult = nullptr;
-      m_CurrentNumberOfReducedContours = 0;
+      m_CPIMap[m_SelectedSegmentation] = CPITimeStepLabelMap();
 
       auto command = itk::MemberCommand<SurfaceInterpolationController>::New();
       command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted);
-      m_SegmentationObserverTags[m_SelectedSegmentation] = labelSetImage->AddObserver(itk::DeleteEvent(), command);
-
-      m_NumberOfLayersInCurrentSegmentation = labelSetImage->GetNumberOfLayers();
+      m_SegmentationObserverTags[m_SelectedSegmentation] = m_SelectedSegmentation->AddObserver(itk::DeleteEvent(), command);
     }
 
-    // auto labelSetImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
-    auto numLayersInSelectedSegmentation = labelSetImage->GetNumberOfLayers();
-    //  Maybe this has to change.
-    for (size_t layerID = 0; layerID < numLayersInSelectedSegmentation; ++layerID)
-    {
-      this->AddLabelSetConnection(layerID);
-    }
-  }
-  catch (const std::exception &e)
-  {
-    MITK_ERROR << "Unable to cast image as LabelSetImage";
-  }
-
-  auto it2 = m_ListOfInterpolationSessions.find(currentSegmentationImage.GetPointer());
-  if (it2 == m_ListOfInterpolationSessions.end())
-  {
-    ContourPositionInformationVec2D newList;
-    m_ListOfInterpolationSessions[m_SelectedSegmentation] = newList;
-    m_InterpolationResult = nullptr;
-    m_CurrentNumberOfReducedContours = 0;
+    m_SelectedSegmentation->AddLabelRemovedListener(mitk::MessageDelegate1<SurfaceInterpolationController, mitk::LabelSetImage::LabelValueType>(
+      this, &SurfaceInterpolationController::OnRemoveLabel));
   }
 
+  m_InterpolationResult = nullptr;
+  m_CurrentNumberOfReducedContours = 0;
+  m_NormalsFilter->SetSegmentationBinaryImage(nullptr);
   this->ReinitializeInterpolation();
 }
 
-bool mitk::SurfaceInterpolationController::ReplaceInterpolationSession(mitk::Image::Pointer oldSession,
-                                                                       mitk::Image::Pointer newSession)
-{
-  if (oldSession.IsNull() || newSession.IsNull())
-    return false;
-
-  if (oldSession.GetPointer() == newSession.GetPointer())
-    return false;
-
-  if (!mitk::Equal(*(oldSession->GetGeometry()), *(newSession->GetGeometry()), mitk::eps, false))
-    return false;
-
-  auto it = m_ListOfInterpolationSessions.find(oldSession.GetPointer());
-
-  if (it == m_ListOfInterpolationSessions.end())
-    return false;
-
-  if (!newSession->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
-  {
-    MITK_WARN << "Interpolation session cannot be replaced. Currently selected timepoint is not in the time bounds of the new session. Time point: " << m_CurrentTimePoint;
-    return false;
-  }
-
-  ContourPositionInformationVec2D oldList = (*it).second;
-
-  m_ListOfInterpolationSessions[newSession.GetPointer()] = oldList;
-
-  itk::MemberCommand<SurfaceInterpolationController>::Pointer command =
-    itk::MemberCommand<SurfaceInterpolationController>::New();
-
-  command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted);
-
-  m_SegmentationObserverTags[newSession] = newSession->AddObserver(itk::DeleteEvent(), command);
-
-  if (m_SelectedSegmentation == oldSession)
-    m_SelectedSegmentation = newSession;
-
-  const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
-
-  mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
-  timeSelector->SetInput(m_SelectedSegmentation);
-  timeSelector->SetTimeNr(currentTimeStep);
-  timeSelector->SetChannelNr(0);
-  timeSelector->Update();
-  mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
-
-  m_NormalsFilter->SetSegmentationBinaryImage(refSegImage);
-
-  this->RemoveInterpolationSession(oldSession);
-  return true;
-}
-
-void mitk::SurfaceInterpolationController::RemoveSegmentationFromContourList(mitk::Image *segmentation)
+void mitk::SurfaceInterpolationController::RemoveInterpolationSession(mitk::LabelSetImage* segmentationImage)
 {
-  this->RemoveInterpolationSession(segmentation);
-}
-
-void mitk::SurfaceInterpolationController::RemoveInterpolationSession(mitk::Image::Pointer segmentationImage)
-{
-  if (segmentationImage)
+  if (nullptr == segmentationImage)
   {
     if (m_SelectedSegmentation == segmentationImage)
     {
+      m_SelectedSegmentation->RemoveLabelRemovedListener(mitk::MessageDelegate1<SurfaceInterpolationController, mitk::LabelSetImage::LabelValueType>(
+        this, &SurfaceInterpolationController::OnRemoveLabel));
       m_NormalsFilter->SetSegmentationBinaryImage(nullptr);
       m_SelectedSegmentation = nullptr;
     }
-    m_ListOfInterpolationSessions.erase(segmentationImage);
-    m_ListOfContours.erase(segmentationImage);
+
+    m_CPIMap.erase(segmentationImage);
 
     // Remove observer
     auto pos = m_SegmentationObserverTags.find(segmentationImage);
     if (pos != m_SegmentationObserverTags.end())
     {
       segmentationImage->RemoveObserver((*pos).second);
       m_SegmentationObserverTags.erase(pos);
     }
   }
 }
 
 void mitk::SurfaceInterpolationController::RemoveAllInterpolationSessions()
 {
-  // Removing all observers
-  auto dataIter = m_SegmentationObserverTags.begin();
-  while (dataIter != m_SegmentationObserverTags.end())
-  {
-    mitk::Image *image = (*dataIter).first;
-    image->RemoveObserver((*dataIter).second);
-    ++dataIter;
-  }
-
-  m_SegmentationObserverTags.clear();
+  this->RemoveObservers();
+  m_NormalsFilter->SetSegmentationBinaryImage(nullptr);
   m_SelectedSegmentation = nullptr;
-  m_ListOfInterpolationSessions.clear();
-  m_ListOfContours.clear();
+  m_CPIMap.clear();
 }
 
-
-template <unsigned int VImageDimension = 3>
-std::vector<mitk::Label::PixelType> GetPixelValuesPresentInImage(mitk::LabelSetImage* labelSetImage)
+void mitk::SurfaceInterpolationController::RemoveContours(mitk::Label::PixelType label,
+  TimeStepType timeStep)
 {
-  mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage);
-  std::vector<mitk::Label::PixelType> pixelsPresent;
-
-  std::size_t numberOfPixels = 1;
-  for (int dim = 0; dim < static_cast<int>(VImageDimension); ++dim)
-    numberOfPixels *= static_cast<std::size_t>(readAccessor.GetDimension(dim));
+  auto cpiLabelMap = m_CPIMap[m_SelectedSegmentation];
+  auto finding = cpiLabelMap.find(label);
 
-  auto src = readAccessor.GetData();
-  for (std::size_t i = 0; i < numberOfPixels; ++i)
+  if (finding != cpiLabelMap.end())
   {
-    mitk::Label::PixelType pixelVal = *(src + i);
-    if ( (std::find(pixelsPresent.begin(), pixelsPresent.end(), pixelVal) == pixelsPresent.end()) && (pixelVal != 0) )
-    {
-      pixelsPresent.push_back(pixelVal);
-    }
+    finding->second.erase(timeStep);
   }
-  return pixelsPresent;
 }
 
-void mitk::SurfaceInterpolationController::RemoveContours(mitk::Label::PixelType label,
-                                                          unsigned int timeStep,
-                                                          unsigned int layerID)
+void mitk::SurfaceInterpolationController::RemoveContours(mitk::Label::PixelType label)
 {
-  auto isContourEqualToLabelValue = [label] (ContourPositionInformation& contour) -> bool
-  {
-    return (contour.LabelValue == label);
-  };
-
-  ContourPositionInformationVec3D &currentImageContours = m_ListOfContours.at(m_SelectedSegmentation);
-  ContourPositionInformationList &currentContourList = currentImageContours.at(timeStep).at(layerID);
-  unsigned int numContoursBefore = currentContourList.size();
-  auto it = std::remove_if(currentContourList.begin(), currentContourList.end(), isContourEqualToLabelValue);
-  currentContourList.erase(it, currentContourList.end());
-  unsigned int numContoursAfter = currentContourList.size();
-  unsigned int numContours = numContoursAfter - numContoursBefore;
-  m_ContourIndex -= numContours;
+  m_CPIMap[m_SelectedSegmentation].erase(label);
 }
 
+
 void mitk::SurfaceInterpolationController::OnSegmentationDeleted(const itk::Object *caller,
                                                                  const itk::EventObject & /*event*/)
 {
-  auto *tempImage = dynamic_cast<mitk::Image *>(const_cast<itk::Object *>(caller));
+  auto *tempImage = dynamic_cast<mitk::LabelSetImage *>(const_cast<itk::Object *>(caller));
   if (tempImage)
   {
     if (m_SelectedSegmentation == tempImage)
     {
-      m_NormalsFilter->SetSegmentationBinaryImage(nullptr);
-      m_SelectedSegmentation = nullptr;
+      this->SetCurrentInterpolationSession(nullptr);
     }
     m_SegmentationObserverTags.erase(tempImage);
-    m_ListOfContours.erase(tempImage);
-    m_ListOfInterpolationSessions.erase(tempImage);
+    m_CPIMap.erase(tempImage);
   }
 }
 
 void mitk::SurfaceInterpolationController::ReinitializeInterpolation()
 {
   // If session has changed reset the pipeline
   m_ReduceFilter->Reset();
   m_NormalsFilter->Reset();
   m_InterpolateSurfaceFilter->Reset();
 
-  //  Empty out the listOfInterpolationSessions
-  m_ListOfInterpolationSessions[m_SelectedSegmentation].clear();
-
   itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New();
 
-  if (m_SelectedSegmentation)
+  if (m_SelectedSegmentation.IsNotNull())
   {
     if (!m_SelectedSegmentation->GetTimeGeometry()->IsValidTimePoint(m_CurrentTimePoint))
     {
       MITK_WARN << "Interpolation cannot be reinitialized. Currently selected timepoint is not in the time bounds of the currently selected segmentation. Time point: " << m_CurrentTimePoint;
       return;
     }
 
     const auto currentTimeStep = m_SelectedSegmentation->GetTimeGeometry()->TimePointToTimeStep(m_CurrentTimePoint);
 
     //  Set reference image for interpolation surface filter
     mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
     timeSelector->SetInput(m_SelectedSegmentation);
     timeSelector->SetTimeNr(currentTimeStep);
     timeSelector->SetChannelNr(0);
     timeSelector->Update();
     mitk::Image::Pointer refSegImage = timeSelector->GetOutput();
     AccessFixedDimensionByItk_1(refSegImage, GetImageBase, 3, itkImage);
     m_InterpolateSurfaceFilter->SetReferenceImage(itkImage.GetPointer());
-
-    //  Resize listofinterpolationsessions and listofcontours to numTimeSteps
-    unsigned int numTimeSteps = m_SelectedSegmentation->GetTimeSteps();
-    unsigned int size = m_ListOfInterpolationSessions[m_SelectedSegmentation].size();
-
-    if (size != numTimeSteps)
-    {
-      m_ListOfInterpolationSessions.at(m_SelectedSegmentation).resize(numTimeSteps);
-    }
-  }
-}
-
-void mitk::SurfaceInterpolationController::AddLabelSetConnection(unsigned int layerID)
-{
-  if (m_SelectedSegmentation != nullptr)
-  {
-    try
-    {
-      auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
-      auto previousLayerID = workingImage->GetActiveLayer();
-      workingImage->SetActiveLayer(layerID);
-      auto activeLabelSet = workingImage->GetLabelSet(layerID);
-
-      if (activeLabelSet == nullptr)
-        return;
-
-      activeLabelSet->RemoveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-        this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
-      activeLabelSet->ActiveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-            this, &mitk::SurfaceInterpolationController::OnActiveLabel);
-      workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
-        this, &mitk::SurfaceInterpolationController::OnLayerChanged);
-        m_NumberOfConnectionsAdded += 1;
-      workingImage->SetActiveLayer(previousLayerID);
-    }
-    catch(const std::exception& e)
-    {
-      MITK_ERROR << e.what() << '\n';
-    }
   }
 }
 
-void mitk::SurfaceInterpolationController::AddLabelSetConnection()
+void mitk::SurfaceInterpolationController::OnRemoveLabel(mitk::Label::PixelType removedLabelValue)
 {
-  if (m_SelectedSegmentation != nullptr)
+  if (m_SelectedSegmentation.IsNotNull())
   {
-    try
-    {
-      auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
-      auto activeLabelSet = workingImage->GetActiveLabelSet();
-
-      if (activeLabelSet == nullptr)
-        return;
-
-      activeLabelSet->RemoveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-        this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
-      workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-            this, &mitk::SurfaceInterpolationController::OnActiveLabel);
-      workingImage->AfterChangeLayerEvent += mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
-        this, &mitk::SurfaceInterpolationController::OnLayerChanged);
-        m_NumberOfConnectionsAdded += 1;
-    }
-    catch(const std::exception& e)
-    {
-      MITK_ERROR << e.what() << '\n';
-    }
+    this->RemoveContours(removedLabelValue);
   }
 }
 
-void mitk::SurfaceInterpolationController::RemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID)
-{
-  labelSetImage->SetActiveLayer(layerID);
-  labelSetImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-    this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
-  // labelSetImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-  //       this, &mitk::SurfaceInterpolationController::OnActiveLabel);
-  labelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
-    this, &mitk::SurfaceInterpolationController::OnLayerChanged);
-  m_NumberOfConnectionsAdded -= 1;
-}
-
-void mitk::SurfaceInterpolationController::RemoveLabelSetConnection()
+mitk::SurfaceInterpolationController::CPIVector* mitk::SurfaceInterpolationController::GetContours(TimeStepType timeStep, LabelSetImage::LabelValueType labelValue)
 {
-  if (m_SelectedSegmentation != nullptr)
-  {
-    try
-    {
-      auto workingImage = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation);
-      workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-        this, &mitk::SurfaceInterpolationController::OnRemoveLabel);
-      workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1<mitk::SurfaceInterpolationController, mitk::Label::PixelType>(
-            this, &mitk::SurfaceInterpolationController::OnActiveLabel);
-      workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate<mitk::SurfaceInterpolationController>(
-        this, &mitk::SurfaceInterpolationController::OnLayerChanged);
-    }
-    catch (const std::exception& e)
-    {
-      std::cerr << e.what() << '\n';
-    }
-  }
-}
-
-void mitk::SurfaceInterpolationController::OnRemoveLabel(mitk::Label::PixelType /*removedLabelValue*/)
-{
-  if (m_SelectedSegmentation != nullptr)
-  {
-    auto numTimeSteps = m_SelectedSegmentation->GetTimeGeometry()->CountTimeSteps();
-    try
-    {
-      auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
-      auto currentLayerID = labelSetImage->GetActiveLayer();
-
-      for(unsigned int t = 0; t < numTimeSteps; ++t)
-      {
-        this->RemoveContours(m_PreviousActiveLabelValue,t,currentLayerID);
-      }
-
-    }
-    catch(const std::exception& e)
-    {
-      std::cerr << e.what() << '\n';
-    }
-  }
-}
-
-void mitk::SurfaceInterpolationController::OnActiveLabel(mitk::Label::PixelType newActiveLabelValue)
-{
-  m_PreviousActiveLabelValue = m_CurrentActiveLabelValue;
-  m_CurrentActiveLabelValue = newActiveLabelValue;
-}
-
-unsigned int mitk::SurfaceInterpolationController::GetNumberOfLayersInCurrentSegmentation() const
-{
-  return m_NumberOfLayersInCurrentSegmentation;
-}
+  if (m_SelectedSegmentation == nullptr)
+    return nullptr;
 
-void mitk::SurfaceInterpolationController::SetNumberOfLayersInCurrentSegmentation(unsigned int numLayers)
-{
-  m_NumberOfLayersInCurrentSegmentation = numLayers;
-}
+  auto labelFinding = m_CPIMap[m_SelectedSegmentation].find(labelValue);
 
-void mitk::SurfaceInterpolationController::OnAddLayer()
-{
-  assert(m_SelectedSegmentation != nullptr);
-  auto& contoursForSegmentation = m_ListOfContours.at(m_SelectedSegmentation);
-  //  Push an information list for each time step.
-  for(size_t t = 0; t < contoursForSegmentation.size(); ++t)
+  if (labelFinding != m_CPIMap[m_SelectedSegmentation].end())
   {
-    contoursForSegmentation.at(t).push_back( ContourPositionInformationList() );
-  }
-}
-
-void mitk::SurfaceInterpolationController::OnRemoveLayer()
-{
-  assert(m_SelectedSegmentation != nullptr);
-  auto& contoursForSegmentation = m_ListOfContours.at(m_SelectedSegmentation);
-  //  Erase the layers in each of the time steps.
+    auto tsFinding = labelFinding->second.find(labelValue);
 
-  //  The previous layer is removed
-  for (size_t t = 0; t < contoursForSegmentation.size(); ++t)
-  {
-    assert(m_PreviousLayerIndex < contoursForSegmentation.at(t).size());
-    auto& contoursAtTimeStep = contoursForSegmentation.at(t);
-    for (size_t c = m_CurrentLayerIndex+1; c < contoursAtTimeStep.size(); ++c)
+    if (tsFinding != labelFinding->second.end())
     {
-      auto& contoursInCurrentLayer = contoursAtTimeStep.at(c);
-      for (auto& contour : contoursInCurrentLayer)
-      {
-        contour.LayerValue = contour.LayerValue - 1;
-      }
+      return &(tsFinding->second);
     }
   }
 
-  for (size_t t = 0; t < contoursForSegmentation.size(); ++t)
-  {
-    assert (m_CurrentLayerIndex < contoursForSegmentation.at(t).size());
-    contoursForSegmentation.at(t).erase(contoursForSegmentation.at(t).begin() + m_PreviousLayerIndex);
-  }
-  this->Modified();
-}
-
-void mitk::SurfaceInterpolationController::OnLayerChanged()
-{
-  auto currentLayer = dynamic_cast<mitk::LabelSetImage*>(m_SelectedSegmentation)->GetActiveLayer();
-  m_PreviousLayerIndex = m_CurrentLayerIndex;
-  m_CurrentLayerIndex = currentLayer;
-}
-
-mitk::SurfaceInterpolationController::ContourPositionInformationList* mitk::SurfaceInterpolationController::GetContours(unsigned int timeStep, unsigned int layerID)
-{
-  if (m_SelectedSegmentation == nullptr)
-    return nullptr;
-
-  if (timeStep >= m_ListOfContours.at(m_SelectedSegmentation).size())
-    return nullptr;
-
-  if (layerID >= m_ListOfContours.at(m_SelectedSegmentation).at(timeStep).size())
-    return nullptr;
-
-  return &m_ListOfContours[m_SelectedSegmentation][timeStep][layerID];
+  return nullptr;
 }
 
 void mitk::SurfaceInterpolationController::CompleteReinitialization(const std::vector<mitk::Surface::Pointer>& contourList,
                                                                     std::vector<const mitk::PlaneGeometry *>& contourPlanes)
 {
   this->ClearInterpolationSession();
 
-  auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
-  auto numLayers = labelSetImage->GetNumberOfLayers();
-
-  //  Add layers to the m_ListOfContours
-  for (size_t layer = 0; layer < numLayers; ++layer)
-  {
-    this->OnAddLayer();
-  }
-
   //  Now the layers should be empty and the new layers can be added.
   this->AddNewContours(contourList, contourPlanes, true);
 }
 
 void mitk::SurfaceInterpolationController::ClearInterpolationSession()
 {
   if (m_SelectedSegmentation != nullptr)
   {
-    auto it = m_ListOfContours.find(m_SelectedSegmentation);
-    if (it != m_ListOfContours.end())
-    {
-      auto timeSteps = m_ListOfContours[m_SelectedSegmentation].size();
-      try
-      {
-        auto labelSetImage = dynamic_cast<mitk::LabelSetImage *>(m_SelectedSegmentation);
-        auto labelSetImageTimeSteps = labelSetImage->GetTimeGeometry()->CountTimeSteps();
-
-        if (timeSteps != labelSetImageTimeSteps)
-        {
-          MITK_ERROR << "Time steps are not the same.";
-        }
-
-        for (size_t t = 0; t < timeSteps; ++t)
-        {
-          m_ListOfContours[m_SelectedSegmentation][t].clear();
-        }
-
-      }
-      catch(std::bad_cast& e)
-      {
-        MITK_ERROR << "Unable to cast m_SelectedSegmentation to labelSetImage in ClearInterpolationSession";
-      }
-    }
+    m_CPIMap[m_SelectedSegmentation].clear();
   }
 }
 
 std::vector< mitk::Point3D > mitk::ContourExt::GetBoundingBoxGridPoints(
                                               size_t planeDimension,
                                               double startDim1,
                                               size_t numPointsToSampleDim1,
                                               double deltaDim1,
                                               double startDim2,
                                               size_t numPointsToSampleDim2,
                                               double deltaDim2,
                                               double valuePlaneDim)
 {
   std::vector< mitk::Point3D > gridPoints;
   for (size_t i = 0; i < numPointsToSampleDim1; ++i)
   {
     for (size_t j = 0; j < numPointsToSampleDim2; ++j)
     {
       mitk::ScalarType *ptVec = new mitk::ScalarType[3];
 
       if (planeDimension == 0)
       {
         ptVec[0] = valuePlaneDim;
         ptVec[1] = startDim1 + deltaDim1 * i;
         ptVec[2] = startDim2 + deltaDim2 * j;
       }
       else if (planeDimension == 1)
       {
         ptVec[0] = startDim1 + deltaDim1 * i;
         ptVec[1] = valuePlaneDim;
         ptVec[2] = startDim2 + deltaDim2 * j;
 
       }
       else if (planeDimension == 2)
       {
         ptVec[0] = startDim1 + deltaDim1 * i;
         ptVec[1] = startDim2 + deltaDim2 * j;
         ptVec[2] = valuePlaneDim;
       }
 
       mitk::Point3D pt3D;
       pt3D.FillPoint(ptVec);
       gridPoints.push_back(pt3D);
     }
   }
 
   return gridPoints;
 }
 
 mitk::Point3D mitk::SurfaceInterpolationController::ComputeInteriorPointOfContour(
                                     const mitk::SurfaceInterpolationController::ContourPositionInformation& contour,
                                     mitk::LabelSetImage * labelSetImage)
 {
   if (labelSetImage->GetDimension() == 4)
   {
     return mitk::ContourExt::ComputeInteriorPointOfContour<4>(contour, labelSetImage, m_CurrentTimePoint);
   }
   else
   {
     return mitk::ContourExt::ComputeInteriorPointOfContour<3>(contour, labelSetImage, m_CurrentTimePoint);
   }
 }
 
 template<unsigned int VImageDimension>
 mitk::Point3D mitk::ContourExt::ComputeInteriorPointOfContour(
                                     const mitk::SurfaceInterpolationController::ContourPositionInformation& contour,
                                     mitk::LabelSetImage * labelSetImage,
                                     mitk::TimePointType currentTimePoint)
 {
-  mitk::ImagePixelReadAccessor<mitk::LabelSet::PixelType, VImageDimension> readAccessor(labelSetImage);
+  mitk::ImagePixelReadAccessor<mitk::Label::PixelType, VImageDimension> readAccessor(labelSetImage);
 
   if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(currentTimePoint))
   {
     MITK_ERROR << "Invalid time point requested for interpolation pipeline.";
     mitk::Point3D pt;
     return pt;
   }
 
   std::vector<mitk::Label::PixelType> pixelsPresent;
   const auto currentTimeStep = labelSetImage->GetTimeGeometry()->TimePointToTimeStep(currentTimePoint);
 
   auto polyData = contour.Contour->GetVtkPolyData();
 
   polyData->ComputeCellsBounds();
   mitk::ScalarType cellBounds[6];
   polyData->GetCellsBounds(cellBounds);
 
   size_t numPointsToSample = 10;
   mitk::ScalarType StartX = cellBounds[0];
   mitk::ScalarType StartY = cellBounds[2];
   mitk::ScalarType StartZ = cellBounds[4];
 
   size_t deltaX = (cellBounds[1] - cellBounds[0]) / numPointsToSample;
   size_t deltaY = (cellBounds[3] - cellBounds[2]) / numPointsToSample;
   size_t deltaZ = (cellBounds[5] - cellBounds[4]) / numPointsToSample;
 
   auto planeOrientation = mitk::ContourExt::GetContourOrientation(contour.ContourNormal);
 
   std::vector<mitk::Point3D> points;
   if (planeOrientation == 0)
   {
     points = mitk::ContourExt::GetBoundingBoxGridPoints(planeOrientation,
                                       StartY, numPointsToSample, deltaY,
                                       StartZ, numPointsToSample, deltaZ,
                                       StartX);
   }
   else if (planeOrientation == 1)
   {
     points = mitk::ContourExt::GetBoundingBoxGridPoints(planeOrientation,
                                       StartX, numPointsToSample, deltaX,
                                       StartZ, numPointsToSample, deltaZ,
                                       StartY);
   }
   else if (planeOrientation == 2)
   {
     points = mitk::ContourExt::GetBoundingBoxGridPoints(planeOrientation,
                                       StartX, numPointsToSample, deltaX,
                                       StartY, numPointsToSample, deltaY,
                                       StartZ);
   }
   mitk::Label::PixelType pixelVal;
   mitk::Point3D pt3D;
   std::vector<mitk::Label::PixelType> pixelVals;
   for (size_t i = 0; i < points.size(); ++i)
   {
     pt3D = points[i];
     itk::Index<3> itkIndex;
     labelSetImage->GetGeometry()->WorldToIndex(pt3D, itkIndex);
 
     if (VImageDimension == 4)
     {
       itk::Index<VImageDimension> time3DIndex;
       for (size_t i = 0; i < itkIndex.size(); ++i)
         time3DIndex[i] = itkIndex[i];
       time3DIndex[3] = currentTimeStep;
 
       pixelVal = readAccessor.GetPixelByIndexSafe(time3DIndex);
     }
     else if (VImageDimension == 3)
     {
       itk::Index<VImageDimension> geomIndex;
       for (size_t i=0;i<itkIndex.size();++i)
         geomIndex[i] = itkIndex[i];
 
       pixelVal = readAccessor.GetPixelByIndexSafe(geomIndex);
     }
 
     if (pixelVal == contour.LabelValue)
       break;
   }
   return pt3D;
 }
 
 size_t mitk::ContourExt::GetContourOrientation(const mitk::Vector3D& ContourNormal)
 {
   double n[3];
   n[0] = ContourNormal[0];
   n[1] = ContourNormal[1];
   n[2] = ContourNormal[2];
 
   double XVec[3];
   XVec[0] = 1.0;  XVec[1] = 0.0;  XVec[2] = 0.0;
   double dotX = vtkMath::Dot(n, XVec);
 
   double YVec[3];
   YVec[0] = 0.0;  YVec[1] = 1.0;  YVec[2] = 0.0;
   double dotY = vtkMath::Dot(n, YVec);
 
   double ZVec[3];
   ZVec[0] = 0.0;  ZVec[1] = 0.0;  ZVec[2] = 1.0;
   double dotZ = vtkMath::Dot(n, ZVec);
 
   size_t planeOrientation = 0;
   if (fabs(dotZ) > mitk::eps)
   {
     planeOrientation = 2;
   }
   else if (fabs(dotY) > mitk::eps)
   {
     planeOrientation = 1;
   }
   else if(fabs(dotX) > mitk::eps)
   {
     planeOrientation = 0;
   }
   return planeOrientation;
 }
diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h
index 3a2ea6eccc..202dfc3abe 100644
--- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h
+++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.h
@@ -1,468 +1,371 @@
 /*============================================================================
 
 The Medical Imaging Interaction Toolkit (MITK)
 
 Copyright (c) German Cancer Research Center (DKFZ)
 All rights reserved.
 
 Use of this source code is governed by a 3-clause BSD license that can be
 found in the LICENSE file.
 
 ============================================================================*/
 
 #ifndef mitkSurfaceInterpolationController_h
 #define mitkSurfaceInterpolationController_h
 
 #include <mitkDataStorage.h>
-#include <mitkImage.h>
+#include <mitkLabelSetImage.h>
 #include <mitkLabel.h>
 #include <mitkSurface.h>
 
 #include <MitkSurfaceInterpolationExports.h>
 
 namespace mitk
 {
   class ComputeContourSetNormalsFilter;
   class CreateDistanceImageFromSurfaceFilter;
   class LabelSetImage;
   class ReduceContourSetFilter;
 
   class MITKSURFACEINTERPOLATION_EXPORT SurfaceInterpolationController : public itk::Object
   {
   public:
     mitkClassMacroItkParent(SurfaceInterpolationController, itk::Object);
     itkFactorylessNewMacro(Self);
     itkCloneMacro(Self);
     itkGetMacro(DistanceImageSpacing, double);
 
     struct MITKSURFACEINTERPOLATION_EXPORT ContourPositionInformation
     {
       int Pos;
-      unsigned int SliceIndex;
-      Surface::Pointer Contour;
+      Surface::ConstPointer Contour;
       Vector3D ContourNormal;
       Point3D ContourPoint;
-      mitk::PlaneGeometry* Plane;
-      mitk::Label::PixelType LabelValue;
-      unsigned int LayerValue;
-      size_t TimeStep;
+      PlaneGeometry::ConstPointer Plane;
+      Label::PixelType LabelValue;
+      TimeStepType TimeStep;
 
       ContourPositionInformation()
         : Pos(-1),
-          SliceIndex(0),
           Plane(nullptr),
-          LabelValue(std::numeric_limits<mitk::Label::PixelType>::max()),
-          LayerValue(std::numeric_limits<unsigned int>::max()),
-          TimeStep(std::numeric_limits<size_t>::max())
+          LabelValue(std::numeric_limits<Label::PixelType>::max()),
+          TimeStep(std::numeric_limits<TimeStepType>::max())
       {
       }
     };
 
-    typedef std::vector<ContourPositionInformation> ContourPositionInformationList;
-    typedef std::vector<ContourPositionInformationList> ContourPositionInformationVec2D;
+    typedef std::vector<ContourPositionInformation> CPIVector;
+    typedef std::map<TimeStepType, CPIVector> CPITimeStepMap;
+    typedef std::map<LabelSetImage::LabelValueType, CPITimeStepMap> CPITimeStepLabelMap;
 
-    //  first index is the current time step. second index is the layerID. third index is the contour index.
-    typedef std::vector<ContourPositionInformationVec2D> ContourPositionInformationVec3D;
-
-    typedef std::map<mitk::Image *, ContourPositionInformationVec3D> ContourListMap;
-    typedef std::map<mitk::Image *, ContourPositionInformationVec2D> ContourContainer;
+    typedef std::map<LabelSetImage*, CPITimeStepLabelMap> CPITimeStepLabelSegMap;
 
     static SurfaceInterpolationController *GetInstance();
 
     void SetCurrentTimePoint(TimePointType tp)
     {
       if (m_CurrentTimePoint != tp)
       {
         m_CurrentTimePoint = tp;
 
         if (m_SelectedSegmentation)
         {
           this->ReinitializeInterpolation();
         }
       }
     };
 
     TimePointType GetCurrentTimePoint() const { return m_CurrentTimePoint; };
 
     /**
      * @brief Adds a new extracted contour to the list
      * @param newContour the contour to be added. If a contour at that position
      *        already exists the related contour will be updated
      */
     void AddNewContour(Surface::Pointer newContour);
 
     /**
      * @brief Adds new extracted contours to the list. If one or more contours at a given position
      *        already exist they will be updated respectively
      */
     void AddNewContours(const std::vector<Surface::Pointer>& newContours, std::vector<const mitk::PlaneGeometry*>& contourPlanes, bool reinitializeAction = false);
 
     /**
     * @brief Returns the contour for a given plane for the current selected segmenation
     * @param contourInfo the contour which should be returned
     * @return the contour as an mitk::Surface. If no contour is available at the give position nullptr is returned
     */
     const mitk::Surface *GetContour(const ContourPositionInformation& contourInfo);
 
     /**
      * @brief Computes an interior point of the input contour. It's used to detect merge and erase operations.
      *
      * @param contour Contour for which to compute the contour
      * @param labelSetImage LabelSetImage used input to check contour Label.
      * @return mitk::Point3D 3D Interior point of the contour returned.
      */
     mitk::Point3D ComputeInteriorPointOfContour(const ContourPositionInformation& contour,
                                                  mitk::LabelSetImage * labelSetImage);
 
-    /**
-     * @brief Make the surface interpolator responsive to the segmentation image by subscribing to events from the image.
-     *
-     */
-    void AddLabelSetConnection();
-
-    /**
-     * @brief Make the surface interpolator responsive to the segmentation image by stopping subscription to events from the image.
-     *
-     */
-    void RemoveLabelSetConnection();
-
-    void RemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID);
-
 
     /**
      * @brief Resets the pipeline for interpolation. The various filters used are reset.
      *
      */
     void ReinitializeInterpolation();
 
     void RemoveObservers();
 
-    void AddLabelSetConnection(unsigned int layerID);
-
-    void UnsetSelectedImage()
-    {
-      m_SelectedSegmentation = nullptr;
-    }
-
-    /**
-     * @brief Returns the number of layers in the current segmentation image.
-     *
-     */
-    unsigned int GetNumberOfLayersInCurrentSegmentation() const;
-
-    /**
-     * @brief Set the number of layers in the current segmentation image.
-     *
-     */
-    void SetNumberOfLayersInCurrentSegmentation(unsigned int);
-
-    /**
-     * @brief Function that does the data management when a layer is removed.
-     *
-     */
-    void OnRemoveLayer();
-
-    /**
-     * @brief  Function that does the data management when a layer is added.
-     *
-     */
-    void OnAddLayer();
-
-    /**
-    * @brief Returns the number of available contours for the current selected segmentation
-    * @return the number of contours
-    */
-    unsigned int GetNumberOfContours();
-
     /**
      * @brief Performs the interpolation.
      *
      */
     void Interpolate();
 
     /**
      * @brief Get the Result of the interpolation operation.
      *
      * @return mitk::Surface::Pointer
      */
     mitk::Surface::Pointer GetInterpolationResult();
 
     /**
      * @brief Sets the minimum spacing of the current selected segmentation
      * This is needed since the contour points we reduced before they are used to interpolate the surface.
      *
      * @param minSpacing Paramter to set
      */
     void SetMinSpacing(double minSpacing);
 
     /**
      * @brief Sets the minimum spacing of the current selected segmentation
      * This is needed since the contour points we reduced before they are used to interpolate the surface
      * @param maxSpacing Set the max Spacing for interpolation
      */
     void SetMaxSpacing(double maxSpacing);
 
     /**
      * Sets the volume i.e. the number of pixels that the distance image should have
      * By evaluation we found out that 50.000 pixel delivers a good result
      */
     void SetDistanceImageVolume(unsigned int distImageVolume);
 
     /**
      * @brief Get the current selected segmentation for which the interpolation is performed
      * @return the current segmentation image
      */
-    mitk::Image::Pointer GetCurrentSegmentation();
+    mitk::LabelSetImage* GetCurrentSegmentation();
 
     Surface *GetContoursAsSurface();
 
     void SetDataStorage(DataStorage::Pointer ds);
 
-    /**
-     * Sets the current list of contourpoints which is used for the surface interpolation
-     * @param segmentation The current selected segmentation
-     * \deprecatedSince{2014_03}
-     */
-    DEPRECATED(void SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation));
-
     /**
      * Sets the current list of contourpoints which is used for the surface interpolation
      * @param currentSegmentationImage The current selected segmentation
      */
-    void SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage);
-
-    /**
-     * Removes the segmentation and all its contours from the list
-     * @param segmentation The segmentation to be removed
-     * \deprecatedSince{2014_03}
-     */
-    DEPRECATED(void RemoveSegmentationFromContourList(mitk::Image *segmentation));
+    void SetCurrentInterpolationSession(LabelSetImage* currentSegmentationImage);
 
     /**
      * @brief Remove interpolation session
      * @param segmentationImage the session to be removed
      */
-    void RemoveInterpolationSession(mitk::Image::Pointer segmentationImage);
-
-    /**
-     * Replaces the current interpolation session with a new one. All contours form the old
-     * session will be applied to the new session. This only works if the two images have the
-     * geometry
-     * @param oldSession the session which should be replaced
-     * @param newSession the new session which replaces the old one
-     * @return true it the the replacement was successful, false if not (e.g. the image's geometry differs)
-     */
-    bool ReplaceInterpolationSession(mitk::Image::Pointer oldSession, mitk::Image::Pointer newSession);
+    void RemoveInterpolationSession(LabelSetImage* segmentationImage);
 
     /**
      * @brief Removes all sessions
      */
     void RemoveAllInterpolationSessions();
 
-    mitk::Image *GetImage();
+    mitk::Image *GetInterpolationImage();
 
     /**
      * @brief Get the Contours at a certain timeStep and layerID.
      *
      * @param timeStep Time Step from which to get the contours.
      * @param layerID Layer from which to get the contours.
      * @return std::vector<ContourPositionInformation> Returns contours.
      */
-    ContourPositionInformationList* GetContours(unsigned int timeStep, unsigned int layerID);
+    CPIVector* GetContours(TimeStepType timeStep, LabelSetImage::LabelValueType labelValue);
 
     /**
      * @brief Trigerred with the "Reinit Interpolation" action. The contours are used to repopulate the
      *        surfaceInterpolator data structures so that interpolation can be performed after reloading data.
      *
      * @param contourList List of contours extracted
      * @param contourPlanes List of planes at which the contours were extracted
      */
     void CompleteReinitialization(const std::vector<mitk::Surface::Pointer>& contourList,
                                            std::vector<const mitk::PlaneGeometry *>& contourPlanes);
 
     /**
-     * @brief Removes contours of a particular label, at a given time step and layerID.
+     * @brief Removes contours of a particular label and at a given time step for the current session/segmentation.
+     *
+     * @param label Label of contour to remove.
+     * @param timeStep Time step in which to remove the contours.
+     * @remark if the label or time step does not exist, nothing happens.
+     */
+    void RemoveContours(mitk::Label::PixelType label, TimeStepType timeStep);
+
+    /**
+     * @brief Removes contours of a particular label and at a given time step for the current session/segmentation.
      *
      * @param label Label of contour to remove.
      * @param timeStep Time step in which to remove the contours.
-     * @param layerID Layer in which the contour should be removed.
+     * @remark if the label or time step does not exist, nothing happens.
      */
-    void RemoveContours(mitk::Label::PixelType label, unsigned int timeStep, unsigned int layerID);
+    void RemoveContours(mitk::Label::PixelType label);
 
     /**
      * Estimates the memory which is needed to build up the equationsystem for the interpolation.
      * \returns The percentage of the real memory which will be used by the interpolation
      */
     double EstimatePortionOfNeededMemory();
 
     /**
      * Adds Contours from the active Label to the interpolation pipeline
      */
     void AddActiveLabelContoursForInterpolation(mitk::Label::PixelType activeLabel);
 
     unsigned int GetNumberOfInterpolationSessions();
 
     /**
      * @brief Removes the contour for a given plane for the current selected segmenation
      * @param contourInfo the contour which should be removed
      * @return true if a contour was found and removed, false if no contour was found
      */
     bool RemoveContour(ContourPositionInformation contourInfo);
 
     /**
      * @brief Get the Segmentation Image Node object
      *
      * @return DataNode* returns the DataNode containing the segmentation image.
      */
     mitk::DataNode* GetSegmentationImageNode();
 
-
-
   protected:
     SurfaceInterpolationController();
 
     ~SurfaceInterpolationController() override;
 
     template <typename TPixel, unsigned int VImageDimension>
     void GetImageBase(itk::Image<TPixel, VImageDimension> *input, itk::ImageBase<3>::Pointer &result);
 
   private:
 
     /**
      * @brief
      *
      * @param caller
      * @param event
      */
     void OnSegmentationDeleted(const itk::Object *caller, const itk::EventObject &event);
 
     /**
      * @brief Function that removes contours of a particular label when the "Remove Label" event is trigerred in the labelSetImage.
      *
      */
     void OnRemoveLabel(mitk::Label::PixelType removedLabelValue);
 
     /**
      * @brief When a new contour is added to the pipeline or an existing contour is replaced,
      *        the plane geometry information of that contour is added as a child node to the
      *        current node of the segmentation image. This is useful in the retrieval of contour information
      *        when data is reloaded after saving.
      *
      * @param contourInfo contourInfo struct to add to data storage.
      */
     void AddPlaneGeometryNodeToDataStorage(const ContourPositionInformation& contourInfo);
 
-    /**
-     * @brief Function that toggles active label, when the active label is changed.
-     *
-     */
-    void OnActiveLabel(mitk::Label::PixelType);
-
     /**
      * @brief Clears the interpolation data structures. Called from CompleteReinitialization().
      *
      */
     void ClearInterpolationSession();
 
     /**
      * @brief Add contour to the interpolation pipeline
      *
      * @param contourInfo Contour information to be added
      * @param reinitializationAction If the contour is coming from a reinitialization process or not
      */
     void AddToInterpolationPipeline(ContourPositionInformation& contourInfo, bool reinitializationAction = false);
 
-    /**
-     * @brief Function to respond to layer changed
-     *
-     */
-    void OnLayerChanged();
-
     itk::SmartPointer<ReduceContourSetFilter> m_ReduceFilter;
     itk::SmartPointer<ComputeContourSetNormalsFilter> m_NormalsFilter;
     itk::SmartPointer<CreateDistanceImageFromSurfaceFilter> m_InterpolateSurfaceFilter;
 
     mitk::Surface::Pointer m_Contours;
 
     double m_DistanceImageSpacing;
 
     vtkSmartPointer<vtkPolyData> m_PolyData;
 
     mitk::DataStorage::Pointer m_DataStorage;
 
-    ContourContainer m_ListOfInterpolationSessions;
-    ContourListMap m_ListOfContours;
+    CPITimeStepLabelSegMap m_CPIMap;
 
     mitk::Surface::Pointer m_InterpolationResult;
 
     unsigned int m_CurrentNumberOfReducedContours;
-    unsigned int m_NumberOfConnectionsAdded;
 
-    mitk::Image *m_SelectedSegmentation;
+    mitk::LabelSetImage::Pointer m_SelectedSegmentation;
 
     std::map<mitk::Image *, unsigned long> m_SegmentationObserverTags;
 
     mitk::TimePointType m_CurrentTimePoint;
 
-    unsigned int m_ContourIndex;
     unsigned int m_ContourPosIndex;
-    unsigned int m_NumberOfLayersInCurrentSegmentation;
-
-    mitk::Label::PixelType m_PreviousActiveLabelValue;
-    mitk::Label::PixelType m_CurrentActiveLabelValue;
-
-    unsigned int m_PreviousLayerIndex;
-    unsigned int m_CurrentLayerIndex;
   };
 
   namespace ContourExt
   {
     /**
      * @brief Returns the plane the contour belongs to.
      *
      * @param ContourNormal
      * @return size_t
      */
     size_t GetContourOrientation(const mitk::Vector3D& ContourNormal);
 
     /**
      * @brief Function used to compute an interior point of the contour.
      *        Used to react to the merge label and erase label actions.
      *
      *
      * @tparam VImageDimension Dimension of the image
      * @param contour Contour for which to compute the interior point
      * @param labelSetImage Label Set Image For which to find the contour
      * @param currentTimePoint Current Time Point of the Image
      * @return mitk::Point3D The returned point in the interior of the contour.s
      */
     template<unsigned int VImageDimension>
     mitk::Point3D ComputeInteriorPointOfContour(const mitk::SurfaceInterpolationController::ContourPositionInformation& contour,
                                                  mitk::LabelSetImage * labelSetImage,
                                                  mitk::TimePointType currentTimePoint);
     /**
      * @brief Get a Grid points within the bounding box of the contour at a certain spacing.
      *
      * @param planeDimension  Plane orientation (Sagittal, Coronal, Axial)
      * @param startDim1 Starting coordinate along dimension 1 to start the grid point sampling from
      * @param numPointsToSampleDim1 Number of points to sample along dimension 1
      * @param deltaDim1 Spacing for dimension 1 at which points should be sampled
      * @param startDim2 Starting coordinate along dimension 2 to start the grid point sampling from
      * @param numPointsToSampleDim2 Number of points to sample along dimension 2
      * @param deltaDim2 Spacing for dimension 1 at which points should be sampled
      * @param valuePlaneDim Slice index of the plane in the volume
      * @return std::vector< mitk::Point3D > The computed grid points are returned by the function.
      */
     std::vector< mitk::Point3D > GetBoundingBoxGridPoints(size_t planeDimension,
                                             double startDim1,
                                             size_t numPointsToSampleDim1,
                                             double deltaDim1,
                                             double startDim2,
                                             size_t numPointsToSampleDim2,
                                             double deltaDim2,
                                             double valuePlaneDim);
   };
 
 }
 
 #endif