diff --git a/Modules/Core/include/mitkPlaneClipping.h b/Modules/Core/include/mitkPlaneClipping.h index 0500a22f35..3f9748922b 100644 --- a/Modules/Core/include/mitkPlaneClipping.h +++ b/Modules/Core/include/mitkPlaneClipping.h @@ -1,154 +1,155 @@ /*=================================================================== 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 MITKPLANECLIPPING_H_HEADER_INCLUDED #define MITKPLANECLIPPING_H_HEADER_INCLUDED #include #include #include +#include #include namespace mitk { namespace PlaneClipping { /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ static bool LineIntersectZero(vtkPoints *points, int p1, int p2, double *bounds) { double point1[3]; double point2[3]; points->GetPoint(p1, point1); points->GetPoint(p2, point2); if ((point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2])) { double x, y; x = (point1[0] * point2[2] - point1[2] * point2[0]) / (point2[2] - point1[2]); y = (point1[1] * point2[2] - point1[2] * point2[1]) / (point2[2] - point1[2]); if (x < bounds[0]) { bounds[0] = x; } if (x > bounds[1]) { bounds[1] = x; } if (y < bounds[2]) { bounds[2] = y; } if (y > bounds[3]) { bounds[3] = y; } bounds[4] = bounds[5] = 0.0; return true; } return false; } /** \brief Calculate the bounding box of the resliced image. This is necessary for arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) will have a new bounding box, which needs to be calculated. */ static bool CalculateClippedPlaneBounds(const BaseGeometry *boundingGeometry, const PlaneGeometry *planeGeometry, double *bounds) { // Clip the plane with the bounding geometry. To do so, the corner points // of the bounding box are transformed by the inverse transformation // matrix, and the transformed bounding box edges derived therefrom are // clipped with the plane z=0. The resulting min/max values are taken as // bounds for the image reslicer. const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); vtkSmartPointer points = vtkSmartPointer::New(); if (boundingGeometry->GetImageGeometry()) { points->InsertPoint(0, bbMin[0] - 0.5, bbMin[1] - 0.5, bbMin[2] - 0.5); points->InsertPoint(1, bbMin[0] - 0.5, bbMin[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(2, bbMin[0] - 0.5, bbMax[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(3, bbMin[0] - 0.5, bbMax[1] - 0.5, bbMin[2] - 0.5); points->InsertPoint(4, bbMax[0] - 0.5, bbMin[1] - 0.5, bbMin[2] - 0.5); points->InsertPoint(5, bbMax[0] - 0.5, bbMin[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(6, bbMax[0] - 0.5, bbMax[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(7, bbMax[0] - 0.5, bbMax[1] - 0.5, bbMin[2] - 0.5); } else { points->InsertPoint(0, bbMin[0], bbMin[1], bbMin[2]); points->InsertPoint(1, bbMin[0], bbMin[1], bbMax[2]); points->InsertPoint(2, bbMin[0], bbMax[1], bbMax[2]); points->InsertPoint(3, bbMin[0], bbMax[1], bbMin[2]); points->InsertPoint(4, bbMax[0], bbMin[1], bbMin[2]); points->InsertPoint(5, bbMax[0], bbMin[1], bbMax[2]); points->InsertPoint(6, bbMax[0], bbMax[1], bbMax[2]); points->InsertPoint(7, bbMax[0], bbMax[1], bbMin[2]); } vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer transform = vtkSmartPointer::New(); transform->Identity(); transform->Concatenate(planeGeometry->GetVtkTransform()->GetLinearInverse()); transform->Concatenate(boundingGeometry->GetVtkTransform()); transform->TransformPoints(points, newPoints); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; LineIntersectZero(newPoints, 0, 1, bounds); LineIntersectZero(newPoints, 1, 2, bounds); LineIntersectZero(newPoints, 2, 3, bounds); LineIntersectZero(newPoints, 3, 0, bounds); LineIntersectZero(newPoints, 0, 4, bounds); LineIntersectZero(newPoints, 1, 5, bounds); LineIntersectZero(newPoints, 2, 6, bounds); LineIntersectZero(newPoints, 3, 7, bounds); LineIntersectZero(newPoints, 4, 5, bounds); LineIntersectZero(newPoints, 5, 6, bounds); LineIntersectZero(newPoints, 6, 7, bounds); LineIntersectZero(newPoints, 7, 4, bounds); if ((bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0)) { return false; } else { // The resulting bounds must be adjusted by the plane spacing, since we // we have so far dealt with index coordinates const mitk::Vector3D planeSpacing = planeGeometry->GetSpacing(); bounds[0] *= planeSpacing[0]; bounds[1] *= planeSpacing[0]; bounds[2] *= planeSpacing[1]; bounds[3] *= planeSpacing[1]; bounds[4] *= planeSpacing[2]; bounds[5] *= planeSpacing[2]; return true; } } } } #endif diff --git a/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp b/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp index 5212d503f9..593c99425b 100644 --- a/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp +++ b/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp @@ -1,1106 +1,1167 @@ /*=================================================================== 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 +// MITK +#include "mitkImageStatisticsHolder.h" +#include "mitkPlaneClipping.h" +#include "mitkPropertyNameHelper.h" #include #include #include #include #include #include #include #include #include #include #include +#include #include #include -#include #include #include -#include "mitkImageStatisticsHolder.h" -#include "mitkPlaneClipping.h" -#include "mitkPropertyNameHelper.h" -//MITK Rendering +// MITK Rendering #include "mitkDoseImageVtkMapper2D.h" -#include "vtkMitkThickSlicesFilter.h" #include "vtkMitkLevelWindowFilter.h" +#include "vtkMitkThickSlicesFilter.h" #include "vtkNeverTranslucentTexture.h" -//VTK +// VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -//ITK +// ITK #include mitk::DoseImageVtkMapper2D::DoseImageVtkMapper2D() { } mitk::DoseImageVtkMapper2D::~DoseImageVtkMapper2D() { - //The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) is listening to this event, - //in order to delete the images from the 3D RW. - this->InvokeEvent( itk::DeleteEvent() ); + // The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) 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::DoseImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]) +// set the two points defining the textured plane according to the dimension and spacing +void mitk::DoseImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer *renderer, double planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float depth = this->CalculateLayerDepth(renderer); - //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct - //plane size in crosshair rotation and swivel mode. + // 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) + // 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::DoseImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) +float mitk::DoseImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer *renderer) { - //get the clipping range to check how deep into z direction we can render images + // 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 + // 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) { + 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::DoseImageVtkMapper2D::GetInput( void ) +const mitk::Image *mitk::DoseImageVtkMapper2D::GetInput(void) { - return static_cast< const mitk::Image * >( GetDataNode()->GetData() ); + return static_cast(GetDataNode()->GetData()); } -vtkProp* mitk::DoseImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) +vtkProp *mitk::DoseImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { - //return the actor corresponding to the renderer + // return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actors; } -void mitk::DoseImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) +void mitk::DoseImageVtkMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { - LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); - mitk::DataNode* datanode = this->GetDataNode(); + mitk::Image *input = const_cast(this->GetInput()); + mitk::DataNode *datanode = this->GetDataNode(); - if ( input == NULL || input->IsInitialized() == false ) + if (input == NULL || input->IsInitialized() == false) { return; } - //check if there is a valid worldGeometry + // check if there is a valid worldGeometry const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldPlaneGeometry(); - if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) + 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() ) ) + if (!RenderingGeometryIntersectsImage(worldGeometry, input->GetSlicedGeometry())) { // set image to NULL, to clear the texture in 3D, because // the latest image is used there if the plane is out of the geometry // see bug-13275 localStorage->m_ReslicedImage = NULL; - localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); + localStorage->m_Mapper->SetInputData(localStorage->m_EmptyPolyData); return; } - //set main input for ExtractSliceFilter + // set main input for ExtractSliceFilter localStorage->m_Reslicer->SetInput(input); localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); - localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); + localStorage->m_Reslicer->SetTimeStep(this->GetTimestep()); - //set the transformation of the image to adapt reslice axis - localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) ); + // set the transformation of the image to adapt reslice axis + localStorage->m_Reslicer->SetResliceTransformByGeometry( + input->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep())); - //is the geometry of the slice based on the input image or the worldgeometry? + // 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) ) + if ((input->GetDimension() >= 3) && (input->GetDimension(2) > 1)) { VtkResliceInterpolationProperty *resliceInterpolationProperty; - datanode->GetProperty( - resliceInterpolationProperty, "reslice interpolation" ); + datanode->GetProperty(resliceInterpolationProperty, "reslice interpolation"); int interpolationMode = VTK_RESLICE_NEAREST; - if ( resliceInterpolationProperty != NULL ) + if (resliceInterpolationProperty != NULL) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } - switch ( interpolationMode ) + 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; + 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. + // set the vtk output property to true, makes sure that no unneeded mitk image convertion + // is done. localStorage->m_Reslicer->SetVtkOutputRequest(true); - //Thickslicing + // Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; // Thick slices parameters - if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed + if (input->GetPixelType().GetNumberOfComponents() == 1) // for now only single component are allowed { - DataNode *dn=renderer->GetCurrentWorldPlaneGeometryNode(); - if(dn) + DataNode *dn = renderer->GetCurrentWorldPlaneGeometryNode(); + if (dn) { - ResliceMethodProperty *resliceMethodEnumProperty=0; + ResliceMethodProperty *resliceMethodEnumProperty = 0; - if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) + if (dn->GetProperty(resliceMethodEnumProperty, "reslice.thickslices") && resliceMethodEnumProperty) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); - IntProperty *intProperty=0; - if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) + IntProperty *intProperty = 0; + if (dn->GetProperty(intProperty, "reslice.thickslices.num") && intProperty) { thickSlicesNum = intProperty->GetValue(); - if(thickSlicesNum < 1) thickSlicesNum=1; - if(thickSlicesNum > 10) thickSlicesNum=10; + 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 ); + const PlaneGeometry *planeGeometry = dynamic_cast(worldGeometry); - if(thickSlicesMode > 0) + if (thickSlicesMode > 0) { double dataZSpacing = 1.0; Vector3D normInIndex, normal; - if ( planeGeometry != NULL ){ + if (planeGeometry != NULL) + { normal = planeGeometry->GetNormal(); - }else{ - const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); - if(abstractGeometry != NULL) + } + else + { + const mitk::AbstractTransformGeometry *abstractGeometry = + dynamic_cast(worldGeometry); + if (abstractGeometry != NULL) normal = abstractGeometry->GetPlane()->GetNormal(); else - return; //no fitting geometry set + return; // no fitting geometry set } normal.Normalize(); - input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); + input->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep())->WorldToIndex(normal, normInIndex); dataZSpacing = 1.0 / normInIndex.GetNorm(); - localStorage->m_Reslicer->SetOutputDimensionality( 3 ); + localStorage->m_Reslicer->SetOutputDimensionality(3); localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); - localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); + localStorage->m_Reslicer->SetOutputExtentZDirection(-thickSlicesNum, 0 + thickSlicesNum); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. - localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); - localStorage->m_TSFilter->SetInputData( localStorage->m_Reslicer->GetVtkOutput() ); + localStorage->m_TSFilter->SetThickSliceMode(thickSlicesMode - 1); + localStorage->m_TSFilter->SetInputData(localStorage->m_Reslicer->GetVtkOutput()); - //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually + // 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 ); + // 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->SetOutputExtentZDirection(0, 0); localStorage->m_Reslicer->Modified(); - //start the pipeline with updating the largest possible, needed if the geometry of the input has changed + // 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 + // this used for generating a vtkPLaneSource with the right size double sliceBounds[6]; - for ( int i = 0; i < 6; ++i ) + for (int i = 0; i < 6; ++i) { sliceBounds[i] = 0.0; } localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); - //get the spacing of the slice + // get the spacing of the slice localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); // calculate minimum bounding rect of IMAGE in texture { double textureClippingBounds[6]; - for ( int i = 0; i < 6; ++i ) + 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 ); + 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 ); + textureClippingBounds[0] = static_cast(textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5); + textureClippingBounds[1] = static_cast(textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5); + textureClippingBounds[2] = static_cast(textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5); + textureClippingBounds[3] = static_cast(textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5); - //clipping bounds for cutting the image + // clipping bounds for cutting the image localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds); } - //get the number of scalar components to distinguish between different image types + // get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); - //get the showIsoLines property + // get the showIsoLines property bool showIsoLines = false; - datanode->GetBoolProperty( "dose.showIsoLines", showIsoLines, renderer ); + datanode->GetBoolProperty("dose.showIsoLines", showIsoLines, renderer); - if(showIsoLines) //contour rendering + if (showIsoLines) // contour rendering { - //generate contours/outlines + // generate contours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); - if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) ) + if (datanode->GetFloatProperty("outline width", binaryOutlineWidth, renderer)) { - if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) + if (localStorage->m_Actors->GetNumberOfPaths() > 1) { float binaryOutlineShadowWidth(1.5); - datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer ); + datanode->GetFloatProperty("outline shadow width", binaryOutlineShadowWidth, renderer); - dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) - ->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth ); + dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) + ->GetProperty() + ->SetLineWidth(binaryOutlineWidth * binaryOutlineShadowWidth); } - localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth ); + localStorage->m_Actor->GetProperty()->SetLineWidth(binaryOutlineWidth); } } else { localStorage->m_ReslicedImage = NULL; - localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); + localStorage->m_Mapper->SetInputData(localStorage->m_EmptyPolyData); return; } - this->ApplyOpacity( renderer ); + this->ApplyOpacity(renderer); this->ApplyRenderingMode(renderer); // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); int displayedComponent = 0; if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1) { localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent); localStorage->m_VectorComponentExtractor->SetInputData(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0)); } else { - //connect the input with the levelwindow filter + // connect the input with the levelwindow filter localStorage->m_LevelWindowFilter->SetInputData(localStorage->m_ReslicedImage); } // check for texture interpolation property bool textureInterpolation = false; - GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); + GetDataNode()->GetBoolProperty("texture interpolation", textureInterpolation, renderer); - //set the interpolation modus according to the property + // 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()); - this->TransformActor( renderer ); + this->TransformActor(renderer); - vtkActor* contourShadowActor = dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0)); + vtkActor *contourShadowActor = dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)); - if(showIsoLines) //connect the mapper with the polyData which contains the lines + if (showIsoLines) // connect the mapper with the polyData which contains the lines { - //We need the contour for the binary outline property as actor + // We need the contour for the binary outline property as actor localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData); - localStorage->m_Actor->SetTexture(NULL); //no texture for contours + localStorage->m_Actor->SetTexture(NULL); // no texture for contours - bool binaryOutlineShadow( false ); - datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer ); + bool binaryOutlineShadow(false); + datanode->GetBoolProperty("outline binary shadow", binaryOutlineShadow, renderer); - if ( binaryOutlineShadow ) - contourShadowActor->SetVisibility( true ); + if (binaryOutlineShadow) + contourShadowActor->SetVisibility(true); else - contourShadowActor->SetVisibility( false ); + 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 + { // 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 + // set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); - contourShadowActor->SetVisibility( false ); + contourShadowActor->SetVisibility(false); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::DoseImageVtkMapper2D::ApplyLevelWindow(mitk::BaseRenderer *renderer) { - LocalStorage *localStorage = this->GetLocalStorage( renderer ); + LocalStorage *localStorage = this->GetLocalStorage(renderer); LevelWindow levelWindow; - this->GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" ); - localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); + 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" ) ) + if (this->GetDataNode()->GetLevelWindow(opacLevelWindow, renderer, "opaclevelwindow")) { - //pass the opaque level window to the filter + // 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 + // no opaque level window localStorage->m_LevelWindowFilter->SetMinOpacity(0.0); localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0); } } -void mitk::DoseImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyColor(mitk::BaseRenderer *renderer) { - LocalStorage *localStorage = this->GetLocalStorage( renderer ); + LocalStorage *localStorage = this->GetLocalStorage(renderer); - float rgb[3]= { 1.0f, 1.0f, 1.0f }; + 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 hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); - if(hover && !selected) + if (hover && !selected) { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.hoveringcolor", renderer)); - if(colorprop.IsNotNull()) + mitk::ColorProperty::Pointer colorprop = + dynamic_cast(GetDataNode()->GetProperty("binaryimage.hoveringcolor", renderer)); + if (colorprop.IsNotNull()) { - memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float)); } else { - GetDataNode()->GetColor( rgb, renderer, "color" ); + GetDataNode()->GetColor(rgb, renderer, "color"); } } - if(selected) + if (selected) { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.selectedcolor", renderer)); - if(colorprop.IsNotNull()) { - memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + 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) + if (!hover && !selected) { - GetDataNode()->GetColor( rgb, renderer, "color" ); + 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); + 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 ) + 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()) + 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)); + 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); + 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::DoseImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyOpacity(mitk::BaseRenderer *renderer) { - LocalStorage* localStorage = this->GetLocalStorage( 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 + 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 ) + if (localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1) { - dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity); + dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) + ->GetProperty() + ->SetOpacity(opacity); } } -void mitk::DoseImageVtkMapper2D::ApplyRenderingMode( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyRenderingMode(mitk::BaseRenderer *renderer) { - LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); bool binary = false; - this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); - if(binary) // is it a binary image? + 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. + // 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 + // all other image types can make use of the rendering mode int renderingMode = mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR; - mitk::RenderingModeProperty::Pointer mode = dynamic_cast(this->GetDataNode()->GetProperty( "Image Rendering.Mode", renderer )); - if(mode.IsNotNull()) + mitk::RenderingModeProperty::Pointer mode = + dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Mode", renderer)); + if (mode.IsNotNull()) { renderingMode = mode->GetRenderingMode(); } - switch(renderingMode) + switch (renderingMode) { - 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; - default: - MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead."; - this->ApplyLookuptable( renderer ); - 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; + default: + MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead."; + this->ApplyLookuptable(renderer); + this->ApplyLevelWindow(renderer); + break; } } - //we apply color for all images (including binaries). - this->ApplyColor( renderer ); + // we apply color for all images (including binaries). + this->ApplyColor(renderer); } -void mitk::DoseImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyLookuptable(mitk::BaseRenderer *renderer) { - LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); - vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable; + 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")); + mitk::LookupTableProperty::Pointer lookupTableProp = + dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); - if( lookupTableProp.IsNotNull() ) // is a lookuptable set? + if (lookupTableProp.IsNotNull()) // is a lookuptable set? { usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else { //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'. - //A default (rainbow) lookup table will be used. - //Here have to do nothing. Warning for the user has been removed, due to unwanted console output - //in every interation of the rendering. + // A default (rainbow) lookup table will be used. + // Here have to do nothing. Warning for the user has been removed, due to unwanted console output + // in every interation of the rendering. } localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable); } void mitk::DoseImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer *renderer) { - mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); + mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast( + this->GetDataNode()->GetProperty("Image Rendering.Transfer Function", renderer)); - if( transferFunctionProp.IsNull() ) + 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."; + 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 *localStorage = m_LSH.GetLocalStorage(renderer); + // pass the transfer function to our level window filter localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction()); } -void mitk::DoseImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) +void mitk::DoseImageVtkMapper2D::Update(mitk::BaseRenderer *renderer) { - bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); - if ( !visible ) + if (!visible) { return; } - mitk::Image* data = const_cast( this->GetInput() ); - if ( data == NULL ) + 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 ); + this->CalculateTimeStep(renderer); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); - if ( ( dataTimeGeometry == NULL ) - || ( dataTimeGeometry->CountTimeSteps() == 0 ) - || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) + if ((dataTimeGeometry == NULL) || (dataTimeGeometry->CountTimeSteps() == 0) || + (!dataTimeGeometry->IsValidTimeStep(this->GetTimestep()))) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - //check if something important has changed and we need to rerender - if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? - || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? - || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified? - || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) - || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? - || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) + // check if something important has changed and we need to rerender + if ((localStorage->m_LastUpdateTime < node->GetMTime()) // was the node modified? + || + (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) // Was the data modified? + || + (localStorage->m_LastUpdateTime < + renderer->GetCurrentWorldPlaneGeometryUpdateTime()) // was the geometry modified? + || + (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) || + (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) // was a property modified? + || + (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime())) { - this->GenerateDataForRenderer( renderer ); + 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::DoseImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +void mitk::DoseImageVtkMapper2D::SetDefaultProperties(mitk::DataNode *node, + mitk::BaseRenderer *renderer, + bool overwrite) { - mitk::Image::Pointer image = dynamic_cast(node->GetData()); + 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 ) ); + 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)); mitk::RenderingModeProperty::Pointer renderingModeProperty = mitk::RenderingModeProperty::New(); - node->AddProperty( "Image Rendering.Mode", renderingModeProperty); + node->AddProperty("Image Rendering.Mode", renderingModeProperty); // Set default grayscale look-up table mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); mitkLut->SetType(mitk::LookupTable::GRAYSCALE); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed - if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) ) + 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 + if (photometricInterpretation.find("MONOCHROME1") != std::string::npos) // meaning: display MINIMUM pixels as WHITE { // Set inverse grayscale look-up table mitkLut->SetType(mitk::LookupTable::INVERSE_GRAYSCALE); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); } // Otherwise do nothing - the default grayscale look-up table has already been set } bool isBinaryImage(false); - if ( ! node->GetBoolProperty("binary", isBinaryImage) ) + 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->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() ) + if (centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized()) { - minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); - maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); + 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(); + minValue = image->GetStatistics()->GetScalarValueMin(); + maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } - isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); + 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("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 + 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("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) + 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 (image.IsNotNull() && image->IsInitialized()) { - if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) + if ((overwrite) || (node->GetProperty("levelwindow", renderer) == NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; - if (GetBackwardsCompatibleDICOMProperty(0x0028, 0x1050, "dicom.voilut.WindowCenter", image->GetPropertyList(), sLevel) - && GetBackwardsCompatibleDICOMProperty(0x0028, 0x1051, "dicom.voilut.WindowWidth", image->GetPropertyList(), sWindow)) + if (GetBackwardsCompatibleDICOMProperty( + 0x0028, 0x1050, "dicom.voilut.WindowCenter", image->GetPropertyList(), sLevel) && + GetBackwardsCompatibleDICOMProperty( + 0x0028, 0x1051, "dicom.voilut.WindowWidth", image->GetPropertyList(), sWindow)) { - float level = atof( sLevel.c_str() ); - float window = atof( sWindow.c_str() ); + float level = atof(sLevel.c_str()); + float window = atof(sWindow.c_str()); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; - if (GetBackwardsCompatibleDICOMProperty(0x0028, 0x0108, "dicom.series.SmallestPixelValueInSeries", image->GetPropertyList(), sSmallestPixelValueInSeries) - && GetBackwardsCompatibleDICOMProperty(0x0028, 0x0109, "dicom.series.LargestPixelValueInSeries", image->GetPropertyList(), sLargestPixelValueInSeries)) + if (GetBackwardsCompatibleDICOMProperty(0x0028, + 0x0108, + "dicom.series.SmallestPixelValueInSeries", + image->GetPropertyList(), + sSmallestPixelValueInSeries) && + GetBackwardsCompatibleDICOMProperty(0x0028, + 0x0109, + "dicom.series.LargestPixelValueInSeries", + image->GetPropertyList(), + sLargestPixelValueInSeries)) { - float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); - float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); - contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? + 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.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 ); + 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) ) + 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); + opaclevwin.SetRangeMinMax(0, 255); + opaclevwin.SetWindowBounds(0, 255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); - node->SetProperty( "opaclevelwindow", prop, renderer ); + node->SetProperty("opaclevelwindow", prop, renderer); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } -mitk::DoseImageVtkMapper2D::LocalStorage* mitk::DoseImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) +mitk::DoseImageVtkMapper2D::LocalStorage *mitk::DoseImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer *renderer) { return m_LSH.GetLocalStorage(renderer); } - -vtkSmartPointer mitk::DoseImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ) +vtkSmartPointer mitk::DoseImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer *renderer) { - vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw - vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points + vtkSmartPointer points = vtkSmartPointer::New(); // the points to draw + vtkSmartPointer lines = vtkSmartPointer::New(); // the lines to connect the points vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(3); colors->SetName("Colors"); float pref; - this->GetDataNode()->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + this->GetDataNode()->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), pref); - mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast(GetDataNode()->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast( + GetDataNode()->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = propIsoSet->GetValue(); - for(mitk::IsoDoseLevelSet::ConstIterator doseIT = isoDoseLevelSet->Begin(); doseIT!=isoDoseLevelSet->End();++doseIT) + for (mitk::IsoDoseLevelSet::ConstIterator doseIT = isoDoseLevelSet->Begin(); doseIT != isoDoseLevelSet->End(); + ++doseIT) { - if(doseIT->GetVisibleIsoLine()) + if (doseIT->GetVisibleIsoLine()) { this->CreateLevelOutline(renderer, &(doseIT.Value()), pref, points, lines, colors); - }//end of if visible dose value - }//end of loop over all does values + } // end of if visible dose value + } // end of loop over all does values - mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec = dynamic_cast(GetDataNode()->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); + mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec = dynamic_cast( + GetDataNode()->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); mitk::IsoDoseLevelVector::Pointer frereIsoDoseLevelVec = propfreeIsoVec->GetValue(); - for(mitk::IsoDoseLevelVector::ConstIterator freeDoseIT = frereIsoDoseLevelVec->Begin(); freeDoseIT!=frereIsoDoseLevelVec->End();++freeDoseIT) + for (mitk::IsoDoseLevelVector::ConstIterator freeDoseIT = frereIsoDoseLevelVec->Begin(); + freeDoseIT != frereIsoDoseLevelVec->End(); + ++freeDoseIT) { - if(freeDoseIT->Value()->GetVisibleIsoLine()) + if (freeDoseIT->Value()->GetVisibleIsoLine()) { this->CreateLevelOutline(renderer, freeDoseIT->Value(), pref, points, lines, colors); - }//end of if visible dose value - }//end of loop over all does values + } // end of if visible dose value + } // end of loop over all does values // 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); polyData->GetCellData()->SetScalars(colors); return polyData; } -void mitk::DoseImageVtkMapper2D::CreateLevelOutline(mitk::BaseRenderer* renderer, const mitk::IsoDoseLevel* level, float pref, vtkSmartPointer points, vtkSmartPointer lines, vtkSmartPointer colors) +void mitk::DoseImageVtkMapper2D::CreateLevelOutline(mitk::BaseRenderer *renderer, + const mitk::IsoDoseLevel *level, + float pref, + vtkSmartPointer points, + vtkSmartPointer lines, + vtkSmartPointer colors) { - LocalStorage* localStorage = this->GetLocalStorage(renderer); + LocalStorage *localStorage = this->GetLocalStorage(renderer); - //get the min and max index values of each direction - int* extent = localStorage->m_ReslicedImage->GetExtent(); + // 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? - //get the depth for each contour + int *dims = localStorage->m_ReslicedImage->GetDimensions(); // dimensions of the image + int line = dims[0]; // how many pixels per line? + // get the depth for each contour float depth = CalculateLayerDepth(renderer); - double doseValue = level->GetDoseValue()*pref; + double doseValue = level->GetDoseValue() * pref; mitk::IsoDoseLevel::ColorType isoColor = level->GetColor(); - unsigned char colorLine[3] = {static_cast(isoColor.GetRed()*255), - static_cast(isoColor.GetGreen()*255), - static_cast(isoColor.GetBlue()*255)}; + unsigned char colorLine[3] = {static_cast(isoColor.GetRed() * 255), + static_cast(isoColor.GetGreen() * 255), + static_cast(isoColor.GetBlue() * 255)}; - int x = xMin; //pixel index x - int y = yMin; //pixel index y - float* currentPixel; + int x = xMin; // pixel index x + int y = yMin; // pixel index y + float *currentPixel; // We take the pointer to the first pixel of the image - currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer() ); + currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer()); while (y <= yMax) { - //if the current pixel value is set to something + // if the current pixel value is set to something if ((currentPixel) && (*currentPixel >= doseValue)) { - //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) < doseValue) - { //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 + // 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) < doseValue) + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv not the last line vvvvv - if (y < yMax && *(currentPixel+line) < doseValue) - { //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); + // if vvvvv not the last line vvvvv + if (y < yMax && *(currentPixel + line) < doseValue) + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv not the first pixel vvvvv - if ( (x > xMin || y > yMin) && *(currentPixel-1) < doseValue) - { //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); + // if vvvvv not the first pixel vvvvv + if ((x > xMin || y > yMin) && *(currentPixel - 1) < doseValue) + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv not the last pixel vvvvv - if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) < doseValue) - { //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); + // if vvvvv not the last pixel vvvvv + if ((y < yMax || (x < xMax)) && *(currentPixel + 1) < doseValue) + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } /* now consider pixels at the edge of the image */ - //if vvvvv left edge of image vvvvv + // 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); + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv right edge of image vvvvv + // 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); + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv bottom edge of image vvvvv + // 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); + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv top edge of image vvvvv + // 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); + { // 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); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - }//end if currentpixel is set + } // end if currentpixel is set x++; if (x > xMax) - { //reached end of line + { // 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 + } // end of while } -void mitk::DoseImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) +void mitk::DoseImageVtkMapper2D::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 + // 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) + // 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); + // 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 ) + if (localStorage->m_Actors->GetNumberOfPaths() > 1) { - vtkActor* secondaryActor = dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) ); + 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); + secondaryActor->SetPosition(-0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0); } } -bool mitk::DoseImageVtkMapper2D::RenderingGeometryIntersectsImage( const PlaneGeometry* renderingGeometry, SlicedGeometry3D* imageGeometry ) +bool mitk::DoseImageVtkMapper2D::RenderingGeometryIntersectsImage(const PlaneGeometry *renderingGeometry, + SlicedGeometry3D *imageGeometry) { // if either one of the two geometries is NULL we return true // for safety reasons - if ( renderingGeometry == NULL || imageGeometry == NULL ) + 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++ ) + ScalarType initialDistance = renderingGeometry->SignedDistance(imageGeometry->GetCornerPoint(0)); + for (int i = 1; i < 8; i++) { - mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i ); + mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint(i); // get the distance to the other cornerpoints - ScalarType distance = renderingGeometry->SignedDistance( cornerPoint ); + ScalarType distance = renderingGeometry->SignedDistance(cornerPoint); // if it has not the same signing as the distance of the first point - if ( initialDistance * distance < 0 ) + 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::DoseImageVtkMapper2D::LocalStorage::~LocalStorage() { } mitk::DoseImageVtkMapper2D::LocalStorage::LocalStorage() -: m_VectorComponentExtractor(vtkSmartPointer::New()) + : m_VectorComponentExtractor(vtkSmartPointer::New()) { - m_LevelWindowFilter = vtkSmartPointer::New(); - //Do as much actions as possible in here to avoid double executions. + // 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) + // the following actions are always the same and thus can be performed + // in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); mitk::LookupTable::Pointer mitkLUT = mitk::LookupTable::New(); - //built a default lookuptable + // built a default lookuptable mitkLUT->SetType(mitk::LookupTable::GRAYSCALE); m_DefaultLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_BINARY); m_BinaryLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_RAINBOW_COLOR); m_ColorLookupTable = mitkLUT->GetVtkLookupTable(); - //do not repeat the texture (the image) + // do not repeat the texture (the image) m_Texture->RepeatOff(); - //set the mapper for the actor - m_Actor->SetMapper( m_Mapper ); + // set the mapper for the actor + m_Actor->SetMapper(m_Mapper); vtkSmartPointer outlineShadowActor = vtkSmartPointer::New(); - outlineShadowActor->SetMapper( m_Mapper ); + outlineShadowActor->SetMapper(m_Mapper); - m_Actors->AddPart( outlineShadowActor ); - m_Actors->AddPart( m_Actor ); + m_Actors->AddPart(outlineShadowActor); + m_Actors->AddPart(m_Actor); } diff --git a/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp b/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp index c31aa6c71f..53f872f987 100644 --- a/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp +++ b/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp @@ -1,597 +1,592 @@ /*=================================================================== 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. ===================================================================*/ #define GPU_INFO MITK_INFO("mapper.vr") #define GPU_WARN MITK_WARN("mapper.vr") #define GPU_ERROR MITK_ERROR("mapper.vr") #include "mitkGPUVolumeMapper3D.h" #include "mitkDataNode.h" #include "mitkColorProperty.h" #include "mitkColorProperty.h" #include "mitkLevelWindow.h" #include "mitkLevelWindowProperty.h" #include "mitkLookupTableProperty.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkTransferFunctionInitializer.h" #include "mitkTransferFunctionProperty.h" #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vtkMitkGPUVolumeRayCastMapper.h" #include "vtkOpenGLGPUVolumeRayCastMapper.h" const mitk::Image *mitk::GPUVolumeMapper3D::GetInput() { return static_cast(GetDataNode()->GetData()); } void mitk::GPUVolumeMapper3D::MitkRenderVolumetricGeometry(mitk::BaseRenderer *renderer) { VtkMapper::MitkRenderVolumetricGeometry(renderer); // if(ls->m_gpuInitialized) // ls->m_MapperGPU->UpdateMTime(); } bool mitk::GPUVolumeMapper3D::InitGPU(mitk::BaseRenderer * /*renderer*/) { return false; // TODO 18922 } void mitk::GPUVolumeMapper3D::InitCPU(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_cpuInitialized) return; ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); ls->m_MapperCPU = vtkSmartPointer::New(); int numThreads = ls->m_MapperCPU->GetNumberOfThreads(); GPU_INFO << "initializing cpu-raycast-vr (vtkFixedPointVolumeRayCastMapper) (" << numThreads << " threads)"; ls->m_MapperCPU->SetSampleDistance(1.0); // ls->m_MapperCPU->LockSampleDistanceToInputSpacingOn(); ls->m_MapperCPU->SetImageSampleDistance(1.0); ls->m_MapperCPU->IntermixIntersectingGeometryOn(); ls->m_MapperCPU->SetAutoAdjustSampleDistances(0); ls->m_VolumePropertyCPU = vtkSmartPointer::New(); ls->m_VolumePropertyCPU->ShadeOn(); ls->m_VolumePropertyCPU->SetAmbient(0.10f); // 0.05f ls->m_VolumePropertyCPU->SetDiffuse(0.50f); // 0.45f ls->m_VolumePropertyCPU->SetSpecular(0.40f); // 0.50f ls->m_VolumePropertyCPU->SetSpecularPower(16.0f); ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); ls->m_VolumeCPU = vtkSmartPointer::New(); ls->m_VolumeCPU->SetMapper(ls->m_MapperCPU); ls->m_VolumeCPU->SetProperty(ls->m_VolumePropertyCPU); ls->m_VolumeCPU->VisibilityOn(); ls->m_MapperCPU->SetInputConnection(m_UnitSpacingImageFilter->GetOutputPort()); // m_Resampler->GetOutput()); ls->m_cpuInitialized = true; } -{ -} - void mitk::GPUVolumeMapper3D::DeinitCPU(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (!ls->m_cpuInitialized) return; GPU_INFO << "deinitializing cpu-raycast-vr"; ls->m_VolumePropertyCPU = NULL; ls->m_MapperCPU = NULL; ls->m_VolumeCPU = NULL; ls->m_cpuInitialized = false; } mitk::GPUVolumeMapper3D::GPUVolumeMapper3D() { m_VolumeNULL = 0; m_commonInitialized = false; } mitk::GPUVolumeMapper3D::~GPUVolumeMapper3D() { DeinitCommon(); } void mitk::GPUVolumeMapper3D::InitCommon() { if (m_commonInitialized) return; m_UnitSpacingImageFilter = vtkSmartPointer::New(); m_UnitSpacingImageFilter->SetOutputSpacing(1.0, 1.0, 1.0); CreateDefaultTransferFunctions(); m_commonInitialized = true; } void mitk::GPUVolumeMapper3D::DeinitCommon() { if (!m_commonInitialized) return; m_commonInitialized = false; } bool mitk::GPUVolumeMapper3D::IsRenderable(mitk::BaseRenderer *renderer) { if (!GetDataNode()) return false; DataNode *node = GetDataNode(); bool visible = true; node->GetVisibility(visible, renderer, "visible"); if (!visible) return false; bool value = false; if (!node->GetBoolProperty("volumerendering", value, renderer)) return false; if (!value) return false; mitk::Image *input = const_cast(this->GetInput()); if (!input || !input->IsInitialized()) return false; vtkImageData *inputData = input->GetVtkImageData(this->GetTimestep()); if (inputData == NULL) return false; return true; } void mitk::GPUVolumeMapper3D::InitVtkMapper(mitk::BaseRenderer *renderer) { if (IsRAYEnabled(renderer)) { DeinitCPU(renderer); - DeinitGPU(renderer); if (!InitRAY(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } else if (IsGPUEnabled(renderer)) { DeinitCPU(renderer); DeinitRAY(renderer); if (!InitGPU(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } else { fallback: - DeinitGPU(renderer); DeinitRAY(renderer); InitCPU(renderer); } } vtkProp *mitk::GPUVolumeMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { if (!IsRenderable(renderer)) { if (!m_VolumeNULL) { m_VolumeNULL = vtkSmartPointer::New(); m_VolumeNULL->VisibilityOff(); } return m_VolumeNULL; } InitCommon(); InitVtkMapper(renderer); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_rayInitialized) return ls->m_VolumeRAY; if (ls->m_gpuInitialized) return ls->m_VolumeGPU; return ls->m_VolumeCPU; } void mitk::GPUVolumeMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { if (!IsRenderable(renderer)) return; InitCommon(); InitVtkMapper(renderer); mitk::Image *input = const_cast(this->GetInput()); vtkImageData *inputData = input->GetVtkImageData(this->GetTimestep()); m_UnitSpacingImageFilter->SetInputData(inputData); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_rayInitialized) { GenerateDataRAY(renderer); } else if (ls->m_gpuInitialized) { GenerateDataGPU(renderer); } else { GenerateDataCPU(renderer); } // UpdateTransferFunctions UpdateTransferFunctions(renderer); } void mitk::GPUVolumeMapper3D::GenerateDataGPU(mitk::BaseRenderer * /*renderer*/) { } void mitk::GPUVolumeMapper3D::GenerateDataCPU(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); int nextLod = mitk::RenderingManager::GetInstance()->GetNextLOD(renderer); if (IsLODEnabled(renderer) && nextLod == 0) { ls->m_MapperCPU->SetImageSampleDistance(3.5); ls->m_MapperCPU->SetSampleDistance(1.25); ls->m_VolumePropertyCPU->SetInterpolationTypeToNearest(); } else { ls->m_MapperCPU->SetImageSampleDistance(1.0); ls->m_MapperCPU->SetSampleDistance(1.0); ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); } // Check raycasting mode if (IsMIPEnabled(renderer)) ls->m_MapperCPU->SetBlendModeToMaximumIntensity(); else ls->m_MapperCPU->SetBlendModeToComposite(); // Updating shadings { float value = 0; if (GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient", value, renderer)) ls->m_VolumePropertyCPU->SetAmbient(value); if (GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse", value, renderer)) ls->m_VolumePropertyCPU->SetDiffuse(value); if (GetDataNode()->GetFloatProperty("volumerendering.cpu.specular", value, renderer)) ls->m_VolumePropertyCPU->SetSpecular(value); if (GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power", value, renderer)) ls->m_VolumePropertyCPU->SetSpecularPower(value); } } void mitk::GPUVolumeMapper3D::CreateDefaultTransferFunctions() { m_DefaultOpacityTransferFunction = vtkSmartPointer::New(); m_DefaultOpacityTransferFunction->AddPoint(0.0, 0.0); m_DefaultOpacityTransferFunction->AddPoint(255.0, 0.8); m_DefaultOpacityTransferFunction->ClampingOn(); m_DefaultGradientTransferFunction = vtkSmartPointer::New(); m_DefaultGradientTransferFunction->AddPoint(0.0, 0.0); m_DefaultGradientTransferFunction->AddPoint(255.0, 0.8); m_DefaultGradientTransferFunction->ClampingOn(); m_DefaultColorTransferFunction = vtkSmartPointer::New(); m_DefaultColorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0); m_DefaultColorTransferFunction->AddRGBPoint(127.5, 1, 1, 0.0); m_DefaultColorTransferFunction->AddRGBPoint(255.0, 0.8, 0.2, 0); m_DefaultColorTransferFunction->ClampingOn(); m_BinaryOpacityTransferFunction = vtkSmartPointer::New(); m_BinaryOpacityTransferFunction->AddPoint(0, 0.0); m_BinaryOpacityTransferFunction->AddPoint(1, 1.0); m_BinaryGradientTransferFunction = vtkSmartPointer::New(); m_BinaryGradientTransferFunction->AddPoint(0.0, 1.0); m_BinaryColorTransferFunction = vtkSmartPointer::New(); } void mitk::GPUVolumeMapper3D::UpdateTransferFunctions(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); vtkPiecewiseFunction *opacityTransferFunction = m_DefaultOpacityTransferFunction; vtkPiecewiseFunction *gradientTransferFunction = m_DefaultGradientTransferFunction; vtkColorTransferFunction *colorTransferFunction = m_DefaultColorTransferFunction; bool isBinary = false; GetDataNode()->GetBoolProperty("binary", isBinary, renderer); if (isBinary) { opacityTransferFunction = m_BinaryOpacityTransferFunction; gradientTransferFunction = m_BinaryGradientTransferFunction; colorTransferFunction = m_BinaryColorTransferFunction; colorTransferFunction->RemoveAllPoints(); float rgb[3]; if (!GetDataNode()->GetColor(rgb, renderer)) rgb[0] = rgb[1] = rgb[2] = 1; colorTransferFunction->AddRGBPoint(0, rgb[0], rgb[1], rgb[2]); colorTransferFunction->Modified(); } else { mitk::TransferFunctionProperty *transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction", renderer)); if (transferFunctionProp) { opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); } } if (ls->m_gpuInitialized) { ls->m_VolumePropertyGPU->SetColor(colorTransferFunction); ls->m_VolumePropertyGPU->SetScalarOpacity(opacityTransferFunction); ls->m_VolumePropertyGPU->SetGradientOpacity(gradientTransferFunction); } if (ls->m_rayInitialized) { ls->m_VolumePropertyRAY->SetColor(colorTransferFunction); ls->m_VolumePropertyRAY->SetScalarOpacity(opacityTransferFunction); ls->m_VolumePropertyRAY->SetGradientOpacity(gradientTransferFunction); } if (ls->m_cpuInitialized) { ls->m_VolumePropertyCPU->SetColor(colorTransferFunction); ls->m_VolumePropertyCPU->SetScalarOpacity(opacityTransferFunction); ls->m_VolumePropertyCPU->SetGradientOpacity(gradientTransferFunction); } } void mitk::GPUVolumeMapper3D::ApplyProperties(vtkActor * /*actor*/, mitk::BaseRenderer * /*renderer*/) { // GPU_INFO << "ApplyProperties"; } void mitk::GPUVolumeMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { // GPU_INFO << "SetDefaultProperties"; node->AddProperty("volumerendering", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.usemip", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.uselod", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.cpu.ambient", mitk::FloatProperty::New(0.10f), renderer, overwrite); node->AddProperty("volumerendering.cpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.cpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.cpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); bool usegpu = true; #ifdef __APPLE__ usegpu = false; node->AddProperty("volumerendering.uselod", mitk::BoolProperty::New(true), renderer, overwrite); #endif node->AddProperty("volumerendering.usegpu", mitk::BoolProperty::New(usegpu), renderer, overwrite); node->AddProperty("volumerendering.useray", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.ray.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); node->AddProperty("volumerendering.ray.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.ray.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.ray.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("volumerendering.gpu.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); node->AddProperty("volumerendering.gpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.gpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.gpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("volumerendering.gpu.usetexturecompression", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.gpu.reducesliceartifacts", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { if ((overwrite) || (node->GetProperty("levelwindow", renderer) == NULL)) { mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetAuto(image); levWinProp->SetLevelWindow(levelwindow); node->SetProperty("levelwindow", levWinProp, renderer); } if ((overwrite) || (node->GetProperty("TransferFunction", renderer) == NULL)) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); tfInit->SetTransferFunctionMode(0); node->SetProperty("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } bool mitk::GPUVolumeMapper3D::IsLODEnabled(mitk::BaseRenderer *renderer) const { bool value = false; return GetDataNode()->GetBoolProperty("volumerendering.uselod", value, renderer) && value; } bool mitk::GPUVolumeMapper3D::IsMIPEnabled(mitk::BaseRenderer *renderer) { bool value = false; return GetDataNode()->GetBoolProperty("volumerendering.usemip", value, renderer) && value; } bool mitk::GPUVolumeMapper3D::IsGPUEnabled(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool value = false; return ls->m_gpuSupported && GetDataNode()->GetBoolProperty("volumerendering.usegpu", value, renderer) && value; } bool mitk::GPUVolumeMapper3D::InitRAY(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_rayInitialized) return ls->m_raySupported; ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); GPU_INFO << "initializing gpu-raycast-vr (vtkOpenGLGPUVolumeRayCastMapper)"; ls->m_MapperRAY = vtkSmartPointer::New(); ls->m_MapperRAY->SetAutoAdjustSampleDistances(0); ls->m_MapperRAY->SetSampleDistance(1.0); ls->m_VolumePropertyRAY = vtkSmartPointer::New(); ls->m_VolumePropertyRAY->ShadeOn(); ls->m_VolumePropertyRAY->SetAmbient(0.25f); // 0.05f ls->m_VolumePropertyRAY->SetDiffuse(0.50f); // 0.45f ls->m_VolumePropertyRAY->SetSpecular(0.40f); // 0.50f ls->m_VolumePropertyRAY->SetSpecularPower(16.0f); ls->m_VolumePropertyRAY->SetInterpolationTypeToLinear(); ls->m_VolumeRAY = vtkSmartPointer::New(); ls->m_VolumeRAY->SetMapper(ls->m_MapperRAY); ls->m_VolumeRAY->SetProperty(ls->m_VolumePropertyRAY); ls->m_VolumeRAY->VisibilityOn(); ls->m_MapperRAY->SetInputConnection(this->m_UnitSpacingImageFilter->GetOutputPort()); ls->m_raySupported = ls->m_MapperRAY->IsRenderSupported(renderer->GetRenderWindow(), ls->m_VolumePropertyRAY); ls->m_rayInitialized = true; return ls->m_raySupported; } void mitk::GPUVolumeMapper3D::DeinitRAY(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_rayInitialized) { GPU_INFO << "deinitializing gpu-raycast-vr"; ls->m_MapperRAY = NULL; ls->m_VolumePropertyRAY = NULL; // Here ReleaseGraphicsResources has to be called to avoid VTK error messages. // This seems like a VTK bug, because ReleaseGraphicsResources() is ment for internal use, // but you cannot just delete the object (last smartpointer reference) without getting the // VTK error. ls->m_VolumeRAY->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetRenderWindow()); ls->m_VolumeRAY = NULL; ls->m_rayInitialized = false; } } void mitk::GPUVolumeMapper3D::GenerateDataRAY(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD(renderer) == 0) ls->m_MapperRAY->SetImageSampleDistance(4.0); else ls->m_MapperRAY->SetImageSampleDistance(1.0); // Check raycasting mode if (IsMIPEnabled(renderer)) ls->m_MapperRAY->SetBlendModeToMaximumIntensity(); else ls->m_MapperRAY->SetBlendModeToComposite(); // Updating shadings { float value = 0; if (GetDataNode()->GetFloatProperty("volumerendering.ray.ambient", value, renderer)) ls->m_VolumePropertyRAY->SetAmbient(value); if (GetDataNode()->GetFloatProperty("volumerendering.ray.diffuse", value, renderer)) ls->m_VolumePropertyRAY->SetDiffuse(value); if (GetDataNode()->GetFloatProperty("volumerendering.ray.specular", value, renderer)) ls->m_VolumePropertyRAY->SetSpecular(value); if (GetDataNode()->GetFloatProperty("volumerendering.ray.specular.power", value, renderer)) ls->m_VolumePropertyRAY->SetSpecularPower(value); } } bool mitk::GPUVolumeMapper3D::IsRAYEnabled(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool value = false; return ls->m_raySupported && GetDataNode()->GetBoolProperty("volumerendering.useray", value, renderer) && value; } diff --git a/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp b/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp index d0f2ab40aa..0760835b3e 100644 --- a/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp +++ b/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp @@ -1,626 +1,624 @@ /*=================================================================== 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. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkMitkGPUVolumeRayCastMapper.h" #include "vtkCamera.h" #include "vtkCellData.h" #include "vtkCommand.h" // for VolumeMapperRender{Start|End|Progress}Event #include "vtkDataArray.h" #include "vtkGPUInfo.h" #include "vtkGPUInfoList.h" #include "vtkImageData.h" #include "vtkImageResample.h" #include "vtkMultiThreader.h" #include "vtkPointData.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkRendererCollection.h" #include "vtkTimerLog.h" #include "vtkVolume.h" #include "vtkVolumeProperty.h" #include vtkInstantiatorNewMacro(vtkMitkGPUVolumeRayCastMapper); vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, MaskInput, vtkImageData); vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, TransformedInput, vtkImageData); vtkMitkGPUVolumeRayCastMapper::vtkMitkGPUVolumeRayCastMapper() { this->AutoAdjustSampleDistances = 1; this->ImageSampleDistance = 1.0; this->MinimumImageSampleDistance = 1.0; this->MaximumImageSampleDistance = 10.0; this->SampleDistance = 1.0; this->SmallVolumeRender = 0; this->BigTimeToDraw = 0.0; this->SmallTimeToDraw = 0.0; this->FinalColorWindow = 1.0; this->FinalColorLevel = 0.5; this->GeneratingCanonicalView = 0; this->CanonicalViewImageData = nullptr; this->MaskInput = nullptr; this->MaskBlendFactor = 1.0f; this->AMRMode = 0; this->ClippedCroppingRegionPlanes[0] = VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[1] = VTK_DOUBLE_MIN; this->ClippedCroppingRegionPlanes[2] = VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[3] = VTK_DOUBLE_MIN; this->ClippedCroppingRegionPlanes[4] = VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[5] = VTK_DOUBLE_MIN; this->MaxMemoryInBytes = 0; vtkGPUInfoList *l = vtkGPUInfoList::New(); l->Probe(); if (l->GetNumberOfGPUs() > 0) { vtkGPUInfo *info = l->GetGPUInfo(0); this->MaxMemoryInBytes = info->GetDedicatedVideoMemory(); if (this->MaxMemoryInBytes == 0) { this->MaxMemoryInBytes = info->GetDedicatedSystemMemory(); } // we ignore info->GetSharedSystemMemory(); as this is very slow. } l->Delete(); if (this->MaxMemoryInBytes == 0) // use some default value: 128MB. { this->MaxMemoryInBytes = 128 * 1024 * 1024; } this->MaxMemoryFraction = 0.75; this->ReportProgress = true; this->TransformedInput = nullptr; this->LastInput = nullptr; } // ---------------------------------------------------------------------------- vtkMitkGPUVolumeRayCastMapper::~vtkMitkGPUVolumeRayCastMapper() { this->SetMaskInput(nullptr); this->SetTransformedInput(nullptr); this->LastInput = nullptr; } // ---------------------------------------------------------------------------- // The render method that is called from the volume. If this is a canonical // view render, a specialized version of this method will be called instead. // Otherwise we will // - Invoke a start event // - Start timing // - Check that everything is OK for rendering // - Render // - Stop the timer and record results // - Invoke an end event // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::Render(vtkRenderer *ren, vtkVolume *vol) { // Catch renders that are happening due to a canonical view render and // handle them separately. if (this->GeneratingCanonicalView) { this->CanonicalViewRender(ren, vol); return; } // Invoke a VolumeMapperRenderStartEvent this->InvokeEvent(vtkCommand::VolumeMapperRenderStartEvent, nullptr); // Start the timer to time the length of this render vtkTimerLog *timer = vtkTimerLog::New(); timer->StartTimer(); // Make sure everything about this render is OK. // This is where the input is updated. if (this->ValidateRender(ren, vol)) { // Everything is OK - so go ahead and really do the render this->GPURender(ren, vol); } // Stop the timer timer->StopTimer(); double t = timer->GetElapsedTime(); // cout << "Render Timer " << t << " seconds, " << 1.0/t << " frames per second" << endl; this->TimeToDraw = t; timer->Delete(); if (vol->GetAllocatedRenderTime() < 1.0) { this->SmallTimeToDraw = t; } else { this->BigTimeToDraw = t; } // Invoke a VolumeMapperRenderEndEvent this->InvokeEvent(vtkCommand::VolumeMapperRenderEndEvent, nullptr); } // ---------------------------------------------------------------------------- // Special version for rendering a canonical view - we don't do things like // invoke start or end events, and we don't capture the render time. // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::CanonicalViewRender(vtkRenderer *ren, vtkVolume *vol) { // Make sure everything about this render is OK if (this->ValidateRender(ren, vol)) { // Everything is OK - so go ahead and really do the render this->GPURender(ren, vol); } } // ---------------------------------------------------------------------------- // This method us used by the render method to validate everything before // attempting to render. This method returns 0 if something is not right - // such as missing input, a null renderer or a null volume, no scalars, etc. // In some cases it will produce a vtkErrorMacro message, and in others // (for example, in the case of cropping planes that define a region with // a volume or 0 or less) it will fail silently. If everything is OK, it will // return with a value of 1. // ---------------------------------------------------------------------------- int vtkMitkGPUVolumeRayCastMapper::ValidateRender(vtkRenderer *ren, vtkVolume *vol) { // Check that we have everything we need to render. int goodSoFar = 1; // Check for a renderer - we MUST have one if (!ren) { goodSoFar = 0; vtkErrorMacro("Renderer cannot be null."); } // Check for the volume - we MUST have one if (goodSoFar && !vol) { goodSoFar = 0; vtkErrorMacro("Volume cannot be null."); } // Don't need to check if we have a volume property // since the volume will create one if we don't. Also // don't need to check for the scalar opacity function // or the RGB transfer function since the property will // create them if they do not yet exist. // However we must currently check that the number of // color channels is 3 // TODO: lift this restriction - should work with // gray functions as well. Right now turning off test // because otherwise 4 component rendering isn't working. // Will revisit. if (goodSoFar && vol->GetProperty()->GetColorChannels() != 3) { // goodSoFar = 0; // vtkErrorMacro("Must have a color transfer function."); } // Check the cropping planes. If they are invalid, just silently // fail. This will happen when an interactive widget is dragged // such that it defines 0 or negative volume - this can happen // and should just not render the volume. // Check the cropping planes if (goodSoFar && this->Cropping && (this->CroppingRegionPlanes[0] >= this->CroppingRegionPlanes[1] || this->CroppingRegionPlanes[2] >= this->CroppingRegionPlanes[3] || this->CroppingRegionPlanes[4] >= this->CroppingRegionPlanes[5])) { // No error message here - we want to be silent goodSoFar = 0; } // Check that we have input data vtkImageData *input = this->GetInput(); // If we have a timestamp change or data change then create a new clone. if (input != this->LastInput || input->GetMTime() > this->TransformedInput->GetMTime()) { this->LastInput = input; vtkImageData *clone; if (!this->TransformedInput) { clone = vtkImageData::New(); this->SetTransformedInput(clone); clone->Delete(); } else { clone = this->TransformedInput; } clone->ShallowCopy(input); // @TODO: This is the workaround to deal with GPUVolumeRayCastMapper // not able to handle extents starting from non zero values. // There is not a easy fix in the GPU volume ray cast mapper hence // this fix has been introduced. // Get the current extents. int extents[6], real_extents[6]; clone->GetExtent(extents); clone->GetExtent(real_extents); // Get the current origin and spacing. double origin[3], spacing[3]; clone->GetOrigin(origin); clone->GetSpacing(spacing); for (int cc = 0; cc < 3; cc++) { // Transform the origin and the extents. origin[cc] = origin[cc] + extents[2 * cc] * spacing[cc]; extents[2 * cc + 1] -= extents[2 * cc]; extents[2 * cc] -= extents[2 * cc]; } clone->SetOrigin(origin); clone->SetExtent(extents); } if (goodSoFar && !this->TransformedInput) { vtkErrorMacro("Input is NULL but is required"); goodSoFar = 0; } // Update the date then make sure we have scalars. Note // that we must have point or cell scalars because field // scalars are not supported. vtkDataArray *scalars = nullptr; if (goodSoFar) { // Here is where we update the input // this->TransformedInput->UpdateInformation(); //VTK6_TODO // this->TransformedInput->SetUpdateExtentToWholeExtent(); // this->TransformedInput->Update(); // Now make sure we can find scalars scalars = this->GetScalars( this->TransformedInput, this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag); // We couldn't find scalars if (!scalars) { vtkErrorMacro("No scalars found on input."); goodSoFar = 0; } // Even if we found scalars, if they are field data scalars that isn't good else if (this->CellFlag == 2) { vtkErrorMacro("Only point or cell scalar support - found field scalars instead."); goodSoFar = 0; } } // Make sure the scalar type is actually supported. This mappers supports // almost all standard scalar types. if (goodSoFar) { switch (scalars->GetDataType()) { case VTK_CHAR: vtkErrorMacro(<< "scalar of type VTK_CHAR is not supported " << "because this type is platform dependent. " << "Use VTK_SIGNED_CHAR or VTK_UNSIGNED_CHAR instead."); goodSoFar = 0; break; case VTK_BIT: vtkErrorMacro("scalar of type VTK_BIT is not supported by this mapper."); goodSoFar = 0; break; case VTK_ID_TYPE: vtkErrorMacro("scalar of type VTK_ID_TYPE is not supported by this mapper."); goodSoFar = 0; break; case VTK_STRING: vtkErrorMacro("scalar of type VTK_STRING is not supported by this mapper."); goodSoFar = 0; break; default: // Don't need to do anything here break; } } // Check on the blending type - we support composite and min / max intensity if (goodSoFar) { if (this->BlendMode != vtkVolumeMapper::COMPOSITE_BLEND && this->BlendMode != vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND && this->BlendMode != vtkVolumeMapper::MINIMUM_INTENSITY_BLEND) { goodSoFar = 0; vtkErrorMacro(<< "Selected blend mode not supported. " << "Only Composite and MIP and MinIP modes " << "are supported by the current implementation."); } } // This mapper supports 1 component data, or 4 component if it is not independent // component (i.e. the four components define RGBA) int numberOfComponents = 0; if (goodSoFar) { numberOfComponents = scalars->GetNumberOfComponents(); if (!(numberOfComponents == 1 || (numberOfComponents == 4 && vol->GetProperty()->GetIndependentComponents() == 0))) { goodSoFar = 0; vtkErrorMacro(<< "Only one component scalars, or four " << "component with non-independent components, " << "are supported by this mapper."); } } // If this is four component data, then it better be unsigned char (RGBA). if (goodSoFar && numberOfComponents == 4 && scalars->GetDataType() != VTK_UNSIGNED_CHAR) { goodSoFar = 0; vtkErrorMacro("Only unsigned char is supported for 4-component scalars!"); } // return our status return goodSoFar; } // ---------------------------------------------------------------------------- // Description: // Called by the AMR Volume Mapper. // Set the flag that tells if the scalars are on point data (0) or // cell data (1). void vtkMitkGPUVolumeRayCastMapper::SetCellFlag(int cellFlag) { this->CellFlag = cellFlag; } // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::CreateCanonicalView(vtkRenderer *ren, vtkVolume *volume, vtkImageData *image, int vtkNotUsed(blend_mode), double viewDirection[3], double viewUp[3]) { this->GeneratingCanonicalView = 1; int oldSwap = ren->GetRenderWindow()->GetSwapBuffers(); ren->GetRenderWindow()->SwapBuffersOff(); int dim[3]; image->GetDimensions(dim); int *size = ren->GetRenderWindow()->GetSize(); vtkImageData *bigImage = vtkImageData::New(); bigImage->SetDimensions(size[0], size[1], 1); bigImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3); this->CanonicalViewImageData = bigImage; double scale[2]; scale[0] = dim[0] / static_cast(size[0]); scale[1] = dim[1] / static_cast(size[1]); // Save the visibility flags of the renderers and set all to false except // for the ren. vtkRendererCollection *renderers = ren->GetRenderWindow()->GetRenderers(); int numberOfRenderers = renderers->GetNumberOfItems(); auto rendererVisibilities = new bool[numberOfRenderers]; renderers->InitTraversal(); int i = 0; while (i < numberOfRenderers) { vtkRenderer *r = renderers->GetNextItem(); rendererVisibilities[i] = r->GetDraw() == 1; if (r != ren) { r->SetDraw(false); } ++i; } // Save the visibility flags of the props and set all to false except // for the volume. vtkPropCollection *props = ren->GetViewProps(); int numberOfProps = props->GetNumberOfItems(); auto propVisibilities = new bool[numberOfProps]; props->InitTraversal(); i = 0; while (i < numberOfProps) { vtkProp *p = props->GetNextProp(); propVisibilities[i] = p->GetVisibility() == 1; if (p != volume) { p->SetVisibility(false); } ++i; } vtkCamera *savedCamera = ren->GetActiveCamera(); savedCamera->Modified(); vtkCamera *canonicalViewCamera = vtkCamera::New(); // Code from vtkFixedPointVolumeRayCastMapper: double *center = volume->GetCenter(); double bounds[6]; volume->GetBounds(bounds); double d = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) + (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) + (bounds[5] - bounds[4]) * (bounds[5] - bounds[4])); // For now use x distance - need to change this d = bounds[1] - bounds[0]; // Set up the camera in parallel canonicalViewCamera->SetFocalPoint(center); canonicalViewCamera->ParallelProjectionOn(); canonicalViewCamera->SetPosition( center[0] - d * viewDirection[0], center[1] - d * viewDirection[1], center[2] - d * viewDirection[2]); canonicalViewCamera->SetViewUp(viewUp); canonicalViewCamera->SetParallelScale(d / 2); ren->SetActiveCamera(canonicalViewCamera); ren->GetRenderWindow()->Render(); ren->SetActiveCamera(savedCamera); canonicalViewCamera->Delete(); // Shrink to image to the desired size vtkImageResample *resample = vtkImageResample::New(); resample->SetInputData(bigImage); resample->SetAxisMagnificationFactor(0, scale[0]); resample->SetAxisMagnificationFactor(1, scale[1]); resample->SetAxisMagnificationFactor(2, 1); resample->UpdateWholeExtent(); // Copy the pixels over image->DeepCopy(resample->GetOutput()); bigImage->Delete(); resample->Delete(); // Restore the visibility flags of the props props->InitTraversal(); i = 0; while (i < numberOfProps) { vtkProp *p = props->GetNextProp(); p->SetVisibility(propVisibilities[i]); ++i; } delete[] propVisibilities; // Restore the visibility flags of the renderers renderers->InitTraversal(); i = 0; while (i < numberOfRenderers) { vtkRenderer *r = renderers->GetNextItem(); r->SetDraw(rendererVisibilities[i]); ++i; } delete[] rendererVisibilities; ren->GetRenderWindow()->SetSwapBuffers(oldSwap); this->CanonicalViewImageData = nullptr; this->GeneratingCanonicalView = 0; } // ---------------------------------------------------------------------------- // Print method for vtkMitkGPUVolumeRayCastMapper void vtkMitkGPUVolumeRayCastMapper::PrintSelf(ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "AutoAdjustSampleDistances: " << this->AutoAdjustSampleDistances << endl; os << indent << "MinimumImageSampleDistance: " << this->MinimumImageSampleDistance << endl; os << indent << "MaximumImageSampleDistance: " << this->MaximumImageSampleDistance << endl; os << indent << "ImageSampleDistance: " << this->ImageSampleDistance << endl; os << indent << "SampleDistance: " << this->SampleDistance << endl; os << indent << "FinalColorWindow: " << this->FinalColorWindow << endl; os << indent << "FinalColorLevel: " << this->FinalColorLevel << endl; os << indent << "MaskInput: " << this->MaskInput << endl; os << indent << "MaskBlendFactor: " << this->MaskBlendFactor << endl; os << indent << "MaxMemoryInBytes: " << this->MaxMemoryInBytes << endl; os << indent << "MaxMemoryFraction: " << this->MaxMemoryFraction << endl; os << indent << "ReportProgress: " << this->ReportProgress << endl; } // ---------------------------------------------------------------------------- // Description: // Compute the cropping planes clipped by the bounds of the volume. // The result is put into this->ClippedCroppingRegionPlanes. // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes // members instead of CroppingRegionPlanes. // \pre volume_exists: this->GetInput()!=0 // \pre valid_cropping: this->Cropping && // this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && // this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && // this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) void vtkMitkGPUVolumeRayCastMapper::ClipCroppingRegionPlanes() { assert("pre: volume_exists" && this->GetInput() != nullptr); assert("pre: valid_cropping" && this->Cropping && this->CroppingRegionPlanes[0] < this->CroppingRegionPlanes[1] && this->CroppingRegionPlanes[2] < this->CroppingRegionPlanes[3] && this->CroppingRegionPlanes[4] < this->CroppingRegionPlanes[5]); // vtkVolumeMapper::Render() will have something like: // if(this->Cropping && (this->CroppingRegionPlanes[0]>=this->CroppingRegionPlanes[1] || // this->CroppingRegionPlanes[2]>=this->CroppingRegionPlanes[3] || // this->CroppingRegionPlanes[4]>=this->CroppingRegionPlanes[5])) // { // // silentely stop because the cropping is not valid. // return; // } double volBounds[6]; this->GetInput()->GetBounds(volBounds); int i = 0; while (i < 6) { // max of the mins if (this->CroppingRegionPlanes[i] < volBounds[i]) { this->ClippedCroppingRegionPlanes[i] = volBounds[i]; } else { this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i]; } ++i; // min of the maxs if (this->CroppingRegionPlanes[i] > volBounds[i]) { this->ClippedCroppingRegionPlanes[i] = volBounds[i]; } else { this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i]; } ++i; } } - -#endif