diff --git a/CMake/FindDCMTK.cmake b/CMake/FindDCMTK.cmake index 1ebd82cb10..7996817cd4 100644 --- a/CMake/FindDCMTK.cmake +++ b/CMake/FindDCMTK.cmake @@ -1,180 +1,183 @@ # adapted version of FindDCMTK, better suited for super-builds # - find DCMTK libraries and applications # # DCMTK_INCLUDE_DIRS - Directories to include to use DCMTK # DCMTK_LIBRARIES - Files to link against to use DCMTK # DCMTK_FOUND - If false, don't try to use DCMTK # DCMTK_DIR - (optional) Source directory for DCMTK # # DCMTK_DIR can be used to make it simpler to find the various include # directories and compiled libraries if you've just compiled it in the # source tree. Just set it to the root of the tree where you extracted # the source (default to /usr/include/dcmtk/) #============================================================================= # Copyright 2004-2009 Kitware, Inc. # Copyright 2009-2010 Mathieu Malaterre # Copyright 2010 Thomas Sondergaard # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distributed this file outside of CMake, substitute the full # License text for the above reference.) # # Written for VXL by Amitha Perera. # Upgraded for GDCM by Mathieu Malaterre. # Modified for EasyViz by Thomas Sondergaard. # # prefer DCMTK_DIR over default system paths like /usr/lib set(CMAKE_PREFIX_PATH ${DCMTK_DIR}/lib ${CMAKE_PREFIX_PATH}) # this is given to FIND_LIBRARY or FIND_PATH if(NOT DCMTK_FOUND AND NOT DCMTK_DIR) set(DCMTK_DIR "/usr/include/dcmtk/" CACHE PATH "Root of DCMTK source tree (optional).") mark_as_advanced(DCMTK_DIR) endif() # Find all libraries, store debug and release separately foreach(lib dcmpstat dcmsr dcmsign dcmtls dcmqrdb dcmnet dcmjpeg dcmimage dcmimgle dcmdata + dcmrt oflog ofstd ijg12 ijg16 ijg8 ) # Find Release libraries find_library(DCMTK_${lib}_LIBRARY_RELEASE ${lib} PATHS ${DCMTK_DIR}/${lib}/libsrc ${DCMTK_DIR}/${lib}/libsrc/Release ${DCMTK_DIR}/${lib}/Release ${DCMTK_DIR}/lib ${DCMTK_DIR}/lib/Release ${DCMTK_DIR}/dcmjpeg/lib${lib}/Release NO_DEFAULT_PATH ) # Find Debug libraries find_library(DCMTK_${lib}_LIBRARY_DEBUG ${lib} PATHS ${DCMTK_DIR}/${lib}/libsrc ${DCMTK_DIR}/${lib}/libsrc/Debug ${DCMTK_DIR}/${lib}/Debug ${DCMTK_DIR}/lib ${DCMTK_DIR}/lib/Debug ${DCMTK_DIR}/dcmjpeg/lib${lib}/Debug NO_DEFAULT_PATH ) mark_as_advanced(DCMTK_${lib}_LIBRARY_RELEASE) mark_as_advanced(DCMTK_${lib}_LIBRARY_DEBUG) # Add libraries to variable according to build type set(DCMTK_${lib}_LIBRARY) if(DCMTK_${lib}_LIBRARY_RELEASE) list(APPEND DCMTK_LIBRARIES optimized ${DCMTK_${lib}_LIBRARY_RELEASE}) list(APPEND DCMTK_${lib}_LIBRARY optimized ${DCMTK_${lib}_LIBRARY_RELEASE}) endif() if(DCMTK_${lib}_LIBRARY_DEBUG) list(APPEND DCMTK_LIBRARIES debug ${DCMTK_${lib}_LIBRARY_DEBUG}) list(APPEND DCMTK_${lib}_LIBRARY debug ${DCMTK_${lib}_LIBRARY_DEBUG}) endif() endforeach() set(DCMTK_config_TEST_HEADER osconfig.h) set(DCMTK_dcmdata_TEST_HEADER dctypes.h) set(DCMTK_dcmimage_TEST_HEADER dicoimg.h) set(DCMTK_dcmimgle_TEST_HEADER dcmimage.h) set(DCMTK_dcmjpeg_TEST_HEADER djdecode.h) set(DCMTK_dcmnet_TEST_HEADER assoc.h) set(DCMTK_dcmpstat_TEST_HEADER dcmpstat.h) set(DCMTK_dcmqrdb_TEST_HEADER dcmqrdba.h) set(DCMTK_dcmsign_TEST_HEADER sicert.h) set(DCMTK_dcmsr_TEST_HEADER dsrtree.h) set(DCMTK_dcmtls_TEST_HEADER tlslayer.h) set(DCMTK_ofstd_TEST_HEADER ofstdinc.h) +set(DCMTK_dcmrt_TEST_HEADER drtstrct.h) foreach(dir config dcmdata dcmimage dcmimgle dcmjpeg dcmnet dcmpstat dcmqrdb dcmsign dcmsr dcmtls + dcmrt ofstd) find_path(DCMTK_${dir}_INCLUDE_DIR ${DCMTK_${dir}_TEST_HEADER} PATHS ${DCMTK_DIR}/${dir}/include ${DCMTK_DIR}/${dir} ${DCMTK_DIR}/include/dcmtk/${dir} ${DCMTK_DIR}/include/${dir}) mark_as_advanced(DCMTK_${dir}_INCLUDE_DIR) #message("** DCMTKs ${dir} found at ${DCMTK_${dir}_INCLUDE_DIR}") if(DCMTK_${dir}_INCLUDE_DIR) list(APPEND DCMTK_INCLUDE_DIRS ${DCMTK_${dir}_INCLUDE_DIR}) endif() endforeach() if(WIN32) list(APPEND DCMTK_LIBRARIES netapi32 wsock32) endif() if(DCMTK_ofstd_INCLUDE_DIR) get_filename_component(DCMTK_dcmtk_INCLUDE_DIR ${DCMTK_ofstd_INCLUDE_DIR} PATH CACHE) list(APPEND DCMTK_INCLUDE_DIRS ${DCMTK_dcmtk_INCLUDE_DIR}) mark_as_advanced(DCMTK_dcmtk_INCLUDE_DIR) endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(DCMTK DEFAULT_MSG DCMTK_config_INCLUDE_DIR DCMTK_ofstd_INCLUDE_DIR DCMTK_ofstd_LIBRARY DCMTK_dcmdata_INCLUDE_DIR DCMTK_dcmdata_LIBRARY DCMTK_dcmimgle_INCLUDE_DIR DCMTK_dcmimgle_LIBRARY ) # Compatibility: This variable is deprecated set(DCMTK_INCLUDE_DIR ${DCMTK_INCLUDE_DIRS}) diff --git a/Core/Code/DataManagement/mitkRenderingModeProperty.cpp b/Core/Code/DataManagement/mitkRenderingModeProperty.cpp index b943aedd83..03df9590a1 100644 --- a/Core/Code/DataManagement/mitkRenderingModeProperty.cpp +++ b/Core/Code/DataManagement/mitkRenderingModeProperty.cpp @@ -1,72 +1,73 @@ /*=================================================================== 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 "mitkRenderingModeProperty.h" mitk::RenderingModeProperty::RenderingModeProperty( ) { this->AddRenderingModes(); this->SetValue( LEVELWINDOW_COLOR ); } mitk::RenderingModeProperty::RenderingModeProperty( const IdType& value ) { this->AddRenderingModes(); if ( IsValidEnumerationValue( value ) ) { this->SetValue( value ) ; } else MITK_WARN << "Warning: invalid image rendering mode"; } mitk::RenderingModeProperty::RenderingModeProperty( const std::string& value ) { this->AddRenderingModes(); if ( IsValidEnumerationValue( value ) ) { this->SetValue( value ); } else MITK_WARN << "Invalid image rendering mode"; } int mitk::RenderingModeProperty::GetRenderingMode() { return static_cast( this->GetValueAsId() ); } void mitk::RenderingModeProperty::AddRenderingModes() { AddEnum( "LevelWindow_Color", LEVELWINDOW_COLOR ); AddEnum( "LookupTable_LevelWindow_Color", LOOKUPTABLE_LEVELWINDOW_COLOR ); AddEnum( "ColorTransferFunction_LevelWindow_Color", COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR ); AddEnum( "LookupTable_Color", LOOKUPTABLE_COLOR ); AddEnum( "ColorTransferFunction_Color", COLORTRANSFERFUNCTION_COLOR ); + AddEnum( "IsoDoseShader_Color", ISODOSESHADER_COLOR ); } bool mitk::RenderingModeProperty::AddEnum( const std::string& name, const IdType& id ) { return Superclass::AddEnum( name, id ); } itk::LightObject::Pointer mitk::RenderingModeProperty::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); result->UnRegister(); return result; } diff --git a/Core/Code/DataManagement/mitkRenderingModeProperty.h b/Core/Code/DataManagement/mitkRenderingModeProperty.h index 7608d6d353..c2d47efb9e 100644 --- a/Core/Code/DataManagement/mitkRenderingModeProperty.h +++ b/Core/Code/DataManagement/mitkRenderingModeProperty.h @@ -1,166 +1,167 @@ /*=================================================================== 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_RENDERING_MODE_PROPERTY__H_ #define _MITK_RENDERING_MODE_PROPERTY__H_ #include "mitkEnumerationProperty.h" namespace mitk { #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4522) #endif /** * Encapsulates the enumeration for rendering modes. The property human-readable name (which is * used in the mitkWorkbench inside the Property View) is "Image Rendering.Mode". This property * affects rendering of images and is used inside the mitkImageVtkMapper2D to define which * rendering mode is applied to images. * Valid values are: * * \li LEVELWINDOW_COLOR: Level window and color will be applied to the image. * Our default level-window (sometimes referred to as window-level by other sources) setup for a test image looks like this: * \image html ExampleLevelWindowColor.png * This image can be reproduced with the mitkImageVtkMapper2DColorTest or mitkImageVtkMapper2DLevelWindowTest. * If "Image Rendering.Mode" is set to LEVELWINDOW_COLOR inside the mitkWorkbench, the level window slider will change * the rendering of the image. That means it will change the values of an internally used default lookup table. * Note, the level window slider changes the property "levelwindow" which modifies the range of * the internally used default lookup table. There is no way to directly modify the default lookup table. * In case you want to create a lookup table, use any LOOKUPTABLE mode as "Image Rendering.Mode". * This mode will apply the "color" property. The default color is white. If you change the "color" * property to yellow, the test image will be rendered like this: * \image html ExampleColorYellow.png * This image can be reproduced with the mitkImageVtkMapper2DColorTest. * * \li LOOKUPTABLE_LEVELWINDOW_COLOR: A lookup table, level window and color will be applied to the image. * As lookup table, the table object supplied by the property "LookupTable" will be used. If the user does not * supply any lookup table, a default rainbow-like lookup table will be used instead. This lookup table * will be influenced by the property "levelwindow" and the actor will be colored by the * "color" property. * Our test image with a lookup table mapping everything from red to blue looks like this: * \image html ExampleLookupTable.png * This image can be reproduced with the mitkImageVtkMapper2DLookupTableTest. Check this test code for an example how * to apply a lookup table to an image. * \note Changing a lookup table via the "levelwindow" property can be unintuitive and unwanted since the * level window slider will overwrite the range of the lookup table. Use LOOKUPTABLE_COLOR if you * don't want your lookuptable to be influenced by the "levelwindow" property. * * \li COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: A color transfer function, level window and color will be applied to the image. * Very similar mode to LOOKUPTABLE_LEVELWINDOW_COLOR. Instead of the lookup table a color transfer function will be used. * Color transfer functions are useful to colorize floating point images and allow sometimes more flexibility than * a lookup table. The "Image Rendering.Transfer Function" property defines the transfer function. Our test image * with a transfer function mapping everything from to red, green and blue looks like this: * \image html ExampleTransferFunction.png * This image can be reproduced with the mitkImageVtkMapper2DTransferFunctionTest. Check the test code for * an example how to define a transfer function for an image. This transfer function * will be influenced by the property "levelwindow" and the actor will be colored by the * "color" property. * \note Changing a transfer function table via the "levelwindow" property can be unintuitive and unwanted since * the level window slider will overwrite the.Use COLORTRANSFERFUNCTION_COLOR if you don't want your transfer * function to be influenced by the level window. * * \li LOOKUPTABLE_COLOR: A lookup table and color will be applied to the image. * Similar mode to LOOKUPTABLE_LEVELWINDOW_COLOR, except that the "levelwindow" property will not * modify the range of the lookup table. * * \li COLORTRANSFERFUNCTION_COLOR: A color trans ferfunction and color will be applied to the image. * Similar mode to COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR, except that the "levelwindow" property will not * modify the range of the transfer function. * * The order is given by the names (e.g. LOOKUPTABLE_COLOR applies first a lookup table and next a color). * Currently, there is no GUI (in mitkWorkbench) support for controlling lookup tables or transfer functions. * This has to be done by the programmer. Color and level window are controlled by color widget and level window slider. * Currently, the color is always applied. We do not set the color to white, if the user changes the mode. We assume * that users who change the mode know that a previously set color will still be applied (on top of the respective mode). * See VTK documentation for examples how to use vtkTransferfunction and vtkLookupTable. */ class MITK_CORE_EXPORT RenderingModeProperty : public EnumerationProperty { public: mitkClassMacro( RenderingModeProperty, EnumerationProperty ); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(RenderingModeProperty, const IdType&); mitkNewMacro1Param(RenderingModeProperty, const std::string&); //Never (!) change this without adaptation of mitkLevelWindowManagerTest::VerifyRenderingModes and mitkLevelWindowManagerTest::TestLevelWindowSliderVisibility ! enum ImageRenderingMode { LEVELWINDOW_COLOR = 0, LOOKUPTABLE_LEVELWINDOW_COLOR = 1, COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR = 2, LOOKUPTABLE_COLOR = 3, - COLORTRANSFERFUNCTION_COLOR = 4 + COLORTRANSFERFUNCTION_COLOR = 4, + ISODOSESHADER_COLOR = 5 // Default = LEVELWINDOW_COLOR; }; /** * Returns the current rendering mode */ virtual int GetRenderingMode(); using BaseProperty::operator=; protected: /** Sets rendering type to default (VTK_RAY_CAST_COMPOSITE_FUNCTION). */ RenderingModeProperty( ); /** * Constructor. Sets rendering type to the given value. */ RenderingModeProperty( const IdType& value ); /** * Constructor. Sets rendering type to the given value. */ RenderingModeProperty( const std::string& value ); /** * this function is overridden as protected, so that the user may not add * additional invalid rendering types. */ virtual bool AddEnum( const std::string& name, const IdType& id ); /** * Adds the default enumeration types. */ virtual void AddRenderingModes(); private: // purposely not implemented RenderingModeProperty& operator=(const RenderingModeProperty&); virtual itk::LightObject::Pointer InternalClone() const; }; #ifdef _MSC_VER # pragma warning(pop) #endif } // end of namespace mitk #endif diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp index 2218176cdb..5bd5d6d259 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp @@ -1,1087 +1,1163 @@ /*=================================================================== 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. ===================================================================*/ //MITK #include #include #include #include #include #include #include #include #include #include #include //#include #include #include "mitkImageStatisticsHolder.h" #include "mitkPlaneClipping.h" //MITK Rendering #include "mitkImageVtkMapper2D.h" #include "vtkMitkThickSlicesFilter.h" #include "vtkMitkLevelWindowFilter.h" #include "vtkNeverTranslucentTexture.h" +#include "vtkMitkShaderTexture.h" +#include "vtkImageToImageFilter.h" + +#include //VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //ITK #include #include mitk::ImageVtkMapper2D::ImageVtkMapper2D() { } mitk::ImageVtkMapper2D::~ImageVtkMapper2D() { //The 3D RW Mapper (Geometry2DDataVtkMapper3D) is listening to this event, //in order to delete the images from the 3D RW. this->InvokeEvent( itk::DeleteEvent() ); } //set the two points defining the textured plane according to the dimension and spacing void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float depth = this->CalculateLayerDepth(renderer); //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct //plane size in crosshair rotation and swivel mode. localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); //These two points define the axes of the plane in combination with the origin. //Point 1 is the x-axis and point 2 the y-axis. //Each plane is transformed according to the view (axial, coronal and saggital) afterwards. localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth) localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) } float mitk::ImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) { //get the clipping range to check how deep into z direction we can render images double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined float depth = -maxRange*0.01; // divide by 100 int layer = 0; GetDataNode()->GetIntProperty( "layer", layer, renderer); //add the layer property for each image to render images with a higher layer on top of the others depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) if(depth > 0.0f) { depth = 0.0f; MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; } return depth; } const mitk::Image* mitk::ImageVtkMapper2D::GetInput( void ) { return static_cast< const mitk::Image * >( GetDataNode()->GetData() ); } vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actors; } void mitk::ImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); mitk::DataNode* datanode = this->GetDataNode(); if ( input == NULL || input->IsInitialized() == false ) { return; } //check if there is a valid worldGeometry const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) { return; } input->Update(); // early out if there is no intersection of the current rendering geometry // and the geometry of the image that is to be rendered. if ( !RenderingGeometryIntersectsImage( worldGeometry, input->GetSlicedGeometry() ) ) { // set image to NULL, to clear the texture in 3D, because // the latest image is used there if the plane is out of the geometry // see bug-13275 localStorage->m_ReslicedImage = NULL; localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); return; } //set main input for ExtractSliceFilter localStorage->m_Reslicer->SetInput(input); localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); //set the transformation of the image to adapt reslice axis localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) ); //is the geometry of the slice based on the input image or the worldgeometry? bool inPlaneResampleExtentByGeometry = false; datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry); // Initialize the interpolation mode for resampling; switch to nearest // neighbor if the input image is too small. if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) { VtkResliceInterpolationProperty *resliceInterpolationProperty; datanode->GetProperty( resliceInterpolationProperty, "reslice interpolation" ); int interpolationMode = VTK_RESLICE_NEAREST; if ( resliceInterpolationProperty != NULL ) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } switch ( interpolationMode ) { case VTK_RESLICE_NEAREST: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); break; case VTK_RESLICE_LINEAR: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); break; case VTK_RESLICE_CUBIC: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); break; } } else { localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); } //set the vtk output property to true, makes sure that no unneeded mitk image convertion //is done. localStorage->m_Reslicer->SetVtkOutputRequest(true); //Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; // Thick slices parameters if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed { DataNode *dn=renderer->GetCurrentWorldGeometry2DNode(); if(dn) { ResliceMethodProperty *resliceMethodEnumProperty=0; if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); IntProperty *intProperty=0; if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) { thickSlicesNum = intProperty->GetValue(); if(thickSlicesNum < 1) thickSlicesNum=1; if(thickSlicesNum > 10) thickSlicesNum=10; } } else { MITK_WARN << "no associated widget plane data tree node found"; } } const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); if(thickSlicesMode > 0) { double dataZSpacing = 1.0; Vector3D normInIndex, normal; if ( planeGeometry != NULL ){ normal = planeGeometry->GetNormal(); }else{ const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); if(abstractGeometry != NULL) normal = abstractGeometry->GetPlane()->GetNormal(); else return; //no fitting geometry set } normal.Normalize(); input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); dataZSpacing = 1.0 / normInIndex.GetNorm(); localStorage->m_Reslicer->SetOutputDimensionality( 3 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); localStorage->m_TSFilter->SetInputData( localStorage->m_Reslicer->GetVtkOutput() ); //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually localStorage->m_Reslicer->Modified(); localStorage->m_Reslicer->Update(); localStorage->m_TSFilter->Modified(); localStorage->m_TSFilter->Update(); localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput(); } else { //this is needed when thick mode was enable bevore. These variable have to be reset to default values localStorage->m_Reslicer->SetOutputDimensionality( 2 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0); localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 ); localStorage->m_Reslicer->Modified(); //start the pipeline with updating the largest possible, needed if the geometry of the input has changed localStorage->m_Reslicer->UpdateLargestPossibleRegion(); localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput(); } // Bounds information for reslicing (only reuqired if reference geometry // is present) //this used for generating a vtkPLaneSource with the right size double sliceBounds[6]; for ( int i = 0; i < 6; ++i ) { sliceBounds[i] = 0.0; } localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); //get the spacing of the slice localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); // calculate minimum bounding rect of IMAGE in texture { double textureClippingBounds[6]; for ( int i = 0; i < 6; ++i ) { textureClippingBounds[i] = 0.0; } // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. mitk::PlaneClipping::CalculateClippedPlaneBounds( input->GetGeometry(), planeGeometry, textureClippingBounds ); textureClippingBounds[0] = static_cast< int >( textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[1] = static_cast< int >( textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[2] = static_cast< int >( textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 ); textureClippingBounds[3] = static_cast< int >( textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 ); //clipping bounds for cutting the image localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds); } //get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); //get the binary property bool binary = false; bool binaryOutline = false; datanode->GetBoolProperty( "binary", binary, renderer ); if(binary) //binary image { datanode->GetBoolProperty( "outline binary", binaryOutline, renderer ); if(binaryOutline) //contour rendering { if ( input->GetPixelType().GetBpe() <= 8 ) { //generate contours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) ) { if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { float binaryOutlineShadowWidth(1.5); datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer ); dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) ->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth ); } localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth ); } } else { binaryOutline = false; this->ApplyLookuptable(renderer); MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!"; } } else //standard binary image { if(numberOfComponents != 1) { MITK_ERROR << "Rendering Error: Binary Images with more then 1 component are not supported!"; } } } this->ApplyOpacity( renderer ); this->ApplyRenderingMode(renderer); // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); int displayedComponent = 0; if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1) { localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent); localStorage->m_VectorComponentExtractor->SetInputData(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0)); } else { //connect the input with the levelwindow filter localStorage->m_LevelWindowFilter->SetInputData(localStorage->m_ReslicedImage); } // check for texture interpolation property bool textureInterpolation = false; GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); //set the interpolation modus according to the property localStorage->m_Texture->SetInterpolate(textureInterpolation); +// bool doseProperty; +// if(datanode->GetBoolProperty("dose",doseProperty) && doseProperty) +// { +// // if the input is a dose file dont use the levelwindow filter because we need a float texture +// // and the levelwindow filter is casting to unsigned char +// localStorage->m_Texture->SetInput(localStorage->m_ReslicedImage); +// } +// else +// { // connect the texture with the output of the levelwindow filter localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); +// } this->TransformActor( renderer ); vtkActor* contourShadowActor = dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0)); if(binary && binaryOutline) //connect the mapper with the polyData which contains the lines { //We need the contour for the binary outline property as actor localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData); localStorage->m_Actor->SetTexture(NULL); //no texture for contours bool binaryOutlineShadow( false ); datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer ); if ( binaryOutlineShadow ) contourShadowActor->SetVisibility( true ); else contourShadowActor->SetVisibility( false ); } else { //Connect the mapper with the input texture. This is the standard case. //setup the textured plane this->GeneratePlane( renderer, sliceBounds ); //set the plane as input for the mapper localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); //set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); contourShadowActor->SetVisibility( false ); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::ApplyLevelWindow(mitk::BaseRenderer *renderer) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); LevelWindow levelWindow; this->GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" ); localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); mitk::LevelWindow opacLevelWindow; if( this->GetDataNode()->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) { //pass the opaque level window to the filter localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); } else { //no opaque level window localStorage->m_LevelWindowFilter->SetMinOpacity(0.0); localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0); } } void mitk::ImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); float rgb[3]= { 1.0f, 1.0f, 1.0f }; // check for color prop and use it for rendering if it exists // binary image hovering & binary image selection bool hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); if(hover && !selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.hoveringcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetDataNode()->GetColor( rgb, renderer, "color" ); } } if(selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.selectedcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetDataNode()->GetColor(rgb, renderer, "color"); } } if(!hover && !selected) { GetDataNode()->GetColor( rgb, renderer, "color" ); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); localStorage->m_Actor->GetProperty()->SetColor(rgbConv); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { float rgb[3]= { 1.0f, 1.0f, 1.0f }; mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("outline binary shadow color", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetColor(rgbConv); } } +void mitk::ImageVtkMapper2D::ApplyShader( mitk::BaseRenderer* renderer) +{ + LocalStorage *localStorage = this->GetLocalStorage( renderer ); + + localStorage->m_Texture = vtkSmartPointer::New().GetPointer(); + + CoreServicePointer shaderRepo(CoreServices::GetShaderRepository()); + itk::TimeStamp timestamp; + shaderRepo->ApplyProperties(this->GetDataNode(),localStorage->m_Actor,renderer,timestamp); +} + void mitk::ImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = this->GetLocalStorage( renderer ); float opacity = 1.0f; // check for opacity prop and use it for rendering if it exists GetDataNode()->GetOpacity( opacity, renderer, "opacity" ); //set the opacity according to the properties localStorage->m_Actor->GetProperty()->SetOpacity(opacity); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity); } } void mitk::ImageVtkMapper2D::ApplyRenderingMode( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); bool binary = false; this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); if(binary) // is it a binary image? { //for binary images, we always use our default LuT and map every value to (0,1) //the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window. localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_BinaryLookupTable); } else { //all other image types can make use of the rendering mode int renderingMode = mitk::RenderingModeProperty::LEVELWINDOW_COLOR; mitk::RenderingModeProperty::Pointer mode = dynamic_cast(this->GetDataNode()->GetProperty( "Image Rendering.Mode", renderer )); if(mode.IsNotNull()) { renderingMode = mode->GetRenderingMode(); } switch(renderingMode) { case mitk::RenderingModeProperty::LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_Color"; localStorage->m_LevelWindowFilter->SetLookupTable( localStorage->m_DefaultLookupTable ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color"; this->ApplyLookuptable( renderer ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color"; this->ApplyColorTransferFunction( renderer ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::LOOKUPTABLE_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color"; this->ApplyLookuptable( renderer ); break; case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color"; this->ApplyColorTransferFunction( renderer ); break; + case mitk::RenderingModeProperty::ISODOSESHADER_COLOR: + MITK_DEBUG << "'Image Rendering.Mode' = IsoDoseShader_Color"; + localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_DefaultLookupTable); + this->ApplyLevelWindow( renderer ); +// this->ApplyShader( renderer ); + break; default: MITK_ERROR << "No valid 'Image Rendering.Mode' set"; break; } } //we apply color for all images (including binaries). this->ApplyColor( renderer ); } void mitk::ImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable; // If lookup table or transferfunction use is requested... mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); if( lookupTableProp.IsNotNull() ) // is a lookuptable set? { usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else { //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'. //A default (rainbow) lookup table will be used. //Here have to do nothing. Warning for the user has been removed, due to unwanted console output //in every interation of the rendering. } localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable); } void mitk::ImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer *renderer) { mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); if( transferFunctionProp.IsNull() ) { MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image Rendering.Transfer Function'. Nothing will be done."; return; } LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); //pass the transfer function to our level window filter localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction()); } void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) { return; } mitk::Image* data = const_cast( this->GetInput() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //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->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->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(); } void mitk::ImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::Image::Pointer image = dynamic_cast(node->GetData()); // Properties common for both images and segmentations node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "outline binary shadow", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline binary shadow color", ColorProperty::New(0.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "outline shadow width", mitk::FloatProperty::New( 1.5 ), renderer, overwrite ); if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); + CoreServicePointer shaderRepo(CoreServices::GetShaderRepository()); + shaderRepo->AddDefaultProperties(node,renderer,overwrite); + mitk::RenderingModeProperty::Pointer renderingModeProperty = mitk::RenderingModeProperty::New(); node->AddProperty( "Image Rendering.Mode", renderingModeProperty); // Set default grayscale look-up table mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) ) { // modality provided by DICOM or other reader if ( photometricInterpretation.find("MONOCHROME1") != std::string::npos ) // meaning: display MINIMUM pixels as WHITE { // Set inverse grayscale look-up table mitkLut->SetType(mitk::LookupTable::INVERSE_GRAYSCALE); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); } // Otherwise do nothing - the default grayscale look-up table has already been set /* else if ( photometricInterpretation.find("MONOCHROME2") != std::string::npos ) // meaning: display MINIMUM pixels as BLACK { // apply default LUT (black to white) node->SetProperty( "color", mitk::ColorProperty::New( 1,1,1 ), renderer ); } // PALETTE interpretation should be handled ok by RGB loading */ } bool isBinaryImage(false); if ( ! node->GetBoolProperty("binary", isBinaryImage) ) { // ok, property is not set, use heuristic to determine if this // is a binary image mitk::Image::Pointer centralSliceImage; ScalarType minValue = 0.0; ScalarType maxValue = 0.0; ScalarType min2ndValue = 0.0; ScalarType max2ndValue = 0.0; mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); sliceSelector->SetInput(image); sliceSelector->SetSliceNr(image->GetDimension(2)/2); sliceSelector->SetTimeNr(image->GetDimension(3)/2); sliceSelector->SetChannelNr(image->GetDimension(4)/2); sliceSelector->Update(); centralSliceImage = sliceSelector->GetOutput(); if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) { minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin(); max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax(); } if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue) { // centralSlice is strange, lets look at all data minValue = image->GetStatistics()->GetScalarValueMin(); maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); } // some more properties specific for a binary... if (isBinaryImage) { node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); } else //...or image type object { node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); std::string className = image->GetNameOfClass(); if (className != "TensorImage" && className != "QBallImage") { PixelType pixelType = image->GetPixelType(); size_t numComponents = pixelType.GetNumberOfComponents(); if ((pixelType.GetPixelTypeAsString() == "vector" && numComponents > 1) || numComponents == 2 || numComponents > 4) node->AddProperty("Image.Displayed Component", mitk::IntProperty::New(0), renderer, overwrite); } } if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; if ( image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowCenter", sLevel ) && image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowWidth", sWindow ) ) { float level = atof( sLevel.c_str() ); float window = atof( sWindow.c_str() ); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; if ( image->GetPropertyList()->GetStringProperty( "dicom.series.SmallestPixelValueInSeries", sSmallestPixelValueInSeries ) && image->GetPropertyList()->GetStringProperty( "dicom.series.LargestPixelValueInSeries", sLargestPixelValueInSeries ) ) { float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? // might remedy some l/w widget challenges } else { contrast.SetAuto( static_cast(node->GetData()), false, true ); // we need this as a fallback } contrast.SetLevelWindow( level, window, true ); node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer ); } } if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) && (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA) && (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR) ) { mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->SetProperty( "opaclevelwindow", prop, renderer ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } mitk::ImageVtkMapper2D::LocalStorage* mitk::ImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } vtkSmartPointer mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ){ +// LocalStorage* localStorage = this->GetLocalStorage(renderer); + +// vtkMarchingSquares* squares = vtkMarchingSquares::New(); +// vtkSmartPointer polyData = vtkSmartPointer::New(); + +// float depth = CalculateLayerDepth(renderer); + +// squares->SetInput(localStorage->m_ReslicedImage); +// squares->SetNumberOfContours(1); +// squares->SetValue(0,1); +// squares->Update(); + +// polyData = squares->GetOutput(); + +// vtkIdType numberOfPoints = polyData->GetNumberOfPoints(); +// fstream f; +// f.open("mapper_neu.txt", ios::out); + +// for(int i=0;iGetPoint(i); +// x[2] = depth; +// f << "Point" << i << ": " << x[0] << ", " << x[1] << ", " << x[2] << endl; +// } + +// polyData->BuildCells(); +// polyData->BuildLinks(); + +// f.close(); + LocalStorage* localStorage = this->GetLocalStorage(renderer); //get the min and max index values of each direction int* extent = localStorage->m_ReslicedImage->GetExtent(); int xMin = extent[0]; int xMax = extent[1]; int yMin = extent[2]; int yMax = extent[3]; int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image int line = dims[0]; //how many pixels per line? int x = xMin; //pixel index x int y = yMin; //pixel index y char* currentPixel; //get the depth for each contour float depth = CalculateLayerDepth(renderer); vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points // We take the pointer to the first pixel of the image currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer() ); while (y <= yMax) { //if the current pixel value is set to something if ((currentPixel) && (*currentPixel != 0)) { //check in which direction a line is necessary //a line is added if the neighbor of the current pixel has the value 0 //and if the pixel is located at the edge of the image //if vvvvv not the first line vvvvv if (y > yMin && *(currentPixel-line) == 0) { //x direction - bottom edge of the pixel //add the 2 points vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); //add the line between both points lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the last line vvvvv if (y < yMax && *(currentPixel+line) == 0) { //x direction - top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the first pixel vvvvv if ( (x > xMin || y > yMin) && *(currentPixel-1) == 0) { //y direction - left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the last pixel vvvvv if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) == 0) { //y direction - right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } /* now consider pixels at the edge of the image */ //if vvvvv left edge of image vvvvv if (x == xMin) { //draw left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv right edge of image vvvvv if (x == xMax) { //draw right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv bottom edge of image vvvvv if (y == yMin) { //draw bottom edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv top edge of image vvvvv if (y == yMax) { //draw top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } }//end if currentpixel is set x++; if (x > xMax) { //reached end of line x = xMin; y++; } // Increase the pointer-position to the next pixel. // This is safe, as the while-loop and the x-reset logic above makes // sure we do not exceed the bounds of the image currentPixel++; }//end of while // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); + + fstream f; + f.open("mapper_alt.txt", ios::out); + + for(int i=0;iGetNumberOfPoints();i++) + { + double x[3]; + polyData->GetPoint(i,x); + f << "Point" << i << ": " << x[0] << ", " << x[1] << ", " << x[2] << endl; + } + + f.close(); return polyData; } void mitk::ImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); trans->SetMatrix(matrix); //transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital) localStorage->m_Actor->SetUserTransform(trans); //transform the origin to center based coordinates, because MITK is center based. localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { vtkActor* secondaryActor = dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) ); secondaryActor->SetUserTransform(trans); secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); } } bool mitk::ImageVtkMapper2D::RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry ) { // if either one of the two geometries is NULL we return true // for safety reasons if ( renderingGeometry == NULL || imageGeometry == NULL ) return true; // get the distance for the first cornerpoint ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) ); for( int i=1; i<8; i++ ) { mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i ); // get the distance to the other cornerpoints ScalarType distance = renderingGeometry->SignedDistance( cornerPoint ); // if it has not the same signing as the distance of the first point if ( initialDistance * distance < 0 ) { // we have an intersection and return true return true; } } // all distances have the same sign, no intersection and we return false return false; } mitk::ImageVtkMapper2D::LocalStorage::~LocalStorage() { } mitk::ImageVtkMapper2D::LocalStorage::LocalStorage() : m_VectorComponentExtractor(vtkSmartPointer::New()) { m_LevelWindowFilter = vtkSmartPointer::New(); //Do as much actions as possible in here to avoid double executions. m_Plane = vtkSmartPointer::New(); m_Texture = vtkSmartPointer::New().GetPointer(); m_DefaultLookupTable = vtkSmartPointer::New(); m_BinaryLookupTable = vtkSmartPointer::New(); m_ColorLookupTable = vtkSmartPointer::New(); m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_Actors = vtkSmartPointer::New(); m_Reslicer = mitk::ExtractSliceFilter::New(); m_TSFilter = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_ReslicedImage = vtkSmartPointer::New(); m_EmptyPolyData = vtkSmartPointer::New(); //the following actions are always the same and thus can be performed //in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); mitk::LookupTable::Pointer mitkLUT = mitk::LookupTable::New(); //built a default lookuptable mitkLUT->SetType(mitk::LookupTable::GRAYSCALE); m_DefaultLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_BINARY); m_BinaryLookupTable = mitkLUT->GetVtkLookupTable(); // add a default rainbow lookup table for color mapping m_ColorLookupTable->SetRampToLinear(); m_ColorLookupTable->SetHueRange(0.6667, 0.0); m_ColorLookupTable->SetTableRange(0.0, 20.0); m_ColorLookupTable->Build(); //do not repeat the texture (the image) m_Texture->RepeatOff(); //set the mapper for the actor m_Actor->SetMapper( m_Mapper ); vtkSmartPointer outlineShadowActor = vtkSmartPointer::New(); outlineShadowActor->SetMapper( m_Mapper ); m_Actors->AddPart( outlineShadowActor ); m_Actors->AddPart( m_Actor ); } diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.h b/Core/Code/Rendering/mitkImageVtkMapper2D.h index 1409106e72..7086f1324a 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.h +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.h @@ -1,307 +1,322 @@ /*=================================================================== 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 MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E #define MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E //MITK #include //MITK Rendering #include "mitkBaseRenderer.h" #include "mitkVtkMapper.h" #include "mitkExtractSliceFilter.h" //VTK #include #include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + class vtkActor; class vtkPolyDataMapper; class vtkPlaneSource; class vtkImageData; class vtkLookupTable; class vtkImageExtractComponents; class vtkImageReslice; class vtkImageChangeInformation; class vtkPoints; class vtkMitkThickSlicesFilter; class vtkPolyData; class vtkMitkApplyLevelWindowToRGBFilter; class vtkMitkLevelWindowFilter; namespace mitk { /** \brief Mapper to resample and display 2D slices of a 3D image. * * The following image gives a brief overview of the mapping and the involved parts. * * \image html imageVtkMapper2Darchitecture.png * * First, the image is resliced by means of vtkImageReslice. The volume image * serves as input to the mapper in addition to spatial placement of the slice and a few other * properties such as thick slices. This code was already present in the old version * (mitkImageMapperGL2D). * * Next, the obtained slice (m_ReslicedImage) is put into a vtkMitkLevelWindowFilter * and the scalar levelwindow, opacity levelwindow and optional clipping to * local image bounds are applied * * Next, the output of the vtkMitkLevelWindowFilter is used to create a texture * (m_Texture) and a plane onto which the texture is rendered (m_Plane). For * mapping purposes, a vtkPolyDataMapper (m_Mapper) is utilized. Orthographic * projection is applied to create the effect of a 2D image. The mapper and the * texture are assigned to the actor (m_Actor) which is passed to the VTK rendering * pipeline via the method GetVtkProp(). * * In order to transform the textured plane to the correct position in space, the * same transformation as used for reslicing is applied to both the camera and the * vtkActor. All important steps are explained in more detail below. The resulting * 2D image (by reslicing the underlying 3D input image appropriately) can either * be directly rendered in a 2D view or just be calculated to be used later by another * rendering entity, e.g. in texture mapping in a 3D view. * * Properties that can be set for images and influence the imageMapper2D are: * * - \b "opacity": (FloatProperty) Opacity of the image * - \b "color": (ColorProperty) Color of the image * - \b "LookupTable": (mitkLookupTableProperty) If this property is set, * the default lookuptable will be ignored and the "LookupTable" value * will be used instead. * - \b "Image Rendering.Mode": This property decides which mode is used to render images. (E.g. if a lookup table or a transferfunction is applied). Detailed documentation about the modes can be found here: \link mitk::RenderingerModeProperty \endlink * - \b "Image Rendering.Transfer Function": (mitkTransferFunctionProperty) If this * property is set, a color transferfunction will be used to color the image. * - \b "binary": (BoolProperty) is the image a binary image or not * - \b "outline binary": (BoolProperty) show outline of the image or not * - \b "texture interpolation": (BoolProperty) texture interpolation of the image * - \b "reslice interpolation": (VtkResliceInterpolationProperty) reslice interpolation of the image * - \b "in plane resample extent by geometry": (BoolProperty) Do it or not * - \b "bounding box": (BoolProperty) Is the Bounding Box of the image shown or not * - \b "layer": (IntProperty) Layer of the image * - \b "volume annotation color": (ColorProperty) color of the volume annotation, TODO has to be reimplemented * - \b "volume annotation unit": (StringProperty) annotation unit as string (does not implicit convert the unit!) unit is ml or cm3, TODO has to be reimplemented * The default properties are: * - \b "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ) * - \b "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ) * - \b "binary", mitk::BoolProperty::New( true ), renderer, overwrite ) * - \b "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ) * - \b "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ) * - \b "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ) * - \b "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ) * - \b "bounding box", mitk::BoolProperty::New( false ) ) * - \b "layer", mitk::IntProperty::New(10), renderer, overwrite) * - \b "Image Rendering.Transfer Function": Default color transfer function for CTs * - \b "LookupTable": Rainbow color. * If the modality-property is set for an image, the mapper uses modality-specific default properties, * e.g. color maps, if they are defined. * \ingroup Mapper */ class MITK_CORE_EXPORT ImageVtkMapper2D : public VtkMapper { public: /** Standard class typedefs. */ mitkClassMacro( ImageVtkMapper2D,VtkMapper ); /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** \brief Get the Image to map */ const mitk::Image *GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ /** * To render transveral, coronal, and sagittal, the mapper is called three times. * For performance reasons, the corresponding data for each view is saved in the * internal helper class LocalStorage. This allows rendering n views with just * 1 mitkMapper using n vtkMapper. * */ class MITK_CORE_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_Actor; vtkSmartPointer m_Actors; /** \brief Mapper of a 2D render window. */ vtkSmartPointer m_Mapper; vtkSmartPointer m_VectorComponentExtractor; /** \brief Current slice of a 2D render window.*/ vtkSmartPointer m_ReslicedImage; /** \brief Empty vtkPolyData that is set when rendering geometry does not * intersect the image geometry. * \warning This member variable is set to NULL, * if no image geometry is inside the plane geometry * of the respective render window. Any user of this * slice has to check whether it is set to NULL! */ vtkSmartPointer m_EmptyPolyData; /** \brief Plane on which the slice is rendered as texture. */ vtkSmartPointer m_Plane; /** \brief The texture which is used to render the current slice. */ vtkSmartPointer m_Texture; /** \brief The lookuptables for colors and level window */ vtkSmartPointer m_DefaultLookupTable; vtkSmartPointer m_BinaryLookupTable; vtkSmartPointer m_ColorLookupTable; /** \brief The actual reslicer (one per renderer) */ mitk::ExtractSliceFilter::Pointer m_Reslicer; /** \brief Filter for thick slices */ vtkSmartPointer m_TSFilter; /** \brief PolyData object containg all lines/points needed for outlining the contour. This container is used to save a computed contour for the next rendering execution. For instance, if you zoom or pann, there is no need to recompute the contour. */ vtkSmartPointer m_OutlinePolyData; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief mmPerPixel relation between pixel and mm. (World spacing).*/ mitk::ScalarType* m_mmPerPixel; /** \brief This filter is used to apply the level window to Grayvalue and RBG(A) images. */ vtkSmartPointer m_LevelWindowFilter; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage(); }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); /** \brief This method switches between different rendering modes (e.g. use a lookup table or a transfer function). * Detailed documentation about the modes can be found here: \link mitk::RenderingerModeProperty \endlink */ void ApplyRenderingMode(mitk::BaseRenderer *renderer); protected: /** \brief Transforms the actor to the actual position in 3D. * \param renderer The current renderer corresponding to the render window. */ void TransformActor(mitk::BaseRenderer* renderer); /** \brief Generates a plane according to the size of the resliced image in milimeters. * * \image html texturedPlane.png * * In VTK a vtkPlaneSource is defined through three points. The origin and two * points defining the axes of the plane (see VTK documentation). The origin is * set to (xMin; yMin; Z), where xMin and yMin are the minimal bounds of the * resliced image in space. Z is relevant for blending and the layer property. * The center of the plane (C) is also the center of the view plane (cf. the image above). * * \note For the standard MITK view with three 2D render windows showing three * different slices, three such planes are generated. All these planes are generated * in the XY-plane (even if they depict a YZ-slice of the volume). * */ void GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]); /** \brief Generates a vtkPolyData object containing the outline of a given binary slice. \param renderer: Pointer to the renderer containing the needed information \note This code is based on code from the iil library. */ vtkSmartPointer CreateOutlinePolyData(mitk::BaseRenderer* renderer); /** Default constructor */ ImageVtkMapper2D(); /** Default deconstructor */ virtual ~ImageVtkMapper2D(); /** \brief Does the actual resampling, without rendering the image yet. * All the data is generated inside this method. The vtkProp (or Actor) * is filled with content (i.e. the resliced image). * * After generation, a 4x4 transformation matrix(t) of the current slice is obtained * from the vtkResliceImage object via GetReslicesAxis(). This matrix is * applied to each textured plane (actor->SetUserTransform(t)) to transform everything * to the actual 3D position (cf. the following image). * * \image html cameraPositioning3D.png * */ virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer); /** \brief This method uses the vtkCamera clipping range and the layer property * to calcualte the depth of the object (e.g. image or contour). The depth is used * to keep the correct order for the final VTK rendering.*/ float CalculateLayerDepth(mitk::BaseRenderer* renderer); /** \brief This method applies (or modifies) the lookuptable for all types of images. * \warning To use the lookup table, the property 'Lookup Table' must be set and a 'Image Rendering.Mode' * which uses the lookup table must be set. */ void ApplyLookuptable(mitk::BaseRenderer* renderer); /** \brief This method applies a color transfer function. * Internally, a vtkColorTransferFunction is used. This is usefull for coloring continous * images (e.g. float) * \warning To use the color transfer function, the property 'Image Rendering.Transfer Function' must be set and a 'Image Rendering.Mode' which uses the color transfer function must be set. */ void ApplyColorTransferFunction(mitk::BaseRenderer* renderer); /** * @brief ApplyLevelWindow Apply the level window for the given renderer. * \warning To use the level window, the property 'LevelWindow' must be set and a 'Image Rendering.Mode' which uses the level window must be set. * @param renderer Level window for which renderer? */ void ApplyLevelWindow(mitk::BaseRenderer* renderer); /** \brief Set the color of the image/polydata */ void ApplyColor( mitk::BaseRenderer* renderer ); + /** \brief Set the shader of the image/polydata */ + void ApplyShader( mitk::BaseRenderer* renderer ); + /** \brief Set the opacity of the actor. */ void ApplyOpacity( mitk::BaseRenderer* renderer ); /** * \brief Calculates whether the given rendering geometry intersects the * given SlicedGeometry3D. * * This method checks if the given Geometry2D intersects the given * SlicedGeometry3D. It calculates the distance of the Geometry2D to all * 8 cornerpoints of the SlicedGeometry3D. If all distances have the same * sign (all positive or all negative) there is no intersection. * If the distances have different sign, there is an intersection. **/ bool RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry ); }; } // namespace mitk #endif /* MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E */ diff --git a/Core/Code/Rendering/vtkMitkShaderTexture.cpp b/Core/Code/Rendering/vtkMitkShaderTexture.cpp new file mode 100644 index 0000000000..39a0dc8387 --- /dev/null +++ b/Core/Code/Rendering/vtkMitkShaderTexture.cpp @@ -0,0 +1,514 @@ +/*=================================================================== + +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 "vtkMitkShaderTexture.h" + +#include "vtkHomogeneousTransform.h" +#include "vtkImageData.h" +#include "vtkLookupTable.h" +#include "vtkObjectFactory.h" +#include "vtkOpenGLRenderer.h" +#include "vtkPointData.h" +#include "vtkRenderWindow.h" +#include "vtkOpenGLExtensionManager.h" +#include "vtkOpenGLRenderWindow.h" +#include "vtkTransform.h" +#include "vtkPixelBufferObject.h" +#include "vtkOpenGL.h" +#include "vtkUnsignedShortArray.h" +#include "vtkFloatArray.h" +#include "vtkgl.h" // vtkgl namespace +//#include "GL/glext.h" + +#include + +#ifndef VTK_IMPLEMENT_MESA_CXX +vtkStandardNewMacro(vtkMitkShaderTexture); +#endif + +void vtkMitkShaderTexture::SetLevelWindow(float lower, float upper) +{ + this->LevelWindowEnabled = true; + this->LevelWindowLower = lower; + this->LevelWindowUpper = upper; + if(this->Index) + { + glBindTexture(GL_TEXTURE_2D, this->Index); +#ifdef MES_MOBILE_BUILD + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LW_LOWER, this->LevelWindowLower); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LW_UPPER, this->LevelWindowUpper); +#endif + } +} + + +// ---------------------------------------------------------------------------- +// Initializes an instance, generates a unique index. +vtkMitkShaderTexture::vtkMitkShaderTexture() +{ + this->Index = 0; + this->RenderWindow = 0; + this->LevelWindowEnabled = false; + this->LevelWindowLower = 0.0f; + this->LevelWindowUpper = 0.0f; + + this->Format16BIT = false; + + MapColorScalarsThroughLookupTable = 0; +} + +// ---------------------------------------------------------------------------- +vtkMitkShaderTexture::~vtkMitkShaderTexture() +{ + if (this->RenderWindow) + { + this->ReleaseGraphicsResources(this->RenderWindow); + } + this->RenderWindow = NULL; +} + +// ---------------------------------------------------------------------------- +void vtkMitkShaderTexture::Initialize(vtkRenderer * vtkNotUsed(ren)) +{ +} + +// ---------------------------------------------------------------------------- +// Release the graphics resources used by this texture. +void vtkMitkShaderTexture::ReleaseGraphicsResources(vtkWindow *renWin) +{ + if (this->Index && renWin && renWin->GetMapped()) + { + static_cast(renWin)->MakeCurrent(); + + // free any textures + if (glIsTexture(static_cast(this->Index))) + { + GLuint tempIndex; + tempIndex = this->Index; + // NOTE: Sun's OpenGL seems to require disabling of texture before delete + glDisable(GL_TEXTURE_2D); + glDeleteTextures(1, &tempIndex); + } + } + this->Index = 0; + this->RenderWindow = NULL; + this->Modified(); +} + +// ---------------------------------------------------------------------------- +// Implement base class method. +void vtkMitkShaderTexture::Load(vtkRenderer *ren) +{ + GLenum format = GL_LUMINANCE; + vtkImageData *input = this->GetInput(); + + this->Initialize(ren); + + // Need to reload the texture. + // There used to be a check on the render window's mtime, but + // this is too broad of a check (e.g. it would cause all textures + // to load when only the desired update rate changed). + // If a better check is required, check something more specific, + // like the graphics context. +// vtkOpenGLRenderWindow* renWin = +// static_cast(ren->GetRenderWindow()); + + if(this->BlendingMode != VTK_TEXTURE_BLENDING_MODE_NONE + && vtkgl::ActiveTexture) + { + glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, vtkgl::COMBINE); + + switch(this->BlendingMode) + { + case VTK_TEXTURE_BLENDING_MODE_REPLACE: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); + break; + } + case VTK_TEXTURE_BLENDING_MODE_MODULATE: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_MODULATE); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_MODULATE); + break; + } + case VTK_TEXTURE_BLENDING_MODE_ADD: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_ADD); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_ADD); + break; + } + case VTK_TEXTURE_BLENDING_MODE_ADD_SIGNED: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::ADD_SIGNED); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::ADD_SIGNED); + break; + } + case VTK_TEXTURE_BLENDING_MODE_INTERPOLATE: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::INTERPOLATE); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::INTERPOLATE); + break; + } + case VTK_TEXTURE_BLENDING_MODE_SUBTRACT: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, vtkgl::SUBTRACT); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, vtkgl::SUBTRACT); + break; + } + default: + { + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_ADD); + glTexEnvf (GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_ADD); + } + } + } + + if (this->GetMTime() > this->LoadTime.GetMTime() || + input->GetMTime() > this->LoadTime.GetMTime() || + (this->GetLookupTable() && this->GetLookupTable()->GetMTime () > this->LoadTime.GetMTime()) ) + { + int size[3]; + vtkDataArray *scalars; + float *floatPtr; + float *floatData=NULL; + int xsize, ysize; + GLuint tempIndex=0; + + scalars = this->GetInputArrayToProcess(0, input); + + if (!scalars) + { + vtkErrorMacro(<< "No scalar values found for texture input!"); + return; + } + + input->GetDimensions(size); + + if (input->GetNumberOfCells() == scalars->GetNumberOfTuples()) + { + // we are using cell scalars. Adjust image size for cells. + for (int kk=0; kk < 3; kk++) + { + if (size[kk]>1) + { + size[kk]--; + } + } + } + + // we only support 2d texture maps right now so one of the three sizes must be 1, + // but it could be any of them, so lets find it + if (size[0] == 1) + { + xsize = size[1]; + ysize = size[2]; + } + else + { + xsize = size[0]; + if (size[1] == 1) + { + ysize = size[2]; + } + else + { + ysize = size[1]; + if (size[2] != 1) + { + vtkErrorMacro(<< "3D texture maps currently are not supported!"); + return; + } + } + } + +// numChannels = scalars->GetNumberOfComponents(); + + this->Interpolate = 1; + + if (scalars->GetDataType() == VTK_FLOAT) + { + floatData = new float[xsize*ysize]; + floatPtr = reinterpret_cast(static_cast(scalars)->GetPointer(0)); + floatData = floatPtr; + } + + // -- decide whether the texture needs to be resampled -- + + GLint maxDimGL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL); + // if larger than permitted by the graphics library then must resample + bool resampleNeeded=xsize > maxDimGL || ysize > maxDimGL; + if(resampleNeeded) + { + vtkDebugMacro( "Texture too big for gl, maximum is " << maxDimGL); + } + + // free any old display lists (from the old context) + this->RenderWindow = ren->GetRenderWindow(); + + // make the new context current before we mess with opengl + this->RenderWindow->MakeCurrent(); + + // define a display list for this texture + // get a unique display list id + + if(!this->Index) + { + glGenTextures(1, &tempIndex); + this->Index = static_cast(tempIndex); + } + glBindTexture(GL_TEXTURE_2D, this->Index); + + if (this->Interpolate) + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_LINEAR ); + } + else + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + } + if (this->Repeat) + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); + } + else + { + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + vtkgl::CLAMP_TO_EDGE ); + glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, + vtkgl::CLAMP_TO_EDGE ); + } + +// int internalFormat = GL_LUMINANCE32F_ARB; + int internalFormat = 0; + format = GL_LUMINANCE; + + glTexImage2D( GL_TEXTURE_2D, 0 , internalFormat, + xsize, ysize, 0, format, + GL_FLOAT, + static_cast(floatData) ); + + this->Format16BIT = false; + + + // modify the load time to the current time + this->LoadTime.Modified(); + + // free memory + if (floatData != floatPtr) + { + delete [] floatData; + } + } + + // execute the display list that uses creates the texture + glBindTexture(GL_TEXTURE_2D, this->Index); + + if (this->LevelWindowEnabled) + { +#ifdef MES_MOBILE_BUILD + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LW_LOWER, this->LevelWindowLower); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LW_UPPER, this->LevelWindowUpper); +#endif + } + + // don't accept fragments if they have zero opacity. this will stop the + // zbuffer from be blocked by totally transparent texture fragments. + glAlphaFunc (GL_GREATER, static_cast(0)); + glEnable (GL_ALPHA_TEST); + + if (this->PremultipliedAlpha) + { + // save the blend function. + glPushAttrib(GL_COLOR_BUFFER_BIT); + + // make the blend function correct for textures premultiplied by alpha. + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } + + // now bind it + glEnable(GL_TEXTURE_2D); + + // clear any texture transform + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + // build transformation + if (this->Transform) + { + double *mat = this->Transform->GetMatrix()->Element[0]; + double mat2[16]; + mat2[0] = mat[0]; + mat2[1] = mat[4]; + mat2[2] = mat[8]; + mat2[3] = mat[12]; + mat2[4] = mat[1]; + mat2[5] = mat[5]; + mat2[6] = mat[9]; + mat2[7] = mat[13]; + mat2[8] = mat[2]; + mat2[9] = mat[6]; + mat2[10] = mat[10]; + mat2[11] = mat[14]; + mat2[12] = mat[3]; + mat2[13] = mat[7]; + mat2[14] = mat[11]; + mat2[15] = mat[15]; + + // insert texture transformation + glMultMatrixd(mat2); + } + glMatrixMode(GL_MODELVIEW); + +} + +// ---------------------------------------------------------------------------- +void vtkMitkShaderTexture::PostRender(vtkRenderer *vtkNotUsed(ren)) +{ + if (this->GetInput() && this->PremultipliedAlpha) + { + // restore the blend function + glPopAttrib(); + } +} + +// ---------------------------------------------------------------------------- +static int FindPowerOfTwo(int i) +{ + int size; + + for ( i--, size=1; i > 0; size*=2 ) + { + i /= 2; + } + + // [these lines added by Tim Hutton (implementing Joris Vanden Wyngaerd's + // suggestions)] + // limit the size of the texture to the maximum allowed by OpenGL + // (slightly more graceful than texture failing but not ideal) + GLint maxDimGL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxDimGL); + if ( size > maxDimGL ) + { + size = maxDimGL ; + } + // end of Tim's additions + + return size; +} + +// ---------------------------------------------------------------------------- +// Creates resampled unsigned char texture map that is a power of two in both +// x and y. +template +T *vtkMitkShaderTexture::ResampleToPowerOfTwo(int &xs, + int &ys, + T *dptr, + int numChannels) +{ + T *tptr, *p, *p1, *p2, *p3, *p4; + int xsize, ysize, i, j, k, jOffset, iIdx, jIdx; + double pcoords[3], hx, hy, rm, sm, w0, w1, w2, w3; + + xsize = FindPowerOfTwo(xs); + ysize = FindPowerOfTwo(ys); + if (this->RestrictPowerOf2ImageSmaller) + { + if (xsize > xs) + { + xsize /= 2; + } + if (ysize > ys) + { + ysize /= 2; + } + } + hx = xsize > 1 ? (xs - 1.0) / (xsize - 1.0) : 0; + hy = ysize > 1 ? (ys - 1.0) / (ysize - 1.0) : 0; + + tptr = p = new T[xsize*ysize*numChannels]; + + // Resample from the previous image. Compute parametric coordinates and + // interpolate + for (j=0; j < ysize; j++) + { + pcoords[1] = j*hy; + + jIdx = static_cast(pcoords[1]); + if ( jIdx >= (ys-1) ) //make sure to interpolate correctly at edge + { + jIdx = ys - 2; + pcoords[1] = 1.0; + } + else + { + pcoords[1] = pcoords[1] - jIdx; + } + jOffset = jIdx*xs; + sm = 1.0 - pcoords[1]; + + for (i=0; i < xsize; i++) + { + pcoords[0] = i*hx; + iIdx = static_cast(pcoords[0]); + if ( iIdx >= (xs-1) ) + { + iIdx = xs - 2; + pcoords[0] = 1.0; + } + else + { + pcoords[0] = pcoords[0] - iIdx; + } + rm = 1.0 - pcoords[0]; + + // Get pointers to 4 surrounding pixels + p1 = dptr + numChannels*(iIdx + jOffset); + p2 = p1 + numChannels; + p3 = p1 + numChannels*xs; + p4 = p3 + numChannels; + + // Compute interpolation weights interpolate components + w0 = rm*sm; + w1 = pcoords[0]*sm; + w2 = rm*pcoords[1]; + w3 = pcoords[0]*pcoords[1]; + for (k=0; k < numChannels; k++) + { + *p++ = static_cast(p1[k]*w0 + p2[k]*w1 + p3[k]*w2 + + p4[k]*w3); + } + } + } + + xs = xsize; + ys = ysize; + + return tptr; +} + +// ---------------------------------------------------------------------------- +void vtkMitkShaderTexture::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os,indent); + os << indent << "Index: " << this->Index << endl; +} diff --git a/Core/Code/Rendering/vtkMitkShaderTexture.h b/Core/Code/Rendering/vtkMitkShaderTexture.h new file mode 100644 index 0000000000..4c9c84f8f4 --- /dev/null +++ b/Core/Code/Rendering/vtkMitkShaderTexture.h @@ -0,0 +1,94 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// .NAME vtkMitkShaderTexture - OpenGL texture map +// .SECTION Description +// vtkMitkShaderTexture is a concrete implementation of the abstract class +// vtkTexture. vtkMitkShaderTexture interfaces to the OpenGL rendering library. + +#ifndef __vtkMesOpenGLTexture_h +#define __vtkMesOpenGLTexture_h + +#include "vtkTexture.h" +//BTX +#include "vtkWeakPointer.h" // needed for vtkWeakPointer. +//ETX + +class vtkWindow; +class vtkOpenGLRenderer; +class vtkRenderWindow; +class vtkPixelBufferObject; + +class vtkMitkShaderTexture : public vtkTexture +{ +public: + static vtkMitkShaderTexture *New(); + vtkTypeMacro(vtkMitkShaderTexture,vtkTexture); + virtual void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Implement base class method. + void Load(vtkRenderer *ren); + + // Descsription: + // Clean up after the rendering is complete. + virtual void PostRender(vtkRenderer *ren); + + // Description: + // Release any graphics resources that are being consumed by this texture. + // The parameter window could be used to determine which graphic + // resources to release. Using the same texture object in multiple + // render windows is NOT currently supported. + void ReleaseGraphicsResources(vtkWindow *); + + void SetLevelWindow(float lower, float upper); + + float GetLevelWindowLower() const { return LevelWindowLower; } + float GetLevelWindowUpper() const { return LevelWindowUpper; } + bool Is16Bit() const { return Format16BIT; } + // Description: + // Get the openGL texture name to which this texture is bound. + // This is available only if GL version >= 1.1 + vtkGetMacro(Index, long); +//BTX +protected: + vtkMitkShaderTexture(); + ~vtkMitkShaderTexture(); + + template + T *ResampleToPowerOfTwo(int &xsize, int &ysize, T *dptr, int numChannels); + + vtkTimeStamp LoadTime; + unsigned int Index; // actually GLuint + vtkWeakPointer RenderWindow; // RenderWindow used for previous render + + bool Format16BIT; + bool LevelWindowEnabled; + float LevelWindowLower; + float LevelWindowUpper; + +private: + vtkMitkShaderTexture(const vtkMitkShaderTexture&); // Not implemented. + void operator=(const vtkMitkShaderTexture&); // Not implemented. + + // Description: + // Handle loading in extension support + virtual void Initialize(vtkRenderer * ren); + +//ETX +}; + +#endif diff --git a/Core/Code/files.cmake b/Core/Code/files.cmake index 3525e7084f..f340568c70 100644 --- a/Core/Code/files.cmake +++ b/Core/Code/files.cmake @@ -1,406 +1,408 @@ set(H_FILES Algorithms/itkImportMitkImageContainer.h Algorithms/itkImportMitkImageContainer.txx Algorithms/itkMITKScalarImageToHistogramGenerator.h Algorithms/itkMITKScalarImageToHistogramGenerator.txx Algorithms/mitkInstantiateAccessFunctions.h Algorithms/mitkPixelTypeList.h Algorithms/mitkPPArithmeticDec.h Algorithms/mitkPPArgCount.h Algorithms/mitkPPCat.h Algorithms/mitkPPConfig.h Algorithms/mitkPPControlExprIIf.h Algorithms/mitkPPControlIf.h Algorithms/mitkPPControlIIf.h Algorithms/mitkPPDebugError.h Algorithms/mitkPPDetailAutoRec.h Algorithms/mitkPPDetailDMCAutoRec.h Algorithms/mitkPPExpand.h Algorithms/mitkPPFacilitiesEmpty.h Algorithms/mitkPPFacilitiesExpand.h Algorithms/mitkPPLogicalBool.h Algorithms/mitkPPRepetitionDetailDMCFor.h Algorithms/mitkPPRepetitionDetailEDGFor.h Algorithms/mitkPPRepetitionDetailFor.h Algorithms/mitkPPRepetitionDetailMSVCFor.h Algorithms/mitkPPRepetitionFor.h Algorithms/mitkPPSeqElem.h Algorithms/mitkPPSeqForEach.h Algorithms/mitkPPSeqForEachProduct.h Algorithms/mitkPPSeq.h Algorithms/mitkPPSeqEnum.h Algorithms/mitkPPSeqSize.h Algorithms/mitkPPSeqToTuple.h Algorithms/mitkPPStringize.h Algorithms/mitkPPTupleEat.h Algorithms/mitkPPTupleElem.h Algorithms/mitkPPTupleRem.h Algorithms/mitkClippedSurfaceBoundsCalculator.h Algorithms/mitkExtractSliceFilter.h Algorithms/mitkConvert2Dto3DImageFilter.h Algorithms/mitkPlaneClipping.h Common/mitkCommon.h Common/mitkExceptionMacro.h DataManagement/mitkProportionalTimeGeometry.h DataManagement/mitkTimeGeometry.h DataManagement/mitkImageAccessByItk.h DataManagement/mitkImageCast.h DataManagement/mitkImagePixelAccessor.h DataManagement/mitkImagePixelReadAccessor.h DataManagement/mitkImagePixelWriteAccessor.h DataManagement/mitkImageReadAccessor.h DataManagement/mitkImageWriteAccessor.h DataManagement/mitkITKImageImport.h DataManagement/mitkITKImageImport.txx DataManagement/mitkImageToItk.h DataManagement/mitkShaderProperty.h DataManagement/mitkImageToItk.txx DataManagement/mitkTimeSlicedGeometry.h # Deprecated, empty for compatibilty reasons. DataManagement/mitkPropertyListReplacedObserver.cpp Interactions/mitkEventMapperAddOn.h Interfaces/mitkIDataNodeReader.h Rendering/mitkLocalStorageHandler.h Rendering/Colortables/HotIron.h Rendering/Colortables/Jet.h Rendering/Colortables/PET20.h Rendering/Colortables/PETColor.h IO/mitkPixelTypeTraits.h ) set(CPP_FILES Algorithms/mitkBaseDataSource.cpp Algorithms/mitkCompareImageDataFilter.cpp Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkImageToSurfaceFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToImageFilter.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkExtractSliceFilter.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkCoreActivator.cpp Controllers/mitkFocusManager.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkSlicesRotator.cpp Controllers/mitkSlicesSwiveller.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkInteractorCameraController.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkProportionalTimeGeometry.cpp DataManagement/mitkTimeGeometry.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataStorage.cpp # DataManagement/mitkDataTree.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataNodeFactory.cpp # DataManagement/mitkDataTreeStorage.cpp DataManagement/mitkDisplayGeometry.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkGeometry2D.cpp DataManagement/mitkGeometry2DData.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkLandmarkBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModeOperation.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkPropertyObserver.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkApplyTransformMatrixOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStateTransitionOperation.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkVector.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkRenderingModeProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkMaterial.cpp DataManagement/mitkPointSetShapeProperty.cpp DataManagement/mitkFloatPropertyExtension.cpp DataManagement/mitkIntPropertyExtension.cpp DataManagement/mitkPropertyExtension.cpp DataManagement/mitkPropertyFilter.cpp DataManagement/mitkPropertyAliases.cpp DataManagement/mitkPropertyDescriptions.cpp DataManagement/mitkPropertyExtensions.cpp DataManagement/mitkPropertyFilters.cpp DataManagement/mitkShaderProperty.cpp Interactions/mitkAction.cpp Interactions/mitkAffineInteractor.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkCoordinateSupplier.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkDisplayPositionEvent.cpp # Interactions/mitkDisplayVectorInteractorLevelWindow.cpp # legacy, prob even now unneeded # Interactions/mitkDisplayVectorInteractorScroll.cpp Interactions/mitkEvent.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventDescription.cpp Interactions/mitkEventFactory.cpp Interactions/mitkInteractionEventHandler.cpp Interactions/mitkEventMapper.cpp Interactions/mitkEventRecorder.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkGlobalInteraction.cpp Interactions/mitkInteractor.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionEventConst.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkMouseDoubleClickEvent.cpp Interactions/mitkMouseModeSwitcher.cpp Interactions/mitkMouseMovePointSetInteractor.cpp Interactions/mitkMoveBaseDataInteractor.cpp Interactions/mitkNodeDepententPointSetInteractor.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkPointSetInteractor.cpp Interactions/mitkPositionEvent.cpp Interactions/mitkPositionTracker.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineCondition.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkState.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateEvent.cpp Interactions/mitkStateMachine.cpp Interactions/mitkStateMachineFactory.cpp Interactions/mitkTransition.cpp Interactions/mitkWheelEvent.cpp Interactions/mitkKeyEvent.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkCrosshairPositionEvent.cpp Interactions/mitkXML2EventParser.cpp Interfaces/mitkInteractionEventObserver.cpp Interfaces/mitkIShaderRepository.cpp Interfaces/mitkIPropertyAliases.cpp Interfaces/mitkIPropertyDescriptions.cpp Interfaces/mitkIPropertyExtensions.cpp Interfaces/mitkIPropertyFilters.cpp Interfaces/mitkIPersistenceService.cpp IO/mitkBaseDataIOFactory.cpp IO/mitkCoreDataNodeReader.cpp IO/mitkDicomSeriesReader.cpp IO/mitkDicomSR_LoadDICOMScalar.cpp IO/mitkDicomSR_LoadDICOMScalar4D.cpp IO/mitkDicomSR_LoadDICOMRGBPixel.cpp IO/mitkDicomSR_LoadDICOMRGBPixel4D.cpp IO/mitkDicomSR_ImageBlockDescriptor.cpp IO/mitkDicomSR_GantryTiltInformation.cpp IO/mitkDicomSR_SliceGroupingResult.cpp IO/mitkFileReader.cpp IO/mitkFileSeriesReader.cpp IO/mitkFileWriter.cpp # IO/mitkIpPicGet.c IO/mitkImageGenerator.cpp IO/mitkImageWriter.cpp IO/mitkImageWriterFactory.cpp IO/mitkItkImageFileIOFactory.cpp IO/mitkItkImageFileReader.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkItkPictureWrite.cpp IO/mitkIOUtil.cpp IO/mitkLookupTableProperty.cpp IO/mitkOperation.cpp # IO/mitkPicFileIOFactory.cpp # IO/mitkPicFileReader.cpp # IO/mitkPicFileWriter.cpp # IO/mitkPicHelper.cpp # IO/mitkPicVolumeTimeSeriesIOFactory.cpp # IO/mitkPicVolumeTimeSeriesReader.cpp IO/mitkPixelType.cpp IO/mitkPointSetIOFactory.cpp IO/mitkPointSetReader.cpp IO/mitkPointSetWriter.cpp IO/mitkPointSetWriterFactory.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSTLFileIOFactory.cpp IO/mitkSTLFileReader.cpp IO/mitkSurfaceVtkWriter.cpp IO/mitkSurfaceVtkWriterFactory.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkVtiFileIOFactory.cpp IO/mitkVtiFileReader.cpp IO/mitkVtkImageIOFactory.cpp IO/mitkVtkImageReader.cpp IO/mitkVtkSurfaceIOFactory.cpp IO/mitkVtkSurfaceReader.cpp IO/vtkPointSetXMLParser.cpp IO/mitkLog.cpp Rendering/mitkBaseRenderer.cpp Rendering/mitkVtkMapper.cpp Rendering/mitkRenderWindowFrame.cpp Rendering/mitkGeometry2DDataMapper2D.cpp Rendering/mitkGeometry2DDataVtkMapper3D.cpp Rendering/mitkGLMapper.cpp Rendering/mitkGradientBackground.cpp Rendering/mitkManufacturerLogo.cpp Rendering/mitkMapper.cpp Rendering/mitkPointSetGLMapper2D.cpp Rendering/mitkPointSetVtkMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkPolyDataGLMapper2D.cpp Rendering/mitkSurfaceGLMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVolumeDataVtkMapper3D.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp + Rendering/vtkMitkShaderTexture.cpp + Rendering/mitkOverlay.cpp Rendering/mitkVtkOverlay.cpp Rendering/mitkVtkOverlay2D.cpp Rendering/mitkVtkOverlay3D.cpp Rendering/mitkOverlayManager.cpp Rendering/mitkAbstractOverlayLayouter.cpp Rendering/mitkTextOverlay2D.cpp Rendering/mitkTextOverlay3D.cpp Rendering/mitkLabelOverlay3D.cpp Rendering/mitkOverlay2DLayouter.cpp Rendering/mitkScaleLegendOverlay Common/mitkException.cpp Common/mitkCommon.h Common/mitkCoreObjectFactoryBase.cpp Common/mitkCoreObjectFactory.cpp Common/mitkCoreServices.cpp ) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfig.xml Interactions/DisplayConfigPACS.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigMITK.xml Interactions/PointSet.xml Interactions/Legacy/StateMachine.xml Interactions/Legacy/DisplayConfigMITKTools.xml Interactions/PointSetConfig.xml mitkLevelWindowPresets.xml ) diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index 04af24e273..386bffa6ca 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -1,78 +1,80 @@ # Modules must be listed according to their dependencies set(module_dirs DataTypesExt AlgorithmsExt MapperExt IOExt Qt4Qt5TestModule SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction ImageStatistics LegacyAdaptors IpPicSupport Ext SceneSerialization GraphAlgorithms ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation OpenViewCore QmlItems QtWidgets QtWidgetsExt SegmentationUI DiffusionImaging GPGPU IGTBase IGT CameraCalibration IGTUI RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCL OpenCVVideoSupport Overlays InputDevices ToFHardware ToFProcessing ToFUI US ClippingTools USUI DicomUI Simulation Remeshing Python Persistence VtkShaders + DicomRT + RTUI ) if(MITK_ENABLE_PIC_READER) list(APPEND module_dirs IpPicSupportIO) endif() set(MITK_DEFAULT_SUBPROJECTS MITK-Modules) foreach(module_dir ${module_dirs}) add_subdirectory(${module_dir}) endforeach() if(MITK_PRIVATE_MODULES) file(GLOB all_subdirs RELATIVE ${MITK_PRIVATE_MODULES} ${MITK_PRIVATE_MODULES}/*) foreach(subdir ${all_subdirs}) string(FIND ${subdir} "." _result) if(_result EQUAL -1) if(EXISTS ${MITK_PRIVATE_MODULES}/${subdir}/CMakeLists.txt) message(STATUS "Found private module ${subdir}") add_subdirectory(${MITK_PRIVATE_MODULES}/${subdir} private_modules/${subdir}) endif() endif() endforeach() endif(MITK_PRIVATE_MODULES) diff --git a/Modules/ContourModel/Rendering/mitkContourModelGLMapper2D.cpp b/Modules/ContourModel/Rendering/mitkContourModelGLMapper2D.cpp index 0421c4beda..fd5e2fe0f4 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelGLMapper2D.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelGLMapper2D.cpp @@ -1,106 +1,114 @@ /*=================================================================== 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 "mitkContourModelGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkContourModel.h" #include "mitkContourModelSubDivisionFilter.h" #include +#include +#include #include "mitkGL.h" mitk::ContourModelGLMapper2D::ContourModelGLMapper2D() : m_SubdivisionContour(mitk::ContourModel::New()), m_InitSubdivisionCurve(true) { } mitk::ContourModelGLMapper2D::~ContourModelGLMapper2D() { } void mitk::ContourModelGLMapper2D::Paint(mitk::BaseRenderer * renderer) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); mitk::DataNode* dataNode = this->GetDataNode(); bool visible = true; dataNode->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::ContourModel* input = this->GetInput(); mitk::ContourModel::Pointer renderingContour = input; bool subdivision = false; dataNode->GetBoolProperty( "subdivision curve", subdivision, renderer ); if (subdivision) { if(this->m_SubdivisionContour->GetMTime() < renderingContour->GetMTime() || m_InitSubdivisionCurve) { //mitk::ContourModel::Pointer subdivContour = mitk::ContourModel::New(); mitk::ContourModelSubDivisionFilter::Pointer subdivFilter = mitk::ContourModelSubDivisionFilter::New(); subdivFilter->SetInput(input); subdivFilter->Update(); this->m_SubdivisionContour = subdivFilter->GetOutput(); m_InitSubdivisionCurve = false; } renderingContour = this->m_SubdivisionContour; } this->DrawContour(renderingContour, renderer); ls->UpdateGenerateDataTime(); } mitk::ContourModel* mitk::ContourModelGLMapper2D::GetInput(void) { return const_cast< mitk::ContourModel* >(static_cast< const mitk::ContourModel* > ( GetDataNode()->GetData() )); } void mitk::ContourModelGLMapper2D::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( "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( "subdivision curve", 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 ); + IPropertyAliases* aliases = CoreServices::GetPropertyAliases(); + + if(aliases != NULL) + { + aliases->AddAlias("color", "contour.color", "ContourModel"); + } + Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/ContourModel/Rendering/mitkContourModelGLMapper2DBase.cpp b/Modules/ContourModel/Rendering/mitkContourModelGLMapper2DBase.cpp index 073936ea1e..b1f75b335d 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelGLMapper2DBase.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelGLMapper2DBase.cpp @@ -1,329 +1,329 @@ /*=================================================================== 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 "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkContourModelSet.h" #include #include "mitkGL.h" mitk::ContourModelGLMapper2DBase::ContourModelGLMapper2DBase() { } mitk::ContourModelGLMapper2DBase::~ContourModelGLMapper2DBase() { } void mitk::ContourModelGLMapper2DBase::DrawContour(mitk::ContourModel* renderingContour, mitk::BaseRenderer* renderer) { if(!renderingContour) return; mitk::DataNode* dataNode = this->GetDataNode(); renderingContour->UpdateOutputInformation(); unsigned int timestep = renderer->GetTimeStep(); if ( !renderingContour->IsEmptyTimeStep(timestep) ) { mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //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, projected_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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetNorm(); //project to plane if(projectmode) { drawit=true; } else if(scalardiffIteratorBegin(timestep)) ) { glLineWidth(lineWidth); glBegin (GL_LINES); glVertex2f(pt2d[0], pt2d[1]); glVertex2f(lastPt2d[0], lastPt2d[1]); glEnd(); glLineWidth(1); } } if (showControlPoints) { //draw ontrol 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()); + glColor3f(color[0],color[1],color[2]); 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()); + glColor3f(color[0],color[1],color[2]); 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()); mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); float rgb[3]; rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0; OpenGLrenderer->WriteSimpleText(l, pt2d[0] + 2, pt2d[1] + 2,rgb[0], rgb[1],rgb[2]); } if (showControlPointsNumbers && (*pointsIt)->IsControlPoint) { std::string l; std::stringstream ss; ss << index; l.append(ss.str()); mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); float rgb[3]; rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 0.0; OpenGLrenderer->WriteSimpleText(l, pt2d[0] + 2, pt2d[1] + 2,rgb[0], rgb[1],rgb[2]); } 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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, 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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetNorm(); //---------------------------------- //draw point if close to plane if(scalardiff #include #include #include #include #include #include #include #include #include #include +#include +#include mitk::ContourModelMapper2D::ContourModelMapper2D() { } mitk::ContourModelMapper2D::~ContourModelMapper2D() { } const mitk::ContourModel* mitk::ContourModelMapper2D::GetInput( void ) { //convient way to get the data from the dataNode return static_cast< const mitk::ContourModel * >( GetDataNode()->GetData() ); } vtkProp* mitk::ContourModelMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actor; } void mitk::ContourModelMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { /*++ convert the contour to vtkPolyData and set it as input for our mapper ++*/ LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( GetDataNode()->GetData() ); unsigned int timestep = renderer->GetTimeStep(); //if there's something to be rendered if( inputContour->GetNumberOfVertices(timestep) > 0) { localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour, renderer); } this->ApplyContourProperties(renderer); localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData); } void mitk::ContourModelMapper2D::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; //check if there is something to be rendered mitk::ContourModel* data = static_cast< mitk::ContourModel*>( 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); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( renderer->GetTimeStep() ) ) ) { //clear the rendered polydata localStorage->m_Mapper->RemoveAllInputs();//SetInput(vtkSmartPointer::New()); 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->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->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::ContourModelMapper2D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour, mitk::BaseRenderer* renderer) { unsigned int timestep = this->GetTimestep(); // Create a polydata to store everything in vtkSmartPointer resultingPolyData = vtkSmartPointer::New(); //check for the worldgeometry from the current render window mitk::PlaneGeometry* currentWorldGeometry = dynamic_cast( const_cast(renderer->GetCurrentWorldGeometry2D())); if(currentWorldGeometry) { //origin and normal of vtkPlane mitk::Point3D origin = currentWorldGeometry->GetOrigin(); mitk::Vector3D normal = currentWorldGeometry->GetNormal(); //the implicit function to slice through the polyData vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetOrigin(origin[0], origin[1], origin[2]); plane->SetNormal(normal[0], normal[1], normal[2]); /* First of all convert the control points of the contourModel to vtk points * and add lines in between them */ //the points to draw vtkSmartPointer points = vtkSmartPointer::New(); //the lines to connect the points vtkSmartPointer lines = vtkSmartPointer::New(); // Create a polydata to store everything in vtkSmartPointer polyDataIn3D = vtkSmartPointer::New(); vtkSmartPointer appendPoly = vtkSmartPointer::New(); mitk::ContourModel::Pointer renderingContour = mitk::ContourModel::New(); renderingContour = inputContour; bool subdivision = false; this->GetDataNode()->GetBoolProperty( "subdivision curve", subdivision, renderer ); if (subdivision) { mitk::ContourModel::Pointer subdivContour = mitk::ContourModel::New(); mitk::ContourModelSubDivisionFilter::Pointer subdivFilter = mitk::ContourModelSubDivisionFilter::New(); subdivFilter->SetInput(inputContour); subdivFilter->Update(); subdivContour = subdivFilter->GetOutput(); if(subdivContour->GetNumberOfVertices() == 0 ) { subdivContour = inputContour; } renderingContour = subdivContour; } //iterate over all control points mitk::ContourModel::VertexIterator current = renderingContour->IteratorBegin(timestep); mitk::ContourModel::VertexIterator next = renderingContour->IteratorBegin(timestep); if(next != renderingContour->IteratorEnd(timestep)) { next++; mitk::ContourModel::VertexIterator end = renderingContour->IteratorEnd(timestep); while(next != end) { mitk::ContourModel::VertexType* currentControlPoint = *current; mitk::ContourModel::VertexType* nextControlPoint = *next; vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]); vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]); //add the line between both contorlPoints lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); if ( currentControlPoint->IsControlPoint ) { double coordinates[3]; coordinates[0] = currentControlPoint->Coordinates[0]; coordinates[1] = currentControlPoint->Coordinates[1]; coordinates[2] = currentControlPoint->Coordinates[2]; double distance = plane->DistanceToPlane(coordinates); if(distance < 0.1) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(1.2); sphere->SetCenter(coordinates[0], coordinates[1], coordinates[2]); sphere->Update(); appendPoly->AddInputConnection(sphere->GetOutputPort()); } } current++; next++; }//end while (it!=end) //check if last control point is enabled to draw it if ( (*current)->IsControlPoint ) { double coordinates[3]; coordinates[0] = (*current)->Coordinates[0]; coordinates[1] = (*current)->Coordinates[1]; coordinates[2] = (*current)->Coordinates[2]; double distance = plane->DistanceToPlane(coordinates); if(distance < 0.1) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(1.2); sphere->SetCenter(coordinates[0], coordinates[1], coordinates[2]); sphere->Update(); appendPoly->AddInputConnection(sphere->GetOutputPort()); } } /* If the contour is closed an additional line has to be created between the very first point * and the last point */ if(renderingContour->IsClosed(timestep)) { //add a line from the last to the first control point mitk::ContourModel::VertexType* firstControlPoint = *(renderingContour->IteratorBegin(timestep)); mitk::ContourModel::VertexType* lastControlPoint = *(--(renderingContour->IteratorEnd(timestep))); vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]); vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]); //add the line between both contorlPoints lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); }//end if(isClosed) // Add the points to the dataset polyDataIn3D->SetPoints(points); // Add the lines to the dataset polyDataIn3D->SetLines(lines); //cut through polyData bool useCuttingPlane = false; this->GetDataNode()->GetBoolProperty( "use cutting plane", useCuttingPlane, renderer ); if (useCuttingPlane) { //slice through the data to get a 2D representation of the (possible) 3D contour //needed because currently there is no outher solution if the contour is within the plane vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetInputData(polyDataIn3D); tubeFilter->SetRadius(0.05); //cuts through vtkPolyData with a given implicit function. In our case a plane vtkSmartPointer cutter = vtkSmartPointer::New(); cutter->SetCutFunction(plane); cutter->SetInputConnection(tubeFilter->GetOutputPort()); //we want the scalars of the input - so turn off generating the scalars within vtkCutter cutter->GenerateCutScalarsOff(); cutter->Update(); //set to 2D representation of the contour resultingPolyData= cutter->GetOutput(); }//end if(project contour) else { //set to 3D polyData resultingPolyData = polyDataIn3D; } }//end if (it != end) appendPoly->AddInputData(resultingPolyData); appendPoly->Update(); //return contour with control points return appendPoly->GetOutput(); }else { //return empty polyData return resultingPolyData; } } void mitk::ContourModelMapper2D::ApplyContourProperties(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float lineWidth(1.0); if (this->GetDataNode()->GetFloatProperty( "width", lineWidth, renderer )) { localStorage->m_Actor->GetProperty()->SetLineWidth(lineWidth); } - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty("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(); - localStorage->m_Actor->GetProperty()->SetColor(red, green, blue); - } + float color[3]; + this->GetDataNode()->GetColor(color, renderer); + localStorage->m_Actor->GetProperty()->SetColor(color[0], color[1], color[2]); //make sure that directional lighting isn't used for our contour localStorage->m_Actor->GetProperty()->SetAmbient(1.0); localStorage->m_Actor->GetProperty()->SetDiffuse(0.0); localStorage->m_Actor->GetProperty()->SetSpecular(0.0); } /*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/ mitk::ContourModelMapper2D::LocalStorage* mitk::ContourModelMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } mitk::ContourModelMapper2D::LocalStorage::LocalStorage() { m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); //set the mapper for the actor m_Actor->SetMapper(m_Mapper); } void mitk::ContourModelMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite ); node->AddProperty( "width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "use cutting plane", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty( "subdivision curve", mitk::BoolProperty::New( false ), renderer, overwrite ); + IPropertyAliases* aliases = CoreServices::GetPropertyAliases(); + + if(aliases != NULL) + { + aliases->AddAlias("color", "contour.color", "ContourModel"); + } + Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp b/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp index a38fe8ee8f..72f287b658 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelMapper3D.cpp @@ -1,243 +1,244 @@ /*=================================================================== 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 +#include mitk::ContourModelMapper3D::ContourModelMapper3D() { } mitk::ContourModelMapper3D::~ContourModelMapper3D() { } const mitk::ContourModel* mitk::ContourModelMapper3D::GetInput( void ) { //convient way to get the data from the dataNode return static_cast< const mitk::ContourModel * >( GetDataNode()->GetData() ); } vtkProp* mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actor; } void mitk::ContourModelMapper3D::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); mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( GetDataNode()->GetData() ); localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour); this->ApplyContourProperties(renderer); //tube filter the polyData localStorage->m_TubeFilter->SetInputData(localStorage->m_OutlinePolyData); float lineWidth(1.0); if (this->GetDataNode()->GetFloatProperty( "contour.3D.width", lineWidth, renderer )) { localStorage->m_TubeFilter->SetRadius(lineWidth); }else { localStorage->m_TubeFilter->SetRadius(0.5); } localStorage->m_TubeFilter->CappingOn(); localStorage->m_TubeFilter->SetNumberOfSides(10); localStorage->m_TubeFilter->Update(); localStorage->m_Mapper->SetInputConnection(localStorage->m_TubeFilter->GetOutputPort()); } void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); mitk::ContourModel* data = static_cast< mitk::ContourModel*>( 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); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( renderer->GetTimeStep() ) ) || ( this->GetTimestep() == -1 ) ) { //clear the rendered polydata localStorage->m_Mapper->SetInputData(vtkSmartPointer::New()); 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->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->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::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour) { unsigned int timestep = this->GetTimestep(); //the points to draw vtkSmartPointer points = vtkSmartPointer::New(); //the lines to connect the points vtkSmartPointer lines = vtkSmartPointer::New(); // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); //iterate over the control points mitk::ContourModel::VertexIterator current = inputContour->IteratorBegin(timestep); mitk::ContourModel::VertexIterator next = inputContour->IteratorBegin(timestep); if(next != inputContour->IteratorEnd(timestep)) { next++; mitk::ContourModel::VertexIterator end = inputContour->IteratorEnd(timestep); while(next != end) { mitk::ContourModel::VertexType* currentControlPoint = *current; mitk::ContourModel::VertexType* nextControlPoint = *next; if( !(currentControlPoint->Coordinates[0] == nextControlPoint->Coordinates[0] && currentControlPoint->Coordinates[1] == nextControlPoint->Coordinates[1] && currentControlPoint->Coordinates[2] == nextControlPoint->Coordinates[2])) { vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]); vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]); //add the line between both contorlPoints lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } current++; next++; } if(inputContour->IsClosed(timestep)) { // If the contour is closed add a line from the last to the first control point mitk::ContourModel::VertexType* firstControlPoint = *(inputContour->IteratorBegin(timestep)); mitk::ContourModel::VertexType* lastControlPoint = *(--(inputContour->IteratorEnd(timestep))); if( lastControlPoint->Coordinates[0] != firstControlPoint->Coordinates[0] || lastControlPoint->Coordinates[1] != firstControlPoint->Coordinates[1] || lastControlPoint->Coordinates[2] != firstControlPoint->Coordinates[2]) { vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]); vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]); //add the line to the cellArray lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } } // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); } return polyData; } void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + float color[3]; + this->GetDataNode()->GetColor(color, 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(); - localStorage->m_Actor->GetProperty()->SetColor(red, green, blue); - } + localStorage->m_Actor->GetProperty()->SetColor(color[0], color[1], color[2]); } /*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/ mitk::ContourModelMapper3D::LocalStorage* mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } mitk::ContourModelMapper3D::LocalStorage::LocalStorage() { m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_TubeFilter = vtkSmartPointer::New(); //set the mapper for the actor m_Actor->SetMapper(m_Mapper); } void mitk::ContourModelMapper3D::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 ); + IPropertyAliases* aliases = CoreServices::GetPropertyAliases(); + if(aliases != NULL) + { + aliases->AddAlias("color", "contour.color", "ContourModel"); + } + Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp b/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp index 667410a59c..341dd60195 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelSetGLMapper2D.cpp @@ -1,383 +1,391 @@ /*=================================================================== 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 "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkContourModelSet.h" #include +#include +#include #include "mitkGL.h" mitk::ContourModelSetGLMapper2D::ContourModelSetGLMapper2D() { } mitk::ContourModelSetGLMapper2D::~ContourModelSetGLMapper2D() { } void mitk::ContourModelSetGLMapper2D::Paint(mitk::BaseRenderer * renderer) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); mitk::DataNode* dataNode = this->GetDataNode(); bool visible = true; dataNode->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::ContourModelSet* input = this->GetInput(); mitk::ContourModelSet::ContourModelSetIterator it = input->Begin(); mitk::ContourModelSet::ContourModelSetIterator end = input->End(); while(it!=end) { this->DrawContour(it->GetPointer(), renderer); ++it; } if(input->GetSize() < 1) return; ls->UpdateGenerateDataTime(); } mitk::ContourModelSet* mitk::ContourModelSetGLMapper2D::GetInput(void) { return const_cast(static_cast ( GetDataNode()->GetData() )); } void mitk::ContourModelSetGLMapper2D::DrawContour(mitk::ContourModel* renderingContour, mitk::BaseRenderer* renderer) { if(!renderingContour) return; mitk::DataNode* dataNode = this->GetDataNode(); renderingContour->UpdateOutputInformation(); unsigned int timestep = renderer->GetTimeStep(); if ( !renderingContour->IsEmptyTimeStep(timestep) ) { mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //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, projected_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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetNorm(); //project to plane if(projectmode) { drawit=true; } else if(scalardiffIteratorBegin(timestep)) ) { glLineWidth(lineWidth); glBegin (GL_LINES); glVertex2f(pt2d[0], pt2d[1]); glVertex2f(lastPt2d[0], lastPt2d[1]); glEnd(); glLineWidth(1); } } if (showControlPoints) { //draw ontrol 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()); + glColor3f(color[0],color[1],color[2]); 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()); + glColor3f(color[0],color[1],color[2]); 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()); mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); float rgb[3]; rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0; OpenGLrenderer->WriteSimpleText(l, pt2d[0] + 2, pt2d[1] + 2,rgb[0], rgb[1],rgb[2]); } if (showControlPointsNumbers && (*pointsIt)->IsControlPoint) { std::string l; std::stringstream ss; ss << index; l.append(ss.str()); mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); float rgb[3]; rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 0.0; OpenGLrenderer->WriteSimpleText(l, pt2d[0] + 2, pt2d[1] + 2,rgb[0], rgb[1],rgb[2]); } 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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, 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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetNorm(); //---------------------------------- //draw point if close to plane if(scalardiffAddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite ); + node->AddProperty( "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 ); + IPropertyAliases* aliases = CoreServices::GetPropertyAliases(); + + if(aliases != NULL) + { + aliases->AddAlias("color", "contour.color", "ContourModelSet"); + } + Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp index 5de27d6f60..25174f4684 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp +++ b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.cpp @@ -1,206 +1,208 @@ /*=================================================================== 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 "mitkSurface.h" +#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 return static_cast< const mitk::ContourModelSet * >( 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); mitk::ContourModelSet* contourSet = static_cast< mitk::ContourModelSet* >( GetDataNode()->GetData() ); mitk::ContourModelSet::ContourModelSetIterator it = contourSet->Begin(); mitk::ContourModelSet::ContourModelSetIterator end = contourSet->End(); while(it!=end) { mitk::ContourModel* inputContour = it->GetPointer(); vtkSmartPointer polyData = this->CreateVtkPolyDataFromContour(inputContour, renderer); vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetInputData(polyData); float lineWidth(1.0); if (this->GetDataNode()->GetFloatProperty( "contour.3D.width", lineWidth, renderer )) { tubeFilter->SetRadius(lineWidth); }else { tubeFilter->SetRadius(0.5); } tubeFilter->CappingOn(); tubeFilter->SetNumberOfSides(10); tubeFilter->Update(); vtkSmartPointer mapper = vtkSmartPointer::New(); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); mapper->SetInputConnection(tubeFilter->GetOutputPort()); //mapper->SetInput(polyData); localStorage->m_Assembly->AddPart(actor); ++it; } - this->ApplyContourProperties(renderer); + this->ApplyColorAndOpacityProperties(renderer); } void mitk::ContourModelSetMapper3D::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); mitk::ContourModel* data = static_cast< mitk::ContourModel*>( 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->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->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::ApplyContourProperties(mitk::BaseRenderer* renderer) +void mitk::ContourModelSetMapper3D::ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor*) { + MITK_INFO << "ApplyColorAndOpacityProperties()"; + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + float color[3]; + this->GetDataNode()->GetColor(color, renderer); - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("contour.color", renderer)); - if(colorprop) + vtkSmartPointer collection = vtkSmartPointer::New(); + localStorage->m_Assembly->GetActors(collection); + collection->InitTraversal(); + for(vtkIdType i = 0; i < collection->GetNumberOfItems(); i++) { - //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); - } + vtkActor::SafeDownCast(collection->GetNextProp())->GetProperty()->SetColor(color[0], color[1], color[2]); } } /*+++++++++++++++++++ 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( "color", ColorProperty::New(1.0,1.0,0.0), renderer, overwrite ); node->AddProperty( "contour.3D.width", mitk::FloatProperty::New( 0.5 ), renderer, overwrite ); + IPropertyAliases* aliases = CoreServices::GetPropertyAliases(); + + if (aliases != NULL) + { + aliases->AddAlias("color", "contour.color", "ContourModelSet"); + } + Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.h b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.h index 74e01de925..9546f65700 100644 --- a/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.h +++ b/Modules/ContourModel/Rendering/mitkContourModelSetMapper3D.h @@ -1,107 +1,107 @@ /*=================================================================== 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_CONTOURMODELSET_MAPPER_3D_H_ #define _MITK_CONTOURMODELSET_MAPPER_3D_H_ #include "mitkCommon.h" #include #include "mitkBaseRenderer.h" #include "mitkVtkMapper.h" #include "mitkContourModel.h" #include "mitkContourModelSet.h" #include "mitkContourModelToSurfaceFilter.h" #include #include #include #include #include #include #include namespace mitk { class MitkContourModel_EXPORT ContourModelSetMapper3D : public VtkMapper { public: /** Standard class typedefs. */ mitkClassMacro( ContourModelSetMapper3D,VtkMapper ); /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) const mitk::ContourModelSet* GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); /*+++ methods of MITK-VTK rendering pipeline +++*/ virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); /*+++ END methods of MITK-VTK rendering pipeline +++*/ class MitkContourModel_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Assembly of contours. */ vtkSmartPointer m_Assembly; mitk::ContourModelToSurfaceFilter::Pointer m_contourToPolyData; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: ContourModelSetMapper3D(); virtual ~ContourModelSetMapper3D(); void GenerateDataForRenderer( mitk::BaseRenderer *renderer ); virtual vtkSmartPointer CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour,mitk::BaseRenderer* renderer); - virtual void ApplyContourProperties(mitk::BaseRenderer* renderer); + virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor* actor = NULL); }; } #endif diff --git a/Modules/DicomRT/CMakeLists.txt b/Modules/DicomRT/CMakeLists.txt new file mode 100644 index 0000000000..4e2d45448d --- /dev/null +++ b/Modules/DicomRT/CMakeLists.txt @@ -0,0 +1,12 @@ +# CREATE MODULE HERE +IF (NOT DEFINED DCMTK_dcmrt_LIBRARY OR DCMTK_dcmrt_LIBRARY) +MITK_CREATE_MODULE(mitkDicomRT + INCLUDE_DIRS DataStructures + DEPENDS Mitk Segmentation SceneSerializationBase + PACKAGE_DEPENDS DCMTK + QT_MODULE +) +ADD_SUBDIRECTORY(Testing) +ELSE() +MESSAGE("MITK DicomRT Support disabled because the DCMTK dcmrt library not found") +ENDIF() diff --git a/Modules/DicomRT/DataStructures/mitkDoseValueType.h b/Modules/DicomRT/DataStructures/mitkDoseValueType.h new file mode 100644 index 0000000000..ed3ba8680a --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkDoseValueType.h @@ -0,0 +1,37 @@ +/*=================================================================== + +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_DOSE_VALUE_TYPE_H_ +#define _MITK_DOSE_VALUE_TYPE_H_ + +namespace mitk +{ + +/** + \brief Represents absolute dose values (in Gy). +*/ +typedef double DoseValueAbs; + +/** +\brief Represents relative dose values (in %). +*/ +typedef double DoseValueRel; + + +} // namespace mitk + +#endif //_MITK_DOSE_VALUE_TYPE_H_ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevel.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevel.cpp new file mode 100644 index 0000000000..fa4feb2218 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevel.cpp @@ -0,0 +1,79 @@ +/*=================================================================== + +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 "mitkIsoDoseLevel.h" + +mitk::IsoDoseLevel::IsoDoseLevel() : +m_DoseValue (0.0), + m_VisibleIsoLine ( true ), + m_VisibleColorWash (true) +{ + m_Color.Fill(0); +} + +mitk::IsoDoseLevel::IsoDoseLevel( const IsoDoseLevel & other ) +{ + if (&other != this) + { + this->m_Color = other.m_Color; + this->m_DoseValue = other.m_DoseValue; + this->m_VisibleColorWash = other.m_VisibleColorWash; + this->m_VisibleIsoLine = other.m_VisibleIsoLine; + } +} + +mitk::IsoDoseLevel::IsoDoseLevel(const DoseValueType & value, const ColorType& color, bool visibleIsoLine, bool visibleColorWash): + m_DoseValue (value), + m_Color (color), + m_VisibleIsoLine ( visibleIsoLine ), + m_VisibleColorWash ( visibleColorWash ) +{ +}; + +mitk::IsoDoseLevel::~IsoDoseLevel() +{ +} + +bool mitk::IsoDoseLevel::operator == ( const IsoDoseLevel& right) const +{ + bool result = this->m_DoseValue == right.m_DoseValue; + + result = result && (this->m_Color == right.m_Color); + result = result && (this->m_VisibleColorWash == right.m_VisibleColorWash); + result = result && (this->m_VisibleIsoLine == right.m_VisibleIsoLine); + + return result; +} + +bool mitk::IsoDoseLevel::operator <( const IsoDoseLevel& right) const +{ + return this->m_DoseValue < right.m_DoseValue; +} + +bool mitk::IsoDoseLevel::operator > ( const IsoDoseLevel& right) const +{ + return this->m_DoseValue > right.m_DoseValue; +} + +void mitk::IsoDoseLevel::PrintSelf(std::ostream &os, itk::Indent indent) const +{ + Superclass::PrintSelf(os,indent); + os< +#include +#include + +#include "mitkCommon.h" +#include "mitkDoseValueType.h" +#include "mitkDicomRTExports.h" + +namespace mitk +{ + + /** + \brief Stores values needed for the representation/visualization of dose iso levels. + * + * The dose iso level is defined in the topology of a dose distribution by the dose value + * that indicates the lower boundary of the iso level. The upper boundary is implicitly defined + * by the next IsoDoseLevel greater (higher dose value) than the current iso level. + * Color and the visibility options are used to indicate the visualization style. + */ + class mitkDicomRT_EXPORT IsoDoseLevel: public itk::Object + { + public: + typedef ::itk::RGBPixel ColorType; + typedef DoseValueRel DoseValueType; + + mitkClassMacro(IsoDoseLevel, itk::Object); + itkNewMacro(Self); + mitkNewMacro4Param(Self,DoseValueType, ColorType, bool, bool); + + /** Checks if current dose iso level instances is greater + according to the dose values.*/ + bool operator> ( const IsoDoseLevel& right ) const; + /** Checks if current dose iso level instances is lesser + according to the dose values.*/ + bool operator< ( const IsoDoseLevel& right ) const; + + bool operator == ( const IsoDoseLevel& right) const; + + itkSetMacro(DoseValue,DoseValueType); + itkGetConstMacro(DoseValue,DoseValueType); + + itkSetMacro(Color,ColorType); + itkGetConstMacro(Color,ColorType); + + itkSetMacro(VisibleIsoLine,bool); + itkGetConstMacro(VisibleIsoLine,bool); + itkBooleanMacro(VisibleIsoLine); + + itkSetMacro(VisibleColorWash,bool); + itkGetConstMacro(VisibleColorWash,bool); + itkBooleanMacro(VisibleColorWash); + + protected: + IsoDoseLevel(); + IsoDoseLevel(const IsoDoseLevel & other); + IsoDoseLevel(const DoseValueType & value, const ColorType& color, bool visibleIsoLine = true, bool visibleColorWash = true ); + virtual ~IsoDoseLevel(); + + mitkCloneMacro(IsoDoseLevel); + + void PrintSelf(std::ostream &os, itk::Indent indent) const; + + private: + /** Relative dose value and lower boundary of the iso level instance + */ + DoseValueType m_DoseValue; + + /** RGB color code that should be used for the iso level.*/ + ColorType m_Color; + + /** indicates if an iso line should be shown for the iso level + (the lower boundary indicated by m_DoseValue)*/ + bool m_VisibleIsoLine; + + /** indicates if a color wash should be shown for the iso level.*/ + bool m_VisibleColorWash; + + /** Not implemented on purpose*/ + IsoDoseLevel& operator = (const IsoDoseLevel& source); + }; + +} // namespace mitk + +#endif //_MITK_DOSE_ISO_LEVEL_H_ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.cpp new file mode 100644 index 0000000000..f39b3a264e --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.cpp @@ -0,0 +1,148 @@ +/*=================================================================== + +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 "mitkIsoDoseLevelCollections.h" +#include "mitkExceptionMacro.h" + +namespace mitk +{ + namespace rt + { + /** "Private" functor used in std::find_if to find IsoDoseLevels with a given reference value */ + class EqualDoseFunctor + { + public: + typedef IsoDoseLevel::DoseValueType DoseValueType; + + EqualDoseFunctor(const DoseValueType& refValue) : m_refValue(refValue) + {}; + + bool operator () (const IsoDoseLevel* level) + { + return level->GetDoseValue() == m_refValue; + } + + protected: + DoseValueType m_refValue; + }; + + /** "Private" binary function used in std::sort to check the order of IsoDoseLeveles */ + bool lesserIsoDoseLevel(const IsoDoseLevel* first, const IsoDoseLevel* second) + { + return first->GetDoseValue() < second->GetDoseValue(); + } + } +} + +mitk::IsoDoseLevelSet::IsoDoseLevelSet(const IsoDoseLevelSet & other) +{ + if (&other != this) + { + this->m_IsoLevels = other.m_IsoLevels; + } +}; + +const mitk::IsoDoseLevel& mitk::IsoDoseLevelSet::GetIsoDoseLevel(IsoLevelIndexType index) const +{ + if (index < this->m_IsoLevels.size()) + { + return *(this->m_IsoLevels[index].GetPointer()); + } + else + { + mitkThrow() << "Try to access non existing dose iso level."; + } +}; + +const mitk::IsoDoseLevel& mitk::IsoDoseLevelSet::GetIsoDoseLevel(DoseValueType value) const +{ + InternalVectorType::const_iterator pos = std::find_if(this->m_IsoLevels.begin(), this->m_IsoLevels.end(), rt::EqualDoseFunctor(value)); + + if (pos != this->m_IsoLevels.end()) + { + return *(pos->GetPointer()); + } + else + { + mitkThrow() << "Try to access non existing dose iso level."; + } +}; + +void mitk::IsoDoseLevelSet::SetIsoDoseLevel(const IsoDoseLevel* level) +{ + if (!level) + { + mitkThrow() << "Cannot set iso level. Passed null pointer."; + } + + this->DeleteIsoDoseLevel(level->GetDoseValue()); + + this->m_IsoLevels.push_back(level->Clone()); + + std::sort(this->m_IsoLevels.begin(), this->m_IsoLevels.end(),rt::lesserIsoDoseLevel); +}; + +bool mitk::IsoDoseLevelSet::DoseLevelExists(IsoLevelIndexType index) const +{ + return index < this->m_IsoLevels.size(); +}; + + +bool mitk::IsoDoseLevelSet::DoseLevelExists(DoseValueType value) const +{ + InternalVectorType::const_iterator pos = std::find_if(this->m_IsoLevels.begin(), this->m_IsoLevels.end(), rt::EqualDoseFunctor(value)); + return pos != this->m_IsoLevels.end(); +}; + +void mitk::IsoDoseLevelSet::DeleteIsoDoseLevel(DoseValueType value) +{ + InternalVectorType::iterator pos = std::find_if(this->m_IsoLevels.begin(), this->m_IsoLevels.end(), rt::EqualDoseFunctor(value)); + + if (pos != this->m_IsoLevels.end()) + { + this->m_IsoLevels.erase(pos); + } +}; + +void mitk::IsoDoseLevelSet::DeleteIsoDoseLevel(IsoLevelIndexType index) +{ + if (DoseLevelExists(index)) + { + this->m_IsoLevels.erase(this->m_IsoLevels.begin()+index); + } +}; + +mitk::IsoDoseLevelSet::ConstIterator mitk::IsoDoseLevelSet::Begin(void) const +{ + return ConstIterator(this->m_IsoLevels.begin()); +}; + +mitk::IsoDoseLevelSet::ConstIterator mitk::IsoDoseLevelSet::End(void) const +{ + return ConstIterator(this->m_IsoLevels.end()); +}; + +mitk::IsoDoseLevelSet::IsoLevelIndexType mitk::IsoDoseLevelSet::Size(void) const +{ + return this->m_IsoLevels.size(); +}; + +void mitk::IsoDoseLevelSet::Reset(void) +{ + this->m_IsoLevels.clear(); +}; diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.h b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.h new file mode 100644 index 0000000000..3099aa2e6f --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelCollections.h @@ -0,0 +1,161 @@ +/*=================================================================== + +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_DOSE_ISO_LEVEL_COLLECTIONS_H_ +#define _MITK_DOSE_ISO_LEVEL_COLLECTIONS_H_ + +#include +#include + +#include "mitkIsoDoseLevel.h" + +namespace mitk +{ + + + /** + \class IsoDoseLevelVector + \brief Simple vector that stores dose iso levels. + * + * This class is for example used to store the user defined free iso values. + */ + typedef ::itk::VectorContainer IsoDoseLevelVector; + + + /** + \class IsoDoseLevelSet + \brief Stores values needed for the representation/visualization of dose iso levels. + * + * Set of dose iso levels sorted by the dose values of the iso levels (low to high values). + * This data structure is used to represent the dose iso level setup used for the + * visualization of a dose distribution. + */ +class mitkDicomRT_EXPORT IsoDoseLevelSet: + public itk::Object +{ +public: + mitkClassMacro(IsoDoseLevelSet, itk::Object); + itkNewMacro(Self); + +private: + /** Quick access to the STL vector type that was inherited. */ + typedef std::vector< IsoDoseLevel::Pointer > InternalVectorType; + typedef InternalVectorType::size_type size_type; + typedef InternalVectorType::iterator VectorIterator; + typedef InternalVectorType::const_iterator VectorConstIterator; + + InternalVectorType m_IsoLevels; + +protected: + IsoDoseLevelSet() {}; + IsoDoseLevelSet(const IsoDoseLevelSet & other); + + virtual ~IsoDoseLevelSet() {}; + + mitkCloneMacro(IsoDoseLevelSet); + +public: + typedef size_type IsoLevelIndexType; + typedef IsoDoseLevel::DoseValueType DoseValueType; + + /** Convenient typedefs for the iterator and const iterator. */ + class ConstIterator; + + /** Friends to this class. */ + friend class ConstIterator; + + /** \class ConstIterator + * Simulate STL-vector style const iteration where dereferencing the iterator + * gives read access to the value. + */ + class ConstIterator + { +public: + ConstIterator() {} + ConstIterator(const VectorConstIterator & i): m_Iter(i) {} + ConstIterator(const ConstIterator & r) { m_Iter = r.m_Iter; } + const IsoDoseLevel & operator*() { return *(m_Iter->GetPointer()); } + const IsoDoseLevel * operator->() { return m_Iter->GetPointer(); } + ConstIterator & operator++() {++m_Iter; return *this; } + ConstIterator operator++(int) { ConstIterator temp(*this); ++m_Iter; return temp; } + ConstIterator & operator--() {--m_Iter; return *this; } + ConstIterator operator--(int) { ConstIterator temp(*this); --m_Iter; return temp; } + ConstIterator & operator=(const ConstIterator & r) {m_Iter = r.m_Iter; return *this; } + bool operator==(const ConstIterator & r) const { return m_Iter == r.m_Iter; } + bool operator!=(const ConstIterator & r) const { return m_Iter != r.m_Iter; } + + const IsoDoseLevel & Value(void) const { return *(m_Iter->GetPointer()); } + +private: + VectorConstIterator m_Iter; + }; + + /* Declare the public interface routines. */ + + /** + * Read the element from the given index. + * It is assumed that the index exists. + */ + const IsoDoseLevel& GetIsoDoseLevel(IsoLevelIndexType) const; + const IsoDoseLevel& GetIsoDoseLevel(DoseValueType) const; + + /** + * Set the element value at the given index. + * It is assumed that the index exists. + */ + void SetIsoDoseLevel(const IsoDoseLevel*); + + /** + * Check if the index range of the vector is large enough to allow the + * given index without expansion. + */ + bool DoseLevelExists(IsoLevelIndexType) const; + bool DoseLevelExists(DoseValueType) const; + + /** + * Delete the element defined by the index identifier. In practice, it + * doesn't make sense to delete a vector index. Instead, this method just + * overwrites the index with the default element. + */ + void DeleteIsoDoseLevel(DoseValueType); + void DeleteIsoDoseLevel(IsoLevelIndexType); + + /** + * Get a begin const iterator for the vector. + */ + ConstIterator Begin(void) const; + + /** + * Get an end const iterator for the vector. + */ + ConstIterator End(void) const; + + /** + * Get the number of elements currently stored in the vector. + */ + IsoLevelIndexType Size(void) const; + + /** + * Clear the elements. The final size will be zero. + */ + void Reset(void); +}; + + +} + +#endif //_MITK_DOSE_ISO_LEVEL_COLLECTIONS_H_ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.cpp new file mode 100644 index 0000000000..8d15835b82 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.cpp @@ -0,0 +1,107 @@ +/*=================================================================== + +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 "mitkIsoDoseLevelSetProperty.h" + + +mitk::IsoDoseLevelSetProperty::IsoDoseLevelSetProperty() +{ +} + +mitk::IsoDoseLevelSetProperty::IsoDoseLevelSetProperty(const mitk::IsoDoseLevelSetProperty& other) + : BaseProperty(other) + , m_IsoLevelSet(other.m_IsoLevelSet) +{ +} + +mitk::IsoDoseLevelSetProperty::IsoDoseLevelSetProperty(IsoDoseLevelSet* levelSet) : m_IsoLevelSet(levelSet) +{ +} + +mitk::IsoDoseLevelSetProperty::~IsoDoseLevelSetProperty() +{ +} + +bool mitk::IsoDoseLevelSetProperty::IsEqual(const BaseProperty& property) const +{ + return this->m_IsoLevelSet == static_cast(property).m_IsoLevelSet; +} + +bool mitk::IsoDoseLevelSetProperty::Assign(const BaseProperty& property) +{ + this->m_IsoLevelSet = static_cast(property).m_IsoLevelSet; + return true; +} + +const mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetIsoDoseLevelSet() const +{ + return m_IsoLevelSet; +} + +const mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetValue() const +{ + return GetIsoDoseLevelSet(); +} + +mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetIsoDoseLevelSet() +{ + return m_IsoLevelSet; +} + +mitk::IsoDoseLevelSet * mitk::IsoDoseLevelSetProperty::GetValue() +{ + return GetIsoDoseLevelSet(); +} + + +void mitk::IsoDoseLevelSetProperty::SetIsoDoseLevelSet(IsoDoseLevelSet* levelSet) +{ + if(m_IsoLevelSet != levelSet) + { + m_IsoLevelSet = levelSet; + Modified(); + } +} + +void mitk::IsoDoseLevelSetProperty::SetValue(IsoDoseLevelSet* levelSet) +{ + SetIsoDoseLevelSet(levelSet); +} + +std::string mitk::IsoDoseLevelSetProperty::GetValueAsString() const +{ + std::stringstream myStr; + + myStr << "IsoDoseLevels: "; + + if (m_IsoLevelSet.IsNotNull()) + { + myStr << m_IsoLevelSet->Size() << std::endl; + + for (IsoDoseLevelSet::ConstIterator pos = m_IsoLevelSet->Begin(); pos != m_IsoLevelSet->End(); ++pos) + { + myStr << " " << 100*(pos->GetDoseValue()) << "% : ("<GetColor()<< "); iso line: " << pos->GetVisibleIsoLine() << "; color wash: "<GetVisibleColorWash() << std::endl; + } + } + return myStr.str(); +} + +itk::LightObject::Pointer mitk::IsoDoseLevelSetProperty::InternalClone() const +{ + itk::LightObject::Pointer result(new Self(*this)); + return result; +} diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.h b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.h new file mode 100644 index 0000000000..18065fe1e3 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelSetProperty.h @@ -0,0 +1,82 @@ +/*=================================================================== + +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_DOSE_ISO_LEVEL_SET_PROPERTY_H_ +#define _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ + +#include "mitkBaseProperty.h" +#include "mitkIsoDoseLevelCollections.h" +#include "mitkDicomRTExports.h" + +namespace mitk { + + +/** +\brief Property class for dose iso level sets. +*/ +class mitkDicomRT_EXPORT IsoDoseLevelSetProperty : public BaseProperty +{ + +protected: + IsoDoseLevelSet::Pointer m_IsoLevelSet; + + IsoDoseLevelSetProperty(); + + IsoDoseLevelSetProperty(const IsoDoseLevelSetProperty& other); + + IsoDoseLevelSetProperty(IsoDoseLevelSet* levelSet); + +public: + mitkClassMacro(IsoDoseLevelSetProperty, BaseProperty); + + itkNewMacro(IsoDoseLevelSetProperty); + mitkNewMacro1Param(IsoDoseLevelSetProperty, IsoDoseLevelSet*); + + typedef IsoDoseLevelSet ValueType; + + virtual ~IsoDoseLevelSetProperty(); + + const IsoDoseLevelSet * GetIsoDoseLevelSet() const; + const IsoDoseLevelSet * GetValue() const; + IsoDoseLevelSet * GetIsoDoseLevelSet(); + IsoDoseLevelSet * GetValue(); + + + void SetIsoDoseLevelSet(IsoDoseLevelSet* levelSet); + void SetValue(IsoDoseLevelSet* levelSet); + + virtual std::string GetValueAsString() const; + + using BaseProperty::operator=; + +private: + + // purposely not implemented + IsoDoseLevelSetProperty& operator=(const IsoDoseLevelSetProperty&); + + itk::LightObject::Pointer InternalClone() const; + + virtual bool IsEqual(const BaseProperty& property) const; + virtual bool Assign(const BaseProperty& property); + +}; + +} // namespace mitk + + + +#endif /* _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ */ diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.cpp b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.cpp new file mode 100644 index 0000000000..cc4b577bc7 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.cpp @@ -0,0 +1,107 @@ +/*=================================================================== + +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 "mitkIsoDoseLevelVectorProperty.h" + + +mitk::IsoDoseLevelVectorProperty::IsoDoseLevelVectorProperty() +{ +} + +mitk::IsoDoseLevelVectorProperty::IsoDoseLevelVectorProperty(const mitk::IsoDoseLevelVectorProperty& other) + : BaseProperty(other) + , m_IsoLevelVector(other.m_IsoLevelVector) +{ +} + +mitk::IsoDoseLevelVectorProperty::IsoDoseLevelVectorProperty(IsoDoseLevelVector* levelVector) : m_IsoLevelVector(levelVector) +{ +} + +mitk::IsoDoseLevelVectorProperty::~IsoDoseLevelVectorProperty() +{ +} + +bool mitk::IsoDoseLevelVectorProperty::IsEqual(const BaseProperty& property) const +{ + return this->m_IsoLevelVector == static_cast(property).m_IsoLevelVector; +} + +bool mitk::IsoDoseLevelVectorProperty::Assign(const BaseProperty& property) +{ + this->m_IsoLevelVector = static_cast(property).m_IsoLevelVector; + return true; +} + +const mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetIsoDoseLevelVector() const +{ + return m_IsoLevelVector; +} + +const mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetValue() const +{ + return GetIsoDoseLevelVector(); +} + +mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetIsoDoseLevelVector() +{ + return m_IsoLevelVector; +} + +mitk::IsoDoseLevelVector * mitk::IsoDoseLevelVectorProperty::GetValue() +{ + return GetIsoDoseLevelVector(); +} + + +void mitk::IsoDoseLevelVectorProperty::SetIsoDoseLevelVector(IsoDoseLevelVector* levelVector) +{ + if(m_IsoLevelVector != levelVector) + { + m_IsoLevelVector = levelVector; + Modified(); + } +} + +void mitk::IsoDoseLevelVectorProperty::SetValue(IsoDoseLevelVector* levelVector) +{ + SetIsoDoseLevelVector(levelVector); +} + +std::string mitk::IsoDoseLevelVectorProperty::GetValueAsString() const +{ + std::stringstream myStr; + + myStr << "IsoDoseLevels: "; + + if (m_IsoLevelVector.IsNotNull()) + { + myStr << m_IsoLevelVector->Size() << std::endl; + + for (IsoDoseLevelVector::ConstIterator pos = m_IsoLevelVector->Begin(); pos != m_IsoLevelVector->End(); ++pos) + { + myStr << " " << 100*(pos->Value()->GetDoseValue()) << "% : ("<Value()->GetColor()<< "); iso line: " << pos->Value()->GetVisibleIsoLine() << std::endl; + } + } + return myStr.str(); +} + +itk::LightObject::Pointer mitk::IsoDoseLevelVectorProperty::InternalClone() const +{ + itk::LightObject::Pointer result(new Self(*this)); + return result; +} diff --git a/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.h b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.h new file mode 100644 index 0000000000..c83651aafd --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkIsoDoseLevelVectorProperty.h @@ -0,0 +1,82 @@ +/*=================================================================== + +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_DOSE_ISO_LEVEL_VECTOR_PROPERTY_H_ +#define _MITK_DOSE_ISO_LEVEL_VECTOR_PROPERTY_H_ + +#include "mitkBaseProperty.h" +#include "mitkIsoDoseLevelCollections.h" +#include "mitkDicomRTExports.h" + +namespace mitk { + + +/** +\brief Property class for dose iso level vector. +*/ +class mitkDicomRT_EXPORT IsoDoseLevelVectorProperty : public BaseProperty +{ + +protected: + IsoDoseLevelVector::Pointer m_IsoLevelVector; + + IsoDoseLevelVectorProperty(); + + IsoDoseLevelVectorProperty(const IsoDoseLevelVectorProperty& other); + + IsoDoseLevelVectorProperty(IsoDoseLevelVector* levelVector); + +public: + mitkClassMacro(IsoDoseLevelVectorProperty, BaseProperty); + + itkNewMacro(IsoDoseLevelVectorProperty); + mitkNewMacro1Param(IsoDoseLevelVectorProperty, IsoDoseLevelVector*); + + typedef IsoDoseLevelVector ValueType; + + virtual ~IsoDoseLevelVectorProperty(); + + const IsoDoseLevelVector * GetIsoDoseLevelVector() const; + const IsoDoseLevelVector * GetValue() const; + IsoDoseLevelVector * GetIsoDoseLevelVector(); + IsoDoseLevelVector * GetValue(); + + + void SetIsoDoseLevelVector(IsoDoseLevelVector* levelVector); + void SetValue(IsoDoseLevelVector* levelVector); + + virtual std::string GetValueAsString() const; + + using BaseProperty::operator=; + +private: + + // purposely not implemented + IsoDoseLevelVectorProperty& operator=(const IsoDoseLevelVectorProperty&); + + itk::LightObject::Pointer InternalClone() const; + + virtual bool IsEqual(const BaseProperty& property) const; + virtual bool Assign(const BaseProperty& property); + +}; + +} // namespace mitk + + + +#endif /* _MITK_DOSE_ISO_LEVEL_SET_PROPERTY_H_ */ diff --git a/Modules/DicomRT/DataStructures/mitkRTConstants.cpp b/Modules/DicomRT/DataStructures/mitkRTConstants.cpp new file mode 100644 index 0000000000..a54dae2331 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkRTConstants.cpp @@ -0,0 +1,28 @@ +/*=================================================================== + +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 "mitkRTConstants.h" + +const std::string mitk::rt::Constants::DOSE_PROPERTY_NAME = "dose"; +const std::string mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME = "dose.PrescribedDose"; +const std::string mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME = "dose.ReferenceDose"; +const std::string mitk::rt::Constants::DOSE_TYPE_PROPERTY_NAME = "dose.type"; +const std::string mitk::rt::Constants::DOSE_SUMMATION_TYPE_PROPERTY_NAME = "dose.summationType"; +const std::string mitk::rt::Constants::DOSE_FRACTION_COUNT_PROPERTY_NAME = "dose.fractionCount"; +const std::string mitk::rt::Constants::DOSE_SHOW_ISOLINES_PROPERTY_NAME = "dose.showIsoLines"; +const std::string mitk::rt::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME = "dose.showColorWash"; +const std::string mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME = "dose.isoLevels"; +const std::string mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME = "dose.freeIsoValues"; diff --git a/Modules/DicomRT/DataStructures/mitkRTConstants.h b/Modules/DicomRT/DataStructures/mitkRTConstants.h new file mode 100644 index 0000000000..7a591b9151 --- /dev/null +++ b/Modules/DicomRT/DataStructures/mitkRTConstants.h @@ -0,0 +1,90 @@ +/*=================================================================== + +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_RT_CONSTANTS_H_ +#define _MITK_RT_CONSTANTS_H_ + +#include + +#include "mitkDicomRTExports.h" + +namespace mitk +{ + namespace rt + { + struct mitkDicomRT_EXPORT Constants + { + /** + * Name of the property that indicates if a data/node is a dose. + */ + static const std::string DOSE_PROPERTY_NAME; + + /** + * Name of the property that encodes the prescribed dose associated with the data node + * If a RTPLAN file exists the value can be extracted from the tag (300A,0026) - Target Prescription Dose in the plan file. + */ + static const std::string PRESCRIBED_DOSE_PROPERTY_NAME; + + /** + * Name of the property that encodes the reference dose that should be used for relative dose vizualization/evaluation purpose. + * It is often the prescribed dose but may differ e.g. when to dose distributions sould be compared using the same reference. + */ + static const std::string REFERENCE_DOSE_PROPERTY_NAME; + + /** + * Name of the property that encodes the optional string property holding the information from the tag (3004,0004) - Dose Type. + * This contains useful information for medical doctors + */ + static const std::string DOSE_TYPE_PROPERTY_NAME; + + /** + * Name of the property that encodes the optional string property holding the information from the tag (3004,000A) - Dose Summation Type. + * This contains useful information for medical doctors + */ + static const std::string DOSE_SUMMATION_TYPE_PROPERTY_NAME; + + /** + * Name of the property that encodes the number of fractions. + * It is for example in DICOM stored in tag (300A,0078) - Number of Fractions Prescribed (from the RTPLAN file if this file exists). + * This value could be used to further scale the dose according to dose summation type. + * For example a given plan consists of 8 fractions. Scaling the fraction dose by 8 gives the complete planned dose. + */ + static const std::string DOSE_FRACTION_COUNT_PROPERTY_NAME; + + /** + * Name of the property that encodes if the iso line rendering should be activated for the node. + */ + static const std::string DOSE_SHOW_ISOLINES_PROPERTY_NAME; + + /** + * Name of the property that encodes if the color wash rendering should be activated for the node. + */ + static const std::string DOSE_SHOW_COLORWASH_PROPERTY_NAME; + + /** + * Name of the property that encodes if the set of iso levels should be used to visualize the dose distribution. + */ + static const std::string DOSE_ISO_LEVELS_PROPERTY_NAME; + + /** + * Name of the property that encodes user defined iso values that mark special dose values in the distribution. + */ + static const std::string DOSE_FREE_ISO_VALUES_PROPERTY_NAME; + }; + } +} + +#endif diff --git a/Modules/DicomRT/Testing/CMakeLists.txt b/Modules/DicomRT/Testing/CMakeLists.txt new file mode 100644 index 0000000000..153cd81e2e --- /dev/null +++ b/Modules/DicomRT/Testing/CMakeLists.txt @@ -0,0 +1 @@ +MITK_CREATE_MODULE_TESTS() diff --git a/Modules/DicomRT/Testing/files.cmake b/Modules/DicomRT/Testing/files.cmake new file mode 100644 index 0000000000..d1458a00e5 --- /dev/null +++ b/Modules/DicomRT/Testing/files.cmake @@ -0,0 +1,4 @@ +SET(MODULE_TESTS + mitkDicomRTWriterTest.cpp + mitkDicomRTReaderTest.cpp +) diff --git a/Modules/DicomRT/Testing/mitkDicomRTReaderTest.cpp b/Modules/DicomRT/Testing/mitkDicomRTReaderTest.cpp new file mode 100644 index 0000000000..7e2a2df857 --- /dev/null +++ b/Modules/DicomRT/Testing/mitkDicomRTReaderTest.cpp @@ -0,0 +1,114 @@ +/*=================================================================== + +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 "mitkDicomRTReader.h" +#include + + +int mitkDicomRTReaderTest(int argc , char* argv[]) +{ + // always start with this! + MITK_TEST_BEGIN("DicomRTReader") + + mitk::DicomRTReader::Pointer _DicomRTReader = mitk::DicomRTReader::New(); + + char* h = "/home/riecker/DicomRT/DICOMRT_Bilder/DICOM-RT/W_K/RD1.2.826.0.1.3680043.8.176.2013826103830726.377.2260480657.dcm"; + char* i = "/home/riecker/DicomRT/DICOMRT_Bilder/RD.1.2.246.352.71.7.2088656855.452083.20110920153746.dcm"; + char* j = "/home/riecker/DicomRT/DICOMRT_Bilder/2/RTDOSE.2.16.840.1.113669.2.931128.509887832.20120106104806.483734.dcm"; + + mitk::ContourModelSet::Pointer emptyItem; + std::deque result; + result = _DicomRTReader->ReadDicomFile(h); + +// DcmFileFormat file; +// OFCondition outp = file.loadFile(argv[1], EXS_Unknown); +// DcmDataset *dataset = file.getDataset(); + +// std::cout << "Filename:" << argv[1] << "\n\n"; + +// int x = _DicomRTReader->LoadRTDose(dataset); + +// ContourModelVector result = _DicomRTReader->ReadStructureSet(dataset); + + +// mitk::ContourModel::Pointer real = mitk::ContourModel::New(); +// real = result.front(); + +// mitk::Point3D point; +// point[0] = 30.9; +// point[1] = 20.6; +// point[2] = 11.7; + +// mitk::Point3D samePoint; +// samePoint[0] = -0.3823089599609; +// samePoint[1] = -0.3836975097656; +// samePoint[2] = 2.5; + +// mitk::Point3D b; +// b[0] = -0.3823089599609; +// b[1] = -0.3836975097656; +// b[2] = 2.5; + +// mitk::ContourModel::Pointer created = mitk::ContourModel::New(); +// created->AddVertex(point); +// created->Close(); + +// mitk::ContourModel::Pointer same = mitk::ContourModel::New(); +// same->AddVertex(samePoint); +// same->Close(); + +// mitk::ContourModel::Pointer a1 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer a2 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer a3 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer a4 = mitk::ContourModel::New(); + +// mitk::ContourModel::Pointer a5 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer a6 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer a7 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer empty0 = mitk::ContourModel::New(); +// mitk::ContourModel::Pointer empty1 = mitk::ContourModel::New(); + +// a1->AddVertex(samePoint); +// a2->AddVertex(samePoint); +// a3->AddVertex(b); +// a4->AddVertex(point); + +// a5->AddVertex(samePoint); +// a5->AddVertex(b); +// a6->AddVertex(b); +// a6->AddVertex(samePoint); +// a7->AddVertex(samePoint); +// a7->AddVertex(point); + +// MITK_TEST_CONDITION_REQUIRED( !real->IsEmpty() , " 01. Tests if the first ContouModelObject from ReadDicomFile/Struct isnt empty -> False" ); +// MITK_TEST_CONDITION_REQUIRED( real != created , " 02. Tests if created ContourModel is different to frist ContourModel -> True" ); +// MITK_TEST_CONDITION_REQUIRED( same != real , " 03. Tests if the ContourModel looks like in the DcmDump Output -> True" ); +// MITK_TEST_CONDITION_REQUIRED( samePoint == b , " 04. Tests the two Points with same coords -> True" ); + +// MITK_TEST_CONDITION_REQUIRED( _DicomRTReader->Equals(empty0,empty1) , " 05. Tests two empty ContourModels -> True" ); +// MITK_TEST_CONDITION_REQUIRED( !_DicomRTReader->Equals(a1,empty0) , " 06. Tests Model with 1 Point and empty Model -> False" ); +// MITK_TEST_CONDITION_REQUIRED( !_DicomRTReader->Equals(a1,a4) , " 07. Tests Models with 1 different point -> False" ); +// MITK_TEST_CONDITION_REQUIRED( _DicomRTReader->Equals(a1,a3) , " 08. Tests Models with 1 point and same coords -> True" ); +// MITK_TEST_CONDITION_REQUIRED( !_DicomRTReader->Equals(a5,a1) , " 09. Tests a Model with 2 points and a model with one point, first point is the same -> False" ); +// MITK_TEST_CONDITION_REQUIRED( !_DicomRTReader->Equals(a5,a4) , " 10. Tests a Model with 2 points and a model with one point, first point is different -> False" ); +// MITK_TEST_CONDITION_REQUIRED( _DicomRTReader->Equals(a5,a6) , " 11. Tests two Models with 2 points and same coords -> True" ); +// MITK_TEST_CONDITION_REQUIRED( !_DicomRTReader->Equals(a5,a7) , " 12. Tests two Models with 2 points first is the same second is different -> False" ); + +// std::cout << "\n"; + // always end with this! + MITK_TEST_END() +} diff --git a/Modules/DicomRT/Testing/mitkDicomRTWriterTest.cpp b/Modules/DicomRT/Testing/mitkDicomRTWriterTest.cpp new file mode 100644 index 0000000000..0ccf1b6311 --- /dev/null +++ b/Modules/DicomRT/Testing/mitkDicomRTWriterTest.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +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 "mitkDicomRTWriter.h" +#include + +/** + * blaaa + */ +int mitkDicomRTWriterTest(int /* argc */, char* /*argv*/[]) +{ + // always start with this! + MITK_TEST_BEGIN("DicomRTWriter") + + mitk::DicomRTWriter::Pointer _DicomRTWriter = mitk::DicomRTWriter::New(); + + std::string helloWorld = _DicomRTWriter->SayHelloWorld(); + + MITK_TEST_CONDITION_REQUIRED( helloWorld == "Hello World", "SayHelloWorld worked correctly" ); + + // always end with this! + MITK_TEST_END() +} + diff --git a/Modules/DicomRT/files.cmake b/Modules/DicomRT/files.cmake new file mode 100644 index 0000000000..d596025962 --- /dev/null +++ b/Modules/DicomRT/files.cmake @@ -0,0 +1,26 @@ +SET(CPP_FILES + mitkDicomRTWriter.cpp + mitkDicomRTReader.cpp + DataStructures/mitkRTConstants.cpp + DataStructures/mitkIsoDoseLevel.cpp + DataStructures/mitkIsoDoseLevelCollections.cpp + DataStructures/mitkIsoDoseLevelSetProperty.cpp + DataStructures/mitkIsoDoseLevelVectorProperty.cpp +) + +set(H_FILES + mitkDicomRTWriter.h + mitkDicomRTReader.h + DataStructures/mitkIsoDoseLevel.h + DataStructures/mitkIsoDoseLevelCollections.h + DataStructures/mitkIsoDoseLevelSetProperty.h + DataStructures/mitkIsoDoseLevelVectorProperty.h + DataStructures/mitkDoseValueType.h + DataStructures/mitkRTConstants.h +) + +set(TPP_FILES +) + +set(MOC_H_FILES +) diff --git a/Modules/DicomRT/mitkDicomRTReader.cpp b/Modules/DicomRT/mitkDicomRTReader.cpp new file mode 100644 index 0000000000..473001f847 --- /dev/null +++ b/Modules/DicomRT/mitkDicomRTReader.cpp @@ -0,0 +1,547 @@ +/*=================================================================== + +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 "mitkDicomRTReader.h" + +#include +#include +#include + +namespace mitk +{ + + DicomRTReader::DicomRTReader(){} + + DicomRTReader::~DicomRTReader(){} + + DicomRTReader::RoiEntry::RoiEntry() + { + Number=0; + DisplayColor[0]=1.0; + DisplayColor[1]=0.0; + DisplayColor[2]=0.0; + ContourModelSet=mitk::ContourModelSet::New(); + } + + DicomRTReader::RoiEntry::~RoiEntry(){} + + DicomRTReader::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); + } + + DicomRTReader::RoiEntry& DicomRTReader::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 DicomRTReader::RoiEntry::SetPolyData(mitk::ContourModelSet::Pointer roiPolyData) + { + if (roiPolyData == this->ContourModelSet) + return; + this->ContourModelSet = roiPolyData; + } + + std::deque DicomRTReader::ReadDicomFile(char* filename) + { + DcmFileFormat file; + OFCondition outp; + outp = file.loadFile(filename, EXS_Unknown); + if(outp.good()) + { + DcmDataset *dataset = file.getDataset(); + OFString sopClass; + if(dataset->findAndGetOFString(DCM_SOPClassUID, sopClass).good() && !sopClass.empty()) + { + if(sopClass == UID_RTDoseStorage) + { + mitk::DataNode::Pointer x = mitk::DataNode::New(); + x = this->DicomRTReader::LoadRTDose(dataset, filename); + ContourModelSetVector y; + return y; + } + else if(sopClass == UID_RTStructureSetStorage) + { + ContourModelSetVector x = this->DicomRTReader::ReadStructureSet(dataset); + return x; + } + else if(sopClass == UID_RTPlanStorage) + { +// Function isnt implemented yet +// int x = this->DicomRTReader::LoadRTPlan(dataset); + ContourModelSetVector y; + return y; + } + else + { + MITK_ERROR << "Error matching the SOP Class, maybe an unsupported type" << endl; + ContourModelSetVector y; + return y; + } + } + else + { + MITK_ERROR << "Error reading the SOPClassID" << endl; + ContourModelSetVector y; + return y; + } + } + else + { + MITK_ERROR << "Error rading the input file" << endl; + ContourModelSetVector y; + return y; + } + } + + size_t DicomRTReader::GetNumberOfRois() + { + return this->RoiSequenceVector.size(); + } + + DicomRTReader::RoiEntry* DicomRTReader::FindRoiByNumber(unsigned int roiNumber) + { + for(unsigned int i=0; iRoiSequenceVector.size(); ++i) + { + if(this->RoiSequenceVector[i].Number == roiNumber) + return &this->RoiSequenceVector[i]; + } + return NULL; + } + + std::deque DicomRTReader::ReadStructureSet(DcmDataset* dataset) + { + /** + * @brief For storing contourmodelsets that belongs to the same object + * + * e.g. An eye consists of several contourmodels (contourmodel consists of several 3D-Points) + * and together they are a contourmodelset + */ + ContourModelSetVector contourModelSetVector; + + DRTStructureSetIOD structureSetObject; + OFCondition outp = structureSetObject.read(*dataset); + if(!outp.good()) + { + MITK_ERROR << "Error reading the file" << endl; + std::deque x; + return x; + } + DRTStructureSetROISequence &roiSequence = structureSetObject.getStructureSetROISequence(); + if(!roiSequence.gotoFirstItem().good()) + { + MITK_ERROR << "Error reading the structure sequence" << endl; + std::deque x; + return x; + } + do{ + DRTStructureSetROISequence::Item ¤tSequence = 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()); + +// Dont know anymore >.< +// OFString refSOPInstUID = GetReferencedFrameOfReferenceSOPInstanceUID(structureSetObject); +// double sliceThickness = 2.0; + + Sint32 refRoiNumber; + DRTROIContourSequence &roiContourSeqObject = structureSetObject.getROIContourSequence(); + if(!roiContourSeqObject.gotoFirstItem().good()) + { + MITK_ERROR << "Error reading the contour sequence" << endl; + std::deque x; + return x; + } + do + { + mitk::ContourModelSet::Pointer contourSet = mitk::ContourModelSet::New(); + DRTROIContourSequence::Item ¤tRoiObject = roiContourSeqObject.getCurrentItem(); + if(!currentRoiObject.isValid()) + { + continue; + } + currentRoiObject.getReferencedROINumber(refRoiNumber); + DRTContourSequence &contourSeqObject = currentRoiObject.getContourSequence(); + + if(contourSeqObject.gotoFirstItem().good()) + { + do + { + DRTContourSequence::Item &contourItem = contourSeqObject.getCurrentItem(); + if(!contourItem.isValid()) + { + continue; + } + int number; + OFString contourNumber; + OFString numberOfPoints; + OFVector contourData_LPS; + mitk::ContourModel::Pointer contourSequence = mitk::ContourModel::New(); + + contourItem.getContourNumber(contourNumber); + contourItem.getNumberOfContourPoints(numberOfPoints); + contourItem.getContourData(contourData_LPS); + + std::stringstream stream; + stream << numberOfPoints; + stream >> number; + + for(unsigned int i=0; iAddVertex(point); + } + contourSequence->Close(); + contourSet->AddContourModel(contourSequence); + } + while(contourSeqObject.gotoNextItem().good()); + } + else + { + MITK_ERROR << "Error reading contourSeqObject" << endl; + } + RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber); + if(refROI==NULL) + { + MITK_ERROR << "Can not find references ROI" << endl; + continue; + } + Sint32 roiColor; + for(int j=0;j<3;j++) + { + currentRoiObject.getROIDisplayColor(roiColor, j); + refROI->DisplayColor[j] = roiColor/255.0; + } + //TODO check for ordering maybe outsource contourmodelsetvector to + //Roientry and maybe it can replace the ContoruModelSet + refROI->ContourModelSet = contourSet; + contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name)); + contourModelSetVector.push_back(contourSet); + + } + while(roiContourSeqObject.gotoNextItem().good()); + + MITK_INFO << "Number of ROIs found: " << contourModelSetVector.size() << endl; + + return contourModelSetVector; + } + + OFString DicomRTReader::GetReferencedFrameOfReferenceSOPInstanceUID(DRTStructureSetIOD &structSetObject) + { + OFString invalid; + DRTReferencedFrameOfReferenceSequence &refFrameOfRefSeqObject = structSetObject.getReferencedFrameOfReferenceSequence(); + if(!refFrameOfRefSeqObject.gotoFirstItem().good()) + return invalid; + DRTReferencedFrameOfReferenceSequence::Item ¤tRefFrameOfRefSeqItem = refFrameOfRefSeqObject.getCurrentItem(); + if(!currentRefFrameOfRefSeqItem.isValid()) + return invalid; + DRTRTReferencedStudySequence &refStudySeqObject = currentRefFrameOfRefSeqItem.getRTReferencedStudySequence(); + if(!refStudySeqObject.gotoFirstItem().good()) + return invalid; + DRTRTReferencedStudySequence::Item &refStudySeqItem = refStudySeqObject.getCurrentItem(); + if(!refStudySeqItem.isValid()) + return invalid; + DRTRTReferencedSeriesSequence &refSeriesSeqObject = refStudySeqItem.getRTReferencedSeriesSequence(); + if(!refSeriesSeqObject.gotoFirstItem().good()) + return invalid; + DRTRTReferencedSeriesSequence::Item &refSeriesSeqItem = refSeriesSeqObject.getCurrentItem(); + if(!refSeriesSeqItem.isValid()) + return invalid; + DRTContourImageSequence &contourImageSeqObject = refSeriesSeqItem.getContourImageSequence(); + if(!contourImageSeqObject.gotoFirstItem().good()) + return invalid; + DRTContourImageSequence::Item &contourImageSeqItem = contourImageSeqObject.getCurrentItem(); + if(!contourImageSeqItem.isValid()) + return invalid; + + OFString resultUid; + contourImageSeqItem.getReferencedSOPInstanceUID(resultUid); + + return resultUid; + } + + int DicomRTReader::LoadRTPlan(DcmDataset *dataset) + { + DRTPlanIOD planObject; + OFCondition result = planObject.read(*dataset); + if(result.good()) + { + OFString tmpString, dummyString; + DRTBeamSequence &planeBeamSeqObject = planObject.getBeamSequence(); + if(planeBeamSeqObject.gotoFirstItem().good()) + { + do + { + DRTBeamSequence::Item ¤tBeamSeqItem = planeBeamSeqObject.getCurrentItem(); + if(!currentBeamSeqItem.isValid()) + { + std::cout << "Invalid Beam Sequence \n\n"; + continue; + } + BeamEntry beamEntry; + OFString beamName, beamDescription, beamType; + Sint32 beamNumber; + Float64 srcAxisDistance; + + currentBeamSeqItem.getBeamName(beamName); + currentBeamSeqItem.getBeamDescription(beamDescription); + currentBeamSeqItem.getBeamType(beamType); + currentBeamSeqItem.getBeamNumber(beamNumber); + currentBeamSeqItem.getSourceAxisDistance(srcAxisDistance); + + beamEntry.Name = beamName.c_str(); + beamEntry.Description = beamDescription.c_str(); + beamEntry.Type = beamType.c_str(); + beamEntry.Number = beamNumber; + beamEntry.SrcAxisDistance = srcAxisDistance; + + DRTControlPointSequence &controlPointSeqObject = currentBeamSeqItem.getControlPointSequence(); + if(controlPointSeqObject.gotoFirstItem().good()) + { + DRTControlPointSequence::Item &controlPointItem = controlPointSeqObject.getCurrentItem(); + if(controlPointItem.isValid()) + { + OFVector isocenterPosData_LPS; + Float64 gantryAngle, patientSupportAngle, beamLimitingDeviceAngle; + unsigned int numOfCollimatorPosItems = 0; + + controlPointItem.getIsocenterPosition(isocenterPosData_LPS); + controlPointItem.getGantryAngle(gantryAngle); + controlPointItem.getPatientSupportAngle(patientSupportAngle); + controlPointItem.getBeamLimitingDeviceAngle(beamLimitingDeviceAngle); + + beamEntry.GantryAngle = gantryAngle; + beamEntry.PatientSupportAngle = patientSupportAngle; + beamEntry.BeamLimitingDeviceAngle = beamLimitingDeviceAngle; + + DRTBeamLimitingDevicePositionSequence ¤tCollimatorPosSeqObject = controlPointItem.getBeamLimitingDevicePositionSequence(); + if(currentCollimatorPosSeqObject.gotoFirstItem().good()) + { + do + { + if(++numOfCollimatorPosItems > 2) + { + std::cout << "Number of collimator position items is higher than 2 but should be exactly 2 ..."; + return 0; + } + DRTBeamLimitingDevicePositionSequence::Item &collimatorPositionItem = currentCollimatorPosSeqObject.getCurrentItem(); + if(collimatorPositionItem.isValid()) + { + OFString beamLimitingDeviceType; + OFVector leafJawPositions; + + collimatorPositionItem.getRTBeamLimitingDeviceType(beamLimitingDeviceType); + collimatorPositionItem.getLeafJawPositions(leafJawPositions); + + if(!beamLimitingDeviceType.compare("ASYMX") || !beamLimitingDeviceType.compare("X")) + { + beamEntry.LeafJawPositions[0][0] = leafJawPositions[0]; + beamEntry.LeafJawPositions[0][1] = leafJawPositions[1]; + } + else if(!beamLimitingDeviceType.compare("ASYMY") || !beamLimitingDeviceType.compare("Y")) + { + beamEntry.LeafJawPositions[1][0] = leafJawPositions[0]; + beamEntry.LeafJawPositions[1][1] = leafJawPositions[0]; + } + else + { + std::cout << "Unknown collimator type: " << beamLimitingDeviceType << "\n\n"; + } + } + } + while(currentCollimatorPosSeqObject.gotoNextItem().good()); + } + }//endif controlPointItem.isValid() + } + this->BeamSequenceVector.push_back(beamEntry); + } + while(planeBeamSeqObject.gotoNextItem().good()); + } + } + return 1; + } + + mitk::DataNode::Pointer DicomRTReader::LoadRTDose(DcmDataset* dataset, char* filename) + { + std::string name = filename; + itk::FilenamesContainer file; + file.push_back(name); + + mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader; + + mitk::DataNode::Pointer originalNode = reader->LoadDicomSeries(file,false); + mitk::Image::Pointer originalImage = dynamic_cast(originalNode->GetData()); + + mitk::Geometry3D::Pointer geo = originalImage->GetGeometry()->Clone(); + + DRTDoseIOD doseObject; + + OFCondition result = doseObject.read(*dataset); + if(result.bad()) + { + std::cout << "Error reading the RT Dose dataset\n\n"; + return 0; + } + + Uint16 rows, columns, frames, planarConfig, samplesPP; + OFString nrframes, doseUnits, doseType, summationType, gridScaling, photoInterpret, lutShape; + Uint16 &rows_ref = rows; + Uint16 &columns_ref = columns; + Float32 gridscale; +// const Uint16 *pixelData = NULL; + const Uint16 *pixelData = NULL; + unsigned long count = 0; + + doseObject.getRows(rows_ref); + doseObject.getColumns(columns_ref); + doseObject.getNumberOfFrames(nrframes); + doseObject.getDoseUnits(doseUnits); + doseObject.getDoseType(doseType); + doseObject.getDoseSummationType(summationType); + doseObject.getDoseGridScaling(gridScaling); + doseObject.getPhotometricInterpretation(photoInterpret); + doseObject.getPlanarConfiguration(planarConfig); + doseObject.getSamplesPerPixel(samplesPP); + doseObject.getPresentationLUTShape(lutShape); + + //standard testing picture: 0.001 + gridscale = OFStandard::atof(gridScaling.c_str()); + std::cout << std::setprecision(10) << "GRIDSCALE >> " << gridscale << endl; + frames = atoi(nrframes.c_str()); + + //dataset->findAndGetUint16Array(DCM_PixelData, pixelData, &count); + dataset->findAndGetUint16Array(DCM_PixelData, pixelData, &count); + + mitk::Image::Pointer image = mitk::Image::New(); + mitk::PixelType pt = mitk::MakeScalarPixelType(); + unsigned int dim[] = {columns,rows,frames}; + + image->Initialize( pt, 3, dim); + image->SetSpacing(1.0); + mitk::Point3D m_origin; + m_origin[0] = 0.0; + m_origin[1] = 0.0; + m_origin[2] = 0.0; + image->SetOrigin(m_origin); + + float* pixel = (float*)image->GetData(); + int size = dim[0]*dim[1]*dim[2]; + + for(int i=0; iSetGeometry(geo); + + double prescripeDose = this->GetMaxDoseValue(dataset); + + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetName("DicomRT Dosis"); +// node->SetProperty("shader.mitkIsoLineShader.Gridscale", mitk::FloatProperty::New(10.0)); + node->SetFloatProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),prescripeDose); + node->SetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(),true); + node->SetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), 40); +// node->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); +// node->SetProperty("Image Rendering.Mode", renderingMode); +// node->SetProperty("opacity", mitk::FloatProperty::New(0.3)); + node->SetData(image); + + MITK_INFO << "PRESCRIPEDOSE >> " << prescripeDose << endl; + + return node; + } + + double DicomRTReader::GetMaxDoseValue(DcmDataset* dataSet) + { + DRTDoseIOD doseObject; + OFCondition result = doseObject.read(*dataSet); + if(result.bad()) + { + std::cout << "Error reading the RT Dose dataset\n\n"; + return 0; + } + + Uint16 rows, columns, frames; + OFString nrframes, gridScaling; + const Uint16 *pixelData = NULL; + Float32 gridscale; + + Uint16 &rows_ref = rows; + Uint16 &columns_ref = columns; + + doseObject.getRows(rows_ref); + doseObject.getColumns(columns_ref); + doseObject.getNumberOfFrames(nrframes); + doseObject.getDoseGridScaling(gridScaling); + + frames = atoi(nrframes.c_str()); + gridscale = OFStandard::atof(gridScaling.c_str()); + MITK_INFO << "Gridscale " << gridscale << endl; + MITK_INFO << "As String: " << gridScaling << endl; + dataSet->findAndGetUint16Array(DCM_PixelData, pixelData, 0); + + int size = columns*rows*frames; + double highest = 0; + + for(int i=0; ihighest) + { + highest = pixelData[i] * gridscale; + } + } + + return highest; + } + +} diff --git a/Modules/DicomRT/mitkDicomRTReader.h b/Modules/DicomRT/mitkDicomRTReader.h new file mode 100644 index 0000000000..790843e327 --- /dev/null +++ b/Modules/DicomRT/mitkDicomRTReader.h @@ -0,0 +1,232 @@ +/*=================================================================== + +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 mitkDicomRTReader_h +#define mitkDicomRTReader_h + +#include +#include +#include +#include +#include "mitkContourModel.h" +#include "mitkContourElement.h" +#include + +#include "dcmtk/config/osconfig.h" +#include "dcmtk/ofstd/ofconapp.h" + +#include "dcmtk/ofstd/ofcond.h" + +#include "dcmtk/dcmrt/drtdose.h" +#include "dcmtk/dcmrt/drtimage.h" +#include "dcmtk/dcmrt/drtplan.h" +#include "dcmtk/dcmrt/drttreat.h" +#include "dcmtk/dcmrt/drtionpl.h" +#include "dcmtk/dcmrt/drtiontr.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dcmtk/dcmrt/drtstrct.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class vtkPolyData; +class DcmDataset; +class OFString; +class DRTContourSequence; +class DRTStructureSetIOD; + +namespace mitk +{ + + class mitkDicomRT_EXPORT DicomRTReader: public itk::Object + { + + typedef std::deque ContourModelSetVector; + + /** + * @brief Describes and holds some information about the beams. + */ + class BeamEntry + { + public: + BeamEntry() + { + Number=-1; + SrcAxisDistance=0.0; + GantryAngle=0.0; + PatientSupportAngle=0.0; + BeamLimitingDeviceAngle=0.0; + LeafJawPositions[0][0]=0.0; + LeafJawPositions[0][1]=0.0; + LeafJawPositions[1][0]=0.0; + LeafJawPositions[1][1]=0.0; + } + unsigned int Number; + std::string Name; + std::string Type; + std::string Description; + double SrcAxisDistance; + double GantryAngle; + double PatientSupportAngle; + double BeamLimitingDeviceAngle; + double LeafJawPositions[2][2]; + }; + + /** + * @brief Describes and holds some information about the Rois. + */ + class RoiEntry + { + public: + RoiEntry(); + virtual ~RoiEntry(); + RoiEntry(const RoiEntry& src); + 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: + + mitkClassMacro( DicomRTReader, itk::Object ); + itkNewMacro( Self ); + + /** + * @brief Get the maximum dose value from the dose file + * @param dataSet The DcmDataset of the DicomRTDose file + * @return The dose value + * + * Checks all pixel values for the maximum value + */ + double GetMaxDoseValue(DcmDataset* dataSet); + + /** + * @brief Used for reading a DicomRT file + * @param filename The path with your file which you want to read + * + * Calls the right method for reading a dose, structure or plan file. + */ + ContourModelSetVector ReadDicomFile(char* filename); + + /** + * @brief Reads a DcmDataset from a DicomRT structureset file + * @param dataset DcmDataset-object from DCMTK + * @return Returns a Deque with mitk::ContourModelSet + * + * The returned mitk::ContourModelSet represent exactly one Roi/Structureset. + * So the size of the returned deque is the number of Rois. The names of the + * rois is stored in their mitk::Property. + */ + ContourModelSetVector ReadStructureSet(DcmDataset* dataset); + + /** + * @brief Reads a DcmDataset from a DicomRT plan file + * @param dataset DcmDataset-object from DCMTK + * @return The return doesnt make senese at the moment + * + * This method isnt ready for use at the moment. Dont use it! + */ + int LoadRTPlan(DcmDataset* dataset); + + /** + * @brief Reads a DcmDataset from a DicomRT dose file + * @param dataset DcmDataset-object from DCMTK + * @param filename The path with the dose file used for getting the geometry + * @return Returns a mitk::DataNode::Pointer in which a mitk::Image is stored + * + * The method reads the PixelData from the DicomRT dose file and scales them + * with a factor for getting Gray-values instead of pixel-values. + * The Gray-values are stored in a mitk::Image with an vtkColorTransferFunction. + * Relative values are used for coloring the image. The relative values are + * relative to a PrescriptionDose definied in the RT-Plan. If there is no + * RT-Plan file PrescriptionDose is set to 80% of the maximum dose. + */ + mitk::DataNode::Pointer LoadRTDose(DcmDataset* dataset, char* filename); + + /** + * @brief Returns the number of Rois stored in the RoiSequenceVector + * @return unsigned long size_t Number of Rois + */ + size_t GetNumberOfRois(); + + /** + * @brief Find a Roi stored in the RoiSequenceVector by his number + * @param roiNumber The number of the searched roi + * @return Returns a mitk::DicomRTReader::RoiEntry object + */ + RoiEntry* FindRoiByNumber(unsigned int roiNumber); + + /** + * @brief GetReferencedFrameOfReferenceSOPInstanceUID + * @param structSetObject + * @return + */ + OFString GetReferencedFrameOfReferenceSOPInstanceUID(DRTStructureSetIOD &structSetObject); + + /** + * Virtual destructor. + */ + virtual ~DicomRTReader(); + + protected: + + /** + * @brief Storing the Rois found in the Structureset file + */ + std::vector RoiSequenceVector; + + /** + * @brief Storing the Beams foud in the RT Plan file + */ + std::vector BeamSequenceVector; + + /** + * Constructor. + */ + DicomRTReader(); + + }; + +} + +#endif diff --git a/Modules/DicomRT/mitkDicomRTWriter.cpp b/Modules/DicomRT/mitkDicomRTWriter.cpp new file mode 100644 index 0000000000..983a47a090 --- /dev/null +++ b/Modules/DicomRT/mitkDicomRTWriter.cpp @@ -0,0 +1,37 @@ +/*=================================================================== + +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 "mitkDicomRTWriter.h" + +namespace mitk +{ + +DicomRTWriter::DicomRTWriter() +{ +} + +DicomRTWriter::~DicomRTWriter() +{ +} + +std::string DicomRTWriter::SayHelloWorld() +{ + return "Hello World"; +} + + +} // namespace diff --git a/Modules/DicomRT/mitkDicomRTWriter.h b/Modules/DicomRT/mitkDicomRTWriter.h new file mode 100644 index 0000000000..1621c98555 --- /dev/null +++ b/Modules/DicomRT/mitkDicomRTWriter.h @@ -0,0 +1,62 @@ +/*=================================================================== + +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 mitkDicomRTWriter_h +#define mitkDicomRTWriter_h + +#include +#include +#include +#include + +namespace mitk +{ + +/** + * @brief bla + * + */ +class mitkDicomRT_EXPORT DicomRTWriter: public itk::Object +{ +public: + + mitkClassMacro( DicomRTWriter, itk::Object ); + + itkNewMacro( Self ); + + std::string SayHelloWorld(); + + /** + * Virtual destructor. + */ + virtual ~DicomRTWriter(); + +protected: + + /** + * Constructor. + */ + DicomRTWriter(); + +}; + + + +} + + +#endif diff --git a/Modules/RTUI/CMakeLists.txt b/Modules/RTUI/CMakeLists.txt new file mode 100644 index 0000000000..1bc0607a67 --- /dev/null +++ b/Modules/RTUI/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(RTUI + INCLUDE_DIRS Qmitk Helper + DEPENDS mitkDicomRT Qmitk QmitkExt + PACKAGE_DEPENDS CTK + QT_MODULE +) diff --git a/Modules/RTUI/Helper/mitkIsoLevelsGenerator.cpp b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.cpp new file mode 100644 index 0000000000..dceba4c132 --- /dev/null +++ b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.cpp @@ -0,0 +1,134 @@ +/*=================================================================== + +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 "mitkIsoLevelsGenerator.h" + +mitk::IsoDoseLevelSet::Pointer mitk::rt::GeneratIsoLevels_Virtuos() +{ + mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); + + mitk::IsoDoseLevel::ColorType color; + color[0] = 0.0; + color[1] = 0.0; + color[2] = 0.4; + mitk::IsoDoseLevel::Pointer level = mitk::IsoDoseLevel::New(0.01,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.2; + color[2] = 0.8; + level = mitk::IsoDoseLevel::New(0.1,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.4; + color[2] = 1.0; + level = mitk::IsoDoseLevel::New(0.2,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.7; + color[2] = 1.0; + level = mitk::IsoDoseLevel::New(0.3,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.7; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(0.4,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 1.0; + color[2] = 0.3; + level = mitk::IsoDoseLevel::New(0.5,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 1.0; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(0.6,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 1.0; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.7,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.8; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.8,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.5; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.9,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.95,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.2; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(1.0,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.0; + color[2] = 0.3; + level = mitk::IsoDoseLevel::New(1.07,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.0; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.1,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.2,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.7; + color[2] = 0.7; + level = mitk::IsoDoseLevel::New(1.3,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.8; + color[1] = 0.6; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(1.4,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.65; + color[1] = 0.4; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.5,color,true,true); + levelSet->SetIsoDoseLevel(level); + + return levelSet; +} diff --git a/Modules/RTUI/Helper/mitkIsoLevelsGenerator.h b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.h new file mode 100644 index 0000000000..9367280be4 --- /dev/null +++ b/Modules/RTUI/Helper/mitkIsoLevelsGenerator.h @@ -0,0 +1,33 @@ +/*=================================================================== + +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 __ISO_LEVELS_GENERATOR_H +#define __ISO_LEVELS_GENERATOR_H + +#include "mitkIsoDoseLevelCollections.h" + +#include "RTUIExports.h" + +namespace mitk +{ + namespace rt + { + IsoDoseLevelSet::Pointer RTUI_EXPORT GeneratIsoLevels_Virtuos(); + } +} + +#endif diff --git a/Modules/RTUI/Helper/mitkRTUIConstants.cpp b/Modules/RTUI/Helper/mitkRTUIConstants.cpp new file mode 100644 index 0000000000..6fa6d768af --- /dev/null +++ b/Modules/RTUI/Helper/mitkRTUIConstants.cpp @@ -0,0 +1,45 @@ +/*=================================================================== + +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 "mitkRTUIConstants.h" + +const std::string mitk::rt::UIConstants::ROOT_PREFERENCE_NODE_ID = "/RT/UI"; +const std::string mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID = "unkownDoseHandlingStyle"; +const std::string mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID = "unkownDoseHandlingValue"; + + +const std::string mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID = "/RT/UI/doseVis"; +const std::string mitk::rt::UIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID = "/RT/UI/doseVis/isoPresets"; +const std::string mitk::rt::UIConstants::REFERENCE_DOSE_ID = "referenceDose"; +const std::string mitk::rt::UIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID = "globalReferenceDoseSync"; +const std::string mitk::rt::UIConstants::DOSE_DISPLAY_ABSOLUTE_ID = "doseDisplayAbsolute"; +const std::string mitk::rt::UIConstants::GLOBAL_VISIBILITY_ISOLINES_ID = "globalVisibilityIsoLines"; +const std::string mitk::rt::UIConstants::GLOBAL_VISIBILITY_COLORWASH_ID = "globalVisibilityColorWash"; +const std::string mitk::rt::UIConstants::SELECTED_ISO_PRESET_ID = "selectedIsoPreset"; + +const std::string mitk::rt::UIConstants::ISO_LEVEL_DOSE_VALUE_ID = "doseValue"; +const std::string mitk::rt::UIConstants::ISO_LEVEL_COLOR_RED_ID = "color_R"; +const std::string mitk::rt::UIConstants::ISO_LEVEL_COLOR_GREEN_ID = "color_G"; +const std::string mitk::rt::UIConstants::ISO_LEVEL_COLOR_BLUE_ID = "color_B"; +const std::string mitk::rt::UIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID = "visibleIsoLines"; +const std::string mitk::rt::UIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID = "visibleColorWash"; + +const mitk::DoseValueAbs mitk::rt::UIConstants::DEFAULT_REFERENCE_DOSE_VALUE = 40.0; + +const std::string mitk::rt::CTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS = "org/mitk/rt/dosevisualization/presets"; +const std::string mitk::rt::CTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED = "org/mitk/rt/dosevisualization/presets/CHANGED"; +const std::string mitk::rt::CTKEventConstants::TOPIC_REFERENCE_DOSE = "org/mitk/rt/dosevisualization/referenceDose"; +const std::string mitk::rt::CTKEventConstants::TOPIC_REFERENCE_DOSE_CHANGED = "org/mitk/rt/dosevisualization/referenceDose/CHANGED"; diff --git a/Modules/RTUI/Helper/mitkRTUIConstants.h b/Modules/RTUI/Helper/mitkRTUIConstants.h new file mode 100644 index 0000000000..87b1535479 --- /dev/null +++ b/Modules/RTUI/Helper/mitkRTUIConstants.h @@ -0,0 +1,86 @@ +/*=================================================================== + +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_RT_UI_CONSTANTS_H_ +#define _MITK_RT_UI_CONSTANTS_H_ + +#include +#include + +#include "RTUIExports.h" + +namespace mitk +{ + namespace rt + { + struct RTUI_EXPORT UIConstants + { + /** ID/Path of main preference node for RT UI. */ + static const std::string ROOT_PREFERENCE_NODE_ID; + /** Bool that indicates how the prescribed dose should be defined, if unkown. True: UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE should be used as + default dose value in Gy; False: it should be used as fraction of the max dose to determin the prescribed dose.*/ + static const std::string UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID; + /** Value that is used to determin unknown prescribed doses.*/ + static const std::string UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID; + + /** ID/Path of main preference node where all iso dose level presets are stored (e.g. ROOT_ISO_PRESETS_PREFERENCE_NODE_ID+"/[Preset1]"). */ + static const std::string ROOT_ISO_PRESETS_PREFERENCE_NODE_ID; + /** ID/Path of main preference for dose visualization preferences. */ + static const std::string ROOT_DOSE_VIS_PREFERENCE_NODE_ID; + /** ID for the reference dose stored as preference. */ + static const std::string REFERENCE_DOSE_ID; + /** ID for the preference flag that indicates if the reference dose is synced for all nodes*/ + static const std::string GLOBAL_REFERENCE_DOSE_SYNC_ID; + /** ID for the flag if dose should be displayed as absoulte dose. */ + static const std::string DOSE_DISPLAY_ABSOLUTE_ID; + /** ID for the global visiblity switch for iso line visualization. */ + static const std::string GLOBAL_VISIBILITY_ISOLINES_ID; + /** ID for the global visiblity switch for color wash visualization. */ + static const std::string GLOBAL_VISIBILITY_COLORWASH_ID; + /** ID for the selected iso preset that should be used (value of ROOT_ISO_PRESETS_PREFERENCE_NODE_ID + value of this key can + be used to construct the passed to the selected preset. */ + static const std::string SELECTED_ISO_PRESET_ID; + + /** ID for the relative dose value of an iso dose level. */ + static const std::string ISO_LEVEL_DOSE_VALUE_ID; + /** ID for the color (red component) of an iso dose level. */ + static const std::string ISO_LEVEL_COLOR_RED_ID; + /** ID for the color (green component) of an iso dose level. */ + static const std::string ISO_LEVEL_COLOR_GREEN_ID; + /** ID for the color (blue component) of an iso dose level. */ + static const std::string ISO_LEVEL_COLOR_BLUE_ID; + /** ID for the visiblity switch for iso line visualization. */ + static const std::string ISO_LEVEL_VISIBILITY_ISOLINES_ID; + /** ID for the visiblity switch for color wash visualization. */ + static const std::string ISO_LEVEL_VISIBILITY_COLORWASH_ID; + + /** Default value used as reference_dose_if not defined by application or data node*/ + static const DoseValueAbs DEFAULT_REFERENCE_DOSE_VALUE; + }; + + struct RTUI_EXPORT CTKEventConstants + { + /** ID/Path of main preference node for RT UI. */ + static const std::string TOPIC_REFERENCE_DOSE; + static const std::string TOPIC_REFERENCE_DOSE_CHANGED; + static const std::string TOPIC_ISO_DOSE_LEVEL_PRESETS; + static const std::string TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED; + }; + + } +} + +#endif diff --git a/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.cpp b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.cpp new file mode 100644 index 0000000000..548b5cde00 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.cpp @@ -0,0 +1,83 @@ +/*=================================================================== + +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 "QmitkDoseColorDelegate.h" + +#include +#include +#include +#include +#include +#include + +QmitkDoseColorDelegate::QmitkDoseColorDelegate(QObject * /*parent*/) +{ +} + +void QmitkDoseColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + + if (data.canConvert()) + { + QColor color = data.value(); + + painter->fillRect(option.rect, color); + } + else + { + QStyledItemDelegate::paint(painter, option, index); + } +} + +bool QmitkDoseColorDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index) +{ + Q_ASSERT(event); + Q_ASSERT(model); + + // make sure that the item is checkable + Qt::ItemFlags flags = model->flags(index); + if (!(flags & Qt::ItemIsEditable) || !(flags & Qt::ItemIsEnabled)) + { + return false; + } + + // make sure that we have the right event type + QMouseEvent* mouseEvent = dynamic_cast(event); + if (!mouseEvent) + { + return false; + } + else + { + if (mouseEvent->type() != QEvent::MouseButtonRelease || mouseEvent->button() != Qt::LeftButton) + { + return false; + } + } + + QColor oldcolor = index.data(Qt::EditRole).value(); + QColor newColor = QColorDialog::getColor(oldcolor, NULL); + + if (newColor.isValid()) + { + return model->setData(index, QVariant(newColor), Qt::EditRole); + } + + return false; +}; diff --git a/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.h b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.h new file mode 100644 index 0000000000..f4e9663a80 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseColorDelegate.h @@ -0,0 +1,44 @@ +/*=================================================================== + +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 QmitkDoseColorDelegate_h +#define QmitkDoseColorDelegate_h + + +#include + +#include "RTUIExports.h" + +/** \class QmitkDoseColorDelegate +\brief An item delegate for rendering and editing dose color in a QTableView.*/ +class RTUI_EXPORT QmitkDoseColorDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + /// + /// Creates a new PropertyDelegate. + /// + QmitkDoseColorDelegate(QObject *parent = 0); + + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; +}; + +#endif diff --git a/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.cpp b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.cpp new file mode 100644 index 0000000000..34ed4b28eb --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.cpp @@ -0,0 +1,113 @@ +/*=================================================================== + +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 "QmitkDoseValueDelegate.h" + +#include +#include +#include +#include + +QmitkDoseValueDelegate::QmitkDoseValueDelegate(QObject * /*parent*/) +{ +} + +void QmitkDoseValueDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option + , const QModelIndex &index) const +{ + QVariant data = index.data(Qt::DisplayRole); + + QStyleOptionViewItemV4 opt = option; + initStyleOption(&opt, index); + + QStyle *style = QApplication::style(); + + + style->drawItemText(painter, opt.rect.adjusted(0,0,-5,0), Qt::AlignRight | Qt::AlignVCenter, opt.palette,true, data.toString()); +} + +QWidget* QmitkDoseValueDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option + , const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + QVariant displayData = index.data(Qt::DisplayRole); + QVariant absoluteDose = index.data(Qt::UserRole+1); + + if(data.isValid()) + { + QDoubleSpinBox* spinBox = new QDoubleSpinBox(parent); + spinBox->setDecimals(2); + if (absoluteDose.toBool()) + { + spinBox->setSingleStep(0.5); + spinBox->setSuffix(QString(" Gy")); + } + else + { + spinBox->setSingleStep(1.0); + spinBox->setSuffix(QString(" %")); + } + + spinBox->setMinimum(0.0); + spinBox->setMaximum(9999.0); + + spinBox->installEventFilter( const_cast(this) ); + + return spinBox; + + } + else + return new QLabel(displayData.toString(), parent); + +} + +void QmitkDoseValueDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + + if(data.isValid()) + { + + QDoubleSpinBox* spinBox = qobject_cast(editor); + if (spinBox) + { + spinBox->setValue(data.toDouble()); + } + else + { + QStyledItemDelegate::setEditorData(editor, index); + } + } +} + +void QmitkDoseValueDelegate::setModelData(QWidget *editor, QAbstractItemModel* model + , const QModelIndex &index) const +{ + QVariant data = index.data(Qt::EditRole); + + if(data.isValid()) + { + QDoubleSpinBox* spinBox = qobject_cast(editor); + double doubleValue = spinBox->value(); + + QVariant doubleValueVariant(doubleValue); + model->setData(index, doubleValueVariant); + } + else + { + QStyledItemDelegate::setModelData(editor, model, index); + } +} diff --git a/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.h b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.h new file mode 100644 index 0000000000..711b536170 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseValueDelegate.h @@ -0,0 +1,63 @@ +/*=================================================================== + +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 QmitkDoseValueDelegate_h +#define QmitkDoseValueDelegate_h + + +#include + +#include "RTUIExports.h" + +/** \class QmitkDoseValueDelegate +\brief An item delegate for rendering and editing dose values. +The delegate assumes that the model uses the role Qt::UserRole+1 +to indicate if the returned dose value is an absolute (data(Qt::UserRole+1) == true) +or an relative dose (data(Qt::UserRole+1) == false).*/ +class RTUI_EXPORT QmitkDoseValueDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + /// + /// Creates a new PropertyDelegate. + /// + QmitkDoseValueDelegate(QObject *parent = 0); + + /// + /// Renders a specific property (overwritten from QItemDelegate) + /// + void paint(QPainter *painter, const QStyleOptionViewItem &option + , const QModelIndex &index) const; + + /// + /// Create an editor for a specific property (overwritten from QItemDelegate) + /// + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option + , const QModelIndex &index) const; + + /// + /// Create an editor for a specific property (overwritten from QItemDelegate) + /// + void setEditorData(QWidget *editor, const QModelIndex &index) const; + + /// + /// When the user accepts input this func commits the data to the model (overwritten from QItemDelegate) + /// + void setModelData(QWidget *editor, QAbstractItemModel* model, const QModelIndex &index) const; +}; + +#endif /* QMITKPROPERTIESTABLEMODEL_H_ */ diff --git a/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.cpp b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.cpp new file mode 100644 index 0000000000..9de4f0b4c8 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.cpp @@ -0,0 +1,94 @@ +/*=================================================================== + +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 "QmitkDoseVisualStyleDelegate.h" + +#include +#include +#include +#include +#include + +static QRect CheckBoxRect(const QStyleOptionViewItem &view_item_style_options) { + QStyleOptionButton check_box_style_option; + QRect check_box_rect = QApplication::style()->subElementRect( + QStyle::SE_CheckBoxIndicator, + &check_box_style_option); + QPoint check_box_point(view_item_style_options.rect.x() + + view_item_style_options.rect.width() / 2 - + check_box_rect.width() / 2, + view_item_style_options.rect.y() + + view_item_style_options.rect.height() / 2 - + check_box_rect.height() / 2); + return QRect(check_box_point, check_box_rect.size()); +} + +QmitkDoseVisualStyleDelegate::QmitkDoseVisualStyleDelegate(QObject * /*parent*/) +{ +} + +void QmitkDoseVisualStyleDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + bool checkValue = index.data(Qt::DisplayRole).toBool(); + + QStyleOptionButton BtnStyle; + BtnStyle.state = QStyle::State_Enabled; + + if(checkValue) + { + BtnStyle.state |= QStyle::State_On; + } + else + { + BtnStyle.state |= QStyle::State_Off; + } + + BtnStyle.direction = QApplication::layoutDirection(); + BtnStyle.rect = CheckBoxRect(option); + QApplication::style()->drawControl(QStyle::CE_CheckBox,&BtnStyle,painter ); +} + +bool QmitkDoseVisualStyleDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index) +{ + Q_ASSERT(event); + Q_ASSERT(model); + + // make sure that the item is checkable + Qt::ItemFlags flags = model->flags(index); + if (!(flags & Qt::ItemIsEditable) || !(flags & Qt::ItemIsEnabled)) + { + return false; + } + + // make sure that we have the right event type + QMouseEvent* mouseEvent = dynamic_cast(event); + if (!mouseEvent) + { + return false; + } + else + { + if (mouseEvent->type() != QEvent::MouseButtonRelease || mouseEvent->button() != Qt::LeftButton) + { + return false; + } + } + + bool newState = !(index.data(Qt::EditRole).toBool()); + + return model->setData(index, QVariant(newState), Qt::EditRole); +}; diff --git a/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.h b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.h new file mode 100644 index 0000000000..6ee24667c8 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkDoseVisualStyleDelegate.h @@ -0,0 +1,47 @@ +/*=================================================================== + +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 QmitkDoseVisualStyleDelegate_h +#define QmitkDoseVisualStyleDelegate_h + + +/// Toolkit includes. +#include + +#include "RTUIExports.h" + + +/** \class QmitkDoseVisualStyleDelegate +\brief An item delegate for rendering and editing dose visualization options. +The delegate is used to handle aspects of a isodose level like visualization +of the isodose lines or colorwash display.*/ +class RTUI_EXPORT QmitkDoseVisualStyleDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + + QmitkDoseVisualStyleDelegate(QObject *parent = 0); + + void paint(QPainter *painter, const QStyleOptionViewItem &option + , const QModelIndex &index) const; + + bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, + const QModelIndex &index); + +}; + +#endif diff --git a/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.cpp b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.cpp new file mode 100644 index 0000000000..0a313dbedd --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.cpp @@ -0,0 +1,145 @@ +/*=================================================================== + +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 "QmitkFreeIsoDoseLevelWidget.h" + + +QmitkFreeIsoDoseLevelWidget::QmitkFreeIsoDoseLevelWidget(QWidget*): m_ReferenceDose (40.0), m_InternalUpdate(false) +{ + this->setupUi(this); + + this->colorBtn->setDisplayColorName(false); + this->m_IsoDoseLevel = mitk::IsoDoseLevel::New(); + + connect(this->sbAbsValue, SIGNAL(valueChanged(double)), this, SLOT(OnAbsValueChanged(double))); + connect(this->sbRelValue, SIGNAL(valueChanged(double)), this, SLOT(OnRelValueChanged(double))); + connect(this->doseSlider, SIGNAL(valueChanged(int)), this, SLOT(OnSliderChanged(int))); + connect(this->checkVisibleIso, SIGNAL(clicked(bool)), this, SLOT(OnVisibleClicked(bool))); + connect(this->colorBtn, SIGNAL(colorChanged(QColor)), this, SLOT(OnColorChanged(QColor))); +} + +mitk::DoseValueAbs + QmitkFreeIsoDoseLevelWidget:: + getReferenceDose() const +{ + return this->m_ReferenceDose; +}; + +mitk::IsoDoseLevel* + QmitkFreeIsoDoseLevelWidget:: + getIsoDoseLevel() const +{ + return this->m_IsoDoseLevel; +}; + +void QmitkFreeIsoDoseLevelWidget:: + setReferenceDose(double newReferenceDose) +{ + if (newReferenceDose != m_ReferenceDose) + { + this->m_ReferenceDose = newReferenceDose; + this->update(); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + setIsoDoseLevel(mitk::IsoDoseLevel* level) +{ + if (level != m_IsoDoseLevel) + { + if(!level) + { + mitkThrow() << "Error. Cannot set iso dose level for widget to NULL pointer."; + } + + this->m_IsoDoseLevel = level; + this->update(); + } +} + +void QmitkFreeIsoDoseLevelWidget:: + OnRelValueChanged(double newValue) +{ + if(!m_InternalUpdate) + { + updateValue(newValue/100.0); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnAbsValueChanged(double newValue) +{ + if(!m_InternalUpdate) + { + updateValue(newValue/this->m_ReferenceDose); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnSliderChanged(int newValue) +{ + if(!m_InternalUpdate) + { + updateValue(newValue/100.0); + } +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnVisibleClicked(bool checked) +{ + this->m_IsoDoseLevel->SetVisibleIsoLine(checked); + emit VisualizationStyleChanged(this->m_IsoDoseLevel); +}; + +void QmitkFreeIsoDoseLevelWidget:: + OnColorChanged(QColor color) +{ + mitk::IsoDoseLevel::ColorType doseColor; + doseColor.SetRed(color.redF()); + doseColor.SetGreen(color.greenF()); + doseColor.SetBlue(color.blueF()); + this->m_IsoDoseLevel->SetColor(doseColor); + emit ColorChanged(this->m_IsoDoseLevel); +}; + +void QmitkFreeIsoDoseLevelWidget:: + updateValue(mitk::DoseValueRel newDose) +{ + m_InternalUpdate = true; + + mitk::DoseValueRel oldValue = this->m_IsoDoseLevel->GetDoseValue(); + this->m_IsoDoseLevel->SetDoseValue(newDose); + this->sbAbsValue->setValue(newDose*this->m_ReferenceDose); + this->sbRelValue->setValue(newDose*100); + this->doseSlider->setValue(newDose*100); + + m_InternalUpdate = false; + + emit ValueChanged(this->m_IsoDoseLevel,oldValue); +}; + +void QmitkFreeIsoDoseLevelWidget:: + update() +{ + updateValue(this->m_IsoDoseLevel->GetDoseValue()); + + this->checkVisibleIso->setChecked(this->m_IsoDoseLevel->GetVisibleIsoLine()); + + QColor color; + color.setRgbF(this->m_IsoDoseLevel->GetColor().GetRed(),this->m_IsoDoseLevel->GetColor().GetGreen(),this->m_IsoDoseLevel->GetColor().GetBlue()); + this->colorBtn->setColor(color); +}; diff --git a/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.h b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.h new file mode 100644 index 0000000000..daf3a6d421 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.h @@ -0,0 +1,78 @@ +/*=================================================================== + +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 QMITK_FREE_ISO_DOSE_LEVEL_WIDGET_H +#define QMITK_FREE_ISO_DOSE_LEVEL_WIDGET_H + +#include "RTUIExports.h" + +#include "ui_QmitkFreeIsoDoseLevelWidget.h" +#include + +#include "mitkIsoDoseLevel.h" + +/** +* \class QmitkFreeIsoDoseLevelWidget +* \brief Widget that allows to show and edit the content of an mitk::IsoDoseLevel instance. +*/ +class RTUI_EXPORT QmitkFreeIsoDoseLevelWidget : public QWidget, private Ui::QmitkFreeIsoDoseLevelWidget +{ + Q_OBJECT + +public: + QmitkFreeIsoDoseLevelWidget(QWidget* parent=0); + + mitk::DoseValueAbs getReferenceDose() const; + mitk::IsoDoseLevel* getIsoDoseLevel() const; + +signals: + void ValueChanged(mitk::IsoDoseLevel*, mitk::DoseValueRel oldValue); + void ColorChanged(mitk::IsoDoseLevel*); + void VisualizationStyleChanged(mitk::IsoDoseLevel*); + + public Q_SLOTS: + /** + * \brief Slot that can be used to set the reference dose. + */ + void setReferenceDose(double newReferenceDose); + + /** + * \brief Slot that can be used to set the dose level instance that should be handled by the widget. + */ + void setIsoDoseLevel(mitk::IsoDoseLevel* level); + + void OnRelValueChanged(double newValue); + void OnAbsValueChanged(double newValue); + void OnSliderChanged(int newValue); + void OnVisibleClicked(bool checked); + void OnColorChanged(QColor color); + +protected: + + /** + * \brief Updates the widget according to its current settings. + */ + void update(); + void updateValue(mitk::DoseValueRel newDose); + + mitk::DoseValueAbs m_ReferenceDose; + mitk::IsoDoseLevel::Pointer m_IsoDoseLevel; + bool m_InternalUpdate; + +}; + +#endif // QmitkFreeIsoDoseLevelWidget_H diff --git a/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.ui b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.ui new file mode 100644 index 0000000000..1f168c8044 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkFreeIsoDoseLevelWidget.ui @@ -0,0 +1,201 @@ + + + QmitkFreeIsoDoseLevelWidget + + + + 0 + 0 + 395 + 32 + + + + Form + + + + 2 + + + + + + 0 + 0 + + + + + 40 + 16777215 + + + + Color of the iso dose level + + + + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + 150 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + 0 + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + % + + + 9999.000000000000000 + + + 0.500000000000000 + + + + + + + = + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Minimum dose value of this level. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Gy + + + 9999.000000000000000 + + + 0.500000000000000 + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Show isoline for this dose level + + + Qt::LeftToRight + + + + + + + :/RTUI/eye_open.png + :/RTUI/eye_open.png + :/RTUI/eye_open.png:/RTUI/eye_open.png + + + + 24 + 16 + + + + false + + + + + + + + ctkColorPickerButton + QPushButton +
ctkColorPickerButton.h
+
+
+ + + + +
diff --git a/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.cpp b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.cpp new file mode 100644 index 0000000000..8b0bcdcd7e --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.cpp @@ -0,0 +1,450 @@ +/*=================================================================== + +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 "QmitkIsoDoseLevelSetModel.h" +#include "mitkRTUIConstants.h" + +QmitkIsoDoseLevelSetModel:: + QmitkIsoDoseLevelSetModel(QObject *parent) : +QAbstractTableModel(parent), m_referenceDose(mitk::rt::UIConstants::DEFAULT_REFERENCE_DOSE_VALUE), m_showAbsoluteDose(false), m_visibilityEditOnly(false), m_modified(false) +{ + m_DoseSet = mitk::IsoDoseLevelSet::New(); +} + +void + QmitkIsoDoseLevelSetModel:: + setIsoDoseLevelSet(mitk::IsoDoseLevelSet *pSet) +{ + if (pSet) + { + emit beginResetModel(); + + m_DoseSet = pSet; + m_modified = false; + + emit endResetModel(); + } +}; + +int + QmitkIsoDoseLevelSetModel:: + rowCount(const QModelIndex &parent) const +{ + if(parent.isValid()) + { + return 0; + } + + return m_DoseSet->Size(); +} + +int + QmitkIsoDoseLevelSetModel:: + columnCount(const QModelIndex &parent) const +{ + if(parent.isValid()) + return 0; + + return 4; +} + +QVariant + QmitkIsoDoseLevelSetModel:: + data(const QModelIndex &index, int role) const +{ + if(!index.isValid()) + return QVariant(); + + QVariant result; + + if(index.row()Size()) + { + const mitk::IsoDoseLevel& level = m_DoseSet->GetIsoDoseLevel(static_cast(index.row())); + + switch(index.column()) + { + case 0: + if(role == Qt::EditRole || role == Qt::DecorationRole) + { + QColor color; + color.setRgbF(level.GetColor().GetRed(),level.GetColor().GetGreen(),level.GetColor().GetBlue()); + result = QVariant(color); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Color of the iso dose level."); + } + break; + case 1: + if(role == Qt::DisplayRole) + { + if (this->m_showAbsoluteDose) + { + result = QVariant(QString::number(level.GetDoseValue()*this->m_referenceDose)+QString(" Gy")); + } + else + { + result = QVariant(QString::number(level.GetDoseValue()*100)+QString(" %")); + } + } + else if(role == Qt::EditRole) + { + if (this->m_showAbsoluteDose) + { + result = QVariant(level.GetDoseValue()*this->m_referenceDose); + } + else + { + result = QVariant(level.GetDoseValue()*100); + } + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Minimum dose value of this level / Value of the iso line."); + } + else if (role == Qt::UserRole+1) + { + result = QVariant(this->m_showAbsoluteDose); + } + break; + case 2: + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(level.GetVisibleIsoLine()); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Show isoline for this dose level."); + } + break; + case 3: + if(role == Qt::DisplayRole || role == Qt::EditRole) + { + result = QVariant(level.GetVisibleColorWash()); + } + else if (role == Qt::ToolTipRole) + { + result = QVariant("Show colorwash for this dose level."); + } + break; + } + } + + return result; +} + +Qt::ItemFlags + QmitkIsoDoseLevelSetModel:: + flags(const QModelIndex &index) const +{ + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + + if(index.row()Size()) + { + if (index.column() < 4) + { + if ((index.column() > 1) || (index.column() >= 0 && !this->m_visibilityEditOnly)) + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + } + else if (index.column() >= 0 && this->m_visibilityEditOnly) + { + flags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + + } + } + + return flags; +} + +QVariant + QmitkIsoDoseLevelSetModel:: + headerData(int section, Qt::Orientation orientation, int role) const +{ + if( (Qt::DisplayRole == role) && + (Qt::Horizontal == orientation)) + { + if (section==0) + { + return QVariant("Color"); + } + else if (section==1) + { + if (m_showAbsoluteDose) + { + return QVariant("Dose [Gy]"); + } + else + { + return QVariant("Dose [%]"); + } + } + else if (section==2) + { + return QVariant("IsoLines"); + } + else if (section==3) + { + return QVariant("ColorWash"); + } + } + return QVariant(); +} + +bool + QmitkIsoDoseLevelSetModel:: + setData(const QModelIndex &index, const QVariant &value, int role) +{ + if(!index.isValid() || (m_DoseSet->Size() <= index.row()) || (index.column()>3)) + { + return false; + } + + if(Qt::EditRole == role) + { + const mitk::IsoDoseLevel& level = m_DoseSet->GetIsoDoseLevel(static_cast(index.row())); + mitk::IsoDoseLevel::Pointer pNewLevel = level.Clone(); + switch(index.column()) + { + case 0: + { + QColor val = value.value(); + mitk::IsoDoseLevel::ColorType color; + color.SetRed(val.redF()); + color.SetGreen(val.greenF()); + color.SetBlue(val.blueF()); + pNewLevel->SetColor(color); + emit dataChanged(index,index); + break; + } + case 1: + if (this->m_showAbsoluteDose) + { + pNewLevel->SetDoseValue(value.toDouble()/this->m_referenceDose); + } + else + { + pNewLevel->SetDoseValue(value.toDouble()/100.0); + } + emit dataChanged(index,index); + break; + case 2: + pNewLevel->SetVisibleIsoLine(value.toBool()); + emit dataChanged(index,index); + break; + case 3: + pNewLevel->SetVisibleColorWash(value.toBool()); + emit dataChanged(index,index); + break; + } + + emit beginResetModel(); + + m_DoseSet->DeleteIsoDoseLevel(static_cast(index.row())); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + + m_modified = true; + + emit endResetModel(); + + return true; + } + + return false; +}; + +void QmitkIsoDoseLevelSetModel:: + setReferenceDose(double newReferenceDose) +{ + if (newReferenceDose<= 0) + { + mitkThrow() << "Error. Passed prescribed dose is negative or equals 0."; + } + + if (newReferenceDose != m_referenceDose) + { + this->m_referenceDose = newReferenceDose; + if(m_showAbsoluteDose) + { + emit beginResetModel(); + emit endResetModel(); + } + } +}; + +void QmitkIsoDoseLevelSetModel:: + setShowAbsoluteDose(bool showAbsoluteDose) + +{ + if (showAbsoluteDose != m_showAbsoluteDose) + { + emit beginResetModel(); + this->m_showAbsoluteDose = showAbsoluteDose; + emit endResetModel(); + } +}; + +void QmitkIsoDoseLevelSetModel::setVisibilityEditOnly(bool onlyVisibility) +{ + if (onlyVisibility != m_visibilityEditOnly) + { + emit beginResetModel(); + this->m_visibilityEditOnly = onlyVisibility; + emit endResetModel(); + } +}; + +bool + QmitkIsoDoseLevelSetModel:: + getShowAbsoluteDose() const +{ + return this->m_showAbsoluteDose; +}; + +mitk::DoseValueAbs + QmitkIsoDoseLevelSetModel:: + getReferenceDose() const +{ + return this->m_referenceDose; +}; + +bool + QmitkIsoDoseLevelSetModel:: + getVisibilityEditOnly() const +{ + return this->m_visibilityEditOnly; +}; + +void QmitkIsoDoseLevelSetModel::switchVisibilityIsoLines(bool activate) +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleIsoLine(activate); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::switchVisibilityColorWash(bool activate) +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleColorWash(activate); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::invertVisibilityIsoLines() +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleIsoLine(!pNewLevel->GetVisibleIsoLine()); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::invertVisibilityColorWash() +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + pNewLevel->SetVisibleColorWash(!pNewLevel->GetVisibleColorWash()); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::swapVisibility() +{ + emit beginResetModel(); + + for (mitk::IsoDoseLevelSet::IsoLevelIndexType pos = 0; pos < m_DoseSet->Size(); ++pos) + { + mitk::IsoDoseLevel::Pointer pNewLevel = m_DoseSet->GetIsoDoseLevel(pos).Clone(); + bool colorWash = pNewLevel->GetVisibleColorWash(); + pNewLevel->SetVisibleColorWash(pNewLevel->GetVisibleIsoLine()); + pNewLevel->SetVisibleIsoLine(colorWash); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + } + + m_modified = true; + + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::addLevel() +{ + mitk::IsoDoseLevel::DoseValueType doseVal = 0.01; + + if (m_DoseSet->Size()>0) + { + doseVal = m_DoseSet->GetIsoDoseLevel(m_DoseSet->Size()-1).GetDoseValue()+0.01; + } + + mitk::IsoDoseLevel::Pointer pNewLevel = mitk::IsoDoseLevel::New(doseVal, mitk::IsoDoseLevel::ColorType(), true, true); + + emit beginResetModel(); + m_DoseSet->SetIsoDoseLevel(pNewLevel); + m_modified = true; + emit endResetModel(); +} + +void QmitkIsoDoseLevelSetModel::deleteLevel(const QModelIndex &index) +{ + if(!index.isValid() || (m_DoseSet->Size() <= index.row()) || (index.column()>3)) + { + return; + } + + emit beginResetModel(); + m_DoseSet->DeleteIsoDoseLevel(static_cast(index.row())); + m_modified = true; + emit endResetModel(); +} + +bool QmitkIsoDoseLevelSetModel::isModified() +{ + return m_modified; +} diff --git a/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.h b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.h new file mode 100644 index 0000000000..b74ebef576 --- /dev/null +++ b/Modules/RTUI/Qmitk/QmitkIsoDoseLevelSetModel.h @@ -0,0 +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 QmitkIsoDoseLevelSetModel_h +#define QmitkIsoDoseLevelSetModel_h + +#include + +#include "mitkIsoDoseLevelCollections.h" + +#include "RTUIExports.h" + + +/*! +\class QmitkIsoDoseLevelSetModel +Model that handles a iso dose level set and allows viewing and editing of its contents. +Please see special delegates (QmitkDoseColorDelegate, QmitkDoseValueDelegate, QmitkDoseVisualStyleDelegate) to +handle visualization and editing in views that work on this model. +\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. +*/ +class RTUI_EXPORT QmitkIsoDoseLevelSetModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + QmitkIsoDoseLevelSetModel(QObject *parent = NULL); + virtual ~QmitkIsoDoseLevelSetModel() {}; + + /** Sets the data handled by the model and resets the modified flag*/ + void setIsoDoseLevelSet(mitk::IsoDoseLevelSet *pSet); + + virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QVariant data(const QModelIndex &index, int role) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + bool getShowAbsoluteDose() const; + mitk::DoseValueAbs getReferenceDose() const; + + bool getVisibilityEditOnly() const; + + void switchVisibilityIsoLines(bool activate); + void switchVisibilityColorWash(bool activate); + void invertVisibilityIsoLines(); + void invertVisibilityColorWash(); + void swapVisibility(); + + void addLevel(); + void deleteLevel(const QModelIndex &index); + + /**Indicates if the content of the model was modified since the data was set via setIsoDoseLevelSet()*/ + bool isModified(); + + public Q_SLOTS: + /** + * \brief Slot that can be used to set the prescribed dose. + */ + void setReferenceDose(double newReferenceDose); + /** + * \brief Slot that can be used to adjust whether the dose should be displayed in absolute or relative units. + */ + void setShowAbsoluteDose(bool showAbsoluteDose); + + /** + * \brief Slat that can be used to adjust wether the model allows to edit only visibilities (no dose value or color) + */ + void setVisibilityEditOnly(bool onlyVisibility); + +private: + mitk::IsoDoseLevelSet::Pointer m_DoseSet; + + bool m_showAbsoluteDose; + bool m_visibilityEditOnly; + + mitk::DoseValueAbs m_referenceDose; + + /** Indicates if the data of the model was modified, since the model was set. */ + bool m_modified; + +}; + +#endif // QmitkIsoDoseLevelSetModel_h + diff --git a/Modules/RTUI/files.cmake b/Modules/RTUI/files.cmake new file mode 100644 index 0000000000..d49a968f4c --- /dev/null +++ b/Modules/RTUI/files.cmake @@ -0,0 +1,27 @@ +set(CPP_FILES + Qmitk/QmitkFreeIsoDoseLevelWidget.cpp + Qmitk/QmitkIsoDoseLevelSetModel.cpp + Qmitk/QmitkDoseColorDelegate.cpp + Qmitk/QmitkDoseValueDelegate.cpp + Qmitk/QmitkDoseVisualStyleDelegate.cpp + Helper/mitkRTUIConstants.cpp + Helper/mitkIsoLevelsGenerator.cpp +) + +set(UI_FILES + Qmitk/QmitkFreeIsoDoseLevelWidget.ui +) + +set(MOC_H_FILES + Qmitk/QmitkFreeIsoDoseLevelWidget.h + Qmitk/QmitkIsoDoseLevelSetModel.h + Qmitk/QmitkDoseColorDelegate.h + Qmitk/QmitkDoseValueDelegate.h + Qmitk/QmitkDoseVisualStyleDelegate.h +) + +set(QRC_FILES + resources/RTUI.qrc +) + + diff --git a/Modules/RTUI/resources/RTUI.qrc b/Modules/RTUI/resources/RTUI.qrc new file mode 100644 index 0000000000..174c9563ea --- /dev/null +++ b/Modules/RTUI/resources/RTUI.qrc @@ -0,0 +1,8 @@ + + + powerGreen.png + eye_close.png + eye_open.png + powerRed.png + + diff --git a/Modules/RTUI/resources/eye_close.png b/Modules/RTUI/resources/eye_close.png new file mode 100644 index 0000000000..9b82203c2a Binary files /dev/null and b/Modules/RTUI/resources/eye_close.png differ diff --git a/Modules/RTUI/resources/eye_open.png b/Modules/RTUI/resources/eye_open.png new file mode 100644 index 0000000000..a1c2bb9f35 Binary files /dev/null and b/Modules/RTUI/resources/eye_open.png differ diff --git a/Modules/RTUI/resources/powerGreen.png b/Modules/RTUI/resources/powerGreen.png new file mode 100644 index 0000000000..9e8e0903d9 Binary files /dev/null and b/Modules/RTUI/resources/powerGreen.png differ diff --git a/Modules/RTUI/resources/powerRed.png b/Modules/RTUI/resources/powerRed.png new file mode 100644 index 0000000000..bb3f33bef5 Binary files /dev/null and b/Modules/RTUI/resources/powerRed.png differ diff --git a/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp b/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp index 5b9f6016e5..d7e736924f 100644 --- a/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp +++ b/Modules/Segmentation/Interactions/mitkFeedbackContourTool.cpp @@ -1,136 +1,136 @@ /*=================================================================== 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 "mitkFeedbackContourTool.h" #include "mitkToolManager.h" #include "mitkProperties.h" #include "mitkStringProperty.h" #include "mitkColorProperty.h" #include "mitkDataStorage.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" mitk::FeedbackContourTool::FeedbackContourTool(const char* type) :SegTool2D(type), m_FeedbackContourVisible(false) { m_FeedbackContour = ContourModel::New(); m_FeedbackContour->SetClosed(true); m_FeedbackContourNode = DataNode::New(); m_FeedbackContourNode->SetData( m_FeedbackContour ); m_FeedbackContourNode->SetProperty("name", StringProperty::New("One of FeedbackContourTool's feedback nodes")); m_FeedbackContourNode->SetProperty("visible", BoolProperty::New(true)); m_FeedbackContourNode->SetProperty("helper object", BoolProperty::New(true)); m_FeedbackContourNode->SetProperty("layer", IntProperty::New(1000)); m_FeedbackContourNode->SetProperty("contour.project-onto-plane", BoolProperty::New(false)); m_FeedbackContourNode->SetProperty("contour.width", FloatProperty::New(1.0)); this->Disable3dRendering(); SetFeedbackContourColorDefault(); } mitk::FeedbackContourTool::~FeedbackContourTool() { } void mitk::FeedbackContourTool::SetFeedbackContourColor( float r, float g, float b ) { - m_FeedbackContourNode->SetProperty("contour.color", ColorProperty::New(r, g, b)); + m_FeedbackContourNode->SetProperty("color", ColorProperty::New(r, g, b)); } void mitk::FeedbackContourTool::SetFeedbackContourColorDefault() { - m_FeedbackContourNode->SetProperty("contour.color", ColorProperty::New(0.0/255.0, 255.0/255.0, 0.0/255.0)); + m_FeedbackContourNode->SetProperty("color", ColorProperty::New(0.0/255.0, 255.0/255.0, 0.0/255.0)); } mitk::ContourModel* mitk::FeedbackContourTool::GetFeedbackContour() { return m_FeedbackContour; } void mitk::FeedbackContourTool::SetFeedbackContour(ContourModel& contour) { // begin of temporary fix for 3m3 release this->Disable3dRendering(); //end of temporary fix for 3m3 release m_FeedbackContour = &contour; m_FeedbackContourNode->SetData( m_FeedbackContour ); } void mitk::FeedbackContourTool::SetFeedbackContourVisible(bool visible) { // begin of temporary fix for 3m3 release this->Disable3dRendering(); //end of temporary fix for 3m3 release if ( m_FeedbackContourVisible == visible ) return; // nothing changed if ( DataStorage* storage = m_ToolManager->GetDataStorage() ) { if (visible) { storage->Add( m_FeedbackContourNode ); } else { storage->Remove( m_FeedbackContourNode ); } } m_FeedbackContourVisible = visible; } mitk::ContourModel::Pointer mitk::FeedbackContourTool::ProjectContourTo2DSlice(Image* slice, ContourModel* contourIn3D, bool correctionForIpSegmentation, bool constrainToInside) { return mitk::ContourModelUtils::ProjectContourTo2DSlice(slice, contourIn3D, correctionForIpSegmentation, constrainToInside); } mitk::ContourModel::Pointer mitk::FeedbackContourTool::BackProjectContourFrom2DSlice(const Geometry3D* sliceGeometry, ContourModel* contourIn2D, bool correctionForIpSegmentation) { return mitk::ContourModelUtils::BackProjectContourFrom2DSlice(sliceGeometry, contourIn2D, correctionForIpSegmentation); } void mitk::FeedbackContourTool::FillContourInSlice( ContourModel* projectedContour, Image* sliceImage, int paintingPixelValue ) { this->FillContourInSlice(projectedContour, 0, sliceImage, paintingPixelValue); } void mitk::FeedbackContourTool::FillContourInSlice( ContourModel* projectedContour, unsigned int timeStep, Image* sliceImage, int paintingPixelValue ) { mitk::ContourModelUtils::FillContourInSlice(projectedContour, timeStep, sliceImage, paintingPixelValue); } void mitk::FeedbackContourTool::Disable3dRendering() { // set explicitly visible=false for all 3D renderer (that exist already ...) const RenderingManager::RenderWindowVector& renderWindows = RenderingManager::GetInstance()->GetAllRegisteredRenderWindows(); for (RenderingManager::RenderWindowVector::const_iterator iter = renderWindows.begin(); iter != renderWindows.end(); ++iter) { if ( mitk::BaseRenderer::GetInstance((*iter))->GetMapperID() == BaseRenderer::Standard3D ) //if ( (*iter)->GetRenderer()->GetMapperID() == BaseRenderer::Standard3D ) { m_FeedbackContourNode->SetProperty("visible", BoolProperty::New(false), mitk::BaseRenderer::GetInstance((*iter))); } } } diff --git a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp index f89d28887d..1f7c1d778d 100644 --- a/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp +++ b/Modules/Segmentation/Interactions/mitkLiveWireTool2D.cpp @@ -1,654 +1,654 @@ /*=================================================================== 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 "mitkLiveWireTool2D.h" #include "mitkToolManager.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkLiveWireTool2D.xpm" #include #include #include #include "mitkContourUtils.h" #include "mitkContour.h" #include // us #include #include #include #include namespace mitk { MITK_TOOL_MACRO(MitkSegmentation_EXPORT, LiveWireTool2D, "LiveWire tool"); } mitk::LiveWireTool2D::LiveWireTool2D() :SegTool2D("LiveWireTool") { } mitk::LiveWireTool2D::~LiveWireTool2D() { this->m_WorkingContours.clear(); this->m_EditingContours.clear(); } void mitk::LiveWireTool2D::ConnectActionsAndFunctions() { CONNECT_CONDITION( "CheckContourClosed", OnCheckPoint ); CONNECT_FUNCTION( "InitObject", OnInitLiveWire); CONNECT_FUNCTION( "AddPoint", OnAddPoint); CONNECT_FUNCTION( "MovePoint", OnMouseMoveNoDynamicCosts); CONNECT_FUNCTION( "FinishContour", OnFinish); CONNECT_FUNCTION( "DeletePoint", OnLastSegmentDelete); CONNECT_FUNCTION( "MovePoint", OnMouseMoved); } const char** mitk::LiveWireTool2D::GetXPM() const { return mitkLiveWireTool2D_xpm; } us::ModuleResource mitk::LiveWireTool2D::GetIconResource() const { us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("LiveWire_48x48.png"); return resource; } us::ModuleResource mitk::LiveWireTool2D::GetCursorIconResource() const { us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("LiveWire_Cursor_32x32.png"); return resource; } const char* mitk::LiveWireTool2D::GetName() const { return "Live Wire"; } void mitk::LiveWireTool2D::Activated() { Superclass::Activated(); //enable interaction if there are any previously created contours this->EnableContourLiveWireInteraction(true); } void mitk::LiveWireTool2D::Deactivated() { Superclass::Deactivated(); //disable interaction with current contours this->EnableContourLiveWireInteraction(false); } void mitk::LiveWireTool2D::ClearContours() { // for all contours in list (currently created by tool) std::vector< std::pair >::iterator iter = this->m_WorkingContours.begin(); while(iter != this->m_WorkingContours.end() ) { //remove contour node from datastorage m_ToolManager->GetDataStorage()->Remove( iter->first ); ++iter; } this->m_WorkingContours.clear(); // for all contours in list (currently created by tool) std::vector< std::pair >::iterator itEditingContours = this->m_EditingContours.begin(); while(itEditingContours != this->m_EditingContours.end() ) { //remove contour node from datastorage m_ToolManager->GetDataStorage()->Remove( itEditingContours->first ); ++itEditingContours; } this->m_EditingContours.clear(); this->EnableContourLiveWireInteraction(false); this->m_LiveWireInteractors.clear(); } void mitk::LiveWireTool2D::EnableContourLiveWireInteraction(bool on) { //for all currently created contours enable or disable interactor std::vector< mitk::ContourModelLiveWireInteractor::Pointer >::iterator itLiveWireInteractors = this->m_LiveWireInteractors.begin(); std::vector< mitk::ContourModelLiveWireInteractor::Pointer >::iterator end = this->m_LiveWireInteractors.end(); while(itLiveWireInteractors != end ) { if(on) { // add interactors to globalInteraction instance mitk::GlobalInteraction::GetInstance()->AddInteractor( *itLiveWireInteractors ); } else { // remove interactors from globalInteraction instance mitk::GlobalInteraction::GetInstance()->RemoveInteractor( *itLiveWireInteractors ); } ++itLiveWireInteractors; } } void mitk::LiveWireTool2D::ConfirmSegmentation() { DataNode* workingNode( m_ToolManager->GetWorkingData(0) ); assert ( workingNode ); Image* workingImage = dynamic_cast(workingNode->GetData()); assert ( workingImage ); // for all contours in list (currently created by tool) std::vector< std::pair >::iterator itWorkingContours = this->m_WorkingContours.begin(); while(itWorkingContours != this->m_WorkingContours.end() ) { // if node contains data if( itWorkingContours->first->GetData() ) { // if this is a contourModel mitk::ContourModel* contourModel = dynamic_cast(itWorkingContours->first->GetData()); if( contourModel ) { // for each timestep of this contourModel for( TimeStepType currentTimestep = 0; currentTimestep < contourModel->GetTimeGeometry()->CountTimeSteps(); ++currentTimestep) { //get the segmentation image slice at current timestep mitk::Image::Pointer workingSlice = this->GetAffectedImageSliceAs2DImage(itWorkingContours->second, workingImage, currentTimestep); mitk::ContourModel::Pointer projectedContour = mitk::ContourModelUtils::ProjectContourTo2DSlice(workingSlice, contourModel, true, false); mitk::ContourModelUtils::FillContourInSlice(projectedContour, workingSlice, 1.0); //write back to image volume this->WriteBackSegmentationResult(itWorkingContours->second, workingSlice, currentTimestep); } //remove contour node from datastorage // m_ToolManager->GetDataStorage()->Remove( itWorkingContours->first ); } } ++itWorkingContours; } /* this->m_WorkingContours.clear(); // for all contours in list (currently created by tool) std::vector< std::pair >::iterator itEditingContours = this->m_EditingContours.begin(); while(itEditingContours != this->m_EditingContours.end() ) { //remove contour node from datastorage m_ToolManager->GetDataStorage()->Remove( itEditingContours->first ); ++itEditingContours; } this->m_EditingContours.clear(); std::vector< mitk::ContourModelLiveWireInteractor::Pointer >::iterator itLiveWireInteractors = this->m_LiveWireInteractors.begin(); while(itLiveWireInteractors != this->m_LiveWireInteractors.end() ) { // remove interactors from globalInteraction instance mitk::GlobalInteraction::GetInstance()->RemoveInteractor( *itLiveWireInteractors ); ++itLiveWireInteractors; } this->m_LiveWireInteractors.clear(); */ this->ClearContours(); } bool mitk::LiveWireTool2D::OnInitLiveWire ( StateMachineAction*, InteractionEvent* interactionEvent ) { mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; m_LastEventSender = positionEvent->GetSender(); m_LastEventSlice = m_LastEventSender->GetSlice(); int timestep = positionEvent->GetSender()->GetTimeStep(); m_Contour = mitk::ContourModel::New(); m_Contour->Expand(timestep+1); m_ContourModelNode = mitk::DataNode::New(); m_ContourModelNode->SetData( m_Contour ); m_ContourModelNode->SetName("working contour node"); m_ContourModelNode->SetProperty( "helper object", mitk::BoolProperty::New(true)); m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(1, 1, 0), NULL, true ); m_ContourModelNode->AddProperty( "contour.points.color", ColorProperty::New(1.0, 0.0, 0.1), NULL, true ); m_ContourModelNode->AddProperty( "contour.controlpoints.show", BoolProperty::New(true), NULL, true ); m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContour->Expand(timestep+1); m_LiveWireContourNode = mitk::DataNode::New(); m_LiveWireContourNode->SetData( m_LiveWireContour ); m_LiveWireContourNode->SetName("active livewire node"); m_LiveWireContourNode->SetProperty( "layer", IntProperty::New(100)); m_LiveWireContourNode->SetProperty( "helper object", mitk::BoolProperty::New(true)); - m_LiveWireContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true ); + m_LiveWireContourNode->SetProperty( "color", ColorProperty::New(0.1, 1.0, 0.1)); m_LiveWireContourNode->AddProperty( "contour.width", mitk::FloatProperty::New( 4.0 ), NULL, true ); m_EditingContour = mitk::ContourModel::New(); m_EditingContour->Expand(timestep+1); m_EditingContourNode = mitk::DataNode::New(); m_EditingContourNode->SetData( m_EditingContour ); m_EditingContourNode->SetName("editing node"); m_EditingContourNode->SetProperty( "layer", IntProperty::New(100)); m_EditingContourNode->SetProperty( "helper object", mitk::BoolProperty::New(true)); - m_EditingContourNode->AddProperty( "contour.color", ColorProperty::New(0.1, 1.0, 0.1), NULL, true ); + m_EditingContourNode->SetProperty( "color", ColorProperty::New(0.1, 1.0, 0.1)); m_EditingContourNode->AddProperty( "contour.points.color", ColorProperty::New(0.0, 0.0, 1.0), NULL, true ); m_EditingContourNode->AddProperty( "contour.width", mitk::FloatProperty::New( 4.0 ), NULL, true ); m_ToolManager->GetDataStorage()->Add( m_ContourModelNode ); m_ToolManager->GetDataStorage()->Add( m_LiveWireContourNode ); m_ToolManager->GetDataStorage()->Add( m_EditingContourNode ); //set current slice as input for ImageToLiveWireContourFilter m_WorkingSlice = this->GetAffectedReferenceSlice(positionEvent); m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New(); m_LiveWireFilter->SetInput(m_WorkingSlice); //map click to pixel coordinates mitk::Point3D click = positionEvent->GetPositionInWorld(); itk::Index<3> idx; m_WorkingSlice->GetGeometry()->WorldToIndex(click, idx); // get the pixel the gradient in region of 5x5 itk::Index<3> indexWithHighestGradient; AccessFixedDimensionByItk_2(m_WorkingSlice, FindHighestGradientMagnitudeByITK, 2, idx, indexWithHighestGradient); // itk::Index to mitk::Point3D click[0] = indexWithHighestGradient[0]; click[1] = indexWithHighestGradient[1]; click[2] = indexWithHighestGradient[2]; m_WorkingSlice->GetGeometry()->IndexToWorld(click, click); //set initial start point m_Contour->AddVertex( click, true, timestep ); m_LiveWireFilter->SetStartPoint(click); m_CreateAndUseDynamicCosts = true; //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnAddPoint ( StateMachineAction*, InteractionEvent* interactionEvent ) { //complete LiveWire interaction for last segment //add current LiveWire contour to the finished contour and reset //to start new segment and computation /* check if event can be handled */ mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; int timestep = positionEvent->GetSender()->GetTimeStep(); //add repulsive points to avoid to get the same path again typedef mitk::ImageLiveWireContourModelFilter::InternalImageType::IndexType IndexType; mitk::ContourModel::ConstVertexIterator iter = m_LiveWireContour->IteratorBegin(timestep); for (;iter != m_LiveWireContour->IteratorEnd(timestep); iter++) { IndexType idx; this->m_WorkingSlice->GetGeometry()->WorldToIndex((*iter)->Coordinates, idx); this->m_LiveWireFilter->AddRepulsivePoint( idx ); } //remove duplicate first vertex, it's already contained in m_Contour m_LiveWireContour->RemoveVertexAt(0, timestep); // set last added point as control point m_LiveWireContour->SetControlVertexAt(m_LiveWireContour->GetNumberOfVertices(timestep)-1, timestep); //merge contours m_Contour->Concatenate(m_LiveWireContour, timestep); //clear the livewire contour and reset the corresponding datanode m_LiveWireContour->Clear(timestep); //set new start point m_LiveWireFilter->SetStartPoint(positionEvent->GetPositionInWorld()); if( m_CreateAndUseDynamicCosts ) { //use dynamic cost map for next update m_LiveWireFilter->CreateDynamicCostMap(m_Contour); m_LiveWireFilter->SetUseDynamicCostMap(true); //m_CreateAndUseDynamicCosts = false; } //render assert( positionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnMouseMoved( StateMachineAction*, InteractionEvent* interactionEvent ) { //compute LiveWire segment from last control point to current mouse position mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; // actual LiveWire computation int timestep = positionEvent->GetSender()->GetTimeStep(); m_LiveWireFilter->SetEndPoint(positionEvent->GetPositionInWorld()); m_LiveWireFilter->SetTimeStep( timestep ); m_LiveWireFilter->Update(); m_LiveWireContour = this->m_LiveWireFilter->GetOutput(); m_LiveWireContourNode->SetData( this->m_LiveWireContour ); //render assert( positionEvent->GetSender()->GetRenderWindow() ); positionEvent->GetSender()->GetRenderingManager()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() ); return true; } bool mitk::LiveWireTool2D::OnMouseMoveNoDynamicCosts( StateMachineAction*, InteractionEvent* interactionEvent ) { //do not use dynamic cost map m_LiveWireFilter->SetUseDynamicCostMap(false); OnMouseMoved( NULL, interactionEvent); m_LiveWireFilter->SetUseDynamicCostMap(true); return true; } bool mitk::LiveWireTool2D::OnCheckPoint( const InteractionEvent* interactionEvent) { //check double click on first control point to finish the LiveWire tool // //Check distance to first point. //Transition YES if click close to first control point // const mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); if (positionEvent) { int timestep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D click = positionEvent->GetPositionInWorld(); mitk::Point3D first = this->m_Contour->GetVertexAt(0, timestep)->Coordinates; if (first.EuclideanDistanceTo(click) < 4.5) { // allow to finish return true; } else { return false; } } return false; } bool mitk::LiveWireTool2D::OnFinish( StateMachineAction*, InteractionEvent* interactionEvent ) { // finish livewire tool interaction mitk::InteractionPositionEvent* positionEvent = dynamic_cast( interactionEvent ); //const PositionEvent* positionEvent = dynamic_cast(stateEvent->GetEvent()); if (!positionEvent) return false; // actual timestep int timestep = positionEvent->GetSender()->GetTimeStep(); // remove last control point being added by double click m_Contour->RemoveVertexAt(m_Contour->GetNumberOfVertices(timestep) - 1, timestep); // save contour and corresponding plane geometry to list std::pair cp(m_ContourModelNode, dynamic_cast(positionEvent->GetSender()->GetCurrentWorldGeometry2D()->Clone().GetPointer()) ); this->m_WorkingContours.push_back(cp); std::pair ecp(m_EditingContourNode, dynamic_cast(positionEvent->GetSender()->GetCurrentWorldGeometry2D()->Clone().GetPointer()) ); this->m_EditingContours.push_back(ecp); m_LiveWireFilter->SetUseDynamicCostMap(false); this->FinishTool(); return true; } void mitk::LiveWireTool2D::FinishTool() { TimeStepType numberOfTimesteps = m_Contour->GetTimeGeometry()->CountTimeSteps(); //close contour in each timestep for( int i = 0; i <= numberOfTimesteps; i++) { m_Contour->Close(i); } m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode ); // clear live wire contour node m_LiveWireContourNode = NULL; m_LiveWireContour = NULL; //change color as visual feedback of completed livewire //m_ContourModelNode->AddProperty( "contour.color", ColorProperty::New(1.0, 1.0, 0.1), NULL, true ); //m_ContourModelNode->SetName("contour node"); //set the livewire interactor to edit control points m_ContourInteractor = mitk::ContourModelLiveWireInteractor::New(m_ContourModelNode); m_ContourInteractor->SetWorkingImage(this->m_WorkingSlice); m_ContourInteractor->SetEditingContourModelNode(this->m_EditingContourNode); m_ContourModelNode->SetInteractor(m_ContourInteractor); this->m_LiveWireInteractors.push_back( m_ContourInteractor ); //add interactor to globalInteraction instance mitk::GlobalInteraction::GetInstance()->AddInteractor(m_ContourInteractor); } bool mitk::LiveWireTool2D::OnLastSegmentDelete( StateMachineAction*, InteractionEvent* interactionEvent ) { int timestep = interactionEvent->GetSender()->GetTimeStep(); //if last point of current contour will be removed go to start state and remove nodes if( m_Contour->GetNumberOfVertices(timestep) <= 1 ) { m_ToolManager->GetDataStorage()->Remove( m_LiveWireContourNode ); m_ToolManager->GetDataStorage()->Remove( m_ContourModelNode ); m_ToolManager->GetDataStorage()->Remove( m_EditingContourNode ); m_LiveWireContour = mitk::ContourModel::New(); m_Contour = mitk::ContourModel::New(); m_ContourModelNode->SetData( m_Contour ); m_LiveWireContourNode->SetData( m_LiveWireContour ); this->ResetToStartState(); //go to start state } else //remove last segment from contour and reset livewire contour { m_LiveWireContour = mitk::ContourModel::New(); m_LiveWireContourNode->SetData(m_LiveWireContour); mitk::ContourModel::Pointer newContour = mitk::ContourModel::New(); newContour->Expand(m_Contour->GetTimeSteps()); mitk::ContourModel::VertexIterator begin = m_Contour->IteratorBegin(); //iterate from last point to next active point mitk::ContourModel::VertexIterator newLast = m_Contour->IteratorBegin() + (m_Contour->GetNumberOfVertices() - 1); //go at least one down if(newLast != begin) { newLast--; } //search next active control point while(newLast != begin && !((*newLast)->IsControlPoint) ) { newLast--; } //set position of start point for livewire filter to coordinates of the new last point m_LiveWireFilter->SetStartPoint((*newLast)->Coordinates); mitk::ContourModel::VertexIterator it = m_Contour->IteratorBegin(); //fill new Contour while(it <= newLast) { newContour->AddVertex((*it)->Coordinates, (*it)->IsControlPoint, timestep); it++; } newContour->SetClosed(m_Contour->IsClosed()); //set new contour visible m_ContourModelNode->SetData(newContour); m_Contour = newContour; assert( interactionEvent->GetSender()->GetRenderWindow() ); mitk::RenderingManager::GetInstance()->RequestUpdate( interactionEvent->GetSender()->GetRenderWindow() ); } return true; } template void mitk::LiveWireTool2D::FindHighestGradientMagnitudeByITK(itk::Image* inputImage, itk::Index<3> &index, itk::Index<3> &returnIndex) { typedef itk::Image InputImageType; typedef typename InputImageType::IndexType IndexType; unsigned long xMAX = inputImage->GetLargestPossibleRegion().GetSize()[0]; unsigned long yMAX = inputImage->GetLargestPossibleRegion().GetSize()[1]; returnIndex[0] = index[0]; returnIndex[1] = index[1]; returnIndex[2] = 0.0; double gradientMagnitude = 0.0; double maxGradientMagnitude = 0.0; /* the size and thus the region of 7x7 is only used to calculate the gradient magnitude in that region not for searching the maximum value */ //maximum value in each direction for size typename InputImageType::SizeType size; size[0] = 7; size[1] = 7; //minimum value in each direction for startRegion IndexType startRegion; startRegion[0] = index[0] - 3; startRegion[1] = index[1] - 3; if(startRegion[0] < 0) startRegion[0] = 0; if(startRegion[1] < 0) startRegion[1] = 0; if(xMAX - index[0] < 7) startRegion[0] = xMAX - 7; if(yMAX - index[1] < 7) startRegion[1] = yMAX - 7; index[0] = startRegion[0] + 3; index[1] = startRegion[1] + 3; typename InputImageType::RegionType region; region.SetSize( size ); region.SetIndex( startRegion ); typedef typename itk::GradientMagnitudeImageFilter< InputImageType, InputImageType> GradientMagnitudeFilterType; typename GradientMagnitudeFilterType::Pointer gradientFilter = GradientMagnitudeFilterType::New(); gradientFilter->SetInput(inputImage); gradientFilter->GetOutput()->SetRequestedRegion(region); gradientFilter->Update(); typename InputImageType::Pointer gradientMagnImage; gradientMagnImage = gradientFilter->GetOutput(); IndexType currentIndex; currentIndex[0] = 0; currentIndex[1] = 0; // search max (approximate) gradient magnitude for( int x = -1; x <= 1; ++x) { currentIndex[0] = index[0] + x; for( int y = -1; y <= 1; ++y) { currentIndex[1] = index[1] + y; gradientMagnitude = gradientMagnImage->GetPixel(currentIndex); //check for new max if(maxGradientMagnitude < gradientMagnitude) { maxGradientMagnitude = gradientMagnitude; returnIndex[0] = currentIndex[0]; returnIndex[1] = currentIndex[1]; returnIndex[2] = 0.0; }//end if }//end for y currentIndex[1] = index[1]; }//end for x } diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index e6bb125766..0c0318d38d 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,58 +1,59 @@ # Plug-ins must be ordered according to their dependencies if (MITK_USE_Qt4) set(MITK_EXT_PLUGINS org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF + org.mitk.gui.qt.rt.dosevisualization:ON org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dtiatlasapp:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.meshdecimation:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF ) else() set(MITK_EXT_PLUGINS # empty so far ) endif() diff --git a/Plugins/org.mitk.dicomrtview/src/internal/DcmRTV.cpp b/Plugins/org.mitk.dicomrtview/src/internal/DcmRTV.cpp new file mode 100644 index 0000000000..7ce5bf0885 --- /dev/null +++ b/Plugins/org.mitk.dicomrtview/src/internal/DcmRTV.cpp @@ -0,0 +1,478 @@ +/*=================================================================== + +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. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "DcmRTV.h" + +#include +#include +#include + +#include "mitkSegmentationObjectFactory.h" + + +// Qt +#include + + +const std::string DcmRTV::VIEW_ID = "org.mitk.views.dcmrtv"; + +DcmRTV::DcmRTV() +{ + mitk::IsoDoseLevel::ColorType color; + color[0] = 1.0; + color[1] = 1.0; + color[2] = 1.0; + m_freeIsoValues = mitk::IsoDoseLevelVector::New(); + m_freeIsoValues->push_back(mitk::IsoDoseLevel::New(0.0,color,true,false)); + + // std::string m_VolumeDir = MITK_ROOT; + // m_VolumeDir += "../mbi/Plugins/org.mbi.gui.qt.tofoscopy"; + // mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( m_VolumeDir.c_str(), false ); + // mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository(); + mitk::CoreServicePointer shadoRepo(mitk::CoreServices::GetShaderRepository()); + + std::string path = "/home/riecker/mitkShaderLighting.xml"; //mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderTOF.xml"); + std::string isoShaderName = "mitkIsoLineShader"; + MITK_INFO << "shader found under: " << path; + std::ifstream str(path.c_str()); + shadoRepo->LoadShader(str,isoShaderName); +} + +DcmRTV::~DcmRTV(){} + +void DcmRTV::SetFocus() +{ + m_Controls.buttonPerformImageProcessing->setFocus(); +} + +void DcmRTV::CreateQtPartControl( QWidget *parent ) +{ + RegisterSegmentationObjectFactory(); + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + connect( m_Controls.buttonPerformImageProcessing, SIGNAL(clicked()), this, SLOT(DoImageProcessing()) ); + connect( m_Controls.pushButton, SIGNAL(clicked()), this, SLOT(LoadRTDoseFile()) ); + connect( m_Controls.btn_isolines, SIGNAL(clicked()), this ,SLOT(LoadIsoLines())); + + connect(m_Controls.btnUpdate, SIGNAL(clicked()), this, SLOT(OnUpdateButtonClicked())); + connect(m_Controls.freeSlider, SIGNAL(valueChanged(int)), m_Controls.freeBox, SLOT(setValue(int))); + connect(m_Controls.freeBox, SIGNAL(valueChanged(int)), this, SLOT(OnFreeIsoValueChanged(int))); + connect(m_Controls.spinPrescribedDose, SIGNAL(valueChanged(double)), this, SLOT(OnPrescribedDoseChanged(double))); +} + +void DcmRTV::OnPrescribedDoseChanged(double value) +{ + if (m_selectedNode.IsNotNull()) + { + m_selectedNode->SetFloatProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), m_Controls.spinPrescribedDose->value()); + } +} + +void DcmRTV::LoadIsoLines() +{ + bool result; + if(m_selectedNode->GetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(),result) && result) + { + m_selectedNode->SetProperty("shader",mitk::ShaderProperty::New("mitkIsoLineShader")); + m_selectedNode->SetProperty("shader.mitkIsoLineShader.CustomISO", mitk::FloatProperty::New(20)); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + else + { + MITK_WARN << "Selected file has to be a Dose file!"; + } +} + +//void DcmRTV::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, +// const QList& nodes ) +//{ +// // iterate all selected objects, adjust warning visibility +// foreach( mitk::DataNode::Pointer node, nodes ) +// { +// if( node.IsNotNull() && dynamic_cast(node->GetData()) ) +// { +// m_Controls.buttonPerformImageProcessing->setEnabled( true ); +// return; +// } +// } + +// m_Controls.buttonPerformImageProcessing->setEnabled( true ); +//} + +void DcmRTV::OnFreeIsoValueChanged(int value) +{ + if(m_selectedNode.IsNotNull()) + { + m_selectedNode->SetProperty("shader.mitkIsoLineShader.CustomISO", mitk::FloatProperty::New(m_Controls.freeBox->value())); + (*m_freeIsoValues)[0]->SetDoseValue(value/100.0); + mitk::IsoDoseLevelVectorProperty::Pointer levelVecProp = mitk::IsoDoseLevelVectorProperty::New(m_freeIsoValues); + m_selectedNode->SetProperty(mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),levelVecProp); + + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); + } +} + +void DcmRTV::OnUpdateButtonClicked() +{ + if(m_selectedNode.IsNotNull()) + { + m_selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(), true); + m_selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), true); + m_selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), true); + m_selectedNode->SetFloatProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), m_Controls.spinPrescribedDose->value()); + + mitk::IsoDoseLevelSet::Pointer levelSet = mitk::IsoDoseLevelSet::New(); + + mitk::IsoDoseLevel::ColorType color; + color[0] = 0.0; + color[1] = 0.0; + color[2] = 0.4; + mitk::IsoDoseLevel::Pointer level = mitk::IsoDoseLevel::New(0.01,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.2; + color[2] = 0.8; + level = mitk::IsoDoseLevel::New(0.1,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.4; + color[2] = 1.0; + level = mitk::IsoDoseLevel::New(0.2,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.7; + color[2] = 1.0; + level = mitk::IsoDoseLevel::New(0.3,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 0.7; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(0.4,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.0; + color[1] = 1.0; + color[2] = 0.3; + level = mitk::IsoDoseLevel::New(0.5,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 1.0; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(0.6,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 1.0; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.7,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.8; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.8,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.5; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.9,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(0.95,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.2; + color[2] = 0.0; + level = mitk::IsoDoseLevel::New(1.0,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.0; + color[2] = 0.3; + level = mitk::IsoDoseLevel::New(1.07,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.0; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.1,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.4; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.2,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 1.0; + color[1] = 0.7; + color[2] = 0.7; + level = mitk::IsoDoseLevel::New(1.3,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.8; + color[1] = 0.6; + color[2] = 0.6; + level = mitk::IsoDoseLevel::New(1.4,color,true,true); + levelSet->SetIsoDoseLevel(level); + + color[0] = 0.65; + color[1] = 0.4; + color[2] = 0.4; + level = mitk::IsoDoseLevel::New(1.5,color,true,true); + levelSet->SetIsoDoseLevel(level); + + mitk::IsoDoseLevelSetProperty::Pointer levelSetProp = mitk::IsoDoseLevelSetProperty::New(levelSet); + m_selectedNode->SetProperty(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),levelSetProp); + + + (*m_freeIsoValues)[0]->SetDoseValue(m_Controls.freeBox->value()/100.0); + mitk::IsoDoseLevelVectorProperty::Pointer levelVecProp = mitk::IsoDoseLevelVectorProperty::New(m_freeIsoValues); + m_selectedNode->SetProperty(mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),levelVecProp); + + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); + } +} + +void DcmRTV::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes ) +{ + QList dataNodes = this->GetDataManagerSelection(); + if (dataNodes.empty()) + { + m_selectedNode = NULL; + m_Controls.btn_isolines->setDisabled(true); + } + else + { + m_selectedNode = dataNodes[0]; + bool result; + if(m_selectedNode->GetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(),result) && result) + { + m_Controls.btn_isolines->setEnabled(m_selectedNode.IsNotNull()); + } + else + { + m_Controls.btn_isolines->setDisabled(true); + } + } + m_Controls.btnUpdate->setEnabled(m_selectedNode.IsNotNull()); +// m_Controls.btn_isolines->setEnabled(m_selectedNode.IsNotNull()); +} + +void DcmRTV::UpdateIsoLines(int value) +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.dcm")); + + mitk::DicomSeriesReader::StringContainer files; + QStringList fileNames = dialog.getOpenFileNames(); + if(fileNames.empty()) + { + return; + } + QStringListIterator fileNamesIterator(fileNames); + while(fileNamesIterator.hasNext()) + { + files.push_back(fileNamesIterator.next().toStdString()); + } + + std::string tmp = files.front(); + const char* filename = tmp.c_str(); + char* ncFilename = const_cast(filename); + + mitk::DicomRTReader::Pointer _DicomRTReader = mitk::DicomRTReader::New(); + + DcmFileFormat file; + OFCondition outp = file.loadFile(filename, EXS_Unknown); + if(outp.bad()) + { + QMessageBox::information(NULL,"Error","Cant read the file"); + } + DcmDataset *dataset = file.getDataset(); + + mitk::DataNode::Pointer mitkImage = mitk::DataNode::New(); + mitkImage = _DicomRTReader->LoadRTDose(dataset,ncFilename); + + mitk::Image::Pointer picture = dynamic_cast(mitkImage->GetData()); + + vtkSmartPointer polyData = vtkSmartPointer::New(); + double omg = value; + polyData = _DicomRTReader->GetIsoLine(omg, picture->GetVtkImageData()); + mitk::Surface::Pointer surface = mitk::Surface::New(); + surface->SetVtkPolyData(polyData); + for(int i=0;iGetLength();++i) + { + double* ar; + polyData->GetPoint(i,ar); + } + + mitk::DataNode::Pointer node = mitk::DataNode::New(); + node->SetData(surface); + GetDataStorage()->Add(node); +} + +void DcmRTV::DoImageProcessing() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.dcm")); + + mitk::DicomSeriesReader::StringContainer files; + QStringList fileNames = dialog.getOpenFileNames(); + if(fileNames.empty()) + { + return; + } + QStringListIterator fileNamesIterator(fileNames); + while(fileNamesIterator.hasNext()) + { + files.push_back(fileNamesIterator.next().toStdString()); + } + + std::string tmp = files.front(); + const char* filename = tmp.c_str(); + char* filenameC = const_cast(filename); + + DcmFileFormat file; + OFCondition outp = file.loadFile(filename, EXS_Unknown); + if(outp.bad()) + { + QMessageBox::information(NULL,"Error","Cant read the file"); + } + DcmDataset *dataset = file.getDataset(); + + mitk::DicomRTReader::Pointer readerRT = mitk::DicomRTReader::New(); + std::deque modelVector; + modelVector = readerRT->ReadDicomFile(filenameC); + + if(modelVector.empty()) + { + QMessageBox::information(NULL, "Error", "Vector is empty ..."); + } + + for(int i=0; iSetData(modelVector.at(i)); + x->SetProperty("name", modelVector.at(i)->GetProperty("name")); + x->SetVisibility(true); + GetDataStorage()->Add(x); + } + mitk::TimeSlicedGeometry::Pointer geo = this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews( geo ); +} + +void DcmRTV::LoadRTDoseFile() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.dcm")); + + mitk::DicomSeriesReader::StringContainer files; + QStringList fileNames = dialog.getOpenFileNames(); + if(fileNames.empty()) + { + return; + } + QStringListIterator fileNamesIterator(fileNames); + while(fileNamesIterator.hasNext()) + { + files.push_back(fileNamesIterator.next().toStdString()); + } + + std::string tmp = files.front(); + const char* filename = tmp.c_str(); + char* ncFilename = const_cast(filename); + + mitk::DicomRTReader::Pointer _DicomRTReader = mitk::DicomRTReader::New(); + + DcmFileFormat file; + OFCondition outp = file.loadFile(filename, EXS_Unknown); + if(outp.bad()) + { + QMessageBox::information(NULL,"Error","Cant read the file"); + } + DcmDataset *dataset = file.getDataset(); + + mitk::DataNode::Pointer mitkImage = mitk::DataNode::New(); + mitkImage = _DicomRTReader->LoadRTDose(dataset,ncFilename); + + GetDataStorage()->Add(mitkImage); + +// mitk::DataNode::Pointer doseNode = GetDataStorage()->GetNamedNode("DicomRT Dose"); +// mitk::Image::Pointer doseImage = dynamic_cast(doseNode->GetData()); +// vtkMarchingSquares* contourFilter = vtkMarchingSquares::New(); +// std::deque surfaceStorage; + +// mitk::ExtractImageFilter::Pointer imageExtractor = mitk::ExtractImageFilter::New(); +// mitk::DataNode::Pointer img = this->GetDataStorage()->GetNamedNode("abc"); +// mitk::Image::Pointer picture = dynamic_cast(img->GetData()); +// imageExtractor->SetInput( picture ); +// imageExtractor->SetSliceDimension( 2 ); +// imageExtractor->SetSliceIndex( 12 ); +// imageExtractor->Update(); + +// vtkMarchingSquares* contourFilter = vtkMarchingSquares::New(); +// vtkPolyData* polyData = vtkPolyData::New(); + +// contourFilter->SetInput(imageExtractor->GetOutput()->GetVtkImageData()); +// contourFilter->SetNumberOfContours(1); +// contourFilter->SetValue(0,0.5); +// polyData = contourFilter->GetOutput(); + +// mitk::Surface::Pointer c = mitk::Surface::New(); +// c->SetVtkPolyData(polyData); +// mitk::Geometry3D::Pointer geo = doseImage->GetGeometry()->Clone(); +// mitk::Vector3D spacing; +// spacing.Fill(1); +// geo->SetSpacing(spacing); +// surfaceStorage.push_back(c); + +// mitk::DataNode::Pointer extractNode = mitk::DataNode::New(); +// mitk::Image::Pointer stuff = dynamic_cast(imageExtractor->GetOutput()); +// mitk::Geometry3D::Pointer geo2 = stuff->GetGeometry()->Clone(); +// mitk::Vector3D spacing2; +// spacing2.Fill(1); +// geo2->SetSpacing(spacing2); +// stuff->SetGeometry(geo); +// extractNode->SetData(stuff); +// extractNode->SetName("ExtractImage"); +// GetDataStorage()->Add(extractNode); + +// mitk::DataNode::Pointer contourNode = mitk::DataNode::New(); +// c->SetGeometry(geo2); +// contourNode->SetData(c); +// contourNode->SetName("IsoDose"); +// GetDataStorage()->Add(contourNode); + + mitk::TimeSlicedGeometry::Pointer geo3 = this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews( geo3 ); +} diff --git a/Plugins/org.mitk.dicomrtview/src/internal/DcmRTVControls.ui b/Plugins/org.mitk.dicomrtview/src/internal/DcmRTVControls.ui new file mode 100644 index 0000000000..c8ee7e424b --- /dev/null +++ b/Plugins/org.mitk.dicomrtview/src/internal/DcmRTVControls.ui @@ -0,0 +1,201 @@ + + + DcmRTVControls + + + + 0 + 0 + 244 + 329 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + + 204 + 0 + + + + + 31 + 75 + true + true + + + + Qt::LeftToRight + + + DICOM RT + + + Qt::AlignCenter + + + + + + + + 0 + 30 + + + + Do image processing + + + Load Structure Set + + + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + Load Dose File + + + + + + + + + Isolines + + + + + + + Qt::Horizontal + + + + 40 + 40 + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Prescribed dose [Gy] + + + + + + + 1 + + + + + + + + + Update iso level + + + + + + + + + Free Iso Dose [%] + + + + + + + 50 + + + 20 + + + 20 + + + Qt::Horizontal + + + + + + + 50 + + + 20 + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 220 + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/CMakeLists.txt b/Plugins/org.mitk.gui.qt.rt.dosevisualization/CMakeLists.txt new file mode 100644 index 0000000000..9a86aaa7a2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_rt_dosevisualization) + +MACRO_CREATE_MITK_CTK_PLUGIN( + EXPORT_DIRECTIVE RTDOSEVISUALIZATION_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDENCIES QmitkExt mitkDicomRT RTUI +) diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/UserManual/Manual.dox new file mode 100644 index 0000000000..8b68f8e2c8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/UserManual/Manual.dox @@ -0,0 +1,18 @@ +/** +\page org_mitk_dicomrtview Dicomrtview + +\image html icon.xpm "Icon of Dicomrtview" + +Available sections: + - \ref org_mitk_dicomrtviewOverview + +\section org_mitk_dicomrtviewOverview +Describe the features of your awesome plugin here +
    +
  • Increases productivity +
  • Creates beautiful images +
  • Generates PhD thesis +
  • Brings world peace +
+ +*/ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/UserManual/icon.xpm new file mode 100644 index 0000000000..83e48be4d8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/UserManual/icon.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static const char * icon_xpm[] = { +"16 16 2 1", +" c #FF0000", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..bfe7d676e2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_dicomrtview org.mitk.dicomrtview + \ingroup MITKPlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_dicomrtview_internal Internal + \ingroup org_mitk_dicomrtview + + \brief This subcategory includes the internal classes of the org.mitk.dicomrtview plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/files.cmake b/Plugins/org.mitk.gui.qt.rt.dosevisualization/files.cmake new file mode 100644 index 0000000000..3acb2dbbb9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/files.cmake @@ -0,0 +1,55 @@ +set(SRC_CPP_FILES +) + +set(INTERNAL_CPP_FILES + org_mitk_gui_qt_rt_dosevisualization_Activator.cpp + RTDoseVisualizer.cpp + RTUIPreferencePage.cpp + DoseVisualizationPreferencePage.cpp + mitkDoseVisPreferenceHelper.cpp + LoadingRTView.cpp +) + +set(UI_FILES + src/internal/RTDoseVisualizerControls.ui + src/internal/DoseVisualizationPreferencePageControls.ui + src/internal/RTUIPreferencePageControls.ui + src/internal/LoadingRTViewControls.ui +) + +set(MOC_H_FILES + src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.h + src/internal/RTDoseVisualizer.h + src/internal/RTUIPreferencePage.h + src/internal/DoseVisualizationPreferencePage.h + src/internal/LoadingRTView.h +) + +# list of resource files which can be used by the plug-in +# system without loading the plug-ins shared library, +# for example the icon used in the menu and tabs for the +# plug-in views in the workbench +set(CACHED_RESOURCE_FILES + resources/iso.png + resources/iso2.png + resources/icon4.png + resources/icon5.png + resources/icon7.png + plugin.xml +) + +# list of Qt .qrc files which contain additional resources +# specific to this plugin +set(QRC_FILES + +) + +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.rt.dosevisualization/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.rt.dosevisualization/manifest_headers.cmake new file mode 100644 index 0000000000..9492c2783b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "RTDoseVisualization") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ, Software development for Integrated Diagnostic and Therapy") +set(Plugin-ContactAddress "sbr@dkfz-heidelber.de") +set(Require-Plugin org.mitk.gui.qt.common org.commontk.eventadmin) diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/plugin.xml b/Plugins/org.mitk.gui.qt.rt.dosevisualization/plugin.xml new file mode 100644 index 0000000000..7ad988c76e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/plugin.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon4.png b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon4.png new file mode 100644 index 0000000000..07e3d5d412 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon4.png differ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon5.png b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon5.png new file mode 100644 index 0000000000..a3338ef126 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon5.png differ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon7.png b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon7.png new file mode 100644 index 0000000000..55f6b4cbf3 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/icon7.png differ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/iso.png b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/iso.png new file mode 100644 index 0000000000..7edf418042 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/iso.png differ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/iso2.png b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/iso2.png new file mode 100644 index 0000000000..2a73d321db Binary files /dev/null and b/Plugins/org.mitk.gui.qt.rt.dosevisualization/resources/iso2.png differ diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePage.cpp b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePage.cpp new file mode 100644 index 0000000000..e5e934987f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePage.cpp @@ -0,0 +1,377 @@ +/*=================================================================== + +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 "DoseVisualizationPreferencePage.h" +#include "mitkRTUIConstants.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "mitkIsoLevelsGenerator.h" + +#include "org_mitk_gui_qt_rt_dosevisualization_Activator.h" + +DoseVisualizationPreferencePage::DoseVisualizationPreferencePage() + : m_MainControl(0), m_Controls(0), m_referenceDoseChanged(false), m_presetMapChanged(false) +{ + +} + +DoseVisualizationPreferencePage::~DoseVisualizationPreferencePage() +{ + delete m_LevelSetModel; + delete m_DoseColorDelegate; + delete m_DoseValueDelegate; + delete m_DoseVisualDelegate; + delete m_Controls; +} + +void DoseVisualizationPreferencePage::Init(berry::IWorkbench::Pointer ) +{ + +} + +void DoseVisualizationPreferencePage::CreateQtControl(QWidget* parent) +{ + berry::IPreferencesService::Pointer prefService + = berry::Platform::GetServiceRegistry() + .GetServiceById(berry::IPreferencesService::ID); + + m_DoseVisNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + m_MainControl = new QWidget(parent); + m_Controls = new Ui::DoseVisualizationPreferencePageControls; + m_Controls->setupUi( m_MainControl ); + + m_LevelSetModel = new QmitkIsoDoseLevelSetModel(this); + m_DoseColorDelegate = new QmitkDoseColorDelegate(this); + m_DoseValueDelegate = new QmitkDoseValueDelegate(this); + m_DoseVisualDelegate = new QmitkDoseVisualStyleDelegate(this); + + this->m_Controls->isoLevelSetView->setModel(m_LevelSetModel); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(0,m_DoseColorDelegate); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(1,m_DoseValueDelegate); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(2,m_DoseVisualDelegate); + this->m_Controls->isoLevelSetView->setItemDelegateForColumn(3,m_DoseVisualDelegate); + this->m_Controls->isoLevelSetView->setContextMenuPolicy(Qt::CustomContextMenu); + + connect(m_Controls->spinReferenceDose, SIGNAL(valueChanged(double)), m_LevelSetModel, SLOT(setReferenceDose(double))); + connect(m_Controls->spinReferenceDose, SIGNAL(valueChanged(double)), this, SLOT(OnReferenceDoseChanged(double))); + connect(m_Controls->checkGlobalSync, SIGNAL(toggled(bool)), m_Controls->spinReferenceDose, SLOT(setEnabled(bool))); + connect(m_Controls->radioAbsDose, SIGNAL(toggled(bool)), m_LevelSetModel, SLOT(setShowAbsoluteDose(bool))); + connect(m_Controls->isoLevelSetView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnShowContextMenuIsoSet(const QPoint&))); + connect(m_Controls->listPresets, SIGNAL(currentItemChanged ( QListWidgetItem *, QListWidgetItem *)), this, SLOT(OnCurrentItemChanged ( QListWidgetItem *, QListWidgetItem *))); + connect(m_Controls->btnAddPreset, SIGNAL(clicked(bool)), this, SLOT(OnAddPresetClicked(bool))); + connect(m_Controls->btnDelPreset, SIGNAL(clicked(bool)), this, SLOT(OnDelPresetClicked(bool))); + connect(m_Controls->btnResetPreset, SIGNAL(clicked(bool)), this, SLOT(OnResetPresetClicked(bool))); + connect(m_Controls->btnDelLevel, SIGNAL(clicked(bool)), this, SLOT(OnDelLevelClicked(bool))); + connect(m_Controls->btnAddLevel, SIGNAL(clicked(bool)), this, SLOT(OnAddLevelClicked(bool))); + + this->Update(); +} + +QWidget* DoseVisualizationPreferencePage::GetQtControl() const +{ + return m_MainControl; +} + +bool DoseVisualizationPreferencePage::PerformOk() +{ + m_DoseVisNode->PutBool(mitk::rt::UIConstants::DOSE_DISPLAY_ABSOLUTE_ID,m_Controls->radioAbsDose->isChecked()); + m_DoseVisNode->PutBool(mitk::rt::UIConstants::GLOBAL_VISIBILITY_COLORWASH_ID,m_Controls->checkGlobalVisColorWash->isChecked()); + m_DoseVisNode->PutBool(mitk::rt::UIConstants::GLOBAL_VISIBILITY_ISOLINES_ID,m_Controls->checkGlobalVisIsoLine->isChecked()); + m_DoseVisNode->PutDouble(mitk::rt::UIConstants::REFERENCE_DOSE_ID,m_Controls->spinReferenceDose->value()); + m_DoseVisNode->PutBool(mitk::rt::UIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, m_Controls->checkGlobalSync->isChecked()); + + mitk::rt::StorePresetsMap(this->m_Presets); + + if (this->m_Presets.find(this->m_selectedPresetName)==this->m_Presets.end()) + { //the preset currently selected in the application is not available any more. Change it to a valid one. + mitk::rt::SetSelectedPresetName(this->m_Presets.begin()->first); + } + + if (this->m_LevelSetModel->isModified()) + { + this->m_presetMapChanged = true; + } + + if (m_referenceDoseChanged) + { + mitk::rt::SignalReferenceDoseChange(m_Controls->checkGlobalSync->isChecked(), m_Controls->spinReferenceDose->value(), mitk::org_mitk_gui_qt_rt_dosevisualization_Activator::GetContext()); + } + + if (m_presetMapChanged) + { + mitk::rt::SignalPresetMapChange(mitk::org_mitk_gui_qt_rt_dosevisualization_Activator::GetContext()); + } + + return true; +} + +void DoseVisualizationPreferencePage::PerformCancel() +{ +} + +void DoseVisualizationPreferencePage::Update() +{ + m_Controls->checkGlobalVisColorWash->setChecked(m_DoseVisNode->GetBool(mitk::rt::UIConstants::GLOBAL_VISIBILITY_COLORWASH_ID, true)); + m_Controls->checkGlobalVisIsoLine->setChecked(m_DoseVisNode->GetBool(mitk::rt::UIConstants::GLOBAL_VISIBILITY_ISOLINES_ID, true)); + m_Controls->radioAbsDose->setChecked(m_DoseVisNode->GetBool(mitk::rt::UIConstants::DOSE_DISPLAY_ABSOLUTE_ID, true)); + m_Controls->radioRelDose->setChecked(!(m_DoseVisNode->GetBool(mitk::rt::UIConstants::DOSE_DISPLAY_ABSOLUTE_ID, false))); + m_Controls->spinReferenceDose->setValue(m_DoseVisNode->GetDouble(mitk::rt::UIConstants::REFERENCE_DOSE_ID, mitk::rt::UIConstants::DEFAULT_REFERENCE_DOSE_VALUE)); + m_Controls->checkGlobalSync->setChecked(m_DoseVisNode->GetBool(mitk::rt::UIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, true)); + + m_referenceDoseChanged = false; + m_presetMapChanged = false; + + + berry::IPreferences::Pointer presetsNode = m_DoseVisNode->Node(mitk::rt::UIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + this->m_Presets = mitk::rt::LoadPresetsMap(); + this->m_selectedPresetName = mitk::rt::GetSelectedPresetName(); + UpdatePresetsWidgets(); +} + + +mitk::IsoDoseLevelSet* DoseVisualizationPreferencePage::GetSelectedIsoLevelSet() +{ + QListWidgetItem* selectedItem = m_Controls->listPresets->currentItem(); + + mitk::IsoDoseLevelSet::Pointer result; + + if (selectedItem) + { + result = m_Presets[selectedItem->text().toStdString()]; + } + + return result; +} + +void DoseVisualizationPreferencePage::UpdateLevelSetWidgets() +{ + this->m_Controls->btnAddLevel->setEnabled(this->GetSelectedIsoLevelSet()!=NULL); + + QModelIndex selectedIndex = m_Controls->isoLevelSetView->currentIndex(); + this->m_Controls->btnDelLevel->setEnabled(this->GetSelectedIsoLevelSet()!=NULL && selectedIndex.isValid()); +} + +void DoseVisualizationPreferencePage::UpdatePresetsWidgets() +{ + m_Controls->listPresets->clear(); + + QListWidgetItem* selectedItem = NULL; + for (PresetMapType::iterator pos = m_Presets.begin(); pos != m_Presets.end(); ++pos) + { + QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(pos->first)); + if (!selectedItem) + { + selectedItem = item; + } + + m_Controls->listPresets->addItem(item); + } + + if (selectedItem) + { + m_Controls->listPresets->setCurrentItem(selectedItem); + } + + if (this->m_LevelSetModel->isModified()) + { + this->m_presetMapChanged = true; + } + + this->m_LevelSetModel->setIsoDoseLevelSet(this->GetSelectedIsoLevelSet()); + + m_Controls->btnDelPreset->setEnabled((m_Controls->listPresets->currentItem() != NULL) && (m_Controls->listPresets->count()>1)); +} + +void DoseVisualizationPreferencePage::OnCurrentItemChanged ( QListWidgetItem * currentItem, QListWidgetItem * previousItem) +{ + this->m_LevelSetModel->setIsoDoseLevelSet(this->GetSelectedIsoLevelSet()); +} + +void DoseVisualizationPreferencePage::OnShowContextMenuIsoSet(const QPoint& pos) +{ + QPoint globalPos = m_Controls->isoLevelSetView->viewport()->mapToGlobal(pos); + + QModelIndex selectedIndex = m_Controls->isoLevelSetView->currentIndex(); + + QMenu viewMenu; + QAction* addLevelAct = viewMenu.addAction("Add new level"); + QAction* delLevelAct = viewMenu.addAction("Delete selected level"); + delLevelAct->setEnabled(selectedIndex.isValid()); + viewMenu.addSeparator(); + QAction* invertIsoLineAct = viewMenu.addAction("Invert iso line visibility"); + QAction* activateIsoLineAct = viewMenu.addAction("Activate all iso lines"); + QAction* deactivateIsoLineAct = viewMenu.addAction("Deactivate all iso lines"); + viewMenu.addSeparator(); + QAction* invertColorWashAct = viewMenu.addAction("Invert color wash visibility"); + QAction* activateColorWashAct = viewMenu.addAction("Activate all color wash levels"); + QAction* deactivateColorWashAct = viewMenu.addAction("Deactivate all color wash levels"); + viewMenu.addSeparator(); + QAction* swapAct = viewMenu.addAction("Swap iso line/color wash visibility"); + + QAction* selectedItem = viewMenu.exec(globalPos); + if (selectedItem == invertIsoLineAct) + { + this->m_LevelSetModel->invertVisibilityIsoLines(); + } + else if (selectedItem == activateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(true); + } + else if (selectedItem == deactivateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(false); + } + else if (selectedItem == invertColorWashAct) + { + this->m_LevelSetModel->invertVisibilityColorWash(); + } + else if (selectedItem == activateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(true); + } + else if (selectedItem == deactivateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(false); + } + else if (selectedItem == swapAct) + { + this->m_LevelSetModel->swapVisibility(); + } + else if (selectedItem == addLevelAct) + { + this->m_LevelSetModel->addLevel(); + } + else if (selectedItem == delLevelAct) + { + this->m_LevelSetModel->deleteLevel(selectedIndex); + } +} + +void DoseVisualizationPreferencePage::OnAddPresetClicked(bool checked) +{ + bool done = false; + QString name = tr("new_preset"); + while (!done) + { + bool ok; + name = QInputDialog::getText(m_MainControl, tr("Define name of new preset."), tr("Preset name:"), QLineEdit::Normal, name, &ok); + + if (!ok) + { + return; //cancled by user; + } + + bool uniqueName = m_Presets.find(name.toStdString()) == m_Presets.end(); + if (!uniqueName) + { + QMessageBox box; + box.setText(tr("New preset name is not unique. Please, choose another one.")); + box.exec(); + } + + bool validName = name.indexOf(tr("/")) ==-1; + if (!validName) + { + QMessageBox box; + box.setText(tr("New preset name is not valid. Please don't use \"/\".")); + box.exec(); + } + + done = uniqueName && validName; + } + + mitk::IsoDoseLevelSet::Pointer newSet = mitk::rt::GeneratIsoLevels_Virtuos(); + m_Presets.insert(std::make_pair(name.toStdString(),newSet)); + + m_presetMapChanged = true; + + UpdatePresetsWidgets(); +} + +void DoseVisualizationPreferencePage::OnDelPresetClicked(bool checked) +{ + QListWidgetItem* selectedItem = m_Controls->listPresets->currentItem(); + + if (selectedItem) + { + if (m_Controls->listPresets->count() > 1) + { + m_Presets.erase(selectedItem->text().toStdString()); + + m_presetMapChanged = true; + this->UpdatePresetsWidgets(); + } + } +} + + +void DoseVisualizationPreferencePage::OnResetPresetClicked(bool checked) +{ + QMessageBox box; + box.setText("Do you want to reset the presets?"); + box.setInformativeText("If you reset the presets. All user defined presets will be removed and the default presets will be loaded."); + box.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + box.setDefaultButton(QMessageBox::No); + int ret = box.exec(); + + if (ret == QMessageBox::Yes) + { + mitk::IsoDoseLevelSet::Pointer newSet = mitk::rt::GeneratIsoLevels_Virtuos(); + m_Presets.clear(); + m_Presets.insert(std::make_pair("Virtuos",newSet)); + + m_presetMapChanged = true; + + UpdatePresetsWidgets(); + } +} + + +void DoseVisualizationPreferencePage::OnAddLevelClicked(bool checked) +{ + this->m_LevelSetModel->addLevel(); +} + +void DoseVisualizationPreferencePage::OnDelLevelClicked(bool checked) +{ + QModelIndex selectedIndex = m_Controls->isoLevelSetView->currentIndex(); + + if (!selectedIndex.isValid()) + { + selectedIndex = m_Controls->isoLevelSetView->indexAt(QPoint(1,1)); + } + + this->m_LevelSetModel->deleteLevel(selectedIndex); +} + +void DoseVisualizationPreferencePage::OnReferenceDoseChanged(double dose) +{ + this->m_referenceDoseChanged = true; +}; diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePage.h b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePage.h new file mode 100644 index 0000000000..ed45400c1b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePage.h @@ -0,0 +1,123 @@ +/*=================================================================== + +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 __DOSE_VISUALIZATION_PREFERENCE_PAGE_H +#define __DOSE_VISUALIZATION_PREFERENCE_PAGE_H + +#include "berryIQtPreferencePage.h" +#include "berryIPreferences.h" + +#include "ui_DoseVisualizationPreferencePageControls.h" + +#include +#include "mitkDoseVisPreferenceHelper.h" + +/*forward declarations*/ +class QmitkIsoDoseLevelSetModel; +class QmitkDoseColorDelegate; +class QmitkDoseValueDelegate; +class QmitkDoseVisualStyleDelegate; + +class QWidget; + +/** +* \class DoseVisualizationPreferencePage +* \brief Preference page for RT Dose visualization +*/ +class DoseVisualizationPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + DoseVisualizationPreferencePage(); + ~DoseVisualizationPreferencePage(); + + /** + * \brief Called by framework to initialize this preference page, but currently does nothing. + * \param workbench The workbench. + */ + void Init(berry::IWorkbench::Pointer workbench); + + /** + * \brief Called by framework to create the GUI, and connect signals and slots. + * \param widget The Qt widget that acts as parent to all GUI components, as this class itself is not derived from QWidget. + */ + void CreateQtControl(QWidget* widget); + + /** + * \brief Required by framework to get hold of the GUI. + * \return QWidget* the top most QWidget for the GUI. + */ + QWidget* GetQtControl() const; + + /** + * \see IPreferencePage::PerformOk + */ + virtual bool PerformOk(); + + /** + * \see IPreferencePage::PerformCancel + */ + virtual void PerformCancel(); + + /** + * \see IPreferencePage::Update + */ + virtual void Update(); + + public slots: + + void OnCurrentItemChanged ( QListWidgetItem * currentItem, QListWidgetItem * previousItem); + void OnShowContextMenuIsoSet(const QPoint& pos); + void OnAddPresetClicked(bool checked); + void OnDelPresetClicked(bool checked); + void OnResetPresetClicked(bool checked); + void OnAddLevelClicked(bool checked); + void OnDelLevelClicked(bool checked); + void OnReferenceDoseChanged(double dose); + +protected: + + /** Method updates the presets widgets according to the internal members*/ + void UpdatePresetsWidgets(); + /** Method actualizes the level set model and edit buttons according to the currently selected item in the presets list view*/ + void UpdateLevelSetWidgets(); + + /** Method returns the iso dose level set selected in the preset lists. May return NULL if no preset is selected.*/ + mitk::IsoDoseLevelSet* GetSelectedIsoLevelSet(); + + QWidget *m_MainControl; + Ui::DoseVisualizationPreferencePageControls* m_Controls; + + berry::IPreferences::Pointer m_DoseVisNode; + + typedef mitk::rt::PresetMapType PresetMapType; + PresetMapType m_Presets; + std::string m_selectedPresetName; + + bool m_referenceDoseChanged; + bool m_presetMapChanged; + + QmitkIsoDoseLevelSetModel* m_LevelSetModel; + QmitkDoseColorDelegate* m_DoseColorDelegate; + QmitkDoseValueDelegate* m_DoseValueDelegate; + QmitkDoseVisualStyleDelegate* m_DoseVisualDelegate; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePageControls.ui b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePageControls.ui new file mode 100644 index 0000000000..ffbdbcad21 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/DoseVisualizationPreferencePageControls.ui @@ -0,0 +1,307 @@ + + + DoseVisualizationPreferencePageControls + + + + 0 + 0 + 714 + 651 + + + + + 0 + 0 + + + + QmitkTemplate + + + + 5 + + + 5 + + + + + Global viszualization settings: + + + + + + + 0 + 0 + + + + + 105 + 0 + + + + Qt::NoFocus + + + Reference dose [Gy]: + + + + + + + + 0 + 0 + + + + + 65 + 0 + + + + Dose display: + + + + + + + + + relative [%] + + + true + + + + + + + absolute [Gy] + + + + + + + + + Global visibility: + + + + + + + + + Isolines + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + Colorwash + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + + + + + + + + + + + 1 + + + 0.100000000000000 + + + 9999.000000000000000 + + + + + + + global sync + + + + + + + + + + + + Iso dose level presets: + + + + 5 + + + 5 + + + + + + 16777215 + 100 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Remove + + + + + + + Reset + + + + + + + + + Preset editor: + + + + + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + 30 + 20 + + + + 75 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add level + + + + + + + Remove level + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTView.cpp b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTView.cpp new file mode 100644 index 0000000000..d57b173c73 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTView.cpp @@ -0,0 +1,131 @@ +/*=================================================================== + +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. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "LoadingRTView.h" + +// Qt +#include +#include + +#include + +const std::string LoadingRTView::VIEW_ID = "org.mitk.views.loadingrtview"; + +void LoadingRTView::SetFocus(){} + +void LoadingRTView::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + connect( m_Controls.btnLoadStruct, SIGNAL(clicked()), this, SLOT(LoadRTStructureSet()) ); + connect( m_Controls.btnLoadDose, SIGNAL(clicked()), this, SLOT(LoadRTDoseFile()) ); +} + +void LoadingRTView::LoadRTStructureSet() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.dcm")); + + mitk::DicomSeriesReader::StringContainer files; + QStringList fileNames = dialog.getOpenFileNames(); + if(fileNames.empty()) + { + return; + } + QStringListIterator fileNamesIterator(fileNames); + while(fileNamesIterator.hasNext()) + { + files.push_back(fileNamesIterator.next().toStdString()); + } + + std::string tmp = files.front(); + const char* filename = tmp.c_str(); + char* filenameC = const_cast(filename); + + DcmFileFormat file; + OFCondition outp = file.loadFile(filename, EXS_Unknown); + if(outp.bad()) + { + QMessageBox::information(NULL,"Error","Cant read the file"); + } + DcmDataset *dataset = file.getDataset(); + + mitk::DicomRTReader::Pointer readerRT = mitk::DicomRTReader::New(); + std::deque modelVector; + modelVector = readerRT->ReadDicomFile(filenameC); + + if(modelVector.empty()) + { + QMessageBox::information(NULL, "Error", "Vector is empty ..."); + } + + for(int i=0; iSetData(modelVector.at(i)); + x->SetProperty("name", modelVector.at(i)->GetProperty("name")); + x->SetVisibility(true); + GetDataStorage()->Add(x); + } + mitk::TimeSlicedGeometry::Pointer geo = this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews( geo ); +} + +void LoadingRTView::LoadRTDoseFile() +{ + QFileDialog dialog; + dialog.setNameFilter(tr("Images (*.dcm")); + + mitk::DicomSeriesReader::StringContainer files; + QStringList fileNames = dialog.getOpenFileNames(); + if(fileNames.empty()) + { + return; + } + QStringListIterator fileNamesIterator(fileNames); + while(fileNamesIterator.hasNext()) + { + files.push_back(fileNamesIterator.next().toStdString()); + } + + std::string tmp = files.front(); + const char* filename = tmp.c_str(); + char* ncFilename = const_cast(filename); + + mitk::DicomRTReader::Pointer _DicomRTReader = mitk::DicomRTReader::New(); + + DcmFileFormat file; + OFCondition outp = file.loadFile(filename, EXS_Unknown); + if(outp.bad()) + { + QMessageBox::information(NULL,"Error","Cant read the file"); + } + DcmDataset *dataset = file.getDataset(); + + mitk::DataNode::Pointer mitkImage = mitk::DataNode::New(); + mitkImage = _DicomRTReader->LoadRTDose(dataset,ncFilename); + + GetDataStorage()->Add(mitkImage); + + mitk::TimeSlicedGeometry::Pointer geo3 = this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews( geo3 ); +} diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTView.h b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTView.h new file mode 100644 index 0000000000..893221b596 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTView.h @@ -0,0 +1,61 @@ +/*=================================================================== + +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 LoadingRTView_h +#define LoadingRTView_h + +#include + +#include + +#include "ui_LoadingRTViewControls.h" + + +/** + \brief LoadingRTView + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class LoadingRTView : 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) + Q_OBJECT + + public: + + static const std::string VIEW_ID; + + protected slots: + + void LoadRTDoseFile(); + void LoadRTStructureSet(); + + protected: + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + Ui::LoadingRTViewControls m_Controls; + +}; + +#endif // LoadingRTView_h diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTViewControls.ui b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTViewControls.ui new file mode 100644 index 0000000000..95f9893a6e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/LoadingRTViewControls.ui @@ -0,0 +1,100 @@ + + + LoadingRTViewControls + + + + 0 + 0 + 288 + 161 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + Loading RT Data + + + + + + + + + + 0 + 60 + + + + RT Struct + + + + :/org.mitk.gui.qt.rt.dosevisualization/resources/icon7.png:/org.mitk.gui.qt.rt.dosevisualization/resources/icon7.png + + + + 50 + 50 + + + + + + + + + 0 + 60 + + + + RT Dose + + + + :/org.mitk.gui.qt.rt.dosevisualization/resources/icon5.png:/org.mitk.gui.qt.rt.dosevisualization/resources/icon5.png + + + + 50 + 50 + + + + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizer.cpp b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizer.cpp new file mode 100644 index 0000000000..9a0cae2a7b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizer.cpp @@ -0,0 +1,807 @@ +/*=================================================================== + +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. + +===================================================================*/ + + +// Qt +#include +#include + +// Blueberry +#include +#include + +// MITK +#include + +#include +#include + +// Qmitk +#include "RTDoseVisualizer.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "org_mitk_gui_qt_rt_dosevisualization_Activator.h" + +#include +#include +#include + +#include +#include +#include "QmitkRenderWindow.h" +#include + +#include "mitkSurfaceGLMapper2D.h" +#include "mitkPolyDataGLMapper2D.h" +#include "mitkSurfaceVtkMapper3D.h" + +#include "mitkSliceNavigationController.h" + +const std::string RTDoseVisualizer::VIEW_ID = "org.mitk.views.rt.dosevisualization"; + +RTDoseVisualizer::RTDoseVisualizer() +{ + m_freeIsoValues = mitk::IsoDoseLevelVector::New(); + m_selectedNodeIsoSet = mitk::IsoDoseLevelSet::New(); + + m_freeIsoFilter = vtkSmartPointer::New(); + + m_selectedNode = NULL; + m_selectedPresetName = ""; + m_internalUpdate = false; + m_PrescribedDose_Data = 0.0; + + //hier crash ?! +// QmitkRenderWindow* rw = this->GetRenderWindowPart()->GetQmitkRenderWindow(name); + +// itk::MemberCommand::Pointer sliceChangedCommand = +// itk::MemberCommand::New(); +// sliceChangedCommand->SetCallbackFunction(this, &RTDoseVisualizer::OnSliceChanged); +// rw->GetSliceNavigationController()->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(NULL,0), sliceChangedCommand); + +// mitk::CoreServicePointer shadoRepo(mitk::CoreServices::GetShaderRepository()); +// std::string path = "/home/riecker/mitkShaderLighting.xml"; +// std::string isoShaderName = "mitkIsoLineShader"; +// MITK_INFO << "shader found under: " << path; +// std::ifstream str(path.c_str()); +// shadoRepo->LoadShader(str,isoShaderName); +} + +RTDoseVisualizer::~RTDoseVisualizer() +{ + delete m_LevelSetModel; + delete m_DoseColorDelegate; + delete m_DoseValueDelegate; + delete m_DoseVisualDelegate; +} + +void RTDoseVisualizer::InitScrolling(){ + QmitkRenderWindow* rw = this->GetRenderWindowPart()->GetQmitkRenderWindow("axial"); + + itk::MemberCommand::Pointer sliceChangedCommand = + itk::MemberCommand::New(); + sliceChangedCommand->SetCallbackFunction(this, &RTDoseVisualizer::OnSliceChanged); + rw->GetSliceNavigationController()->AddObserver(mitk::SliceNavigationController::GeometrySliceEvent(NULL,0), sliceChangedCommand); +} + +void RTDoseVisualizer::SetFocus() +{ +} + +void RTDoseVisualizer::OnSliceChanged(itk::Object *sender, const itk::EventObject &e) +{ + for(int i=0; iRemove(m_StdIsoLines.at(i)); + } + m_StdIsoLines.clear(); + this->UpdateStdIsolines(); +} + +void RTDoseVisualizer::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + + m_LevelSetModel = new QmitkIsoDoseLevelSetModel(this); + m_LevelSetModel->setVisibilityEditOnly(true); + m_DoseColorDelegate = new QmitkDoseColorDelegate(this); + m_DoseValueDelegate = new QmitkDoseValueDelegate(this); + m_DoseVisualDelegate = new QmitkDoseVisualStyleDelegate(this); + + this->UpdateByPreferences(); + this->ActualizeIsoLevelsForAllDoseDataNodes(); + this->ActualizeReferenceDoseForAllDoseDataNodes(); + this->ActualizeDisplayStyleForAllDoseDataNodes(); + + this->m_Controls.isoLevelSetView->setModel(m_LevelSetModel); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(0,m_DoseColorDelegate); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(1,m_DoseValueDelegate); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(2,m_DoseVisualDelegate); + this->m_Controls.isoLevelSetView->setItemDelegateForColumn(3,m_DoseVisualDelegate); + this->m_Controls.isoLevelSetView->setContextMenuPolicy(Qt::CustomContextMenu); + + this->m_Controls.btnRemoveFreeValue->setDisabled(true); + + connect(m_Controls.btnConvert, SIGNAL(clicked()), this, SLOT(OnConvertButtonClicked())); + connect(m_Controls.spinReferenceDose, SIGNAL(valueChanged(double)), this, SLOT(OnReferenceDoseChanged(double))); + connect(m_Controls.spinReferenceDose, SIGNAL(valueChanged(double)), m_LevelSetModel, SLOT(setReferenceDose(double))); + connect(m_Controls.radioAbsDose, SIGNAL(toggled(bool)), m_LevelSetModel, SLOT(setShowAbsoluteDose(bool))); + connect(m_Controls.radioAbsDose, SIGNAL(toggled(bool)), this, SLOT(OnAbsDoseToggled(bool))); + connect(m_Controls.btnAddFreeValue, SIGNAL(clicked()), this, SLOT(OnAddFreeValueClicked())); + connect(m_Controls.btnRemoveFreeValue, SIGNAL(clicked()), this, SLOT(OnRemoveFreeValueClicked())); + connect(m_Controls.checkGlobalVisColorWash, SIGNAL(toggled(bool)), this, SLOT(OnGlobalVisColorWashToggled(bool))); + connect(m_Controls.checkGlobalVisIsoLine, SIGNAL(toggled(bool)), this, SLOT(OnGlobalVisIsoLineToggled(bool))); + connect(m_Controls.isoLevelSetView, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnShowContextMenuIsoSet(const QPoint&))); + connect(m_Controls.comboPresets, SIGNAL(currentIndexChanged ( const QString&)), this, SLOT(OnCurrentPresetChanged(const QString&))); + connect(m_Controls.btnUsePrescribedDose, SIGNAL(clicked()), this, SLOT(OnUsePrescribedDoseClicked())); + + ctkServiceReference ref = mitk::org_mitk_gui_qt_rt_dosevisualization_Activator::GetContext()->getServiceReference(); + + ctkDictionary propsForSlot; + if (ref) + { + ctkEventAdmin* eventAdmin = mitk::org_mitk_gui_qt_rt_dosevisualization_Activator::GetContext()->getService(ref); + + propsForSlot[ctkEventConstants::EVENT_TOPIC] = mitk::rt::CTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED.c_str(); + eventAdmin->subscribeSlot(this, SLOT(OnHandleCTKEventPresetsChanged(ctkEvent)), propsForSlot); + + propsForSlot[ctkEventConstants::EVENT_TOPIC] = mitk::rt::CTKEventConstants::TOPIC_REFERENCE_DOSE_CHANGED.c_str(); + eventAdmin->subscribeSlot(this, SLOT(OnHandleCTKEventReferenceDoseChanged(ctkEvent)), propsForSlot); + } + + this->UpdateBySelectedNode(); +} + +void RTDoseVisualizer::OnReferenceDoseChanged(double value) +{ + if (! m_internalUpdate) + { + mitk::DoseValueAbs referenceDose = 0.0; + bool globalSync = mitk::rt::GetReferenceDoseValue(referenceDose); + + if (globalSync) + { + mitk::rt::SetReferenceDoseValue(globalSync, value); + this->ActualizeReferenceDoseForAllDoseDataNodes(); + } + else + { + if (this->m_selectedNode.IsNotNull()) + { + this->m_selectedNode->SetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), value); + } + } + if (this->m_selectedNode.IsNotNull()) + { + mitk::TransferFunction::ControlPoints scalarOpacityPoints; + scalarOpacityPoints.push_back( std::make_pair(0, 1 ) ); + vtkSmartPointer transferFunction = vtkSmartPointer::New(); + mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = this->m_Presets[this->m_selectedPresetName]; + for(mitk::IsoDoseLevelSet::ConstIterator setIT = isoDoseLevelSet->Begin(); setIT != isoDoseLevelSet->End(); ++setIT) + { + float *hsv = new float[3]; + vtkSmartPointer cCalc = vtkSmartPointer::New(); + if(setIT->GetVisibleColorWash()){ + cCalc->RGBToHSV(setIT->GetColor()[0],setIT->GetColor()[1],setIT->GetColor()[2],&hsv[0],&hsv[1],&hsv[2]); + transferFunction->AddHSVPoint(setIT->GetDoseValue()*value,hsv[0],hsv[1],hsv[2],1.0,1.0); + } + else + { + scalarOpacityPoints.push_back( std::make_pair(setIT->GetDoseValue()*value, 1 ) ); + } + } + mitk::TransferFunction::Pointer mitkTransFunc = mitk::TransferFunction::New(); + mitk::TransferFunctionProperty::Pointer mitkTransFuncProp = mitk::TransferFunctionProperty::New(); + mitkTransFunc->SetColorTransferFunction(transferFunction); + mitkTransFunc->SetScalarOpacityPoints(scalarOpacityPoints); + mitkTransFuncProp->SetValue(mitkTransFunc); + + mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); + renderingMode->SetValue(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); + + m_selectedNode->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); + m_selectedNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); + + mitk::TimeSlicedGeometry::Pointer geo3 = this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews( geo3 ); + } + } +} + +void RTDoseVisualizer::OnAddFreeValueClicked() +{ + QColor newColor; + //Use HSV schema of QColor to calculate a different color depending on the + //number of already existing free iso lines. + newColor.setHsv((m_freeIsoValues->Size()*85)%360,255,255); + + mitk::DataNode::Pointer isoNode = this->UpdatePolyData(1,m_Controls.spinReferenceDose->value()*0.5,m_Controls.spinReferenceDose->value()*0.5); + m_FreeIsoLines.push_back(isoNode); + + mitk::IsoDoseLevel::ColorType color; + color[0] = newColor.redF(); + color[1] = newColor.greenF(); + color[2] = newColor.blueF(); + m_freeIsoValues->push_back(mitk::IsoDoseLevel::New(0.5,color,true,false)); + UpdateFreeIsoValues(); + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); + if(m_FreeIsoLines.size()>=3) + this->m_Controls.btnAddFreeValue->setDisabled(true); + this->m_Controls.btnRemoveFreeValue->setEnabled(true); +} + +void RTDoseVisualizer::OnRemoveFreeValueClicked() +{ + m_freeIsoValues->pop_back(); + mitk::DataNode::Pointer isoNode = m_FreeIsoLines.at(m_FreeIsoLines.size()-1); + m_FreeIsoLines.pop_back(); + m_Filters.pop_back(); + if(m_FreeIsoLines.empty()) + this->m_Controls.btnRemoveFreeValue->setDisabled(true); + if(m_FreeIsoLines.size()<3) + this->m_Controls.btnAddFreeValue->setEnabled(true); + this->GetDataStorage()->Remove(isoNode); + UpdateFreeIsoValues(); +} + +void RTDoseVisualizer::OnUsePrescribedDoseClicked() +{ + m_Controls.spinReferenceDose->setValue(this->m_PrescribedDose_Data); +}; + + +void RTDoseVisualizer::OnShowContextMenuIsoSet(const QPoint& pos) +{ + QPoint globalPos = m_Controls.isoLevelSetView->viewport()->mapToGlobal(pos); + + QMenu viewMenu; + QAction* invertIsoLineAct = viewMenu.addAction("Invert iso line visibility"); + QAction* activateIsoLineAct = viewMenu.addAction("Activate all iso lines"); + QAction* deactivateIsoLineAct = viewMenu.addAction("Deactivate all iso lines"); + viewMenu.addSeparator(); + QAction* invertColorWashAct = viewMenu.addAction("Invert color wash visibility"); + QAction* activateColorWashAct = viewMenu.addAction("Activate all color wash levels"); + QAction* deactivateColorWashAct = viewMenu.addAction("Deactivate all color wash levels"); + viewMenu.addSeparator(); + QAction* swapAct = viewMenu.addAction("Swap iso line/color wash visibility"); + // ... + + QAction* selectedItem = viewMenu.exec(globalPos); + if (selectedItem == invertIsoLineAct) + { + this->m_LevelSetModel->invertVisibilityIsoLines(); + } + else if (selectedItem == activateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(true); + } + else if (selectedItem == deactivateIsoLineAct) + { + this->m_LevelSetModel->switchVisibilityIsoLines(false); + } + else if (selectedItem == invertColorWashAct) + { + this->m_LevelSetModel->invertVisibilityColorWash(); + } + else if (selectedItem == activateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(true); + } + else if (selectedItem == deactivateColorWashAct) + { + this->m_LevelSetModel->switchVisibilityColorWash(false); + } + else if (selectedItem == swapAct) + { + this->m_LevelSetModel->swapVisibility(); + } +} + +void RTDoseVisualizer::UpdateFreeIsoValues() +{ + this->m_Controls.listFreeValues->clear(); + + for (mitk::IsoDoseLevelVector::Iterator pos = this->m_freeIsoValues->Begin(); pos != this->m_freeIsoValues->End(); ++pos) + { + QListWidgetItem* item = new QListWidgetItem; + item->setSizeHint(QSize(0,25)); + QmitkFreeIsoDoseLevelWidget* widget = new QmitkFreeIsoDoseLevelWidget; + + float pref; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + + widget->setIsoDoseLevel(pos->Value().GetPointer()); + widget->setReferenceDose(pref); + connect(m_Controls.spinReferenceDose, SIGNAL(valueChanged(double)), widget, SLOT(setReferenceDose(double))); + connect(widget,SIGNAL(ValueChanged(mitk::IsoDoseLevel*,mitk::DoseValueRel)), this, SLOT(UpdateFreeIsoLine(mitk::IsoDoseLevel*,mitk::DoseValueRel))); + + this->m_Controls.listFreeValues->addItem(item); + this->m_Controls.listFreeValues->setItemWidget(item,widget); + } +} + +void RTDoseVisualizer::UpdateFreeIsoLine(mitk::IsoDoseLevel * level, mitk::DoseValueRel old) +{ + float pref; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + mitk::Image::Pointer image = dynamic_cast(m_selectedNode->GetData()); + mitk::Image::Pointer slicedImage = this->GetExtractedSlice(image); + + m_Filters.at(0)->SetInput(slicedImage->GetVtkImageData()); + m_Filters.at(0)->GenerateValues(1,level->GetDoseValue()*pref,level->GetDoseValue()*pref); + m_Filters.at(0)->Update(); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void RTDoseVisualizer::OnAbsDoseToggled(bool showAbs) +{ + if (! m_internalUpdate) + { + mitk::rt::SetDoseDisplayAbsolute(showAbs); + this->ActualizeDisplayStyleForAllDoseDataNodes(); + } +} + +void RTDoseVisualizer::OnGlobalVisColorWashToggled(bool showColorWash) +{ + if (m_selectedNode.IsNotNull()) + { + m_selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), showColorWash); + } +} + +void RTDoseVisualizer::OnGlobalVisIsoLineToggled(bool showIsoLines) +{ + if (m_selectedNode.IsNotNull()) + { + m_selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), showIsoLines); + mitk::NodePredicateProperty::Pointer isoProp = mitk::NodePredicateProperty:: + New(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + mitk::DataStorage::SetOfObjects::ConstPointer isoSet = this->GetDataStorage()->GetSubset(isoProp); + for(mitk::DataStorage::SetOfObjects::ConstIterator iso = isoSet->Begin(); iso!=isoSet->End(); ++iso) + { + mitk::DataNode::Pointer node = iso.Value(); + node->SetVisibility(showIsoLines); + } + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); + } +} + + +void RTDoseVisualizer::OnConvertButtonClicked() +{ + this->InitScrolling(); + + QList dataNodes = this->GetDataManagerSelection(); + + mitk::DataNode* selectedNode = NULL; + + if (!dataNodes.empty()) + { + selectedNode = dataNodes[0]; + } + + if(selectedNode) + { + selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(), true); + selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(), true); + selectedNode->SetBoolProperty(mitk::rt::Constants::DOSE_SHOW_ISOLINES_PROPERTY_NAME.c_str(), true); + selectedNode->SetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), m_Controls.spinReferenceDose->value()); + + //selectedNode->GetData()->SetProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(), mitk::DoubleProperty::New(1.0)); + + mitk::IsoDoseLevelSet::Pointer clonedPreset = this->m_Presets[this->m_selectedPresetName]->Clone(); + mitk::IsoDoseLevelSetProperty::Pointer levelSetProp = mitk::IsoDoseLevelSetProperty::New(clonedPreset); + selectedNode->SetProperty(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),levelSetProp); + + + double hsvValue = 0.002778; + float prescribed; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),prescribed); + + vtkSmartPointer transferFunction = vtkSmartPointer::New(); + + mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = this->m_Presets[this->m_selectedPresetName]; + + MITK_INFO << "FUNCTION PRESCRIBE " << prescribed << endl; + + + float pref; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + mitk::Image::Pointer image = dynamic_cast(m_selectedNode->GetData()); + mitk::Image::Pointer reslicedImage = this->GetExtractedSlice(image); + + //Generating the Colorwash + for(mitk::IsoDoseLevelSet::ConstIterator setIT = isoDoseLevelSet->Begin(); setIT != isoDoseLevelSet->End(); ++setIT) + { + float *hsv = new float[3]; + //used for transfer rgb to hsv + vtkSmartPointer cCalc = vtkSmartPointer::New(); + if(setIT->GetVisibleColorWash()){ + cCalc->RGBToHSV(setIT->GetColor()[0],setIT->GetColor()[1],setIT->GetColor()[2],&hsv[0],&hsv[1],&hsv[2]); + transferFunction->AddHSVPoint(setIT->GetDoseValue()*pref,hsv[0],hsv[1],hsv[2],1.0,1.0); + } + } + + //Generating the standard isolines + this->UpdateStdIsolines(); + + mitk::TransferFunction::Pointer mitkTransFunc = mitk::TransferFunction::New(); + mitk::TransferFunctionProperty::Pointer mitkTransFuncProp = mitk::TransferFunctionProperty::New(); + mitkTransFunc->SetColorTransferFunction(transferFunction); + mitkTransFuncProp->SetValue(mitkTransFunc); + + mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); + renderingMode->SetValue(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); + + selectedNode->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); + selectedNode->SetProperty("Image Rendering.Mode", renderingMode); + m_selectedNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); + + mitk::IsoDoseLevelVector::Pointer levelVector = mitk::IsoDoseLevelVector::New(); + mitk::IsoDoseLevelVectorProperty::Pointer levelVecProp = mitk::IsoDoseLevelVectorProperty::New(levelVector); + selectedNode->SetProperty(mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),levelVecProp); + + UpdateBySelectedNode(); + +// mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); +// renderingMode->SetValue(mitk::RenderingModeProperty::ISODOSESHADER_COLOR); +// selectedNode->SetProperty("shader.mitkIsoLineShader.Gridscale", mitk::FloatProperty::New(10.0)); +// selectedNode->SetProperty("Image Rendering.Mode", renderingMode); + + mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); + } +} +//###################################################################################################### +const mitk::Geometry2D* RTDoseVisualizer::GetGeometry2D(char* dim) +{ + QmitkRenderWindow* rw = this->GetRenderWindowPart()->GetQmitkRenderWindow(dim); + const mitk::Geometry2D* worldGeo = rw->GetRenderer()->GetCurrentWorldGeometry2D(); + return worldGeo; +} + +mitk::Image::Pointer RTDoseVisualizer::GetExtractedSlice(mitk::Image::Pointer image) +{ + mitk::ExtractSliceFilter::Pointer extractFilter = mitk::ExtractSliceFilter::New(); + extractFilter->SetInput(image); + extractFilter->SetWorldGeometry(this->GetGeometry2D("axial")); + extractFilter->SetResliceTransformByGeometry( image->GetGeometry() ); + extractFilter->Update(); + mitk::Image::Pointer reslicedImage = extractFilter->GetOutput(); + return reslicedImage; +} + +mitk::DataNode::Pointer RTDoseVisualizer::UpdatePolyData(int num, double min, double max) +{ + mitk::Image::Pointer image = dynamic_cast(m_selectedNode->GetData()); + mitk::Image::Pointer reslicedImage = this->GetExtractedSlice(image); + + vtkSmartPointer contourFilter = vtkSmartPointer::New(); + m_Filters.push_back(contourFilter); + contourFilter->SetInput(reslicedImage->GetVtkImageData()); + contourFilter->GenerateValues(num,min,max); + contourFilter->Update(); + vtkSmartPointer polyData = vtkSmartPointer::New(); + polyData =contourFilter->GetOutput(); +// polyData->Print(std::cout); + + mitk::Surface::Pointer isoline = mitk::Surface::New(); + isoline->SetVtkPolyData(polyData); + isoline->SetGeometry(const_cast(this->GetGeometry2D("axial"))->Clone()); + isoline->GetGeometry()->SetSpacing(image->GetGeometry()->GetSpacing()); + isoline->SetOrigin(reslicedImage->GetGeometry()->GetOrigin()); + + mitk::DataNode::Pointer isolineNode = mitk::DataNode::New(); + isolineNode->SetData(isoline); +// mitk::PolyDataGLMapper2D::Pointer mapper = mitk::PolyDataGLMapper2D::New(); +// mitk::SurfaceGLMapper2D::Pointer mapper = mitk::SurfaceGLMapper2D::New(); + mitk::SurfaceVtkMapper3D::Pointer mapper = mitk::SurfaceVtkMapper3D::New(); + isolineNode->SetMapper(1, mapper); + isolineNode->SetName("Isoline1"); + isolineNode->SetBoolProperty(mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),true); + this->GetDataStorage()->Add(isolineNode); + return isolineNode; +} + +void RTDoseVisualizer::UpdateStdIsolines() +{ + mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = this->m_Presets[this->m_selectedPresetName]; + mitk::Image::Pointer image = dynamic_cast(m_selectedNode->GetData()); + mitk::Image::Pointer reslicedImage = this->GetExtractedSlice(image); + + float pref; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + + for(mitk::IsoDoseLevelSet::ConstIterator doseIT = isoDoseLevelSet->Begin(); doseIT!=isoDoseLevelSet->End();++doseIT) + { + if(doseIT->GetVisibleIsoLine()){ + vtkSmartPointer isolineFilter = vtkSmartPointer::New(); + isolineFilter->SetInput(reslicedImage->GetVtkImageData()); + isolineFilter->GenerateValues(1,doseIT->GetDoseValue()*pref,doseIT->GetDoseValue()*pref); + isolineFilter->Update(); + + vtkSmartPointer polyData = vtkSmartPointer::New(); + polyData=isolineFilter->GetOutput(); + + mitk::Surface::Pointer surface = mitk::Surface::New(); + surface->SetVtkPolyData(polyData); + surface->SetGeometry(const_cast(this->GetGeometry2D("axial"))->Clone()); + surface->GetGeometry()->SetSpacing(image->GetGeometry()->GetSpacing()); + surface->SetOrigin(reslicedImage->GetGeometry()->GetOrigin()); + + mitk::DataNode::Pointer isoNode = mitk::DataNode::New(); + isoNode->SetData(surface); + mitk::SurfaceVtkMapper3D::Pointer mapper = mitk::SurfaceVtkMapper3D::New(); + mitk::Color color; + color[0]=doseIT->GetColor()[0];color[1]=doseIT->GetColor()[1];color[2]=doseIT->GetColor()[2]; + isoNode->SetMapper(1,mapper); + isoNode->SetColor(color); + isoNode->SetProperty( "helper object", mitk::BoolProperty::New(true) ); + isoNode->SetName("StdIsoline"); + isoNode->SetBoolProperty(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),true); + m_StdIsoLines.push_back(isoNode); + this->GetDataStorage()->Add(isoNode); + } + } +} + +void RTDoseVisualizer::HideIsoline() +{ + mitk::NodePredicateProperty::Pointer isoProp = mitk::NodePredicateProperty:: + New(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + mitk::DataStorage::SetOfObjects::ConstPointer isoSet = this->GetDataStorage()->GetSubset(isoProp); + for(mitk::DataStorage::SetOfObjects::ConstIterator iso = isoSet->Begin(); iso!=isoSet->End(); ++iso) + { + } +} + +//###################################################################################################### +void RTDoseVisualizer::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes ) +{ + QList dataNodes = this->GetDataManagerSelection(); + + mitk::DataNode* selectedNode = NULL; + + if (!dataNodes.empty()) + { + bool isDoseNode = false; + dataNodes[0]->GetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(),isDoseNode); + + if (isDoseNode) + { + selectedNode = dataNodes[0]; + } + } + + if (selectedNode != m_selectedNode.GetPointer()) + { + m_selectedNode = selectedNode; + } + + UpdateBySelectedNode(); +} + +void RTDoseVisualizer::UpdateBySelectedNode() +{ + m_Controls.groupNodeSpecific->setEnabled(m_selectedNode.IsNotNull()); + m_Controls.groupFreeValues->setEnabled(m_selectedNode.IsNotNull()); + + if(m_selectedNode.IsNull()) + { + m_Controls.NrOfFractions->setText(QString("N/A. No dose selected")); + m_Controls.prescribedDoseSpecific->setText(QString("N/A. No dose selected")); + m_freeIsoValues = mitk::IsoDoseLevelVector::New(); + UpdateFreeIsoValues(); + } + else + { + /////////////////////////////////////////// + //dose specific information + int fracCount = 1; + m_selectedNode->GetIntProperty(mitk::rt::Constants::DOSE_FRACTION_COUNT_PROPERTY_NAME.c_str(),fracCount); + m_Controls.NrOfFractions->setText(QString::number(fracCount)); + + m_PrescribedDose_Data = 0.0; + + float tmp; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str(),tmp); + m_PrescribedDose_Data = (double)tmp; +// dynamic cast von float zu doubleproperty funktioniert nicht & getProperty von node->getData() funktioniert das ? +// mitk::DoubleProperty* propDouble = dynamic_cast(m_selectedNode->GetData()->GetProperty(mitk::rt::Constants::PRESCRIBED_DOSE_PROPERTY_NAME.c_str()).GetPointer()); +// if (propDouble) +// { +// m_PrescribedDose_Data = propDouble->GetValue(); +// } + + m_Controls.prescribedDoseSpecific->setText(QString::number(m_PrescribedDose_Data)); + + /////////////////////////////////////////// + //free iso lines + mitk::IsoDoseLevelVectorProperty::Pointer propIsoVector; + m_selectedNode->GetProperty(propIsoVector, mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str()); + + if (propIsoVector.IsNull()) + { + m_freeIsoValues = mitk::IsoDoseLevelVector::New(); + propIsoVector = mitk::IsoDoseLevelVectorProperty::New(m_freeIsoValues); + m_selectedNode->SetProperty(mitk::rt::Constants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str(),propIsoVector); + } + else + { + m_freeIsoValues = propIsoVector->GetValue(); + } + + UpdateFreeIsoValues(); + + /////////////////////////////////////////// + //global dose issues + bool showIsoLine = false; + m_selectedNode->GetBoolProperty(mitk::rt::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(),showIsoLine); + m_Controls.checkGlobalVisIsoLine->setChecked(showIsoLine); + + bool showColorWash = false; + m_selectedNode->GetBoolProperty(mitk::rt::Constants::DOSE_SHOW_COLORWASH_PROPERTY_NAME.c_str(),showColorWash); + m_Controls.checkGlobalVisColorWash->setChecked(showColorWash); + + float referenceDose = 0.0; + m_selectedNode->GetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),referenceDose); + m_Controls.spinReferenceDose->setValue(referenceDose); + + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = + dynamic_cast(m_selectedNode->GetProperty(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); + + if (propIsoSet) + { + this->m_selectedNodeIsoSet = propIsoSet->GetValue(); + this->m_LevelSetModel->setIsoDoseLevelSet(m_selectedNodeIsoSet); + } + } +} + +void RTDoseVisualizer::UpdateByPreferences() +{ + m_Presets = mitk::rt::LoadPresetsMap(); + m_internalUpdate = true; + m_Controls.comboPresets->clear(); + this->m_selectedPresetName = mitk::rt::GetSelectedPresetName(); + + int index = 0; + int selectedIndex = -1; + for (mitk::rt::PresetMapType::const_iterator pos = m_Presets.begin(); pos != m_Presets.end(); ++pos, ++index) + { + m_Controls.comboPresets->addItem(QString(pos->first.c_str())); + if (this->m_selectedPresetName == pos->first) + { + selectedIndex = index; + } + } + + if (selectedIndex == -1) + { + selectedIndex = 0; + MITK_WARN << "Error. Cannot iso dose level preset specified in preferences does not exist. Preset name: "<m_selectedPresetName; + this->m_selectedPresetName = m_Presets.begin()->first; + mitk::rt::SetSelectedPresetName(this->m_selectedPresetName); + MITK_INFO << "Changed selected iso dose level preset to first existing preset. New preset name: "<m_selectedPresetName; + } + + m_Controls.comboPresets->setCurrentIndex(selectedIndex); + + this->m_selectedNodeIsoSet = this->m_Presets[this->m_selectedPresetName]; + this->m_LevelSetModel->setIsoDoseLevelSet(m_selectedNodeIsoSet); + + mitk::DoseValueAbs referenceDose = 0.0; + bool globalSync = mitk::rt::GetReferenceDoseValue(referenceDose); + if (globalSync || this->m_selectedNode.IsNull()) + { + m_Controls.spinReferenceDose->setValue(referenceDose); + } + + bool displayAbsoluteDose = mitk::rt::GetDoseDisplayAbsolute(); + m_Controls.radioAbsDose->setChecked(displayAbsoluteDose); + m_Controls.radioRelDose->setChecked(!displayAbsoluteDose); + this->m_LevelSetModel->setShowAbsoluteDose(displayAbsoluteDose); + m_internalUpdate = false; +} + +void RTDoseVisualizer::OnCurrentPresetChanged(const QString& presetName) +{ + if (! m_internalUpdate) + { + mitk::rt::SetSelectedPresetName(presetName.toStdString()); + this->UpdateByPreferences(); + this->ActualizeIsoLevelsForAllDoseDataNodes(); + this->UpdateBySelectedNode(); + } +} + +void RTDoseVisualizer::ActualizeIsoLevelsForAllDoseDataNodes() +{ + std::string presetName = mitk::rt::GetSelectedPresetName(); + + mitk::rt::PresetMapType presetMap = mitk::rt::LoadPresetsMap(); + + mitk::NodePredicateProperty::Pointer isDoseNode = mitk::NodePredicateProperty::New(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + + mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetDataStorage()->GetSubset(isDoseNode); + + mitk::IsoDoseLevelSet* selectedPreset = presetMap[presetName]; + + if (!selectedPreset) + { + mitkThrow() << "Error. Cannot actualize iso dose level preset. Selected preset idoes not exist. Preset name: "<begin(); pos != nodes->end(); ++pos) + { + mitk::IsoDoseLevelSet::Pointer clonedPreset = selectedPreset->Clone(); + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = mitk::IsoDoseLevelSetProperty::New(clonedPreset); + (*pos)->SetProperty(mitk::rt::Constants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str(),propIsoSet); + } +} + +void RTDoseVisualizer::ActualizeReferenceDoseForAllDoseDataNodes() +{ + /** @TODO Klären ob diese präsentations info genauso wie*/ + mitk::DoseValueAbs value = 0; + bool sync = mitk::rt::GetReferenceDoseValue(value); + + if (sync) + { + mitk::NodePredicateProperty::Pointer isDoseNode = mitk::NodePredicateProperty::New(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(), mitk::BoolProperty::New(true)); + + mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->GetDataStorage()->GetSubset(isDoseNode); + + for(mitk::DataStorage::SetOfObjects::const_iterator pos = nodes->begin(); pos != nodes->end(); ++pos) + { + (*pos)->SetFloatProperty(mitk::rt::Constants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), value); + } + } +} + +void RTDoseVisualizer::ActualizeDisplayStyleForAllDoseDataNodes() +{ + /** @TODO Klären ob diese präsentations info global oder auch per node gespeichert wird*/ +} + +void RTDoseVisualizer::OnHandleCTKEventReferenceDoseChanged(const ctkEvent& event) +{ + mitk::DoseValueAbs referenceDose = 0.0; + bool globalSync = mitk::rt::GetReferenceDoseValue(referenceDose); + + this->m_Controls.spinReferenceDose->setValue(referenceDose); +} + +void RTDoseVisualizer::OnHandleCTKEventPresetsChanged(const ctkEvent& event) +{ + std::string currentPresetName = mitk::rt::GetSelectedPresetName(); + + this->OnCurrentPresetChanged(QString::fromStdString(currentPresetName)); +} diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizer.h b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizer.h new file mode 100644 index 0000000000..5b6f52462a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizer.h @@ -0,0 +1,171 @@ +/*=================================================================== + +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 RTDoseVisualizer_h +#define RTDoseVisualizer_h + +#include + +#include +#include + +#include + +#include "ui_RTDoseVisualizerControls.h" + +#include + +#include + +#include "mitkDoseVisPreferenceHelper.h" + +// Shader +#include +#include +#include + +#include + +/*forward declarations*/ +class QmitkIsoDoseLevelSetModel; +class QmitkDoseColorDelegate; +class QmitkDoseValueDelegate; +class QmitkDoseVisualStyleDelegate; +class ctkEvent; + +/** +\brief RTDoseVisualizer + +\warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + +\sa QmitkAbstractView +\ingroup ${plugin_target}_internal +*/ +class RTDoseVisualizer : 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) + Q_OBJECT + +public: + + RTDoseVisualizer(); + virtual ~RTDoseVisualizer(); + static const std::string VIEW_ID; + + void OnSliceChanged(itk::Object *sender, const itk::EventObject &e); + + protected slots: + + void OnConvertButtonClicked(); + + void OnAddFreeValueClicked(); + + void OnRemoveFreeValueClicked(); + + void OnUsePrescribedDoseClicked(); + + void OnAbsDoseToggled(bool); + + void OnGlobalVisColorWashToggled(bool); + + void OnGlobalVisIsoLineToggled(bool); + + void OnShowContextMenuIsoSet(const QPoint&); + + void OnCurrentPresetChanged(const QString&); + + void OnReferenceDoseChanged(double); + + void OnHandleCTKEventReferenceDoseChanged(const ctkEvent& event); + + void OnHandleCTKEventPresetsChanged(const ctkEvent& event); + + void UpdateFreeIsoLine(mitk::IsoDoseLevel*level, mitk::DoseValueRel old); + +protected: + + void InitScrolling(); + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes ); + + /** Method updates the list widget according to the current m_freeIsoValues.*/ + void UpdateFreeIsoValues(); + + /** Update the members according to the currently selected node */ + void UpdateBySelectedNode(); + + /** Update the member widgets according to the information stored in the application preferences*/ + void UpdateByPreferences(); + + /**helper function that iterates throug all data nodes and sets there iso level set property + according to the selected preset. + @TODO: should be moved outside the class, to be available for other classes at well.*/ + void ActualizeIsoLevelsForAllDoseDataNodes(); + + /**helper function that iterates throug all data nodes and sets there reference dose value + according to the preference. + @TODO: should be moved outside the class, to be available for other classes at well.*/ + void ActualizeReferenceDoseForAllDoseDataNodes(); + + /**helper function that iterates through all data nodes and sets there dose display style (relative/absolute) + according to the preference. + @TODO: should be moved outside the class, to be available for other classes at well.*/ + void ActualizeDisplayStyleForAllDoseDataNodes(); + + mitk::DataNode::Pointer UpdatePolyData(int num, double min, double max); + void UpdateStdIsolines(); + void HideIsoline(); + mitk::Image::Pointer GetExtractedSlice(mitk::Image::Pointer image); + const mitk::Geometry2D* GetGeometry2D(char* dim); + + Ui::RTDoseVisualizerControls m_Controls; + mitk::DataNode::Pointer m_selectedNode; + mitk::IsoDoseLevelVector::Pointer m_freeIsoValues; + std::vector m_FreeIsoLines; + std::vector m_StdIsoLines; + /** Iso level set of the current node. Should normaly be a clone of the + * current iso preset. It held as own member because visibility + * settings may differ.*/ + mitk::IsoDoseLevelSet::Pointer m_selectedNodeIsoSet; + mitk::rt::PresetMapType m_Presets; + std::string m_selectedPresetName; + + mitk::DataNode::Pointer m_FreeIsoline; + + /** Prescribed Dose of the selected data.*/ + mitk::DoseValueAbs m_PrescribedDose_Data; + + QmitkIsoDoseLevelSetModel* m_LevelSetModel; + QmitkDoseColorDelegate* m_DoseColorDelegate; + QmitkDoseValueDelegate* m_DoseValueDelegate; + QmitkDoseVisualStyleDelegate* m_DoseVisualDelegate; + + vtkSmartPointer m_freeIsoFilter; + std::vector< vtkSmartPointer > m_Filters; + + + bool m_internalUpdate; +}; + +#endif // RTDoseVisualizer_h diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizerControls.ui b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizerControls.ui new file mode 100644 index 0000000000..091d7664c1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTDoseVisualizerControls.ui @@ -0,0 +1,508 @@ + + + RTDoseVisualizerControls + + + + 0 + 0 + 421 + 651 + + + + + 0 + 0 + + + + QmitkTemplate + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + Dose specific information: + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + 30 Gy + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + true + + + + + + + + + Number of fractions: + + + + + + + Prescribed dose [Gy]: + + + + + + + Use as reference dose + + + + + + + true + + + + + + + + + + + + + 0 + 0 + + + + Free iso lines: + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + + 0 + 40 + + + + + 16777215 + 110 + + + + + 0 + 25 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Remove + + + + + + + + + + + + Global iso dose visualization: + + + + 5 + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + 0 + 0 + + + + + 65 + 0 + + + + Dose display: + + + + + + + + + + + 0 + 0 + + + + + 65 + 0 + + + + Preset style: + + + + + + + + 0 + 0 + + + + + 105 + 0 + + + + Qt::NoFocus + + + Reference dose [Gy]: + + + + + + + + + + 1 + + + 0.100000000000000 + + + 9999.000000000000000 + + + 0.100000000000000 + + + + + + + + + relative [%] + + + true + + + + + + + absolute [Gy] + + + + + + + + + + + true + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + 30 + 20 + + + + 80 + + + + + + + + + Global visibility: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Isolines + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + Colorwash + + + + :/RTUI/eye_open.png + + + + + 24 + 16 + + + + + + + + + + + + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + + + 255 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + + + 120 + 120 + 120 + + + + + + + 120 + 120 + 120 + + + + + + + + Convert nod to dose node (for testing only!) + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePage.cpp b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePage.cpp new file mode 100644 index 0000000000..445efc1532 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePage.cpp @@ -0,0 +1,117 @@ +/*=================================================================== + +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 "RTUIPreferencePage.h" + +#include "mitkRTUIConstants.h" + +#include +#include + +//----------------------------------------------------------------------------- +RTUIPreferencePage::RTUIPreferencePage() + : m_MainControl(0), m_Controls(0) +{ + +} + + +//----------------------------------------------------------------------------- +RTUIPreferencePage::~RTUIPreferencePage() +{ + delete m_Controls; +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::Init(berry::IWorkbench::Pointer ) +{ + +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::CreateQtControl(QWidget* parent) +{ + berry::IPreferencesService::Pointer prefService + = berry::Platform::GetServiceRegistry() + .GetServiceById(berry::IPreferencesService::ID); + + m_PreferencesNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_PREFERENCE_NODE_ID); + + m_MainControl = new QWidget(parent); + m_Controls = new Ui::RTUIPreferencePageControls; + m_Controls->setupUi( m_MainControl ); + + connect(m_Controls->radioDefault, SIGNAL(toggled(bool)), m_Controls->spinDefault, SLOT(setEnabled(bool))); + connect(m_Controls->radioRelativeToMax, SIGNAL(toggled(bool)), m_Controls->spinRelativeToMax, SLOT(setEnabled(bool))); + + this->Update(); +} + + +//----------------------------------------------------------------------------- +QWidget* RTUIPreferencePage::GetQtControl() const +{ + return m_MainControl; +} + +//----------------------------------------------------------------------------- +bool RTUIPreferencePage::PerformOk() +{ + bool useAsDefaultValue = m_Controls->radioDefault->isChecked(); + m_PreferencesNode->PutBool(mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID,useAsDefaultValue); + + if (useAsDefaultValue) + { + m_PreferencesNode->PutDouble(mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID, m_Controls->spinDefault->value()); + } + else + { + m_PreferencesNode->PutDouble(mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID, m_Controls->spinRelativeToMax->value()/100.0); + } + + return true; +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::PerformCancel() +{ +} + + +//----------------------------------------------------------------------------- +void RTUIPreferencePage::Update() +{ + bool useAsDefaultValue = m_PreferencesNode->GetBool(mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_AS_DEFAULT_ID, true); + double doseValue = m_PreferencesNode->GetDouble(mitk::rt::UIConstants::UNKNOWN_PRESCRIBED_DOSE_HANDLING_VALUE_ID, 50.0); + + m_Controls->radioDefault->setChecked(useAsDefaultValue); + m_Controls->radioRelativeToMax->setChecked(!useAsDefaultValue); + m_Controls->spinDefault->setEnabled(useAsDefaultValue); + m_Controls->spinRelativeToMax->setEnabled(!useAsDefaultValue); + + if (useAsDefaultValue) + { + m_Controls->spinDefault->setValue(doseValue); + } + else + { + m_Controls->spinRelativeToMax->setValue(doseValue*100.0); + } +} diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePage.h b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePage.h new file mode 100644 index 0000000000..208a41773f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePage.h @@ -0,0 +1,85 @@ +/*=================================================================== + +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 __RT_UI_PREFERENCE_PAGE_H +#define __RT_UI_PREFERENCE_PAGE_H + +#include "berryIQtPreferencePage.h" +#include "berryIPreferences.h" + +#include "ui_RTUIPreferencePageControls.h" + +class QWidget; + +/** +* \class RTUIPreferencePage +* \brief Preference page for general RT visualization settings. +*/ +class RTUIPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + RTUIPreferencePage(); + ~RTUIPreferencePage(); + + /** + * \brief Called by framework to initialize this preference page, but currently does nothing. + * \param workbench The workbench. + */ + void Init(berry::IWorkbench::Pointer workbench); + + /** + * \brief Called by framework to create the GUI, and connect signals and slots. + * \param widget The Qt widget that acts as parent to all GUI components, as this class itself is not derived from QWidget. + */ + void CreateQtControl(QWidget* widget); + + /** + * \brief Required by framework to get hold of the GUI. + * \return QWidget* the top most QWidget for the GUI. + */ + QWidget* GetQtControl() const; + + /** + * \see IPreferencePage::PerformOk + */ + virtual bool PerformOk(); + + /** + * \see IPreferencePage::PerformCancel + */ + virtual void PerformCancel(); + + /** + * \see IPreferencePage::Update + */ + virtual void Update(); + + public slots: + +protected: + + QWidget *m_MainControl; + Ui::RTUIPreferencePageControls* m_Controls; + + berry::IPreferences::Pointer m_PreferencesNode; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePageControls.ui b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePageControls.ui new file mode 100644 index 0000000000..efd18081ca --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/RTUIPreferencePageControls.ui @@ -0,0 +1,86 @@ + + + RTUIPreferencePageControls + + + + 0 + 0 + 403 + 438 + + + + Form + + + + + + Handling of unkown prescribed dose: + + + + + + false + + + % + + + 200.000000000000000 + + + 80.000000000000000 + + + + + + + set to default value: + + + + + + + set relative to max dose: + + + + + + + Gy + + + 9999.000000000000000 + + + 50.000000000000000 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.cpp b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.cpp new file mode 100644 index 0000000000..a8d01b1fd1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.cpp @@ -0,0 +1,245 @@ +/*=================================================================== + +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 "mitkDoseVisPreferenceHelper.h" +#include "mitkRTUIConstants.h" +#include "mitkIsoLevelsGenerator.h" + + +#include + +#include + +#include +#include + +void mitk::rt::StorePresetsMap(const PresetMapType& presetMap) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer doseVisNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + berry::IPreferences::Pointer presetsNode = doseVisNode->Node(mitk::rt::UIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + presetsNode->RemoveNode(); + doseVisNode->Flush(); + + //new empty preset node + presetsNode = doseVisNode->Node(mitk::rt::UIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + //store map in new node + for (PresetMapType::const_iterator pos = presetMap.begin(); pos != presetMap.end(); ++pos) + { + berry::IPreferences::Pointer aPresetNode = presetsNode->Node(pos->first); + + unsigned int id = 0; + + for (mitk::IsoDoseLevelSet::ConstIterator levelPos = pos->second->Begin(); levelPos != pos->second->End(); ++levelPos, ++id ) + { + std::ostringstream stream; + stream << id; + + berry::IPreferences::Pointer levelNode = aPresetNode->Node(stream.str()); + + levelNode->PutDouble(mitk::rt::UIConstants::ISO_LEVEL_DOSE_VALUE_ID,levelPos->GetDoseValue()); + levelNode->PutFloat(mitk::rt::UIConstants::ISO_LEVEL_COLOR_RED_ID,levelPos->GetColor().GetRed()); + levelNode->PutFloat(mitk::rt::UIConstants::ISO_LEVEL_COLOR_GREEN_ID,levelPos->GetColor().GetGreen()); + levelNode->PutFloat(mitk::rt::UIConstants::ISO_LEVEL_COLOR_BLUE_ID,levelPos->GetColor().GetBlue()); + levelNode->PutBool(mitk::rt::UIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID,levelPos->GetVisibleIsoLine()); + levelNode->PutBool(mitk::rt::UIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID,levelPos->GetVisibleColorWash()); + levelNode->Flush(); + } + + aPresetNode->Flush(); + } + + presetsNode->Flush(); +} + +mitk::rt::PresetMapType mitk::rt::LoadPresetsMap() +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer presetsNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + typedef std::vector NamesType; + NamesType names = presetsNode->ChildrenNames(); + + PresetMapType presetMap; + + for (NamesType::const_iterator pos = names.begin(); pos != names.end(); ++pos) + { + berry::IPreferences::Pointer aPresetNode = presetsNode->Node(*pos); + + if (aPresetNode.IsNull()) + { + mitkThrow()<< "Error in preference interface. Cannot find preset node under given name. Name: "<<*pos; + } + + 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<<"; Level id: "<<*levelName; + } + + mitk::IsoDoseLevel::Pointer isoLevel = mitk::IsoDoseLevel::New(); + + isoLevel->SetDoseValue(levelNode->GetDouble(mitk::rt::UIConstants::ISO_LEVEL_DOSE_VALUE_ID,0.0)); + mitk::IsoDoseLevel::ColorType color; + color.SetRed(levelNode->GetFloat(mitk::rt::UIConstants::ISO_LEVEL_COLOR_RED_ID,1.0)); + color.SetGreen(levelNode->GetFloat(mitk::rt::UIConstants::ISO_LEVEL_COLOR_GREEN_ID,1.0)); + color.SetBlue(levelNode->GetFloat(mitk::rt::UIConstants::ISO_LEVEL_COLOR_BLUE_ID,1.0)); + isoLevel->SetColor(color); + isoLevel->SetVisibleIsoLine(levelNode->GetBool(mitk::rt::UIConstants::ISO_LEVEL_VISIBILITY_ISOLINES_ID,true)); + isoLevel->SetVisibleColorWash(levelNode->GetBool(mitk::rt::UIConstants::ISO_LEVEL_VISIBILITY_COLORWASH_ID,true)); + + levelSet->SetIsoDoseLevel(isoLevel); + } + + presetMap.insert(std::make_pair(*pos,levelSet)); + } + + if (presetMap.size() == 0) + { //if there are no presets use fallback and store it. + presetMap = mitk::rt::GenerateDefaultPresetsMap(); + StorePresetsMap(presetMap); + } + + return presetMap; +} + +mitk::rt::PresetMapType mitk::rt::GenerateDefaultPresetsMap() +{ + mitk::rt::PresetMapType result; + + result.insert(std::make_pair(std::string("Virtuos"), mitk::rt::GeneratIsoLevels_Virtuos())); + return result; +} + +std::string mitk::rt::GetSelectedPresetName() +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + std::string result = prefNode->Get(mitk::rt::UIConstants::SELECTED_ISO_PRESET_ID, ""); + + return result; +} + +void mitk::rt::SetSelectedPresetName(const std::string& presetName) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + berry::IPreferences::Pointer presetsNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_ISO_PRESETS_PREFERENCE_NODE_ID); + + typedef std::vector NamesType; + NamesType presetNames = presetsNode->ChildrenNames(); + + NamesType::iterator finding = std::find(presetNames.begin(),presetNames.end(),presetName); + + if (finding == presetNames.end()) + { + mitkThrow()<< "Error. Tried to set invalid selected preset name. Preset name does not exist in the defined presets. Preset name: "<Put(mitk::rt::UIConstants::SELECTED_ISO_PRESET_ID,presetName); +} + +bool mitk::rt::GetReferenceDoseValue(mitk::DoseValueAbs& value) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + bool result = prefNode->GetBool(mitk::rt::UIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, true); + value = prefNode->GetDouble(mitk::rt::UIConstants::REFERENCE_DOSE_ID, mitk::rt::UIConstants::DEFAULT_REFERENCE_DOSE_VALUE); + + return result; +} + +void mitk::rt::SetReferenceDoseValue(bool globalSync, mitk::DoseValueAbs value) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + prefNode->PutBool(mitk::rt::UIConstants::GLOBAL_REFERENCE_DOSE_SYNC_ID, globalSync); + if (value >= 0) + { + prefNode->PutDouble(mitk::rt::UIConstants::REFERENCE_DOSE_ID, value); + } +} + + +bool mitk::rt::GetDoseDisplayAbsolute() +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + bool result = prefNode->GetBool(mitk::rt::UIConstants::DOSE_DISPLAY_ABSOLUTE_ID, false); + + return result; +} + +void mitk::rt::SetDoseDisplayAbsolute(bool isAbsolute) +{ + berry::IPreferencesService::Pointer prefService = + berry::Platform::GetServiceRegistry().GetServiceById(berry::IPreferencesService::ID); + + berry::IPreferences::Pointer prefNode = prefService->GetSystemPreferences()->Node(mitk::rt::UIConstants::ROOT_DOSE_VIS_PREFERENCE_NODE_ID); + + prefNode->PutBool(mitk::rt::UIConstants::DOSE_DISPLAY_ABSOLUTE_ID, isAbsolute); +} + +void mitk::rt::SignalReferenceDoseChange(bool globalSync, mitk::DoseValueAbs value, ctkPluginContext* context) +{ + ctkServiceReference ref = context->getServiceReference(); + if (ref) + { + ctkEventAdmin* eventAdmin = context->getService(ref); + ctkProperties props; + props["value"] = value; + props["globalSync"] = globalSync; + ctkEvent presetMapChangedEvent(mitk::rt::CTKEventConstants::TOPIC_REFERENCE_DOSE_CHANGED.c_str()); + eventAdmin->sendEvent(presetMapChangedEvent); + } +} + +void mitk::rt::SignalPresetMapChange(ctkPluginContext* context) +{ + ctkServiceReference ref = context->getServiceReference(); + if (ref) + { + ctkEventAdmin* eventAdmin = context->getService(ref); + ctkEvent presetMapChangedEvent(mitk::rt::CTKEventConstants::TOPIC_ISO_DOSE_LEVEL_PRESETS_CHANGED.c_str()); + eventAdmin->sendEvent(presetMapChangedEvent); + } +} diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.h b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.h new file mode 100644 index 0000000000..ebf9c734b4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/mitkDoseVisPreferenceHelper.h @@ -0,0 +1,74 @@ +/*=================================================================== + +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 __DOSE_VIS_PREFERENCE_HELPER_H +#define __DOSE_VIS_PREFERENCE_HELPER_H + +#include +#include + +#include "mitkIsoDoseLevelCollections.h" + +class ctkPluginContext; + +namespace mitk +{ + namespace rt + { + typedef std::map PresetMapType; + + /** Stores the given preset map in the application preferences. */ + void StorePresetsMap(const PresetMapType& presetMap); + + /** Loads all defined iso dose level presets from the preferences and stores them + in a map. Key is the name of the preset. + @remark If no presets are stored in the preferences this function will generate default presets + (using GenerateDefaultPresetsMap()) and the stores it in the preferences (to guarantee a consistent state) + before passing the default presets back.*/ + PresetMapType LoadPresetsMap(); + + /** Generate the default presets map.*/ + PresetMapType GenerateDefaultPresetsMap(); + + /**Retrieves the name of the preset, that is currently selected for the application, from the preferences.*/ + std::string GetSelectedPresetName(); + + /** checks if the passed name exists in the preset map. If not an exception is thrown. If it exists, the new + * value will be set.*/ + void SetSelectedPresetName(const std::string& presetName); + + /** retrieves the reference dose from the preferences and indicates if global sync for reference dose is activated + or not. + @param value The reference dose value stored in the preferences. + @return Indicator for global sync. True: global sync activated -> preference value is relevant. + False: global sync deactivated. Value is irrelevant. Each node has its own value.*/ + bool GetReferenceDoseValue(DoseValueAbs& value); + /** Sets the global sync setting and dose reference value in the preferences. + * @param globalSync Indicator if global sync should be set active (true) or inactive (false). If it is true, the value is irrelevant (but will be set). + * @param value The dose reference value that should be stored in the preferences.If set to <0 it will be ignored and not changed/set.*/ + void SetReferenceDoseValue(bool globalSync, DoseValueAbs value = -1); + + bool GetDoseDisplayAbsolute(); + void SetDoseDisplayAbsolute(bool isAbsolute); + + void SignalReferenceDoseChange(bool globalSync, mitk::DoseValueAbs value, ctkPluginContext* context); + void SignalPresetMapChange(ctkPluginContext* context); + + } +} + +#endif diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.cpp b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.cpp new file mode 100644 index 0000000000..eb0e2631cc --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.cpp @@ -0,0 +1,55 @@ +/*=================================================================== + +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 "org_mitk_gui_qt_rt_dosevisualization_Activator.h" + +#include + +#include "RTDoseVisualizer.h" +#include "RTUIPreferencePage.h" +#include "DoseVisualizationPreferencePage.h" +#include "LoadingRTView.h" + +namespace mitk { + + ctkPluginContext* org_mitk_gui_qt_rt_dosevisualization_Activator::m_Context = NULL; + + void org_mitk_gui_qt_rt_dosevisualization_Activator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(RTDoseVisualizer, context); + BERRY_REGISTER_EXTENSION_CLASS(RTUIPreferencePage, context) + BERRY_REGISTER_EXTENSION_CLASS(DoseVisualizationPreferencePage, context) + BERRY_REGISTER_EXTENSION_CLASS(LoadingRTView, context) + + m_Context = context; + } + + void org_mitk_gui_qt_rt_dosevisualization_Activator::stop(ctkPluginContext* context) + { + Q_UNUSED(context); + + m_Context = NULL; + } + + ctkPluginContext* org_mitk_gui_qt_rt_dosevisualization_Activator::GetContext() + { + return m_Context; + } + +} + +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_rt_dosevisualization, mitk::org_mitk_gui_qt_rt_dosevisualization_Activator) diff --git a/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.h b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.h new file mode 100644 index 0000000000..f0f1449354 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.rt.dosevisualization/src/internal/org_mitk_gui_qt_rt_dosevisualization_Activator.h @@ -0,0 +1,46 @@ +/*=================================================================== + +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_rt_dosevisualization_Activator_h +#define org_mitk_gui_qt_rt_dosevisualization_Activator_h + +#include + +namespace mitk { + + class org_mitk_gui_qt_rt_dosevisualization_Activator : + public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_INTERFACES(ctkPluginActivator) + + public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + + static ctkPluginContext* GetContext(); + + private: + + static ctkPluginContext* m_Context; + + }; // org_mitk_gui_qt_rt_dosevisualization_Activator + +} + +#endif // org_mitk_gui_qt_rt_dosevisualization_Activator_h