diff --git a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp index 7984c4bdae..20faa7a6e4 100644 --- a/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp +++ b/Modules/SurfaceInterpolation/Testing/mitkSurfaceInterpolationControllerTest.cpp @@ -1,1098 +1,1097 @@ /*============================================================================ 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 #include #include #include #include #include #include #include #include #include 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(); 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(); 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->SetCurrentTimePoint(0.); + m_Controller->RemoveAllInterpolationSessions(); + m_Controller->SetCurrentTimePoint(0); vtkSmartPointer polygonSource = vtkSmartPointer::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("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()); 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()); 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()); 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("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 p_source = vtkSmartPointer::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 int1Array = vtkSmartPointer::New(); int1Array->InsertNextValue(1); int1Array->InsertNextValue(0); int1Array->InsertNextValue(0); surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array); vtkSmartPointer double1Array = vtkSmartPointer::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 p_source_2 = vtkSmartPointer::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 int2Array = vtkSmartPointer::New(); int2Array->InsertNextValue(1); int2Array->InsertNextValue(0); int2Array->InsertNextValue(0); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array); vtkSmartPointer doubleArray = vtkSmartPointer::New(); doubleArray->InsertNextValue(center_2[0]); doubleArray->InsertNextValue(center_2[1]); doubleArray->InsertNextValue(center_2[2]); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(doubleArray); std::vector surfaces; surfaces.push_back(surf_1); surfaces.push_back(surf_2); const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry(); const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry(); std::vector 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); // 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()); CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed", m_Controller->GetCurrentSegmentation().IsNotNull()); 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()); } void TestOnSegmentationDeleted() { - { - m_Controller->RemoveAllInterpolationSessions(); - // Create image for testing - unsigned int dimensions1[] = {10, 10, 10}; - mitk::Image::Pointer segmentation_1 = createLabelSetImage(dimensions1); - m_Controller->SetCurrentInterpolationSession(segmentation_1); - } + // 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() { - m_Controller->RemoveAllInterpolationSessions(); // Create segmentation image unsigned int dimensions1[] = {10, 10, 10}; mitk::Image::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 p_source = vtkSmartPointer::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 int1Array = vtkSmartPointer::New(); int1Array->InsertNextValue(1); int1Array->InsertNextValue(0); int1Array->InsertNextValue(0); surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array); vtkSmartPointer double1Array = vtkSmartPointer::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 p_source_2 = vtkSmartPointer::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 int2Array = vtkSmartPointer::New(); int2Array->InsertNextValue(1); int2Array->InsertNextValue(0); int2Array->InsertNextValue(0); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array); vtkSmartPointer double2Array = vtkSmartPointer::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 p_source_3 = vtkSmartPointer::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 int3Array = vtkSmartPointer::New(); int3Array->InsertNextValue(1); int3Array->InsertNextValue(0); int3Array->InsertNextValue(0); surf_3->GetVtkPolyData()->GetFieldData()->AddArray(int3Array); vtkSmartPointer double3Array = vtkSmartPointer::New(); double3Array->InsertNextValue(center_3[0]); double3Array->InsertNextValue(center_3[1]); double3Array->InsertNextValue(center_3[2]); surf_3->GetVtkPolyData()->GetFieldData()->AddArray(double3Array); std::vector 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 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("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 p_source_4 = vtkSmartPointer::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 int4Array = vtkSmartPointer::New(); int4Array->InsertNextValue(2); int4Array->InsertNextValue(0); int4Array->InsertNextValue(0); surf_4->GetVtkPolyData()->GetFieldData()->AddArray(int4Array); vtkSmartPointer double4Array = vtkSmartPointer::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 p_source_5 = vtkSmartPointer::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 int5Array = vtkSmartPointer::New(); int5Array->InsertNextValue(2); int5Array->InsertNextValue(0); int5Array->InsertNextValue(0); surf_5->GetVtkPolyData()->GetFieldData()->AddArray(int5Array); vtkSmartPointer double5Array = vtkSmartPointer::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 p_source_6 = vtkSmartPointer::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 int6Array = vtkSmartPointer::New(); int6Array->InsertNextValue(2); int6Array->InsertNextValue(0); int6Array->InsertNextValue(0); surf_6->GetVtkPolyData()->GetFieldData()->AddArray(int6Array); vtkSmartPointer double6Array = vtkSmartPointer::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 surfaces2; surfaces2.push_back(surf_4); surfaces2.push_back(surf_5); surfaces2.push_back(surf_6); std::vector 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("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 p_source_7 = vtkSmartPointer::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 int7Array = vtkSmartPointer::New(); int7Array->InsertNextValue(2); int7Array->InsertNextValue(0); int7Array->InsertNextValue(0); surf_7->GetVtkPolyData()->GetFieldData()->AddArray(int7Array); vtkSmartPointer double7Array = vtkSmartPointer::New(); double7Array->InsertNextValue(3.0); double7Array->InsertNextValue(10.0); double7Array->InsertNextValue(10.0); surf_7->GetVtkPolyData()->GetFieldData()->AddArray(double7Array); std::vector surfaces3; surfaces3.push_back(surf_7); const mitk::PlaneGeometry * planeGeometry7 = GetPlaneGeometry(); std::vector 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("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() { - m_Controller->RemoveAllInterpolationSessions(); // 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 p_source = vtkSmartPointer::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 int1Array = vtkSmartPointer::New(); int1Array->InsertNextValue(1); int1Array->InsertNextValue(0); int1Array->InsertNextValue(0); surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array); vtkSmartPointer double1Array = vtkSmartPointer::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 p_source_2 = vtkSmartPointer::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 int2Array = vtkSmartPointer::New(); int2Array->InsertNextValue(1); int2Array->InsertNextValue(0); int2Array->InsertNextValue(0); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array); vtkSmartPointer double2Array = vtkSmartPointer::New(); double2Array->InsertNextValue(center_2[0]); double2Array->InsertNextValue(center_2[1]); double2Array->InsertNextValue(center_2[2]); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array); std::vector surfaces; surfaces.push_back(surf_1); surfaces.push_back(surf_2); const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry(); const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry(); std::vector 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); 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 += 0.5; bool success = m_Controller->RemoveContour(contourInfo3); CPPUNIT_ASSERT_MESSAGE("Remove failed - contour was unintentionally removed!", (m_Controller->GetNumberOfContours() == 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); // // Let's see if the other contour No. 1 is still there contourInfo3.ContourPoint -= 0.5; const mitk::Surface *remainingContour = m_Controller->GetContour(contourInfo3); CPPUNIT_ASSERT_MESSAGE( "Remove failed - contour was accidentally removed!", (m_Controller->GetNumberOfContours() == 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 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(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(m_Controller->GetCurrentSegmentation().GetPointer()); AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone()); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == 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(m_Controller->GetCurrentSegmentation().GetPointer()); // 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(m_Controller->GetCurrentSegmentation().GetPointer()); AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone()); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == 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(m_Controller->GetCurrentSegmentation().GetPointer()); AssertImagesEqual4D(currentSegmentation, segmentation_1->Clone()); CPPUNIT_ASSERT_MESSAGE("Segmentation images are not equal", m_Controller->GetCurrentSegmentation().GetPointer() == 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("Number of interpolation session not 2", m_Controller->GetNumberOfInterpolationSessions() == 2); } void TestReplaceInterpolationSession4D() { - m_Controller->RemoveAllInterpolationSessions(); // 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 p_source = vtkSmartPointer::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 int1Array = vtkSmartPointer::New(); int1Array->InsertNextValue(1); int1Array->InsertNextValue(0); int1Array->InsertNextValue(0); surf_1->GetVtkPolyData()->GetFieldData()->AddArray(int1Array); vtkSmartPointer double1Array = vtkSmartPointer::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 p_source_2 = vtkSmartPointer::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 int2Array = vtkSmartPointer::New(); int2Array->InsertNextValue(1); int2Array->InsertNextValue(0); int2Array->InsertNextValue(0); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(int2Array); vtkSmartPointer double2Array = vtkSmartPointer::New(); double2Array->InsertNextValue(center_2[0]); double2Array->InsertNextValue(center_2[1]); double2Array->InsertNextValue(center_2[2]); surf_2->GetVtkPolyData()->GetFieldData()->AddArray(double2Array); std::vector surfaces; surfaces.push_back(surf_1); surfaces.push_back(surf_2); const mitk::PlaneGeometry * planeGeometry1 = GetPlaneGeometry(); const mitk::PlaneGeometry * planeGeometry2 = GetPlaneGeometry(); std::vector 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 p_source_3 = vtkSmartPointer::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 int3Array = vtkSmartPointer::New(); int3Array->InsertNextValue(1); int3Array->InsertNextValue(0); int3Array->InsertNextValue(2); surf_3->GetVtkPolyData()->GetFieldData()->AddArray(int3Array); vtkSmartPointer double3Array = vtkSmartPointer::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 p_source_4 = vtkSmartPointer::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 int4Array = vtkSmartPointer::New(); int4Array->InsertNextValue(1); int4Array->InsertNextValue(0); int4Array->InsertNextValue(2); surf_4->GetVtkPolyData()->GetFieldData()->AddArray(int4Array); vtkSmartPointer double4Array = vtkSmartPointer::New(); double4Array->InsertNextValue(center_4[0]); double4Array->InsertNextValue(center_4[1]); double4Array->InsertNextValue(center_4[2]); surf_4->GetVtkPolyData()->GetFieldData()->AddArray(double4Array); std::vector surfaces2; surfaces2.push_back(surf_3); surfaces2.push_back(surf_4); const mitk::PlaneGeometry * planeGeometry3 = GetPlaneGeometry(); const mitk::PlaneGeometry * planeGeometry4 = GetPlaneGeometry(); std::vector 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()); CPPUNIT_ASSERT_MESSAGE("Current segmentation is null after another one was removed", m_Controller->GetCurrentSegmentation().IsNotNull()); 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()); } 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 bbcebc407f..626a63c64b 100644 --- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp +++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp @@ -1,1398 +1,1399 @@ /*============================================================================ 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 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) { 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::max(); contourInfo.Plane = const_cast(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_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::New(); vtkSmartPointer points = vtkSmartPointer::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(); } 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& newContours, std::vector& contourPlanes, bool reinitializationAction) { 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(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 (dataNodeObjects->Size() != 0) { for (auto it = dataNodeObjects->Begin(); it != dataNodeObjects->End(); ++it) { segmentationNode = it->Value(); } } else { MITK_ERROR << "Unable to find the labelSetImage with the desired UID."; } return segmentationNode; } void mitk::SurfaceInterpolationController::AddPlaneGeometryNodeToDataStorage(const ContourPositionInformation& contourInfo) { 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); if (planeGeometry) { 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; // 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(it->Value()->GetProperty("layerID"))->GetValue(); auto labelID = dynamic_cast(it->Value()->GetProperty("labelID"))->GetValue(); auto posID = dynamic_cast(it->Value()->GetProperty("position"))->GetValue(); bool sameLayer = (layerID == contourInfo.LayerValue); bool sameLabel = (labelID == contourInfo.LabelValue); bool samePos = (posID == contourInfo.Pos); if (samePos & sameLabel & sameLayer) { contourFound = true; it->Value()->SetData(planeGeometryData); 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) { std::string contourName = "contourPlane " + std::to_string(m_ContourIndex); auto 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); } } } void mitk::SurfaceInterpolationController::AddToInterpolationPipeline(ContourPositionInformation& contourInfo, bool reinitializationAction) { if (!m_SelectedSegmentation) 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(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::max()) { MITK_ERROR << "In mitk::SurfaceInterpolationController::AddToInterpolationPipeline. Problem in finding layerID"; } currentLayerID = contourInfo.LayerValue; } else { try { currentLayerID = dynamic_cast(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 ¤tImageContours = m_ListOfContours.at(m_SelectedSegmentation); ContourPositionInformationVec2D ¤tTimeStepContoursList = currentImageContours.at(currentTimeStep); ContourPositionInformationList ¤tContourList = currentTimeStepContoursList.at(currentLayerID); int replacementIndex = -1; int pos = -1; mitk::Surface* newContour = contourInfo.Contour; for (size_t i = 0; i < currentContourList.size(); i++) { 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; } } } // 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); } return; } // Case that there is no contour in the current slice with the current label if (pos == -1) pos = m_ContourPosIndex++; m_ContourIndex++; contourInfo.Pos = pos; m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).push_back(contourInfo); if (contourInfo.Plane == nullptr) { MITK_ERROR << "contourInfo plane is null."; } if (!reinitializationAction) { this->AddPlaneGeometryNodeToDataStorage(contourInfo); } if (newContour->GetVtkPolyData()->GetNumberOfPoints() == 0) { this->RemoveContour(contourInfo); if (m_ContourIndex > 0) m_ContourIndex--; if (m_ContourIndex > 0) m_ContourIndex--; } } 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(m_SelectedSegmentation)->GetActiveLayer(); } catch (const std::exception& e) { MITK_ERROR << e.what() << '\n'; } auto it = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).begin(); while (it != m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).end()) { const ContourPositionInformation ¤tContour = (*it); if (ContoursCoplanar(currentContour, contourInfo)) { m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(currentLayerID).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(m_SelectedSegmentation)->GetActiveLayer(); const auto &contourList = m_ListOfContours.at(m_SelectedSegmentation).at(currentTimeStep).at(activeLayerID); for (auto ¤tContour : 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; } 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(m_SelectedSegmentation)->GetActiveLayer(); } catch (const std::exception& e) { MITK_ERROR << e.what() << '\n'; } ContourPositionInformationVec3D ¤tImageContours = m_ListOfContours.at(m_SelectedSegmentation); if (currentImageContours.size() <= currentTimeStep) { MITK_INFO << "Contours for current time step don't exist."; return; } ContourPositionInformationVec2D ¤tTimeStepContoursList = currentImageContours.at(currentTimeStep); if (currentTimeStepContoursList.size() <= currentLayerID) { MITK_INFO << "Contours for current layer don't exist."; return; } ContourPositionInformationList ¤tContours = currentTimeStepContoursList.at(currentLayerID); for (size_t i = 0; i < currentContours.size(); ++i) { 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); } } } 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_WARN << "No interpolation is possible. Too few reduced contours."; + 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(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() { return m_SelectedSegmentation; } mitk::Image *mitk::SurfaceInterpolationController::GetImage() { 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(); } template void mitk::SurfaceInterpolationController::GetImageBase(itk::Image *input, itk::ImageBase<3>::Pointer &result) { result->Graft(input); } void mitk::SurfaceInterpolationController::SetCurrentSegmentationInterpolationList(mitk::Image::Pointer segmentation) { this->SetCurrentInterpolationSession(segmentation); } void mitk::SurfaceInterpolationController::SetCurrentInterpolationSession(mitk::Image::Pointer currentSegmentationImage) { if (currentSegmentationImage.GetPointer() == m_SelectedSegmentation) { return; } if (currentSegmentationImage.IsNull()) { m_SelectedSegmentation = nullptr; return; } m_SelectedSegmentation = currentSegmentationImage.GetPointer(); try { auto labelSetImage = dynamic_cast(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()) { 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; auto command = itk::MemberCommand::New(); command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted); + m_SegmentationObserverTags[m_SelectedSegmentation] = labelSetImage->AddObserver(itk::DeleteEvent(), command); m_NumberOfLayersInCurrentSegmentation = labelSetImage->GetNumberOfLayers(); } // auto labelSetImage = dynamic_cast(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; } 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::Pointer command = itk::MemberCommand::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) { this->RemoveInterpolationSession(segmentation); } void mitk::SurfaceInterpolationController::RemoveInterpolationSession(mitk::Image::Pointer segmentationImage) { if (segmentationImage) { if (m_SelectedSegmentation == segmentationImage) { m_NormalsFilter->SetSegmentationBinaryImage(nullptr); m_SelectedSegmentation = nullptr; } m_ListOfInterpolationSessions.erase(segmentationImage); m_ListOfContours.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(); m_SelectedSegmentation = nullptr; m_ListOfInterpolationSessions.clear(); m_ListOfContours.clear(); } template std::vector GetPixelValuesPresentInImage(mitk::LabelSetImage* labelSetImage) { mitk::ImagePixelReadAccessor readAccessor(labelSetImage); std::vector pixelsPresent; std::size_t numberOfPixels = 1; for (int dim = 0; dim < static_cast(VImageDimension); ++dim) numberOfPixels *= static_cast(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 != 0) ) { pixelsPresent.push_back(pixelVal); } } return pixelsPresent; } void mitk::SurfaceInterpolationController::RemoveContours(mitk::Label::PixelType label, unsigned int timeStep, unsigned int layerID) { auto isContourEqualToLabelValue = [label] (ContourPositionInformation& contour) -> bool { return (contour.LabelValue == label); }; ContourPositionInformationVec3D ¤tImageContours = m_ListOfContours.at(m_SelectedSegmentation); ContourPositionInformationList ¤tContourList = 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; } void mitk::SurfaceInterpolationController::OnSegmentationDeleted(const itk::Object *caller, const itk::EventObject & /*event*/) { auto *tempImage = dynamic_cast(const_cast(caller)); if (tempImage) { if (m_SelectedSegmentation == tempImage) { m_NormalsFilter->SetSegmentationBinaryImage(nullptr); m_SelectedSegmentation = nullptr; } m_SegmentationObserverTags.erase(tempImage); m_ListOfContours.erase(tempImage); m_ListOfInterpolationSessions.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->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(m_SelectedSegmentation); auto previousLayerID = workingImage->GetActiveLayer(); workingImage->SetActiveLayer(layerID); auto activeLabelSet = workingImage->GetLabelSet(layerID); activeLabelSet->RemoveLabelEvent += mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnRemoveLabel); activeLabelSet->ActiveLabelEvent += mitk::MessageDelegate1( this, &mitk::SurfaceInterpolationController::OnActiveLabel); workingImage->AfterChangeLayerEvent += mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnLayerChanged); m_NumberOfConnectionsAdded += 1; workingImage->SetActiveLayer(previousLayerID); } catch(const std::exception& e) { MITK_ERROR << e.what() << '\n'; } } } void mitk::SurfaceInterpolationController::AddLabelSetConnection() { if (m_SelectedSegmentation != nullptr) { try { auto workingImage = dynamic_cast(m_SelectedSegmentation); auto activeLabelSet = workingImage->GetActiveLabelSet(); activeLabelSet->RemoveLabelEvent += mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnRemoveLabel); workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1( this, &mitk::SurfaceInterpolationController::OnActiveLabel); workingImage->AfterChangeLayerEvent += mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnLayerChanged); m_NumberOfConnectionsAdded += 1; } catch(const std::exception& e) { MITK_ERROR << e.what() << '\n'; } } } void mitk::SurfaceInterpolationController::RemoveLabelSetConnection(mitk::LabelSetImage* labelSetImage, unsigned int layerID) { labelSetImage->SetActiveLayer(layerID); labelSetImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnRemoveLabel); // labelSetImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1( // this, &mitk::SurfaceInterpolationController::OnActiveLabel); labelSetImage->AfterChangeLayerEvent -= mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnLayerChanged); m_NumberOfConnectionsAdded -= 1; } void mitk::SurfaceInterpolationController::RemoveLabelSetConnection() { if (m_SelectedSegmentation != nullptr) { try { auto workingImage = dynamic_cast(m_SelectedSegmentation); workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnRemoveLabel); workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1( this, &mitk::SurfaceInterpolationController::OnActiveLabel); workingImage->AfterChangeLayerEvent -= mitk::MessageDelegate( this, &mitk::SurfaceInterpolationController::OnLayerChanged); } catch (const std::exception& e) { std::cerr << e.what() << '\n'; } } } void mitk::SurfaceInterpolationController::OnRemoveLabel() { if (m_SelectedSegmentation != nullptr) { auto numTimeSteps = m_SelectedSegmentation->GetTimeGeometry()->CountTimeSteps(); try { auto labelSetImage = dynamic_cast(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; } void mitk::SurfaceInterpolationController::SetNumberOfLayersInCurrentSegmentation(unsigned int numLayers) { m_NumberOfLayersInCurrentSegmentation = numLayers; } 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) { 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. // 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) { auto& contoursInCurrentLayer = contoursAtTimeStep.at(c); for (auto& contour : contoursInCurrentLayer) { contour.LayerValue = contour.LayerValue - 1; } } } 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(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) { MITK_ERROR << "Invalid segmentation from mitk::SurfaceInterpolationController::GetContours"; } if (timeStep >= m_ListOfContours.at(m_SelectedSegmentation).size()) { MITK_ERROR << "Invalid timeStep from mitk::SurfaceInterpolationController::GetContours"; } if (layerID >= m_ListOfContours.at(m_SelectedSegmentation).at(timeStep).size()) { MITK_ERROR << "Invalid timeStep from mitk::SurfaceInterpolationController::GetContours"; } return m_ListOfContours.at(m_SelectedSegmentation).at(timeStep).at(layerID); } void mitk::SurfaceInterpolationController::CompleteReinitialization(const std::vector& contourList, std::vector& contourPlanes) { this->ClearInterpolationSession(); auto labelSetImage = dynamic_cast(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(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"; } } } } 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 mitk::Point3D mitk::ContourExt::ComputeInteriorPointOfContour( const mitk::SurfaceInterpolationController::ContourPositionInformation& contour, mitk::LabelSetImage * labelSetImage, mitk::TimePointType currentTimePoint) { mitk::ImagePixelReadAccessor readAccessor(labelSetImage); if (!labelSetImage->GetTimeGeometry()->IsValidTimePoint(currentTimePoint)) { MITK_ERROR << "Invalid time point requested for interpolation pipeline."; mitk::Point3D pt; return pt; } std::vector 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 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 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 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 geomIndex; for (size_t i=0;i mitk::eps) { planeOrientation = 2; } else if (fabs(dotY) > mitk::eps) { planeOrientation = 1; } else if(fabs(dotX) > mitk::eps) { planeOrientation = 0; } return planeOrientation; }