diff --git a/Modules/SurfaceRegistration/CMakeLists.txt b/Modules/SurfaceRegistration/CMakeLists.txt new file mode 100644 index 0000000000..017932dd79 --- /dev/null +++ b/Modules/SurfaceRegistration/CMakeLists.txt @@ -0,0 +1,3 @@ +mitk_create_module( SurfaceRegistration + DEPENDS PUBLIC MitkCore +) diff --git a/Modules/SurfaceRegistration/files.cmake b/Modules/SurfaceRegistration/files.cmake new file mode 100644 index 0000000000..9d45d8dad6 --- /dev/null +++ b/Modules/SurfaceRegistration/files.cmake @@ -0,0 +1,9 @@ +set(CPP_FILES + AwesomeImageFilter.cpp + AwesomeImageInteractor.cpp +) + +set(RESOURCE_FILES + Interactions/Paint.xml + Interactions/PaintConfig.xml +) diff --git a/Modules/SurfaceRegistration/include/AwesomeImageFilter.h b/Modules/SurfaceRegistration/include/AwesomeImageFilter.h new file mode 100644 index 0000000000..8cb5750b2e --- /dev/null +++ b/Modules/SurfaceRegistration/include/AwesomeImageFilter.h @@ -0,0 +1,52 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef AwesomeImageFilter_h +#define AwesomeImageFilter_h + +#include + +// The following header file is generated by CMake and thus it's located in +// the build directory. It provides an export macro for classes and functions +// that you want to be part of the public interface of your module. +#include + +// While you are free to derive directly from ITK filter base classes, +// MITK filter base classes provide typed accessor methods for the inputs +// and outputs, which will save you and your clients lots of manual casting. +class MITKSURFACEREGISTRATION_EXPORT AwesomeImageFilter final : public mitk::ImageToImageFilter +{ +public: + // All classes that derive from an ITK-based MITK class need at least the + // following two macros. Make sure you don't declare the constructor public + // to force clients of your class to follow the ITK convention for + // instantiating classes via the static New() method. + mitkClassMacro(AwesomeImageFilter, mitk::ImageToImageFilter) + itkFactorylessNewMacro(Self) + + itkSetMacro(Offset, int) + itkGetMacro(Offset, int) + +private: + AwesomeImageFilter(); + ~AwesomeImageFilter(); + + void GenerateData() override; + + int m_Offset; +}; + +#endif diff --git a/Modules/SurfaceRegistration/include/AwesomeImageInteractor.h b/Modules/SurfaceRegistration/include/AwesomeImageInteractor.h new file mode 100644 index 0000000000..2e31d2330b --- /dev/null +++ b/Modules/SurfaceRegistration/include/AwesomeImageInteractor.h @@ -0,0 +1,50 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef AwesomeImageInteractor_h +#define AwesomeImageInteractor_h + +#include +#include + +#include +namespace mitk +{ + + // See AwesomeImageFilter.h for details on typical class declarations + // in MITK. The actual functionality of this class is commented in its + // implementation file. + + class MITKSURFACEREGISTRATION_EXPORT AwesomeImageInteractor final : public mitk::DataInteractor + { + public: + mitkClassMacro(AwesomeImageInteractor, DataInteractor) + itkFactorylessNewMacro(Self) + + private: + AwesomeImageInteractor(); + ~AwesomeImageInteractor(); + + void ConnectActionsAndFunctions() override; + void DataNodeChanged() override; + + void Paint(mitk::StateMachineAction* action, mitk::InteractionEvent* event); + + itk::Index<3> m_LastPixelIndex; + }; + +#endif +} \ No newline at end of file diff --git a/Modules/SurfaceRegistration/resource/Interactions/Paint.xml b/Modules/SurfaceRegistration/resource/Interactions/Paint.xml new file mode 100644 index 0000000000..c63efb3683 --- /dev/null +++ b/Modules/SurfaceRegistration/resource/Interactions/Paint.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/Modules/SurfaceRegistration/resource/Interactions/PaintConfig.xml b/Modules/SurfaceRegistration/resource/Interactions/PaintConfig.xml new file mode 100644 index 0000000000..e141844565 --- /dev/null +++ b/Modules/SurfaceRegistration/resource/Interactions/PaintConfig.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Modules/SurfaceRegistration/src/AwesomeImageFilter.cpp b/Modules/SurfaceRegistration/src/AwesomeImageFilter.cpp new file mode 100644 index 0000000000..2f91a99430 --- /dev/null +++ b/Modules/SurfaceRegistration/src/AwesomeImageFilter.cpp @@ -0,0 +1,100 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include +#include + +#include + +// See definition of AwesomeImageFilter::GenerateData() further below for +// a rationale behind this function template. +template +static void AddOffset(const itk::Image* inputImage, int offset, mitk::Image::Pointer outputImage) +{ + typedef itk::Image ImageType; + typedef itk::ShiftScaleImageFilter FilterType; + + auto filter = FilterType::New(); + filter->SetInput(inputImage); + filter->SetShift(offset); + + filter->Update(); + + // This is the tricky part that is done wrong very often. As the image data + // of ITK images and MITK images are binary compatible, we don't need to + // cast or copy the ITK output image. Instead, we just want to reference + // the image data and tell ITK that we took the ownership. + mitk::GrabItkImageMemory(filter->GetOutput(), outputImage); +} + +AwesomeImageFilter::AwesomeImageFilter() + : m_Offset(0) +{ + this->SetNumberOfRequiredInputs(1); + this->SetNumberOfRequiredOutputs(1); +} + +AwesomeImageFilter::~AwesomeImageFilter() +{ +} + +void AwesomeImageFilter::GenerateData() +{ + mitk::Image::Pointer inputImage = this->GetInput(0); + + if (m_Offset == 0) + { + // Nothing to calculate in this case, just copy the input image. + this->SetPrimaryOutput(inputImage->Clone().GetPointer()); + } + else + { + mitk::Image::Pointer outputImage = this->GetOutput(); + + try + { + // We want to apply an ITK filter to the MITK input image. While MITK + // images are not templated, ITK images are templated by both pixel type + // and image dimension. The actual image data is binary compatible, though. + // MITK provides ITK access macros that enable you to directly operate + // on MITK images without any superfluous copying. + // To allow ITK filters to work with different image types at runtime you + // would be required to instantiate your function templates for each and + // every expected combination of pixel type and image dimension. Luckily, + // MITK provides a whole bunch of multiplexer macros to save you doing this + // manually (see mitkImageAccessByItk.h). + // These macros range from being completely generic to partly constrained + // variants. For example, you may want to constrain the image dimension or + // the pixel type. As your function template is compiled for each allowed + // combination, compile time and code size may increase dramatically. + // As a rule of thumb, use a suitable multiplexer macro that is as + // constrained as possible and yet as generic as necessary. + // To prevent a combinatorial explosion, image dimension is restricted to + // 2 and 3 even for the dimension-variable multiplexer macros. + // Thus, the following multiplexer macro allows for 2-dimensional and + // 3-dimensional images with an integer pixel type, for example, + // (un)signed char, short, and int, resulting in a total of 12 distinct + // combinations. + AccessIntegralPixelTypeByItk_n(inputImage, AddOffset, (m_Offset, outputImage)); + } + catch (const mitk::AccessByItkException& e) + { + MITK_ERROR << "Unsupported pixel type or image dimension: " << e.what(); + } + } +} diff --git a/Modules/SurfaceRegistration/src/AwesomeImageInteractor.cpp b/Modules/SurfaceRegistration/src/AwesomeImageInteractor.cpp new file mode 100644 index 0000000000..71fd1753bf --- /dev/null +++ b/Modules/SurfaceRegistration/src/AwesomeImageInteractor.cpp @@ -0,0 +1,185 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +#include +#include +#include + +#include + + + + // Helper function to get an image from a data node. + static mitk::Image::Pointer GetImage(mitk::DataNode::Pointer dataNode) + { + if (dataNode.IsNull()) + mitkThrow(); + + mitk::Image::Pointer image = dynamic_cast(dataNode->GetData()); + + if (image.IsNull()) + mitkThrow(); + + return image; + } + + // Helper function to get a geometry of an image for a specific time step. + static mitk::BaseGeometry::Pointer GetGeometry(mitk::Image::Pointer image, unsigned int timeStep) + { + mitk::TimeGeometry::Pointer timeGeometry = image->GetTimeGeometry(); + + if (timeGeometry.IsNull()) + mitkThrow(); + + auto geometry = timeGeometry->GetGeometryForTimeStep(timeStep); + + if (geometry.IsNull()) + mitkThrow(); + + return geometry; + } + + // The actual painting happens here. We're using a write accessor to gain safe + // write access to our image. The whole image volume for a given time step is + // locked. However, it's also possible - and preferable - to lock the slice of + // interest only. + template + static void Paint(mitk::Image::Pointer image, itk::Index<3> index, unsigned int timeStep) + { + // As soon as the ImagePixelWriteAccessor object goes out of scope at the + // end of this function, the image will be unlocked again (RAII). + mitk::ImagePixelWriteAccessor writeAccessor(image, image->GetVolumeData(timeStep)); + writeAccessor.SetPixelByIndex(index, std::numeric_limits::min()); + + // Don't forget to update the modified time stamp of the image. Otherwise, + // everything downstream wouldn't recognize that the image changed, + // including the rendering system. + image->Modified(); + } + + // Helper function to multiplex the actual Paint function call for different + // pixel types. As it's cumbersome and ugly, you may want to avoid such + // functions by using ITK for the actual painting and use the ITK access + // macros like we did for the AwesomeImageFilter. + static void Paint(mitk::Image::Pointer image, itk::Index<3> index, unsigned int timeStep) + { + switch (image->GetPixelType().GetComponentType()) + { + case itk::ImageIOBase::CHAR: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::UCHAR: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::SHORT: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::USHORT: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::INT: + Paint(image, index, timeStep); + break; + + case itk::ImageIOBase::UINT: + Paint(image, index, timeStep); + break; + + default: + mitkThrow(); + } + } + + mitk::AwesomeImageInteractor::AwesomeImageInteractor() + { + } + + mitk::AwesomeImageInteractor::~AwesomeImageInteractor() + { + } + + void mitk::AwesomeImageInteractor::ConnectActionsAndFunctions() + { + // Wire up this interactor with the state machine that is described by + // resource/Interactions/Paint.xml. + CONNECT_FUNCTION("paint", Paint) + } + + void mitk::AwesomeImageInteractor::DataNodeChanged() + { + // You almost always want to reset the state machine when the interactor + // has been attached to another data node. + this->ResetToStartState(); + } + + // The state machine is wired up with this Paint method. We wrote a few helper + // functions at the top of this files to keep this method clear and easy to + // read. + void mitk::AwesomeImageInteractor::Paint(mitk::StateMachineAction* action, mitk::InteractionEvent* event) + { + try + { + auto renderer = event->GetSender(); + + auto image = GetImage(this->GetDataNode()); + auto timeStep = renderer->GetTimeStep(); + auto geometry = GetGeometry(image, timeStep); + + // This method is wired up to mouse events. Thus, we can safely assume + // that the following cast will succeed and we have access to the mouse + // position and the first intersection point of a ray originating at the + // mouse position and shot into the scene. Convenient, isn't it? :-) + auto positionEvent = dynamic_cast(event); + auto position = positionEvent->GetPositionInWorld(); + + if (!geometry->IsInside(position)) + return; // Nothing to paint, as we're not inside the image bounds. + + // Okay, we're safe. Convert the mouse position to the index of the pixel + // we're pointing at. + itk::Index<3> index; + geometry->WorldToIndex<3>(position, index); + + // We don't need to paint over and over again while moving the mouse + // pointer inside the same pixel. That's especially relevant when operating + // on zoomed images. + if (index != m_LastPixelIndex) + { + // And finally... + ::Paint(image, index, timeStep); + + // Nearly done. We request the renderer to update the render window in + // order to see the result immediately. Actually, we should update all + // of the render windows by caling RequestUpdateAll() instead, as the + // painted pixels are possibly visible in other render windows, too. + // However, we decided to prefer performance here. + mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); + MITK_INFO << index[0] << " " << index[1] << " " << index[2]; + + m_LastPixelIndex = index; + } + } + catch (...) + { + return; + } + } diff --git a/Plugins/org.mitk.gui.qt.exampleplugin/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.exampleplugin/manifest_headers.cmake new file mode 100644 index 0000000000..fc9b0eb826 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.exampleplugin/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "Awesome Example Plugin") +set(Plugin-Version "0.1") +set(Plugin-Vendor "Awesome Company") +set(Plugin-ContactAddress "http://www.awesomeproject.my") +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/CMakeLists.txt b/Plugins/org.mitk.gui.qt.surfaceregistration/CMakeLists.txt new file mode 100644 index 0000000000..79422fc910 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/CMakeLists.txt @@ -0,0 +1,8 @@ +project(org_mitk_gui_qt_surfaceregistration) + +mitk_create_plugin( + EXPORT_DIRECTIVE MITK_QT_SURFACEREGISTRATION + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkQtWidgetsExt MitkSurfaceRegistration +) + diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/files.cmake b/Plugins/org.mitk.gui.qt.surfaceregistration/files.cmake new file mode 100644 index 0000000000..9be9068c28 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/files.cmake @@ -0,0 +1,36 @@ +set(SRC_CPP_FILES + +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_surfaceregistration_Activator.cpp + QmitkSurfaceRegistration.cpp +) + +set(UI_FILES + src/internal/SurfaceRegistrationControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_gui_qt_surfaceregistration_Activator.h + src/internal/QmitkSurfaceRegistration.h +) + +set(CACHED_RESOURCE_FILES + resources/icon.png + plugin.xml +) + +set(QRC_FILES + #resources/imagecropper.qrc +) + +set(CPP_FILES) + +foreach(file ${SRC_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + set(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.surfaceregistration/manifest_headers.cmake new file mode 100644 index 0000000000..38e2a4bf86 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "MITK Surface Registration") +set(Plugin-Version "1.0.0") +set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/plugin.xml b/Plugins/org.mitk.gui.qt.surfaceregistration/plugin.xml new file mode 100644 index 0000000000..cf5f59fa59 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/plugin.xml @@ -0,0 +1,30 @@ + + + + + + + + + Please describe + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/resources/icon.png b/Plugins/org.mitk.gui.qt.surfaceregistration/resources/icon.png new file mode 100644 index 0000000000..88300643d6 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.surfaceregistration/resources/icon.png differ diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/AwesomeView.cpp b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/AwesomeView.cpp new file mode 100644 index 0000000000..ef2ca51cec --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/AwesomeView.cpp @@ -0,0 +1,178 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "AwesomeView.h" + +#include +#include + +#include + +#include + +#include + +#include +#include + + + + //Helper function to create a fully set up instance of our + //AwesomeImageInteractor, based on the state machine specified in Paint.xml + //as well as its configuration in PaintConfig.xml. Both files are compiled + //into our MyAwesomeLib module as resources. + static mitk::AwesomeImageInteractor::Pointer CreateAwesomeImageInteractor() + { + auto myAwesomeLib = us::ModuleRegistry::GetModule("MitkMyAwesomeLib");//wichtig ist hier das Mitk noch dran zu schreiben + + auto interactor = mitk::AwesomeImageInteractor::New(); + interactor->LoadStateMachine("Paint.xml", myAwesomeLib); + interactor->SetEventConfig("PaintConfig.xml", myAwesomeLib); + + return interactor; + } + + // Don't forget to initialize the VIEW_ID. + const std::string AwesomeView::VIEW_ID = "my.awesomeproject.views.awesomeview"; + + void AwesomeView::CreateQtPartControl(QWidget* parent) + { + // Setting up the UI is a true pleasure when using .ui files, isn't it? + m_Controls.setupUi(parent); + + // Wire up the UI widgets with our functionality. + connect(m_Controls.processImageButton, SIGNAL(clicked()), this, SLOT(ProcessSelectedImage())); + } + + void AwesomeView::SetFocus() + { + m_Controls.processImageButton->setFocus(); + } + + void AwesomeView::OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& dataNodes) + { + for (const auto& dataNode : dataNodes) + { + // Write robust code. Always check pointers before using them. If the + // data node pointer is null, the second half of our condition isn't + // even evaluated and we're safe (C++ short-circuit evaluation). + if (dataNode.IsNotNull() && dynamic_cast(dataNode->GetData()) != nullptr) + { + m_Controls.selectImageLabel->setVisible(false); + return; + } + } + + // Nothing is selected or the selection doesn't contain an image. + m_Controls.selectImageLabel->setVisible(true); + } + + void AwesomeView::ProcessSelectedImage() + { + MITK_INFO << "Process start"; + // Before we even think about processing something, we need to make sure + // that we have valid input. Don't be sloppy, this is a main reason + // for application crashes if neglected. + + auto selectedDataNodes = this->GetDataManagerSelection(); + + if (selectedDataNodes.empty()) + return; + + auto firstSelectedDataNode = selectedDataNodes.front(); + + if (firstSelectedDataNode.IsNull()) + { + QMessageBox::information(nullptr, "Awesome View", "Please load and select an image before starting image processing."); + return; + } + MITK_INFO << "Process data"; + auto data = firstSelectedDataNode->GetData(); + + // Something is selected, but does it contain data? + if (data != nullptr) + { + // We don't use the auto keyword here, which would evaluate to a native + // image pointer. Instead, we want a smart pointer in order to ensure that + // the image isn't deleted somewhere else while we're using it. + mitk::Image::Pointer image = dynamic_cast(data); + + // Something is selected and it contains data, but is it an image? + if (image.IsNotNull()) + { + auto imageName = firstSelectedDataNode->GetName(); + auto offset = m_Controls.offsetSpinBox->value(); + + MITK_INFO << "Process image \"" << imageName << "\" ..."; + + // We're finally using the AwesomeImageFilter from our AwesomeLib module. + auto filter = AwesomeImageFilter::New(); + filter->SetInput(image); + filter->SetOffset(offset); + + filter->Update(); + + mitk::Image::Pointer processedImage = filter->GetOutput(); + + if (processedImage.IsNull() || !processedImage->IsInitialized()) + return; + + MITK_INFO << " done"; + + //// Stuff the resulting image into a data node, set some properties, + //// and add it to the data storage, which will eventually display the + //// image in the application. + auto processedImageDataNode = mitk::DataNode::New(); + processedImageDataNode->SetData(processedImage); + + QString name = QString("%1 (Offset: %2)").arg(imageName.c_str()).arg(offset); + processedImageDataNode->SetName(name.toStdString()); + + //// We don't really need to copy the level window, but if we wouldn't + //// do it, the new level window would be initialized to display the image + //// with optimal contrast in order to capture the whole range of pixel + //// values. This is also true for the input image as long as one didn't + //// modify its level window manually. Thus, the images would appear + //// identical unless you compare the level window widget for both images. + mitk::LevelWindow levelWindow; + + if (firstSelectedDataNode->GetLevelWindow(levelWindow)) + processedImageDataNode->SetLevelWindow(levelWindow); + + // We also attach our AwesomeImageInteractor, which allows us to paint + // on the resulting images by using the mouse as long as the CTRL key + // is pressed. + auto interactor = CreateAwesomeImageInteractor(); + + if (interactor.IsNotNull()) + interactor->SetDataNode(processedImageDataNode); + + this->GetDataStorage()->Add(processedImageDataNode); + } + } + + // Now it's your turn. This class/method has lots of room for improvements, + // for example: + // + // - What happens when multiple items are selected but the first one isn't + // an image? - There isn't any feedback for the user at all. + // - What's the front item of a selection? Does it depend on the order + // of selection or the position in the Data Manager? - Isn't it + // better to process all selected images? Don't forget to adjust the + // titles of the UI widgets. + // - In addition to the the displayed label, it's probably a good idea to + // enable or disable the button depending on the selection. + } diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/AwesomeView.h b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/AwesomeView.h new file mode 100644 index 0000000000..2a545080b5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/AwesomeView.h @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef AwesomeView_h +#define AwesomeView_h + +#include +#include + +// There's an item "AwesomeViewControls.ui" in the UI_FILES list in +// files.cmake. The Qt UI Compiler will parse this file and generate a +// header file prefixed with "ui_", which is located in the build directory. +// Use Qt Creator to view and edit .ui files. The generated header file +// provides a class that contains all of the UI widgets. +#include + +// All views in MITK derive from QmitkAbstractView. You have to override +// at least the two methods CreateQtPartControl() and SetFocus(). +class AwesomeView : public QmitkAbstractView +{ + // As QmitkAbstractView derives from QObject and we want to use the Qt + // signal and slot mechanism, we must not forget the Q_OBJECT macro. + // This header file also has to be listed in MOC_H_FILES in files.cmake, + // in order that the Qt Meta-Object Compiler can find and process this + // class declaration. + Q_OBJECT + +public: + // This is a tricky one and will give you some headache later on in + // your debug sessions if it has been forgotten. Also, don't forget + // to initialize it in the implementation file. + static const std::string VIEW_ID; + + // In this method we initialize the GUI components and connect the + // associated signals and slots. + void CreateQtPartControl(QWidget* parent) override; + +private slots: + void ProcessSelectedImage(); + +private: + // Typically a one-liner. Set the focus to the default widget. + void SetFocus() override; + + // This method is conveniently called whenever the selection of Data Manager + // items changes. + void OnSelectionChanged( + berry::IWorkbenchPart::Pointer source, + const QList& dataNodes) override; + + // Generated from the associated UI file, it encapsulates all the widgets + // of our view. + Ui::AwesomeViewControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/QmitkSurfaceRegistration.cpp b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/QmitkSurfaceRegistration.cpp new file mode 100644 index 0000000000..3f642e17f8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/QmitkSurfaceRegistration.cpp @@ -0,0 +1,143 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "QmitkSurfaceRegistration.h" + + +#include +#include + +#include +#include +#include +#include +#include // Includes for image casting between ITK and MITK: added after using Plugin Generator +#include // added for surface dynamic cast + +#include +#include + +const std::string QmitkSurfaceRegistration::VIEW_ID = "org.mitk.views.qmitksurfaceregistration"; + +QmitkSurfaceRegistration::QmitkSurfaceRegistration(QObject *parent) + : m_ParentWidget(0), m_movingSurfaceNode(nullptr), m_targetSurfaceNode(nullptr) +{ +} + +QmitkSurfaceRegistration::~QmitkSurfaceRegistration() +{ + // delete pointer objects + m_movingSurfaceNode = nullptr; + m_targetSurfaceNode = nullptr; +} +// + +void QmitkSurfaceRegistration::SetFocus(){ + +} + +void QmitkSurfaceRegistration::CreateQtPartControl(QWidget *parent) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi(parent); + + connect(m_Controls.pushButtonExecute, SIGNAL(clicked()), this, SLOT(doExecute())); + + m_ParentWidget = parent; +} + +void QmitkSurfaceRegistration::doExecute() +{ + MITK_INFO << "pushButtonExecute clicked"; +} + +void QmitkSurfaceRegistration::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, + const QList &nodes) +{ + MITK_INFO << "On Selection Changed"; + bool rotationEnabled = false; + if (nodes.empty()) + { + MITK_INFO << "Nothing selected yet"; + m_Controls.labelSelectMovingSurface->setStyleSheet(" QLabel { color: rgb(255, 0, 0) }"); + m_Controls.labelSelectTargetSurface->setStyleSheet(" QLabel { color: rgb(255, 0, 0) }"); + + m_Controls.labelMovingSurfaceName->setText(QString::fromStdString("No moving surface selected")); + m_Controls.labelTargetSurfaceName->setText(QString::fromStdString("No target surface selected")); + + m_Controls.groupBoxMappedData->setEnabled(false); + m_Controls.pushButtonExecute->setEnabled(false); + + return; + } + else + { + foreach(mitk::DataNode::Pointer dataNode, nodes) + { + MITK_INFO << dynamic_cast(dataNode->GetData()) + << " in selection changed and nodes available..."; + if (dataNode.IsNotNull() && dynamic_cast(dataNode->GetData())) + { + if (nodes.size() == 1) + { + MITK_INFO << "There is exactly one Image selected"; + m_movingSurfaceNode = nodes[0]; + m_Controls.labelSelectMovingSurface->setText("Selected moving surface:"); + m_Controls.labelSelectMovingSurface->setStyleSheet(" QLabel { color: rgb(0, 0, 0) }"); + m_Controls.labelMovingSurfaceName->setText( + QString::fromStdString("File name: " + m_movingSurfaceNode->GetName())); + } + else + { + MITK_INFO << "There is more than one Image selected"; + m_targetSurfaceNode = nodes[1]; + m_Controls.labelSelectTargetSurface->setText("Selected target surface:"); + m_Controls.labelSelectTargetSurface->setStyleSheet(" QLabel { color: rgb(0, 0, 0) }"); + m_Controls.labelTargetSurfaceName->setText( + QString::fromStdString("File name: " + m_targetSurfaceNode->GetName())); + m_Controls.groupBoxMappedData->setEnabled(true); + m_Controls.textMappedDataName->setEnabled(true); + m_Controls.pushButtonExecute->setEnabled(true); + } + } + } + } + + // mitk::Image::Pointer image = dynamic_cast(m_ImageNode->GetData()); + // if (image != nullptr) + // { + // vtkSmartPointer imageMat = image->GetGeometry()->GetVtkMatrix(); + // // check whether the image geometry is rotated, if so, no pixel aligned cropping or masking can be performed + // if ((imageMat->GetElement(1, 0) == 0.0) && (imageMat->GetElement(0, 1) == 0.0) && + // (imageMat->GetElement(1, 2) == 0.0) && (imageMat->GetElement(2, 1) == 0.0) && + // (imageMat->GetElement(2, 0) == 0.0) && (imageMat->GetElement(0, 2) == 0.0)) + // { + // rotationEnabled = false; + // m_Controls.labelWarningRotation->setVisible(false); + // } + // else + // { + // rotationEnabled = true; + // m_Controls.labelWarningRotation->setStyleSheet(" QLabel { color: rgb(255, 0, 0) }"); + // m_Controls.labelWarningRotation->setVisible(true); + // } +} +// else +// { +// QMessageBox::information(nullptr, "Warning", "Please load and select an image before starting image processing."); +// } +//} \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/QmitkSurfaceRegistration.h b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/QmitkSurfaceRegistration.h new file mode 100644 index 0000000000..be41e5096a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/QmitkSurfaceRegistration.h @@ -0,0 +1,100 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef QmitkSurfaceRegistration_h +#define QmitkSurfaceRegistration_h + +#include + +#ifdef WIN32 +#pragma warning( disable : 4250 ) +#endif + + +#include "QVTKWidget.h" +#include "QmitkRegisterClasses.h" + +#include + +#include "ui_SurfaceRegistrationControls.h" +#include "usServiceRegistration.h" + +/*! +@brief QmitkSurfaceRegistrationView +\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + +\sa QmitkFunctionality +\ingroup ${plugin_target}_internal +*/ +class QmitkSurfaceRegistration : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) +private: + + Q_OBJECT + +public: + /*! + @brief Constructor. Called by SampleApp (or other apps that use functionalities) + */ + QmitkSurfaceRegistration(QObject *parent = 0); + + virtual ~QmitkSurfaceRegistration(); + + static const std::string VIEW_ID; + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus() override; + + ///*! + //@brief Creates the Qt connections needed + //*/ + QWidget* GetControls(); + + /// @brief Called when the user clicks the GUI button + protected slots: + + void doExecute(); + +protected: + + // /*! + //@brief called by QmitkFunctionality when DataManager's selection has changed + // */ + void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; + +private: + /*! + * The parent QWidget + */ + QWidget* m_ParentWidget; + + /*! + * @brief A pointer to the node of the moving surface. + */ + mitk::WeakPointer m_movingSurfaceNode; + /*! + * @brief A pointer to the node of the target surface. + */ + mitk::WeakPointer m_targetSurfaceNode; + + Ui::SurfaceRegistrationControls m_Controls; +}; + +#endif // QmitkSurfaceRegistration_h \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/SurfaceRegistrationControls.ui b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/SurfaceRegistrationControls.ui new file mode 100644 index 0000000000..a41234dbc4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/SurfaceRegistrationControls.ui @@ -0,0 +1,377 @@ + + + SurfaceRegistrationControls + + + Qt::WindowModal + + + true + + + + 0 + 0 + 271 + 863 + + + + + 0 + 0 + + + + + 100 + 100 + + + + + 16777215 + 16777215 + + + + QmitkTemplate + + + + + + + 0 + 0 + + + + + 0 + 75 + + + + Moving + + + false + + + + + 10 + 20 + 347 + 13 + + + + + 0 + 0 + + + + QLabel { color: rgb(255, 0, 0) } + + + Select moving surface + + + + + + 10 + 40 + 171 + 20 + + + + + 0 + 0 + + + + + 50 + 20 + + + + + 16777215 + 16777215 + + + + QFrame::Box + + + No moving surface selected + + + + + + + + + 0 + 0 + + + + + 0 + 75 + + + + Target + + + false + + + + + 10 + 20 + 331 + 16 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + + Select target surface + + + + + + 10 + 40 + 171 + 20 + + + + + 0 + 0 + + + + + 50 + 20 + + + + + 16777215 + 16777215 + + + + QFrame::Box + + + No target surface selected + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 75 + + + + + 0 + 75 + + + + Mapped Data + + + + + 10 + 20 + 331 + 16 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + + Type mapped data name: + + + + + + 10 + 40 + 171 + 20 + + + + + 0 + 0 + + + + + 50 + 20 + + + + true + + + false + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustIgnored + + + true + + + defaultMappedDataName + + + Qt::TextEditable + + + + + + + + false + + + Execute + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/org_mitk_gui_qt_surfaceregistration_Activator.cpp b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/org_mitk_gui_qt_surfaceregistration_Activator.cpp new file mode 100644 index 0000000000..3165cf1ca7 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/org_mitk_gui_qt_surfaceregistration_Activator.cpp @@ -0,0 +1,41 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "org_mitk_gui_qt_surfaceregistration_Activator.h" +#include "QmitkSurfaceRegistration.h" +#include + +#include +#include + +US_INITIALIZE_MODULE + +namespace mitk { + void org_mitk_gui_qt_surfaceregistration_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(QmitkSurfaceRegistration, context) + } + + void org_mitk_gui_qt_surfaceregistration_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context) + } +} + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_surfaceregistration, mitk::PluginActivator) +#endif \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/org_mitk_gui_qt_surfaceregistration_Activator.h b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/org_mitk_gui_qt_surfaceregistration_Activator.h new file mode 100644 index 0000000000..01756f3873 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.surfaceregistration/src/internal/org_mitk_gui_qt_surfaceregistration_Activator.h @@ -0,0 +1,42 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#ifndef org_mitk_gui_qt_surfaceregistration_Activator_h +#define org_mitk_gui_qt_surfaceregistration_Activator_h + +#include + +namespace mitk { + + class org_mitk_gui_qt_surfaceregistration_Activator : + public QObject, public ctkPluginActivator +{ + Q_OBJECT + +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_surfaceregistration") +#endif + Q_INTERFACES(ctkPluginActivator) + +public: + + void start(ctkPluginContext* context) override; + void stop(ctkPluginContext* context) override; + +}; // PluginActivator + +} + +#endif // org_mitk_gui_qt_surfaceregistration_Activator_h