diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp index cbeac65937..80b2912df2 100644 --- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp +++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp @@ -1,508 +1,508 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkExtractDirectedPlaneImageFilter.h" #include "mitkAbstractTransformGeometry.h" //#include "mitkImageMapperGL2D.h" #include #include #include #include #include "vtkMitkThickSlicesFilter.h" #include #include #include #include #include #include #include mitk::ExtractDirectedPlaneImageFilter::ExtractDirectedPlaneImageFilter() : m_WorldGeometry(NULL) { MITK_WARN << "Class ExtractDirectedPlaneImageFilter is deprecated! Use ExtractSliceFilter instead."; m_Reslicer = vtkImageReslice::New(); m_TargetTimestep = 0; m_InPlaneResampleExtentByGeometry = true; m_ResliceInterpolationProperty = NULL;//VtkResliceInterpolationProperty::New(); //TODO initial with value m_ThickSlicesMode = 0; m_ThickSlicesNum = 1; } mitk::ExtractDirectedPlaneImageFilter::~ExtractDirectedPlaneImageFilter() { if(m_ResliceInterpolationProperty!=NULL)m_ResliceInterpolationProperty->Delete(); m_Reslicer->Delete(); } void mitk::ExtractDirectedPlaneImageFilter::GenerateData() { // A world geometry must be set... if ( m_WorldGeometry == NULL ) { itkWarningMacro(<<"No world geometry has been set. Returning."); return; } Image *input = const_cast< ImageToImageFilter::InputImageType* >( this->GetInput() ); input->Update(); if ( input == NULL ) { itkWarningMacro(<<"No input set."); return; } const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); if ( ( inputTimeGeometry == NULL ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) ) { itkWarningMacro(<<"Error reading input image geometry."); return; } // Get the target timestep; if none is set, use the lowest given. unsigned int timestep = 0; if ( ! m_TargetTimestep ) { ScalarType time = m_WorldGeometry->GetTimeBounds()[0]; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) { timestep = inputTimeGeometry->TimePointToTimeStep( time ); } } else timestep = m_TargetTimestep; if ( inputTimeGeometry->IsValidTimeStep( timestep ) == false ) { itkWarningMacro(<<"This is not a valid timestep: "<IsVolumeSet( timestep ) ) { itkWarningMacro(<<"No volume data existent at given timestep "<GetLargestPossibleRegion(); requestedRegion.SetIndex( 3, timestep ); requestedRegion.SetSize( 3, 1 ); requestedRegion.SetSize( 4, 1 ); input->SetRequestedRegion( &requestedRegion ); input->Update(); vtkImageData* inputData = input->GetVtkImageData( timestep ); if ( inputData == NULL ) { itkWarningMacro(<<"Could not extract vtk image data for given timestep"<GetSpacing( spacing ); // how big the area is in physical coordinates: widthInMM x heightInMM pixels mitk::ScalarType widthInMM, heightInMM; // where we want to sample Point3D origin; Vector3D right, bottom, normal; Vector3D rightInIndex, bottomInIndex; assert( input->GetTimeGeometry() == inputTimeGeometry ); // take transform of input image into account Geometry3D* inputGeometry = inputTimeGeometry->GetGeometryForTimeStep( timestep ); if ( inputGeometry == NULL ) { itkWarningMacro(<<"There is no Geometry3D at given timestep "<( m_WorldGeometry ) != NULL ) { const PlaneGeometry *planeGeometry = static_cast< const PlaneGeometry * >( m_WorldGeometry ); origin = planeGeometry->GetOrigin(); right = planeGeometry->GetAxisVector( 0 ); bottom = planeGeometry->GetAxisVector( 1 ); normal = planeGeometry->GetNormal(); if ( m_InPlaneResampleExtentByGeometry ) { // Resampling grid corresponds to the current world geometry. This // means that the spacing of the output 2D image depends on the // currently selected world geometry, and *not* on the image itself. extent[0] = m_WorldGeometry->GetExtent( 0 ); extent[1] = m_WorldGeometry->GetExtent( 1 ); } else { // Resampling grid corresponds to the input geometry. This means that // the spacing of the output 2D image is directly derived from the // associated input image, regardless of the currently selected world // geometry. inputGeometry->WorldToIndex( right, rightInIndex ); inputGeometry->WorldToIndex( bottom, bottomInIndex ); extent[0] = rightInIndex.GetNorm(); extent[1] = bottomInIndex.GetNorm(); } // Get the extent of the current world geometry and calculate resampling // spacing therefrom. widthInMM = m_WorldGeometry->GetExtentInMM( 0 ); heightInMM = m_WorldGeometry->GetExtentInMM( 1 ); mmPerPixel[0] = widthInMM / extent[0]; mmPerPixel[1] = heightInMM / extent[1]; right.Normalize(); bottom.Normalize(); normal.Normalize(); //origin += right * ( mmPerPixel[0] * 0.5 ); //origin += bottom * ( mmPerPixel[1] * 0.5 ); //widthInMM -= mmPerPixel[0]; //heightInMM -= mmPerPixel[1]; // Use inverse transform of the input geometry for reslicing the 3D image m_Reslicer->SetResliceTransform( inputGeometry->GetVtkTransform()->GetLinearInverse() ); // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D) m_Reslicer->SetBackgroundLevel( -32768 ); // Check if a reference geometry does exist (as would usually be the case for // PlaneGeometry). // Note: this is currently not strictly required, but could facilitate // correct plane clipping. if ( m_WorldGeometry->GetReferenceGeometry() ) { // 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. boundsInitialized = this->CalculateClippedPlaneBounds( m_WorldGeometry->GetReferenceGeometry(), planeGeometry, bounds ); } } // Do we have an AbstractTransformGeometry? else if ( dynamic_cast< const AbstractTransformGeometry * >( m_WorldGeometry ) ) { const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry); extent[0] = abstractGeometry->GetParametricExtent(0); extent[1] = abstractGeometry->GetParametricExtent(1); widthInMM = abstractGeometry->GetParametricExtentInMM(0); heightInMM = abstractGeometry->GetParametricExtentInMM(1); mmPerPixel[0] = widthInMM / extent[0]; mmPerPixel[1] = heightInMM / extent[1]; origin = abstractGeometry->GetPlane()->GetOrigin(); right = abstractGeometry->GetPlane()->GetAxisVector(0); right.Normalize(); bottom = abstractGeometry->GetPlane()->GetAxisVector(1); bottom.Normalize(); normal = abstractGeometry->GetPlane()->GetNormal(); normal.Normalize(); // Use a combination of the InputGeometry *and* the possible non-rigid // AbstractTransformGeometry for reslicing the 3D Image vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); composedResliceTransform->Identity(); composedResliceTransform->Concatenate( inputGeometry->GetVtkTransform()->GetLinearInverse() ); composedResliceTransform->Concatenate( abstractGeometry->GetVtkAbstractTransform() ); m_Reslicer->SetResliceTransform( composedResliceTransform ); // Set background level to BLACK instead of translucent, to avoid // boundary artifacts (see Geometry2DDataVtkMapper3D) m_Reslicer->SetBackgroundLevel( -1023 ); composedResliceTransform->Delete(); } else { itkWarningMacro(<<"World Geometry has to be a PlaneGeometry or an AbstractTransformGeometry."); return; } // Make sure that the image to be resliced has a certain minimum size. if ( (extent[0] <= 2) && (extent[1] <= 2) ) { itkWarningMacro(<<"Image is too small to be resliced..."); return; } vtkImageChangeInformation * unitSpacingImageFilter = vtkImageChangeInformation::New() ; unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); - unitSpacingImageFilter->SetInput( inputData ); + unitSpacingImageFilter->SetInputData( inputData ); - m_Reslicer->SetInput( unitSpacingImageFilter->GetOutput() ); + m_Reslicer->SetInputData( unitSpacingImageFilter->GetOutput() ); unitSpacingImageFilter->Delete(); //m_Reslicer->SetInput( inputData ); m_Reslicer->SetOutputDimensionality( 2 ); m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); Vector2D pixelsPerMM; pixelsPerMM[0] = 1.0 / mmPerPixel[0]; pixelsPerMM[1] = 1.0 / mmPerPixel[1]; //calulate the originArray and the orientations for the reslice-filter double originArray[3]; itk2vtk( origin, originArray ); m_Reslicer->SetResliceAxesOrigin( originArray ); double cosines[9]; // direction of the X-axis of the sampled result vnl2vtk( right.GetVnlVector(), cosines ); // direction of the Y-axis of the sampled result vnl2vtk( bottom.GetVnlVector(), cosines + 3 ); // normal of the plane vnl2vtk( normal.GetVnlVector(), cosines + 6 ); m_Reslicer->SetResliceAxesDirectionCosines( cosines ); int xMin, xMax, yMin, yMax; if ( boundsInitialized ) { xMin = static_cast< int >( bounds[0] / mmPerPixel[0] );//+ 0.5 ); xMax = static_cast< int >( bounds[1] / mmPerPixel[0] );//+ 0.5 ); yMin = static_cast< int >( bounds[2] / mmPerPixel[1] );//+ 0.5); yMax = static_cast< int >( bounds[3] / mmPerPixel[1] );//+ 0.5 ); } else { // If no reference geometry is available, we also don't know about the // maximum plane size; so the overlap is just ignored xMin = yMin = 0; xMax = static_cast< int >( extent[0] - pixelsPerMM[0] );//+ 0.5 ); yMax = static_cast< int >( extent[1] - pixelsPerMM[1] );//+ 0.5 ); } m_Reslicer->SetOutputSpacing( mmPerPixel[0], mmPerPixel[1], 1.0 ); // xMax and yMax are meant exclusive until now, whereas // SetOutputExtent wants an inclusive bound. Thus, we need // to subtract 1. m_Reslicer->SetOutputExtent( xMin, xMax-1, yMin, yMax-1, 0, 1 ); // 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. m_Reslicer->Modified(); m_Reslicer->ReleaseDataFlagOn(); m_Reslicer->Update(); // 1. Check the result vtkImageData* reslicedImage = m_Reslicer->GetOutput(); //mitkIpPicDescriptor *pic = Pic2vtk::convert( reslicedImage ); if((reslicedImage == NULL) || (reslicedImage->GetDataDimension() < 1)) { itkWarningMacro(<<"Reslicer returned empty image"); return; } unsigned int dimensions[2]; dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; Vector3D spacingVector; FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); mitk::Image::Pointer resultImage = this->GetOutput(); resultImage->Initialize(input->GetPixelType(), 2, dimensions ); //resultImage->Initialize( pic ); resultImage->SetSpacing( spacingVector ); //resultImage->SetPicVolume( pic ); //mitkIpPicFree(pic); /*unsigned int dimensions[2]; dimensions[0] = (unsigned int)extent[0]; dimensions[1] = (unsigned int)extent[1]; Vector3D spacingVector; FillVector3D(spacingVector, mmPerPixel[0], mmPerPixel[1], 1.0); mitk::Image::Pointer resultImage = this->GetOutput(); resultImage->Initialize(m_Reslicer->GetOutput()); resultImage->Initialize(inputImage->GetPixelType(), 2, dimensions); resultImage->SetSpacing(spacingVector); resultImage->SetSlice(m_Reslicer->GetOutput());*/ } void mitk::ExtractDirectedPlaneImageFilter::GenerateOutputInformation() { Superclass::GenerateOutputInformation(); } bool mitk::ExtractDirectedPlaneImageFilter ::CalculateClippedPlaneBounds( const Geometry3D *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 BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); BoundingBox::PointType bbMin = boundingBox->GetMinimum(); BoundingBox::PointType bbMax = boundingBox->GetMaximum(); vtkPoints *points = vtkPoints::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] ); } vtkPoints *newPoints = vtkPoints::New(); vtkTransform *transform = vtkTransform::New(); transform->Identity(); transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); transform->Concatenate( boundingGeometry->GetVtkTransform() ); transform->TransformPoints( points, newPoints ); transform->Delete(); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; this->LineIntersectZero( newPoints, 0, 1, bounds ); this->LineIntersectZero( newPoints, 1, 2, bounds ); this->LineIntersectZero( newPoints, 2, 3, bounds ); this->LineIntersectZero( newPoints, 3, 0, bounds ); this->LineIntersectZero( newPoints, 0, 4, bounds ); this->LineIntersectZero( newPoints, 1, 5, bounds ); this->LineIntersectZero( newPoints, 2, 6, bounds ); this->LineIntersectZero( newPoints, 3, 7, bounds ); this->LineIntersectZero( newPoints, 4, 5, bounds ); this->LineIntersectZero( newPoints, 5, 6, bounds ); this->LineIntersectZero( newPoints, 6, 7, bounds ); this->LineIntersectZero( newPoints, 7, 4, bounds ); // clean up vtk data points->Delete(); newPoints->Delete(); 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 float *planeSpacing = planeGeometry->GetFloatSpacing(); 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; } } bool mitk::ExtractDirectedPlaneImageFilter ::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; } diff --git a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp index 702ebb3677..ae6b4fe5de 100644 --- a/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp +++ b/Modules/ImageStatistics/mitkImageStatisticsCalculator.cpp @@ -1,1218 +1,1218 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageStatisticsCalculator.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkExtractImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if ( ( VTK_MAJOR_VERSION <= 5 ) && ( VTK_MINOR_VERSION<=8) ) #include "mitkvtkLassoStencilSource.h" #else #include "vtkLassoStencilSource.h" #endif #include #include namespace mitk { ImageStatisticsCalculator::ImageStatisticsCalculator() : m_MaskingMode( MASKING_MODE_NONE ), m_MaskingModeChanged( false ), m_IgnorePixelValue(0.0), m_DoIgnorePixelValue(false), m_IgnorePixelValueChanged(false), m_PlanarFigureAxis (0), m_PlanarFigureSlice (0), m_PlanarFigureCoordinate0 (0), m_PlanarFigureCoordinate1 (0) { m_EmptyHistogram = HistogramType::New(); m_EmptyHistogram->SetMeasurementVectorSize(1); HistogramType::SizeType histogramSize(1); histogramSize.Fill( 256 ); m_EmptyHistogram->Initialize( histogramSize ); m_EmptyStatistics.Reset(); } ImageStatisticsCalculator::~ImageStatisticsCalculator() { } void ImageStatisticsCalculator::SetImage( const mitk::Image *image ) { if ( m_Image != image ) { m_Image = image; this->Modified(); unsigned int numberOfTimeSteps = image->GetTimeSteps(); // Initialize vectors to time-size of this image m_ImageHistogramVector.resize( numberOfTimeSteps ); m_MaskedImageHistogramVector.resize( numberOfTimeSteps ); m_PlanarFigureHistogramVector.resize( numberOfTimeSteps ); m_ImageStatisticsVector.resize( numberOfTimeSteps ); m_MaskedImageStatisticsVector.resize( numberOfTimeSteps ); m_PlanarFigureStatisticsVector.resize( numberOfTimeSteps ); m_ImageStatisticsTimeStampVector.resize( numberOfTimeSteps ); m_MaskedImageStatisticsTimeStampVector.resize( numberOfTimeSteps ); m_PlanarFigureStatisticsTimeStampVector.resize( numberOfTimeSteps ); m_ImageStatisticsCalculationTriggerVector.resize( numberOfTimeSteps ); m_MaskedImageStatisticsCalculationTriggerVector.resize( numberOfTimeSteps ); m_PlanarFigureStatisticsCalculationTriggerVector.resize( numberOfTimeSteps ); for ( unsigned int t = 0; t < image->GetTimeSteps(); ++t ) { m_ImageStatisticsTimeStampVector[t].Modified(); m_ImageStatisticsCalculationTriggerVector[t] = true; } } } void ImageStatisticsCalculator::SetImageMask( const mitk::Image *imageMask ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() ) { itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" ); } if ( m_ImageMask != imageMask ) { m_ImageMask = imageMask; this->Modified(); for ( unsigned int t = 0; t < m_Image->GetTimeSteps(); ++t ) { m_MaskedImageStatisticsTimeStampVector[t].Modified(); m_MaskedImageStatisticsCalculationTriggerVector[t] = true; } } } void ImageStatisticsCalculator::SetPlanarFigure( mitk::PlanarFigure *planarFigure ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_PlanarFigure != planarFigure ) { m_PlanarFigure = planarFigure; this->Modified(); for ( unsigned int t = 0; t < m_Image->GetTimeSteps(); ++t ) { m_PlanarFigureStatisticsTimeStampVector[t].Modified(); m_PlanarFigureStatisticsCalculationTriggerVector[t] = true; } } } void ImageStatisticsCalculator::SetMaskingMode( unsigned int mode ) { if ( m_MaskingMode != mode ) { m_MaskingMode = mode; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetMaskingModeToNone() { if ( m_MaskingMode != MASKING_MODE_NONE ) { m_MaskingMode = MASKING_MODE_NONE; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetMaskingModeToImage() { if ( m_MaskingMode != MASKING_MODE_IMAGE ) { m_MaskingMode = MASKING_MODE_IMAGE; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetMaskingModeToPlanarFigure() { if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE ) { m_MaskingMode = MASKING_MODE_PLANARFIGURE; m_MaskingModeChanged = true; this->Modified(); } } void ImageStatisticsCalculator::SetIgnorePixelValue(double value) { if ( m_IgnorePixelValue != value ) { m_IgnorePixelValue = value; if(m_DoIgnorePixelValue) { m_IgnorePixelValueChanged = true; } this->Modified(); } } double ImageStatisticsCalculator::GetIgnorePixelValue() { return m_IgnorePixelValue; } void ImageStatisticsCalculator::SetDoIgnorePixelValue(bool value) { if ( m_DoIgnorePixelValue != value ) { m_DoIgnorePixelValue = value; m_IgnorePixelValueChanged = true; this->Modified(); } } bool ImageStatisticsCalculator::GetDoIgnorePixelValue() { return m_DoIgnorePixelValue; } bool ImageStatisticsCalculator::ComputeStatistics( unsigned int timeStep ) { if (m_Image.IsNull() ) { mitkThrow() << "Image not set!"; } if (!m_Image->IsInitialized()) { mitkThrow() << "Image not initialized!"; } if ( m_Image->GetReferenceCount() == 1 ) { // Image no longer valid; we are the only ones to still hold a reference on it return false; } if ( timeStep >= m_Image->GetTimeSteps() ) { throw std::runtime_error( "Error: invalid time step!" ); } // If a mask was set but we are the only ones to still hold a reference on // it, delete it. if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) ) { m_ImageMask = NULL; } // Check if statistics is already up-to-date unsigned long imageMTime = m_ImageStatisticsTimeStampVector[timeStep].GetMTime(); unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStampVector[timeStep].GetMTime(); unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStampVector[timeStep].GetMTime(); bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerVector[timeStep]; bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerVector[timeStep]; bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerVector[timeStep]; if ( !m_IgnorePixelValueChanged && ((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_IMAGE) || (maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) { // Statistics is up to date! if ( m_MaskingModeChanged ) { m_MaskingModeChanged = false; return true; } else { return false; } } // Reset state changed flag m_MaskingModeChanged = false; m_IgnorePixelValueChanged = false; // Depending on masking mode, extract and/or generate the required image // and mask data from the user input this->ExtractImageAndMask( timeStep ); StatisticsContainer *statisticsContainer; HistogramContainer *histogramContainer; switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: if(!m_DoIgnorePixelValue) { statisticsContainer = &m_ImageStatisticsVector[timeStep]; histogramContainer = &m_ImageHistogramVector[timeStep]; m_ImageStatisticsTimeStampVector[timeStep].Modified(); m_ImageStatisticsCalculationTriggerVector[timeStep] = false; } else { statisticsContainer = &m_MaskedImageStatisticsVector[timeStep]; histogramContainer = &m_MaskedImageHistogramVector[timeStep]; m_MaskedImageStatisticsTimeStampVector[timeStep].Modified(); m_MaskedImageStatisticsCalculationTriggerVector[timeStep] = false; } break; case MASKING_MODE_IMAGE: statisticsContainer = &m_MaskedImageStatisticsVector[timeStep]; histogramContainer = &m_MaskedImageHistogramVector[timeStep]; m_MaskedImageStatisticsTimeStampVector[timeStep].Modified(); m_MaskedImageStatisticsCalculationTriggerVector[timeStep] = false; break; case MASKING_MODE_PLANARFIGURE: statisticsContainer = &m_PlanarFigureStatisticsVector[timeStep]; histogramContainer = &m_PlanarFigureHistogramVector[timeStep]; m_PlanarFigureStatisticsTimeStampVector[timeStep].Modified(); m_PlanarFigureStatisticsCalculationTriggerVector[timeStep] = false; break; } // Calculate statistics and histogram(s) if ( m_InternalImage->GetDimension() == 3 ) { if ( m_MaskingMode == MASKING_MODE_NONE && !m_DoIgnorePixelValue ) { AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 3, statisticsContainer, histogramContainer ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 3, m_InternalImageMask3D.GetPointer(), statisticsContainer, histogramContainer ); } } else if ( m_InternalImage->GetDimension() == 2 ) { if ( m_MaskingMode == MASKING_MODE_NONE && !m_DoIgnorePixelValue ) { AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 2, statisticsContainer, histogramContainer ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 2, m_InternalImageMask2D.GetPointer(), statisticsContainer, histogramContainer ); } } else { MITK_ERROR << "ImageStatistics: Image dimension not supported!"; } // Release unused image smart pointers to free memory m_InternalImage = mitk::Image::ConstPointer(); m_InternalImageMask3D = MaskImage3DType::Pointer(); m_InternalImageMask2D = MaskImage2DType::Pointer(); return true; } const ImageStatisticsCalculator::HistogramType * ImageStatisticsCalculator::GetHistogram( unsigned int timeStep, unsigned int label ) const { if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) ) { return NULL; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(m_DoIgnorePixelValue) return m_MaskedImageHistogramVector[timeStep][label]; return m_ImageHistogramVector[timeStep][label]; } case MASKING_MODE_IMAGE: return m_MaskedImageHistogramVector[timeStep][label]; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureHistogramVector[timeStep][label]; } } const ImageStatisticsCalculator::HistogramContainer & ImageStatisticsCalculator::GetHistogramVector( unsigned int timeStep ) const { if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) ) { return m_EmptyHistogramContainer; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(m_DoIgnorePixelValue) return m_MaskedImageHistogramVector[timeStep]; return m_ImageHistogramVector[timeStep]; } case MASKING_MODE_IMAGE: return m_MaskedImageHistogramVector[timeStep]; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureHistogramVector[timeStep]; } } const ImageStatisticsCalculator::Statistics & ImageStatisticsCalculator::GetStatistics( unsigned int timeStep, unsigned int label ) const { if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) ) { return m_EmptyStatistics; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(m_DoIgnorePixelValue) return m_MaskedImageStatisticsVector[timeStep][label]; return m_ImageStatisticsVector[timeStep][label]; } case MASKING_MODE_IMAGE: return m_MaskedImageStatisticsVector[timeStep][label]; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureStatisticsVector[timeStep][label]; } } const ImageStatisticsCalculator::StatisticsContainer & ImageStatisticsCalculator::GetStatisticsVector( unsigned int timeStep ) const { if ( m_Image.IsNull() || (timeStep >= m_Image->GetTimeSteps()) ) { return m_EmptyStatisticsContainer; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: { if(m_DoIgnorePixelValue) return m_MaskedImageStatisticsVector[timeStep]; return m_ImageStatisticsVector[timeStep]; } case MASKING_MODE_IMAGE: return m_MaskedImageStatisticsVector[timeStep]; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureStatisticsVector[timeStep]; } } void ImageStatisticsCalculator::ExtractImageAndMask( unsigned int timeStep ) { if ( m_Image.IsNull() ) { throw std::runtime_error( "Error: image empty!" ); } if ( timeStep >= m_Image->GetTimeSteps() ) { throw std::runtime_error( "Error: invalid time step!" ); } ImageTimeSelector::Pointer imageTimeSelector = ImageTimeSelector::New(); imageTimeSelector->SetInput( m_Image ); imageTimeSelector->SetTimeNr( timeStep ); imageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image *timeSliceImage = imageTimeSelector->GetOutput(); switch ( m_MaskingMode ) { case MASKING_MODE_NONE: { m_InternalImage = timeSliceImage; m_InternalImageMask2D = NULL; m_InternalImageMask3D = NULL; if(m_DoIgnorePixelValue) { if( m_InternalImage->GetDimension() == 3 ) { CastToItkImage( timeSliceImage, m_InternalImageMask3D ); m_InternalImageMask3D->FillBuffer(1); } if( m_InternalImage->GetDimension() == 2 ) { CastToItkImage( timeSliceImage, m_InternalImageMask2D ); m_InternalImageMask2D->FillBuffer(1); } } break; } case MASKING_MODE_IMAGE: { if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) ) { if ( timeStep < m_ImageMask->GetTimeSteps() ) { ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New(); maskedImageTimeSelector->SetInput( m_ImageMask ); maskedImageTimeSelector->SetTimeNr( timeStep ); maskedImageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput(); m_InternalImage = timeSliceImage; CastToItkImage( timeSliceMaskedImage, m_InternalImageMask3D ); } else { throw std::runtime_error( "Error: image mask has not enough time steps!" ); } } else { throw std::runtime_error( "Error: image mask empty!" ); } break; } case MASKING_MODE_PLANARFIGURE: { m_InternalImageMask2D = NULL; if ( m_PlanarFigure.IsNull() ) { throw std::runtime_error( "Error: planar figure empty!" ); } if ( !m_PlanarFigure->IsClosed() ) { throw std::runtime_error( "Masking not possible for non-closed figures" ); } const Geometry3D *imageGeometry = timeSliceImage->GetGeometry(); if ( imageGeometry == NULL ) { throw std::runtime_error( "Image geometry invalid!" ); } const Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); if ( planarFigureGeometry2D == NULL ) { throw std::runtime_error( "Planar-Figure not yet initialized!" ); } const PlaneGeometry *planarFigureGeometry = dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D ); if ( planarFigureGeometry == NULL ) { throw std::runtime_error( "Non-planar planar figures not supported!" ); } // Find principal direction of PlanarFigure in input image unsigned int axis; if ( !this->GetPrincipalAxis( imageGeometry, planarFigureGeometry->GetNormal(), axis ) ) { throw std::runtime_error( "Non-aligned planar figures not supported!" ); } m_PlanarFigureAxis = axis; // Find slice number corresponding to PlanarFigure in input image MaskImage3DType::IndexType index; imageGeometry->WorldToIndex( planarFigureGeometry->GetOrigin(), index ); unsigned int slice = index[axis]; m_PlanarFigureSlice = slice; // Extract slice with given position and direction from image ExtractImageFilter::Pointer imageExtractor = ExtractImageFilter::New(); imageExtractor->SetInput( timeSliceImage ); imageExtractor->SetSliceDimension( axis ); imageExtractor->SetSliceIndex( slice ); imageExtractor->Update(); m_InternalImage = imageExtractor->GetOutput(); // Compute mask from PlanarFigure AccessFixedDimensionByItk_1( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 2, axis ); } } if(m_DoIgnorePixelValue) { if ( m_InternalImage->GetDimension() == 3 ) { AccessFixedDimensionByItk_1( m_InternalImage, InternalMaskIgnoredPixels, 3, m_InternalImageMask3D.GetPointer() ); } else if ( m_InternalImage->GetDimension() == 2 ) { AccessFixedDimensionByItk_1( m_InternalImage, InternalMaskIgnoredPixels, 2, m_InternalImageMask2D.GetPointer() ); } } } bool ImageStatisticsCalculator::GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector, unsigned int &axis ) { vector.Normalize(); for ( unsigned int i = 0; i < 3; ++i ) { Vector3D axisVector = geometry->GetAxisVector( i ); axisVector.Normalize(); if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps ) { axis = i; return true; } } return false; } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalCalculateStatisticsUnmasked( const itk::Image< TPixel, VImageDimension > *image, StatisticsContainer *statisticsContainer, HistogramContainer* histogramContainer ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned short, VImageDimension > MaskImageType; typedef typename ImageType::IndexType IndexType; typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType > HistogramGeneratorType; statisticsContainer->clear(); histogramContainer->clear(); // Progress listening... typedef itk::SimpleMemberCommand< ImageStatisticsCalculator > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &ImageStatisticsCalculator::UnmaskedStatisticsProgressUpdate ); // Issue 100 artificial progress events since ScalarIMageToHistogramGenerator // does not (yet?) support progress reporting this->InvokeEvent( itk::StartEvent() ); for ( unsigned int i = 0; i < 100; ++i ) { this->UnmaskedStatisticsProgressUpdate(); } // Calculate statistics (separate filter) typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType; typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New(); statisticsFilter->SetInput( image ); unsigned long observerTag = statisticsFilter->AddObserver( itk::ProgressEvent(), progressListener ); statisticsFilter->Update(); statisticsFilter->RemoveObserver( observerTag ); this->InvokeEvent( itk::EndEvent() ); // Calculate minimum and maximum typedef itk::MinimumMaximumImageCalculator< ImageType > MinMaxFilterType; typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New(); minMaxFilter->SetImage( image ); unsigned long observerTag2 = minMaxFilter->AddObserver( itk::ProgressEvent(), progressListener ); minMaxFilter->Compute(); minMaxFilter->RemoveObserver( observerTag2 ); this->InvokeEvent( itk::EndEvent() ); Statistics statistics; statistics.Reset(); statistics.Label = 1; statistics.N = image->GetBufferedRegion().GetNumberOfPixels(); statistics.Min = statisticsFilter->GetMinimum(); statistics.Max = statisticsFilter->GetMaximum(); statistics.Mean = statisticsFilter->GetMean(); statistics.Median = 0.0; statistics.Sigma = statisticsFilter->GetSigma(); statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma ); statistics.MinIndex.set_size(image->GetImageDimension()); statistics.MaxIndex.set_size(image->GetImageDimension()); for (int i=0; iGetIndexOfMaximum()[i]; statistics.MinIndex[i] = minMaxFilter->GetIndexOfMinimum()[i]; } statisticsContainer->push_back( statistics ); // Calculate histogram typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New(); histogramGenerator->SetInput( image ); histogramGenerator->SetMarginalScale( 100 ); histogramGenerator->SetNumberOfBins( 768 ); histogramGenerator->SetHistogramMin( statistics.Min ); histogramGenerator->SetHistogramMax( statistics.Max ); histogramGenerator->Compute(); histogramContainer->push_back( histogramGenerator->GetOutput() ); } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalMaskIgnoredPixels( const itk::Image< TPixel, VImageDimension > *image, itk::Image< unsigned short, VImageDimension > *maskImage ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned short, VImageDimension > MaskImageType; itk::ImageRegionIterator itmask(maskImage, maskImage->GetLargestPossibleRegion()); itk::ImageRegionConstIterator itimage(image, image->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); while( !itmask.IsAtEnd() ) { if(m_IgnorePixelValue == itimage.Get()) { itmask.Set(0); } ++itmask; ++itimage; } } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalCalculateStatisticsMasked( const itk::Image< TPixel, VImageDimension > *image, itk::Image< unsigned short, VImageDimension > *maskImage, StatisticsContainer* statisticsContainer, HistogramContainer* histogramContainer ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned short, VImageDimension > MaskImageType; typedef typename ImageType::IndexType IndexType; typedef typename ImageType::PointType PointType; typedef typename ImageType::SpacingType SpacingType; typedef itk::LabelStatisticsImageFilter< ImageType, MaskImageType > LabelStatisticsFilterType; typedef itk::ChangeInformationImageFilter< MaskImageType > ChangeInformationFilterType; typedef itk::ExtractImageFilter< ImageType, ImageType > ExtractImageFilterType; statisticsContainer->clear(); histogramContainer->clear(); // Make sure that mask is set if ( maskImage == NULL ) { itkExceptionMacro( << "Mask image needs to be set!" ); } // Make sure that spacing of mask and image are the same SpacingType imageSpacing = image->GetSpacing(); SpacingType maskSpacing = maskImage->GetSpacing(); PointType zeroPoint; zeroPoint.Fill( 0.0 ); if ( (zeroPoint + imageSpacing).SquaredEuclideanDistanceTo( (zeroPoint + maskSpacing) ) > mitk::eps ) { itkExceptionMacro( << "Mask needs to have same spacing as image! (Image spacing: " << imageSpacing << "; Mask spacing: " << maskSpacing << ")" ); } // Make sure that orientation of mask and image are the same typedef typename ImageType::DirectionType DirectionType; DirectionType imageDirection = image->GetDirection(); DirectionType maskDirection = maskImage->GetDirection(); for( int i = 0; i < imageDirection.ColumnDimensions; ++i ) { for( int j = 0; j < imageDirection.ColumnDimensions; ++j ) { double differenceDirection = imageDirection[i][j] - maskDirection[i][j]; if ( fabs( differenceDirection ) > mitk::eps ) { itkExceptionMacro( << "Mask needs to have same direction as image! (Image direction: " << imageDirection << "; Mask direction: " << maskDirection << ")" ); } } } // Make sure that the voxels of mask and image are correctly "aligned", i.e., voxel boundaries are the same in both images PointType imageOrigin = image->GetOrigin(); PointType maskOrigin = maskImage->GetOrigin(); long offset[ImageType::ImageDimension]; typedef itk::ContinuousIndex ContinousIndexType; ContinousIndexType maskOriginContinousIndex, imageOriginContinousIndex; image->TransformPhysicalPointToContinuousIndex(maskOrigin, maskOriginContinousIndex); image->TransformPhysicalPointToContinuousIndex(imageOrigin, imageOriginContinousIndex); for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i ) { double misalignment = maskOriginContinousIndex[i] - floor( maskOriginContinousIndex[i] + 0.5 ); if ( fabs( misalignment ) > mitk::eps ) { itkExceptionMacro( << "Pixels/voxels of mask and image are not sufficiently aligned! (Misalignment: " << misalignment << ")" ); } double indexCoordDistance = maskOriginContinousIndex[i] - imageOriginContinousIndex[i]; offset[i] = (int) indexCoordDistance + image->GetBufferedRegion().GetIndex()[i]; } // Adapt the origin and region (index/size) of the mask so that the origin of both are the same typename ChangeInformationFilterType::Pointer adaptMaskFilter; adaptMaskFilter = ChangeInformationFilterType::New(); adaptMaskFilter->ChangeOriginOn(); adaptMaskFilter->ChangeRegionOn(); adaptMaskFilter->SetInput( maskImage ); adaptMaskFilter->SetOutputOrigin( image->GetOrigin() ); adaptMaskFilter->SetOutputOffset( offset ); adaptMaskFilter->Update(); typename MaskImageType::Pointer adaptedMaskImage = adaptMaskFilter->GetOutput(); // Make sure that mask region is contained within image region if ( !image->GetLargestPossibleRegion().IsInside( adaptedMaskImage->GetLargestPossibleRegion() ) ) { itkExceptionMacro( << "Mask region needs to be inside of image region! (Image region: " << image->GetLargestPossibleRegion() << "; Mask region: " << adaptedMaskImage->GetLargestPossibleRegion() << ")" ); } // If mask region is smaller than image region, extract the sub-sampled region from the original image typename ImageType::SizeType imageSize = image->GetBufferedRegion().GetSize(); typename ImageType::SizeType maskSize = maskImage->GetBufferedRegion().GetSize(); bool maskSmallerImage = false; for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i ) { if ( maskSize[i] < imageSize[i] ) { maskSmallerImage = true; } } typename ImageType::ConstPointer adaptedImage; if ( maskSmallerImage ) { typename ExtractImageFilterType::Pointer extractImageFilter = ExtractImageFilterType::New(); extractImageFilter->SetInput( image ); extractImageFilter->SetExtractionRegion( adaptedMaskImage->GetBufferedRegion() ); extractImageFilter->Update(); adaptedImage = extractImageFilter->GetOutput(); } else { adaptedImage = image; } // Initialize Filter typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType; typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New(); statisticsFilter->SetInput( adaptedImage ); statisticsFilter->Update(); int numberOfBins = ( m_DoIgnorePixelValue && (m_MaskingMode == MASKING_MODE_NONE) ) ? 768 : 384; typename LabelStatisticsFilterType::Pointer labelStatisticsFilter; labelStatisticsFilter = LabelStatisticsFilterType::New(); labelStatisticsFilter->SetInput( adaptedImage ); labelStatisticsFilter->SetLabelInput( adaptedMaskImage ); labelStatisticsFilter->UseHistogramsOn(); labelStatisticsFilter->SetHistogramParameters( numberOfBins, statisticsFilter->GetMinimum(), statisticsFilter->GetMaximum() ); // Add progress listening typedef itk::SimpleMemberCommand< ImageStatisticsCalculator > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &ImageStatisticsCalculator::MaskedStatisticsProgressUpdate ); unsigned long observerTag = labelStatisticsFilter->AddObserver( itk::ProgressEvent(), progressListener ); // Execute filter this->InvokeEvent( itk::StartEvent() ); // Make sure that only the mask region is considered (otherwise, if the mask region is smaller // than the image region, the Update() would result in an exception). labelStatisticsFilter->GetOutput()->SetRequestedRegion( adaptedMaskImage->GetLargestPossibleRegion() ); // Execute the filter labelStatisticsFilter->Update(); this->InvokeEvent( itk::EndEvent() ); labelStatisticsFilter->RemoveObserver( observerTag ); // Find all relevant labels of mask (other than 0) std::list< int > relevantLabels; bool maskNonEmpty = false; unsigned int i; for ( i = 1; i < 4096; ++i ) { if ( labelStatisticsFilter->HasLabel( i ) ) { relevantLabels.push_back( i ); maskNonEmpty = true; } } if ( maskNonEmpty ) { std::list< int >::iterator it; for ( it = relevantLabels.begin(), i = 0; it != relevantLabels.end(); ++it, ++i ) { histogramContainer->push_back( HistogramType::ConstPointer( labelStatisticsFilter->GetHistogram( (*it) ) ) ); Statistics statistics; statistics.Label = (*it); statistics.N = labelStatisticsFilter->GetCount( *it ); statistics.Min = labelStatisticsFilter->GetMinimum( *it ); statistics.Max = labelStatisticsFilter->GetMaximum( *it ); statistics.Mean = labelStatisticsFilter->GetMean( *it ); statistics.Median = labelStatisticsFilter->GetMedian( *it ); statistics.Sigma = labelStatisticsFilter->GetSigma( *it ); statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma ); // restrict image to mask area for min/max index calculation typedef itk::MaskImageFilter< ImageType, MaskImageType, ImageType > MaskImageFilterType; typename MaskImageFilterType::Pointer masker = MaskImageFilterType::New(); masker->SetOutsideValue( (statistics.Min+statistics.Max)/2 ); masker->SetInput1(adaptedImage); masker->SetInput2(adaptedMaskImage); masker->Update(); // get index of minimum and maximum typedef itk::MinimumMaximumImageCalculator< ImageType > MinMaxFilterType; typename MinMaxFilterType::Pointer minMaxFilter = MinMaxFilterType::New(); minMaxFilter->SetImage( masker->GetOutput() ); unsigned long observerTag2 = minMaxFilter->AddObserver( itk::ProgressEvent(), progressListener ); minMaxFilter->Compute(); minMaxFilter->RemoveObserver( observerTag2 ); this->InvokeEvent( itk::EndEvent() ); statistics.MinIndex.set_size(adaptedImage->GetImageDimension()); statistics.MaxIndex.set_size(adaptedImage->GetImageDimension()); typename MinMaxFilterType::IndexType tempMaxIndex = minMaxFilter->GetIndexOfMaximum(); typename MinMaxFilterType::IndexType tempMinIndex = minMaxFilter->GetIndexOfMinimum(); // FIX BUG 14644 //If a PlanarFigure is used for segmentation the //adaptedImage is a single slice (2D). Adding the // 3. dimension. if (m_MaskingMode == MASKING_MODE_PLANARFIGURE && m_Image->GetDimension()==3) { statistics.MaxIndex.set_size(m_Image->GetDimension()); statistics.MaxIndex[m_PlanarFigureCoordinate0]=tempMaxIndex[0]; statistics.MaxIndex[m_PlanarFigureCoordinate1]=tempMaxIndex[1]; statistics.MaxIndex[m_PlanarFigureAxis]=m_PlanarFigureSlice; statistics.MinIndex.set_size(m_Image->GetDimension()); statistics.MinIndex[m_PlanarFigureCoordinate0]=tempMinIndex[0]; statistics.MinIndex[m_PlanarFigureCoordinate1]=tempMinIndex[1]; statistics.MinIndex[m_PlanarFigureAxis]=m_PlanarFigureSlice; } else { for (int i = 0; ipush_back( statistics ); } } else { histogramContainer->push_back( HistogramType::ConstPointer( m_EmptyHistogram ) ); statisticsContainer->push_back( Statistics() );; } } template < typename TPixel, unsigned int VImageDimension > void ImageStatisticsCalculator::InternalCalculateMaskFromPlanarFigure( const itk::Image< TPixel, VImageDimension > *image, unsigned int axis ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::CastImageFilter< ImageType, MaskImage2DType > CastFilterType; // Generate mask image as new image with same header as input image and // initialize with "1". typename CastFilterType::Pointer castFilter = CastFilterType::New(); castFilter->SetInput( image ); castFilter->Update(); castFilter->GetOutput()->FillBuffer( 1 ); // all PolylinePoints of the PlanarFigure are stored in a vtkPoints object. // These points are used by the vtkLassoStencilSource to create // a vtkImageStencil. const mitk::Geometry2D *planarFigureGeometry2D = m_PlanarFigure->GetGeometry2D(); const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const mitk::Geometry3D *imageGeometry3D = m_Image->GetGeometry( 0 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } m_PlanarFigureCoordinate0= i0; m_PlanarFigureCoordinate1= i1; // store the polyline contour as vtkPoints object bool outOfBounds = false; vtkSmartPointer points = vtkSmartPointer::New(); typename PlanarFigure::PolyLineType::const_iterator it; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected // image planarFigureGeometry2D->Map( it->Point, point3D ); // Polygons (partially) outside of the image bounds can not be processed // further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { outOfBounds = true; } imageGeometry3D->WorldToIndex( point3D, point3D ); points->InsertNextPoint( point3D[i0], point3D[i1], 0 ); } // mark a malformed 2D planar figure ( i.e. area = 0 ) as out of bounds // this can happen when all control points of a rectangle lie on the same line = two of the three extents are zero double bounds[6] = {0, 0, 0, 0, 0, 0}; points->GetBounds( bounds ); bool extent_x = (fabs(bounds[0] - bounds[1])) < mitk::eps; bool extent_y = (fabs(bounds[2] - bounds[3])) < mitk::eps; bool extent_z = (fabs(bounds[4] - bounds[5])) < mitk::eps; // throw an exception if a closed planar figure is deformed, i.e. has only one non-zero extent if ( m_PlanarFigure->IsClosed() && ((extent_x && extent_y) || (extent_x && extent_z) || (extent_y && extent_z))) { mitkThrow() << "Figure has a zero area and cannot be used for masking."; } if ( outOfBounds ) { throw std::runtime_error( "Figure at least partially outside of image bounds!" ); } // create a vtkLassoStencilSource and set the points of the Polygon vtkSmartPointer lassoStencil = vtkSmartPointer::New(); lassoStencil->SetShapeToPolygon(); lassoStencil->SetPoints( points ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< MaskImage2DType > ImageImportType; typedef itk::VTKImageExport< MaskImage2DType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( castFilter->GetOutput() ); vtkSmartPointer vtkImporter = vtkSmartPointer::New(); this->ConnectPipelines( itkExporter, vtkImporter ); // Apply the generated image stencil to the input image vtkSmartPointer imageStencilFilter = vtkSmartPointer::New(); imageStencilFilter->SetInputConnection( vtkImporter->GetOutputPort() ); - imageStencilFilter->SetStencil( lassoStencil->GetOutput() ); + imageStencilFilter->SetStencilData(lassoStencil->GetOutput() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkSmartPointer vtkExporter = vtkImageExport::New(); // TODO: this is WRONG, should be vtkSmartPointer::New(), but bug # 14455 //vtkSmartPointer vtkExporter = vtkSmartPointer::New(); vtkExporter->SetInputConnection( imageStencilFilter->GetOutputPort() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // Store mask m_InternalImageMask2D = itkImporter->GetOutput(); } void ImageStatisticsCalculator::UnmaskedStatisticsProgressUpdate() { // Need to throw away every second progress event to reach a final count of // 100 since two consecutive filters are used in this case static int updateCounter = 0; if ( updateCounter++ % 2 == 0 ) { this->InvokeEvent( itk::ProgressEvent() ); } } void ImageStatisticsCalculator::MaskedStatisticsProgressUpdate() { this->InvokeEvent( itk::ProgressEvent() ); } } diff --git a/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp b/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp index ceb16e6d83..7d6d38fcbf 100644 --- a/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp @@ -1,365 +1,364 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::LabeledImageToSurfaceFilter::LabeledImageToSurfaceFilter() : m_GaussianStandardDeviation(1.5), m_GenerateAllLabels(true), m_Label(1), m_BackgroundLabel(0) { } mitk::LabeledImageToSurfaceFilter::~LabeledImageToSurfaceFilter() { } void mitk::LabeledImageToSurfaceFilter::GenerateOutputInformation() { Superclass::GenerateOutputInformation(); // // check which labels are available in the image // m_AvailableLabels = this->GetAvailableLabels(); m_IdxToLabels.clear(); // // if we don't want to generate surfaces for all labels // we have to remove all labels except m_Label and m_BackgroundLabel // from the list of available labels // if ( ! m_GenerateAllLabels ) { LabelMapType tmp; LabelMapType::iterator it; it = m_AvailableLabels.find( m_Label ); if ( it != m_AvailableLabels.end() ) tmp[m_Label] = it->second; else tmp[m_Label] = 0; it = m_AvailableLabels.find( m_BackgroundLabel ); if ( it != m_AvailableLabels.end() ) tmp[m_BackgroundLabel] = it->second; else tmp[m_BackgroundLabel] = 0; m_AvailableLabels = tmp; } // // check for the number of labels: if the whole image is filled, no // background is available and thus the numberOfOutpus is equal to the // number of available labels in the image (which is a special case). // If we have background voxels, the number of outputs is one less than // then number of available labels. // unsigned int numberOfOutputs = 0; if ( m_AvailableLabels.find( m_BackgroundLabel ) == m_AvailableLabels.end() ) numberOfOutputs = m_AvailableLabels.size(); else numberOfOutputs = m_AvailableLabels.size() - 1; if ( numberOfOutputs == 0 ) { itkWarningMacro("Number of outputs == 0"); } // // determine the number of time steps of the input image // mitk::Image* image = ( mitk::Image* )GetInput(); unsigned int numberOfTimeSteps = image->GetTimeGeometry()->CountTimeSteps(); // // set the number of outputs to the number of labels used. // initialize the output surfaces accordingly (incl. time steps) // this->SetNumberOfIndexedOutputs( numberOfOutputs ); this->SetNumberOfRequiredOutputs( numberOfOutputs ); for ( unsigned int i = 0 ; i < numberOfOutputs; ++i ) { if ( ! this->GetOutput( i ) ) { mitk::Surface::Pointer output = static_cast( this->MakeOutput(0).GetPointer() ); assert ( output.IsNotNull() ); output->Expand( numberOfTimeSteps ); this->SetNthOutput( i, output.GetPointer() ); } } } void mitk::LabeledImageToSurfaceFilter::GenerateData() { mitk::Image* image = ( mitk::Image* )GetInput(); if ( image == NULL ) { itkWarningMacro("Image is NULL"); return; } mitk::Image::RegionType outputRegion = image->GetRequestedRegion(); m_IdxToLabels.clear(); if ( this->GetNumberOfOutputs() == 0 ) return; // // traverse the known labels and create surfaces for them. // unsigned int currentOutputIndex = 0; for ( LabelMapType::iterator it = m_AvailableLabels.begin() ; it != m_AvailableLabels.end() ; ++it ) { if ( it->first == m_BackgroundLabel ) continue; if ( ( it->second == 0 ) && m_GenerateAllLabels ) continue; assert ( currentOutputIndex < this->GetNumberOfOutputs() ); mitk::Surface::Pointer surface = this->GetOutput( currentOutputIndex ); assert( surface.IsNotNull() ); int tstart=outputRegion.GetIndex(3); int tmax=tstart+outputRegion.GetSize(3); //GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloet int t; for( t=tstart; t < tmax; ++t) { vtkImageData *vtkimagedata = image->GetVtkImageData( t ); CreateSurface( t,vtkimagedata,surface.GetPointer(), it->first ); } m_IdxToLabels[ currentOutputIndex ] = it->first; currentOutputIndex++; } } void mitk::LabeledImageToSurfaceFilter::CreateSurface( int time, vtkImageData *vtkimage, mitk::Surface * surface, mitk::LabeledImageToSurfaceFilter::LabelType label ) { vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New(); - indexCoordinatesImageFilter->SetInput(vtkimage); + indexCoordinatesImageFilter->SetInputData(vtkimage); indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0); vtkImageThreshold* threshold = vtkImageThreshold::New(); - threshold->SetInput( indexCoordinatesImageFilter->GetOutput() ); + threshold->SetInputData( indexCoordinatesImageFilter->GetOutput() ); //indexCoordinatesImageFilter->Delete(); threshold->SetInValue( 100 ); threshold->SetOutValue( 0 ); threshold->ThresholdBetween( label, label ); threshold->SetOutputScalarTypeToUnsignedChar(); threshold->ReleaseDataFlagOn(); vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New(); - gaussian->SetInput( threshold->GetOutput() ); + gaussian->SetInputData( threshold->GetOutput() ); //threshold->Delete(); gaussian->SetDimensionality( 3 ); gaussian->SetRadiusFactor( 0.49 ); gaussian->SetStandardDeviation( GetGaussianStandardDeviation() ); gaussian->ReleaseDataFlagOn(); gaussian->UpdateInformation(); gaussian->Update(); //MarchingCube -->create Surface vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New(); skinExtractor->ReleaseDataFlagOn(); - skinExtractor->SetInput(gaussian->GetOutput());//RC++ + skinExtractor->SetInputData(gaussian->GetOutput());//RC++ indexCoordinatesImageFilter->Delete(); skinExtractor->SetValue(0, 50); vtkPolyData *polydata; polydata = skinExtractor->GetOutput(); polydata->Register(NULL);//RC++ skinExtractor->Delete(); if (m_Smooth) { vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New(); //read poly1 (poly1 can be the original polygon, or the decimated polygon) - smoother->SetInput(polydata);//RC++ + smoother->SetInputData(polydata);//RC++ smoother->SetNumberOfIterations( m_SmoothIteration ); smoother->SetRelaxationFactor( m_SmoothRelaxation ); smoother->SetFeatureAngle( 60 ); smoother->FeatureEdgeSmoothingOff(); smoother->BoundarySmoothingOff(); smoother->SetConvergence( 0 ); polydata->Delete();//RC-- polydata = smoother->GetOutput(); polydata->Register(NULL);//RC++ smoother->Delete(); } //decimate = to reduce number of polygons if(m_Decimate==DecimatePro) { vtkDecimatePro *decimate = vtkDecimatePro::New(); decimate->SplittingOff(); decimate->SetErrorIsAbsolute(5); decimate->SetFeatureAngle(30); decimate->PreserveTopologyOn(); decimate->BoundaryVertexDeletionOff(); decimate->SetDegree(10); //std-value is 25! - decimate->SetInput(polydata);//RC++ + decimate->SetInputData(polydata);//RC++ decimate->SetTargetReduction(m_TargetReduction); decimate->SetMaximumError(0.002); polydata->Delete();//RC-- polydata = decimate->GetOutput(); polydata->Register(NULL);//RC++ decimate->Delete(); } - polydata->Update(); - - polydata->SetSource(NULL); +// polydata->Update(); //VTK6_TODO +// polydata->SetSource(NULL); if(polydata->GetNumberOfPoints() > 0) { mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing(); vtkPoints * points = polydata->GetPoints(); vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New(); GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix); double (*matrix)[4] = vtkmatrix->Element; unsigned int i,j; for(i=0;i<3;++i) for(j=0;j<3;++j) matrix[i][j]/=spacing[j]; unsigned int n = points->GetNumberOfPoints(); double point[3]; for (i = 0; i < n; i++) { points->GetPoint(i, point); mitkVtkLinearTransformPoint(matrix,point,point); points->SetPoint(i, point); } vtkmatrix->Delete(); } surface->SetVtkPolyData(polydata, time); polydata->UnRegister(NULL); gaussian->Delete(); threshold->Delete(); } template < typename TPixel, unsigned int VImageDimension > void GetAvailableLabelsInternal( itk::Image* image, mitk::LabeledImageToSurfaceFilter::LabelMapType& availableLabels ) { typedef itk::Image ImageType; typedef itk::ImageRegionIterator< ImageType > ImageRegionIteratorType; availableLabels.clear(); ImageRegionIteratorType it( image, image->GetLargestPossibleRegion() ); it.GoToBegin(); mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt; while( ! it.IsAtEnd() ) { labelIt = availableLabels.find( ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ); if ( labelIt == availableLabels.end() ) { availableLabels[ ( mitk::LabeledImageToSurfaceFilter::LabelType ) ( it.Get() ) ] = 1; } else { labelIt->second += 1; } ++it; } } #define InstantiateAccessFunction_GetAvailableLabelsInternal(pixelType, dim) \ template void GetAvailableLabelsInternal(itk::Image*, mitk::LabeledImageToSurfaceFilter::LabelMapType&); InstantiateAccessFunctionForFixedDimension(GetAvailableLabelsInternal, 3); mitk::LabeledImageToSurfaceFilter::LabelMapType mitk::LabeledImageToSurfaceFilter::GetAvailableLabels() { mitk::Image::Pointer image = ( mitk::Image* )GetInput(); LabelMapType availableLabels; AccessFixedDimensionByItk_1( image, GetAvailableLabelsInternal, 3, availableLabels ); return availableLabels; } void mitk::LabeledImageToSurfaceFilter::CreateSurface(int, vtkImageData*, mitk::Surface*, const ScalarType) { itkWarningMacro( "This function should never be called!" ); assert(false); } mitk::LabeledImageToSurfaceFilter::LabelType mitk::LabeledImageToSurfaceFilter::GetLabelForNthOutput( const unsigned int& idx ) { IdxToLabelMapType::iterator it = m_IdxToLabels.find( idx ); if ( it != m_IdxToLabels.end() ) { return it->second; } else { itkWarningMacro( "Unknown index encountered: " << idx << ". There are " << this->GetNumberOfOutputs() << " outputs available." ); return itk::NumericTraits::max(); } } mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForNthOutput( const unsigned int& i ) { return GetVolumeForLabel( GetLabelForNthOutput( i ) ); } mitk::ScalarType mitk::LabeledImageToSurfaceFilter::GetVolumeForLabel( const mitk::LabeledImageToSurfaceFilter::LabelType& label ) { // get the image spacing mitk::Image* image = ( mitk::Image* )GetInput(); const float* spacing = image->GetSlicedGeometry()->GetFloatSpacing(); // get the number of voxels encountered for the given label, // calculate the volume and return it. LabelMapType::iterator it = m_AvailableLabels.find( label ); if ( it != m_AvailableLabels.end() ) { return static_cast(it->second) * ( spacing[0] * spacing[1] * spacing[2] / 1000.0f ); } else { itkWarningMacro( "Unknown label encountered: " << label ); return 0.0; } } diff --git a/Modules/MitkExt/Algorithms/mitkProbeFilter.cpp b/Modules/MitkExt/Algorithms/mitkProbeFilter.cpp index d0285c3e23..f3c6416b1f 100644 --- a/Modules/MitkExt/Algorithms/mitkProbeFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkProbeFilter.cpp @@ -1,214 +1,213 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkProbeFilter.h" #include "mitkSurface.h" #include "mitkImage.h" -#include #include #include #include #include #include mitk::ProbeFilter::ProbeFilter() { } mitk::ProbeFilter::~ProbeFilter() { } const mitk::Surface *mitk::ProbeFilter::GetInput(void) { if (this->GetNumberOfInputs() < 1) { return 0; } return static_cast< const mitk::Surface * >(this->ProcessObject::GetInput(0) ); } const mitk::Image *mitk::ProbeFilter::GetSource(void) { return static_cast< const mitk::Image * >(this->ProcessObject::GetInput(1)); } void mitk::ProbeFilter::SetInput(const mitk::Surface *input) { this->ProcessObject::SetNthInput( 0, const_cast< mitk::Surface * >( input ) ); } void mitk::ProbeFilter::SetSource(const mitk::Image *source) { this->ProcessObject::SetNthInput( 1, const_cast< mitk::Image * >( source ) ); } void mitk::ProbeFilter::GenerateOutputInformation() { mitk::Surface::ConstPointer input = this->GetInput(); mitk::Image::ConstPointer source = this->GetSource(); mitk::Surface::Pointer output = this->GetOutput(); if(input.IsNull()) return; if(source.IsNull()) return; if(input->GetGeometry()==NULL) return; if(source->GetGeometry()==NULL) return; if( (input->GetTimeGeometry()->CountTimeSteps()==1) && (source->GetTimeGeometry()->CountTimeSteps()>1) ) { Geometry3D::Pointer geometry3D = Geometry3D::New(); geometry3D->Initialize(); geometry3D->SetBounds(source->GetTimeGeometry()->GetBoundsInWorld()); geometry3D->SetTimeBounds(source->GetTimeGeometry()->GetGeometryForTimeStep(0)->GetTimeBounds()); ProportionalTimeGeometry::Pointer outputTimeGeometry = ProportionalTimeGeometry::New(); outputTimeGeometry->Initialize(geometry3D, source->GetTimeGeometry()->CountTimeSteps()); output->Expand(outputTimeGeometry->CountTimeSteps()); output->SetTimeGeometry( outputTimeGeometry ); } else output->SetGeometry( static_cast(input->GetGeometry()->Clone().GetPointer()) ); itkDebugMacro(<<"GenerateOutputInformation()"); } void mitk::ProbeFilter::GenerateData() { mitk::Surface *input = const_cast< mitk::Surface * >(this->GetInput()); mitk::Image *source = const_cast< mitk::Image * >(this->GetSource()); mitk::Surface::Pointer output = this->GetOutput(); itkDebugMacro(<<"Generating Data"); if(output.IsNull()) { itkDebugMacro(<<"Output is NULL."); return; } mitk::Surface::RegionType outputRegion = output->GetRequestedRegion(); const TimeGeometry *outputTimeGeometry = output->GetTimeGeometry(); const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); const TimeGeometry *sourceTimeGeometry = source->GetTimeGeometry(); TimePointType timeInMS; int timestep=0; int tstart, tmax; tstart=outputRegion.GetIndex(3); tmax=tstart+outputRegion.GetSize(3); int t; for(t=tstart;tTimeStepToTimePoint( t ); vtkProbeFilter* probe = vtkProbeFilter::New(); timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS ); - probe->SetInput( input->GetVtkPolyData(timestep) ); + probe->SetInputData( input->GetVtkPolyData(timestep) ); timestep = sourceTimeGeometry->TimePointToTimeStep( timeInMS ); - probe->SetSource( source->GetVtkImageData(timestep) ); + probe->SetSourceData( source->GetVtkImageData(timestep) ); output->SetVtkPolyData( probe->GetPolyDataOutput(), t ); probe->Update(); probe->Delete(); } } void mitk::ProbeFilter::GenerateInputRequestedRegion() { Superclass::GenerateInputRequestedRegion(); mitk::Surface *input = const_cast< mitk::Surface * >( this->GetInput() ); mitk::Image *source = const_cast< mitk::Image * >( this->GetSource() ); if(input==NULL) return; if(source==NULL) return; mitk::Surface::Pointer output = this->GetOutput(); mitk::Surface::RegionType outputRegion = output->GetRequestedRegion(); const TimeGeometry *outputTimeGeometry = output->GetTimeGeometry(); mitk::Surface::RegionType inputSurfaceRegion = outputRegion; Image::RegionType sourceImageRegion = source->GetLargestPossibleRegion(); if(outputRegion.GetSize(3)<1) { mitk::Surface::RegionType::SizeType surfacesize; surfacesize.Fill(0); inputSurfaceRegion.SetSize(surfacesize); input->SetRequestedRegion( &inputSurfaceRegion ); mitk::Image::RegionType::SizeType imagesize; imagesize.Fill(0); sourceImageRegion.SetSize(imagesize); source->SetRequestedRegion( &sourceImageRegion ); return; } //create and set input requested region for the input surface const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); ScalarType timeInMS; int timestep=0; // convert the start-index-time of output in start-index-time of input via millisecond-time timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3)); timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS ); if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( inputTimeGeometry->IsValidTimeStep( timestep ) ) ) inputSurfaceRegion.SetIndex( 3, timestep ); else inputSurfaceRegion.SetIndex( 3, 0 ); // convert the end-index-time of output in end-index-time of input via millisecond-time timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3)+outputRegion.GetSize(3)-1); timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS ); if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( outputTimeGeometry->IsValidTimeStep( timestep ) ) ) inputSurfaceRegion.SetSize( 3, timestep - inputSurfaceRegion.GetIndex(3) + 1 ); else inputSurfaceRegion.SetSize( 3, 1 ); input->SetRequestedRegion( &inputSurfaceRegion ); //create and set input requested region for the source image const TimeGeometry *sourceTimeGeometry = source->GetTimeGeometry(); // convert the start-index-time of output in start-index-time of source via millisecond-time timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3)); timestep = sourceTimeGeometry->TimePointToTimeStep( timeInMS ); if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( sourceTimeGeometry->IsValidTimeStep( timestep ) ) ) sourceImageRegion.SetIndex( 3, timestep ); else sourceImageRegion.SetIndex( 3, 0 ); // convert the end-index-time of output in end-index-time of source via millisecond-time timeInMS = outputTimeGeometry->TimeStepToTimePoint(outputRegion.GetIndex(3)+outputRegion.GetSize(3)-1); timestep = sourceTimeGeometry->TimePointToTimeStep( timeInMS ); if( ( timeInMS > ScalarTypeNumericTraits::NonpositiveMin() ) && ( outputTimeGeometry->IsValidTimeStep( timestep ) ) ) sourceImageRegion.SetSize( 3, timestep - sourceImageRegion.GetIndex(3) + 1 ); else sourceImageRegion.SetSize( 3, 1 ); sourceImageRegion.SetIndex( 4, 0 ); sourceImageRegion.SetSize( 4, 1 ); source->SetRequestedRegion( &sourceImageRegion ); } diff --git a/Modules/MitkExt/DataManagement/mitkUnstructuredGrid.cpp b/Modules/MitkExt/DataManagement/mitkUnstructuredGrid.cpp index 0abe926dee..eae4f56cf1 100644 --- a/Modules/MitkExt/DataManagement/mitkUnstructuredGrid.cpp +++ b/Modules/MitkExt/DataManagement/mitkUnstructuredGrid.cpp @@ -1,248 +1,248 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUnstructuredGrid.h" #include void mitk::UnstructuredGrid::SetVtkUnstructuredGrid( vtkUnstructuredGrid* grid, unsigned int t ) { this->Expand(t); if(m_GridSeries[ t ] != NULL) { m_GridSeries[ t ]->Delete(); } m_GridSeries[ t ] = grid; // call m_VtkPolyData->Register(NULL) to tell the reference counting that we // want to keep a reference on the object if (m_GridSeries[t] != 0) m_GridSeries[t]->Register(grid); this->Modified(); m_CalculateBoundingBox = true; } void mitk::UnstructuredGrid::Expand(unsigned int timeSteps) { // check if the vector is long enough to contain the new element // at the given position. If not, expand it with sufficient zero-filled elements. if(timeSteps > m_GridSeries.size()) { Superclass::Expand(timeSteps); vtkUnstructuredGrid* pdnull = 0; m_GridSeries.resize( timeSteps, pdnull ); m_CalculateBoundingBox = true; } } void mitk::UnstructuredGrid::ClearData() { for ( VTKUnstructuredGridSeries::iterator it = m_GridSeries.begin(); it != m_GridSeries.end(); ++it ) { if ( ( *it ) != 0 ) ( *it )->Delete(); } m_GridSeries.clear(); Superclass::ClearData(); } void mitk::UnstructuredGrid::InitializeEmpty() { vtkUnstructuredGrid* pdnull = 0; m_GridSeries.resize( 1, pdnull ); Superclass::InitializeTimeGeometry(1); m_Initialized = true; } vtkUnstructuredGrid* mitk::UnstructuredGrid::GetVtkUnstructuredGrid(unsigned int t) { if ( t < m_GridSeries.size() ) { vtkUnstructuredGrid* grid = m_GridSeries[ t ]; if((grid == 0) && (GetSource().GetPointer() != 0)) { RegionType requestedregion; requestedregion.SetIndex(3, t); requestedregion.SetSize(3, 1); SetRequestedRegion(&requestedregion); GetSource()->Update(); } grid = m_GridSeries[ t ]; return grid; } else return 0; } mitk::UnstructuredGrid::UnstructuredGrid() : m_CalculateBoundingBox( false ) { this->InitializeEmpty(); } mitk::UnstructuredGrid::UnstructuredGrid(const mitk::UnstructuredGrid &other) : BaseData(other), m_CalculateBoundingBox( other.m_CalculateBoundingBox ), m_LargestPossibleRegion(other.m_LargestPossibleRegion) { if(!other.m_Initialized) { this->InitializeEmpty(); } else { m_GridSeries = other.m_GridSeries; m_Initialized = other.m_Initialized; } this->SetRequestedRegion( const_cast(&other) ); } mitk::UnstructuredGrid::~UnstructuredGrid() { this->ClearData(); } void mitk::UnstructuredGrid::UpdateOutputInformation() { if ( this->GetSource() ) { this->GetSource()->UpdateOutputInformation(); } if ( ( m_CalculateBoundingBox ) && ( m_GridSeries.size() > 0 ) ) CalculateBoundingBox(); else GetTimeGeometry()->Update(); } void mitk::UnstructuredGrid::CalculateBoundingBox() { // // first make sure, that the associated time sliced geometry has // the same number of geometry 3d's as vtkUnstructuredGrids are present // TimeGeometry* timeGeometry = GetTimeGeometry(); if ( timeGeometry->CountTimeSteps() != m_GridSeries.size() ) { itkExceptionMacro(<<"timeGeometry->CountTimeSteps() != m_GridSeries.size() -- use Initialize(timeSteps) with correct number of timeSteps!"); } // // Iterate over the vtkUnstructuredGrids and update the Geometry // information of each of the items. // for ( unsigned int i = 0 ; i < m_GridSeries.size() ; ++i ) { vtkUnstructuredGrid* grid = m_GridSeries[ i ]; double bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; if ( ( grid != 0 ) && ( grid->GetNumberOfCells() > 0 ) ) { - grid->Update(); +// grid->Update(); //VTK6_TODO grid->ComputeBounds(); grid->GetBounds( bounds ); } mitk::Geometry3D::Pointer g3d = timeGeometry->GetGeometryForTimeStep( i ); assert( g3d.IsNotNull() ); g3d->SetFloatBounds( bounds ); } timeGeometry->Update(); mitk::BoundingBox::Pointer bb = const_cast( timeGeometry->GetBoundingBoxInWorld() ); itkDebugMacro( << "boundingbox min: "<< bb->GetMinimum()); itkDebugMacro( << "boundingbox max: "<< bb->GetMaximum()); m_CalculateBoundingBox = false; } void mitk::UnstructuredGrid::SetRequestedRegionToLargestPossibleRegion() { m_RequestedRegion = GetLargestPossibleRegion(); } bool mitk::UnstructuredGrid::RequestedRegionIsOutsideOfTheBufferedRegion() { RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3); if(((RegionType::IndexValueType)m_GridSeries.size()) < end) return true; for( RegionType::IndexValueType t=m_RequestedRegion.GetIndex(3); t < end; ++t ) if(m_GridSeries[t] == 0) return true; return false; } bool mitk::UnstructuredGrid::VerifyRequestedRegion() { if( (m_RequestedRegion.GetIndex(3)>=0) && (m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3)<=m_GridSeries.size()) ) return true; return false; } void mitk::UnstructuredGrid::SetRequestedRegion(const itk::DataObject *data ) { const mitk::UnstructuredGrid *gridData; gridData = dynamic_cast(data); if (gridData) { m_RequestedRegion = gridData->GetRequestedRegion(); } else { // pointer could not be cast back down itkExceptionMacro( << "mitk::UnstructuredGrid::SetRequestedRegion(DataObject*) cannot cast " << typeid(data).name() << " to " << typeid(UnstructuredGrid*).name() ); } } void mitk::UnstructuredGrid::SetRequestedRegion(UnstructuredGrid::RegionType *region) //by arin { if(region != 0) { m_RequestedRegion = *region; } else { // pointer could not be cast back down itkExceptionMacro( << "mitk::UnstructuredGrid::SetRequestedRegion(UnstructuredGrid::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(UnstructuredGrid*).name() ); } } void mitk::UnstructuredGrid::CopyInformation( const itk::DataObject * data ) { Superclass::CopyInformation(data); } void mitk::UnstructuredGrid::Update() { if ( GetSource().IsNull() ) { for ( VTKUnstructuredGridSeries::iterator it = m_GridSeries.begin() ; it != m_GridSeries.end() ; ++it ) { - if ( ( *it ) != 0 ) - ( *it )->Update(); +// if ( ( *it ) != 0 ) +// ( *it )->Update(); //VTK6_TODO } } Superclass::Update(); } diff --git a/Modules/MitkExt/IO/mitkUnstructuredGridVtkWriter.txx b/Modules/MitkExt/IO/mitkUnstructuredGridVtkWriter.txx index 10a55f9add..a09db5110a 100644 --- a/Modules/MitkExt/IO/mitkUnstructuredGridVtkWriter.txx +++ b/Modules/MitkExt/IO/mitkUnstructuredGridVtkWriter.txx @@ -1,205 +1,205 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_UNSTRUCTURED_GRID_VTKWRITER_TXX_ #define _MITK_UNSTRUCTURED_GRID_VTKWRITER_TXX_ #include #include #include #include #include #include #include #include #include #include #include namespace mitk { template UnstructuredGridVtkWriter::UnstructuredGridVtkWriter() : m_Success(false) { this->SetNumberOfRequiredInputs(1); } template UnstructuredGridVtkWriter::~UnstructuredGridVtkWriter() { } template void UnstructuredGridVtkWriter::GenerateData() { m_Success = false; if ( m_FileName == "" ) { itkWarningMacro( << "Sorry, filename has not been set!" ); return ; } mitk::UnstructuredGrid::Pointer input = const_cast(this->GetInput()); if (input.IsNull()) { itkWarningMacro( << "Sorry, input to mitk::UnstructuredGridVtkWriter is NULL"); return; } VTKWRITER* unstructuredGridWriter = VTKWRITER::New(); vtkTransformFilter* transformPointSet = vtkTransformFilter::New(); vtkUnstructuredGrid * unstructuredGrid; Geometry3D* geometry; if(input->GetTimeGeometry()->CountTimeSteps()>1) { int t, timesteps; timesteps = input->GetTimeGeometry()->CountTimeSteps(); for(t = 0; t < timesteps; ++t) { std::ostringstream filename; geometry = input->GetGeometry(t); if(input->GetTimeGeometry()->IsValidTimeStep(t)) { const mitk::TimeBounds& timebounds = geometry->GetTimeBounds(); filename << m_FileName.c_str() << "_S" << std::setprecision(0) << timebounds[0] << "_E" << std::setprecision(0) << timebounds[1] << "_T" << t << GetDefaultExtension(); } else { itkWarningMacro(<<"Error on write: TimeGeometry invalid of unstructured grid " << filename << "."); filename << m_FileName.c_str() << "_T" << t << GetDefaultExtension(); } geometry->TransferItkToVtkTransform(); - transformPointSet->SetInput(input->GetVtkUnstructuredGrid(t)); + transformPointSet->SetInputData(input->GetVtkUnstructuredGrid(t)); transformPointSet->SetTransform(geometry->GetVtkTransform()); transformPointSet->UpdateWholeExtent(); unstructuredGrid = static_cast(transformPointSet->GetOutput()); unstructuredGridWriter->SetFileName(filename.str().c_str()); - unstructuredGridWriter->SetInput(unstructuredGrid); + unstructuredGridWriter->SetInputData(unstructuredGrid); ExecuteWrite( unstructuredGridWriter ); } } else { geometry = input->GetGeometry(); geometry->TransferItkToVtkTransform(); - transformPointSet->SetInput(input->GetVtkUnstructuredGrid()); + transformPointSet->SetInputData(input->GetVtkUnstructuredGrid()); transformPointSet->SetTransform(geometry->GetVtkTransform()); transformPointSet->UpdateWholeExtent(); unstructuredGrid = static_cast(transformPointSet->GetOutput()); unstructuredGridWriter->SetFileName(m_FileName.c_str()); - unstructuredGridWriter->SetInput(unstructuredGrid); + unstructuredGridWriter->SetInputData(unstructuredGrid); ExecuteWrite( unstructuredGridWriter ); } transformPointSet->Delete(); unstructuredGridWriter->Delete(); m_Success = true; } template void UnstructuredGridVtkWriter::ExecuteWrite( VTKWRITER* vtkWriter ) { struct stat fileStatus; time_t timeBefore=0; if (!stat(vtkWriter->GetFileName(), &fileStatus)) { timeBefore = fileStatus.st_mtime; } if (!vtkWriter->Write()) { itkExceptionMacro( << "Error during unstructured grid writing."); } // check if file can be written because vtkWriter doesn't check that if (stat(vtkWriter->GetFileName(), &fileStatus) || (timeBefore == fileStatus.st_mtime)) { itkExceptionMacro(<<"Error during unstructured grid writing: file could not be written"); } } template void UnstructuredGridVtkWriter::SetInput(BaseData *input) { this->ProcessObject::SetNthInput(0, input); } template const UnstructuredGrid* UnstructuredGridVtkWriter::GetInput() { if (this->GetNumberOfInputs() < 1) { return 0; } else { return dynamic_cast(this->ProcessObject::GetInput(0)); } } template bool UnstructuredGridVtkWriter::CanWriteBaseDataType(BaseData::Pointer data) { return (dynamic_cast(data.GetPointer()) != 0); } template void UnstructuredGridVtkWriter::DoWrite(BaseData::Pointer data) { if (CanWriteBaseDataType(data)) { this->SetInput(dynamic_cast(data.GetPointer())); this->Update(); } } template std::vector UnstructuredGridVtkWriter::GetPossibleFileExtensions() { throw std::exception(); // no specialization available! } template const char* UnstructuredGridVtkWriter::GetDefaultFilename() { throw std::exception(); // no specialization available! } template const char* UnstructuredGridVtkWriter::GetFileDialogPattern() { throw std::exception(); // no specialization available! } template const char* UnstructuredGridVtkWriter::GetDefaultExtension() { throw std::exception(); // no specialization available! } } #endif diff --git a/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp index 00b95f3fe3..b012ffa0f7 100644 --- a/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp @@ -1,438 +1,438 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkEnhancedPointSetVtkMapper3D.h" //#include #include #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkLookupTables.h" #include "mitkColorProperty.h" //#include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include const mitk::PointSet* mitk::EnhancedPointSetVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } mitk::EnhancedPointSetVtkMapper3D::EnhancedPointSetVtkMapper3D() { m_Contour = vtkActor::New(); m_ContourSource = vtkTubeFilter::New(); m_PropAssembly = vtkAssembly::New(); } vtkProp* mitk::EnhancedPointSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_PropAssembly; } mitk::EnhancedPointSetVtkMapper3D::~EnhancedPointSetVtkMapper3D() { m_Contour->Delete(); m_ContourSource->Delete(); m_PropAssembly->Delete(); // TODO: do cleanup correctly // Clean up all remaining actors and poly-data sources //std::for_each(m_PointActors.begin(), m_PointActors.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // std::for_each(m_SphereSources.begin(), m_SphereSources.end(), &mitk::EnhancedPointSetVtgkMapper3D::DeleteVtkObject); // std::for_each(m_CubeSources.begin(), m_CubeSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // std::for_each(m_ConeSources.begin(), m_ConeSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // std::for_each(m_CylinderSources.begin(), m_CylinderSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // } void mitk::EnhancedPointSetVtkMapper3D::UpdateVtkObjects() { // get and update the PointSet const mitk::PointSet* pointset = this->GetInput(); //pointset->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType* itkPointSet = pointset->GetPointSet( timestep ); mitk::PointSet::PointsContainer* points = itkPointSet->GetPoints(); mitk::PointSet::PointDataContainer* pointData = itkPointSet->GetPointData(); assert(points->Size() == pointData->Size()); mitk::PointSet::PointsIterator pIt; mitk::PointSet::PointDataIterator pdIt; /* search removed points and delete the corresponding source/actor/mapper objects */ for (ActorMap::iterator it = m_PointActors.begin(); it != m_PointActors.end(); ) { PointIdentifier id = it->first; if (!points->IndexExists(id)) { this->RemoveEntryFromSourceMaps(id); m_PropAssembly->GetParts()->RemoveItem(it->second.first); // remove from prop assembly if (it->second.first != NULL) it->second.first->Delete(); // Delete actor, which deletes mapper too (reference count) ActorMap::iterator er = it; // save iterator for deleting ++it; // advance iterator to next object m_PointActors.erase(er); // erase element from map. This invalidates er, therefore we had to advance it before deletion. } else ++it; } /* iterate over each point in the pointset and create corresponding vtk objects */ for (pIt = points->Begin(), pdIt = pointData->Begin(); pIt != itkPointSet->GetPoints()->End(); ++pIt, ++pdIt) { PointIdentifier pointID = pIt->Index(); assert (pointID == pdIt->Index()); mitk::PointSet::PointType point = pIt->Value(); mitk::PointSet::PointDataType data = pdIt->Value(); ActorMap::iterator aIt = m_PointActors.find(pointID); // Does an actor exist for the point? /* Create/Update sources for the point */ vtkActor* a = NULL; bool newPoint = (aIt == m_PointActors.end()); // current point is new bool specChanged = (!newPoint && data.pointSpec != aIt->second.second); // point spec of current point has changed if (newPoint) // point did not exist before, we have to create vtk objects for it { // create actor and mapper for the new point a = vtkActor::New(); vtkPolyDataMapper* m = vtkPolyDataMapper::New(); a->SetMapper(m); m->UnRegister( NULL ); aIt = m_PointActors.insert(std::make_pair(pointID, std::make_pair(a, data.pointSpec))).first; // insert element and update actormap iterator to point to new element m_PropAssembly->AddPart(a); } else { a = aIt->second.first; if (specChanged) // point exists, but point spec has changed { this->RemoveEntryFromSourceMaps( pointID ); } } if ( newPoint || specChanged ) // new point OR existing point but point spec changed { vtkPolyDataAlgorithm* source = NULL; // works only in VTK 5+ switch (data.pointSpec) // add to new map { //TODO: look up representation in a representationlookuptable case PTSTART: //cube m_CubeSources[pointID] = vtkCubeSource::New(); source = m_CubeSources[pointID]; break; case PTCORNER: //cone m_ConeSources[pointID] = vtkConeSource::New(); source = m_ConeSources[pointID]; break; case PTEDGE: // cylinder m_CylinderSources[pointID] = vtkCylinderSource::New(); source = m_CylinderSources[pointID]; break; case PTUNDEFINED: // sphere case PTEND: default: m_SphereSources[pointID] = vtkSphereSource::New(); source = m_SphereSources[pointID]; break; } vtkPolyDataMapper* m = dynamic_cast(a->GetMapper()); assert(m != NULL); - m->SetInput(source->GetOutput()); + m->SetInputData(source->GetOutput()); aIt->second.second = data.pointSpec; // update point spec in actormap } } // for each point } void mitk::EnhancedPointSetVtkMapper3D::ApplyProperties( mitk::BaseRenderer * renderer ) { this->UpdateVtkObjects(); /* iterate over all points in pointset and apply properties to corresponding vtk objects */ // get and update the PointSet const mitk::PointSet* pointset = this->GetInput(); int timestep = this->GetTimestep(); mitk::PointSet::DataType* itkPointSet = pointset->GetPointSet( timestep ); mitk::PointSet::PointsContainer* points = itkPointSet->GetPoints(); mitk::PointSet::PointDataContainer* pointData = itkPointSet->GetPointData(); assert(points->Size() == pointData->Size()); mitk::PointSet::PointsIterator pIt; mitk::PointSet::PointDataIterator pdIt; mitk::DataNode* n = this->GetDataNode(); assert(n != NULL); for (pIt = points->Begin(), pdIt = pointData->Begin(); pIt != itkPointSet->GetPoints()->End(); ++pIt, ++pdIt) // for each point in the pointset { PointIdentifier pointID = pIt->Index(); assert (pointID == pdIt->Index()); mitk::PointSet::PointType point = pIt->Value(); mitk::PointSet::PointDataType data = pdIt->Value(); ActorMap::iterator aIt = m_PointActors.find(pointID); // Does an actor exist for the point? assert(aIt != m_PointActors.end()); // UpdateVtkObjects() must ensure that actor exists vtkActor* a = aIt->second.first; assert(a != NULL); SetVtkMapperImmediateModeRendering(a->GetMapper()); /* update properties */ // visibility bool pointVisibility = true; bool visValueFound = false; mitk::BaseProperty* visProp = n->GetProperty("visibility", renderer); mitk::BoolLookupTableProperty* visLTProp = dynamic_cast(visProp); if (visLTProp != NULL) { mitk::BoolLookupTable visLookupTable = visLTProp->GetValue(); //if (visLookupTable != NULL) //{ try { pointVisibility = visLookupTable.GetTableValue(pointID); visValueFound = true; } catch (...) { } //} } if (visValueFound == false) { pointVisibility = n->IsVisible(renderer, "show points"); // use BoolProperty instead } a->SetVisibility(pointVisibility); // opacity float opacity = 1.0; bool opValueFound = false; mitk::BaseProperty* opProp = n->GetProperty("opacity", renderer); mitk::FloatLookupTableProperty* opLTProp = dynamic_cast(opProp); if (opLTProp != NULL) { mitk::FloatLookupTable opLookupTable = opLTProp->GetValue(); //if (opLookupTable != NULL) //{ try { opacity = opLookupTable.GetTableValue(pointID); opValueFound = true; } catch (...) { } //} } if (opValueFound == false) { n->GetOpacity(opacity, renderer); } a->GetProperty()->SetOpacity(opacity); ////////////////////// continue here /////////////////// // pointsize & point position float pointSize = 1.0; n->GetFloatProperty( "pointsize", pointSize, renderer); switch (data.pointSpec) { //TODO: look up representation in a representationlookuptable case PTSTART: //cube m_CubeSources[pointID]->SetXLength(pointSize); m_CubeSources[pointID]->SetYLength(pointSize); m_CubeSources[pointID]->SetZLength(pointSize); //m_CubeSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; case PTCORNER: //cone m_ConeSources[pointID]->SetRadius(pointSize/2); m_ConeSources[pointID]->SetHeight(pointSize); m_ConeSources[pointID]->SetResolution(2); // two crossed triangles. Maybe introduce an extra property for //m_ConeSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; case PTEDGE: // cylinder m_CylinderSources[pointID]->SetRadius(pointSize/2); m_CylinderSources[pointID]->SetHeight(pointSize); m_CylinderSources[pointID]->CappingOn(); m_CylinderSources[pointID]->SetResolution(6); //m_CylinderSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; case PTUNDEFINED: // sphere case PTEND: default: m_SphereSources[pointID]->SetRadius(pointSize/2); m_SphereSources[pointID]->SetThetaResolution(10); m_SphereSources[pointID]->SetPhiResolution(10); //m_SphereSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; } // set position mitk::Point3D pos = pIt->Value(); aIt->second.first->SetPosition(pos[0], pos[1], pos[2]); // selectedcolor & color float color[3]; if (data.selected) { if(!n->GetColor(color, renderer, "selectedcolor")) n->GetColor(color, renderer); } else { mitk::BaseProperty* a = n->GetProperty("colorLookupTable", renderer); mitk::LookupTableProperty* b = dynamic_cast(a); if (b != NULL) { mitk::LookupTable::Pointer c = b->GetLookupTable(); vtkLookupTable *d = c->GetVtkLookupTable(); double *e=d->GetTableValue(pointID); color[0]=e[0]; color[1]=e[1]; color[2]=e[2]; } else { if(!n->GetColor(color, renderer, "unselectedcolor")) n->GetColor(color, renderer); } } // TODO: What about "color" property? 2D Mapper only uses unselected and selected color properties a->GetProperty()->SetColor(color[0], color[1], color[2]); // TODO: label property } //TODO test different pointSpec // TODO "line width" "show contour" "contourcolor" "contoursize" "close contour" "show label", "label" // TODO "show points" vs "visibility" - is visibility evaluated at all? in a superclass maybe? // TODO create lookup tables for all properties that should be evaluated per point. also create editor widgets for these lookup tables! // TODO check if property changes and pointset changes are reflected in the render window immediately. // TODO check behavior with large PointSets // TODO check for memory leaks on adding/deleting points } void mitk::EnhancedPointSetVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer * renderer ) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); if(needGenerateData) { ls->UpdateGenerateDataTime(); this->UpdateVtkObjects(); } ApplyProperties(renderer); } void mitk::EnhancedPointSetVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { // TODO: apply new transform if time step changed //vtkLinearTransform * vtktransform = // this->GetDataNode()->GetVtkTransform(this->GetTimestep()); //m_SelectedActor->SetUserTransform(vtktransform); //m_UnselectedActor->SetUserTransform(vtktransform); //m_ContourActor->SetUserTransform(vtktransform); } void mitk::EnhancedPointSetVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "pointsize", mitk::FloatProperty::New(1.0), renderer, overwrite); node->AddProperty( "selectedcolor", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); //yellow for selected node->AddProperty( "unselectedcolor", mitk::ColorProperty::New(0.5f, 1.0f, 0.5f), renderer, overwrite); // middle green for unselected node->AddProperty( "color", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); // red as standard node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "contourcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); node->AddProperty( "contoursize", mitk::FloatProperty::New(0.5), renderer, overwrite ); node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "show label", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "label", mitk::StringProperty::New("P"), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New(1.0), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject( vtkObject* o) { if (o != NULL) o->Delete(); } void mitk::EnhancedPointSetVtkMapper3D::RemoveEntryFromSourceMaps( mitk::PointSet::PointIdentifier pointID ) { ActorMap::iterator aIt = m_PointActors.find(pointID); if (aIt == m_PointActors.end()) return; switch (aIt->second.second) // erase in old map { //TODO: look up representation in a representationlookuptable case PTSTART: //cube m_CubeSources[pointID]->Delete(); m_CubeSources.erase(pointID); break; case PTCORNER: //cone m_ConeSources[pointID]->Delete(); m_ConeSources.erase(pointID); break; case PTEDGE: // cylinder m_CylinderSources[pointID]->Delete(); m_CylinderSources.erase(pointID); break; case PTUNDEFINED: // sphere case PTEND: default: m_SphereSources[pointID]->Delete(); m_SphereSources.erase(pointID); break; } } diff --git a/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp b/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp index d08c0a2d4d..5e766956b9 100644 --- a/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp @@ -1,712 +1,712 @@ /*=================================================================== 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 "mitkProperties.h" #include "mitkLevelWindow.h" #include "mitkColorProperty.h" #include "mitkLevelWindowProperty.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunctionProperty.h" #include "mitkTransferFunctionInitializer.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkRenderingManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) #include "vtkMitkGPUVolumeRayCastMapper.h" #endif #include "vtkOpenGLGPUVolumeRayCastMapper.h" #include "vtkMitkOpenGLVolumeTextureMapper3D.h" const mitk::Image* mitk::GPUVolumeMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } void mitk::GPUVolumeMapper3D::MitkRenderVolumetricGeometry(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); VtkMapper::MitkRenderVolumetricGeometry(renderer); if(ls->m_gpuInitialized) ls->m_MapperGPU->UpdateMTime(); } bool mitk::GPUVolumeMapper3D::InitGPU(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_gpuInitialized) return ls->m_gpuSupported; ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); GPU_INFO << "initializing gpu-slicing-vr (vtkMitkOpenGLVolumeTextureMapper3D)"; ls->m_MapperGPU = vtkSmartPointer::New(); ls->m_MapperGPU->SetUseCompressedTexture(false); ls->m_MapperGPU->SetSampleDistance(1.0); ls->m_VolumePropertyGPU = vtkSmartPointer::New(); ls->m_VolumePropertyGPU->ShadeOn(); ls->m_VolumePropertyGPU->SetAmbient (0.25f); //0.05f ls->m_VolumePropertyGPU->SetDiffuse (0.50f); //0.45f ls->m_VolumePropertyGPU->SetSpecular(0.40f); //0.50f ls->m_VolumePropertyGPU->SetSpecularPower(16.0f); ls->m_VolumePropertyGPU->SetInterpolationTypeToLinear(); ls->m_VolumeGPU = vtkSmartPointer::New(); ls->m_VolumeGPU->SetMapper( ls->m_MapperGPU ); ls->m_VolumeGPU->SetProperty( ls->m_VolumePropertyGPU ); ls->m_VolumeGPU->VisibilityOn(); - ls->m_MapperGPU->SetInput( this->m_UnitSpacingImageFilter->GetOutput() ); + ls->m_MapperGPU->SetInputData( this->m_UnitSpacingImageFilter->GetOutput() ); ls->m_gpuSupported = ls->m_MapperGPU->IsRenderSupported(renderer->GetVtkRenderer(),ls->m_VolumePropertyGPU); ls->m_gpuInitialized = true; return ls->m_gpuSupported; } 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->SetInput( m_UnitSpacingImageFilter->GetOutput() );//m_Resampler->GetOutput()); + ls->m_MapperCPU->SetInputData( m_UnitSpacingImageFilter->GetOutput() );//m_Resampler->GetOutput()); ls->m_cpuInitialized=true; } void mitk::GPUVolumeMapper3D::DeinitGPU(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_gpuInitialized) { GPU_INFO << "deinitializing gpu-slicing-vr"; // deinit renderwindow, this is needed to release the memory allocated on the gpu // to prevent leaking memory on the gpu ls->m_MapperGPU->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetVTKWindow()); ls->m_VolumePropertyGPU = NULL; ls->m_MapperGPU = NULL; ls->m_VolumeGPU = NULL; ls->m_gpuInitialized=false; } } 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< mitk::Image * >( 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) { // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) 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 #endif if(IsGPUEnabled(renderer)) { DeinitCPU(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) DeinitRAY(renderer); #endif if(!InitGPU(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } else { fallback: DeinitGPU(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) DeinitRAY(renderer); #endif 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); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(ls->m_rayInitialized) return ls->m_VolumeRAY; #endif 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< mitk::Image * >( this->GetInput() ); vtkImageData *inputData = input->GetVtkImageData( this->GetTimestep() ); - m_UnitSpacingImageFilter->SetInput( inputData ); + m_UnitSpacingImageFilter->SetInputData( inputData ); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(ls->m_rayInitialized) { GenerateDataRAY(renderer); } else #endif if(ls->m_gpuInitialized) { GenerateDataGPU(renderer); } else { GenerateDataCPU(renderer); } // UpdateTransferFunctions UpdateTransferFunctions( renderer ); } void mitk::GPUVolumeMapper3D::GenerateDataGPU( mitk::BaseRenderer *renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool useCompression = false; GetDataNode()->GetBoolProperty("volumerendering.gpu.usetexturecompression",useCompression,renderer); ls->m_MapperGPU->SetUseCompressedTexture(useCompression); if( IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) == 0 ) ls->m_MapperGPU->SetSampleDistance(2.0); else ls->m_MapperGPU->SetSampleDistance(1.0); // Updating shadings { float value=0; if(GetDataNode()->GetFloatProperty("volumerendering.gpu.ambient",value,renderer)) ls->m_VolumePropertyGPU->SetAmbient(value); if(GetDataNode()->GetFloatProperty("volumerendering.gpu.diffuse",value,renderer)) ls->m_VolumePropertyGPU->SetDiffuse(value); if(GetDataNode()->GetFloatProperty("volumerendering.gpu.specular",value,renderer)) ls->m_VolumePropertyGPU->SetSpecular(value); if(GetDataNode()->GetFloatProperty("volumerendering.gpu.specular.power",value,renderer)) ls->m_VolumePropertyGPU->SetSpecularPower(value); } } 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 ); } // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(ls->m_rayInitialized) { ls->m_VolumePropertyRAY->SetColor( colorTransferFunction ); ls->m_VolumePropertyRAY->SetScalarOpacity( opacityTransferFunction ); ls->m_VolumePropertyRAY->SetGradientOpacity( gradientTransferFunction ); } #endif 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 ); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) 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 ); #endif 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; } // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) 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->SetInput( this->m_UnitSpacingImageFilter->GetOutput() ); 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; } #endif diff --git a/Modules/MitkExt/Rendering/mitkImageBackground2D.cpp b/Modules/MitkExt/Rendering/mitkImageBackground2D.cpp index 6ae8bee623..77df492c68 100644 --- a/Modules/MitkExt/Rendering/mitkImageBackground2D.cpp +++ b/Modules/MitkExt/Rendering/mitkImageBackground2D.cpp @@ -1,268 +1,268 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkImageBackground2D.h" // MITK includes #include "mitkVtkLayerController.h" // VTK includes #include "vtkSystemIncludes.h" #include "vtkRenderer.h" #include "vtkMapper.h" #include "vtkObjectFactory.h" #include "vtkImageActor.h" #include "vtkRenderWindow.h" #include "vtkImageImport.h" #include "vtkCommand.h" #include "vtkCamera.h" #include // VTK CALLBACK for automatic resize of the video class vtkVideoSizeCallback : public vtkCommand { public: static vtkVideoSizeCallback *New(){ return new vtkVideoSizeCallback; } vtkRenderer * m_ImageRenderer; int m_ImageWidth, m_ImageHeight; void SetVtkVideoRenderer(vtkRenderer* r) { m_ImageRenderer = r; } void SetVideoDimensions(int x, int y) { m_ImageWidth = x; m_ImageHeight = y; } virtual void Execute(vtkObject* /*caller*/, unsigned long, void*) { //vtkRenderWindow * RenderWindow = reinterpret_cast(caller); //m_ImageRenderer->ResetCameraClippingRange(); } }; mitk::ImageBackground2D::ImageBackground2D() { m_ImageWidth = 0; m_ImageHeight = 0; m_ImageScalarComponents = 3; m_ParallelScale = 0; m_RenderWindow = NULL; m_Actor = vtkImageActor::New(); m_ImageRenderer = vtkRenderer::New(); m_VtkImageImport = vtkImageImport::New(); m_ImageData = NULL; } void mitk::ImageBackground2D::InitVtkImageImport() { /*m_VtkImageImport->Delete(); m_VtkImageImport = vtkImageImport::New();*/ m_VtkImageImport->SetDataScalarTypeToUnsignedChar(); m_VtkImageImport->SetNumberOfScalarComponents(m_ImageScalarComponents); m_VtkImageImport->SetWholeExtent(0,m_ImageWidth-1,0,m_ImageHeight-1,0,1-1); m_VtkImageImport->SetDataExtentToWholeExtent(); } mitk::ImageBackground2D::~ImageBackground2D() { if ( m_RenderWindow != NULL ) if ( this->IsEnabled() ) this->Disable(); if ( m_Actor!=NULL ) m_Actor->Delete(); if ( m_ImageRenderer != NULL ) m_ImageRenderer->Delete(); if ( m_VtkImageImport != NULL) m_VtkImageImport->Delete(); } /** * Sets the renderwindow, in which the Video background * will be shown. Make sure, you have called this function * before calling Enable() */ void mitk::ImageBackground2D::SetRenderWindow(vtkRenderWindow* renderWindow ) { m_RenderWindow = renderWindow; /*m_SizeCallback = vtkVideoSizeCallback::New(); m_RenderWindow->GetVtkRenderWindow()->AddObserver(vtkCommand::ModifiedEvent,m_SizeCallback);*/ } void mitk::ImageBackground2D::SetParallelScale(int scale) { m_ParallelScale = scale; m_ImageRenderer->GetActiveCamera()->SetParallelScale(m_ParallelScale); } int mitk::ImageBackground2D::GetParallelScale() { // TODO someone who knows this, check if double->int could cause problems return static_cast(m_ImageRenderer->GetActiveCamera()->GetParallelScale()); } /** * Enables drawing of the color Video background. * If you want to disable it, call the Disable() function. */ void mitk::ImageBackground2D::Enable() { m_ImageRenderer = vtkRenderer::New(); mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertBackgroundRenderer(m_ImageRenderer,true); char * c = 0; Update(c); - m_Actor->SetInput(m_VtkImageImport->GetOutput()); + m_Actor->SetInputData(m_VtkImageImport->GetOutput()); m_ImageRenderer->AddActor2D(m_Actor); m_ImageRenderer->ResetCamera(); m_ImageRenderer->InteractiveOff(); m_ImageRenderer->GetActiveCamera()->ParallelProjectionOn(); if(m_ParallelScale == 0) m_ImageRenderer->GetActiveCamera()->SetParallelScale(m_ImageHeight/2); //m_SizeCallback->SetVtkVideoRenderer(m_ImageRenderer); //m_SizeCallback->SetVideoDimensions(m_ImageWidth, m_ImageHeight); } /** * Disables drawing of the color Video background. * If you want to enable it, call the Enable() function. */ void mitk::ImageBackground2D::Disable() { if ( this->IsEnabled() ) mitk::VtkLayerController::GetInstance(m_RenderWindow)->RemoveRenderer(m_ImageRenderer); } /** * Checks, if the Video background is currently * enabled (visible) */ bool mitk::ImageBackground2D::IsEnabled() { if ( mitk::VtkLayerController::GetInstance(m_RenderWindow)->IsRendererInserted(m_ImageRenderer)) return true; else return false; } void mitk::ImageBackground2D::Update(char * dataPointer) { if(!IsEnabled()) return; // VTK import image data must be allocated before import (with correct parameters) if(m_ImageData == NULL) m_ImageData = new unsigned char[m_ImageHeight*m_ImageWidth*m_ImageScalarComponents]; if(!dataPointer) {// no valid image pointer provided -> initialize black image unsigned char* b = m_ImageData; for ( int textCounter = 0; textCounter < (m_ImageHeight*m_ImageWidth*m_ImageScalarComponents); textCounter++ ) *b++ = 0; } m_VtkImageImport->SetImportVoidPointer(m_ImageData); m_VtkImageImport->Modified(); m_VtkImageImport->Update(); m_RenderWindow->Render(); } void mitk::ImageBackground2D::Update(char * dataPointer, int width, int height, int imageScalarComponents) { // no image-backround layer is rendered if(!IsEnabled()) return; // image contains no data, OR image scalar components missmatch (no RGB, no greyscale) if(!dataPointer || (imageScalarComponents != 1 && imageScalarComponents != 3)) { // no valid image pointer provided -> we initialize black image if(m_ImageData == NULL) m_ImageData = new unsigned char[m_ImageHeight*m_ImageWidth*m_ImageScalarComponents]; unsigned char* b = m_ImageData; for ( int textCounter = 0; textCounter < (m_ImageHeight*m_ImageWidth*m_ImageScalarComponents); textCounter++ ) *b++ = 0; } else { if(m_ImageWidth == 0) { // VTK Image Import has to be initialized properly m_ImageHeight = height; m_ImageWidth = width; m_ImageScalarComponents = imageScalarComponents; InitVtkImageImport(); } // VTK import image data must be allocated before import (with correct parameters) if(m_ImageData == NULL) m_ImageData = new unsigned char[m_ImageHeight*m_ImageWidth*m_ImageScalarComponents]; int column, row; unsigned char* tex = m_ImageData; char* data = dataPointer; // PREPARE image Data for VTKImageImport Filter // if(imageScalarComponents == 1) { m_VtkImageImport->SetNumberOfScalarComponents(m_ImageScalarComponents); unsigned char g; for (column = 0; column < m_ImageHeight; column++) for (row = 0; row < m_ImageWidth; row++) { g = *data++; *tex++ = g; } } else if(imageScalarComponents == 3) { // flip image, change color channels unsigned char r, g, b; for (column = 0; column < m_ImageHeight; column++) for (row = 0; row < m_ImageWidth; row++) { //change r with b b = *data++; g = *data++; r = *data++; *tex++ = r; *tex++ = g; *tex++ = b; } } // else if(imageScalarComponents == 3) } // end else image data present // Initialize VTK-ImageImport Filter // m_VtkImageImport->SetImportVoidPointer(m_ImageData); m_VtkImageImport->Modified(); m_VtkImageImport->Update(); m_RenderWindow->Render(); } diff --git a/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp index 3615b86be2..40e71bfbeb 100644 --- a/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp @@ -1,237 +1,237 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMeshVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkVtkPropRenderer.h" #ifndef VCL_VC60 #include "mitkMeshUtil.h" #endif #include #include #include #include #include #include #include #include #include const mitk::Mesh* mitk::MeshVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } vtkProp* mitk::MeshVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_PropAssembly; } void mitk::MeshVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); m_SpheresActor->SetUserTransform(vtktransform); m_ContourActor->SetUserTransform(vtktransform); } mitk::MeshVtkMapper3D::MeshVtkMapper3D() : m_PropAssembly(NULL) { m_Spheres = vtkAppendPolyData::New(); m_Contour = vtkPolyData::New(); m_SpheresActor = vtkActor::New(); m_SpheresMapper = vtkPolyDataMapper::New(); m_SpheresActor->SetMapper(m_SpheresMapper); m_ContourActor = vtkActor::New(); m_ContourMapper = vtkPolyDataMapper::New(); m_ContourActor->SetMapper(m_ContourMapper); m_ContourActor->GetProperty()->SetAmbient(1.0); m_PropAssembly = vtkPropAssembly::New(); // a vtkPropAssembly is not a sub-class of vtkProp3D, so // we cannot use m_Prop3D. } mitk::MeshVtkMapper3D::~MeshVtkMapper3D() { m_ContourActor->Delete(); m_SpheresActor->Delete(); m_ContourMapper->Delete(); m_SpheresMapper->Delete(); m_PropAssembly->Delete(); m_Spheres->Delete(); m_Contour->Delete(); } void mitk::MeshVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); if(needGenerateData) { ls->UpdateGenerateDataTime(); m_PropAssembly->VisibilityOn(); if(m_PropAssembly->GetParts()->IsItemPresent(m_SpheresActor)) m_PropAssembly->RemovePart(m_SpheresActor); if(m_PropAssembly->GetParts()->IsItemPresent(m_ContourActor)) m_PropAssembly->RemovePart(m_ContourActor); m_Spheres->RemoveAllInputs(); m_Contour->Initialize(); mitk::Mesh::Pointer input = const_cast(this->GetInput()); input->Update(); mitk::Mesh::DataType::Pointer itkMesh = input->GetMesh( this->GetTimestep() ); if ( itkMesh.GetPointer() == NULL) { m_PropAssembly->VisibilityOff(); return; } mitk::Mesh::PointsContainer::Iterator i; int j; float floatRgba[4] = {1.0f,1.0f,1.0f,1.0f}; double doubleRgba[4]={1.0f,1.0f,1.0f,1.0f}; mitk::Color tmpColor; // check for color prop and use it for rendering if it exists m_DataNode->GetColor(floatRgba, NULL); if (dynamic_cast(this->GetDataNode()->GetProperty("unselectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetProperty("unselectedcolor"))->GetValue(); floatRgba[0] = tmpColor[0]; floatRgba[1] = tmpColor[1]; floatRgba[2] = tmpColor[2]; floatRgba[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value doubleRgba[0] = floatRgba[0]; doubleRgba[1] = floatRgba[1]; doubleRgba[2] = floatRgba[2]; doubleRgba[3] = floatRgba[3]; } if(itkMesh->GetNumberOfPoints()>0) { // build m_Spheres->GetOutput() vtkPolyData float pointSize = 2.0; mitk::FloatProperty::Pointer pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); if (pointSizeProp.IsNotNull()) pointSize = pointSizeProp->GetValue(); for (j=0, i=itkMesh->GetPoints()->Begin(); i!=itkMesh->GetPoints()->End() ; i++,j++) { vtkSphereSource *sphere = vtkSphereSource::New(); sphere->SetRadius(pointSize); sphere->SetCenter(i.Value()[0],i.Value()[1],i.Value()[2]); - m_Spheres->AddInput(sphere->GetOutput()); + m_Spheres->AddInputData(sphere->GetOutput()); sphere->Delete(); } // setup mapper, actor and add to assembly - m_SpheresMapper->SetInput(m_Spheres->GetOutput()); + m_SpheresMapper->SetInputData(m_Spheres->GetOutput()); m_SpheresActor->GetProperty()->SetColor(doubleRgba); m_PropAssembly->AddPart(m_SpheresActor); } if(itkMesh->GetNumberOfCells()>0) { // build m_Contour vtkPolyData #ifdef VCL_VC60 itkExceptionMacro(<<"MeshVtkMapper3D currently not working for MS Visual C++ 6.0, because MeshUtils are currently not supported."); #else m_Contour = MeshUtil::MeshToPolyData(itkMesh.GetPointer(), false, false, 0, NULL, m_Contour); #endif if(m_Contour->GetNumberOfCells()>0) { // setup mapper, actor and add to assembly - m_ContourMapper->SetInput(m_Contour); + m_ContourMapper->SetInputData(m_Contour); bool wireframe=true; GetDataNode()->GetVisibility(wireframe, NULL, "wireframe"); if(wireframe) m_ContourActor->GetProperty()->SetRepresentationToWireframe(); else m_ContourActor->GetProperty()->SetRepresentationToSurface(); m_ContourActor->GetProperty()->SetColor(doubleRgba); m_PropAssembly->AddPart(m_ContourActor); } } } SetVtkMapperImmediateModeRendering(m_ContourMapper); SetVtkMapperImmediateModeRendering(m_SpheresMapper); bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) { m_SpheresActor->VisibilityOff(); m_ContourActor->VisibilityOff(); return; } bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour); if (makeContour) { m_ContourActor->VisibilityOn(); } else { m_ContourActor->VisibilityOff(); } bool showPoints = true; this->GetDataNode()->GetBoolProperty("show points", showPoints); if(showPoints) { m_SpheresActor->VisibilityOn(); } else { m_SpheresActor->VisibilityOff(); } } void mitk::MeshVtkMapper3D::ResetMapper( BaseRenderer* /*renderer*/ ) { m_PropAssembly->VisibilityOff(); } diff --git a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp index 9723e63bf8..d72cae0754 100644 --- a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp @@ -1,231 +1,231 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSplineVtkMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::SplineVtkMapper3D::SplineVtkMapper3D() : m_SplinesAvailable (false), m_SplinesAddedToAssembly(false) { m_SplinesActor = vtkActor::New(); m_SplineAssembly = vtkPropAssembly::New(); m_SplineResolution = 500; } mitk::SplineVtkMapper3D::~SplineVtkMapper3D() { m_SplinesActor->Delete(); m_SplineAssembly->Delete(); } vtkProp* mitk::SplineVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_SplineAssembly; } void mitk::SplineVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); m_SplinesActor->SetUserTransform(vtktransform); } void mitk::SplineVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); // only update spline if UpdateSpline has not been called from // external, e.g. by the SplineMapper2D. But call it the first time when m_SplineUpdateTime = 0 and m_LastUpdateTime = 0. if ( m_SplineUpdateTime < ls->GetLastGenerateDataTime() || m_SplineUpdateTime == 0) { this->UpdateSpline(); this->ApplyAllProperties(renderer, m_SplinesActor); } if ( m_SplinesAvailable ) { if ( ! m_SplinesAddedToAssembly ) { m_SplineAssembly->AddPart( m_SplinesActor ); m_SplinesAddedToAssembly = true; } } else { if ( m_SplinesAddedToAssembly ) { m_SplineAssembly->RemovePart( m_SplinesActor ); m_SplinesAddedToAssembly = false; } } bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) { m_SplinesActor->VisibilityOff(); m_SplineAssembly->VisibilityOff(); } else { m_SplinesActor->VisibilityOn(); m_SplineAssembly->VisibilityOn(); //remove the PointsAssembly if it was added in superclass. No need to display points and spline! if(m_SplineAssembly->GetParts()->IsItemPresent(m_PointsAssembly)) m_SplineAssembly->RemovePart(m_PointsAssembly); } //if the properties have been changed, then refresh the properties if ( (m_SplineUpdateTime < this->m_DataNode->GetPropertyList()->GetMTime() ) || (m_SplineUpdateTime < this->m_DataNode->GetPropertyList(renderer)->GetMTime() ) ) this->ApplyAllProperties(renderer, m_SplinesActor); } void mitk::SplineVtkMapper3D::ApplyAllProperties(BaseRenderer *renderer, vtkActor *actor) { Superclass::ApplyColorAndOpacityProperties(renderer, actor); //vtk changed the type of rgba during releases. Due to that, the following convert is done double rgba[ 4 ] = {1.0f, 1.0f, 1.0f, 1.0f};//white //getting the color from DataNode float temprgba[4]; this->GetDataNode()->GetColor( &temprgba[0], NULL ); //convert to rgba, what ever type it has! rgba[0] = temprgba[0]; rgba[1] = temprgba[1]; rgba[2] = temprgba[2]; rgba[3] = temprgba[3]; //finaly set the color inside the actor m_SplinesActor->GetProperty()->SetColor( rgba ); float lineWidth; if (dynamic_cast(this->GetDataNode()->GetProperty("line width")) == NULL) lineWidth = 1.0; else lineWidth = dynamic_cast(this->GetDataNode()->GetProperty("line width"))->GetValue(); m_SplinesActor->GetProperty()->SetLineWidth(lineWidth); m_SplineUpdateTime.Modified(); } bool mitk::SplineVtkMapper3D::SplinesAreAvailable() { return m_SplinesAvailable; } vtkPolyData* mitk::SplineVtkMapper3D::GetSplinesPolyData() { if ( m_SplinesAvailable ) return ( dynamic_cast( m_SplinesActor->GetMapper() ) )->GetInput(); else return NULL; } vtkActor* mitk::SplineVtkMapper3D::GetSplinesActor() { if ( m_SplinesAvailable ) return m_SplinesActor; else return vtkActor::New(); } void mitk::SplineVtkMapper3D::UpdateSpline() { mitk::PointSet::Pointer input = const_cast( this->GetInput( ) ); // input->Update();//already done in superclass // Number of points on the spline unsigned int numberOfOutputPoints = m_SplineResolution; unsigned int numberOfInputPoints = input->GetSize(); if ( numberOfInputPoints >= 2 ) { m_SplinesAvailable = true; vtkCardinalSpline* splineX = vtkCardinalSpline::New(); vtkCardinalSpline* splineY = vtkCardinalSpline::New(); vtkCardinalSpline* splineZ = vtkCardinalSpline::New(); unsigned int index = 0; mitk::PointSet::DataType::PointsContainer::Pointer pointsContainer = input->GetPointSet()->GetPoints(); for ( mitk::PointSet::DataType::PointsContainer::Iterator it = pointsContainer->Begin(); it != pointsContainer->End(); ++it, ++index ) //for ( unsigned int i = 0 ; i < numberOfInputPoints; ++i ) { mitk::PointSet::PointType point = it->Value(); splineX->AddPoint( index, point[ 0 ] ); splineY->AddPoint( index, point[ 1 ] ); splineZ->AddPoint( index, point[ 2 ] ); } vtkPoints* points = vtkPoints::New(); vtkPolyData* profileData = vtkPolyData::New(); // Interpolate x, y and z by using the three spline filters and // create new points double t = 0.0f; for ( unsigned int i = 0; i < numberOfOutputPoints; ++i ) { t = ( ( ( ( double ) numberOfInputPoints ) - 1.0f ) / ( ( ( double ) numberOfOutputPoints ) - 1.0f ) ) * ( ( double ) i ); points->InsertPoint( i, splineX->Evaluate( t ), splineY->Evaluate( t ), splineZ->Evaluate( t ) ) ; } // Create the polyline. vtkCellArray* lines = vtkCellArray::New(); lines->InsertNextCell( numberOfOutputPoints ); for ( unsigned int i = 0; i < numberOfOutputPoints; ++i ) lines->InsertCellPoint( i ); profileData->SetPoints( points ); profileData->SetLines( lines ); // Add thickness to the resulting line. //vtkTubeFilter* profileTubes = vtkTubeFilter::New(); //profileTubes->SetNumberOfSides(8); //profileTubes->SetInput(profileData); //profileTubes->SetRadius(.005); vtkPolyDataMapper* profileMapper = vtkPolyDataMapper::New(); - profileMapper->SetInput( profileData ); + profileMapper->SetInputData( profileData ); m_SplinesActor->SetMapper( profileMapper ); } else { m_SplinesAvailable = false; } m_SplineUpdateTime.Modified(); } diff --git a/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp b/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp index adfc70113f..4cdfa1ae4d 100644 --- a/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp @@ -1,575 +1,575 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkUnstructuredGridMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkUnstructuredGrid.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkColorProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkProperties.h" #include "mitkAbstractTransformGeometry.h" #include "mitkVtkMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void mitk::UnstructuredGridMapper2D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); if(needGenerateData) { ls->UpdateGenerateDataTime(); mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return; if (!node->GetProperty(m_ScalarMode, "scalar mode")) { m_ScalarMode = mitk::VtkScalarModeProperty::New(0); } if (!node->GetProperty(m_ScalarVisibility, "scalar visibility")) { m_ScalarVisibility = mitk::BoolProperty::New(true); } if (!node->GetProperty(m_Outline, "outline polygons")) { m_Outline = mitk::BoolProperty::New(false); } if (!node->GetProperty(m_Color, "color")) { m_Color = mitk::ColorProperty::New(1.0f, 1.0f, 1.0f); } if (!node->GetProperty(m_LineWidth, "line width")) { m_LineWidth = mitk::IntProperty::New(1); } } mitk::BaseData::Pointer input = const_cast( GetDataNode()->GetData() ); assert( input ); input->Update(); if (m_VtkPointSet) m_VtkPointSet->UnRegister(0); m_VtkPointSet = this->GetVtkPointSet(renderer); assert(m_VtkPointSet); m_VtkPointSet->Register(0); if (m_ScalarVisibility->GetValue()) { mitk::DataNode::ConstPointer node = this->GetDataNode(); mitk::TransferFunctionProperty::Pointer transferFuncProp; node->GetProperty(transferFuncProp, "TransferFunction", renderer); if (transferFuncProp.IsNotNull()) { mitk::TransferFunction::Pointer tf = transferFuncProp->GetValue(); if (m_ScalarsToColors) m_ScalarsToColors->UnRegister(0); m_ScalarsToColors = static_cast(tf->GetColorTransferFunction()); m_ScalarsToColors->Register(0); if (m_ScalarsToOpacity) m_ScalarsToOpacity->UnRegister(0); m_ScalarsToOpacity = tf->GetScalarOpacityFunction(); m_ScalarsToOpacity->Register(0); } else { if (m_ScalarsToColors) m_ScalarsToColors->UnRegister(0); m_ScalarsToColors = this->GetVtkLUT(renderer); assert(m_ScalarsToColors); m_ScalarsToColors->Register(0); float opacity; node->GetOpacity(opacity, renderer); if (m_ScalarsToOpacity) m_ScalarsToOpacity->UnRegister(0); m_ScalarsToOpacity = vtkPiecewiseFunction::New(); double range[2]; m_VtkPointSet->GetScalarRange(range); m_ScalarsToOpacity->AddSegment(range[0], opacity, range[1], opacity); } } } void mitk::UnstructuredGridMapper2D::Paint( mitk::BaseRenderer* renderer ) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) return; vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(); vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); Point3D point; Vector3D normal; if(worldPlaneGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=worldPlaneGeometry->GetOrigin(); normal=worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform((vtkAbstractTransform*)NULL); } else { //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "plane plane" into a "curved plane"? return; AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); if(worldAbstractGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=const_cast(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum(); FillVector3D(normal, 0, 0, 1); m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse()); } else return; } double vp[ 3 ], vnormal[ 3 ]; vnl2vtk(point.Get_vnl_vector(), vp); vnl2vtk(normal.Get_vnl_vector(), vnormal); //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. inversetransform->TransformPoint( vp, vp ); inversetransform->TransformNormalAtPoint( vp, vnormal, vnormal ); m_Plane->SetOrigin( vp ); m_Plane->SetNormal( vnormal ); // set data into cutter - m_Slicer->SetInput( m_VtkPointSet ); + m_Slicer->SetInputData( m_VtkPointSet ); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); // calculate the cut m_Slicer->Update(); // fetch geometry mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert( displayGeometry ); // float toGL=displayGeometry->GetSizeInDisplayUnits()[1]; //apply color and opacity read from the PropertyList ApplyColorAndOpacityProperties( renderer ); // traverse the cut contour vtkPolyData * contour = m_Slicer->GetOutput(); vtkPoints *vpoints = contour->GetPoints(); vtkCellArray *vlines = contour->GetLines(); vtkCellArray *vpolys = contour->GetPolys(); vtkPointData *vpointdata = contour->GetPointData(); vtkDataArray* vscalars = vpointdata->GetScalars(); vtkCellData *vcelldata = contour->GetCellData(); vtkDataArray* vcellscalars = vcelldata->GetScalars(); const int numberOfLines = contour->GetNumberOfLines(); const int numberOfPolys = contour->GetNumberOfPolys(); const bool useCellData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT || m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA; const bool usePointData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA; Point3D p; Point2D p2d; vlines->InitTraversal(); vpolys->InitTraversal(); mitk::Color outlineColor = m_Color->GetColor(); glLineWidth((float)m_LineWidth->GetValue()); for (int i = 0;i < numberOfLines;++i ) { vtkIdType *cell(0); vtkIdType cellSize(0); vlines->GetNextCell( cellSize, cell ); float rgba[4] = {outlineColor[0], outlineColor[1], outlineColor[2], 1.0f}; if (m_ScalarVisibility->GetValue() && vcellscalars) { if ( useCellData ) { // color each cell according to cell data double scalar = vcellscalars->GetComponent( i, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } else if ( usePointData ) { double scalar = vscalars->GetComponent( i, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } } glColor4fv( rgba ); glBegin ( GL_LINE_LOOP ); for ( int j = 0;j < cellSize;++j ) { vpoints->GetPoint( cell[ j ], vp ); //take transformation via vtktransform into account vtktransform->TransformPoint( vp, vp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); //convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left ) //p2d[1]=toGL-p2d[1]; //add the current vertex to the line glVertex2f( p2d[0], p2d[1] ); } glEnd (); } bool polyOutline = m_Outline->GetValue(); bool scalarVisibility = m_ScalarVisibility->GetValue(); // cache the transformed points // a fixed size array is way faster than 'new' // slices through 3d cells usually do not generated // polygons with more than 6 vertices const int maxPolySize = 10; Point2D* cachedPoints = new Point2D[maxPolySize*numberOfPolys]; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only draw polygons if there are cell scalars // or the outline property is set to true if (scalarVisibility && vcellscalars) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); for (int i = 0;i < numberOfPolys;++i ) { vtkIdType *cell(0); vtkIdType cellSize(0); vpolys->GetNextCell( cellSize, cell ); float rgba[4] = {1.0f, 1.0f, 1.0f, 0}; if (scalarVisibility && vcellscalars) { if ( useCellData ) { // color each cell according to cell data double scalar = vcellscalars->GetComponent( i+numberOfLines, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } else if ( usePointData ) { double scalar = vscalars->GetComponent( i, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } } glColor4fv( rgba ); glBegin( GL_POLYGON ); for (int j = 0; j < cellSize; ++j) { vpoints->GetPoint( cell[ j ], vp ); //take transformation via vtktransform into account vtktransform->TransformPoint( vp, vp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); //convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left ) //p2d[1]=toGL-p2d[1]; cachedPoints[i*10+j][0] = p2d[0]; cachedPoints[i*10+j][1] = p2d[1]; //add the current vertex to the line glVertex2f( p2d[0], p2d[1] ); } glEnd(); } if (polyOutline) { vpolys->InitTraversal(); glColor4f(outlineColor[0], outlineColor[1], outlineColor[2], 1.0f); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for (int i = 0;i < numberOfPolys;++i) { vtkIdType *cell(0); vtkIdType cellSize(0); vpolys->GetNextCell( cellSize, cell ); glBegin( GL_POLYGON ); //glPolygonOffset(1.0, 1.0); for (int j = 0; j < cellSize; ++j) { //add the current vertex to the line glVertex2f( cachedPoints[i*10+j][0], cachedPoints[i*10+j][1] ); } glEnd(); } } } glDisable(GL_BLEND); delete cachedPoints; } vtkAbstractMapper3D* mitk::UnstructuredGridMapper2D ::GetVtkAbstractMapper3D(mitk::BaseRenderer * renderer) { //MITK_INFO << "GETVTKABSTRACTMAPPER3D\n"; mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return 0; mitk::VtkMapper::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper* > ( node->GetMapper( 2 ) ); if ( mitkMapper.IsNull() ) { return 0; } mitkMapper->Update(renderer); vtkAssembly* assembly = dynamic_cast(mitkMapper->GetVtkProp(renderer)); if (assembly) { vtkProp3DCollection* collection = assembly->GetParts(); collection->InitTraversal(); vtkProp3D* prop3d = 0; do { prop3d = collection->GetNextProp3D(); vtkActor* actor = dynamic_cast( prop3d ); if (actor) { return dynamic_cast( actor->GetMapper() ); } vtkVolume* volume = dynamic_cast( prop3d ); if (volume) { return dynamic_cast( volume->GetMapper() ); } } while (prop3d != collection->GetLastProp3D()); } else { vtkActor* actor = dynamic_cast( mitkMapper->GetVtkProp(renderer) ); if (actor) { return dynamic_cast( actor->GetMapper() ); } vtkVolume* volume = dynamic_cast( mitkMapper->GetVtkProp(renderer) ); if (volume) { return dynamic_cast( volume->GetMapper() ); } } return 0; } vtkPointSet* mitk::UnstructuredGridMapper2D ::GetVtkPointSet(mitk::BaseRenderer* renderer) { //MITK_INFO << "GETVTKPOINTSET\n"; vtkAbstractMapper3D * abstractMapper = GetVtkAbstractMapper3D(renderer); if ( abstractMapper == 0 ) { // try to get data from the node mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return 0; mitk::BaseData::Pointer data = node->GetData(); mitk::UnstructuredGrid::Pointer grid = dynamic_cast(data.GetPointer()); if (!grid.IsNull()) return static_cast(grid->GetVtkUnstructuredGrid()); return 0; } else { vtkMapper* mapper = dynamic_cast(abstractMapper); if (mapper) { return dynamic_cast(mapper->GetInput()); } vtkAbstractVolumeMapper* volMapper = dynamic_cast(abstractMapper); if (volMapper) { return dynamic_cast(volMapper->GetDataSetInput()); } } return 0; } vtkScalarsToColors* mitk::UnstructuredGridMapper2D::GetVtkLUT(mitk::BaseRenderer* renderer) { //MITK_INFO << "GETVTKLUT\n"; vtkMapper * mapper = dynamic_cast(GetVtkAbstractMapper3D(renderer)); if (mapper) return mapper->GetLookupTable(); else { mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return 0; mitk::VtkMapper::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper* > ( node->GetMapper( 2 ) ); if ( mitkMapper.IsNull() ) { //MITK_INFO << "mitkMapper is null\n"; return 0; } mitkMapper->Update(renderer); vtkVolume* volume = dynamic_cast( mitkMapper->GetVtkProp(renderer) ); if (volume) { //MITK_INFO << "found volume prop\n"; return static_cast(volume->GetProperty()->GetRGBTransferFunction()); } vtkAssembly* assembly = dynamic_cast(mitkMapper->GetVtkProp(renderer)); if (assembly) { //MITK_INFO << "found assembly prop\n"; mitk::TransferFunctionProperty::Pointer transferFuncProp; node->GetProperty(transferFuncProp, "TransferFunction", 0); if (transferFuncProp.IsNotNull()) { MITK_INFO << "return colortransferfunction\n"; return static_cast(transferFuncProp->GetValue()->GetColorTransferFunction()); } } return 0; } } bool mitk::UnstructuredGridMapper2D::IsConvertibleToVtkPointSet(mitk::BaseRenderer * renderer) { return ( GetVtkPointSet(renderer) != 0 ); } mitk::UnstructuredGridMapper2D::UnstructuredGridMapper2D() { m_Plane = vtkPlane::New(); m_Slicer = vtkPointSetSlicer::New(); m_Slicer->SetSlicePlane( m_Plane ); m_ScalarsToColors = 0; m_ScalarsToOpacity = 0; m_VtkPointSet = 0; //m_LUT = vtkLookupTable::New(); //m_LUT->SetTableRange( 0, 255 ); //m_LUT->SetNumberOfColors( 255 ); //m_LUT->SetRampToLinear (); //m_LUT->Build(); } mitk::UnstructuredGridMapper2D::~UnstructuredGridMapper2D() { m_Slicer->Delete(); m_Plane->Delete(); if (m_ScalarsToOpacity != 0) m_ScalarsToOpacity->UnRegister(0); if (m_ScalarsToColors != 0) m_ScalarsToColors->UnRegister(0); if (m_VtkPointSet != 0) m_VtkPointSet->UnRegister(0); } diff --git a/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp index fd8543fe08..f0e7de8bac 100644 --- a/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp @@ -1,425 +1,425 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUnstructuredGridVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkTransferFunctionProperty.h" #include "mitkColorProperty.h" //#include "mitkLookupTableProperty.h" #include "mitkGridRepresentationProperty.h" #include "mitkGridVolumeMapperProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkDataStorage.h" #include "mitkSurfaceVtkMapper3D.h" #include #include #include #include #include const mitk::UnstructuredGrid* mitk::UnstructuredGridVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } mitk::UnstructuredGridVtkMapper3D::UnstructuredGridVtkMapper3D() { m_VtkTriangleFilter = vtkDataSetTriangleFilter::New(); m_Assembly = vtkAssembly::New(); m_Volume = vtkVolume::New(); m_Actor = vtkActor::New(); m_ActorWireframe = vtkActor::New(); m_VtkDataSetMapper = vtkUnstructuredGridMapper::New(); m_VtkDataSetMapper->SetResolveCoincidentTopologyToPolygonOffset(); m_VtkDataSetMapper->SetResolveCoincidentTopologyPolygonOffsetParameters(0,1); m_Actor->SetMapper(m_VtkDataSetMapper); m_VtkDataSetMapper2 = vtkUnstructuredGridMapper::New(); m_VtkDataSetMapper2->SetResolveCoincidentTopologyToPolygonOffset(); m_VtkDataSetMapper2->SetResolveCoincidentTopologyPolygonOffsetParameters(1,1); m_ActorWireframe->SetMapper(m_VtkDataSetMapper2); m_ActorWireframe->GetProperty()->SetRepresentationToWireframe(); m_Assembly->AddPart(m_Actor); m_Assembly->AddPart(m_ActorWireframe); m_Assembly->AddPart(m_Volume); m_VtkVolumeRayCastMapper = 0; m_VtkPTMapper = 0; m_VtkVolumeZSweepMapper = 0; //m_GenerateNormals = false; } mitk::UnstructuredGridVtkMapper3D::~UnstructuredGridVtkMapper3D() { if (m_VtkTriangleFilter != 0) m_VtkTriangleFilter->Delete(); if (m_VtkVolumeRayCastMapper != 0) m_VtkVolumeRayCastMapper->Delete(); if (m_VtkVolumeZSweepMapper != 0) m_VtkVolumeZSweepMapper->Delete(); if (m_VtkPTMapper != 0) m_VtkPTMapper->Delete(); if (m_VtkDataSetMapper != 0) m_VtkDataSetMapper->Delete(); if (m_VtkDataSetMapper2 != 0) m_VtkDataSetMapper2->Delete(); if (m_Assembly != 0) m_Assembly->Delete(); if (m_Actor != 0) m_Actor->Delete(); if (m_ActorWireframe != 0) m_ActorWireframe->Delete(); if (m_Volume != 0) m_Volume->Delete(); } vtkProp* mitk::UnstructuredGridVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Assembly; } void mitk::UnstructuredGridVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { mitk::DataNode::ConstPointer node = this->GetDataNode(); BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); if(needGenerateData) { ls->UpdateGenerateDataTime(); m_Assembly->VisibilityOn(); m_ActorWireframe->GetProperty()->SetAmbient(1.0); m_ActorWireframe->GetProperty()->SetDiffuse(0.0); m_ActorWireframe->GetProperty()->SetSpecular(0.0); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction")) { mitk::TransferFunction::Pointer transferFunction = transferFuncProp->GetValue(); if (transferFunction->GetColorTransferFunction()->GetSize() < 2) { mitk::UnstructuredGrid::Pointer input = const_cast< mitk::UnstructuredGrid* >(this->GetInput()); if (input.IsNull()) return; vtkUnstructuredGrid * grid = input->GetVtkUnstructuredGrid(this->GetTimestep()); if (grid == 0) return; double* scalarRange = grid->GetScalarRange(); vtkColorTransferFunction* colorFunc = transferFunction->GetColorTransferFunction(); colorFunc->RemoveAllPoints(); colorFunc->AddRGBPoint(scalarRange[0], 1, 0, 0); colorFunc->AddRGBPoint((scalarRange[0] + scalarRange[1])/2.0, 0, 1, 0); colorFunc->AddRGBPoint(scalarRange[1], 0, 0, 1); } } } bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) { m_Assembly->VisibilityOff(); return; } // // get the TimeGeometry of the input object // mitk::UnstructuredGrid::Pointer input = const_cast< mitk::UnstructuredGrid* >( this->GetInput() ); // // set the input-object at time t for the mapper // vtkUnstructuredGrid * grid = input->GetVtkUnstructuredGrid( this->GetTimestep() ); if(grid == 0) { m_Assembly->VisibilityOff(); return; } m_Assembly->VisibilityOn(); - m_VtkTriangleFilter->SetInput(grid); + m_VtkTriangleFilter->SetInputData(grid); m_VtkDataSetMapper->SetInput(grid); m_VtkDataSetMapper2->SetInput(grid); bool clip = false; node->GetBoolProperty("enable clipping", clip); mitk::DataNode::Pointer bbNode = renderer->GetDataStorage()->GetNamedDerivedNode("Clipping Bounding Object", node); if (clip && bbNode.IsNotNull()) { m_VtkDataSetMapper->SetBoundingObject(dynamic_cast(bbNode->GetData())); m_VtkDataSetMapper2->SetBoundingObject(dynamic_cast(bbNode->GetData())); } else { m_VtkDataSetMapper->SetBoundingObject(0); m_VtkDataSetMapper2->SetBoundingObject(0); } // // apply properties read from the PropertyList // ApplyProperties(0, renderer); } void mitk::UnstructuredGridVtkMapper3D::ResetMapper( BaseRenderer* /*renderer*/ ) { m_Assembly->VisibilityOff(); } void mitk::UnstructuredGridVtkMapper3D::ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* renderer) { mitk::DataNode::Pointer node = this->GetDataNode(); ApplyColorAndOpacityProperties(renderer, m_Actor); ApplyColorAndOpacityProperties(renderer, m_ActorWireframe); vtkVolumeProperty* volProp = m_Volume->GetProperty(); vtkProperty* property = m_Actor->GetProperty(); vtkProperty* wireframeProp = m_ActorWireframe->GetProperty(); mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(node,property,renderer); mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(node,wireframeProp,renderer); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction", renderer)) { mitk::TransferFunction::Pointer transferFunction = transferFuncProp->GetValue(); volProp->SetColor(transferFunction->GetColorTransferFunction()); volProp->SetScalarOpacity(transferFunction->GetScalarOpacityFunction()); volProp->SetGradientOpacity(transferFunction->GetGradientOpacityFunction()); m_VtkDataSetMapper->SetLookupTable(transferFunction->GetColorTransferFunction()); m_VtkDataSetMapper2->SetLookupTable(transferFunction->GetColorTransferFunction()); } bool isVolumeRenderingOn = false; node->GetBoolProperty("volumerendering", isVolumeRenderingOn, renderer); if (isVolumeRenderingOn) { m_Assembly->RemovePart(m_Actor); m_Assembly->RemovePart(m_ActorWireframe); m_Assembly->AddPart(m_Volume); mitk::GridVolumeMapperProperty::Pointer mapperProp; if (node->GetProperty(mapperProp, "volumerendering.mapper", renderer)) { mitk::GridVolumeMapperProperty::IdType type = mapperProp->GetValueAsId(); switch (type) { case mitk::GridVolumeMapperProperty::RAYCAST: if (m_VtkVolumeRayCastMapper == 0) { m_VtkVolumeRayCastMapper = vtkUnstructuredGridVolumeRayCastMapper::New(); - m_VtkVolumeRayCastMapper->SetInput(m_VtkTriangleFilter->GetOutput()); + m_VtkVolumeRayCastMapper->SetInputData(m_VtkTriangleFilter->GetOutput()); } m_Volume->SetMapper(m_VtkVolumeRayCastMapper); break; case mitk::GridVolumeMapperProperty::PT: if (m_VtkPTMapper == 0) { m_VtkPTMapper = vtkProjectedTetrahedraMapper::New(); m_VtkPTMapper->SetInputConnection(m_VtkTriangleFilter->GetOutputPort()); } m_Volume->SetMapper(m_VtkPTMapper); break; case mitk::GridVolumeMapperProperty::ZSWEEP: if (m_VtkVolumeZSweepMapper == 0) { m_VtkVolumeZSweepMapper = vtkUnstructuredGridVolumeZSweepMapper::New(); m_VtkVolumeZSweepMapper->SetInputConnection(m_VtkTriangleFilter->GetOutputPort()); } m_Volume->SetMapper(m_VtkVolumeZSweepMapper); break; } } } else { m_Assembly->RemovePart(m_Volume); m_Assembly->AddPart(m_Actor); m_Assembly->RemovePart(m_ActorWireframe); mitk::GridRepresentationProperty::Pointer gridRepProp; if (node->GetProperty(gridRepProp, "grid representation", renderer)) { mitk::GridRepresentationProperty::IdType type = gridRepProp->GetValueAsId(); switch (type) { case mitk::GridRepresentationProperty::POINTS: property->SetRepresentationToPoints(); break; case mitk::GridRepresentationProperty::WIREFRAME: property->SetRepresentationToWireframe(); break; case mitk::GridRepresentationProperty::SURFACE: property->SetRepresentationToSurface(); break; } // if (type == mitk::GridRepresentationProperty::WIREFRAME_SURFACE) // { // m_Assembly->AddPart(m_ActorWireframe); // } } } // mitk::LevelWindow levelWindow; // if(node->GetLevelWindow(levelWindow, renderer, "levelWindow")) // { // m_VtkVolumeRayCastMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax()); // } // else // if(node->GetLevelWindow(levelWindow, renderer)) // { // m_VtkVolumeRayCastMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax()); // } // // mitk::VtkRepresentationProperty* representationProperty; // node->GetProperty(representationProperty, "material.representation", renderer); // if ( representationProperty != NULL ) // m_Volume->GetProperty()->SetRepresentation( representationProperty->GetVtkRepresentation() ); // // mitk::VtkInterpolationProperty* interpolationProperty; // node->GetProperty(interpolationProperty, "material.interpolation", renderer); // if ( interpolationProperty != NULL ) // m_Volume->GetProperty()->SetInterpolation( interpolationProperty->GetVtkInterpolation() ); // mitk::VtkScalarModeProperty* scalarMode = 0; if(node->GetProperty(scalarMode, "scalar mode", renderer)) { if (m_VtkVolumeRayCastMapper) m_VtkVolumeRayCastMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); if (m_VtkPTMapper) m_VtkPTMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); if (m_VtkVolumeZSweepMapper) m_VtkVolumeZSweepMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); m_VtkDataSetMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); m_VtkDataSetMapper2->SetScalarMode(scalarMode->GetVtkScalarMode()); } else { if (m_VtkVolumeRayCastMapper) m_VtkVolumeRayCastMapper->SetScalarModeToDefault(); if (m_VtkPTMapper) m_VtkPTMapper->SetScalarModeToDefault(); if (m_VtkVolumeZSweepMapper) m_VtkVolumeZSweepMapper->SetScalarModeToDefault(); m_VtkDataSetMapper->SetScalarModeToDefault(); m_VtkDataSetMapper2->SetScalarModeToDefault(); } bool scalarVisibility = true; node->GetBoolProperty("scalar visibility", scalarVisibility, renderer); m_VtkDataSetMapper->SetScalarVisibility(scalarVisibility ? 1 : 0); m_VtkDataSetMapper2->SetScalarVisibility(scalarVisibility ? 1 : 0); // double scalarRangeLower = std::numeric_limits::min(); // double scalarRangeUpper = std::numeric_limits::max(); // mitk::DoubleProperty* lowerRange = 0; // if (node->GetProperty(lowerRange, "scalar range min", renderer)) // { // scalarRangeLower = lowerRange->GetValue(); // } // mitk::DoubleProperty* upperRange = 0; // if (node->GetProperty(upperRange, "scalar range max", renderer)) // { // scalarRangeUpper = upperRange->GetValue(); // } // m_VtkDataSetMapper->SetScalarRange(scalarRangeLower, scalarRangeUpper); // m_VtkDataSetMapper2->SetScalarRange(scalarRangeLower, scalarRangeUpper); // bool colorMode = false; // node->GetBoolProperty("color mode", colorMode); // m_VtkVolumeRayCastMapper->SetColorMode( (colorMode ? 1 : 0) ); // float scalarsMin = 0; // if (dynamic_cast(node->GetProperty("ScalarsRangeMinimum").GetPointer()) != NULL) // scalarsMin = dynamic_cast(node->GetProperty("ScalarsRangeMinimum").GetPointer())->GetValue(); // float scalarsMax = 1.0; // if (dynamic_cast(node->GetProperty("ScalarsRangeMaximum").GetPointer()) != NULL) // scalarsMax = dynamic_cast(node->GetProperty("ScalarsRangeMaximum").GetPointer())->GetValue(); // m_VtkVolumeRayCastMapper->SetScalarRange(scalarsMin,scalarsMax); } void mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(node, renderer, overwrite); node->AddProperty("grid representation", GridRepresentationProperty::New(), renderer, overwrite); node->AddProperty("volumerendering", BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.mapper", GridVolumeMapperProperty::New(), renderer, overwrite); node->AddProperty("scalar mode", VtkScalarModeProperty::New(0), renderer, overwrite); node->AddProperty("scalar visibility", BoolProperty::New(true), renderer, overwrite); //node->AddProperty("scalar range min", DoubleProperty::New(std::numeric_limits::min()), renderer, overwrite); //node->AddProperty("scalar range max", DoubleProperty::New(std::numeric_limits::max()), renderer, overwrite); node->AddProperty("outline polygons", BoolProperty::New(false), renderer, overwrite); node->AddProperty("color", ColorProperty::New(1.0f, 1.0f, 1.0f), renderer, overwrite); node->AddProperty("line width", IntProperty::New(1), renderer, overwrite); if(overwrite || node->GetProperty("TransferFunction", renderer) == 0) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); //tf->GetColorTransferFunction()->RemoveAllPoints(); node->SetProperty ("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); } Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp index 7592f714a5..ea2fe42436 100644 --- a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp @@ -1,538 +1,537 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVectorImageMapper2D.h" //vtk related includes #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //mitk related includes #include "mitkGL.h" #include "mitkBaseRenderer.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkAbstractTransformGeometry.h" #include const mitk::Image * mitk::VectorImageMapper2D::GetInput( void ) { if ( m_Image.IsNotNull() ) return m_Image; else return dynamic_cast( GetDataNode()->GetData() ); } void mitk::VectorImageMapper2D::Paint( mitk::BaseRenderer * renderer ) { //std::cout << "2d vector mapping..." << std::endl; bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return ; mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; mitk::PlaneGeometry::Pointer worldPlaneGeometry2D = dynamic_cast< mitk::PlaneGeometry*>( const_cast( renderer->GetCurrentWorldGeometry2D() ) ); assert( worldPlaneGeometry2D.IsNotNull() ); vtkImageData* vtkImage = input->GetVtkImageData( this->GetCurrentTimeStep( input, renderer ) ); // // set up the cutter orientation according to the current geometry of // the renderers plane // Point3D point; Vector3D normal; Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); if ( worldPlaneGeometry.IsNotNull() ) { // set up vtkPlane according to worldGeometry point = worldPlaneGeometry->GetOrigin(); normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform( (vtkAbstractTransform*)NULL ); } else { itkWarningMacro( << "worldPlaneGeometry is NULL!" ); return ; } double vp[ 3 ], vp_slice[ 3 ], vnormal[ 3 ]; vnl2vtk( point.Get_vnl_vector(), vp ); vnl2vtk( normal.Get_vnl_vector(), vnormal ); //std::cout << "Origin: " << vp[0] <<" "<< vp[1] <<" "<< vp[2] << std::endl; //std::cout << "Normal: " << vnormal[0] <<" "<< vnormal[1] <<" "<< vnormal[2] << std::endl; //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. vtkLinearTransform * vtktransform = GetDataNode() ->GetVtkTransform(); vtkTransform* world2vtk = vtkTransform::New(); world2vtk->Identity(); world2vtk->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; world2vtk->GetScale(myscale); world2vtk->PostMultiply(); world2vtk->Scale(1/myscale[0],1/myscale[1],1/myscale[2]); world2vtk->TransformPoint( vp, vp ); world2vtk->TransformNormalAtPoint( vp, vnormal, vnormal ); world2vtk->Delete(); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; vtkImage->GetDimensions(dims); double spac[3]; vtkImage->GetSpacing(spac); vp_slice[0] = vp[0]; vp_slice[1] = vp[1]; vp_slice[2] = vp[2]; if(fabs(vnormal[0]) > fabs(vnormal[1]) && fabs(vnormal[0]) > fabs(vnormal[2]) ) { if(fabs(vp_slice[0]/spac[0]) < 0.4) vp_slice[0] = 0.4*spac[0]; if(fabs(vp_slice[0]/spac[0]) > (dims[0]-1)-0.4) vp_slice[0] = ((dims[0]-1)-0.4)*spac[0]; vnormal[1] = 0; vnormal[2] = 0; } if(fabs(vnormal[1]) > fabs(vnormal[0]) && fabs(vnormal[1]) > fabs(vnormal[2]) ) { if(fabs(vp_slice[1]/spac[1]) < 0.4) vp_slice[1] = 0.4*spac[1]; if(fabs(vp_slice[1]/spac[1]) > (dims[1]-1)-0.4) vp_slice[1] = ((dims[1]-1)-0.4)*spac[1]; vnormal[0] = 0; vnormal[2] = 0; } if(fabs(vnormal[2]) > fabs(vnormal[1]) && fabs(vnormal[2]) > fabs(vnormal[0]) ) { if(fabs(vp_slice[2]/spac[2]) < 0.4) vp_slice[2] = 0.4*spac[2]; if(fabs(vp_slice[2]/spac[2]) > (dims[2]-1)-0.4) vp_slice[2] = ((dims[2]-1)-0.4)*spac[2]; vnormal[0] = 0; vnormal[1] = 0; } m_Plane->SetOrigin( vp_slice ); m_Plane->SetNormal( vnormal ); vtkPolyData* cuttedPlane; if(!( (dims[0] == 1 && vnormal[0] != 0) || (dims[1] == 1 && vnormal[1] != 0) || (dims[2] == 1 && vnormal[2] != 0) )) { m_Cutter->SetCutFunction( m_Plane ); - m_Cutter->SetInput( vtkImage ); + m_Cutter->SetInputData( vtkImage ); m_Cutter->GenerateCutScalarsOff();//! m_Cutter->Update(); cuttedPlane = m_Cutter->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); vtkPoints* points = vtkPoints::New(); points->SetNumberOfPoints(vtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) points->SetPoint(i, vtkImage->GetPoint(i)); cuttedPlane->SetPoints(points); vtkFloatArray* pointdata = vtkFloatArray::New(); int comps = vtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = vtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,vtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); } if ( cuttedPlane->GetNumberOfPoints() != 0) { // // make sure, that we have point data with more than 1 component (as vectors) // vtkPointData * pointData = cuttedPlane->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "no point data associated with cutters result!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "point data returned by cutter doesn't have any arrays associated!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() <= 1) { itkWarningMacro( << "number of components <= 1!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { pointData->GetArray( 0 ) ->SetName( "vector" ); //std::cout << "array name = vectors now" << std::endl; } //std::cout << " projecting..."<< std::endl; // // constrain the vectors to lie on the plane, which means to remove the vector component, // which is orthogonal to the plane. // vtkIdType numPoints, pointId; numPoints = cuttedPlane->GetNumberOfPoints(); vtkDataArray* inVectors = cuttedPlane->GetPointData()->GetVectors( "vector" ); assert( inVectors != NULL ); vtkFloatArray* vectorMagnitudes = vtkFloatArray::New(); vectorMagnitudes->SetName("vectorMagnitudes"); vectorMagnitudes->SetNumberOfComponents(1); vectorMagnitudes->SetNumberOfValues(numPoints); vectorMagnitudes->SetNumberOfTuples(numPoints); double inVector[ 3 ], outVector[3], wnormal[3]; //, tmpVector[ 3 ], outVector[ 3 ]; double k = 0.0; vnl2vtk( normal.Get_vnl_vector(), wnormal ); vtkMath::Normalize( wnormal ); bool normalizeVecs; m_DataNode->GetBoolProperty( "NormalizeVecs", normalizeVecs ); for ( pointId = 0; pointId < numPoints; ++pointId ) { inVectors->GetTuple( pointId, inVector ); if(normalizeVecs) { vnl_vector tmp(3); vtk2vnl(inVector, tmp); tmp.normalize(); vnl2vtk(tmp, inVector); } k = vtkMath::Dot( wnormal, inVector ); // Remove non orthogonal component. outVector[ 0 ] = inVector[ 0 ] - ( wnormal[ 0 ] * k ); outVector[ 1 ] = inVector[ 1 ] - ( wnormal[ 1 ] * k ); outVector[ 2 ] = inVector[ 2 ] - ( wnormal[ 2 ] * k ); inVectors->SetTuple( pointId, outVector ); // ?? this was set to norm(inVector) before, but outVector made more sense to me vectorMagnitudes->SetValue( pointId, vtkMath::Norm( outVector ) ); //std::cout << "method old: " << inVector[0] <<", " << inVector[1] << ", "<AddArray(vectorMagnitudes); pointData->CopyAllOn(); //pointData->PrintSelf(std::cout, vtkIndent(4)); //std::cout << " ...done!"<< std::endl; //std::cout << " glyphing..."<< std::endl; // call glyph2D to generate 2D glyphs for each of the // vectors vtkGlyphSource2D* glyphSource = vtkGlyphSource2D::New(); //glyphSource->SetGlyphTypeToDash(); glyphSource->DashOn(); //glyphSource->SetScale( 0.1 ); //glyphSource->SetScale2( .5 ); //glyphSource->SetCenter( 0.5, 0.5, 0.5 ); glyphSource->CrossOff(); //glyphSource->FilledOff(); //glyphSource->Update(); double spacing[3]; vtkImage->GetSpacing(spacing); double min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; min = min > spacing[2] ? spacing[2] : min; float scale = 1; mitk::FloatProperty::Pointer mitkScaleProp = dynamic_cast(GetDataNode()->GetProperty("Scale")); if (mitkScaleProp.IsNotNull()) { scale = mitkScaleProp->GetValue(); } vtkMaskedGlyph3D* glyphGenerator = vtkMaskedGlyph3D::New(); - glyphGenerator->SetSource( glyphSource->GetOutput() ); - glyphGenerator->SetInputConnection(cuttedPlane->GetProducerPort()); + glyphGenerator->SetSourceData(glyphSource->GetOutput() ); + glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetInputArrayToProcess (1, 0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetVectorModeToUseVector(); glyphGenerator->OrientOn(); glyphGenerator->SetScaleFactor( min*scale ); glyphGenerator->SetUseMaskPoints( true ); glyphGenerator->SetRandomMode( true ); glyphGenerator->SetMaximumNumberOfPoints( 128*128 ); glyphGenerator->Update(); vtkLookupTable* vtkLut = NULL; mitk::LookupTableProperty::Pointer mitkLutProp = dynamic_cast(GetDataNode()->GetProperty("LookupTable")); if (mitkLutProp.IsNotNull()) { vtkLut = mitkLutProp->GetLookupTable()->GetVtkLookupTable(); } mitk::Color color; mitk::ColorProperty::Pointer mitkColorProp = dynamic_cast(GetDataNode()->GetProperty("color")); if (mitkColorProp.IsNotNull()) { color = mitkColorProp->GetColor(); } else { color.SetRed(0); color.SetBlue(1); color.SetGreen(0); } float lwidth = 1; mitk::FloatProperty::Pointer mitkLWidthProp = dynamic_cast(GetDataNode()->GetProperty("LineWidth")); if (mitkLWidthProp.IsNotNull()) { lwidth = mitkLWidthProp->GetValue(); } vtkTransform* trafo = vtkTransform::New(); trafo->Identity(); trafo->Concatenate(vtktransform); trafo->PreMultiply(); double myscale[3]; trafo->GetScale(myscale); trafo->Scale(1/myscale[0],1/myscale[1],1/myscale[2]); this->PaintCells( glyphGenerator->GetOutput(), renderer->GetCurrentWorldGeometry2D(), renderer->GetDisplayGeometry(), trafo, renderer, NULL/*vtkLut*/, color, lwidth, spacing ); vectorMagnitudes->Delete(); glyphSource->Delete(); glyphGenerator->Delete(); trafo->Delete(); } else { std::cout << " no points cutted!"<< std::endl; } //std::cout << "...done!" << std::endl; } void mitk::VectorImageMapper2D::PaintCells( vtkPolyData* glyphs, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, mitk::BaseRenderer* /*renderer*/, vtkScalarsToColors *lut, mitk::Color color, float lwidth, double *spacing ) { vtkPoints * points = glyphs->GetPoints(); vtkPointData * vpointdata = glyphs->GetPointData(); vtkDataArray* vpointscalars = vpointdata->GetArray("vectorMagnitudes"); //vtkDataArray* vpointpositions = vpointdata->GetArray("pointPositions"); assert(vpointscalars != NULL); //std::cout << " Scalars range 2d:" << vpointscalars->GetRange()[0] << " " << vpointscalars->GetRange()[0] << std::endl; Point3D p; Point2D p2d; vtkIdList* idList; vtkCell* cell; double offset[3]; for (unsigned int i = 0; i < 3; ++i) { offset[i] = 0; } vtkIdType numCells = glyphs->GetNumberOfCells(); for ( vtkIdType cellId = 0; cellId < numCells; ++cellId ) { double vp[ 3 ]; cell = glyphs->GetCell( cellId ); idList = cell->GetPointIds(); int numPoints = idList->GetNumberOfIds(); if(numPoints == 1) { //take transformation via vtktransform into account double pos[ 3 ],vp_raster[3]; points->GetPoint( idList->GetId( 0 ), vp ); vp_raster[0] = vtkMath::Round(vp[0]/spacing[0])*spacing[0]; vp_raster[1] = vtkMath::Round(vp[1]/spacing[1])*spacing[1]; vp_raster[2] = vtkMath::Round(vp[2]/spacing[2])*spacing[2]; vtktransform->TransformPoint( vp_raster, pos ); offset[0] = pos[0] - vp[0]; offset[1] = pos[1] - vp[1]; offset[2] = pos[2] - vp[2]; } else { glLineWidth(lwidth); glBegin ( GL_LINE_LOOP ); for ( int pointNr = 0; pointNr < numPoints ;++pointNr ) { points->GetPoint( idList->GetId( pointNr ), vp ); vp[0] = vp[0] + offset[0]; vp[1] = vp[1] + offset[1]; vp[2] = vp[2] + offset[2]; double tmp[ 3 ]; vtktransform->TransformPoint( vp,tmp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); if ( lut != NULL ) { // color each point according to point data double * color; if ( vpointscalars != NULL ) { vpointscalars->GetComponent( pointNr, 0 ); color = lut->GetColor( vpointscalars->GetComponent( idList->GetId( pointNr ), 0 ) ); glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] ); } } else { glColor3f( color.GetRed(), color.GetGreen(), color.GetBlue() ); } //std::cout << idList->GetId( pointNr )<< ": " << p2d[0]<< " "<< p2d[1] << std::endl; //draw the line glVertex2f( p2d[ 0 ], p2d[ 1 ] ); } glEnd (); } } } mitk::VectorImageMapper2D::VectorImageMapper2D() { m_LUT = NULL; m_Plane = vtkPlane::New(); m_Cutter = vtkCutter::New(); m_Cutter->SetCutFunction( m_Plane ); m_Cutter->GenerateValues( 1, 0, 1 ); } mitk::VectorImageMapper2D::~VectorImageMapper2D() { if ( m_LUT != NULL ) m_LUT->Delete(); if ( m_Plane != NULL ) m_Plane->Delete(); if ( m_Cutter != NULL ) m_Cutter->Delete(); } int mitk::VectorImageMapper2D::GetCurrentTimeStep( mitk::BaseData* data, mitk::BaseRenderer* renderer ) { // // get the TimeGeometry of the input object // const TimeGeometry * dataTimeGeometry = data->GetUpdatedTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) ) { itkWarningMacro( << "The given object is missing a mitk::TimeGeometry, or the number of time steps is 0!" ); return 0; } // // get the world time // Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry.IsNotNull() ); ScalarType time = worldGeometry->GetTimeBounds() [ 0 ]; // // convert the world time to time steps of the input object // int timestep = 0; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) timestep = dataTimeGeometry->TimePointToTimeStep( time ); if ( dataTimeGeometry->IsValidTimeStep( timestep ) == false ) { itkWarningMacro( << timestep << " is not a valid time of the given data object!" ); return 0; } return timestep; } diff --git a/Modules/MitkExt/Rendering/vtkMitkOpenGLVolumeTextureMapper3D.cpp b/Modules/MitkExt/Rendering/vtkMitkOpenGLVolumeTextureMapper3D.cpp index 498f08493a..4f5c538af2 100644 --- a/Modules/MitkExt/Rendering/vtkMitkOpenGLVolumeTextureMapper3D.cpp +++ b/Modules/MitkExt/Rendering/vtkMitkOpenGLVolumeTextureMapper3D.cpp @@ -1,2457 +1,2457 @@ /*=================================================================== 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. ===================================================================*/ #ifdef _OPENMP #include #endif #include "vtkWindows.h" #include "vtkMitkOpenGLVolumeTextureMapper3D.h" #include "mitkCommon.h" #define GPU_INFO MITK_INFO("mapper.vr") #define GPU_WARN MITK_WARN("mapper.vr") #include "vtkImageData.h" #include "vtkMatrix4x4.h" #include "vtkDataArray.h" #include "vtkObjectFactory.h" #include "vtkPlane.h" #include "vtkPlaneCollection.h" #include "vtkPointData.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkTimerLog.h" #include "vtkVolumeProperty.h" #include "vtkTransform.h" #include "vtkLightCollection.h" #include "vtkLight.h" #include "vtkCamera.h" #include "vtkMath.h" #include "vtkOpenGLExtensionManager.h" #include "vtkgl.h" #include "vtkOpenGLRenderWindow.h" #define myGL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #define myGL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 #define myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 const char *vtkMitkVolumeTextureMapper3D_FourDependentShadeFP = "!!ARBfp1.0\n" //# We need some temporary variables "TEMP index, normal, finalColor;\n" "TEMP temp,temp1, temp2, temp3,temp4; \n" "TEMP sampleColor;\n" "TEMP ndotl, ndoth, ndotv; \n" "TEMP lightInfo, lightResult;\n" //# We are going to use the first //# texture coordinate "ATTRIB tex0 = fragment.texcoord[0];\n" //# This is the lighting information "PARAM lightDirection = program.local[0];\n" "PARAM halfwayVector = program.local[1];\n" "PARAM coefficient = program.local[2];\n" "PARAM lightDiffColor = program.local[3]; \n" "PARAM lightSpecColor = program.local[4]; \n" "PARAM viewVector = program.local[5];\n" "PARAM constants = program.local[6];\n" //# This is our output color "OUTPUT out = result.color;\n" //# Look up the gradient direction //# in the third volume "TEX temp2, tex0, texture[0], 3D;\n" //# This normal is stored 0 to 1, change to -1 to 1 //# by multiplying by 2.0 then adding -1.0. "MAD normal, temp2, constants.x, constants.y;\n" "DP3 temp4, normal, normal;\n" "RSQ temp, temp4.x;\n" "MUL normal, normal, temp;\n" //"RCP temp4,temp.x;\n" //"MUL temp2.w,temp2.w,temp4.x;\n" //"MUL_SAT temp2.w,temp2.w,6.0;\n" "TEX sampleColor, tex0, texture[1], 3D;\n" //# Take the dot product of the light //# direction and the normal "DP3 ndotl, normal, lightDirection;\n" //# Take the dot product of the halfway //# vector and the normal "DP3 ndoth, normal, halfwayVector;\n" "DP3 ndotv, normal, viewVector;\n" //# flip if necessary for two sided lighting "MUL temp3, ndotl, constants.y; \n" "CMP ndotl, ndotv, ndotl, temp3;\n" "MUL temp3, ndoth, constants.y; \n" "CMP ndoth, ndotv, ndoth, temp3;\n" //# put the pieces together for a LIT operation "MOV lightInfo.x, ndotl.x; \n" "MOV lightInfo.y, ndoth.x; \n" "MOV lightInfo.w, coefficient.w; \n" //# compute the lighting "LIT lightResult, lightInfo;\n" //# COLOR FIX "MUL lightResult, lightResult, 4.0;\n" //# This is the ambient contribution "MUL finalColor, coefficient.x, sampleColor;\n" //# This is the diffuse contribution "MUL temp3, lightDiffColor, sampleColor;\n" "MUL temp3, temp3, lightResult.y;\n" "ADD finalColor, finalColor, temp3;\n" //# This is th specular contribution "MUL temp3, lightSpecColor, lightResult.z; \n" //# Add specular into result so far, and replace //# with the original alpha. "ADD out, finalColor, temp3;\n" "MOV out.w, temp2.w;\n" "END\n"; const char *vtkMitkVolumeTextureMapper3D_OneComponentShadeFP = "!!ARBfp1.0\n" //# This is the fragment program for one //# component data with shading //# We need some temporary variables "TEMP index, normal, finalColor;\n" "TEMP temp,temp1, temp2, temp3,temp4; \n" "TEMP sampleColor;\n" "TEMP ndotl, ndoth, ndotv; \n" "TEMP lightInfo, lightResult;\n" //# We are going to use the first //# texture coordinate "ATTRIB tex0 = fragment.texcoord[0];\n" //# This is the lighting information "PARAM lightDirection = program.local[0];\n" "PARAM halfwayVector = program.local[1];\n" "PARAM coefficient = program.local[2];\n" "PARAM lightDiffColor = program.local[3]; \n" "PARAM lightSpecColor = program.local[4]; \n" "PARAM viewVector = program.local[5];\n" "PARAM constants = program.local[6];\n" //# This is our output color "OUTPUT out = result.color;\n" //# Look up the gradient direction //# in the third volume "TEX temp2, tex0, texture[0], 3D;\n" // Gradient Compution //# Look up the scalar value / gradient //# magnitude in the first volume //"TEX temp1, tex0, texture[0], 3D;\n" /* "ADD temp3,tex0,{-0.005,0,0};\n" "TEX temp2,temp3, texture[0], 3D;\n" //"ADD temp3,tex0,{ 0.005,0,0};\n" //"TEX temp1,temp3, texture[0], 3D;\n" "SUB normal.x,temp2.y,temp1.y;\n" "ADD temp3,tex0,{0,-0.005,0};\n" "TEX temp2,temp3, texture[0], 3D;\n" //"ADD temp3,tex0,{0, 0.005,0};\n" //"TEX temp1,temp3, texture[0], 3D;\n" "SUB normal.y,temp2.y,temp1.y;\n" "ADD temp3,tex0,{0,0,-0.005};\n" "TEX temp2,temp3, texture[0], 3D;\n" //"ADD temp3,tex0,{0,0, 0.005};\n" //"TEX temp1,temp3, texture[0], 3D;\n" "SUB normal.z,temp2.y,temp1.y;\n" */ //"MOV normal,{1,1,1};\n" "MOV index.x,temp2.a;\n" //# This normal is stored 0 to 1, change to -1 to 1 //# by multiplying by 2.0 then adding -1.0. "MAD normal, temp2, constants.x, constants.y;\n" //# Swizzle this to use (a,r) as texture //# coordinates //"SWZ index, temp1, a, r, 1, 1;\n" //# Use this coordinate to look up a //# final color in the third texture //# (this is a 2D texture) "DP3 temp4, normal, normal;\n" "RSQ temp, temp4.x;\n" "RCP temp4,temp.x;\n" "MUL normal, normal, temp;\n" "MOV index.y, temp4.x;\n" "TEX sampleColor, index, texture[1], 2D;\n" //"MUL sampleColor.w,sampleColor.w,temp4.x;\n" //# Take the dot product of the light //# direction and the normal "DP3 ndotl, normal, lightDirection;\n" //# Take the dot product of the halfway //# vector and the normal "DP3 ndoth, normal, halfwayVector;\n" "DP3 ndotv, normal, viewVector;\n" //# flip if necessary for two sided lighting "MUL temp3, ndotl, constants.y; \n" "CMP ndotl, ndotv, ndotl, temp3;\n" "MUL temp3, ndoth, constants.y; \n" "CMP ndoth, ndotv, ndoth, temp3;\n" //# put the pieces together for a LIT operation "MOV lightInfo.x, ndotl.x; \n" "MOV lightInfo.y, ndoth.x; \n" "MOV lightInfo.w, coefficient.w; \n" //# compute the lighting "LIT lightResult, lightInfo;\n" //# COLOR FIX "MUL lightResult, lightResult, 4.0;\n" //# This is the ambient contribution "MUL finalColor, coefficient.x, sampleColor;\n" //# This is the diffuse contribution "MUL temp3, lightDiffColor, sampleColor;\n" "MUL temp3, temp3, lightResult.y;\n" "ADD finalColor, finalColor, temp3;\n" //# This is th specular contribution "MUL temp3, lightSpecColor, lightResult.z; \n" //# Add specular into result so far, and replace //# with the original alpha. "ADD out, finalColor, temp3;\n" "MOV out.w, sampleColor.w;\n" "END\n"; //#ifndef VTK_IMPLEMENT_MESA_CXX vtkStandardNewMacro(vtkMitkOpenGLVolumeTextureMapper3D); //#endif vtkMitkOpenGLVolumeTextureMapper3D::vtkMitkOpenGLVolumeTextureMapper3D() { //GPU_INFO << "vtkMitkOpenGLVolumeTextureMapper3D"; this->Initialized = 0; this->Volume1Index = 0; this->Volume2Index = 0; this->Volume3Index = 0; this->ColorLookupIndex = 0; this->AlphaLookupIndex = 0; this->RenderWindow = NULL; this->SupportsCompressedTexture = false; prgOneComponentShade = 0; prgRGBAShade = 0; } vtkMitkOpenGLVolumeTextureMapper3D::~vtkMitkOpenGLVolumeTextureMapper3D() { //GPU_INFO << "~vtkMitkOpenGLVolumeTextureMapper3D"; if(prgOneComponentShade) vtkgl::DeleteProgramsARB( 1, &prgOneComponentShade ); if(prgRGBAShade) vtkgl::DeleteProgramsARB( 1, &prgRGBAShade ); } // Release the graphics resources used by this texture. void vtkMitkOpenGLVolumeTextureMapper3D::ReleaseGraphicsResources(vtkWindow *renWin) { //GPU_INFO << "ReleaseGraphicsResources"; if (( this->Volume1Index || this->Volume2Index || this->Volume3Index || this->ColorLookupIndex) && renWin) { static_cast(renWin)->MakeCurrent(); #ifdef GL_VERSION_1_1 // free any textures this->DeleteTextureIndex( &this->Volume1Index ); this->DeleteTextureIndex( &this->Volume2Index ); this->DeleteTextureIndex( &this->Volume3Index ); this->DeleteTextureIndex( &this->ColorLookupIndex ); this->DeleteTextureIndex( &this->AlphaLookupIndex ); #endif } this->Volume1Index = 0; this->Volume2Index = 0; this->Volume3Index = 0; this->ColorLookupIndex = 0; this->RenderWindow = NULL; this->SupportsCompressedTexture=false; this->SupportsNonPowerOfTwoTextures=false; this->Modified(); } // Release the graphics resources used by this texture. void vtkMitkOpenGLVolumeTextureMapper3D::ReleaseGraphicsResources(mitk::BaseRenderer* renderer) { //GPU_INFO << "ReleaseGraphicsResources"; vtkWindow * renWin = renderer->GetVtkRenderer()->GetRenderWindow(); if (( this->Volume1Index || this->Volume2Index || this->Volume3Index || this->ColorLookupIndex) && renWin) { static_cast(renWin)->MakeCurrent(); #ifdef GL_VERSION_1_1 // free any textures this->DeleteTextureIndex( &this->Volume1Index ); this->DeleteTextureIndex( &this->Volume2Index ); this->DeleteTextureIndex( &this->Volume3Index ); this->DeleteTextureIndex( &this->ColorLookupIndex ); this->DeleteTextureIndex( &this->AlphaLookupIndex ); #endif } this->Volume1Index = 0; this->Volume2Index = 0; this->Volume3Index = 0; this->ColorLookupIndex = 0; this->RenderWindow = NULL; this->SupportsCompressedTexture=false; this->SupportsNonPowerOfTwoTextures=false; this->Modified(); } void vtkMitkOpenGLVolumeTextureMapper3D::Render(vtkRenderer *ren, vtkVolume *vol) { //GPU_INFO << "Render"; ren->GetRenderWindow()->MakeCurrent(); if ( !this->Initialized ) { //this->Initialize(); this->Initialize(ren); } if ( !this->RenderPossible ) { vtkErrorMacro( "required extensions not supported" ); return; } vtkMatrix4x4 *matrix = vtkMatrix4x4::New(); vtkPlaneCollection *clipPlanes; vtkPlane *plane; int numClipPlanes = 0; double planeEquation[4]; // build transformation vol->GetMatrix(matrix); matrix->Transpose(); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_POLYGON_BIT | GL_TEXTURE_BIT); int i; // Use the OpenGL clip planes clipPlanes = this->ClippingPlanes; if ( clipPlanes ) { numClipPlanes = clipPlanes->GetNumberOfItems(); if (numClipPlanes > 6) { vtkErrorMacro(<< "OpenGL guarantees only 6 additional clipping planes"); } for (i = 0; i < numClipPlanes; i++) { glEnable(static_cast(GL_CLIP_PLANE0+i)); plane = static_cast(clipPlanes->GetItemAsObject(i)); planeEquation[0] = plane->GetNormal()[0]; planeEquation[1] = plane->GetNormal()[1]; planeEquation[2] = plane->GetNormal()[2]; planeEquation[3] = -(planeEquation[0]*plane->GetOrigin()[0]+ planeEquation[1]*plane->GetOrigin()[1]+ planeEquation[2]*plane->GetOrigin()[2]); glClipPlane(static_cast(GL_CLIP_PLANE0+i),planeEquation); } } // insert model transformation glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glMultMatrixd(matrix->Element[0]); glColor4f( 1.0, 1.0, 1.0, 1.0 ); // Turn lighting off - the polygon textures already have illumination glDisable( GL_LIGHTING ); vtkGraphicErrorMacro(ren->GetRenderWindow(),"Before actual render method"); this->RenderFP(ren,vol); // pop transformation matrix glMatrixMode( GL_MODELVIEW ); glPopMatrix(); matrix->Delete(); glPopAttrib(); } void vtkMitkOpenGLVolumeTextureMapper3D::RenderFP(vtkRenderer *ren, vtkVolume *vol) { //GPU_INFO << "RenderFP"; /* glAlphaFunc (GL_GREATER, static_cast(1.0/255.0)); glEnable (GL_ALPHA_TEST); */ glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); int components = this->GetInput()->GetNumberOfScalarComponents(); switch ( components ) { case 1: this->RenderOneIndependentShadeFP(ren,vol); break; case 4: this->RenderRGBAShadeFP(ren,vol); break; } vtkgl::ActiveTexture( vtkgl::TEXTURE2); glDisable( GL_TEXTURE_2D ); glDisable( vtkgl::TEXTURE_3D ); vtkgl::ActiveTexture( vtkgl::TEXTURE1); glDisable( GL_TEXTURE_2D ); glDisable( vtkgl::TEXTURE_3D ); vtkgl::ActiveTexture( vtkgl::TEXTURE0); glDisable( GL_TEXTURE_2D ); glDisable( vtkgl::TEXTURE_3D ); glDisable( GL_BLEND ); } void vtkMitkOpenGLVolumeTextureMapper3D::DeleteTextureIndex( GLuint *index ) { //GPU_INFO << "DeleteTextureIndex"; if (glIsTexture(*index)) { GLuint tempIndex; tempIndex = *index; glDeleteTextures(1, &tempIndex); *index = 0; } } void vtkMitkOpenGLVolumeTextureMapper3D::CreateTextureIndex( GLuint *index ) { //GPU_INFO << "CreateTextureIndex"; GLuint tempIndex=0; glGenTextures(1, &tempIndex); *index = static_cast(tempIndex); } void vtkMitkOpenGLVolumeTextureMapper3D::RenderPolygons( vtkRenderer *ren, vtkVolume *vol, int stages[4] ) { //GPU_INFO << "RenderPolygons"; vtkRenderWindow *renWin = ren->GetRenderWindow(); if ( renWin->CheckAbortStatus() ) { return; } double bounds[27][6]; float distance2[27]; int numIterations; int i, j, k; // No cropping case - render the whole thing if ( !this->Cropping ) { // Use the input data bounds - we'll take care of the volume's // matrix during rendering this->GetInput()->GetBounds(bounds[0]); numIterations = 1; } // Simple cropping case - render the subvolume else if ( this->CroppingRegionFlags == 0x2000 ) { this->GetCroppingRegionPlanes(bounds[0]); numIterations = 1; } // Complex cropping case - render each region in back-to-front order else { // Get the camera position double camPos[4]; ren->GetActiveCamera()->GetPosition(camPos); double volBounds[6]; this->GetInput()->GetBounds(volBounds); // Pass camera through inverse volume matrix // so that we are in the same coordinate system vtkMatrix4x4 *volMatrix = vtkMatrix4x4::New(); vol->GetMatrix( volMatrix ); camPos[3] = 1.0; volMatrix->Invert(); volMatrix->MultiplyPoint( camPos, camPos ); volMatrix->Delete(); if ( camPos[3] ) { camPos[0] /= camPos[3]; camPos[1] /= camPos[3]; camPos[2] /= camPos[3]; } // These are the region limits for x (first four), y (next four) and // z (last four). The first region limit is the lower bound for // that axis, the next two are the region planes along that axis, and // the final one in the upper bound for that axis. float limit[12]; for ( i = 0; i < 3; i++ ) { limit[i*4 ] = volBounds[i*2]; limit[i*4+1] = this->CroppingRegionPlanes[i*2]; limit[i*4+2] = this->CroppingRegionPlanes[i*2+1]; limit[i*4+3] = volBounds[i*2+1]; } // For each of the 27 possible regions, find out if it is enabled, // and if so, compute the bounds and the distance from the camera // to the center of the region. int numRegions = 0; int region; for ( region = 0; region < 27; region++ ) { int regionFlag = 1<CroppingRegionFlags & regionFlag ) { // what is the coordinate in the 3x3x3 grid int loc[3]; loc[0] = region%3; loc[1] = (region/3)%3; loc[2] = (region/9)%3; // compute the bounds and center float center[3]; for ( i = 0; i < 3; i++ ) { bounds[numRegions][i*2 ] = limit[4*i+loc[i]]; bounds[numRegions][i*2+1] = limit[4*i+loc[i]+1]; center[i] = (bounds[numRegions][i*2 ] + bounds[numRegions][i*2+1])/2.0; } // compute the distance squared to the center distance2[numRegions] = (camPos[0]-center[0])*(camPos[0]-center[0]) + (camPos[1]-center[1])*(camPos[1]-center[1]) + (camPos[2]-center[2])*(camPos[2]-center[2]); // we've added one region numRegions++; } } // Do a quick bubble sort on distance for ( i = 1; i < numRegions; i++ ) { for ( j = i; j > 0 && distance2[j] > distance2[j-1]; j-- ) { float tmpBounds[6]; float tmpDistance2; for ( k = 0; k < 6; k++ ) { tmpBounds[k] = bounds[j][k]; } tmpDistance2 = distance2[j]; for ( k = 0; k < 6; k++ ) { bounds[j][k] = bounds[j-1][k]; } distance2[j] = distance2[j-1]; for ( k = 0; k < 6; k++ ) { bounds[j-1][k] = tmpBounds[k]; } distance2[j-1] = tmpDistance2; } } numIterations = numRegions; } // loop over all regions we need to render for ( int loop = 0; loop < numIterations; loop++ ) { // Compute the set of polygons for this region // according to the bounds this->ComputePolygons( ren, vol, bounds[loop] ); // Loop over the polygons for ( i = 0; i < this->NumberOfPolygons; i++ ) { if ( renWin->CheckAbortStatus() ) { return; } float *ptr = this->PolygonBuffer + 36*i; glBegin( GL_TRIANGLE_FAN ); for ( j = 0; j < 6; j++ ) { if ( ptr[0] < 0.0 ) { break; } for ( k = 0; k < 4; k++ ) { if ( stages[k] ) { vtkgl::MultiTexCoord3fv( vtkgl::TEXTURE0 + k, ptr ); } } glVertex3fv( ptr+3 ); ptr += 6; } glEnd(); } } } // This method moves the scalars from the input volume into volume1 (and // possibly volume2) which are the 3D texture maps used for rendering. // // In the case where our volume is a power of two, the copy is done // directly. If we need to resample, then trilinear interpolation is used. // // A shift/scale is applied to the input scalar value to produce an 8 bit // value for the texture volume. // // When the input data is one component, the scalar value is placed in the // second component of the two component volume1. The first component is // filled in later with the gradient magnitude. // // When the input data is two component non-independent, the first component // of the input data is placed in the first component of volume1, and the // second component of the input data is placed in the third component of // volume1. Volume1 has three components - the second is filled in later with // the gradient magnitude. // // When the input data is four component non-independent, the first three // components of the input data are placed in volume1 (which has three // components), and the fourth component is placed in the second component // of volume2. The first component of volume2 is later filled in with the // gradient magnitude. template class ScalarGradientCompute { T *dataPtr; unsigned char *tmpPtr; unsigned char *tmpPtr2; int sizeX; int sizeY; int sizeZ; int sizeXY; int sizeXm1; int sizeYm1; int sizeZm1; int fullX; int fullY; int fullZ; int fullXY; int currentChunkStart; int currentChunkEnd; int offZ; float offset; float scale; public: ScalarGradientCompute( T *_dataPtr,unsigned char *_tmpPtr,unsigned char *_tmpPtr2,int _sizeX,int _sizeY,int _sizeZ,int _fullX,int _fullY,int _fullZ,float _offset,float _scale) { dataPtr=_dataPtr; tmpPtr=_tmpPtr; tmpPtr2=_tmpPtr2; sizeX=_sizeX; sizeY=_sizeY; sizeZ=_sizeZ; fullX=_fullX; fullY=_fullY; fullZ=_fullZ; offset=_offset; scale=_scale; sizeXY=sizeX*sizeY; sizeXm1=sizeX-1; sizeYm1=sizeY-1; sizeZm1=sizeZ-1; fullXY=fullX*fullY; } inline float sample(int x,int y,int z) { return float(dataPtr[ x + y * sizeX + z * sizeXY ]); } inline void fill(int x,int y,int z) { int doff = x + y * fullX + (z-offZ) * fullXY; tmpPtr[doff*4+0]= 0; tmpPtr[doff*4+1]= 0; tmpPtr[doff*4+2]= 0; tmpPtr[doff*4+3]= 0; /* tmpPtr2[doff*3+0]= 0; tmpPtr2[doff*3+1]= 0; tmpPtr2[doff*3+2]= 0; */ } inline int clamp(int x) { if(x<0) x=0; else if(x>255) x=255; return x; } inline void write(int x,int y,int z,float grayValue,float gx,float gy,float gz) { /* gx /= aspect[0]; gy /= aspect[1]; gz /= aspect[2]; */ // Compute the gradient magnitude int iGrayValue = static_cast( (grayValue + offset) * scale + 0.5f ); gx *= scale; gy *= scale; gz *= scale; float t = sqrtf( gx*gx + gy*gy + gz*gz ); if ( t > 0.01f ) { if( t < 2.0f ) { float fac = 2.0f/t; gx *= fac; gy *= fac; gz *= fac; } else if( t > 255.0f) { float fac = 255.0f/t; gx *= fac; gy *= fac; gz *= fac; } } else { gx=gy=gz=0.0f; } int nx = static_cast(0.5f*gx+127.5f); int ny = static_cast(0.5f*gy+127.5f); int nz = static_cast(0.5f*gz+127.5f); int doff = x + y * fullX + (z-offZ) * fullXY; //tmpPtr[doff*2+0]= 0; tmpPtr[doff*4+0]= clamp(nx); tmpPtr[doff*4+1]= clamp(ny); tmpPtr[doff*4+2]= clamp(nz); tmpPtr[doff*4+3]= clamp(iGrayValue); /* if( z == fullZ/2 ) if( y == fullY/2 ) MITK_INFO << x << " " << y << " " << z << " : " << iGrayValue << " : " << iGradient; */ } inline void compute(int x,int y,int z) { float grayValue = sample(x,y,z); float gx,gy,gz; gx = sample(x+1,y,z) - sample(x-1,y,z); gy = sample(x,y+1,z) - sample(x,y-1,z); gz = sample(x,y,z+1) - sample(x,y,z-1); write( x, y, z, grayValue, gx, gy, gz ); } inline void computeClamp(int x,int y,int z) { float grayValue = sample(x,y,z); float gx,gy,gz; if(x==0) gx = 2.0f * ( sample(x+1,y,z) - grayValue ); else if(x==sizeXm1) gx = 2.0f * ( grayValue - sample(x-1,y,z) ); else gx = sample(x+1,y,z) - sample(x-1,y,z); if(y==0) gy = 2.0f * ( sample(x,y+1,z) - grayValue ); else if(y==sizeYm1) gy = 2.0f * ( grayValue - sample(x,y-1,z) ); else gy = sample(x,y+1,z) - sample(x,y-1,z); if(z==0) gz = 2.0f * ( sample(x,y,z+1) - grayValue ); else if(z==sizeZm1) gz = 2.0f * ( grayValue - sample(x,y,z-1) ); else gz = sample(x,y,z+1) - sample(x,y,z-1); write( x, y, z, grayValue, gx, gy, gz ); } inline void compute1D(int y,int z) { int x; x=0; computeClamp(x,y,z); x++; while(x=sizeZ) fill2D(z); else compute2D(z); } } }; template void vtkVolumeTextureMapper3DComputeScalars( T *dataPtr, vtkMitkVolumeTextureMapper3D *me, float offset, float scale, GLuint volume1, GLuint /*volume2*/) { T *inPtr; // unsigned char *outPtr, *outPtr2; // int i, j, k; // int idx; int inputDimensions[3]; double inputSpacing[3]; vtkImageData *input = me->GetInput(); input->GetDimensions( inputDimensions ); input->GetSpacing( inputSpacing ); int outputDimensions[3]; float outputSpacing[3]; me->GetVolumeDimensions( outputDimensions ); me->GetVolumeSpacing( outputSpacing ); // int components = input->GetNumberOfScalarComponents(); // double wx, wy, wz; // double fx, fy, fz; // int x, y, z; double sampleRate[3]; sampleRate[0] = outputSpacing[0] / static_cast(inputSpacing[0]); sampleRate[1] = outputSpacing[1] / static_cast(inputSpacing[1]); sampleRate[2] = outputSpacing[2] / static_cast(inputSpacing[2]); int fullX = outputDimensions[0]; int fullY = outputDimensions[1]; int fullZ = outputDimensions[2]; int sizeX = inputDimensions[0]; int sizeY = inputDimensions[1]; int sizeZ = inputDimensions[2]; int chunkSize = 64; if(fullZ < chunkSize) chunkSize=fullZ; int numChunks = ( fullZ + (chunkSize-1) ) / chunkSize; inPtr = dataPtr; unsigned char *tmpPtr = new unsigned char[fullX*fullY*chunkSize*4]; unsigned char *tmpPtr2 = 0;//new unsigned char[fullX*fullY*chunkSize*3]; // For each Chunk { ScalarGradientCompute sgc(dataPtr,tmpPtr,tmpPtr2,sizeX,sizeY,sizeZ,fullX,fullY,fullZ,offset,scale); int currentChunk = 0; while(currentChunk < numChunks) { // MITK_INFO << "processing chunk " << currentChunk; int currentChunkStart = currentChunk * chunkSize; int currentChunkEnd = currentChunkStart + chunkSize - 1 ; if( currentChunkEnd > (fullZ-1) ) currentChunkEnd = (fullZ-1); int currentChunkSize = currentChunkEnd - currentChunkStart + 1; sgc.fillSlices( currentChunkStart , currentChunkEnd ); glBindTexture(vtkgl::TEXTURE_3D, volume1); vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D,0,0,0,currentChunkStart,fullX,fullY,currentChunkSize,GL_RGBA,GL_UNSIGNED_BYTE,tmpPtr); /* glBindTexture(vtkgl::TEXTURE_3D, volume2); vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D,0,0,0,currentChunkStart,fullX,fullY,currentChunkSize,GL_RGB,GL_UNSIGNED_BYTE,tmpPtr2); */ currentChunk ++; } } delete tmpPtr; // delete tmpPtr2; } class RGBACompute { unsigned char *dataPtr; unsigned char *tmpPtr; unsigned char *tmpPtr2; int sizeX; int sizeY; int sizeZ; int sizeXY; int sizeXm1; int sizeYm1; int sizeZm1; int fullX; int fullY; int fullZ; int fullXY; int currentChunkStart; int currentChunkEnd; int offZ; public: RGBACompute( unsigned char *_dataPtr,unsigned char *_tmpPtr,unsigned char *_tmpPtr2,int _sizeX,int _sizeY,int _sizeZ,int _fullX,int _fullY,int _fullZ) { dataPtr=_dataPtr; tmpPtr=_tmpPtr; tmpPtr2=_tmpPtr2; sizeX=_sizeX; sizeY=_sizeY; sizeZ=_sizeZ; fullX=_fullX; fullY=_fullY; fullZ=_fullZ; sizeXY=sizeX*sizeY; sizeXm1=sizeX-1; sizeYm1=sizeY-1; sizeZm1=sizeZ-1; fullXY=fullX*fullY; } inline int sample(int x,int y,int z) { return dataPtr[ ( x + y * sizeX + z * sizeXY ) * 4 +3 ]; } inline void fill(int x,int y,int z) { int doff = x + y * fullX + (z-offZ) * fullXY; tmpPtr[doff*4+0]= 0; tmpPtr[doff*4+1]= 0; tmpPtr[doff*4+2]= 0; tmpPtr[doff*4+3]= 0; tmpPtr2[doff*3+0]= 0; tmpPtr2[doff*3+1]= 0; tmpPtr2[doff*3+2]= 0; } inline int clamp(int x) { if(x<0) x=0; else if(x>255) x=255; return x; } inline void write(int x,int y,int z,int iGrayValue,int gx,int gy,int gz) { /* gx /= aspect[0]; gy /= aspect[1]; gz /= aspect[2]; */ int nx = static_cast(0.5f*gx+127.5f); int ny = static_cast(0.5f*gy+127.5f); int nz = static_cast(0.5f*gz+127.5f); int doff = x + y * fullX + (z-offZ) * fullXY; //tmpPtr[doff*2+0]= 0; tmpPtr[doff*4+0]= clamp(nx); tmpPtr[doff*4+1]= clamp(ny); tmpPtr[doff*4+2]= clamp(nz); tmpPtr[doff*4+3]= clamp(iGrayValue); int soff = x + y * sizeX + z * sizeXY; tmpPtr2[doff*3+0]= dataPtr[soff*4+0]; tmpPtr2[doff*3+1]= dataPtr[soff*4+1]; tmpPtr2[doff*3+2]= dataPtr[soff*4+2]; /* if( z == fullZ/2 ) if( y == fullY/2 ) MITK_INFO << x << " " << y << " " << z << " : " << iGrayValue << " : " << iGradient; */ } inline void compute(int x,int y,int z) { int grayValue = sample(x,y,z); int gx,gy,gz; gx = sample(x+1,y,z) - sample(x-1,y,z); gy = sample(x,y+1,z) - sample(x,y-1,z); gz = sample(x,y,z+1) - sample(x,y,z-1); write( x, y, z, grayValue, gx, gy, gz ); } inline void computeClamp(int x,int y,int z) { int grayValue = sample(x,y,z); int gx,gy,gz; if(x==0) gx = 2 * ( sample(x+1,y,z) - grayValue ); else if(x==sizeXm1) gx = 2 * ( grayValue - sample(x-1,y,z) ); else gx = sample(x+1,y,z) - sample(x-1,y,z); if(y==0) gy = 2 * ( sample(x,y+1,z) - grayValue ); else if(y==sizeYm1) gy = 2 * ( grayValue - sample(x,y-1,z) ); else gy = sample(x,y+1,z) - sample(x,y-1,z); if(z==0) gz = 2 * ( sample(x,y,z+1) - grayValue ); else if(z==sizeZm1) gz = 2 * ( grayValue - sample(x,y,z-1) ); else gz = sample(x,y,z+1) - sample(x,y,z-1); write( x, y, z, grayValue, gx, gy, gz ); } inline void compute1D(int y,int z) { int x=0; computeClamp(x,y,z); x++; while(x=sizeZ) fill2D(z); else compute2D(z); } } }; void vtkVolumeTextureMapper3DComputeRGBA( unsigned char *dataPtr, vtkMitkVolumeTextureMapper3D *me, GLuint volume1, GLuint volume2) { unsigned char *inPtr; // unsigned char *outPtr, *outPtr2; // int i, j, k; // int idx; int inputDimensions[3]; double inputSpacing[3]; vtkImageData *input = me->GetInput(); input->GetDimensions( inputDimensions ); input->GetSpacing( inputSpacing ); int outputDimensions[3]; float outputSpacing[3]; me->GetVolumeDimensions( outputDimensions ); me->GetVolumeSpacing( outputSpacing ); int components = input->GetNumberOfScalarComponents(); MITK_INFO << "components are " << components; // double wx, wy, wz; // double fx, fy, fz; // int x, y, z; double sampleRate[3]; sampleRate[0] = outputSpacing[0] / static_cast(inputSpacing[0]); sampleRate[1] = outputSpacing[1] / static_cast(inputSpacing[1]); sampleRate[2] = outputSpacing[2] / static_cast(inputSpacing[2]); int fullX = outputDimensions[0]; int fullY = outputDimensions[1]; int fullZ = outputDimensions[2]; int sizeX = inputDimensions[0]; int sizeY = inputDimensions[1]; int sizeZ = inputDimensions[2]; int chunkSize = 64; if(fullZ < chunkSize) chunkSize=fullZ; int numChunks = ( fullZ + (chunkSize-1) ) / chunkSize; inPtr = dataPtr; unsigned char *tmpPtr = new unsigned char[fullX*fullY*chunkSize*4]; unsigned char *tmpPtr2 = new unsigned char[fullX*fullY*chunkSize*3]; // For each Chunk { RGBACompute sgc(dataPtr,tmpPtr,tmpPtr2,sizeX,sizeY,sizeZ,fullX,fullY,fullZ); int currentChunk = 0; while(currentChunk < numChunks) { // MITK_INFO << "processing chunk " << currentChunk; int currentChunkStart = currentChunk * chunkSize; int currentChunkEnd = currentChunkStart + chunkSize - 1 ; if( currentChunkEnd > (fullZ-1) ) currentChunkEnd = (fullZ-1); int currentChunkSize = currentChunkEnd - currentChunkStart + 1; sgc.fillSlices( currentChunkStart , currentChunkEnd ); glBindTexture(vtkgl::TEXTURE_3D, volume1); vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D,0,0,0,currentChunkStart,fullX,fullY,currentChunkSize,GL_RGBA,GL_UNSIGNED_BYTE,tmpPtr); glBindTexture(vtkgl::TEXTURE_3D, volume2); vtkgl::TexSubImage3D(vtkgl::TEXTURE_3D,0,0,0,currentChunkStart,fullX,fullY,currentChunkSize,GL_RGB,GL_UNSIGNED_BYTE,tmpPtr2); currentChunk ++; } } delete tmpPtr; delete tmpPtr2; } //----------------------------------------------------------------------------- void vtkMitkOpenGLVolumeTextureMapper3D::ComputeVolumeDimensions() { // Get the image data vtkImageData *input = this->GetInput(); // How big does the Volume need to be? int dim[3]; input->GetDimensions(dim); int powerOfTwoDim[3]; if(this->SupportsNonPowerOfTwoTextures) { for ( int i = 0; i < 3; i++ ) powerOfTwoDim[i]=(dim[i]+1)&~1; // MITK_INFO << "using non-power-two even textures (" << (1.0-double(dim[0]*dim[1]*dim[2])/double(powerOfTwoDim[0]*powerOfTwoDim[1]*powerOfTwoDim[2])) * 100.0 << "% memory wasted)"; } else { for ( int i = 0; i < 3; i++ ) { powerOfTwoDim[i] = 4; while ( powerOfTwoDim[i] < dim[i] ) powerOfTwoDim[i] *= 2; } MITK_WARN << "using power-two textures (" << (1.0-double(dim[0]*dim[1]*dim[2])/double(powerOfTwoDim[0]*powerOfTwoDim[1]*powerOfTwoDim[2])) * 100.0 << "% memory wasted)"; } // Save the volume size this->VolumeDimensions[0] = powerOfTwoDim[0]; this->VolumeDimensions[1] = powerOfTwoDim[1]; this->VolumeDimensions[2] = powerOfTwoDim[2]; // What is the spacing? double spacing[3]; input->GetSpacing(spacing); // Compute the new spacing this->VolumeSpacing[0] = ( dim[0] -1.01)*spacing[0] / static_cast(this->VolumeDimensions[0]-1); this->VolumeSpacing[1] = ( dim[1] -1.01)*spacing[1] / static_cast(this->VolumeDimensions[1]-1); this->VolumeSpacing[2] = ((dim[2])-1.01)*spacing[2] / static_cast(this->VolumeDimensions[2]-1); } //----------------------------------------------------------------------------- bool vtkMitkOpenGLVolumeTextureMapper3D::UpdateVolumes(vtkVolume *vtkNotUsed(vol)) { // Get the image data vtkImageData *input = this->GetInput(); - input->Update(); +// input->Update(); //VTK6_TODO bool needUpdate = false; // Has the volume changed in some way? if ( this->SavedTextureInput != input || this->SavedTextureMTime.GetMTime() < input->GetMTime() ) needUpdate = true; // Do we have any volume on the gpu already? if(!this->Volume1Index) needUpdate = true; if(!needUpdate) return true; ComputeVolumeDimensions(); int components = input->GetNumberOfScalarComponents(); // Find the scalar range double scalarRange[2]; input->GetPointData()->GetScalars()->GetRange(scalarRange, components-1); // Is the difference between max and min less than 4096? If so, and if // the data is not of float or double type, use a simple offset mapping. // If the difference between max and min is 4096 or greater, or the data // is of type float or double, we must use an offset / scaling mapping. // In this case, the array size will be 4096 - we need to figure out the // offset and scale factor. float offset; float scale; int arraySizeNeeded; int scalarType = input->GetScalarType(); if ( scalarType == VTK_FLOAT || scalarType == VTK_DOUBLE || scalarRange[1] - scalarRange[0] > 255 ) { arraySizeNeeded = 256; offset = -scalarRange[0]; scale = 255.0 / (scalarRange[1] - scalarRange[0]); } else { arraySizeNeeded = static_cast(scalarRange[1] - scalarRange[0] + 1); offset = -scalarRange[0]; scale = 1.0; } this->ColorTableSize = arraySizeNeeded; this->ColorTableOffset = offset; this->ColorTableScale = scale; // Allocating volume on gpu { // Deleting old textures this->DeleteTextureIndex(&this->Volume1Index); this->DeleteTextureIndex(&this->Volume2Index); this->DeleteTextureIndex(&this->Volume3Index); this->CreateTextureIndex(&this->Volume1Index); //this->CreateTextureIndex(&this->Volume2Index); int dim[3]; this->GetVolumeDimensions(dim); vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); MITK_INFO << "allocating volume on gpu"; GLint gradientScalarTextureFormat = GL_RGBA8; if(this->UseCompressedTexture && SupportsCompressedTexture) gradientScalarTextureFormat = myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT; glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,gradientScalarTextureFormat,dim[0],dim[1],dim[2],0,GL_RGBA,GL_UNSIGNED_BYTE,0); this->Setup3DTextureParameters( true ); } // Transfer the input volume to the RGBA volume void *dataPtr = input->GetScalarPointer(); switch ( scalarType ) { vtkTemplateMacro( vtkVolumeTextureMapper3DComputeScalars( static_cast(dataPtr), this, offset, scale, this->Volume1Index, this->Volume2Index)); } this->SavedTextureInput = input; this->SavedTextureMTime.Modified(); return true; } //----------------------------------------------------------------------------- bool vtkMitkOpenGLVolumeTextureMapper3D::UpdateVolumesRGBA(vtkVolume *vtkNotUsed(vol)) { // Get the image data vtkImageData *input = this->GetInput(); - input->Update(); +// input->Update(); //VTK6_TODO bool needUpdate = false; // Has the volume changed in some way? if ( this->SavedTextureInput != input || this->SavedTextureMTime.GetMTime() < input->GetMTime() ) needUpdate = true; // Do we have any volume on the gpu already? if(!this->Volume1Index) needUpdate = true; if(!needUpdate) return true; MITK_INFO << "updating rgba volume"; ComputeVolumeDimensions(); // Allocating volume on gpu { // Deleting old textures this->DeleteTextureIndex(&this->Volume1Index); this->DeleteTextureIndex(&this->Volume2Index); this->DeleteTextureIndex(&this->Volume3Index); this->CreateTextureIndex(&this->Volume1Index); this->CreateTextureIndex(&this->Volume2Index); int dim[3]; this->GetVolumeDimensions(dim); MITK_INFO << "allocating volume on gpu"; GLint gradientScalarTextureFormat = GL_RGBA8; GLint colorTextureFormat = GL_RGB8; if(this->UseCompressedTexture && SupportsCompressedTexture) { gradientScalarTextureFormat = myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT; colorTextureFormat = myGL_COMPRESSED_RGB_S3TC_DXT1_EXT; } vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,gradientScalarTextureFormat,dim[0],dim[1],dim[2],0,GL_RGBA,GL_UNSIGNED_BYTE,0); this->Setup3DTextureParameters( true ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,colorTextureFormat,dim[0],dim[1],dim[2],0,GL_RGB,GL_UNSIGNED_BYTE,0); this->Setup3DTextureParameters( true ); } // Transfer the input volume to the RGBA volume unsigned char *dataPtr = (unsigned char*)input->GetScalarPointer(); vtkVolumeTextureMapper3DComputeRGBA( dataPtr, this, this->Volume1Index, this->Volume2Index); this->SavedTextureInput = input; this->SavedTextureMTime.Modified(); return true; } void vtkMitkOpenGLVolumeTextureMapper3D::Setup3DTextureParameters( bool linear ) { //GPU_INFO << "Setup3DTextureParameters"; if( linear ) { glTexParameterf( vtkgl::TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf( vtkgl::TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); } else { glTexParameterf( vtkgl::TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameterf( vtkgl::TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); } glTexParameterf( vtkgl::TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameterf( vtkgl::TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP ); } void vtkMitkOpenGLVolumeTextureMapper3D::SetupOneIndependentTextures( vtkRenderer *vtkNotUsed(ren), vtkVolume *vol ) { // Update the volume containing the 2 byte scalar / gradient magnitude this->UpdateVolumes( vol ); // Update the dependent 2D color table mapping scalar value and // gradient magnitude to RGBA if ( this->UpdateColorLookup( vol ) || !this->ColorLookupIndex ) { this->DeleteTextureIndex( &this->ColorLookupIndex ); this->DeleteTextureIndex( &this->AlphaLookupIndex ); this->CreateTextureIndex( &this->ColorLookupIndex ); vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); //MITK_INFO << "uploading transferfunction"; GLint colorLookupTextureFormat = GL_RGBA8; if(this->UseCompressedTexture && SupportsCompressedTexture) colorLookupTextureFormat = myGL_COMPRESSED_RGBA_S3TC_DXT5_EXT; glTexImage2D( GL_TEXTURE_2D, 0,colorLookupTextureFormat, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, this->ColorLookup ); } } void vtkMitkOpenGLVolumeTextureMapper3D::SetupRGBATextures( vtkRenderer *vtkNotUsed(ren), vtkVolume *vol ) { MITK_INFO << "SetupFourDependentTextures"; this->UpdateVolumesRGBA(vol); /* vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); // Update the volume containing the 3 byte scalars / gradient magnitude if ( this->UpdateVolumes( vol ) || !this->Volume1Index || !this->Volume2Index || !this->Volume3Index ) { int dim[3]; this->GetVolumeDimensions(dim); vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); glBindTexture(vtkgl::TEXTURE_3D,0); this->DeleteTextureIndex(&this->Volume1Index); this->CreateTextureIndex(&this->Volume1Index); glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,this->InternalRGB,dim[0],dim[1], dim[2],0,GL_RGB,GL_UNSIGNED_BYTE,this->Volume1); vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); glBindTexture(vtkgl::TEXTURE_3D,0); this->DeleteTextureIndex(&this->Volume2Index); this->CreateTextureIndex(&this->Volume2Index); glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,this->InternalLA,dim[0],dim[1], dim[2],0,GL_LUMINANCE_ALPHA,GL_UNSIGNED_BYTE, this->Volume2); vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); glBindTexture(vtkgl::TEXTURE_3D,0); this->DeleteTextureIndex(&this->Volume3Index); this->CreateTextureIndex(&this->Volume3Index); glBindTexture(vtkgl::TEXTURE_3D, this->Volume3Index); vtkgl::TexImage3D(vtkgl::TEXTURE_3D,0,this->InternalRGB,dim[0],dim[1], dim[2],0,GL_RGB,GL_UNSIGNED_BYTE,this->Volume3); } vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); this->Setup3DTextureParameters( true ); vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); this->Setup3DTextureParameters( true ); vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); glBindTexture(vtkgl::TEXTURE_3D_EXT, this->Volume3Index); this->Setup3DTextureParameters( true ); vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); glEnable( GL_TEXTURE_2D ); glDisable( vtkgl::TEXTURE_3D ); // Update the dependent 2D table mapping scalar value and // gradient magnitude to opacity if ( this->UpdateColorLookup( vol ) || !this->AlphaLookupIndex ) { this->DeleteTextureIndex(&this->ColorLookupIndex); vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); glBindTexture(GL_TEXTURE_2D,0); this->DeleteTextureIndex(&this->AlphaLookupIndex); this->CreateTextureIndex(&this->AlphaLookupIndex); glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); //MITK_INFO << "uploading transferfunction"; glTexImage2D(GL_TEXTURE_2D,0,this->InternalAlpha, 256, 256, 0, GL_ALPHA, GL_UNSIGNED_BYTE, this->AlphaLookup ); } vtkgl::ActiveTexture( vtkgl::TEXTURE3 ); glBindTexture(GL_TEXTURE_2D, this->AlphaLookupIndex); */ } void vtkMitkOpenGLVolumeTextureMapper3D::RenderOneIndependentShadeFP( vtkRenderer *ren, vtkVolume *vol ) { //GPU_INFO << "RenderOneIndependentShadeFP"; this->SetupOneIndependentTextures( ren, vol ); glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, prgOneComponentShade ); this->SetupProgramLocalsForShadingFP( ren, vol ); // Bind Textures { vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); glEnable( GL_TEXTURE_2D ); glDisable( vtkgl::TEXTURE_3D ); glBindTexture(GL_TEXTURE_2D, this->ColorLookupIndex); vtkgl::ActiveTexture( vtkgl::TEXTURE2 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); } int stages[4] = {1,1,1,0}; this->RenderPolygons( ren, vol, stages ); glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); } void vtkMitkOpenGLVolumeTextureMapper3D::RenderRGBAShadeFP( vtkRenderer *ren, vtkVolume *vol ) { this->SetupRGBATextures(ren, vol); glEnable( vtkgl::FRAGMENT_PROGRAM_ARB ); vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, prgRGBAShade ); this->SetupProgramLocalsForShadingFP( ren, vol ); // Bind Textures { vtkgl::ActiveTexture( vtkgl::TEXTURE0 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume1Index); vtkgl::ActiveTexture( vtkgl::TEXTURE1 ); glDisable( GL_TEXTURE_2D ); glEnable( vtkgl::TEXTURE_3D ); glBindTexture(vtkgl::TEXTURE_3D, this->Volume2Index); } int stages[4] = {1,1,1,0}; this->RenderPolygons( ren, vol, stages ); glDisable( vtkgl::FRAGMENT_PROGRAM_ARB ); } void vtkMitkOpenGLVolumeTextureMapper3D::GetLightInformation( vtkRenderer *ren, vtkVolume *vol, GLfloat lightDirection[2][4], GLfloat lightDiffuseColor[2][4], GLfloat lightSpecularColor[2][4], GLfloat halfwayVector[2][4], GLfloat ambientColor[4] ) { //GPU_INFO << "GetLightInformation"; float ambient = vol->GetProperty()->GetAmbient(); float diffuse = vol->GetProperty()->GetDiffuse(); float specular = vol->GetProperty()->GetSpecular(); vtkTransform *volumeTransform = vtkTransform::New(); volumeTransform->SetMatrix( vol->GetMatrix() ); volumeTransform->Inverse(); vtkLightCollection *lights = ren->GetLights(); lights->InitTraversal(); vtkLight *light[2]; light[0] = lights->GetNextItem(); light[1] = lights->GetNextItem(); int lightIndex = 0; double cameraPosition[3]; double cameraFocalPoint[3]; ren->GetActiveCamera()->GetPosition( cameraPosition ); ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint ); double viewDirection[3]; volumeTransform->TransformPoint( cameraPosition, cameraPosition ); volumeTransform->TransformPoint( cameraFocalPoint, cameraFocalPoint ); viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; vtkMath::Normalize( viewDirection ); ambientColor[0] = 0.0; ambientColor[1] = 0.0; ambientColor[2] = 0.0; ambientColor[3] = 0.0; for ( lightIndex = 0; lightIndex < 2; lightIndex++ ) { float dir[3] = {0,0,0}; float half[3] = {0,0,0}; if ( light[lightIndex] == NULL || light[lightIndex]->GetSwitch() == 0 ) { lightDiffuseColor[lightIndex][0] = 0.0; lightDiffuseColor[lightIndex][1] = 0.0; lightDiffuseColor[lightIndex][2] = 0.0; lightDiffuseColor[lightIndex][3] = 0.0; lightSpecularColor[lightIndex][0] = 0.0; lightSpecularColor[lightIndex][1] = 0.0; lightSpecularColor[lightIndex][2] = 0.0; lightSpecularColor[lightIndex][3] = 0.0; } else { float lightIntensity = light[lightIndex]->GetIntensity(); double lightColor[3]; light[lightIndex]->GetDiffuseColor( lightColor ); double lightPosition[3]; double lightFocalPoint[3]; light[lightIndex]->GetTransformedPosition( lightPosition ); light[lightIndex]->GetTransformedFocalPoint( lightFocalPoint ); volumeTransform->TransformPoint( lightPosition, lightPosition ); volumeTransform->TransformPoint( lightFocalPoint, lightFocalPoint ); dir[0] = lightPosition[0] - lightFocalPoint[0]; dir[1] = lightPosition[1] - lightFocalPoint[1]; dir[2] = lightPosition[2] - lightFocalPoint[2]; vtkMath::Normalize( dir ); lightDiffuseColor[lightIndex][0] = lightColor[0]*diffuse*lightIntensity; lightDiffuseColor[lightIndex][1] = lightColor[1]*diffuse*lightIntensity; lightDiffuseColor[lightIndex][2] = lightColor[2]*diffuse*lightIntensity; lightDiffuseColor[lightIndex][3] = 1.0; lightSpecularColor[lightIndex][0]= lightColor[0]*specular*lightIntensity; lightSpecularColor[lightIndex][1]= lightColor[1]*specular*lightIntensity; lightSpecularColor[lightIndex][2]= lightColor[2]*specular*lightIntensity; lightSpecularColor[lightIndex][3] = 0.0; half[0] = dir[0] - viewDirection[0]; half[1] = dir[1] - viewDirection[1]; half[2] = dir[2] - viewDirection[2]; vtkMath::Normalize( half ); ambientColor[0] += ambient*lightColor[0]; ambientColor[1] += ambient*lightColor[1]; ambientColor[2] += ambient*lightColor[2]; } lightDirection[lightIndex][0] = (dir[0]+1.0)/2.0; lightDirection[lightIndex][1] = (dir[1]+1.0)/2.0; lightDirection[lightIndex][2] = (dir[2]+1.0)/2.0; lightDirection[lightIndex][3] = 0.0; halfwayVector[lightIndex][0] = (half[0]+1.0)/2.0; halfwayVector[lightIndex][1] = (half[1]+1.0)/2.0; halfwayVector[lightIndex][2] = (half[2]+1.0)/2.0; halfwayVector[lightIndex][3] = 0.0; } volumeTransform->Delete(); } void vtkMitkOpenGLVolumeTextureMapper3D::SetupProgramLocalsForShadingFP( vtkRenderer *ren, vtkVolume *vol ) { //GPU_INFO << "SetupProgramLocalsForShadingFP"; GLfloat lightDirection[2][4]; GLfloat lightDiffuseColor[2][4]; GLfloat lightSpecularColor[2][4]; GLfloat halfwayVector[2][4]; GLfloat ambientColor[4]; float ambient = vol->GetProperty()->GetAmbient(); float diffuse = vol->GetProperty()->GetDiffuse(); float specular = vol->GetProperty()->GetSpecular(); float specularPower = vol->GetProperty()->GetSpecularPower(); vtkTransform *volumeTransform = vtkTransform::New(); volumeTransform->SetMatrix( vol->GetMatrix() ); volumeTransform->Inverse(); vtkLightCollection *lights = ren->GetLights(); lights->InitTraversal(); vtkLight *light[2]; light[0] = lights->GetNextItem(); light[1] = lights->GetNextItem(); int lightIndex = 0; double cameraPosition[3]; double cameraFocalPoint[3]; ren->GetActiveCamera()->GetPosition( cameraPosition ); ren->GetActiveCamera()->GetFocalPoint( cameraFocalPoint ); volumeTransform->TransformPoint( cameraPosition, cameraPosition ); volumeTransform->TransformPoint( cameraFocalPoint, cameraFocalPoint ); double viewDirection[4]; viewDirection[0] = cameraFocalPoint[0] - cameraPosition[0]; viewDirection[1] = cameraFocalPoint[1] - cameraPosition[1]; viewDirection[2] = cameraFocalPoint[2] - cameraPosition[2]; viewDirection[3] = 0.0; vtkMath::Normalize( viewDirection ); ambientColor[0] = 0.0; ambientColor[1] = 0.0; ambientColor[2] = 0.0; ambientColor[3] = 0.0; for ( lightIndex = 0; lightIndex < 2; lightIndex++ ) { float dir[3] = {0,0,0}; float half[3] = {0,0,0}; if ( light[lightIndex] == NULL || light[lightIndex]->GetSwitch() == 0 ) { lightDiffuseColor[lightIndex][0] = 0.0; lightDiffuseColor[lightIndex][1] = 0.0; lightDiffuseColor[lightIndex][2] = 0.0; lightDiffuseColor[lightIndex][3] = 0.0; lightSpecularColor[lightIndex][0] = 0.0; lightSpecularColor[lightIndex][1] = 0.0; lightSpecularColor[lightIndex][2] = 0.0; lightSpecularColor[lightIndex][3] = 0.0; } else { float lightIntensity = light[lightIndex]->GetIntensity(); double lightColor[3]; light[lightIndex]->GetDiffuseColor( lightColor ); double lightPosition[3]; double lightFocalPoint[3]; light[lightIndex]->GetTransformedPosition( lightPosition ); light[lightIndex]->GetTransformedFocalPoint( lightFocalPoint ); volumeTransform->TransformPoint( lightPosition, lightPosition ); volumeTransform->TransformPoint( lightFocalPoint, lightFocalPoint ); dir[0] = lightPosition[0] - lightFocalPoint[0]; dir[1] = lightPosition[1] - lightFocalPoint[1]; dir[2] = lightPosition[2] - lightFocalPoint[2]; vtkMath::Normalize( dir ); lightDiffuseColor[lightIndex][0] = lightColor[0]*diffuse*lightIntensity; lightDiffuseColor[lightIndex][1] = lightColor[1]*diffuse*lightIntensity; lightDiffuseColor[lightIndex][2] = lightColor[2]*diffuse*lightIntensity; lightDiffuseColor[lightIndex][3] = 0.0; lightSpecularColor[lightIndex][0]= lightColor[0]*specular*lightIntensity; lightSpecularColor[lightIndex][1]= lightColor[1]*specular*lightIntensity; lightSpecularColor[lightIndex][2]= lightColor[2]*specular*lightIntensity; lightSpecularColor[lightIndex][3] = 0.0; half[0] = dir[0] - viewDirection[0]; half[1] = dir[1] - viewDirection[1]; half[2] = dir[2] - viewDirection[2]; vtkMath::Normalize( half ); ambientColor[0] += ambient*lightColor[0]; ambientColor[1] += ambient*lightColor[1]; ambientColor[2] += ambient*lightColor[2]; } lightDirection[lightIndex][0] = dir[0]; lightDirection[lightIndex][1] = dir[1]; lightDirection[lightIndex][2] = dir[2]; lightDirection[lightIndex][3] = 0.0; halfwayVector[lightIndex][0] = half[0]; halfwayVector[lightIndex][1] = half[1]; halfwayVector[lightIndex][2] = half[2]; halfwayVector[lightIndex][3] = 0.0; } volumeTransform->Delete(); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 0, lightDirection[0][0], lightDirection[0][1], lightDirection[0][2], lightDirection[0][3] ); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 1, halfwayVector[0][0], halfwayVector[0][1], halfwayVector[0][2], halfwayVector[0][3] ); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 2, ambient, diffuse, specular, specularPower ); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 3, lightDiffuseColor[0][0], lightDiffuseColor[0][1], lightDiffuseColor[0][2], lightDiffuseColor[0][3] ); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 4, lightSpecularColor[0][0], lightSpecularColor[0][1], lightSpecularColor[0][2], lightSpecularColor[0][3] ); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 5, viewDirection[0], viewDirection[1], viewDirection[2], viewDirection[3] ); vtkgl::ProgramLocalParameter4fARB( vtkgl::FRAGMENT_PROGRAM_ARB, 6, 2.0, -1.0, 0.0, 0.0 ); } int vtkMitkOpenGLVolumeTextureMapper3D::IsRenderSupported( vtkRenderer *renderer, vtkVolumeProperty *property ) { //GPU_INFO << "IsRenderSupported"; if ( !this->Initialized ) { //this->Initialize(); this->Initialize(renderer); } if ( !this->RenderPossible ) { return 0; } if ( !this->GetInput() ) { return 0; } if ( this->GetInput()->GetNumberOfScalarComponents() > 1 && property->GetIndependentComponents() ) { return 0; } return 1; } void vtkMitkOpenGLVolumeTextureMapper3D::Initialize(vtkRenderer *renderer) { //GPU_INFO << "Initialize"; this->Initialized = 1; // vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New(); //extensions->SetRenderWindow(NULL); // set render window to the current one. vtkOpenGLExtensionManager *extensions=static_cast(renderer->GetRenderWindow())->GetExtensionManager(); int supports_texture3D=extensions->ExtensionSupported( "GL_VERSION_1_2" ); if(supports_texture3D) { extensions->LoadExtension("GL_VERSION_1_2"); } else { supports_texture3D=extensions->ExtensionSupported( "GL_EXT_texture3D" ); if(supports_texture3D) { extensions->LoadCorePromotedExtension("GL_EXT_texture3D"); } } int supports_multitexture=extensions->ExtensionSupported( "GL_VERSION_1_3" ); if(supports_multitexture) { extensions->LoadExtension("GL_VERSION_1_3"); } else { supports_multitexture= extensions->ExtensionSupported("GL_ARB_multitexture"); if(supports_multitexture) { extensions->LoadCorePromotedExtension("GL_ARB_multitexture"); } } this->SupportsCompressedTexture=extensions->ExtensionSupported("GL_VERSION_1_3")==1; if(!this->SupportsCompressedTexture) { this->SupportsCompressedTexture= extensions->ExtensionSupported("GL_ARB_texture_compression")==1; if(this->SupportsCompressedTexture) { extensions->LoadCorePromotedExtension("GL_ARB_texture_compression"); } } //GPU_INFO(this->SupportsCompressedTexture) << "supporting compressed textures"; this->SupportsNonPowerOfTwoTextures= extensions->ExtensionSupported("GL_VERSION_2_0") || extensions->ExtensionSupported("GL_ARB_texture_non_power_of_two"); //GPU_INFO << "np2: " << (this->SupportsNonPowerOfTwoTextures?1:0); int supports_GL_ARB_fragment_program = extensions->ExtensionSupported( "GL_ARB_fragment_program" ); if(supports_GL_ARB_fragment_program) { extensions->LoadExtension( "GL_ARB_fragment_program" ); } int supports_GL_ARB_vertex_program = extensions->ExtensionSupported( "GL_ARB_vertex_program" ); if(supports_GL_ARB_vertex_program) { extensions->LoadExtension( "GL_ARB_vertex_program" ); } RenderPossible = 0; if ( supports_texture3D && supports_multitexture && supports_GL_ARB_fragment_program && supports_GL_ARB_vertex_program && vtkgl::TexImage3D && vtkgl::ActiveTexture && vtkgl::MultiTexCoord3fv && vtkgl::GenProgramsARB && vtkgl::DeleteProgramsARB && vtkgl::BindProgramARB && vtkgl::ProgramStringARB && vtkgl::ProgramLocalParameter4fARB ) { RenderPossible = 1; } else { std::string errString = "no gpu-acceleration possible cause following extensions/methods are missing or unsupported:"; if(!supports_texture3D) errString += " EXT_TEXTURE3D"; if(!supports_multitexture) errString += " EXT_MULTITEXTURE"; if(!supports_GL_ARB_fragment_program) errString += " ARB_FRAGMENT_PROGRAM"; if(!supports_GL_ARB_vertex_program) errString += " ARB_VERTEX_PROGRAM"; if(!vtkgl::TexImage3D) errString += " glTexImage3D"; if(!vtkgl::ActiveTexture) errString += " glActiveTexture"; if(!vtkgl::MultiTexCoord3fv) errString += " glMultiTexCoord3fv"; if(!vtkgl::GenProgramsARB) errString += " glGenProgramsARB"; if(!vtkgl::DeleteProgramsARB) errString += " glDeleteProgramsARB"; if(!vtkgl::BindProgramARB) errString += " glBindProgramARB"; if(!vtkgl::ProgramStringARB) errString += " glProgramStringARB"; if(!vtkgl::ProgramLocalParameter4fARB) errString += " glProgramLocalParameter4fARB"; GPU_WARN << errString; }; if(RenderPossible) { vtkgl::GenProgramsARB( 1, &prgOneComponentShade ); vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, prgOneComponentShade ); vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, vtkgl::PROGRAM_FORMAT_ASCII_ARB, static_cast(strlen(vtkMitkVolumeTextureMapper3D_OneComponentShadeFP)), vtkMitkVolumeTextureMapper3D_OneComponentShadeFP ); vtkgl::GenProgramsARB( 1, &prgRGBAShade ); vtkgl::BindProgramARB( vtkgl::FRAGMENT_PROGRAM_ARB, prgRGBAShade ); vtkgl::ProgramStringARB( vtkgl::FRAGMENT_PROGRAM_ARB, vtkgl::PROGRAM_FORMAT_ASCII_ARB, static_cast(strlen(vtkMitkVolumeTextureMapper3D_FourDependentShadeFP)), vtkMitkVolumeTextureMapper3D_FourDependentShadeFP ); } } // ---------------------------------------------------------------------------- // Print the vtkMitkOpenGLVolumeTextureMapper3D void vtkMitkOpenGLVolumeTextureMapper3D::PrintSelf(ostream& os, vtkIndent indent) { // vtkOpenGLExtensionManager * extensions = vtkOpenGLExtensionManager::New(); // extensions->SetRenderWindow(NULL); // set render window to current render window os << indent << "Initialized " << this->Initialized << endl; /* if ( this->Initialized ) { os << indent << "Supports GL_VERSION_1_2:" << extensions->ExtensionSupported( "GL_VERSION_1_2" ) << endl; os << indent << "Supports GL_EXT_texture3D:" << extensions->ExtensionSupported( "GL_EXT_texture3D" ) << endl; os << indent << "Supports GL_VERSION_1_3:" << extensions->ExtensionSupported( "GL_VERSION_1_3" ) << endl; os << indent << "Supports GL_ARB_multitexture: " << extensions->ExtensionSupported( "GL_ARB_multitexture" ) << endl; os << indent << "Supports GL_NV_texture_shader2: " << extensions->ExtensionSupported( "GL_NV_texture_shader2" ) << endl; os << indent << "Supports GL_NV_register_combiners2: " << extensions->ExtensionSupported( "GL_NV_register_combiners2" ) << endl; os << indent << "Supports GL_ATI_fragment_shader: " << extensions->ExtensionSupported( "GL_ATI_fragment_shader" ) << endl; os << indent << "Supports GL_ARB_fragment_program: " << extensions->ExtensionSupported( "GL_ARB_fragment_program" ) << endl; os << indent << "Supports GL_ARB_texture_compression: " << extensions->ExtensionSupported( "GL_ARB_texture_compression" ) << endl; os << indent << "Supports GL_VERSION_2_0:" << extensions->ExtensionSupported( "GL_VERSION_2_0" ) << endl; os << indent << "Supports GL_ARB_texture_non_power_of_two:" << extensions->ExtensionSupported( "GL_ARB_texture_non_power_of_two" ) << endl; } extensions->Delete(); */ if(this->RenderWindow!=0) { vtkOpenGLExtensionManager *extensions= static_cast(this->RenderWindow)->GetExtensionManager(); if ( this->Initialized ) { os << indent << "Supports GL_VERSION_1_2:" << extensions->ExtensionSupported( "GL_VERSION_1_2" ) << endl; os << indent << "Supports GL_EXT_texture3D:" << extensions->ExtensionSupported( "GL_EXT_texture3D" ) << endl; os << indent << "Supports GL_VERSION_1_3:" << extensions->ExtensionSupported( "GL_VERSION_1_3" ) << endl; os << indent << "Supports GL_ARB_multitexture: " << extensions->ExtensionSupported( "GL_ARB_multitexture" ) << endl; os << indent << "Supports GL_NV_texture_shader2: " << extensions->ExtensionSupported( "GL_NV_texture_shader2" ) << endl; os << indent << "Supports GL_NV_register_combiners2: " << extensions->ExtensionSupported( "GL_NV_register_combiners2" ) << endl; os << indent << "Supports GL_ATI_fragment_shader: " << extensions->ExtensionSupported( "GL_ATI_fragment_shader" ) << endl; os << indent << "Supports GL_ARB_fragment_program: " << extensions->ExtensionSupported( "GL_ARB_fragment_program" ) << endl; os << indent << "Supports GL_ARB_texture_compression: " << extensions->ExtensionSupported( "GL_ARB_texture_compression" ) << endl; os << indent << "Supports GL_VERSION_2_0:" << extensions->ExtensionSupported( "GL_VERSION_2_0" ) << endl; os << indent << "Supports GL_ARB_texture_non_power_of_two:" << extensions->ExtensionSupported( "GL_ARB_texture_non_power_of_two" ) << endl; } } this->Superclass::PrintSelf(os,indent); } diff --git a/Modules/MitkExt/Rendering/vtkUnstructuredGridMapper.cpp b/Modules/MitkExt/Rendering/vtkUnstructuredGridMapper.cpp index 8c57d69101..2c230737c7 100644 --- a/Modules/MitkExt/Rendering/vtkUnstructuredGridMapper.cpp +++ b/Modules/MitkExt/Rendering/vtkUnstructuredGridMapper.cpp @@ -1,238 +1,238 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "vtkUnstructuredGridMapper.h" #include "vtkGeometryFilter.h" #include "vtkExecutive.h" #include "vtkGarbageCollector.h" #include "vtkInformation.h" #include "vtkObjectFactory.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkUnstructuredGrid.h" vtkStandardNewMacro(vtkUnstructuredGridMapper); //---------------------------------------------------------------------------- vtkUnstructuredGridMapper::vtkUnstructuredGridMapper() { this->GeometryExtractor = 0; this->PolyDataMapper = 0; } //---------------------------------------------------------------------------- vtkUnstructuredGridMapper::~vtkUnstructuredGridMapper() { // delete internally created objects. if ( this->GeometryExtractor ) { this->GeometryExtractor->Delete(); } if ( this->PolyDataMapper ) { this->PolyDataMapper->Delete(); } } void vtkUnstructuredGridMapper::SetBoundingObject(mitk::BoundingObject* bo) { m_BoundingObject = bo; } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::SetInput(vtkUnstructuredGrid *input) { if(input) { - this->SetInputConnection(0, input->GetProducerPort()); + this->SetInput(input); } else { // Setting a NULL input removes the connection. - this->SetInputConnection(0, 0); + this->SetInput(0); } } //---------------------------------------------------------------------------- vtkUnstructuredGrid *vtkUnstructuredGridMapper::GetInput() { //return this->Superclass::GetInputAsDataSet(); return vtkUnstructuredGrid::SafeDownCast( this->GetExecutive()->GetInputData(0, 0)); } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::ReleaseGraphicsResources( vtkWindow *renWin ) { if (this->PolyDataMapper) { this->PolyDataMapper->ReleaseGraphicsResources( renWin ); } } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::ReleaseGraphicsResources( mitk::BaseRenderer * renderer ) { if (this->PolyDataMapper) { this->PolyDataMapper->ReleaseGraphicsResources( renderer->GetVtkRenderer()->GetRenderWindow()); } } //---------------------------------------------------------------------------- // Receives from Actor -> maps data to primitives // void vtkUnstructuredGridMapper::Render(vtkRenderer *ren, vtkActor *act) { // make sure that we've been properly initialized // if ( !this->GetInput() ) { vtkErrorMacro(<< "No input!\n"); return; } // Need a lookup table // if ( this->LookupTable == 0 ) { this->CreateDefaultLookupTable(); } this->LookupTable->Build(); // Now can create appropriate mapper // if ( this->PolyDataMapper == 0 ) { vtkGeometryFilter *gf = vtkGeometryFilter::New(); vtkPolyDataMapper *pm = vtkPolyDataMapper::New(); - pm->SetInput(gf->GetOutput()); + pm->SetInputData(gf->GetOutput()); this->GeometryExtractor = gf; this->PolyDataMapper = pm; } // share clipping planes with the PolyDataMapper // if (this->ClippingPlanes != this->PolyDataMapper->GetClippingPlanes()) { this->PolyDataMapper->SetClippingPlanes(this->ClippingPlanes); } if (this->m_BoundingObject) { mitk::BoundingBox::BoundsArrayType bounds = this->m_BoundingObject->GetGeometry()->CalculateBoundingBoxRelativeToTransform(0)->GetBounds(); this->GeometryExtractor->SetExtent(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]); this->GeometryExtractor->ExtentClippingOn(); } else { this->GeometryExtractor->ExtentClippingOff(); } - this->GeometryExtractor->SetInput(this->GetInput()); - this->PolyDataMapper->SetInput(this->GeometryExtractor->GetOutput()); + this->GeometryExtractor->SetInputData(this->GetInput()); + this->PolyDataMapper->SetInputData(this->GeometryExtractor->GetOutput()); // update ourselves in case something has changed this->PolyDataMapper->SetLookupTable(this->GetLookupTable()); this->PolyDataMapper->SetScalarVisibility(this->GetScalarVisibility()); this->PolyDataMapper->SetUseLookupTableScalarRange( this->GetUseLookupTableScalarRange()); this->PolyDataMapper->SetScalarRange(this->GetScalarRange()); this->PolyDataMapper->SetImmediateModeRendering( this->GetImmediateModeRendering()); this->PolyDataMapper->SetColorMode(this->GetColorMode()); this->PolyDataMapper->SetInterpolateScalarsBeforeMapping( this->GetInterpolateScalarsBeforeMapping()); this->PolyDataMapper->SetScalarMode(this->GetScalarMode()); if ( this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA || this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA ) { if ( this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID ) { this->PolyDataMapper->ColorByArrayComponent(this->ArrayId,ArrayComponent); } else { this->PolyDataMapper->ColorByArrayComponent(this->ArrayName,ArrayComponent); } } this->PolyDataMapper->Render(ren,act); this->TimeToDraw = this->PolyDataMapper->GetTimeToDraw(); } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); if ( this->PolyDataMapper ) { os << indent << "Poly Mapper: (" << this->PolyDataMapper << ")\n"; } else { os << indent << "Poly Mapper: (none)\n"; } if ( this->GeometryExtractor ) { os << indent << "Geometry Extractor: (" << this->GeometryExtractor << ")\n"; } else { os << indent << "Geometry Extractor: (none)\n"; } } //---------------------------------------------------------------------------- unsigned long vtkUnstructuredGridMapper::GetMTime() { unsigned long mTime=this->vtkMapper::GetMTime(); unsigned long time; if ( this->LookupTable != NULL ) { time = this->LookupTable->GetMTime(); mTime = ( time > mTime ? time : mTime ); } return mTime; } //---------------------------------------------------------------------------- int vtkUnstructuredGridMapper::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); return 1; } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::ReportReferences(vtkGarbageCollector* collector) { this->Superclass::ReportReferences(collector); // These filters share our input and are therefore involved in a // reference loop. vtkGarbageCollectorReport(collector, this->GeometryExtractor, "GeometryExtractor"); vtkGarbageCollectorReport(collector, this->PolyDataMapper, "PolyDataMapper"); } diff --git a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp index 8c9375727a..f668134052 100644 --- a/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp +++ b/Modules/SurfaceInterpolation/mitkSurfaceInterpolationController.cpp @@ -1,317 +1,317 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceInterpolationController.h" #include "mitkMemoryUtilities.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkImageToSurfaceFilter.h" mitk::SurfaceInterpolationController::SurfaceInterpolationController() :m_SelectedSegmentation(0) { m_ReduceFilter = ReduceContourSetFilter::New(); m_NormalsFilter = ComputeContourSetNormalsFilter::New(); m_InterpolateSurfaceFilter = CreateDistanceImageFromSurfaceFilter::New(); m_ReduceFilter->SetUseProgressBar(false); m_NormalsFilter->SetUseProgressBar(false); m_InterpolateSurfaceFilter->SetUseProgressBar(false); m_Contours = Surface::New(); m_PolyData = vtkSmartPointer::New(); m_PolyData->SetPoints(vtkPoints::New()); m_InterpolationResult = 0; m_CurrentNumberOfReducedContours = 0; } mitk::SurfaceInterpolationController::~SurfaceInterpolationController() { ContourListMap::iterator it = m_MapOfContourLists.begin(); for (; it != m_MapOfContourLists.end(); it++) { for (unsigned int j = 0; j < m_MapOfContourLists[(*it).first].size(); ++j) { delete(m_MapOfContourLists[(*it).first].at(j).position); } m_MapOfContourLists.erase(it); } //Removing all observers std::map::iterator dataIter = m_SegmentationObserverTags.begin(); for (; dataIter != m_SegmentationObserverTags.end(); ++dataIter ) { (*dataIter).first->GetProperty("visible")->RemoveObserver( (*dataIter).second ); } m_SegmentationObserverTags.clear(); } mitk::SurfaceInterpolationController* mitk::SurfaceInterpolationController::GetInstance() { static mitk::SurfaceInterpolationController* m_Instance; if ( m_Instance == 0) { m_Instance = new SurfaceInterpolationController(); } return m_Instance; } void mitk::SurfaceInterpolationController::AddNewContour (mitk::Surface::Pointer newContour ,RestorePlanePositionOperation* op) { AffineTransform3D::Pointer transform = AffineTransform3D::New(); transform = op->GetTransform(); mitk::Vector3D direction = op->GetDirectionVector(); int pos (-1); for (unsigned int i = 0; i < m_MapOfContourLists[m_SelectedSegmentation].size(); i++) { itk::Matrix diffM = transform->GetMatrix()-m_MapOfContourLists[m_SelectedSegmentation].at(i).position->GetTransform()->GetMatrix(); bool isSameMatrix(true); for (unsigned int j = 0; j < 3; j++) { if (fabs(diffM[j][0]) > 0.0001 && fabs(diffM[j][1]) > 0.0001 && fabs(diffM[j][2]) > 0.0001) { isSameMatrix = false; break; } } itk::Vector diffV = m_MapOfContourLists[m_SelectedSegmentation].at(i).position->GetTransform()->GetOffset()-transform->GetOffset(); if ( isSameMatrix && m_MapOfContourLists[m_SelectedSegmentation].at(i).position->GetPos() == op->GetPos() && (fabs(diffV[0]) < 0.0001 && fabs(diffV[1]) < 0.0001 && fabs(diffV[2]) < 0.0001) ) { pos = i; break; } } //Don't save a new empty contour if (pos == -1 && newContour->GetVtkPolyData()->GetNumberOfPoints() > 0) { mitk::RestorePlanePositionOperation* newOp = new mitk::RestorePlanePositionOperation (OpRESTOREPLANEPOSITION, op->GetWidth(), op->GetHeight(), op->GetSpacing(), op->GetPos(), direction, transform); ContourPositionPair newData; newData.contour = newContour; newData.position = newOp; m_ReduceFilter->SetInput(m_MapOfContourLists[m_SelectedSegmentation].size(), newContour); m_MapOfContourLists[m_SelectedSegmentation].push_back(newData); } //Edit a existing contour. If the contour is empty, edit it anyway so that the interpolation will always be consistent else if (pos != -1) { m_MapOfContourLists[m_SelectedSegmentation].at(pos).contour = newContour; m_ReduceFilter->SetInput(pos, newContour); } m_ReduceFilter->Update(); m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs(); for (unsigned int i = 0; i < m_CurrentNumberOfReducedContours; i++) { m_NormalsFilter->SetInput(i, m_ReduceFilter->GetOutput(i)); m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i)); } this->Modified(); } void mitk::SurfaceInterpolationController::Interpolate() { if (m_CurrentNumberOfReducedContours< 2) { //If no interpolation is possible reset the interpolation result m_InterpolationResult = 0; return; } //Setting up progress bar /* * Removed due to bug 12441. ProgressBar messes around with Qt event queue which is fatal for segmentation */ //mitk::ProgressBar::GetInstance()->AddStepsToDo(8); // update the filter and get teh resulting distance-image m_InterpolateSurfaceFilter->Update(); Image::Pointer distanceImage = m_InterpolateSurfaceFilter->GetOutput(); // create a surface from the distance-image mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New(); imageToSurfaceFilter->SetInput( distanceImage ); imageToSurfaceFilter->SetThreshold( 0 ); imageToSurfaceFilter->Update(); m_InterpolationResult = imageToSurfaceFilter->GetOutput(); vtkSmartPointer polyDataAppender = vtkSmartPointer::New(); for (unsigned int i = 0; i < m_ReduceFilter->GetNumberOfOutputs(); i++) { - polyDataAppender->AddInput(m_ReduceFilter->GetOutput(i)->GetVtkPolyData()); + polyDataAppender->AddInputData(m_ReduceFilter->GetOutput(i)->GetVtkPolyData()); } polyDataAppender->Update(); m_Contours->SetVtkPolyData(polyDataAppender->GetOutput()); //Last progress step /* * Removed due to bug 12441. ProgressBar messes around with Qt event queue which is fatal for segmentation */ //mitk::ProgressBar::GetInstance()->Progress(8); m_InterpolationResult->DisconnectPipeline(); } mitk::Surface::Pointer mitk::SurfaceInterpolationController::GetInterpolationResult() { return m_InterpolationResult; } mitk::Surface* mitk::SurfaceInterpolationController::GetContoursAsSurface() { return m_Contours; } void mitk::SurfaceInterpolationController::SetDataStorage(DataStorage::Pointer ds) { m_DataStorage = ds; } void mitk::SurfaceInterpolationController::SetMinSpacing(double minSpacing) { m_ReduceFilter->SetMinSpacing(minSpacing); } void mitk::SurfaceInterpolationController::SetMaxSpacing(double maxSpacing) { m_ReduceFilter->SetMaxSpacing(maxSpacing); m_NormalsFilter->SetMaxSpacing(maxSpacing); } void mitk::SurfaceInterpolationController::SetDistanceImageVolume(unsigned int distImgVolume) { m_InterpolateSurfaceFilter->SetDistanceImageVolume(distImgVolume); } void mitk::SurfaceInterpolationController::SetSegmentationImage(Image* workingImage) { m_NormalsFilter->SetSegmentationBinaryImage(workingImage); } mitk::Image* mitk::SurfaceInterpolationController::GetImage() { return m_InterpolateSurfaceFilter->GetOutput(); } double mitk::SurfaceInterpolationController::EstimatePortionOfNeededMemory() { double numberOfPointsAfterReduction = m_ReduceFilter->GetNumberOfPointsAfterReduction()*3; double sizeOfPoints = pow(numberOfPointsAfterReduction,2)*sizeof(double); double totalMem = mitk::MemoryUtilities::GetTotalSizeOfPhysicalRam(); double percentage = sizeOfPoints/totalMem; return percentage; } template void mitk::SurfaceInterpolationController::GetImageBase(itk::Image* input, itk::ImageBase<3>::Pointer& result) { result->Graft(input); } void mitk::SurfaceInterpolationController::SetCurrentSegmentationInterpolationList(mitk::Image* segmentation) { if (segmentation == m_SelectedSegmentation) return; m_ReduceFilter->Reset(); m_NormalsFilter->Reset(); m_InterpolateSurfaceFilter->Reset(); if (segmentation == 0) { m_SelectedSegmentation = 0; return; } ContourListMap::iterator it = m_MapOfContourLists.find(segmentation); m_SelectedSegmentation = segmentation; itk::ImageBase<3>::Pointer itkImage = itk::ImageBase<3>::New(); AccessFixedDimensionByItk_1( m_SelectedSegmentation, GetImageBase, 3, itkImage ); m_InterpolateSurfaceFilter->SetReferenceImage( itkImage.GetPointer() ); if (it == m_MapOfContourLists.end()) { ContourPositionPairList newList; m_MapOfContourLists.insert(std::pair(segmentation, newList)); m_InterpolationResult = 0; m_CurrentNumberOfReducedContours = 0; itk::MemberCommand::Pointer command = itk::MemberCommand::New(); command->SetCallbackFunction(this, &SurfaceInterpolationController::OnSegmentationDeleted); m_SegmentationObserverTags.insert( std::pair( segmentation, segmentation->AddObserver( itk::DeleteEvent(), command ) ) ); } else { for (unsigned int i = 0; i < m_MapOfContourLists[m_SelectedSegmentation].size(); i++) { m_ReduceFilter->SetInput(i, m_MapOfContourLists[m_SelectedSegmentation].at(i).contour); } m_ReduceFilter->Update(); m_CurrentNumberOfReducedContours = m_ReduceFilter->GetNumberOfOutputs(); for (unsigned int i = 0; i < m_CurrentNumberOfReducedContours; i++) { m_NormalsFilter->SetInput(i, m_ReduceFilter->GetOutput(i)); m_InterpolateSurfaceFilter->SetInput(i, m_NormalsFilter->GetOutput(i)); } } Modified(); } void mitk::SurfaceInterpolationController::RemoveSegmentationFromContourList(mitk::Image *segmentation) { if (segmentation != 0) { m_MapOfContourLists.erase(segmentation); if (m_SelectedSegmentation == segmentation) { SetSegmentationImage(NULL); m_SelectedSegmentation = 0; } } } void mitk::SurfaceInterpolationController::OnSegmentationDeleted(const itk::Object *caller, const itk::EventObject &/*event*/) { mitk::Image* tempImage = dynamic_cast(const_cast(caller)); if (tempImage) { RemoveSegmentationFromContourList(tempImage); if (tempImage == m_SelectedSegmentation) { SetSegmentationImage(NULL); m_SelectedSegmentation = 0; } } }