diff --git a/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp b/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp index f7ef90d476..be37ab6a6d 100644 --- a/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp +++ b/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp @@ -1,174 +1,173 @@ /*============================================================================ 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 mitkCLPolyToNrrd_cpp #define mitkCLPolyToNrrd_cpp #include "time.h" #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include "vtkRenderLargeImage.h" #include "vtkPNGWriter.h" #include #include typedef itk::Image< double, 3 > FloatImageType; typedef itk::Image< unsigned char, 3 > MaskImageType; template static void FindMostSampleSlice(itk::Image* mask, int & selectedSlice) { int idx = VImageDimension - 1; int size = mask->GetLargestPossibleRegion().GetSize()[idx]; std::vector numberOfSamples; numberOfSamples.resize(size,0); itk::ImageRegionIteratorWithIndex > mask1Iter(mask, mask->GetLargestPossibleRegion()); while (!mask1Iter.IsAtEnd()) { if (mask1Iter.Value() > 0) { numberOfSamples[mask1Iter.GetIndex()[idx]]+=1; } ++mask1Iter; } selectedSlice = 0; for (std::size_t i = 0; i < numberOfSamples.size(); ++i) { if (numberOfSamples[selectedSlice] < numberOfSamples[i]) selectedSlice = i; } } static void SaveSliceOrImageAsPNG(mitk::Image::Pointer image, mitk::Image::Pointer mask, std::string path, int index) { // Create a Standalone Datastorage for the single purpose of saving screenshots.. mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); QmitkRenderWindow renderWindow; renderWindow.GetRenderer()->SetDataStorage(ds); auto nodeI = mitk::DataNode::New(); nodeI->SetData(image); auto nodeM = mitk::DataNode::New(); nodeM->SetData(mask); ds->Add(nodeI); ds->Add(nodeM); auto geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); - mitk::RenderingManager::GetInstance()->InitializeViews( - mask->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + mitk::RenderingManager::GetInstance()->InitializeViews(mask->GetTimeGeometry()); mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); sliceNaviController->SetViewDirection(mitk::SliceNavigationController::Axial); unsigned int numberOfSteps = 1; if (sliceNaviController) { numberOfSteps = sliceNaviController->GetSlice()->GetSteps(); sliceNaviController->GetSlice()->SetPos(numberOfSteps-index); } renderWindow.show(); renderWindow.resize(256, 256); //if (sliceNaviController) //{ // sliceNaviController->GetSlice()->SetPos(index); //} renderWindow.GetRenderer()->PrepareRender(); vtkRenderWindow* renderWindow2 = renderWindow.GetVtkRenderWindow(); mitk::BaseRenderer* baserenderer = mitk::BaseRenderer::GetInstance(renderWindow2); auto vtkRender = baserenderer->GetVtkRenderer(); vtkRender->GetRenderWindow()->WaitForCompletion(); vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New(); magnifier->SetInput(vtkRender); magnifier->SetMagnification(3.0); std::stringstream ss; ss << path <<".png"; std::string tmpImageName; ss >> tmpImageName; auto fileWriter = vtkPNGWriter::New(); fileWriter->SetInputConnection(magnifier->GetOutputPort()); fileWriter->SetFileName(tmpImageName.c_str()); fileWriter->Write(); fileWriter->Delete(); } int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.addArgument("image", "i", mitkCommandLineParser::Image, "Input Image", "", us::Any(),false, false, false, mitkCommandLineParser::Input); parser.addArgument("mask", "m", mitkCommandLineParser::Image, "Input Image", "", us::Any(),false, false, false, mitkCommandLineParser::Input); parser.addArgument("output", "o", mitkCommandLineParser::Image, "Output Image", "", us::Any(),false, false, false, mitkCommandLineParser::Input); // Miniapp Infos parser.setCategory("Classification Tools"); parser.setTitle("Image with Overlay Plotter"); parser.setDescription("Plots "); parser.setContributor("German Cancer Research Center (DKFZ)"); std::map parsedArgs = parser.parseArguments(argc, argv); std::string imagePath = us::any_cast(parsedArgs["image"]); std::string maskPath = us::any_cast(parsedArgs["mask"]); std::string outputPath = us::any_cast(parsedArgs["output"]); if (parsedArgs.size()==0) { return EXIT_FAILURE; } if ( parsedArgs.count("help") || parsedArgs.count("h")) { return EXIT_SUCCESS; } std::string version = "Version: 1.0"; MITK_INFO << version; mitk::Image::Pointer image = mitk::IOUtil::Load(imagePath); mitk::Image::Pointer mask = mitk::IOUtil::Load(maskPath); // Create a QTApplication and a Datastorage // This is necessary in order to save screenshots of // each image / slice. QApplication qtapplication(argc, argv); QmitkRegisterClasses(); int currentSlice = 0; AccessByItk_1(mask, FindMostSampleSlice, currentSlice); SaveSliceOrImageAsPNG(image, mask, outputPath, currentSlice); return 0; } #endif diff --git a/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp b/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp index 8a18b5e708..2ab4f4d8be 100644 --- a/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp +++ b/Modules/QtWidgets/src/QmitkDataStorageTreeModel.cpp @@ -1,881 +1,880 @@ /*============================================================================ 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 "QmitkDataStorageTreeModel.h" #include "QmitkDataStorageTreeModelInternalItem.h" #include "QmitkNodeDescriptorManager.h" #include #include #include #include #include #include #include #include #include QmitkDataStorageTreeModel::QmitkDataStorageTreeModel(mitk::DataStorage *_DataStorage, bool _PlaceNewNodesOnTop, QObject *parent) : QAbstractItemModel(parent), m_DataStorage(nullptr), m_PlaceNewNodesOnTop(_PlaceNewNodesOnTop), m_Root(nullptr), m_BlockDataStorageEvents(false), m_AllowHierarchyChange(false) { this->SetDataStorage(_DataStorage); } QmitkDataStorageTreeModel::~QmitkDataStorageTreeModel() { // set data storage to 0 = remove all listeners this->SetDataStorage(nullptr); m_Root->Delete(); m_Root = nullptr; } mitk::DataNode::Pointer QmitkDataStorageTreeModel::GetNode(const QModelIndex &index) const { return this->TreeItemFromIndex(index)->GetDataNode(); } const mitk::DataStorage::Pointer QmitkDataStorageTreeModel::GetDataStorage() const { return m_DataStorage.Lock(); } QModelIndex QmitkDataStorageTreeModel::index(int row, int column, const QModelIndex &parent) const { TreeItem *parentItem; if (!parent.isValid()) parentItem = m_Root; else parentItem = static_cast(parent.internalPointer()); TreeItem *childItem = parentItem->GetChild(row); if (childItem) return createIndex(row, column, childItem); else return QModelIndex(); } int QmitkDataStorageTreeModel::rowCount(const QModelIndex &parent) const { TreeItem *parentTreeItem = this->TreeItemFromIndex(parent); return parentTreeItem->GetChildCount(); } Qt::ItemFlags QmitkDataStorageTreeModel::flags(const QModelIndex &index) const { if (index.isValid()) { return Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } else { return Qt::ItemIsDropEnabled; } } int QmitkDataStorageTreeModel::columnCount(const QModelIndex & /* parent = QModelIndex() */) const { return 1; } QModelIndex QmitkDataStorageTreeModel::parent(const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); TreeItem *childItem = this->TreeItemFromIndex(index); TreeItem *parentItem = childItem->GetParent(); if (parentItem == m_Root) return QModelIndex(); return this->createIndex(parentItem->GetIndex(), 0, parentItem); } QmitkDataStorageTreeModel::TreeItem *QmitkDataStorageTreeModel::TreeItemFromIndex(const QModelIndex &index) const { if (index.isValid()) return static_cast(index.internalPointer()); else return m_Root; } Qt::DropActions QmitkDataStorageTreeModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } Qt::DropActions QmitkDataStorageTreeModel::supportedDragActions() const { return Qt::CopyAction | Qt::MoveAction; } bool QmitkDataStorageTreeModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent) { // Early exit, returning true, but not actually doing anything (ignoring data). if (action == Qt::IgnoreAction) { return true; } // Note, we are returning true if we handled it, and false otherwise bool returnValue = false; if (data->hasFormat("application/x-qabstractitemmodeldatalist")) { returnValue = true; // First we extract a Qlist of TreeItem* pointers. QList listOfItemsToDrop = ToTreeItemPtrList(data); if (listOfItemsToDrop.empty()) { return false; } // Retrieve the TreeItem* where we are dropping stuff, and its parent. TreeItem *dropItem = this->TreeItemFromIndex(parent); TreeItem *parentItem = dropItem->GetParent(); // If item was dropped onto empty space, we select the root node if (dropItem == m_Root) { parentItem = m_Root; } // Dragging and Dropping is only allowed within the same parent, so use the first item in list to validate. // (otherwise, you could have a derived image such as a segmentation, and assign it to another image). // NOTE: We are assuming the input list is valid... i.e. when it was dragged, all the items had the same parent. // Determine whether or not the drag and drop operation is a valid one. // Examples of invalid operations include: // - dragging nodes with different parents // - dragging nodes from one parent to another parent, if m_AllowHierarchyChange is false // - dragging a node on one of its child nodes (only relevant if m_AllowHierarchyChange is true) bool isValidDragAndDropOperation(true); // different parents { TreeItem *firstParent = listOfItemsToDrop[0]->GetParent(); QList::iterator diIter; for (diIter = listOfItemsToDrop.begin() + 1; diIter != listOfItemsToDrop.end(); diIter++) { if (firstParent != (*diIter)->GetParent()) { isValidDragAndDropOperation = false; break; } } } // dragging from one parent to another if ((!m_AllowHierarchyChange) && isValidDragAndDropOperation) { if (row == -1) // drag onto a node { isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == parentItem; } else // drag between nodes { isValidDragAndDropOperation = listOfItemsToDrop[0]->GetParent() == dropItem; } } // dragging on a child node of one the dragged nodes { QList::iterator diIter; for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++) { TreeItem *tempItem = dropItem; while (tempItem != m_Root) { tempItem = tempItem->GetParent(); if (tempItem == *diIter) { isValidDragAndDropOperation = false; } } } } if (!isValidDragAndDropOperation) return isValidDragAndDropOperation; if (listOfItemsToDrop[0] != dropItem && isValidDragAndDropOperation) { // Retrieve the index of where we are dropping stuff. QModelIndex parentModelIndex = this->IndexFromTreeItem(parentItem); int dragIndex = 0; // Iterate through the list of TreeItem (which may be at non-consecutive indexes). QList::iterator diIter; for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++) { TreeItem *itemToDrop = *diIter; // if the item is dragged down we have to compensate its final position for the // fact it is deleted lateron, this only applies if it is dragged within the same level if ((itemToDrop->GetIndex() < row) && (itemToDrop->GetParent() == dropItem)) { dragIndex = 1; } // Here we assume that as you remove items, one at a time, that GetIndex() will be valid. this->beginRemoveRows( this->IndexFromTreeItem(itemToDrop->GetParent()), itemToDrop->GetIndex(), itemToDrop->GetIndex()); itemToDrop->GetParent()->RemoveChild(itemToDrop); this->endRemoveRows(); } // row = -1 dropped on an item, row != -1 dropped in between two items // Select the target index position, or put it at the end of the list. int dropIndex = 0; if (row != -1) { if (dragIndex == 0) dropIndex = std::min(row, parentItem->GetChildCount() - 1); else dropIndex = std::min(row - 1, parentItem->GetChildCount() - 1); } else { dropIndex = dropItem->GetIndex(); } QModelIndex dropItemModelIndex = this->IndexFromTreeItem(dropItem); if ((row == -1 && dropItemModelIndex.row() == -1) || dropItemModelIndex.row() > parentItem->GetChildCount()) dropIndex = parentItem->GetChildCount() - 1; // Now insert items again at the drop item position if (m_AllowHierarchyChange) { this->beginInsertRows(dropItemModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1); } else { this->beginInsertRows(parentModelIndex, dropIndex, dropIndex + listOfItemsToDrop.size() - 1); } for (diIter = listOfItemsToDrop.begin(); diIter != listOfItemsToDrop.end(); diIter++) { // dropped on node, behaviour depends on preference setting if (m_AllowHierarchyChange) { auto dataStorage = m_DataStorage.Lock(); m_BlockDataStorageEvents = true; mitk::DataNode::Pointer droppedNode = (*diIter)->GetDataNode(); mitk::DataNode *dropOntoNode = dropItem->GetDataNode(); dataStorage->Remove(droppedNode); dataStorage->Add(droppedNode, dropOntoNode); m_BlockDataStorageEvents = false; dropItem->InsertChild((*diIter), dropIndex); } else { if (row == -1) // drag onto a node { parentItem->InsertChild((*diIter), dropIndex); } else // drag between nodes { dropItem->InsertChild((*diIter), dropIndex); } } dropIndex++; } this->endInsertRows(); // Change Layers to match. this->AdjustLayerProperty(); } } else if (data->hasFormat("application/x-mitk-datanodes")) { returnValue = true; int numberOfNodesDropped = 0; QList dataNodeList = QmitkMimeTypes::ToDataNodePtrList(data); mitk::DataNode *node = nullptr; foreach (node, dataNodeList) { auto datastorage = m_DataStorage.Lock(); if (node && datastorage.IsNotNull() && !datastorage->Exists(node)) { m_DataStorage.Lock()->Add(node); mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { - mitk::RenderingManager::GetInstance()->InitializeViews( - basedata->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + mitk::RenderingManager::GetInstance()->InitializeViews(basedata->GetTimeGeometry()); numberOfNodesDropped++; } } } // Only do a rendering update, if we actually dropped anything. if (numberOfNodesDropped > 0) { mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } return returnValue; } QStringList QmitkDataStorageTreeModel::mimeTypes() const { QStringList types = QAbstractItemModel::mimeTypes(); types << "application/x-qabstractitemmodeldatalist"; types << "application/x-mitk-datanodes"; return types; } QMimeData *QmitkDataStorageTreeModel::mimeData(const QModelIndexList &indexes) const { return mimeDataFromModelIndexList(indexes); } QMimeData *QmitkDataStorageTreeModel::mimeDataFromModelIndexList(const QModelIndexList &indexes) { QMimeData *ret = new QMimeData; QString treeItemAddresses(""); QString dataNodeAddresses(""); QByteArray baTreeItemPtrs; QByteArray baDataNodePtrs; QDataStream dsTreeItemPtrs(&baTreeItemPtrs, QIODevice::WriteOnly); QDataStream dsDataNodePtrs(&baDataNodePtrs, QIODevice::WriteOnly); for (int i = 0; i < indexes.size(); i++) { TreeItem *treeItem = static_cast(indexes.at(i).internalPointer()); dsTreeItemPtrs << reinterpret_cast(treeItem); dsDataNodePtrs << reinterpret_cast(treeItem->GetDataNode().GetPointer()); // --------------- deprecated ----------------- unsigned long long treeItemAddress = reinterpret_cast(treeItem); unsigned long long dataNodeAddress = reinterpret_cast(treeItem->GetDataNode().GetPointer()); QTextStream(&treeItemAddresses) << treeItemAddress; QTextStream(&dataNodeAddresses) << dataNodeAddress; if (i != indexes.size() - 1) { QTextStream(&treeItemAddresses) << ","; QTextStream(&dataNodeAddresses) << ","; } // -------------- end deprecated ------------- } // ------------------ deprecated ----------------- ret->setData("application/x-qabstractitemmodeldatalist", QByteArray(treeItemAddresses.toLatin1())); ret->setData("application/x-mitk-datanodes", QByteArray(dataNodeAddresses.toLatin1())); // --------------- end deprecated ----------------- ret->setData(QmitkMimeTypes::DataStorageTreeItemPtrs, baTreeItemPtrs); ret->setData(QmitkMimeTypes::DataNodePtrs, baDataNodePtrs); return ret; } QVariant QmitkDataStorageTreeModel::data(const QModelIndex &index, int role) const { mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode(); // get name of treeItem (may also be edited) QString nodeName = QString::fromStdString(dataNode->GetName()); if (nodeName.isEmpty()) { nodeName = "unnamed"; } if (role == Qt::DisplayRole) return nodeName; else if (role == Qt::ToolTipRole) return nodeName; else if (role == Qt::DecorationRole) { QmitkNodeDescriptor *nodeDescriptor = QmitkNodeDescriptorManager::GetInstance()->GetDescriptor(dataNode); return nodeDescriptor->GetIcon(dataNode); } else if (role == Qt::CheckStateRole) { return dataNode->IsVisible(nullptr); } else if (role == QmitkDataNodeRole) { return QVariant::fromValue(mitk::DataNode::Pointer(dataNode)); } else if (role == QmitkDataNodeRawPointerRole) { return QVariant::fromValue(dataNode); } return QVariant(); } bool QmitkDataStorageTreeModel::DicomPropertiesExists(const mitk::DataNode &node) const { bool propertiesExists = false; mitk::BaseProperty *seriesDescription_deprecated = (node.GetProperty("dicom.series.SeriesDescription")); mitk::BaseProperty *studyDescription_deprecated = (node.GetProperty("dicom.study.StudyDescription")); mitk::BaseProperty *patientsName_deprecated = (node.GetProperty("dicom.patient.PatientsName")); mitk::BaseProperty *seriesDescription = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x103e).c_str())); mitk::BaseProperty *studyDescription = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0008, 0x1030).c_str())); mitk::BaseProperty *patientsName = (node.GetProperty(mitk::GeneratePropertyNameForDICOMTag(0x0010, 0x0010).c_str())); if (patientsName != nullptr && studyDescription != nullptr && seriesDescription != nullptr) { if ((!patientsName->GetValueAsString().empty()) && (!studyDescription->GetValueAsString().empty()) && (!seriesDescription->GetValueAsString().empty())) { propertiesExists = true; } } /** Code coveres the deprecated property naming for backwards compatibility */ if (patientsName_deprecated != nullptr && studyDescription_deprecated != nullptr && seriesDescription_deprecated != nullptr) { if ((!patientsName_deprecated->GetValueAsString().empty()) && (!studyDescription_deprecated->GetValueAsString().empty()) && (!seriesDescription_deprecated->GetValueAsString().empty())) { propertiesExists = true; } } return propertiesExists; } QVariant QmitkDataStorageTreeModel::headerData(int /*section*/, Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole && m_Root) return QString::fromStdString(m_Root->GetDataNode()->GetName()); return QVariant(); } void QmitkDataStorageTreeModel::SetDataStorage(mitk::DataStorage *_DataStorage) { if (m_DataStorage != _DataStorage) // dont take the same again { auto dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull()) { // remove Listener for the data storage itself dataStorage->RemoveObserver(m_DataStorageDeletedTag); // remove listeners for the nodes dataStorage->AddNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkDataStorageTreeModel::AddNode)); dataStorage->ChangedNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetNodeModified)); dataStorage->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::RemoveNode)); } this->beginResetModel(); // take over the new data storage m_DataStorage = _DataStorage; // delete the old root (if necessary, create new) if (m_Root) m_Root->Delete(); mitk::DataNode::Pointer rootDataNode = mitk::DataNode::New(); rootDataNode->SetName("Data Manager"); m_Root = new TreeItem(rootDataNode, nullptr); dataStorage = m_DataStorage.Lock(); if (dataStorage.IsNotNull()) { // add Listener for the data storage itself auto command = itk::SimpleMemberCommand::New(); command->SetCallbackFunction(this, &QmitkDataStorageTreeModel::SetDataStorageDeleted); m_DataStorageDeletedTag = dataStorage->AddObserver(itk::DeleteEvent(), command); // add listeners for the nodes dataStorage->AddNodeEvent.AddListener(mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::AddNode)); dataStorage->ChangedNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::SetNodeModified)); dataStorage->RemoveNodeEvent.AddListener( mitk::MessageDelegate1( this, &QmitkDataStorageTreeModel::RemoveNode)); // finally add all nodes to the model this->Update(); } this->endResetModel(); } } void QmitkDataStorageTreeModel::SetDataStorageDeleted() { this->SetDataStorage(nullptr); } void QmitkDataStorageTreeModel::AddNodeInternal(const mitk::DataNode *node) { if (node == nullptr || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != nullptr) return; // find out if we have a root node TreeItem *parentTreeItem = m_Root; QModelIndex index; mitk::DataNode *parentDataNode = this->GetParentNode(node); if (parentDataNode) // no top level data node { parentTreeItem = m_Root->Find(parentDataNode); // find the corresponding tree item if (!parentTreeItem) { this->AddNode(parentDataNode); parentTreeItem = m_Root->Find(parentDataNode); if (!parentTreeItem) return; } // get the index of this parent with the help of the grand parent index = this->createIndex(parentTreeItem->GetIndex(), 0, parentTreeItem); } // add node if (m_PlaceNewNodesOnTop) { // emit beginInsertRows event beginInsertRows(index, 0, 0); parentTreeItem->InsertChild(new TreeItem(const_cast(node)), 0); } else { int firstRowWithASiblingBelow = 0; int nodeLayer = -1; node->GetIntProperty("layer", nodeLayer); for (TreeItem* siblingTreeItem: parentTreeItem->GetChildren()) { int siblingLayer = -1; if (mitk::DataNode* siblingNode = siblingTreeItem->GetDataNode()) { siblingNode->GetIntProperty("layer", siblingLayer); } if (nodeLayer > siblingLayer) { break; } ++firstRowWithASiblingBelow; } beginInsertRows(index, firstRowWithASiblingBelow, firstRowWithASiblingBelow); parentTreeItem->InsertChild(new TreeItem(const_cast(node)), firstRowWithASiblingBelow); } // emit endInsertRows event endInsertRows(); if(m_PlaceNewNodesOnTop) { this->AdjustLayerProperty(); } } void QmitkDataStorageTreeModel::AddNode(const mitk::DataNode *node) { if (node == nullptr || m_BlockDataStorageEvents || m_DataStorage.IsExpired() || !m_DataStorage.Lock()->Exists(node) || m_Root->Find(node) != nullptr) return; this->AddNodeInternal(node); } void QmitkDataStorageTreeModel::SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop) { m_PlaceNewNodesOnTop = _PlaceNewNodesOnTop; } void QmitkDataStorageTreeModel::RemoveNodeInternal(const mitk::DataNode *node) { if (!m_Root) return; TreeItem *treeItem = m_Root->Find(node); if (!treeItem) return; // return because there is no treeitem containing this node TreeItem *parentTreeItem = treeItem->GetParent(); QModelIndex parentIndex = this->IndexFromTreeItem(parentTreeItem); // emit beginRemoveRows event (QModelIndex is empty because we dont have a tree model) this->beginRemoveRows(parentIndex, treeItem->GetIndex(), treeItem->GetIndex()); // remove node std::vector children = treeItem->GetChildren(); delete treeItem; // emit endRemoveRows event endRemoveRows(); // move all children of deleted node into its parent for (std::vector::iterator it = children.begin(); it != children.end(); it++) { // emit beginInsertRows event beginInsertRows(parentIndex, parentTreeItem->GetChildCount(), parentTreeItem->GetChildCount()); // add nodes again parentTreeItem->AddChild(*it); // emit endInsertRows event endInsertRows(); } this->AdjustLayerProperty(); } void QmitkDataStorageTreeModel::RemoveNode(const mitk::DataNode *node) { if (node == nullptr || m_BlockDataStorageEvents) return; this->RemoveNodeInternal(node); } void QmitkDataStorageTreeModel::SetNodeModified(const mitk::DataNode *node) { TreeItem *treeItem = m_Root->Find(node); if (treeItem) { TreeItem *parentTreeItem = treeItem->GetParent(); // as the root node should not be removed one should always have a parent item if (!parentTreeItem) return; QModelIndex index = this->createIndex(treeItem->GetIndex(), 0, treeItem); // now emit the dataChanged signal emit dataChanged(index, index); } } mitk::DataNode *QmitkDataStorageTreeModel::GetParentNode(const mitk::DataNode *node) const { mitk::DataNode *dataNode = nullptr; mitk::DataStorage::SetOfObjects::ConstPointer _Sources = m_DataStorage.Lock()->GetSources(node); if (_Sources->Size() > 0) dataNode = _Sources->front(); return dataNode; } bool QmitkDataStorageTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) { mitk::DataNode *dataNode = this->TreeItemFromIndex(index)->GetDataNode(); if (!dataNode) return false; if (role == Qt::EditRole && !value.toString().isEmpty()) { dataNode->SetStringProperty("name", value.toString().toStdString().c_str()); mitk::PlanarFigure *planarFigure = dynamic_cast(dataNode->GetData()); if (planarFigure != nullptr) mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if (role == Qt::CheckStateRole) { // Please note: value.toInt() returns 2, independentely from the actual checkstate of the index element. // Therefore the checkstate is being estimated again here. QVariant qcheckstate = index.data(Qt::CheckStateRole); int checkstate = qcheckstate.toInt(); bool isVisible = bool(checkstate); dataNode->SetVisibility(!isVisible); emit nodeVisibilityChanged(); } // inform listeners about changes emit dataChanged(index, index); return true; } bool QmitkDataStorageTreeModel::setHeaderData(int /*section*/, Qt::Orientation /*orientation*/, const QVariant & /* value */, int /*role = Qt::EditRole*/) { return false; } void QmitkDataStorageTreeModel::AdjustLayerProperty() { /// transform the tree into an array and set the layer property descending std::vector vec; this->TreeToVector(m_Root, vec); int i = vec.size() - 1; for (std::vector::const_iterator it = vec.begin(); it != vec.end(); ++it) { mitk::DataNode::Pointer dataNode = (*it)->GetDataNode(); bool fixedLayer = false; if (!(dataNode->GetBoolProperty("fixedLayer", fixedLayer) && fixedLayer)) dataNode->SetIntProperty("layer", i); --i; } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkDataStorageTreeModel::TreeToVector(TreeItem *parent, std::vector &vec) const { TreeItem *current; for (int i = 0; i < parent->GetChildCount(); ++i) { current = parent->GetChild(i); this->TreeToVector(current, vec); vec.push_back(current); } } QModelIndex QmitkDataStorageTreeModel::IndexFromTreeItem(TreeItem *item) const { if (item == m_Root) return QModelIndex(); else return this->createIndex(item->GetIndex(), 0, item); } QList QmitkDataStorageTreeModel::GetNodeSet() const { QList res; if (m_Root) this->TreeToNodeSet(m_Root, res); return res; } void QmitkDataStorageTreeModel::TreeToNodeSet(TreeItem *parent, QList &vec) const { TreeItem *current; for (int i = 0; i < parent->GetChildCount(); ++i) { current = parent->GetChild(i); vec.push_back(current->GetDataNode()); this->TreeToNodeSet(current, vec); } } QModelIndex QmitkDataStorageTreeModel::GetIndex(const mitk::DataNode *node) const { if (m_Root) { TreeItem *item = m_Root->Find(node); if (item) return this->IndexFromTreeItem(item); } return QModelIndex(); } QList QmitkDataStorageTreeModel::ToTreeItemPtrList(const QMimeData *mimeData) { if (mimeData == nullptr || !mimeData->hasFormat(QmitkMimeTypes::DataStorageTreeItemPtrs)) { return QList(); } return ToTreeItemPtrList(mimeData->data(QmitkMimeTypes::DataStorageTreeItemPtrs)); } QList QmitkDataStorageTreeModel::ToTreeItemPtrList(const QByteArray &ba) { QList result; QDataStream ds(ba); while (!ds.atEnd()) { quintptr treeItemPtr; ds >> treeItemPtr; result.push_back(reinterpret_cast(treeItemPtr)); } return result; } void QmitkDataStorageTreeModel::Update() { auto datastorage = m_DataStorage.Lock(); if (datastorage.IsNotNull()) { mitk::DataStorage::SetOfObjects::ConstPointer _NodeSet = datastorage->GetAll(); /// Regardless the value of this preference, the new nodes must not be inserted /// at the top now, but at the position according to their layer. bool newNodesWereToBePlacedOnTop = m_PlaceNewNodesOnTop; m_PlaceNewNodesOnTop = false; for (const auto& node : *_NodeSet) { this->AddNodeInternal(node); } m_PlaceNewNodesOnTop = newNodesWereToBePlacedOnTop; /// Adjust the layers to ensure that derived nodes are above their sources. this->AdjustLayerProperty(); } } void QmitkDataStorageTreeModel::SetAllowHierarchyChange(bool allowHierarchyChange) { m_AllowHierarchyChange = allowHierarchyChange; } diff --git a/Modules/ToFUI/Qmitk/QmitkToFSurfaceGenerationWidget.cpp b/Modules/ToFUI/Qmitk/QmitkToFSurfaceGenerationWidget.cpp index 35de081d33..2275b3dd6c 100644 --- a/Modules/ToFUI/Qmitk/QmitkToFSurfaceGenerationWidget.cpp +++ b/Modules/ToFUI/Qmitk/QmitkToFSurfaceGenerationWidget.cpp @@ -1,290 +1,290 @@ /*============================================================================ 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 "QmitkToFSurfaceGenerationWidget.h" #include #include //QT headers #include #include #include + #include const std::string QmitkToFSurfaceGenerationWidget::VIEW_ID = "org.mitk.views.qmitktofsurfacegenerationwidget"; QmitkToFSurfaceGenerationWidget::QmitkToFSurfaceGenerationWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) , m_Controls(nullptr), m_ToFDistanceImageToSurfaceFilter(nullptr), m_ToFImageGrabber(nullptr), m_CameraIntrinsics(nullptr), m_Active(false) { CreateQtPartControl(this); } QmitkToFSurfaceGenerationWidget::~QmitkToFSurfaceGenerationWidget() { } void QmitkToFSurfaceGenerationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkToFSurfaceGenerationWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); this->OnShowAdvancedOptionsCheckboxChecked(false); } } void QmitkToFSurfaceGenerationWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_Compute3DDataCheckbox), SIGNAL(toggled(bool)), this, SLOT(OnCompute3DDataCheckboxChecked(bool)) ); connect( (QObject*)(m_Controls->m_DistanceColorMapCheckbox), SIGNAL(toggled(bool)), this, SLOT(OnDistanceColorMapCheckBoxChecked(bool)) ); connect( (QObject*)(m_Controls->m_RGBTextureCheckbox), SIGNAL(toggled(bool)), this, SLOT(OnRGBTextureCheckBoxChecked(bool)) ); connect( (QObject*)(m_Controls->m_TriangulationThresholdSpinbox), SIGNAL(valueChanged(double)), this, SLOT(OnTriangulationThresholdSpinBoxChanged()) ); connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsCheckbox), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptionsCheckboxChecked(bool)) ); connect( (QObject*)(m_Controls->m_RepresentationCombobox), SIGNAL(currentIndexChanged(int)),(QObject*) this, SLOT(OnRepresentationChanged(int)) ); connect( (QObject*)(m_Controls->m_ReconstructionCombobox), SIGNAL(currentIndexChanged(int)),(QObject*) this, SLOT(OnReconstructionChanged(int)) ); } } mitk::ToFDistanceImageToSurfaceFilter::Pointer QmitkToFSurfaceGenerationWidget::GetToFDistanceImageToSurfaceFilter() { return m_ToFDistanceImageToSurfaceFilter; } void QmitkToFSurfaceGenerationWidget::OnShowAdvancedOptionsCheckboxChecked(bool checked) { this->m_Controls->m_TextureGroupBox->setVisible(checked); this->m_Controls->m_TriangulationThresholdSpinbox->setVisible(checked); this->m_Controls->m_ReconstructionCombobox->setVisible(checked); this->m_Controls->m_RepresentationCombobox->setVisible(checked); this->m_Controls->label->setVisible(checked); this->m_Controls->label_2->setVisible(checked); this->m_Controls->label_3->setVisible(checked); } void QmitkToFSurfaceGenerationWidget::Initialize(mitk::ToFDistanceImageToSurfaceFilter::Pointer filter, mitk::ToFImageGrabber::Pointer grabber, mitk::CameraIntrinsics::Pointer intrinsics, mitk::DataNode::Pointer surface, vtkSmartPointer camera, bool generateSurface, bool showAdvancedOptions) { m_ToFDistanceImageToSurfaceFilter = filter; m_ToFImageGrabber = grabber; m_CameraIntrinsics = intrinsics; m_Active = true; m_Camera3d = camera; bool hasSurface = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasSurface", hasSurface); if(hasSurface) { this->m_Surface = mitk::Surface::New(); } else { this->m_Surface = this->m_ToFDistanceImageToSurfaceFilter->GetOutput(0); } m_SurfaceNode = surface; m_SurfaceNode->SetData(m_Surface); this->FindReconstructionModeProperty(); m_Controls->m_ShowAdvancedOptionsCheckbox->setChecked(showAdvancedOptions); this->OnShowAdvancedOptionsCheckboxChecked(showAdvancedOptions); m_Controls->m_Compute3DDataCheckbox->setChecked(generateSurface); } bool QmitkToFSurfaceGenerationWidget::IsActive() { if(!m_Active) { MITK_ERROR << "QmitkToFSurfaceGenerationWidget is not active - please call QmitkToFSurfaceGenerationWidget::Initialize() first"; } return m_Active; } void QmitkToFSurfaceGenerationWidget::OnTriangulationThresholdSpinBoxChanged() { if(IsActive()) { this->m_ToFDistanceImageToSurfaceFilter->SetTriangulationThreshold( this->m_Controls->m_TriangulationThresholdSpinbox->value() ); this->m_ToFImageGrabber->GetCameraDevice()->SetFloatProperty("TriangulationThreshold", this->m_Controls->m_TriangulationThresholdSpinbox->value()); } } void QmitkToFSurfaceGenerationWidget::OnReconstructionChanged(int index) { if(IsActive()) { mitk::ToFDistanceImageToSurfaceFilter::ReconstructionModeType type = mitk::ToFDistanceImageToSurfaceFilter::WithInterPixelDistance; switch (index) { case 0: { type = mitk::ToFDistanceImageToSurfaceFilter::WithInterPixelDistance; break; } case 1: { type = mitk::ToFDistanceImageToSurfaceFilter::WithOutInterPixelDistance; break; } case 2: { type = mitk::ToFDistanceImageToSurfaceFilter::Kinect; break; } default: { MITK_ERROR << "ReconstructionModeType does not exist or is not known in QmitkToFSurfaceGenerationWidget."; break; } } this->m_ToFDistanceImageToSurfaceFilter->SetReconstructionMode( type ); } } void QmitkToFSurfaceGenerationWidget::OnRepresentationChanged(int index) { if(IsActive()) { bool generateTriangularMesh = false; //PointCloud case if( index == 0) //Surface case { generateTriangularMesh = true; } this->m_ToFDistanceImageToSurfaceFilter->SetGenerateTriangularMesh(generateTriangularMesh); this->m_ToFImageGrabber->GetCameraDevice()->SetBoolProperty("GenerateTriangularMesh", generateTriangularMesh); this->m_ToFDistanceImageToSurfaceFilter->SetTriangulationThreshold( this->m_Controls->m_TriangulationThresholdSpinbox->value() ); this->m_ToFImageGrabber->GetCameraDevice()->SetFloatProperty("TriangulationThreshold", this->m_Controls->m_TriangulationThresholdSpinbox->value()); this->m_Controls->m_TriangulationThresholdSpinbox->setEnabled(generateTriangularMesh); } } void QmitkToFSurfaceGenerationWidget::OnRGBTextureCheckBoxChecked(bool checked) { if(IsActive()) { if(m_ToFImageGrabber->GetBoolProperty("HasRGBImage")) { if (checked) { // enable texture this->m_SurfaceNode->SetProperty("Surface.Texture",mitk::SmartPointerProperty::New(this->m_ToFImageGrabber->GetOutput(3))); } else { // disable texture this->m_SurfaceNode->GetPropertyList()->DeleteProperty("Surface.Texture"); } } } } void QmitkToFSurfaceGenerationWidget::OnDistanceColorMapCheckBoxChecked(bool checked) { if(m_SurfaceNode.IsNotNull()) { this->m_SurfaceNode->SetBoolProperty("scalar visibility", checked); } } bool QmitkToFSurfaceGenerationWidget::UpdateSurface() { if(IsActive()) { //##### Code for surface ##### if (m_Controls->m_Compute3DDataCheckbox->isChecked()) { bool hasSurface = false; this->m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasSurface", hasSurface); if(hasSurface) { mitk::SmartPointerProperty::Pointer surfaceProp = dynamic_cast< mitk::SmartPointerProperty * >(this->m_ToFImageGrabber->GetCameraDevice()->GetProperty("ToFSurface")); this->m_Surface->SetVtkPolyData( dynamic_cast< mitk::Surface* >( surfaceProp->GetSmartPointer().GetPointer() )->GetVtkPolyData() ); } else { this->m_Surface = m_ToFDistanceImageToSurfaceFilter->GetOutput(0); } //update pipeline this->m_Surface->Update(); return true; } //##### End code for surface ##### } return false; } void QmitkToFSurfaceGenerationWidget::OnCompute3DDataCheckboxChecked(bool checked) { if(checked) { //initialize the surface once MITK_DEBUG << "OnSurfaceCheckboxChecked true"; this->m_SurfaceNode->SetData(this->m_Surface); this->OnRepresentationChanged(m_Controls->m_RepresentationCombobox->currentIndex()); //we need to initialize (reinit) the surface, to make it fit into the renderwindow - mitk::RenderingManager::GetInstance()->InitializeViews( - this->m_Surface->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS, true); + mitk::RenderingManager::GetInstance()->InitializeViews(this->m_Surface->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); // correctly place the vtk camera for appropriate surface rendering //1m distance to camera should be a nice default value for most cameras m_Camera3d->SetPosition(0,0,0); m_Camera3d->SetViewUp(0,-1,0); m_Camera3d->SetFocalPoint(0,0,1); if (this->m_CameraIntrinsics.IsNotNull()) { // compute view angle from camera intrinsics m_Camera3d->SetViewAngle(mitk::ToFProcessingCommon::CalculateViewAngle(m_CameraIntrinsics,m_ToFImageGrabber->GetCaptureWidth())); } else { m_Camera3d->SetViewAngle(45); } m_Camera3d->SetClippingRange(1, 10000); } } void QmitkToFSurfaceGenerationWidget::FindReconstructionModeProperty() { bool KinectReconstructionMode = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("KinectReconstructionMode",KinectReconstructionMode); if(KinectReconstructionMode) { //set the reconstruction mode for kinect this->m_ToFDistanceImageToSurfaceFilter->SetReconstructionMode(mitk::ToFDistanceImageToSurfaceFilter::Kinect); m_Controls->m_ReconstructionCombobox->setDisabled(true); m_Controls->m_ReconstructionCombobox->setCurrentIndex(2); } else { m_Controls->m_ReconstructionCombobox->setEnabled(true); } } mitk::Surface::Pointer QmitkToFSurfaceGenerationWidget::GetSurface() { return m_Surface; }