diff --git a/Core/Code/DataManagement/mitkRenderingModeProperty.cpp b/Core/Code/DataManagement/mitkRenderingModeProperty.cpp index c233ae638d..6d0cfa659a 100644 --- a/Core/Code/DataManagement/mitkRenderingModeProperty.cpp +++ b/Core/Code/DataManagement/mitkRenderingModeProperty.cpp @@ -1,71 +1,72 @@ /*=================================================================== 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)); return result; } diff --git a/Core/Code/DataManagement/mitkRenderingModeProperty.h b/Core/Code/DataManagement/mitkRenderingModeProperty.h index fb550df067..53a6945a76 100644 --- a/Core/Code/DataManagement/mitkRenderingModeProperty.h +++ b/Core/Code/DataManagement/mitkRenderingModeProperty.h @@ -1,115 +1,116 @@ /*=================================================================== 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. Valid values are: * \li LEVELWINDOW_COLOR: Level window and color will be applied to the image. * \li LOOKUPTABLE_LEVELWINDOW_COLOR: A lookup table, level window and color will be applied to the image. * \li COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: A colortransferfunction, level window and color will be applied to the image. * \li LOOKUPTABLE_COLOR: A lookup table and color will be applied to the image. * \li COLORTRANSFERFUNCTION_COLOR: A colortransferfunction and color will be applied to the image. * * 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 controled 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 mode). */ class MITK_CORE_EXPORT RenderingModeProperty : public EnumerationProperty { public: mitkClassMacro( RenderingModeProperty, EnumerationProperty ); itkNewMacro(RenderingModeProperty); mitkNewMacro1Param(RenderingModeProperty, const IdType&); mitkNewMacro1Param(RenderingModeProperty, const std::string&); 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 0dbb786e2b..e8fe387139 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp @@ -1,1154 +1,1173 @@ /*=================================================================== 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 #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, vtkFloatingPointType 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->SetInput( 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->GetTimeSlicedGeometry()->GetGeometry3D( 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->GetTimeSlicedGeometry()->GetGeometry3D( 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->SetInput( 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 vtkFloatingPointType 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 { vtkFloatingPointType 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->SetInput(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0)); } else { //connect the input with the levelwindow filter localStorage->m_LevelWindowFilter->SetInput(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); - // connect the texture with the output of the levelwindow filter - localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); + 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->SetInput(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 ); - this->ApplyShader( 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 { MITK_WARN << "Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'. A default (rainbow) lookup table will be used."; } 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 TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTime( 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); 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 { // generate LUT (white to black) mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); vtkLookupTable* bwLut = mitkLut->GetVtkLookupTable(); bwLut->SetTableRange (0, 1); bwLut->SetSaturationRange (0, 0); bwLut->SetHueRange (0, 0); bwLut->SetValueRange (1, 0); bwLut->SetAlphaRange (1, 1); bwLut->SetRampToLinear(); bwLut->Build(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty( "LookupTable", mitkLutProp ); } 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(); //built a default lookuptable m_DefaultLookupTable->SetRampToLinear(); m_DefaultLookupTable->SetSaturationRange( 0.0, 0.0 ); m_DefaultLookupTable->SetHueRange( 0.0, 0.0 ); m_DefaultLookupTable->SetValueRange( 0.0, 1.0 ); m_DefaultLookupTable->Build(); m_BinaryLookupTable->SetRampToLinear(); m_BinaryLookupTable->SetSaturationRange( 0.0, 0.0 ); m_BinaryLookupTable->SetHueRange( 0.0, 0.0 ); m_BinaryLookupTable->SetValueRange( 0.0, 1.0 ); m_BinaryLookupTable->SetRange(0.0, 1.0); m_BinaryLookupTable->Build(); // 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(); // make first value transparent { double rgba[4]; m_BinaryLookupTable->GetTableValue(0, rgba); m_BinaryLookupTable->SetTableValue(0, rgba[0], rgba[1], rgba[2], 0.0); // background to 0 } //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/vtkMitkShaderTexture.cpp b/Core/Code/Rendering/vtkMitkShaderTexture.cpp new file mode 100644 index 0000000000..35dcb66db2 --- /dev/null +++ b/Core/Code/Rendering/vtkMitkShaderTexture.cpp @@ -0,0 +1,513 @@ +/*=================================================================== + +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; + 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 37d254ccec..05eecce307 100644 --- a/Core/Code/files.cmake +++ b/Core/Code/files.cmake @@ -1,396 +1,398 @@ set(H_FILES Algorithms/itkImportMitkImageContainer.h Algorithms/itkImportMitkImageContainer.txx Algorithms/itkLocalVariationImageFilter.h Algorithms/itkLocalVariationImageFilter.txx Algorithms/itkMITKScalarImageToHistogramGenerator.h Algorithms/itkMITKScalarImageToHistogramGenerator.txx Algorithms/itkTotalVariationDenoisingImageFilter.h Algorithms/itkTotalVariationDenoisingImageFilter.txx Algorithms/itkTotalVariationSingleIterationImageFilter.h Algorithms/itkTotalVariationSingleIterationImageFilter.txx Algorithms/mitkBilateralFilter.h Algorithms/mitkBilateralFilter.cpp 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/mitkExceptionMacro.h Common/mitkServiceBaseObject.h Common/mitkTestingMacros.h Common/mitkTesting.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/mitkImageToItk.txx Interactions/mitkEventMapperAddOn.h Interfaces/mitkIDataNodeReader.h Rendering/mitkLocalStorageHandler.h IO/mitkPixelTypeTraits.h ) set(CPP_FILES Algorithms/mitkBaseDataSource.cpp Algorithms/mitkCompareImageFilter.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/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/mitkRestorePlanePositionOperation.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/mitkTimeSlicedGeometry.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/mitkShaderProperty.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 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/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 Interfaces/mitkInteractionEventObserver.cpp Interfaces/mitkIShaderRepository.cpp Interfaces/mitkIPropertyAliases.cpp Interfaces/mitkIPropertyDescriptions.cpp Interfaces/mitkIPropertyExtensions.cpp Interfaces/mitkIPropertyFilters.cpp IO/mitkBaseDataIOFactory.cpp IO/mitkCoreDataNodeReader.cpp IO/mitkDicomSeriesReader.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/mitkShaderRepository.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp Rendering/mitkRenderingTestHelper.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 Common/mitkException.cpp Common/mitkCommon.h Common/mitkCoreObjectFactoryBase.cpp Common/mitkCoreObjectFactory.cpp Common/mitkCoreServices.cpp ) list(APPEND CPP_FILES ${CppMicroServices_SOURCES}) 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 Shaders/mitkShaderLighting.xml mitkLevelWindowPresets.xml ) diff --git a/Modules/DicomRT/mitkDicomRTReader.cpp b/Modules/DicomRT/mitkDicomRTReader.cpp index 1c7192fab6..3016a74458 100644 --- a/Modules/DicomRT/mitkDicomRTReader.cpp +++ b/Modules/DicomRT/mitkDicomRTReader.cpp @@ -1,641 +1,645 @@ /*=================================================================== 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" namespace mitk { - DicomRTReader::DicomRTReader(){} + DicomRTReader::DicomRTReader() + { + } DicomRTReader::~DicomRTReader(){} DicomRTReader::RoiEntry::RoiEntry() { Number=0; DisplayColor[0]=1.0; DisplayColor[1]=0.0; DisplayColor[2]=0.0; PolyData=NULL; } DicomRTReader::RoiEntry::~RoiEntry() { SetPolyData(NULL); } 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]; PolyData=NULL; SetPolyData(src.PolyData); } 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.PolyData); return (*this); } void DicomRTReader::RoiEntry::SetPolyData(vtkPolyData* roiPolyData) { if (roiPolyData == this->PolyData) { // not changed return; } if (this->PolyData != NULL) { this->PolyData->UnRegister(NULL); } this->PolyData = roiPolyData; if (this->PolyData != NULL) { this->PolyData->Register(NULL); } } std::deque DicomRTReader::ReadDicomFile(char* filename) { std::cout << "\n\n" << "Filename:" << filename << "\n\n"; 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) { int x = this->DicomRTReader::LoadRTPlan(dataset); ContourModelSetVector y; return y; } else { std::cout << "Error reading the RTStructureSetStorage\n\n"; ContourModelSetVector y; return y; } } else { std::cout << "Error reading the SOPClassID\n\n"; ContourModelSetVector y; return y; } } else { std::cout << "Cant read the input file\n\n"; ContourModelSetVector y; return y; } } size_t DicomRTReader::GetNumberOfRois() { return this->RoiSequenceVector.size(); } DicomRTReader::RoiEntry* DicomRTReader::FindRoiByNumber(int roiNumber) { for(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()) { std::cout << "Error reading the file\n\n"; std::deque x; return x; } DRTStructureSetROISequence &roiSequence = structureSetObject.getStructureSetROISequence(); if(!roiSequence.gotoFirstItem().good()) { std::cout << "Error reading the structure sequence\n\n"; 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()); OFString refSOPInstUID = GetReferencedFrameOfReferenceSOPInstanceUID(structureSetObject); double sliceThickness = 2.0; Sint32 refRoiNumber; DRTROIContourSequence &roiContourSeqObject = structureSetObject.getROIContourSequence(); if(!roiContourSeqObject.gotoFirstItem().good()) { std::cout << "Error reading the contour sequence\n\n"; 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(int i=0; iAddVertex(point); } contourSequence->Close(); contourSet->AddContourModel(contourSequence); } while(contourSeqObject.gotoNextItem().good()); } else { std::cout << "Error reading contourSeqObject\n\n"; } RoiEntry* refROI = this->FindRoiByNumber(refRoiNumber); if(refROI==NULL) { std::cout << "Cant find referenced ROI\n\n"; continue; } Sint32 roiColor; for(int j=0;j<3;j++) { currentRoiObject.getROIDisplayColor(roiColor, j); refROI->DisplayColor[j] = roiColor/255.0; } contourSet->SetProperty("name", mitk::StringProperty::New(refROI->Name)); contourModelSetVector.push_back(contourSet); } while(roiContourSeqObject.gotoNextItem().good()); std::cout << "Anzahl von ROI: " << contourModelSetVector.size() << "\n\n"; 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) { // mitk::CoreServicePointer shadoRepo(mitk::CoreServices::GetShaderRepository()); // std::string path = "/home/riecker/mitkShaderLighting.xml"; //mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderTOF.xml"); // MITK_INFO << "shader found under: " << path; // std::ifstream str(path.c_str()); // shadoRepo->LoadShader(str,"mitkIsoLineShader"); 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; 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(50) << "Gridscale " << gridscale << endl; frames = atoi(nrframes.c_str()); 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->GetDefaultPrescriptionDose(dataset); double hsvValue = 0.002778; vtkSmartPointer transferFunction = vtkSmartPointer::New(); transferFunction->AddHSVPoint(prescripeDose*0.0,(240*hsvValue),1.0,1.0,1.0,1.0); transferFunction->AddHSVPoint(prescripeDose*0.2,(180*hsvValue),1.0,1.0,1.0,1.0); transferFunction->AddHSVPoint(prescripeDose*0.4,(120*hsvValue),1.0,0.5,1.0,1.0); transferFunction->AddHSVPoint(prescripeDose*0.5,(120*hsvValue),1.0,1.0,1.0,1.0); transferFunction->AddHSVPoint(prescripeDose*0.6,(060*hsvValue),1.0,1.0,1.0,1.0); transferFunction->AddHSVPoint(prescripeDose*0.7,(026*hsvValue),1.0,1.0,1.0,1.0); transferFunction->AddHSVPoint(prescripeDose*1.0,(000*hsvValue),1.0,1.0,1.0,1.0); transferFunction->Build(); 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_LEVELWINDOW_COLOR); + renderingMode->SetValue(mitk::RenderingModeProperty::ISODOSESHADER_COLOR); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetName("DicomRT Dosis"); + node->SetProperty("shader.mitkIsoLineShader.Gridscale", mitk::FloatProperty::New(10.0)); node->SetBoolProperty(mitk::rt::Constants::DOSE_PROPERTY_NAME.c_str(),true); node->SetProperty("Image Rendering.Mode", renderingMode); - node->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); +// node->SetProperty("Image Rendering.Transfer Function", mitkTransFuncProp); node->SetProperty("opacity", mitk::FloatProperty::New(0.3)); - node->SetProperty("texture interpolation", mitk::BoolProperty::New( true ) ); node->SetData(image); return node; } double DicomRTReader::GetDefaultPrescriptionDose(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()); 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 * 0.8; } vtkSmartPointer DicomRTReader::GetIsoLine(double value, vtkDataObject* dataObject) { vtkSmartPointer contourFilter = vtkSmartPointer::New(); vtkSmartPointer polyData = vtkSmartPointer::New(); contourFilter->SetInput(dataObject); contourFilter->SetNumberOfContours(1); contourFilter->SetValue(0,value); contourFilter->Update(); polyData = contourFilter->GetOutput(); return polyData; } vtkSmartPointer DicomRTReader::GetStandardIsoLines(vtkDataObject* dataObject) { vtkSmartPointer contourFilter = vtkSmartPointer::New(); vtkSmartPointer polyData = vtkSmartPointer::New(); contourFilter->SetInput(dataObject); contourFilter->SetNumberOfContours(1); contourFilter->SetValue(0,10); polyData = contourFilter->GetOutput(); return polyData; } bool DicomRTReader::Equals(mitk::ContourModel::Pointer first, mitk::ContourModel::Pointer second) { if(first->GetNumberOfVertices() != second->GetNumberOfVertices()) { return false; } for( int i = 0; i < first->GetNumberOfVertices(); i++) { const mitk::ContourElement::VertexType* x = first->GetVertexAt(i); const mitk::ContourElement::VertexType* y = second->GetVertexAt(i); mitk::ContourElement::VertexType xx = *x; mitk::ContourElement::VertexType yy = *y; for(int j=0; j<3; j++) { if(xx.Coordinates[j] != yy.Coordinates[j]) { return false; } } } return true; } } diff --git a/Modules/DicomRT/mitkDicomRTReader.h b/Modules/DicomRT/mitkDicomRTReader.h index 7621d2b46e..47b1b8d2f3 100644 --- a/Modules/DicomRT/mitkDicomRTReader.h +++ b/Modules/DicomRT/mitkDicomRTReader.h @@ -1,269 +1,272 @@ /*=================================================================== 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 #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(vtkPolyData* roiPolyData); unsigned int Number; std::string Name; std::string Description; double DisplayColor[3]; //vllt direkt durch die contourmodels ersetzen ?! vtkPolyData* PolyData; }; public: mitkClassMacro( DicomRTReader, itk::Object ); itkNewMacro( Self ); /** * @brief Used for getting a custom Isoline * @param value The gray-value which the isoline represents * @param dataObject The vtkDataObject from the DicomRT dose image * @return Returns a vtkPolyData including the contour/isoline * * This method is used for a custom Isoline e.g. from the DicomRT IsoSlider. * You define the value where the Isoline is by setting the value as a parameter. */ vtkSmartPointer GetIsoLine(double value, vtkDataObject* dataObject); /** * @brief Used for getting the StandardIsoLines * @param dataObject The vtkDataObject from the DicomRT dose image * @return Returns a vtkPolyData including the contours/isolines * * The IsoLines should be equal to the contours of the colorwash. */ vtkSmartPointer GetStandardIsoLines(vtkDataObject* dataObject); /** * @brief Get a default prescription dose * @param dataSet The DcmDataset of the DicomRTDose file * @return The dose value * * If you dont define a prescription dose use this method, it calculates a * default value by reading the dose values from the dose file and multiplys * the highest value with 0.8. */ double GetDefaultPrescriptionDose(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(int roiNumber); /** * @brief GetReferencedFrameOfReferenceSOPInstanceUID * @param structSetObject * @return */ OFString GetReferencedFrameOfReferenceSOPInstanceUID(DRTStructureSetIOD &structSetObject); /** * @brief Compares two mitk::ContourModel::Pointer for testing the Structuresets. * @param first The first mitk::ContourModel::Pointer * @param second The second mitk::ContourModel::Pointer * @return Returns true if they are equal and false if they are different */ bool Equals(mitk::ContourModel::Pointer first, mitk::ContourModel::Pointer second); /** * 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/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 + + + + + + + + + +