diff --git a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp index 5dd3020546..e83f3be3a6 100644 --- a/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp +++ b/Plugins/org.mitk.gui.qt.imagecropper/src/internal/QmitkConvertGeometryDataToROIAction.cpp @@ -1,154 +1,175 @@ /*============================================================================ 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 "QmitkConvertGeometryDataToROIAction.h" #include #include #include #include #include namespace { - void handleInvalidNodeSelection() + void HandleInvalidNodeSelection() { - auto message = QStringLiteral("All selected bounding boxes must be child nodes of a single common reference image with a non-rotated geometry!"); + auto message = QStringLiteral( + "All selected bounding boxes must be child nodes of a single common reference image " + "with a non-rotated geometry and positive pixel spacing!"); + MITK_ERROR << message; QMessageBox::warning(nullptr, QStringLiteral("Convert to ROI"), message); } - bool isRotated(const mitk::BaseGeometry* geometry) + bool IsRotated(const mitk::BaseGeometry* geometry) { - const auto* matrix = geometry->GetVtkMatrix(); + auto matrix = geometry->GetVtkMatrix(); for (int j = 0; j < 3; ++j) { for (int i = 0; i < 3; ++i) { - if (i != j && matrix->GetElement(i, j) > mitk::eps) + if (i != j && std::abs(matrix->GetElement(i, j)) > mitk::eps) return true; } } return false; } - std::pair, mitk::DataNode*> getValidInput(const QList& selectedNodes, const mitk::DataStorage* dataStorage) + bool HasNegativeSpacing(const mitk::BaseGeometry* geometry) + { + auto matrix = geometry->GetVtkMatrix(); + + for (int i = 0; i < 3; ++i) + { + if (matrix->GetElement(i, i) < 0.0) + return true; + } + + return false; + } + + std::pair, mitk::DataNode*> GetValidInput(const QList& selectedNodes, const mitk::DataStorage* dataStorage) { std::pair, mitk::DataNode*> result; result.first.reserve(selectedNodes.size()); std::copy_if(selectedNodes.cbegin(), selectedNodes.cend(), std::back_inserter(result.first), [](const mitk::DataNode* node) { return node != nullptr && dynamic_cast(node->GetData()) != nullptr; }); for (auto node : result.first) { auto sourceNodes = dataStorage->GetSources(node, mitk::TNodePredicateDataType::New()); if (sourceNodes->size() != 1) mitkThrow(); if (result.second == nullptr) { - if (isRotated(sourceNodes->front()->GetData()->GetGeometry())) + auto geometry = sourceNodes->front()->GetData()->GetGeometry(); + + if (IsRotated(geometry)) + mitkThrow(); + + if (HasNegativeSpacing(geometry)) mitkThrow(); result.second = sourceNodes->front(); } else if (result.second != sourceNodes->front()) { mitkThrow(); } } return result; } } QmitkConvertGeometryDataToROIAction::QmitkConvertGeometryDataToROIAction() { } QmitkConvertGeometryDataToROIAction::~QmitkConvertGeometryDataToROIAction() { } void QmitkConvertGeometryDataToROIAction::Run(const QList& selectedNodes) { try { - auto [nodes, referenceNode] = getValidInput(selectedNodes, m_DataStorage); + auto [nodes, referenceNode] = GetValidInput(selectedNodes, m_DataStorage); auto roi = mitk::ROI::New(); roi->SetClonedGeometry(referenceNode->GetData()->GetGeometry()); unsigned int id = 0; for (auto node : nodes) { mitk::ROI::Element element(id++); element.SetProperty("name", mitk::StringProperty::New(node->GetName())); if (auto* color = node->GetProperty("Bounding Shape.Deselected Color"); color != nullptr) element.SetProperty("color", color); const auto* geometry = node->GetData()->GetGeometry(); const auto origin = geometry->GetOrigin() - roi->GetGeometry()->GetOrigin(); const auto spacing = geometry->GetSpacing(); const auto bounds = geometry->GetBounds(); mitk::Point3D min; mitk::Point3D max; for (size_t i = 0; i < 3; ++i) { min[i] = origin[i] / spacing[i] + bounds[2 * i]; max[i] = origin[i] / spacing[i] + bounds[2 * i + 1] - 1; } element.SetMin(min); element.SetMax(max); roi->AddElement(element); } auto roiNode = mitk::DataNode::New(); roiNode->SetName(referenceNode->GetName() + " ROI" + (roi->GetNumberOfElements() > 1 ? "s" : "")); roiNode->SetData(roi); m_DataStorage->Add(roiNode, referenceNode); } catch (const mitk::Exception&) { - handleInvalidNodeSelection(); + HandleInvalidNodeSelection(); } } void QmitkConvertGeometryDataToROIAction::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkConvertGeometryDataToROIAction::SetFunctionality(berry::QtViewPart*) { } void QmitkConvertGeometryDataToROIAction::SetSmoothed(bool) { } void QmitkConvertGeometryDataToROIAction::SetDecimated(bool) { }