diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp b/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp index 5a2ca84385..09bd466ab4 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp @@ -1,389 +1,396 @@ /*=================================================================== 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 "mitkContourModelSetGLMapper2D.h" #include "mitkColorProperty.h" #include "mitkContourModelSet.h" #include "mitkPlaneGeometry.h" #include "mitkProperties.h" #include #include "mitkGL.h" mitk::ContourModelSetGLMapper2D::ContourModelSetGLMapper2D() { } mitk::ContourModelSetGLMapper2D::~ContourModelSetGLMapper2D() { } void mitk::ContourModelSetGLMapper2D::Paint(mitk::BaseRenderer *renderer) { - BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); + BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); - mitk::DataNode *dataNode = this->GetDataNode(); - bool visible = true; - dataNode->GetVisibility(visible, renderer, "visible"); + mitk::DataNode::Pointer dataNode = this->GetDataNode(); + bool visible = true; + dataNode->GetVisibility(visible, nullptr); - if (!visible) - return; + if (!visible) + return; - mitk::ContourModelSet *input = this->GetInput(); + mitk::ContourModelSet::Pointer input = this->GetInput(); - mitk::ContourModelSet::ContourModelSetIterator it = input->Begin(); + auto centerOfViewPointZ = renderer->GetCurrentWorldPlaneGeometry()->GetCenter()[2]; + mitk::ContourModelSet::ContourModelSetIterator it = input->Begin(); - mitk::ContourModelSet::ContourModelSetIterator end = input->End(); + mitk::ContourModelSet::ContourModelSetIterator end = input->End(); - while (it != end) - { - this->DrawContour(it->GetPointer(), renderer); - ++it; - } + while (it != end) + { + //we have the assumption that each contour model vertex has the same z coordinate + auto currentZValue = (*it)->GetVertexAt(0)->Coordinates[2]; + double acceptedDeviationInMM = 5.0; + //only draw contour if it is visible + if (currentZValue - acceptedDeviationInMM < centerOfViewPointZ && currentZValue + acceptedDeviationInMM > centerOfViewPointZ){ + this->DrawContour(it->GetPointer(), renderer); + } + ++it; + } - if (input->GetSize() < 1) - return; + if (input->GetSize() < 1) + return; - ls->UpdateGenerateDataTime(); + ls->UpdateGenerateDataTime(); } mitk::ContourModelSet *mitk::ContourModelSetGLMapper2D::GetInput(void) { return const_cast(static_cast(GetDataNode()->GetData())); } void mitk::ContourModelSetGLMapper2D::InternalDrawContour(mitk::ContourModel *renderingContour, mitk::BaseRenderer *renderer) { if (!renderingContour) return; - mitk::DataNode *dataNode = this->GetDataNode(); + mitk::DataNode::Pointer dataNode = this->GetDataNode(); renderingContour->UpdateOutputInformation(); unsigned int timestep = renderer->GetTimeStep(); if (!renderingContour->IsEmptyTimeStep(timestep)) { // apply color and opacity read from the PropertyList ApplyColorAndOpacityProperties(renderer); mitk::ColorProperty::Pointer colorprop = dynamic_cast(dataNode->GetProperty("contour.color", renderer)); float opacity = 0.5; dataNode->GetFloatProperty("opacity", opacity, renderer); if (colorprop) { // set the color of the contour double red = colorprop->GetColor().GetRed(); double green = colorprop->GetColor().GetGreen(); double blue = colorprop->GetColor().GetBlue(); glColor4f(red, green, blue, opacity); } mitk::ColorProperty::Pointer selectedcolor = dynamic_cast(dataNode->GetProperty("contour.points.color", renderer)); if (!selectedcolor) { selectedcolor = mitk::ColorProperty::New(1.0, 0.0, 0.1); } vtkLinearTransform *transform = dataNode->GetVtkTransform(); // ContourModel::OutputType point; mitk::Point3D point; mitk::Point3D p; float vtkp[3]; float lineWidth = 3.0; bool drawit = false; bool isHovering = false; dataNode->GetBoolProperty("contour.hovering", isHovering); if (isHovering) dataNode->GetFloatProperty("contour.hovering.width", lineWidth); else dataNode->GetFloatProperty("contour.width", lineWidth); bool showSegments = false; dataNode->GetBoolProperty("contour.segments.show", showSegments); bool showControlPoints = false; dataNode->GetBoolProperty("contour.controlpoints.show", showControlPoints); bool showPoints = false; dataNode->GetBoolProperty("contour.points.show", showPoints); bool showPointsNumbers = false; dataNode->GetBoolProperty("contour.points.text", showPointsNumbers); bool showControlPointsNumbers = false; dataNode->GetBoolProperty("contour.controlpoints.text", showControlPointsNumbers); bool projectmode = false; dataNode->GetVisibility(projectmode, renderer, "contour.project-onto-plane"); mitk::ContourModel::VertexIterator pointsIt = renderingContour->IteratorBegin(timestep); Point2D pt2d; // projected_p in display coordinates Point2D lastPt2d; int index = 0; mitk::ScalarType maxDiff = 0.25; while (pointsIt != renderingContour->IteratorEnd(timestep)) { lastPt2d = pt2d; point = (*pointsIt)->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->WorldToDisplay(p, pt2d); ScalarType scalardiff = fabs(renderer->GetCurrentWorldPlaneGeometry()->SignedDistance(p)); // project to plane if (projectmode) { drawit = true; } else if (scalardiff < maxDiff) // point is close enough to be drawn { drawit = true; } else { drawit = false; } // draw line if (drawit) { if (showSegments) { // lastPt2d is not valid in first step if (!(pointsIt == renderingContour->IteratorBegin(timestep))) { glLineWidth(lineWidth); glBegin(GL_LINES); glVertex2f(pt2d[0], pt2d[1]); glVertex2f(lastPt2d[0], lastPt2d[1]); glEnd(); glLineWidth(1); } } if (showControlPoints) { - // draw ontrol points + // draw control points if ((*pointsIt)->IsControlPoint) { float pointsize = 4; Point2D tmp; Vector2D horz, vert; horz[1] = 0; vert[0] = 0; horz[0] = pointsize; vert[1] = pointsize; glColor3f(selectedcolor->GetColor().GetRed(), selectedcolor->GetColor().GetBlue(), selectedcolor->GetColor().GetGreen()); glLineWidth(1); // a rectangle around the point with the selected color glBegin(GL_LINE_LOOP); tmp = pt2d - horz; glVertex2dv(&tmp[0]); tmp = pt2d + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz; glVertex2dv(&tmp[0]); tmp = pt2d - vert; glVertex2dv(&tmp[0]); glEnd(); glLineWidth(1); // the actual point in the specified color to see the usual color of the point glColor3f( colorprop->GetColor().GetRed(), colorprop->GetColor().GetGreen(), colorprop->GetColor().GetBlue()); glPointSize(1); glBegin(GL_POINTS); tmp = pt2d; glVertex2dv(&tmp[0]); glEnd(); } } if (showPoints) { float pointsize = 3; Point2D tmp; Vector2D horz, vert; horz[1] = 0; vert[0] = 0; horz[0] = pointsize; vert[1] = pointsize; glColor3f(0.0, 0.0, 0.0); glLineWidth(1); // a rectangle around the point with the selected color glBegin(GL_LINE_LOOP); tmp = pt2d - horz; glVertex2dv(&tmp[0]); tmp = pt2d + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz; glVertex2dv(&tmp[0]); tmp = pt2d - vert; glVertex2dv(&tmp[0]); glEnd(); glLineWidth(1); // the actual point in the specified color to see the usual color of the point glColor3f(colorprop->GetColor().GetRed(), colorprop->GetColor().GetGreen(), colorprop->GetColor().GetBlue()); glPointSize(1); glBegin(GL_POINTS); tmp = pt2d; glVertex2dv(&tmp[0]); glEnd(); } if (showPointsNumbers) { std::string l; std::stringstream ss; ss << index; l.append(ss.str()); float rgb[3]; rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0; WriteTextWithOverlay(m_PointNumbersOverlay, l.c_str(), rgb, pt2d, renderer); } if (showControlPointsNumbers && (*pointsIt)->IsControlPoint) { std::string l; std::stringstream ss; ss << index; l.append(ss.str()); float rgb[3]; rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 0.0; WriteTextWithOverlay(m_ControlPointNumbersOverlay, l.c_str(), rgb, pt2d, renderer); } index++; } pointsIt++; } // end while iterate over controlpoints // close contour if necessary if (renderingContour->IsClosed(timestep) && drawit && showSegments) { lastPt2d = pt2d; point = renderingContour->GetVertexAt(0, timestep)->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->WorldToDisplay(p, pt2d); glLineWidth(lineWidth); glBegin(GL_LINES); glVertex2f(lastPt2d[0], lastPt2d[1]); glVertex2f(pt2d[0], pt2d[1]); glEnd(); glLineWidth(1); } // draw selected vertex if exists if (renderingContour->GetSelectedVertex()) { // transform selected vertex point = renderingContour->GetSelectedVertex()->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->WorldToDisplay(p, pt2d); ScalarType scalardiff = fabs(renderer->GetCurrentWorldPlaneGeometry()->SignedDistance(p)); //---------------------------------- // draw point if close to plane if (scalardiff < maxDiff) { float pointsize = 5; Point2D tmp; glColor3f(0.0, 1.0, 0.0); glLineWidth(1); // a diamond around the point glBegin(GL_LINE_LOOP); // begin from upper left corner and paint clockwise tmp[0] = pt2d[0] - pointsize; tmp[1] = pt2d[1] + pointsize; glVertex2dv(&tmp[0]); tmp[0] = pt2d[0] + pointsize; tmp[1] = pt2d[1] + pointsize; glVertex2dv(&tmp[0]); tmp[0] = pt2d[0] + pointsize; tmp[1] = pt2d[1] - pointsize; glVertex2dv(&tmp[0]); tmp[0] = pt2d[0] - pointsize; tmp[1] = pt2d[1] - pointsize; glVertex2dv(&tmp[0]); glEnd(); } //------------------------------------ } } } void mitk::ContourModelSetGLMapper2D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { node->AddProperty("contour.color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite); node->AddProperty("contour.points.color", ColorProperty::New(1.0, 0.0, 0.1), renderer, overwrite); node->AddProperty("contour.points.show", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("contour.segments.show", mitk::BoolProperty::New(true), renderer, overwrite); node->AddProperty("contour.controlpoints.show", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("contour.width", mitk::FloatProperty::New(1.0), renderer, overwrite); node->AddProperty("contour.hovering.width", mitk::FloatProperty::New(3.0), renderer, overwrite); node->AddProperty("contour.hovering", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("contour.points.text", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("contour.controlpoints.text", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("contour.project-onto-plane", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.h b/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.h index 53279d9919..cc3e919507 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.h +++ b/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.h @@ -1,70 +1,70 @@ /*=================================================================== 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 MITK_ContourModelSetGLMapper2D_H_ #define MITK_ContourModelSetGLMapper2D_H_ #include "mitkBaseRenderer.h" #include "mitkCommon.h" #include "mitkContourModelGLMapper2DBase.h" #include "mitkContourModelSet.h" #include namespace mitk { class BaseRenderer; class ContourModel; /** * @brief OpenGL-based mapper to display a mitk::ContourModelSet object containing several contours in a 2D render * window * * * @ingroup MitkContourModelModule */ class MITKCONTOURMODEL_EXPORT ContourModelSetGLMapper2D : public ContourModelGLMapper2DBase { public: mitkClassMacro(ContourModelSetGLMapper2D, ContourModelGLMapper2DBase); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** * reimplemented from Baseclass */ virtual void Paint(BaseRenderer *renderer) override; static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = NULL, bool overwrite = false); LocalStorageHandler m_LSH; protected: ContourModelSetGLMapper2D(); virtual ~ContourModelSetGLMapper2D(); void InternalDrawContour(mitk::ContourModel *contour, mitk::BaseRenderer *renderer) override; private: /** - * return a refernce of the rendered data object + * return a reference of the rendered data object */ ContourModelSet *GetInput(void); }; } // namespace mitk #endif diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp index ef3bc6282d..b8c6745739 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp @@ -1,236 +1,236 @@ /*=================================================================== 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 "mitkSurface.h" #include #include #include #include mitk::ContourModelSetMapper3D::ContourModelSetMapper3D() { } mitk::ContourModelSetMapper3D::~ContourModelSetMapper3D() { } const mitk::ContourModelSet *mitk::ContourModelSetMapper3D::GetInput(void) { - // convient way to get the data from the dataNode + // convenient way to get the data from the dataNode return static_cast(GetDataNode()->GetData()); } vtkProp *mitk::ContourModelSetMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { // return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Assembly; } void mitk::ContourModelSetMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { /* First convert the contourModel to vtkPolyData, then tube filter it and * set it input for our mapper */ LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); ContourModelSet *contourModelSet = dynamic_cast(this->GetDataNode()->GetData()); if (contourModelSet != NULL) { vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer cells = vtkSmartPointer::New(); vtkIdType baseIndex = 0; ContourModelSet::ContourModelSetIterator it = contourModelSet->Begin(); ContourModelSet::ContourModelSetIterator end = contourModelSet->End(); while (it != end) { ContourModel *contourModel = it->GetPointer(); ContourModel::VertexIterator vertIt = contourModel->Begin(); ContourModel::VertexIterator vertEnd = contourModel->End(); while (vertIt != vertEnd) { points->InsertNextPoint((*vertIt)->Coordinates[0], (*vertIt)->Coordinates[1], (*vertIt)->Coordinates[2]); ++vertIt; } vtkSmartPointer line = vtkSmartPointer::New(); vtkIdList *pointIds = line->GetPointIds(); vtkIdType numPoints = contourModel->GetNumberOfVertices(); pointIds->SetNumberOfIds(numPoints + 1); for (vtkIdType i = 0; i < numPoints; ++i) pointIds->SetId(i, baseIndex + i); pointIds->SetId(numPoints, baseIndex); cells->InsertNextCell(line); baseIndex += numPoints; ++it; } vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(points); polyData->SetLines(cells); vtkSmartPointer mapper = vtkSmartPointer::New(); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); mapper->SetInputData(polyData); localStorage->m_Assembly->AddPart(actor); } this->ApplyContourProperties(renderer); this->ApplyContourModelSetProperties(renderer); } void mitk::ContourModelSetMapper3D::Update(mitk::BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); mitk::ContourModel *data = static_cast(GetDataNode()->GetData()); if (data == NULL) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep(renderer); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); if (this->GetTimestep() == -1) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); // check if something important has changed and we need to rerender if ((localStorage->m_LastUpdateTime < node->GetMTime()) // was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) // Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) // was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) // was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime())) { this->GenerateDataForRenderer(renderer); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } vtkSmartPointer mitk::ContourModelSetMapper3D::CreateVtkPolyDataFromContour( mitk::ContourModel *inputContour, mitk::BaseRenderer *renderer) { unsigned int timestep = this->GetTimestep(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); localStorage->m_contourToPolyData->SetInput(inputContour); localStorage->m_contourToPolyData->Update(); vtkSmartPointer polyData = vtkSmartPointer::New(); polyData = localStorage->m_contourToPolyData->GetOutput()->GetVtkPolyData(timestep); return polyData; } void mitk::ContourModelSetMapper3D::ApplyContourModelSetProperties(BaseRenderer *renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); DataNode *dataNode = this->GetDataNode(); if (dataNode != NULL) { float lineWidth = 1; dataNode->GetFloatProperty("contour.3D.width", lineWidth, renderer); vtkSmartPointer collection = vtkSmartPointer::New(); localStorage->m_Assembly->GetActors(collection); collection->InitTraversal(); for (vtkIdType i = 0; i < collection->GetNumberOfItems(); i++) { vtkActor::SafeDownCast(collection->GetNextProp())->GetProperty()->SetLineWidth(lineWidth); } } } void mitk::ContourModelSetMapper3D::ApplyContourProperties(mitk::BaseRenderer *renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty("contour.color", renderer)); if (colorprop) { // set the color of the contour double red = colorprop->GetColor().GetRed(); double green = colorprop->GetColor().GetGreen(); double blue = colorprop->GetColor().GetBlue(); vtkSmartPointer collection = vtkSmartPointer::New(); localStorage->m_Assembly->GetActors(collection); collection->InitTraversal(); for (vtkIdType i = 0; i < collection->GetNumberOfItems(); i++) { vtkActor::SafeDownCast(collection->GetNextProp())->GetProperty()->SetColor(red, green, blue); } } } /*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/ mitk::ContourModelSetMapper3D::LocalStorage *mitk::ContourModelSetMapper3D::GetLocalStorage( mitk::BaseRenderer *renderer) { return m_LSH.GetLocalStorage(renderer); } mitk::ContourModelSetMapper3D::LocalStorage::LocalStorage() { m_Assembly = vtkSmartPointer::New(); m_contourToPolyData = mitk::ContourModelToSurfaceFilter::New(); } void mitk::ContourModelSetMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { node->AddProperty("color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite); node->AddProperty("contour.3D.width", mitk::FloatProperty::New(0.5), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/DicomRT/include/mitkRTStructureSetReader.h b/Modules/DicomRT/include/mitkRTStructureSetReader.h index 5cbbc74e8b..e73892adcb 100644 --- a/Modules/DicomRT/include/mitkRTStructureSetReader.h +++ b/Modules/DicomRT/include/mitkRTStructureSetReader.h @@ -1,93 +1,98 @@ /*=================================================================== 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 MITKRTSTRUCTURESETREADER_H #define MITKRTSTRUCTURESETREADER_H -#include -#include +#include #include #include #include +#include +#include -#include "dcmtk/dcmrt/drtstrct.h" - -#include +#include namespace mitk { - class MITKDICOMRT_EXPORT RTStructureSetReader : public itk::Object + class MITKDICOMRT_EXPORT RTStructureSetReader : public mitk::AbstractFileReader { - typedef std::deque ContourModelSetNodes; + typedef std::vector FindingsListVectorType; /** * Represent a region of interest (ROI) */ class RoiEntry { public: RoiEntry(); RoiEntry(const RoiEntry& src); virtual ~RoiEntry(); RoiEntry& operator=(const RoiEntry& src); void SetPolyData(ContourModelSet::Pointer roiPolyData); unsigned int Number; std::string Name; std::string Description; double DisplayColor[3]; mitk::ContourModelSet::Pointer ContourModelSet; }; public: - mitkClassMacroItkParent(RTStructureSetReader, itk::Object) - itkNewMacro(Self) - - /** - * @brief Reading a RT StructureSet from the DICOM file and returns the ROIs - * (region of interest) as a ContourModelSet. One ContourModelSet represent - * one ROI. A ContourModelSet contains ContourModels which represent the - * single structures. - * @param filepath to the RT StructureSet (.dmc) file - * @return Returns a std::deque filled with ContourModelSet::Pointer the - * deque contains all ROIs from the DICOM file - */ - ContourModelSetNodes ReadStructureSet(const char* filepath); - - protected: + RTStructureSetReader(); + RTStructureSetReader(const RTStructureSetReader& other); + + virtual ~RTStructureSetReader(); + + /** + * @brief Reading a RT StructureSet from the DICOM file and returns the ROIs + * (region of interest) as a ContourModelSet. One ContourModelSet represent + * one ROI. A ContourModelSet contains ContourModels which represent the + * single structures. + */ + using AbstractFileReader::Read; + virtual std::vector > Read() override; + + private: + RTStructureSetReader* Clone() const override; + + FindingsListVectorType ExtractPathsOfInterest(const DICOMTagPathList& pathsOfInterest, const DICOMDatasetAccessingImageFrameList& frames) const; + void SetProperties(BaseData::Pointer data, const FindingsListVectorType& findings) const; + mitk::IDICOMTagsOfInterest* GetDicomTagsOfInterestService() const; + /** * containing the ROIs meta information like name number and description */ std::vector ROISequenceVector; - RTStructureSetReader(); - virtual ~RTStructureSetReader(); - /** * Returns the number of ROIs from the ROISequenceVector */ size_t GetNumberOfROIs(); /** * Returns the relevant ROI from the ROISequenceVector by its number */ RoiEntry* FindRoiByNumber(unsigned int roiNum); + + us::ServiceRegistration m_ServiceReg; + IDICOMTagsOfInterest* m_DICOMTagsOfInterestService; }; } #endif // MITKRTSTRUCTURESETREADER_H diff --git a/Modules/DicomRT/src/mitkRTStructureSetReader.cpp b/Modules/DicomRT/src/mitkRTStructureSetReader.cpp index 28d327791d..27ba15197e 100644 --- a/Modules/DicomRT/src/mitkRTStructureSetReader.cpp +++ b/Modules/DicomRT/src/mitkRTStructureSetReader.cpp @@ -1,283 +1,332 @@ /*=================================================================== 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 "mitkRTStructureSetReader.h" -#include -#include -#include "mitkDICOMTagPath.h" +#include +#include +#include +#include + +#include "dcmtk/dcmrt/drtstrct.h" namespace mitk { - RTStructureSetReader::RTStructureSetReader() {} + RTStructureSetReader::RTStructureSetReader() : AbstractFileReader(IOMimeTypes::DICOM_MIMETYPE_NAME(), "DICOM RTSTRUCT File Reader") { + m_ServiceReg = RegisterService(); + m_DICOMTagsOfInterestService = GetDicomTagsOfInterestService(); + } + + RTStructureSetReader::RTStructureSetReader(const RTStructureSetReader& other) : mitk::AbstractFileReader(other) + { + + } RTStructureSetReader::~RTStructureSetReader() {} RTStructureSetReader::RoiEntry::RoiEntry() { Number = 0; DisplayColor[0] = 1.0; DisplayColor[1] = 0.0; DisplayColor[2] = 0.0; ContourModelSet = mitk::ContourModelSet::New(); } RTStructureSetReader::RoiEntry::RoiEntry(const RoiEntry& src) { Number = src.Number; Name = src.Name; Description = src.Description; DisplayColor[0] = src.DisplayColor[0]; DisplayColor[1] = src.DisplayColor[1]; DisplayColor[2] = src.DisplayColor[2]; ContourModelSet = mitk::ContourModelSet::New(); SetPolyData(src.ContourModelSet); } RTStructureSetReader::RoiEntry::~RoiEntry() {} RTStructureSetReader::RoiEntry& RTStructureSetReader:: RoiEntry::operator =(const RoiEntry& src) { Number = src.Number; Name = src.Name; Description = src.Description; DisplayColor[0] = src.DisplayColor[0]; DisplayColor[1] = src.DisplayColor[1]; DisplayColor[2] = src.DisplayColor[2]; SetPolyData(src.ContourModelSet); return (*this); } void RTStructureSetReader::RoiEntry:: SetPolyData(mitk::ContourModelSet::Pointer roiPolyData) { if (roiPolyData == this->ContourModelSet) { return; } this->ContourModelSet = roiPolyData; } size_t RTStructureSetReader::GetNumberOfROIs() { return this->ROISequenceVector.size(); } RTStructureSetReader::RoiEntry* RTStructureSetReader:: FindRoiByNumber(unsigned int roiNum) { for (unsigned int i = 0; i < this->ROISequenceVector.size(); ++i) { if (this->ROISequenceVector[i].Number == roiNum) { return &this->ROISequenceVector[i]; } } return NULL; } - RTStructureSetReader::ContourModelSetNodes RTStructureSetReader:: - ReadStructureSet(const char* filepath) + std::vector > RTStructureSetReader::Read() { + std::vector > result; + + std::string location = GetInputLocation(); + + auto tagsOfInterest = m_DICOMTagsOfInterestService->GetTagsOfInterest(); + DICOMTagPathList tagsOfInterestList; + for (const auto& tag : tagsOfInterest){ + tagsOfInterestList.push_back(tag.first); + } + + + mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); + scanner->SetInputFiles({ location }); + scanner->AddTagPaths(tagsOfInterestList); + scanner->Scan(); + + mitk::DICOMDatasetAccessingImageFrameList frames = scanner->GetFrameInfoList(); + if (frames.empty()){ + MITK_ERROR << "Error reading the RTSTRUCT file" << std::endl; + return result; + } + + auto findings = ExtractPathsOfInterest(tagsOfInterestList, frames); + DcmFileFormat file; - OFCondition output = file.loadFile(filepath, EXS_Unknown); + OFCondition output = file.loadFile(location.c_str(), EXS_Unknown); if (output.bad()) { - MITK_ERROR << "Cant read the file" << std::endl; + MITK_ERROR << "Can't read the file" << std::endl; + return result; } DcmDataset* dataset = file.getDataset(); DRTStructureSetIOD structureSetObject; OFCondition outp = structureSetObject.read(*dataset); if (!outp.good()) { MITK_ERROR << "Error reading the file" << std::endl; - RTStructureSetReader::ContourModelSetNodes x; - return x; + return result; } DRTStructureSetROISequence& roiSequence = structureSetObject.getStructureSetROISequence(); if (!roiSequence.gotoFirstItem().good()) { MITK_ERROR << "Error reading the structure sequence" << std::endl; - RTStructureSetReader::ContourModelSetNodes x; - return x; + return result; } do { DRTStructureSetROISequence::Item& currentSequence = roiSequence.getCurrentItem(); if (!currentSequence.isValid()) { continue; } OFString roiName; OFString roiDescription; Sint32 roiNumber; RoiEntry roi; currentSequence.getROIName(roiName); currentSequence.getROIDescription(roiDescription); currentSequence.getROINumber(roiNumber); roi.Name = roiName.c_str(); roi.Description = roiDescription.c_str(); roi.Number = roiNumber; this->ROISequenceVector.push_back(roi); } while (roiSequence.gotoNextItem().good()); Sint32 refRoiNumber; DRTROIContourSequence& roiContourSeqObject = structureSetObject.getROIContourSequence(); if (!roiContourSeqObject.gotoFirstItem().good()) { MITK_ERROR << "Error reading the contour sequence" << std::endl; - RTStructureSetReader::ContourModelSetNodes x; - return x; + return result; } do { mitk::ContourModelSet::Pointer contourSet = mitk::ContourModelSet::New(); DRTROIContourSequence::Item& currentRoiObject = roiContourSeqObject.getCurrentItem(); if (!currentRoiObject.isValid()) { continue; } currentRoiObject.getReferencedROINumber(refRoiNumber); DRTContourSequence& contourSeqObject = currentRoiObject.getContourSequence(); - if (contourSeqObject.gotoFirstItem().good()) + if (contourSeqObject.getNumberOfItems()>0 && contourSeqObject.gotoFirstItem().good()) { do { DRTContourSequence::Item& contourItem = contourSeqObject.getCurrentItem(); if (!contourItem.isValid()) { continue; } OFString contourNumber; OFString numberOfPoints; OFVector contourData_LPS; mitk::ContourModel::Pointer contourSequence = mitk::ContourModel::New(); contourItem.getContourNumber(contourNumber); contourItem.getNumberOfContourPoints(numberOfPoints); contourItem.getContourData(contourData_LPS); for (unsigned int i = 0; i < contourData_LPS.size() / 3; i++) { mitk::Point3D point; point[0] = contourData_LPS.at(3 * i); point[1] = contourData_LPS.at(3 * i + 1); point[2] = contourData_LPS.at(3 * i + 2); contourSequence->AddVertex(point); } contourSequence->Close(); contourSet->AddContourModel(contourSequence); } while (contourSeqObject.gotoNextItem().good()); } else { - MITK_ERROR << "Error reading contourSeqObject" << std::endl; + MITK_WARN << "contourSeqObject has no items in sequence. Object is neglected and not read. Struct name: " << this->FindRoiByNumber(refRoiNumber)->Name << std::endl; } RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber); if (refROI == NULL) { MITK_ERROR << "Can not find references ROI" << std::endl; continue; } Sint32 roiColor; - for (int j = 0; j < 3; j++) + for (unsigned int j = 0; j < 3; j++) { currentRoiObject.getROIDisplayColor(roiColor, j); refROI->DisplayColor[j] = roiColor / 255.0; } refROI->ContourModelSet = contourSet; contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name)); contourSet->SetProperty("contour.color", mitk::ColorProperty::New( refROI->DisplayColor[0], refROI->DisplayColor[1], refROI->DisplayColor[2])); - //add uid and patient uid to property - OFString uid; - structureSetObject.getSeriesInstanceUID(uid); - std::string uidPropertyName = mitk::DICOMTagPathToPropertyName(mitk::DICOMTagPath(0x0020, 0x000e)); - contourSet->SetProperty(uidPropertyName.c_str(), mitk::StringProperty::New(uid.c_str())); + } while (roiContourSeqObject.gotoNextItem().good()); + + for (auto const& aROI : ROISequenceVector) + { + result.push_back(aROI.ContourModelSet.GetPointer()); + result.at(result.size() - 1)->SetProperty("name", aROI.ContourModelSet->GetProperty("name")); + result.at(result.size() - 1)->SetProperty("color", aROI.ContourModelSet->GetProperty("contour.color")); + result.at(result.size() - 1)->SetProperty("contour.color", aROI.ContourModelSet->GetProperty("contour.color")); + SetProperties(result.at(result.size() - 1).GetPointer(), findings); + } + + return result; + } - OFString patientUid; - structureSetObject.getPatientID(patientUid); - std::string patientUidPropertyName = mitk::DICOMTagPathToPropertyName(mitk::DICOMTagPath(0x0010, - 0x0020)); - contourSet->SetProperty(patientUidPropertyName.c_str(), - mitk::StringProperty::New(patientUid.c_str())); + RTStructureSetReader* RTStructureSetReader::Clone() const + { + return new RTStructureSetReader(*this); + } - } while (roiContourSeqObject.gotoNextItem().good()); + RTStructureSetReader::FindingsListVectorType RTStructureSetReader::ExtractPathsOfInterest(const DICOMTagPathList& pathsOfInterest, const mitk::DICOMDatasetAccessingImageFrameList& frames) const + { + std::vector findings; + for (const auto& entry : pathsOfInterest){ + findings.push_back(frames.front()->GetTagValueAsString(entry)); + } + return findings; + } - std::deque nodes; + void RTStructureSetReader::SetProperties(BaseData::Pointer data, const FindingsListVectorType& findings) const + { + for (const auto& finding : findings){ + for (const auto& entry : finding){ + const std::string propertyName = mitk::DICOMTagPathToPropertyName(entry.path); + auto property = mitk::TemporoSpatialStringProperty::New(); + property->SetValue(entry.value); + data->SetProperty(propertyName.c_str(), property); + } + } + } - for (unsigned int i = 0; i < ROISequenceVector.size(); i++) + mitk::IDICOMTagsOfInterest* RTStructureSetReader::GetDicomTagsOfInterestService() const + { + mitk::IDICOMTagsOfInterest* result = nullptr; + + std::vector > toiRegisters = us::GetModuleContext()->GetServiceReferences(); + if (!toiRegisters.empty()) { - mitk::DataNode::Pointer node = mitk::DataNode::New(); - node->SetData(ROISequenceVector.at(i).ContourModelSet); - node->SetProperty("name", ROISequenceVector.at(i).ContourModelSet->GetProperty("name")); - node->SetProperty("color", ROISequenceVector.at(i).ContourModelSet->GetProperty("contour.color")); - node->SetProperty("contour.color", - ROISequenceVector.at(i).ContourModelSet->GetProperty("contour.color")); - node->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); - node->SetVisibility(true, mitk::BaseRenderer::GetInstance( - mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); - node->SetVisibility(false, mitk::BaseRenderer::GetInstance( - mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); - node->SetVisibility(false, mitk::BaseRenderer::GetInstance( - mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); - node->SetVisibility(true, mitk::BaseRenderer::GetInstance( - mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); - - nodes.push_back(node); + if (toiRegisters.size() > 1) + { + MITK_WARN << "Multiple DICOM tags of interest services found. Using just one."; + } + result = us::GetModuleContext()->GetService(toiRegisters.front()); } - return nodes; + return result; } + } diff --git a/Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp b/Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp index 0b6f39c90b..f667d48543 100644 --- a/Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp +++ b/Modules/DicomRT/test/mitkRTStructureSetReaderTest.cpp @@ -1,158 +1,129 @@ /*=================================================================== 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 "mitkTestingMacros.h" +#include #include #include "mitkRTStructureSetReader.h" #include -#include class mitkRTStructureSetReaderTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkRTStructureSetReaderTestSuite); -// MITK_TEST(TestBody); MITK_TEST(TestStructureSets); CPPUNIT_TEST_SUITE_END(); -private: - - mitk::RTStructureSetReader::Pointer m_rtStructureReader; - public: void setUp() override { - m_rtStructureReader = mitk::RTStructureSetReader::New(); - CPPUNIT_ASSERT_MESSAGE("Failed to initialize RTStructureSetReader", m_rtStructureReader.IsNotNull()); } void TestStructureSets() { - std::deque contourModelVectorCorrect; - std::deque contourModelVectorCorrectSequ; - std::deque contourModelVectorTest; - std::deque contourModelVectorTestDel; - - LoadData(contourModelVectorCorrect); - - contourModelVectorTest = m_rtStructureReader->ReadStructureSet(GetTestDataFilePath("RT/StructureSet/RS.dcm").c_str()); - - //Deleting all empty contourmodelsets - empty contourmodelsets cant be - //saved so we have reference for the comparison - for(unsigned int i=0; i(contourModelVectorTest.at(i)->GetData())->GetSize()>0){ - contourModelVectorTestDel.push_back(dynamic_cast(contourModelVectorTest.at(i)->GetData())); + auto structureSetReader = mitk::RTStructureSetReader(); + structureSetReader.SetInput(GetTestDataFilePath("RT/StructureSet/RS.dcm")); + auto readerOutput = structureSetReader.Read(); + CPPUNIT_ASSERT_EQUAL_MESSAGE("reader output should have one entry.", static_cast(16), static_cast(readerOutput.size())); + + auto contourModelVectorCorrect = LoadGroundTruthData(); + + std::vector contourModelVectorTest; + for (const auto& aStruct : readerOutput){ + mitk::ContourModelSet::Pointer contourModelSet = dynamic_cast(aStruct.GetPointer()); + //only compare structs with content + if (contourModelSet->GetSize() > 0){ + contourModelVectorTest.push_back(contourModelSet); } } - //Loop for ordering the loaded contourmodelsets(contourModelVectorCorrect) - for(unsigned int i=0; iGetProperty("name"); - for(unsigned int j=0; jGetProperty("name")->GetValueAsString(); + for (const auto& aStructCorrect : contourModelVectorCorrect) { - mitk::BaseProperty::Pointer tmp = contourModelVectorCorrect.at(j)->GetProperty("name"); - if(tmp->GetValueAsString().compare(name->GetValueAsString()) == 0) - contourModelVectorCorrectSequ.push_back(contourModelVectorCorrect.at(j)); + const std::string nameCorrect = aStructCorrect->GetProperty("name")->GetValueAsString(); + if (nameTest == nameCorrect){ + if (!Compare(aStructTest, aStructCorrect)){ + equal = false; } } - - //Testing wheather the two deques are equal - bool equal = true; - for(unsigned int i=0;iGetSize()!=c2->GetSize()) { MITK_INFO << "Number of ContourModelSets different" << std::endl; return false; } else { for(int i=0;iGetSize();++i) { mitk::ContourModel::Pointer cm1 = c1->GetContourModelAt(i); mitk::ContourModel::Pointer cm2 = c2->GetContourModelAt(i); + if(cm1->GetNumberOfVertices()!=cm2->GetNumberOfVertices()) { MITK_INFO << "Number of Vertices different" << std::endl; return false; } else { - float ep = 0.001; - for(int j=0;jGetNumberOfVertices();++j) + for(unsigned int j=0;jGetNumberOfVertices();++j) { mitk::Point3D p1 = cm1->GetVertexAt(i)->Coordinates; mitk::Point3D p2 = cm2->GetVertexAt(i)->Coordinates; - if(fabs(p1[0]-p2[0]) > ep || fabs(p1[0]-p2[0]) > ep || fabs(p1[0]-p2[0]) > ep) - { + if (!Equal(p1, p2, 0.001)){ return false; } } } } } return true; } - void LoadData(std::deque &r) + mitk::ContourModelSet::Pointer LoadFileWithNameProperty(const std::string& filename, const std::string& propertyName){ + auto readerOutput = mitk::IOUtil::Load(GetTestDataFilePath(filename)); + mitk::ContourModelSet::Pointer contourSet = dynamic_cast(readerOutput.at(0).GetPointer()); + contourSet->SetProperty("name", mitk::StringProperty::New(propertyName)); + return contourSet; + } + + std::vector LoadGroundTruthData() { - std::vector > readerOutput; - - readerOutput = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/BODY.cnt_set")); - mitk::ContourModelSet::Pointer cnt_set = dynamic_cast(readerOutput.at(0).GetPointer()); - cnt_set->SetProperty("name", mitk::StringProperty::New("BODY")); - r.push_back(cnt_set); - - readerOutput = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/Bladder.cnt_set")); - cnt_set = dynamic_cast(readerOutput.at(0).GetPointer()); - cnt_set->SetProperty("name", mitk::StringProperty::New("Bladder")); - r.push_back(cnt_set); - - readerOutput = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/Femoral Head Lt.cnt_set")); - cnt_set = dynamic_cast(readerOutput.at(0).GetPointer()); - cnt_set->SetProperty("name", mitk::StringProperty::New("Femoral Head Lt")); - r.push_back(cnt_set); - - readerOutput = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/Femoral Head RT.cnt_set")); - cnt_set = dynamic_cast(readerOutput.at(0).GetPointer()); - cnt_set->SetProperty("name", mitk::StringProperty::New("Femoral Head RT")); - r.push_back(cnt_set); - - readerOutput = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/PTV.cnt_set")); - cnt_set = dynamic_cast(readerOutput.at(0).GetPointer()); - cnt_set->SetProperty("name", mitk::StringProperty::New("PTV")); - r.push_back(cnt_set); - - readerOutput = mitk::IOUtil::Load(GetTestDataFilePath("RT/StructureSet/Rectum.cnt_set")); - cnt_set = dynamic_cast(readerOutput.at(0).GetPointer()); - cnt_set->SetProperty("name", mitk::StringProperty::New("Rectum")); - r.push_back(cnt_set); + std::vector allStructs; + + allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/BODY.cnt_set", "BODY")); + allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Bladder.cnt_set", "Bladder")); + allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Femoral Head Lt.cnt_set", "Femoral Head Lt")); + allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Femoral Head RT.cnt_set", "Femoral Head RT")); + allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/PTV.cnt_set", "PTV")); + allStructs.push_back(LoadFileWithNameProperty("RT/StructureSet/Rectum.cnt_set", "Rectum")); + + return allStructs; } }; MITK_TEST_SUITE_REGISTRATION(mitkRTStructureSetReader) diff --git a/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp b/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp index 3b465dd276..f228b79a90 100644 --- a/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp +++ b/Plugins/org.mitk.gui.qt.dicom/src/internal/DicomEventHandler.cpp @@ -1,418 +1,434 @@ /*=================================================================== 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 "mitkPluginActivator.h" #include "DicomEventHandler.h" #include #include #include #include #include #include #include #include #include #include "mitkImage.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include DicomEventHandler::DicomEventHandler() { } DicomEventHandler::~DicomEventHandler() { } void DicomEventHandler::OnSignalAddSeriesToDataManager(const ctkEvent& ctkEvent) { QStringList listOfFilesForSeries; listOfFilesForSeries = ctkEvent.getProperty("FilesForSeries").toStringList(); if (!listOfFilesForSeries.isEmpty()) { //for rt data, if the modality tag isn't defined or is "CT" the image is handled like before if(ctkEvent.containsProperty("Modality") && (ctkEvent.getProperty("Modality").toString().compare("RTDOSE",Qt::CaseInsensitive) == 0 || ctkEvent.getProperty("Modality").toString().compare("RTSTRUCT",Qt::CaseInsensitive) == 0 || ctkEvent.getProperty("Modality").toString().compare("RTPLAN", Qt::CaseInsensitive) == 0)) { QString modality = ctkEvent.getProperty("Modality").toString(); if(modality.compare("RTDOSE",Qt::CaseInsensitive) == 0) { auto doseReader = mitk::RTDoseReader(); doseReader.SetInput(listOfFilesForSeries.front().toStdString()); std::vector > readerOutput = doseReader.Read(); if (!readerOutput.empty()){ mitk::Image::Pointer doseImage = dynamic_cast(readerOutput.at(0).GetPointer()); mitk::DataNode::Pointer doseImageNode = mitk::DataNode::New(); doseImageNode->SetData(doseImage); doseImageNode->SetName("RTDose"); mitk::DataNode::Pointer doseOutlineNode = mitk::DataNode::New(); doseOutlineNode->SetData(doseImage); if (doseImage != nullptr) { auto sopUIDProperty = doseImage->GetProperty("dicomseriesreader.SOPClassUID"); if (sopUIDProperty.IsNotNull()){ auto sopUIDStringProperty = dynamic_cast(sopUIDProperty.GetPointer()); if (sopUIDStringProperty != nullptr){ std::string sopUID = sopUIDStringProperty->GetValue(); doseImageNode->SetName(sopUID); } } berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID.c_str()); typedef QStringList NamesType; NamesType names = prefNode->ChildrenNames(); std::map presetMap; for (NamesType::const_iterator pos = names.begin(); pos != names.end(); ++pos) { berry::IPreferences::Pointer aPresetNode = prefNode->Node(*pos); if (aPresetNode.IsNull()) { mitkThrow() << "Error in preference interface. Cannot find preset node under given name. Name: " << (*pos).toStdString(); } mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); NamesType levelNames = aPresetNode->ChildrenNames(); for (NamesType::const_iterator levelName = levelNames.begin(); levelName != levelNames.end(); ++levelName) { berry::IPreferences::Pointer levelNode = aPresetNode->Node(*levelName); if (aPresetNode.IsNull()) { mitkThrow() << "Error in preference interface. Cannot find level node under given preset name. Name: " << (*pos).toStdString() << "; Level id: " << (*levelName).toStdString(); } mitk::IsoDoseLevel::Pointer isoLevel = mitk::IsoDoseLevel::New(); isoLevel->SetDoseValue(levelNode->GetDouble(mitk::RTUIConstants::ISO_LEVEL_DOSE_VALUE_ID.c_str(), 0.0)); mitk::IsoDoseLevel::ColorType color; color.SetRed(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_RED_ID.c_str(), 1.0)); color.SetGreen(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_GREEN_ID.c_str(), 1.0)); color.SetBlue(levelNode->GetFloat(mitk::RTUIConstants::ISO_LEVEL_COLOR_BLUE_ID.c_str(), 1.0)); isoLevel->SetColor(color); isoLevel->SetVisibleIsoLine(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID.c_str(), true)); isoLevel->SetVisibleColorWash(levelNode->GetBool(mitk::RTUIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID.c_str(), true)); levelSet->SetIsoDoseLevel(isoLevel); } presetMap.insert(std::make_pair((*pos).toStdString(), levelSet)); } if (presetMap.size() == 0) { presetMap.insert(std::make_pair(std::string("Virtuos"), mitk::GeneratIsoLevels_Virtuos())); } prefNode = prefService->GetSystemPreferences()->Node(mitk::RTUIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID.c_str()); if (prefNode.IsNull()) { mitkThrow() << "Error in preference interface. Cannot find preset node under given name. Name: " << prefNode->ToString().toStdString(); } //set some specific colorwash and isoline properties bool showColorWashGlobal = prefNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_COLORWASH_ID.c_str(), true); doseImageNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), showColorWashGlobal); bool showIsolinesGlobal = prefNode->GetBool(mitk::RTUIConstants::GLOBAL_VISIBILITY_ISOLINES_ID.c_str(), true); doseOutlineNode->SetBoolProperty(mitk::RTConstants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), showIsolinesGlobal); //Set reference dose property double referenceDose = prefNode->GetDouble(mitk::RTUIConstants::REFERENCE_DOSE_ID.c_str(), mitk::RTUIConstants::DEFAULT_REFERENCE_DOSE_VALUE); doseImageNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), referenceDose); doseOutlineNode->SetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), referenceDose); QString presetName = prefNode->Get(mitk::RTUIConstants::SELECTED_ISO_PRESET_ID.c_str(), "Virtuos"); mitk::IsoDoseLevelSet::Pointer isoDoseLevelPreset = presetMap[presetName.toStdString()]; mitk::IsoDoseLevelSetProperty::Pointer levelSetProp = mitk::IsoDoseLevelSetProperty::New(isoDoseLevelPreset); doseImageNode->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(), levelSetProp); doseOutlineNode->SetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(), levelSetProp); mitk::IsoDoseLevelVector::Pointer levelVector = mitk::IsoDoseLevelVector::New(); mitk::IsoDoseLevelVectorProperty::Pointer levelVecProp = mitk::IsoDoseLevelVectorProperty::New(levelVector); doseImageNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(), levelVecProp); doseOutlineNode->SetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(), levelVecProp); mitk::RenderingModeProperty::Pointer renderingModeProp = mitk::RenderingModeProperty::New(); if (showColorWashGlobal) { //Generating the Colorwash vtkSmartPointer transferFunction = vtkSmartPointer::New(); for (mitk::IsoDoseLevelSet::ConstIterator itIsoDoseLevel = isoDoseLevelPreset->Begin(); itIsoDoseLevel != isoDoseLevelPreset->End(); ++itIsoDoseLevel) { float *hsv = new float[3]; //used for transfer rgb to hsv vtkSmartPointer cCalc = vtkSmartPointer::New(); if (itIsoDoseLevel->GetVisibleColorWash()){ cCalc->RGBToHSV(itIsoDoseLevel->GetColor()[0], itIsoDoseLevel->GetColor()[1], itIsoDoseLevel->GetColor()[2], &hsv[0], &hsv[1], &hsv[2]); transferFunction->AddHSVPoint(itIsoDoseLevel->GetDoseValue()*referenceDose, hsv[0], hsv[1], hsv[2], 1.0, 1.0); } } mitk::TransferFunction::Pointer mitkTransFunc = mitk::TransferFunction::New(); mitk::TransferFunctionProperty::Pointer mitkTransFuncProp = mitk::TransferFunctionProperty::New(); mitkTransFunc->SetColorTransferFunction(transferFunction); mitkTransFuncProp->SetValue(mitkTransFunc); doseImageNode->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); renderingModeProp->SetValue(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); } else { //Set rendering mode to levelwindow color mode renderingModeProp->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); } doseImageNode->SetProperty("Image Rendering.Mode", renderingModeProp); doseImageNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); //set the outline properties doseOutlineNode->SetBoolProperty("outline binary", true); doseOutlineNode->SetProperty("helper object", mitk::BoolProperty::New(true)); doseOutlineNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); dataStorage->Add(doseImageNode); dataStorage->Add(doseOutlineNode, doseImageNode); //set the dose mapper for outline drawing; the colorwash is realized by the imagevtkmapper2D mitk::DoseImageVtkMapper2D::Pointer contourMapper = mitk::DoseImageVtkMapper2D::New(); doseOutlineNode->SetMapper(1, contourMapper); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); } }//END DOSE } else if(modality.compare("RTSTRUCT",Qt::CaseInsensitive) == 0) { - mitk::RTStructureSetReader::Pointer structreader = mitk::RTStructureSetReader::New(); - std::deque modelVector = structreader->ReadStructureSet(listOfFilesForSeries.at(0).toStdString().c_str()); - - if(modelVector.empty()) - { - MITK_ERROR << "No structuresets were created" << endl; - } - else - { - ctkServiceReference serviceReference =mitk::PluginActivator::getContext()->getServiceReference(); - mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); - mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); - - for(int i=0; iAdd(modelVector.at(i)); + auto structReader = mitk::RTStructureSetReader(); + structReader.SetInput(listOfFilesForSeries.front().toStdString()); + std::vector > readerOutput = structReader.Read(); + + if (readerOutput.empty()){ + MITK_ERROR << "No structure sets were created" << endl; + } + else { + std::vector modelVector; + + ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); + mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); + mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); + + for (const auto& aStruct : readerOutput){ + mitk::ContourModelSet::Pointer countourModelSet = dynamic_cast(aStruct.GetPointer()); + + mitk::DataNode::Pointer structNode = mitk::DataNode::New(); + structNode->SetData(countourModelSet); + structNode->SetProperty("name", aStruct->GetProperty("name")); + structNode->SetProperty("color", aStruct->GetProperty("contour.color")); + structNode->SetProperty("contour.color", aStruct->GetProperty("contour.color")); + structNode->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); + structNode->SetVisibility(true, mitk::BaseRenderer::GetInstance( + mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1"))); + structNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( + mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget2"))); + structNode->SetVisibility(false, mitk::BaseRenderer::GetInstance( + mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget3"))); + structNode->SetVisibility(true, mitk::BaseRenderer::GetInstance( + mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget4"))); + + dataStorage->Add(structNode); + } + mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); } - mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); - } } else if (modality.compare("RTPLAN", Qt::CaseInsensitive) == 0) { - std::cout << "RTPLAN" << std::endl; auto planReader = mitk::RTPlanReader(); planReader.SetInput(listOfFilesForSeries.front().toStdString()); std::vector > readerOutput = planReader.Read(); if (!readerOutput.empty()){ //there is no image, only the properties are interesting mitk::Image::Pointer planDummyImage = dynamic_cast(readerOutput.at(0).GetPointer()); mitk::DataNode::Pointer planImageNode = mitk::DataNode::New(); planImageNode->SetData(planDummyImage); planImageNode->SetName("RTPlan"); ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); dataStorage->Add(planImageNode); } } } else { mitk::StringList seriesToLoad; QStringListIterator it(listOfFilesForSeries); while (it.hasNext()) { seriesToLoad.push_back(it.next().toStdString()); } //Get Reference for default data storage. ctkServiceReference serviceReference = mitk::PluginActivator::getContext()->getServiceReference(); mitk::IDataStorageService* storageService = mitk::PluginActivator::getContext()->getService(serviceReference); mitk::DataStorage* dataStorage = storageService->GetDefaultDataStorage().GetPointer()->GetDataStorage(); //special handling of Philips 3D US DICOM. //Copied from DICOMSeriesReaderService if (!seriesToLoad.empty() && mitk::DicomSeriesReader::IsPhilips3DDicom(seriesToLoad.front())) { MITK_INFO << "it is a Philips3D US Dicom file" << std::endl; mitk::LocaleSwitch localeSwitch("C"); std::locale previousCppLocale(std::cin.getloc()); std::locale l("C"); std::cin.imbue(l); mitk::DataNode::Pointer node = mitk::DataNode::New(); mitk::DicomSeriesReader::StringContainer stringvec; stringvec.push_back(seriesToLoad.front()); if (mitk::DicomSeriesReader::LoadDicomSeries(stringvec, *node)) { mitk::BaseData::Pointer data = node->GetData(); mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameName(seriesToLoad.front())); data->GetPropertyList()->SetProperty("name", nameProp); node->SetProperty("name", nameProp); dataStorage->Add(node); } std::cin.imbue(previousCppLocale); return; } //Normal DICOM handling (It wasn't a Philips 3D US) mitk::DICOMFileReaderSelector::Pointer selector = mitk::DICOMFileReaderSelector::New(); selector->LoadBuiltIn3DConfigs(); selector->LoadBuiltIn3DnTConfigs(); selector->SetInputFiles(seriesToLoad); mitk::DICOMFileReader::Pointer reader = selector->GetFirstReaderWithMinimumNumberOfOutputImages(); reader->SetAdditionalTagsOfInterest(mitk::GetCurrentDICOMTagsOfInterest()); reader->SetTagLookupTableToPropertyFunctor(mitk::GetDICOMPropertyForDICOMValuesFunctor); reader->SetInputFiles(seriesToLoad); mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); scanner->AddTagPaths(reader->GetTagsOfInterest()); scanner->SetInputFiles(seriesToLoad); scanner->Scan(); reader->SetTagCache(scanner->GetScanCache()); reader->AnalyzeInputFiles(); reader->LoadImages(); for (unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i) { const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(i); mitk::BaseData::Pointer data = desc.GetMitkImage().GetPointer(); std::string nodeName = "Unnamed_DICOM"; std::string studyDescription = desc.GetPropertyAsString("studyDescription"); std::string seriesDescription = desc.GetPropertyAsString("seriesDescription"); if (!studyDescription.empty()) { nodeName = studyDescription; } if (!seriesDescription.empty()) { if (!studyDescription.empty()) { nodeName += "/"; } nodeName += seriesDescription; } mitk::StringProperty::Pointer nameProp = mitk::StringProperty::New(nodeName); data->SetProperty("name", nameProp); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(data); nameProp = mitk::StringProperty::New(nodeName); node->SetProperty("name", nameProp); dataStorage->Add(node); } if (reader->GetNumberOfOutputs() < 1) { MITK_ERROR << "Error loading series: " << ctkEvent.getProperty("SeriesName").toString().toStdString() << " id: " << ctkEvent.getProperty("SeriesUID").toString().toStdString(); } } } else { MITK_INFO << "There are no files for the current series"; } } void DicomEventHandler::OnSignalRemoveSeriesFromStorage(const ctkEvent& /*ctkEvent*/) { } void DicomEventHandler::SubscribeSlots() { ctkServiceReference ref = mitk::PluginActivator::getContext()->getServiceReference(); if (ref) { ctkEventAdmin* eventAdmin = mitk::PluginActivator::getContext()->getService(ref); ctkDictionary properties; properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/ADD"; eventAdmin->subscribeSlot(this, SLOT(OnSignalAddSeriesToDataManager(ctkEvent)), properties); properties[ctkEventConstants::EVENT_TOPIC] = "org/mitk/gui/qt/dicom/DELETED"; eventAdmin->subscribeSlot(this, SLOT(OnSignalRemoveSeriesFromStorage(ctkEvent)), properties); } }