diff --git a/Core/Code/Algorithms/mitkExtractSliceFilter.cpp b/Core/Code/Algorithms/mitkExtractSliceFilter.cpp index 8993f58780..d2e87f977d 100644 --- a/Core/Code/Algorithms/mitkExtractSliceFilter.cpp +++ b/Core/Code/Algorithms/mitkExtractSliceFilter.cpp @@ -1,486 +1,486 @@ /*=================================================================== 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 "mitkExtractSliceFilter.h" #include #include #include #include #include #include #include mitk::ExtractSliceFilter::ExtractSliceFilter(vtkImageReslice* reslicer ){ if(reslicer == NULL){ m_Reslicer = vtkSmartPointer::New(); } else { m_Reslicer = reslicer; } m_TimeStep = 0; m_Reslicer->ReleaseDataFlagOn(); m_InterpolationMode = ExtractSliceFilter::RESLICE_NEAREST; m_ResliceTransform = NULL; m_InPlaneResampleExtentByGeometry = false; m_OutPutSpacing = new mitk::ScalarType[2]; m_OutputDimension = 2; m_ZSpacing = 1.0; m_ZMin = 0; m_ZMax = 0; m_VtkOutputRequested = false; } mitk::ExtractSliceFilter::~ExtractSliceFilter(){ m_ResliceTransform = NULL; m_WorldGeometry = NULL; delete [] m_OutPutSpacing; } void mitk::ExtractSliceFilter::GenerateOutputInformation(){ Superclass::GenerateOutputInformation(); //TODO try figure out how to set the specs of the slice before it is actually extracted /*Image::Pointer output = this->GetOutput(); Image::ConstPointer input = this->GetInput(); if (input.IsNull()) return; unsigned int dimensions[2]; dimensions[0] = m_WorldGeometry->GetExtent(0); dimensions[1] = m_WorldGeometry->GetExtent(1); output->Initialize(input->GetPixelType(), 2, dimensions, 1);*/ } void mitk::ExtractSliceFilter::GenerateInputRequestedRegion(){ //As we want all pixel information fo the image in our plane, the requested region //is set to the largest possible region in the image. //This is needed because an oblique plane has a larger extent then the image //and the in pipeline it is checked via PropagateResquestedRegion(). But the //extent of the slice is actually fitting because it is oblique within the image. ImageToImageFilter::InputImagePointer input = const_cast< ImageToImageFilter::InputImageType* > ( this->GetInput() ); input->SetRequestedRegionToLargestPossibleRegion(); } mitk::ScalarType* mitk::ExtractSliceFilter::GetOutputSpacing(){ return m_OutPutSpacing; } void mitk::ExtractSliceFilter::GenerateData(){ mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); if (!input) { MITK_ERROR << "mitk::ExtractSliceFilter: No input image available. Please set the input!" << std::endl; itkExceptionMacro("mitk::ExtractSliceFilter: No input image available. Please set the input!"); return; } if(!m_WorldGeometry) { MITK_ERROR << "mitk::ExtractSliceFilter: No Geometry for reslicing available." << std::endl; itkExceptionMacro("mitk::ExtractSliceFilter: No Geometry for reslicing available."); return; } const TimeGeometry* inputTimeGeometry = this->GetInput()->GetTimeGeometry(); if ( ( inputTimeGeometry == NULL ) || ( inputTimeGeometry->CountTimeSteps() <= 0 ) ) { itkWarningMacro(<<"Error reading input image TimeGeometry."); return; } // is it a valid timeStep? if ( inputTimeGeometry->IsValidTimeStep( m_TimeStep ) == false ) { itkWarningMacro(<<"This is not a valid timestep: "<< m_TimeStep ); return; } // check if there is something to display. if ( ! input->IsVolumeSet( m_TimeStep ) ) { itkWarningMacro(<<"No volume data existent at given timestep "<< m_TimeStep ); return; } /*================#BEGIN setup vtkImageRslice properties================*/ Point3D origin; Vector3D right, bottom, normal; double widthInMM, heightInMM; Vector2D extent; const PlaneGeometry* planeGeometry = dynamic_cast(m_WorldGeometry); if ( planeGeometry != NULL ) { //if the worldGeomatry is a PlaneGeometry everthing is straight forward 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. Vector3D rightInIndex, bottomInIndex; inputTimeGeometry->GetGeometryForTimeStep( m_TimeStep )->WorldToIndex( right, rightInIndex ); inputTimeGeometry->GetGeometryForTimeStep( m_TimeStep )->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 ); m_OutPutSpacing[0] = widthInMM / extent[0]; m_OutPutSpacing[1] = heightInMM / extent[1]; right.Normalize(); bottom.Normalize(); normal.Normalize(); /* * Transform the origin to center based coordinates. * Note: * This is needed besause vtk's origin is center based too (!!!) ( see 'The VTK book' page 88 ) * and the worldGeometry surrouding the image is no imageGeometry. So the worldGeometry * has its origin at the corner of the voxel and needs to be transformed. */ origin += right * ( m_OutPutSpacing[0] * 0.5 ); origin += bottom * ( m_OutPutSpacing[1] * 0.5 ); //set the tranform for reslicing. // Use inverse transform of the input geometry for reslicing the 3D image. // This is needed if the image volume already transformed if(m_ResliceTransform.IsNotNull()) m_Reslicer->SetResliceTransform(m_ResliceTransform->GetVtkTransform()->GetLinearInverse()); // Set background level to TRANSLUCENT (see Geometry2DDataVtkMapper3D), // else the background of the image turns out gray m_Reslicer->SetBackgroundLevel( -32768 ); } else{ //Code for curved planes, mostly taken 1:1 from imageVtkMapper2D and not tested yet. // Do we have an AbstractTransformGeometry? // This is the case for AbstractTransformGeometry's (e.g. a ThinPlateSplineCurvedGeometry ) const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(m_WorldGeometry); if(abstractGeometry != NULL) { m_ResliceTransform = abstractGeometry; extent[0] = abstractGeometry->GetParametricExtent(0); extent[1] = abstractGeometry->GetParametricExtent(1); widthInMM = abstractGeometry->GetParametricExtentInMM(0); heightInMM = abstractGeometry->GetParametricExtentInMM(1); m_OutPutSpacing[0] = widthInMM / extent[0]; m_OutPutSpacing[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 vtkSmartPointer composedResliceTransform = vtkSmartPointer::New(); composedResliceTransform->Identity(); composedResliceTransform->Concatenate( inputTimeGeometry->GetGeometryForTimeStep( m_TimeStep )->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 ); } else { itkExceptionMacro("mitk::ExtractSliceFilter: No fitting geometry for reslice axis!"); return; } } if(m_ResliceTransform.IsNotNull()){ //if the resliceTransform is set the reslice axis are recalculated. //Thus the geometry information is not fitting. Therefor a unitSpacingFilter //is used to set up a global spacing of 1 and compensate the transform. vtkSmartPointer unitSpacingImageFilter = vtkSmartPointer::New() ; unitSpacingImageFilter->ReleaseDataFlagOn(); unitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); unitSpacingImageFilter->SetInput( input->GetVtkImageData(m_TimeStep) ); m_Reslicer->SetInput(unitSpacingImageFilter->GetOutput() ); } else { //if no tranform is set the image can be used directly m_Reslicer->SetInput(input->GetVtkImageData(m_TimeStep)); } /*setup the plane where vktImageReslice extracts the slice*/ //ResliceAxesOrigin is the ancor point of the plane double originInVtk[3]; itk2vtk(origin, originInVtk); m_Reslicer->SetResliceAxesOrigin(originInVtk); //the cosines define the plane: x and y are the direction vectors, n is the planes normal //this specifies a matrix 3x3 // x1 y1 n1 // x2 y2 n2 // x3 y3 n3 double cosines[9]; vnl2vtk(right.GetVnlVector(), cosines);//x vnl2vtk(bottom.GetVnlVector(), cosines + 3);//y vnl2vtk(normal.GetVnlVector(), cosines + 6);//n m_Reslicer->SetResliceAxesDirectionCosines(cosines); //we only have one slice, not a volume m_Reslicer->SetOutputDimensionality(m_OutputDimension); //set the interpolation mode for slicing switch(this->m_InterpolationMode){ case RESLICE_NEAREST: m_Reslicer->SetInterpolationModeToNearestNeighbor(); break; case RESLICE_LINEAR: m_Reslicer->SetInterpolationModeToLinear(); break; case RESLICE_CUBIC: m_Reslicer->SetInterpolationModeToCubic(); break; default: //the default interpolation used by mitk m_Reslicer->SetInterpolationModeToNearestNeighbor(); } /*========== BEGIN setup extent of the slice ==========*/ int xMin, xMax, yMin, yMax; xMin = yMin = 0; xMax = static_cast< int >( extent[0]); yMax = static_cast< int >( extent[1]); - vtkFloatingPointType sliceBounds[6]; + double sliceBounds[6]; if (m_WorldGeometry->GetReferenceGeometry()) { for ( int i = 0; i < 6; ++i ) { sliceBounds[i] = 0.0; } if (this->GetClippedPlaneBounds( m_WorldGeometry->GetReferenceGeometry(), planeGeometry, sliceBounds )) { // Calculate output extent (integer values) xMin = static_cast< int >( sliceBounds[0] / m_OutPutSpacing[0] + 0.5 ); xMax = static_cast< int >( sliceBounds[1] / m_OutPutSpacing[0] + 0.5 ); yMin = static_cast< int >( sliceBounds[2] / m_OutPutSpacing[1] + 0.5 ); yMax = static_cast< int >( sliceBounds[3] / m_OutPutSpacing[1] + 0.5 ); } // ELSE we use the default values } // Set the output extents! First included pixel index and last included pixel index // xMax and yMax are one after the last pixel. so they have to be decremented by 1. // In case we have a 2D image, xMax or yMax might be 0. in this case, do not decrement, but take 0. m_Reslicer->SetOutputExtent(xMin, std::max(0, xMax-1), yMin, std::max(0, yMax-1), m_ZMin, m_ZMax ); /*========== END setup extent of the slice ==========*/ m_Reslicer->SetOutputOrigin( 0.0, 0.0, 0.0 ); m_Reslicer->SetOutputSpacing( m_OutPutSpacing[0], m_OutPutSpacing[1], m_ZSpacing ); //TODO check the following lines, they are responsible wether vtk error outputs appear or not m_Reslicer->UpdateWholeExtent(); //this produces a bad allocation error for 2D images //m_Reslicer->GetOutput()->UpdateInformation(); //m_Reslicer->GetOutput()->SetUpdateExtentToWholeExtent(); //start the pipeline m_Reslicer->Update(); /*================ #END setup vtkImageRslice properties================*/ if(m_VtkOutputRequested){ return; //no converting to mitk //no mitk geometry will be set, as the output is vtkImageData only!!! } else { /*================ #BEGIN Get the slice from vtkImageReslice and convert it to mit::Image================*/ vtkImageData* reslicedImage; reslicedImage = m_Reslicer->GetOutput(); if(!reslicedImage) { itkWarningMacro(<<"Reslicer returned empty image"); return; } mitk::Image::Pointer resultImage = this->GetOutput(); //initialize resultimage with the specs of the vtkImageData object returned from vtkImageReslice if (reslicedImage->GetDataDimension() == 1) { // If original image was 2D, the slice might have an y extent of 0. // Still i want to ensure here that Image is 2D resultImage->Initialize(reslicedImage,1,-1,-1,1); } else { resultImage->Initialize(reslicedImage); } //transfer the voxel data resultImage->SetVolume(reslicedImage->GetScalarPointer()); //set the geometry from current worldgeometry for the reusultimage //this is needed that the image has the correct mitk geometry //the originalGeometry is the Geometry of the result slice // mitk::AffineGeometryFrame3D::Pointer originalGeometryAGF = m_WorldGeometry->Clone(); // Geometry2D::Pointer originalGeometry = dynamic_cast( originalGeometryAGF.GetPointer() ); Geometry2D::Pointer originalGeometry = m_WorldGeometry->Clone(); originalGeometry->GetIndexToWorldTransform()->SetMatrix(m_WorldGeometry->GetIndexToWorldTransform()->GetMatrix()); //the origin of the worldGeometry is transformed to center based coordinates to be an imageGeometry Point3D sliceOrigin = originalGeometry->GetOrigin(); sliceOrigin += right * ( m_OutPutSpacing[0] * 0.5 ); sliceOrigin += bottom * ( m_OutPutSpacing[1] * 0.5 ); //a worldGeometry is no imageGeometry, thus it is manually set to true originalGeometry->ImageGeometryOn(); /*At this point we have to adjust the geometry because the origin isn't correct. The wrong origin is related to the rotation of the current world geometry plane. This causes errors on transfering world to index coordinates. We just shift the origin in each direction about the amount of the expanding (needed while rotating the plane). */ Vector3D axis0 = originalGeometry->GetAxisVector(0); Vector3D axis1 = originalGeometry->GetAxisVector(1); axis0.Normalize(); axis1.Normalize(); //adapt the origin. Note that for orthogonal planes the minima are '0' and thus the origin stays the same. sliceOrigin += (axis0 * (xMin * m_OutPutSpacing[0])) + (axis1 * (yMin * m_OutPutSpacing[1])); originalGeometry->SetOrigin(sliceOrigin); originalGeometry->Modified(); resultImage->SetGeometry( originalGeometry ); /*the bounds as well as the extent of the worldGeometry are not adapted correctly during crosshair rotation. This is only a quick fix and has to be evaluated. The new bounds are set via the max values of the calcuted slice extent. It will look like [ 0, x, 0, y, 0, 1]. */ mitk::BoundingBox::BoundsArrayType boundsCopy; boundsCopy[0] = boundsCopy[2] = boundsCopy[4] = 0; boundsCopy[5] = 1; boundsCopy[1] = xMax - xMin; boundsCopy[3] = yMax - yMin; resultImage->GetGeometry()->SetBounds(boundsCopy); /*================ #END Get the slice from vtkImageReslice and convert it to mitk Image================*/ } } -bool mitk::ExtractSliceFilter::GetClippedPlaneBounds(vtkFloatingPointType bounds[6]){ +bool mitk::ExtractSliceFilter::GetClippedPlaneBounds(double bounds[6]){ if(!m_WorldGeometry || !this->GetInput()) return false; return this->GetClippedPlaneBounds(m_WorldGeometry->GetReferenceGeometry(), dynamic_cast< const PlaneGeometry * >( m_WorldGeometry ), bounds); } bool mitk::ExtractSliceFilter::GetClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) + const PlaneGeometry *planeGeometry, double *bounds ) { bool b = mitk::PlaneClipping::CalculateClippedPlaneBounds(boundingGeometry, planeGeometry, bounds); return b; } diff --git a/Core/Code/Algorithms/mitkExtractSliceFilter.h b/Core/Code/Algorithms/mitkExtractSliceFilter.h index 46444a34bb..50d85b12f4 100644 --- a/Core/Code/Algorithms/mitkExtractSliceFilter.h +++ b/Core/Code/Algorithms/mitkExtractSliceFilter.h @@ -1,174 +1,174 @@ /*=================================================================== 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 mitkExtractSliceFilter_h_Included #define mitkExtractSliceFilter_h_Included #include "MitkExports.h" #include "mitkImageToImageFilter.h" #include #include #include #include #include #include #include namespace mitk { /** \brief ExtractSliceFilter extracts a 2D abitrary oriented slice from a 3D volume. The filter can reslice in all orthogonal planes such as sagittal, coronal and axial, and is also able to reslice a abitrary oriented oblique plane. Curved planes are specified via an AbstractTransformGeometry as the input worldgeometry. The convinient workflow is: 1. Set an image as input. 2. Set the worldGeometry2D. This defines a grid where the slice is being extracted 3. And then start the pipeline. There are a few more properties that can be set to modify the behavior of the slicing. The properties are: - interpolation mode either Nearestneighbor, Linear or Cubic. - a transform this is a convinient way to adapt the reslice axis for the case that the image is transformed e.g. rotated. - time step the time step in a times volume. - resample by geometry wether the resampling grid corresponds to the specs of the worldgeometry or is directly derived from the input image By default the properties are set to: - interpolation mode Nearestneighbor. - a transform NULL (No transform is set). - time step 0. - resample by geometry false (Corresponds to input image). */ class MITK_CORE_EXPORT ExtractSliceFilter : public ImageToImageFilter { public: mitkClassMacro(ExtractSliceFilter, ImageToImageFilter); itkNewMacro(ExtractSliceFilter); mitkNewMacro1Param(Self, vtkImageReslice*); /** \brief Set the axis where to reslice at.*/ void SetWorldGeometry(const Geometry2D* geometry ){ this->m_WorldGeometry = geometry; this->Modified(); } /** \brief Set the time step in the 4D volume */ void SetTimeStep( unsigned int timestep){ this->m_TimeStep = timestep; } unsigned int GetTimeStep(){ return this->m_TimeStep; } /** \brief Set a transform for the reslice axes. * This transform is needed if the image volume itself is transformed. (Effects the reslice axis) */ void SetResliceTransformByGeometry(const Geometry3D* transform){ this->m_ResliceTransform = transform; } /** \brief Resampling grid corresponds to: false->image true->worldgeometry*/ void SetInPlaneResampleExtentByGeometry(bool inPlaneResampleExtentByGeometry){ this->m_InPlaneResampleExtentByGeometry = inPlaneResampleExtentByGeometry; } /** \brief Sets the output dimension of the slice*/ void SetOutputDimensionality(unsigned int dimension){ this->m_OutputDimension = dimension; } /** \brief Set the spacing in z direction manually. * Required if the outputDimension is > 2. */ void SetOutputSpacingZDirection(double zSpacing){ this->m_ZSpacing = zSpacing; } /** \brief Set the extent in pixel for direction z manualy. Required if the output dimension is > 2. */ void SetOutputExtentZDirection(int zMin, int zMax) { this->m_ZMin = zMin; this->m_ZMax = zMax; } /** \brief Get the bounding box of the slice [xMin, xMax, yMin, yMax, zMin, zMax] * The method uses the input of the filter to calculate the bounds. * It is recommended to use - * GetClippedPlaneBounds(const Geometry3D*, const PlaneGeometry*, vtkFloatingPointType*) + * GetClippedPlaneBounds(const Geometry3D*, const PlaneGeometry*, double*) * if you are not sure about the input. */ bool GetClippedPlaneBounds(double bounds[6]); /** \brief Get the bounding box of the slice [xMin, xMax, yMin, yMax, zMin, zMax]*/ bool GetClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); + const PlaneGeometry *planeGeometry, double *bounds ); /** \brief Get the spacing of the slice. returns mitk::ScalarType[2] */ mitk::ScalarType* GetOutputSpacing(); /** \brief Get Output as vtkImageData. * Note: * SetVtkOutputRequest(true) has to be called at least once before * GetVtkOutput(). Otherwise the output is empty for the first update step. */ vtkImageData* GetVtkOutput(){ m_VtkOutputRequested = true; return m_Reslicer->GetOutput(); } /** Set VtkOutPutRequest to suppress the convertion of the image. * It is suggested to use this with GetVtkOutput(). * Note: * SetVtkOutputRequest(true) has to be called at least once before * GetVtkOutput(). Otherwise the output is empty for the first update step. */ void SetVtkOutputRequest(bool isRequested){ m_VtkOutputRequested = isRequested; } /** \brief Get the reslices axis matrix. * Note: the axis are recalculated when calling SetResliceTransformByGeometry. */ vtkMatrix4x4* GetResliceAxes(){ return this->m_Reslicer->GetResliceAxes(); } enum ResliceInterpolation { RESLICE_NEAREST=0, RESLICE_LINEAR=1, RESLICE_CUBIC=3 }; void SetInterpolationMode( ExtractSliceFilter::ResliceInterpolation interpolation){ this->m_InterpolationMode = interpolation; } protected: ExtractSliceFilter(vtkImageReslice* reslicer = NULL); virtual ~ExtractSliceFilter(); virtual void GenerateData(); virtual void GenerateOutputInformation(); virtual void GenerateInputRequestedRegion(); const Geometry2D* m_WorldGeometry; vtkSmartPointer m_Reslicer; unsigned int m_TimeStep; unsigned int m_OutputDimension; double m_ZSpacing; int m_ZMin; int m_ZMax; ResliceInterpolation m_InterpolationMode; Geometry3D::ConstPointer m_ResliceTransform; bool m_InPlaneResampleExtentByGeometry;//Resampling grid corresponds to: false->image true->worldgeometry mitk::ScalarType* m_OutPutSpacing; bool m_VtkOutputRequested; }; } #endif // mitkExtractSliceFilter_h_Included diff --git a/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp b/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp index 4bbdbf2ddb..a79f6e52ed 100644 --- a/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp +++ b/Core/Code/Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp @@ -1,445 +1,445 @@ /*=================================================================== 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 "mitkGeometry2DDataToSurfaceFilter.h" #include "mitkSurface.h" #include "mitkGeometry3D.h" #include "mitkGeometry2DData.h" #include "mitkPlaneGeometry.h" #include "mitkAbstractTransformGeometry.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::Geometry2DDataToSurfaceFilter::Geometry2DDataToSurfaceFilter() : m_UseGeometryParametricBounds( true ), m_XResolution( 10 ), m_YResolution( 10 ), m_PlaceByGeometry( false ), m_UseBoundingBox( false ) { m_PlaneSource = vtkPlaneSource::New(); m_Transform = vtkTransform::New(); m_CubeSource = vtkCubeSource::New(); m_PolyDataTransformer = vtkTransformPolyDataFilter::New(); m_Plane = vtkPlane::New(); m_PlaneCutter = vtkCutter::New(); m_PlaneStripper = vtkStripper::New(); m_PlanePolyData = vtkPolyData::New(); m_NormalsUpdater = vtkPPolyDataNormals::New(); m_PlaneTriangler = vtkTriangleFilter::New(); m_TextureMapToPlane = vtkTextureMapToPlane::New(); m_Box = vtkBox::New(); m_PlaneClipper = vtkClipPolyData::New(); m_VtkTransformPlaneFilter = vtkTransformPolyDataFilter::New(); m_VtkTransformPlaneFilter->SetInput( m_PlaneSource->GetOutput() ); } mitk::Geometry2DDataToSurfaceFilter::~Geometry2DDataToSurfaceFilter() { m_PlaneSource->Delete(); m_Transform->Delete(); m_CubeSource->Delete(); m_PolyDataTransformer->Delete(); m_Plane->Delete(); m_PlaneCutter->Delete(); m_PlaneStripper->Delete(); m_PlanePolyData->Delete(); m_NormalsUpdater->Delete(); m_PlaneTriangler->Delete(); m_TextureMapToPlane->Delete(); m_Box->Delete(); m_PlaneClipper->Delete(); m_VtkTransformPlaneFilter->Delete(); } void mitk::Geometry2DDataToSurfaceFilter::GenerateOutputInformation() { mitk::Geometry2DData::ConstPointer input = this->GetInput(); mitk::Surface::Pointer output = this->GetOutput(); if ( input.IsNull() || (input->GetGeometry2D() == NULL) || (input->GetGeometry2D()->IsValid() == false) || (m_UseBoundingBox && (m_BoundingBox.IsNull() || (m_BoundingBox->GetDiagonalLength2() < mitk::eps))) ) { return; } Point3D origin; Point3D right, bottom; vtkPolyData *planeSurface = NULL; // Does the Geometry2DData contain a PlaneGeometry? if ( dynamic_cast< PlaneGeometry * >( input->GetGeometry2D() ) != NULL ) { mitk::PlaneGeometry *planeGeometry = dynamic_cast< PlaneGeometry * >( input->GetGeometry2D() ); if ( m_PlaceByGeometry ) { // Let the output use the input geometry to appropriately transform the // coordinate system. mitk::Geometry3D::TransformType *affineTransform = planeGeometry->GetIndexToWorldTransform(); TimeGeometry *timeGeometry = output->GetTimeGeometry(); Geometry3D *geometrie3d = timeGeometry->GetGeometryForTimeStep( 0 ); geometrie3d->SetIndexToWorldTransform( affineTransform ); } if ( !m_UseBoundingBox) { // We do not have a bounding box, so no clipping is required. if ( m_PlaceByGeometry ) { // Derive coordinate axes and origin from input geometry extent origin.Fill( 0.0 ); FillVector3D( right, planeGeometry->GetExtent(0), 0.0, 0.0 ); FillVector3D( bottom, 0.0, planeGeometry->GetExtent(1), 0.0 ); } else { // Take the coordinate axes and origin directly from the input geometry. origin = planeGeometry->GetOrigin(); right = planeGeometry->GetCornerPoint( false, true ); bottom = planeGeometry->GetCornerPoint( true, false ); } // Since the plane is planar, there is no need to subdivide the grid // (cf. AbstractTransformGeometry case) m_PlaneSource->SetXResolution( 1 ); m_PlaneSource->SetYResolution( 1 ); m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] ); m_PlaneSource->SetPoint1( right[0], right[1], right[2] ); m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] ); planeSurface = m_PlaneSource->GetOutput(); planeSurface->Update(); } else { // Set up a cube with the extent and origin of the bounding box. This // cube will be clipped by a plane later on. The intersection of the // cube and the plane will be the surface we are interested in. Note // that the bounding box needs to be explicitly specified by the user // of this class, since it is not necessarily clear from the data // available herein which bounding box to use. In most cases, this // would be the bounding box of the input geometry's reference // geometry, but this is not an inevitable requirement. mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum(); mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum(); mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter(); m_CubeSource->SetXLength( boundingBoxMax[0] - boundingBoxMin[0] ); m_CubeSource->SetYLength( boundingBoxMax[1] - boundingBoxMin[1] ); m_CubeSource->SetZLength( boundingBoxMax[2] - boundingBoxMin[2] ); m_CubeSource->SetCenter( boundingBoxCenter[0], boundingBoxCenter[1], boundingBoxCenter[2] ); // Now we have to transform the cube, so that it will cut our plane // appropriately. (As can be seen below, the plane corresponds to the // z-plane in the coordinate system and is *not* transformed.) Therefore, // we get the inverse of the plane geometry's transform and concatenate // it with the transform of the reference geometry, if available. m_Transform->Identity(); m_Transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); Geometry3D *referenceGeometry = planeGeometry->GetReferenceGeometry(); if ( referenceGeometry ) { m_Transform->Concatenate( referenceGeometry->GetVtkTransform() ); } // Transform the cube accordingly (s.a.) m_PolyDataTransformer->SetInput( m_CubeSource->GetOutput() ); m_PolyDataTransformer->SetTransform( m_Transform ); // Initialize the plane to clip the cube with, as lying on the z-plane m_Plane->SetOrigin( 0.0, 0.0, 0.0 ); m_Plane->SetNormal( 0.0, 0.0, 1.0 ); // Cut the plane with the cube. m_PlaneCutter->SetInput( m_PolyDataTransformer->GetOutput() ); m_PlaneCutter->SetCutFunction( m_Plane ); // The output of the cutter must be converted into appropriate poly data. m_PlaneStripper->SetInput( m_PlaneCutter->GetOutput() ); m_PlaneStripper->Update(); if ( m_PlaneStripper->GetOutput()->GetNumberOfPoints() < 3 ) { return; } m_PlanePolyData->SetPoints( m_PlaneStripper->GetOutput()->GetPoints() ); m_PlanePolyData->SetPolys( m_PlaneStripper->GetOutput()->GetLines() ); m_PlaneTriangler->SetInput( m_PlanePolyData ); // Get bounds of the resulting surface and use it to generate the texture // mapping information m_PlaneTriangler->Update(); m_PlaneTriangler->GetOutput()->ComputeBounds(); - vtkFloatingPointType *surfaceBounds = + double *surfaceBounds = m_PlaneTriangler->GetOutput()->GetBounds(); origin[0] = surfaceBounds[0]; origin[1] = surfaceBounds[2]; origin[2] = surfaceBounds[4]; right[0] = surfaceBounds[1]; right[1] = surfaceBounds[2]; right[2] = surfaceBounds[4]; bottom[0] = surfaceBounds[0]; bottom[1] = surfaceBounds[3]; bottom[2] = surfaceBounds[4]; // Now we tell the data how it shall be textured afterwards; // description see above. m_TextureMapToPlane->SetInput( m_PlaneTriangler->GetOutput() ); m_TextureMapToPlane->AutomaticPlaneGenerationOn(); m_TextureMapToPlane->SetOrigin( origin[0], origin[1], origin[2] ); m_TextureMapToPlane->SetPoint1( right[0], right[1], right[2] ); m_TextureMapToPlane->SetPoint2( bottom[0], bottom[1], bottom[2] ); // Need to call update so that output data and bounds are immediately // available m_TextureMapToPlane->Update(); // Return the output of this generation process planeSurface = dynamic_cast< vtkPolyData * >( m_TextureMapToPlane->GetOutput() ); } } // Does the Geometry2DData contain an AbstractTransformGeometry? else if ( mitk::AbstractTransformGeometry *abstractGeometry = dynamic_cast< AbstractTransformGeometry * >( input->GetGeometry2D() ) ) { // In the case of an AbstractTransformGeometry (which holds a possibly // non-rigid transform), we proceed slightly differently: since the // plane can be arbitrarily deformed, we need to transform it by the // abstract transform before clipping it. The setup for this is partially // done in the constructor. origin = abstractGeometry->GetPlane()->GetOrigin(); right = origin + abstractGeometry->GetPlane()->GetAxisVector( 0 ); bottom = origin + abstractGeometry->GetPlane()->GetAxisVector( 1 ); // Define the plane m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] ); m_PlaneSource->SetPoint1( right[0], right[1], right[2] ); m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] ); // Set the plane's resolution (unlike for non-deformable planes, the plane // grid needs to have a certain resolution so that the deformation has the // desired effect). if ( m_UseGeometryParametricBounds ) { m_PlaneSource->SetXResolution( (int)abstractGeometry->GetParametricExtent(0) ); m_PlaneSource->SetYResolution( (int)abstractGeometry->GetParametricExtent(1) ); } else { m_PlaneSource->SetXResolution( m_XResolution ); m_PlaneSource->SetYResolution( m_YResolution ); } if ( m_PlaceByGeometry ) { // Let the output use the input geometry to appropriately transform the // coordinate system. mitk::Geometry3D::TransformType *affineTransform = abstractGeometry->GetIndexToWorldTransform(); TimeGeometry *timeGeometry = output->GetTimeGeometry(); Geometry3D *g3d = timeGeometry->GetGeometryForTimeStep( 0 ); g3d->SetIndexToWorldTransform( affineTransform ); vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); composedResliceTransform->Identity(); composedResliceTransform->Concatenate( abstractGeometry->GetVtkTransform()->GetLinearInverse() ); composedResliceTransform->Concatenate( abstractGeometry->GetVtkAbstractTransform() ); // Use the non-rigid transform for transforming the plane. m_VtkTransformPlaneFilter->SetTransform( composedResliceTransform ); } else { // Use the non-rigid transform for transforming the plane. m_VtkTransformPlaneFilter->SetTransform( abstractGeometry->GetVtkAbstractTransform() ); } if ( m_UseBoundingBox ) { mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum(); mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum(); //mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter(); m_Box->SetXMin( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2] ); m_Box->SetXMax( boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2] ); } else { // Plane will not be clipped m_Box->SetXMin( -10000.0, -10000.0, -10000.0 ); m_Box->SetXMax( 10000.0, 10000.0, 10000.0 ); } m_Transform->Identity(); m_Transform->Concatenate( input->GetGeometry2D()->GetVtkTransform() ); m_Transform->PreMultiply(); m_Box->SetTransform( m_Transform ); m_PlaneClipper->SetInput( m_VtkTransformPlaneFilter->GetOutput() ); m_PlaneClipper->SetClipFunction( m_Box ); m_PlaneClipper->GenerateClippedOutputOff(); // important to NOT generate normals data for clipped part m_PlaneClipper->InsideOutOn(); m_PlaneClipper->SetValue( 0.0 ); planeSurface = m_PlaneClipper->GetOutput(); } m_NormalsUpdater->SetInput( planeSurface ); m_NormalsUpdater->AutoOrientNormalsOn(); // that's the trick! Brings consistency between // normals direction and front/back faces direction (see bug 1440) m_NormalsUpdater->ComputePointNormalsOn(); m_NormalsUpdater->Update(); output->SetVtkPolyData( m_NormalsUpdater->GetOutput() ); output->CalculateBoundingBox(); } void mitk::Geometry2DDataToSurfaceFilter::GenerateData() { mitk::Surface::Pointer output = this->GetOutput(); if (output.IsNull()) return; if (output->GetVtkPolyData()==NULL) return; output->GetVtkPolyData()->Update(); } const mitk::Geometry2DData *mitk::Geometry2DDataToSurfaceFilter::GetInput() { if (this->GetNumberOfInputs() < 1) { return 0; } return static_cast ( this->ProcessObject::GetInput(0) ); } const mitk::Geometry2DData * mitk::Geometry2DDataToSurfaceFilter ::GetInput(unsigned int idx) { return static_cast< const mitk::Geometry2DData * > ( this->ProcessObject::GetInput(idx) ); } void mitk::Geometry2DDataToSurfaceFilter ::SetInput(const mitk::Geometry2DData *input) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput( 0, const_cast< mitk::Geometry2DData * >( input ) ); } void mitk::Geometry2DDataToSurfaceFilter ::SetInput(unsigned int index, const mitk::Geometry2DData *input) { if( index+1 > this->GetNumberOfInputs() ) { this->SetNumberOfRequiredInputs( index + 1 ); } // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(index, const_cast< mitk::Geometry2DData *>( input ) ); } void mitk::Geometry2DDataToSurfaceFilter ::SetBoundingBox( const mitk::BoundingBox *boundingBox ) { m_BoundingBox = boundingBox; this->UseBoundingBoxOn(); } const mitk::BoundingBox * mitk::Geometry2DDataToSurfaceFilter ::GetBoundingBox() const { return m_BoundingBox.GetPointer(); } diff --git a/Core/Code/Algorithms/mitkImageToSurfaceFilter.cpp b/Core/Code/Algorithms/mitkImageToSurfaceFilter.cpp index 6b2633a228..c7cf9d2161 100644 --- a/Core/Code/Algorithms/mitkImageToSurfaceFilter.cpp +++ b/Core/Code/Algorithms/mitkImageToSurfaceFilter.cpp @@ -1,234 +1,234 @@ /*=================================================================== 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 "mitkException.h" #include #include #include #include #include #include #include #include #include #include #include "mitkProgressBar.h" mitk::ImageToSurfaceFilter::ImageToSurfaceFilter(): m_Smooth(false), m_Decimate( NoDecimation), m_Threshold(1.0), m_TargetReduction(0.95f), m_SmoothIteration(50), m_SmoothRelaxation(0.1) { } mitk::ImageToSurfaceFilter::~ImageToSurfaceFilter() { } void mitk::ImageToSurfaceFilter::CreateSurface(int time, vtkImageData *vtkimage, mitk::Surface * surface, const ScalarType threshold) { vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New(); indexCoordinatesImageFilter->SetInput(vtkimage); indexCoordinatesImageFilter->SetOutputOrigin(0.0,0.0,0.0); //MarchingCube -->create Surface vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New(); skinExtractor->ComputeScalarsOff(); skinExtractor->SetInput(indexCoordinatesImageFilter->GetOutput());//RC++ indexCoordinatesImageFilter->Delete(); skinExtractor->SetValue(0, threshold); 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->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(); } ProgressBar::GetInstance()->Progress(); //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->SetTargetReduction(m_TargetReduction); decimate->SetMaximumError(0.002); polydata->Delete();//RC-- polydata = decimate->GetOutput(); polydata->Register(NULL);//RC++ decimate->Delete(); } else if (m_Decimate==QuadricDecimation) { vtkQuadricDecimation* decimate = vtkQuadricDecimation::New(); decimate->SetTargetReduction(m_TargetReduction); decimate->SetInput(polydata); polydata->Delete(); polydata = decimate->GetOutput(); polydata->Register(NULL); decimate->Delete(); } polydata->Update(); ProgressBar::GetInstance()->Progress(); 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(); - vtkFloatingPointType point[3]; + double point[3]; for (i = 0; i < n; i++) { points->GetPoint(i, point); mitkVtkLinearTransformPoint(matrix,point,point); points->SetPoint(i, point); } vtkmatrix->Delete(); } ProgressBar::GetInstance()->Progress(); // determine point_data normals for the poly data points. vtkSmartPointer normalsGenerator = vtkSmartPointer::New(); normalsGenerator->SetInput( polydata ); vtkSmartPointer cleanPolyDataFilter = vtkSmartPointer::New(); cleanPolyDataFilter->SetInput(normalsGenerator->GetOutput()); cleanPolyDataFilter->PieceInvariantOff(); cleanPolyDataFilter->ConvertLinesToPointsOff(); cleanPolyDataFilter->ConvertPolysToLinesOff(); cleanPolyDataFilter->ConvertStripsToPolysOff(); cleanPolyDataFilter->PointMergingOn(); cleanPolyDataFilter->Update(); surface->SetVtkPolyData(cleanPolyDataFilter->GetOutput(), time); polydata->UnRegister(NULL); } void mitk::ImageToSurfaceFilter::GenerateData() { mitk::Surface *surface = this->GetOutput(); mitk::Image * image = (mitk::Image*)GetInput(); if(image == NULL || !image->IsInitialized()) mitkThrow() << "No input image set, please set an valid input image!"; mitk::Image::RegionType outputRegion = image->GetRequestedRegion(); int tstart=outputRegion.GetIndex(3); int tmax=tstart+outputRegion.GetSize(3); //GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloest if ((tmax-tstart) > 0) { ProgressBar::GetInstance()->AddStepsToDo( 4 * (tmax - tstart) ); } int t; for( t=tstart; t < tmax; ++t) { vtkImageData *vtkimagedata = image->GetVtkImageData(t); CreateSurface(t,vtkimagedata,surface,m_Threshold); ProgressBar::GetInstance()->Progress(); } } void mitk::ImageToSurfaceFilter::SetSmoothIteration(int smoothIteration) { m_SmoothIteration = smoothIteration; } void mitk::ImageToSurfaceFilter::SetSmoothRelaxation(float smoothRelaxation) { m_SmoothRelaxation = smoothRelaxation; } void mitk::ImageToSurfaceFilter::SetInput(const mitk::Image *image) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(0, const_cast< mitk::Image * >( image ) ); } const mitk::Image *mitk::ImageToSurfaceFilter::GetInput(void) { if (this->GetNumberOfInputs() < 1) { return 0; } return static_cast ( this->ProcessObject::GetInput(0) ); } void mitk::ImageToSurfaceFilter::GenerateOutputInformation() { mitk::Image::ConstPointer inputImage =(mitk::Image*) this->GetInput(); //mitk::Image *inputImage = (mitk::Image*)this->GetImage(); mitk::Surface::Pointer output = this->GetOutput(); itkDebugMacro(<<"GenerateOutputInformation()"); if(inputImage.IsNull()) return; //Set Data } diff --git a/Core/Code/Algorithms/mitkPlaneClipping.h b/Core/Code/Algorithms/mitkPlaneClipping.h index f685f5589a..256fbcd8c1 100644 --- a/Core/Code/Algorithms/mitkPlaneClipping.h +++ b/Core/Code/Algorithms/mitkPlaneClipping.h @@ -1,141 +1,141 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKPLANECLIPPING_H_HEADER_INCLUDED #define MITKPLANECLIPPING_H_HEADER_INCLUDED #include #include #include #include namespace mitk { namespace PlaneClipping { /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ -static bool LineIntersectZero( vtkPoints *points, int p1, int p2, vtkFloatingPointType *bounds ) +static bool LineIntersectZero( vtkPoints *points, int p1, int p2, double *bounds ) { - vtkFloatingPointType point1[3]; - vtkFloatingPointType point2[3]; + double point1[3]; + double point2[3]; points->GetPoint( p1, point1 ); points->GetPoint( p2, point2 ); if ( (point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2]) ) { double x, y; x = ( point1[0] * point2[2] - point1[2] * point2[0] ) / ( point2[2] - point1[2] ); y = ( point1[1] * point2[2] - point1[2] * point2[1] ) / ( point2[2] - point1[2] ); if ( x < bounds[0] ) { bounds[0] = x; } if ( x > bounds[1] ) { bounds[1] = x; } if ( y < bounds[2] ) { bounds[2] = y; } if ( y > bounds[3] ) { bounds[3] = y; } bounds[4] = bounds[5] = 0.0; return true; } return false; } /** \brief Calculate the bounding box of the resliced image. This is necessary for arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) will have a new bounding box, which needs to be calculated. */ -static bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ) +static bool 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 mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); vtkSmartPointer points = vtkSmartPointer::New(); if(boundingGeometry->GetImageGeometry()) { points->InsertPoint( 0, bbMin[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 1, bbMin[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 2, bbMin[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 3, bbMin[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 4, bbMax[0]-0.5, bbMin[1]-0.5, bbMin[2]-0.5 ); points->InsertPoint( 5, bbMax[0]-0.5, bbMin[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 6, bbMax[0]-0.5, bbMax[1]-0.5, bbMax[2]-0.5 ); points->InsertPoint( 7, bbMax[0]-0.5, bbMax[1]-0.5, bbMin[2]-0.5 ); } else { points->InsertPoint( 0, bbMin[0], bbMin[1], bbMin[2] ); points->InsertPoint( 1, bbMin[0], bbMin[1], bbMax[2] ); points->InsertPoint( 2, bbMin[0], bbMax[1], bbMax[2] ); points->InsertPoint( 3, bbMin[0], bbMax[1], bbMin[2] ); points->InsertPoint( 4, bbMax[0], bbMin[1], bbMin[2] ); points->InsertPoint( 5, bbMax[0], bbMin[1], bbMax[2] ); points->InsertPoint( 6, bbMax[0], bbMax[1], bbMax[2] ); points->InsertPoint( 7, bbMax[0], bbMax[1], bbMin[2] ); } vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer transform = vtkSmartPointer::New(); transform->Identity(); transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); transform->Concatenate( boundingGeometry->GetVtkTransform() ); transform->TransformPoints( points, newPoints ); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; LineIntersectZero( newPoints, 0, 1, bounds ); LineIntersectZero( newPoints, 1, 2, bounds ); LineIntersectZero( newPoints, 2, 3, bounds ); LineIntersectZero( newPoints, 3, 0, bounds ); LineIntersectZero( newPoints, 0, 4, bounds ); LineIntersectZero( newPoints, 1, 5, bounds ); LineIntersectZero( newPoints, 2, 6, bounds ); LineIntersectZero( newPoints, 3, 7, bounds ); LineIntersectZero( newPoints, 4, 5, bounds ); LineIntersectZero( newPoints, 5, 6, bounds ); LineIntersectZero( newPoints, 6, 7, bounds ); LineIntersectZero( newPoints, 7, 4, bounds ); if ( (bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0) ) { return false; } else { // The resulting bounds must be adjusted by the plane spacing, since we // we have so far dealt with index coordinates const 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; } } } } #endif diff --git a/Core/Code/DataManagement/mitkImage.cpp b/Core/Code/DataManagement/mitkImage.cpp index fee317f520..3035a9993e 100644 --- a/Core/Code/DataManagement/mitkImage.cpp +++ b/Core/Code/DataManagement/mitkImage.cpp @@ -1,1383 +1,1383 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //MITK #include "mitkImage.h" #include "mitkImageStatisticsHolder.h" #include "mitkPixelTypeMultiplex.h" #include #include "mitkCompareImageFilter.h" //VTK #include //Other #include #define FILL_C_ARRAY( _arr, _size, _value) for(unsigned int i=0u; i<_size; i++) \ { _arr[i] = _value; } mitk::Image::Image() : m_Dimension(0), m_Dimensions(NULL), m_ImageDescriptor(NULL), m_OffsetTable(NULL), m_CompleteData(NULL), m_ImageStatistics(NULL) { m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS]; FILL_C_ARRAY( m_Dimensions, MAX_IMAGE_DIMENSIONS, 0u); m_Initialized = false; } mitk::Image::Image(const Image &other) : SlicedData(other), m_Dimension(0), m_Dimensions(NULL), m_ImageDescriptor(NULL), m_OffsetTable(NULL), m_CompleteData(NULL), m_ImageStatistics(NULL) { m_Dimensions = new unsigned int[MAX_IMAGE_DIMENSIONS]; FILL_C_ARRAY( m_Dimensions, MAX_IMAGE_DIMENSIONS, 0u); this->Initialize( other.GetPixelType(), other.GetDimension(), other.GetDimensions()); //Since the above called "Initialize" method doesn't take the geometry into account we need to set it //here manually TimeGeometry::Pointer cloned = other.GetTimeGeometry()->Clone(); this->SetTimeGeometry(cloned.GetPointer()); if (this->GetDimension() > 3) { const unsigned int time_steps = this->GetDimension(3); for (unsigned int i = 0u; i < time_steps; ++i) { ImageDataItemPointer volume = const_cast(other).GetVolumeData(i); this->SetVolume(volume->GetData(), i); } } else { ImageDataItemPointer volume = const_cast(other).GetVolumeData(0); this->SetVolume(volume->GetData(), 0); } } mitk::Image::~Image() { Clear(); m_ReferenceCountLock.Lock(); m_ReferenceCount = 3; m_ReferenceCountLock.Unlock(); m_ReferenceCountLock.Lock(); m_ReferenceCount = 0; m_ReferenceCountLock.Unlock(); if(m_OffsetTable != NULL) delete [] m_OffsetTable; if(m_ImageStatistics != NULL) delete m_ImageStatistics; } const mitk::PixelType mitk::Image::GetPixelType(int n) const { return this->m_ImageDescriptor->GetChannelTypeById(n); } unsigned int mitk::Image::GetDimension() const { return m_Dimension; } unsigned int mitk::Image::GetDimension(int i) const { if((i>=0) && (i<(int)m_Dimension)) return m_Dimensions[i]; return 1; } void* mitk::Image::GetData() { if(m_Initialized==false) { if(GetSource().IsNull()) return NULL; if(GetSource()->Updating()==false) GetSource()->UpdateOutputInformation(); } m_CompleteData=GetChannelData(); // update channel's data // if data was not available at creation point, the m_Data of channel descriptor is NULL // if data present, it won't be overwritten m_ImageDescriptor->GetChannelDescriptor(0).SetData(m_CompleteData->GetData()); return m_CompleteData->GetData(); } template void AccessPixel( const mitk::PixelType ptype, void* data, const unsigned int offset, double& value ) { value = 0.0; if( data == NULL ) return; if(ptype.GetBpe() != 24) { value = (double) (((T*) data)[ offset ]); } else { const unsigned int rgboffset = 3 * offset; double returnvalue = (((T*) data)[rgboffset ]); returnvalue += (((T*) data)[rgboffset + 1]); returnvalue += (((T*) data)[rgboffset + 2]); value = returnvalue; } } double mitk::Image::GetPixelValueByIndex(const mitk::Index3D &position, unsigned int timestep) { double value = 0; if (this->GetTimeSteps() < timestep) { timestep = this->GetTimeSteps(); } value = 0.0; const unsigned int* imageDims = this->m_ImageDescriptor->GetDimensions(); const mitk::PixelType ptype = this->m_ImageDescriptor->GetChannelTypeById(0); // Comparison ?>=0 not needed since all position[i] and timestep are unsigned int // (position[0]>=0 && position[1] >=0 && position[2]>=0 && timestep>=0) // bug-11978 : we still need to catch index with negative values if ( position[0] < 0 || position[1] < 0 || position[2] < 0 ) { MITK_WARN << "Given position ("<< position << ") is out of image range, returning 0." ; } // check if the given position is inside the index range of the image, the 3rd dimension needs to be compared only if the dimension is not 0 else if ( (unsigned int)position[0] >= imageDims[0] || (unsigned int)position[1] >= imageDims[1] || ( imageDims[2] && (unsigned int)position[2] >= imageDims[2] )) { MITK_WARN << "Given position ("<< position << ") is out of image range, returning 0." ; } else { const unsigned int offset = position[0] + position[1]*imageDims[0] + position[2]*imageDims[0]*imageDims[1] + timestep*imageDims[0]*imageDims[1]*imageDims[2]; mitkPixelTypeMultiplex3( AccessPixel, ptype, this->GetData(), offset, value ); } return value; } double mitk::Image::GetPixelValueByWorldCoordinate(const mitk::Point3D& position, unsigned int timestep) { double value = 0.0; if (this->GetTimeSteps() < timestep) { timestep = this->GetTimeSteps(); } Index3D itkIndex; this->GetGeometry()->WorldToIndex(position, itkIndex); value = this->GetPixelValueByIndex( itkIndex, timestep); return value; } mitk::ImageVtkAccessor* mitk::Image::GetVtkImageData(int t, int n) { if(m_Initialized==false) { if(GetSource().IsNull()) return NULL; if(GetSource()->Updating()==false) GetSource()->UpdateOutputInformation(); } ImageDataItemPointer volume=GetVolumeData(t, n); if(volume.GetPointer()==NULL || volume->GetVtkImageData(this) == NULL) return NULL; SlicedGeometry3D* geom3d = GetSlicedGeometry(t); float *fspacing = const_cast(geom3d->GetFloatSpacing()); double dspacing[3] = {fspacing[0],fspacing[1],fspacing[2]}; volume->GetVtkImageData(this)->SetSpacing( dspacing ); return volume->GetVtkImageData(this); } mitk::Image::ImageDataItemPointer mitk::Image::GetSliceData(int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) { if(IsValidSlice(s,t,n)==false) return NULL; const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); // slice directly available? int pos=GetSliceIndex(s,t,n); if(m_Slices[pos].GetPointer()!=NULL) return m_Slices[pos]; // is slice available as part of a volume that is available? ImageDataItemPointer sl, ch, vol; vol=m_Volumes[GetVolumeIndex(t,n)]; if((vol.GetPointer()!=NULL) && (vol->IsComplete())) { sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*m_OffsetTable[2]*(ptypeSize)); sl->SetComplete(true); return m_Slices[pos]=sl; } // is slice available as part of a channel that is available? ch=m_Channels[n]; if((ch.GetPointer()!=NULL) && (ch->IsComplete())) { sl=new ImageDataItem(*ch, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, (((size_t) s)*m_OffsetTable[2]+((size_t) t)*m_OffsetTable[3])*(ptypeSize)); sl->SetComplete(true); return m_Slices[pos]=sl; } // slice is unavailable. Can we calculate it? if((GetSource().IsNotNull()) && (GetSource()->Updating()==false)) { // ... wir mussen rechnen!!! .... m_RequestedRegion.SetIndex(0, 0); m_RequestedRegion.SetIndex(1, 0); m_RequestedRegion.SetIndex(2, s); m_RequestedRegion.SetIndex(3, t); m_RequestedRegion.SetIndex(4, n); m_RequestedRegion.SetSize(0, m_Dimensions[0]); m_RequestedRegion.SetSize(1, m_Dimensions[1]); m_RequestedRegion.SetSize(2, 1); m_RequestedRegion.SetSize(3, 1); m_RequestedRegion.SetSize(4, 1); m_RequestedRegionInitialized=true; GetSource()->Update(); if(IsSliceSet(s,t,n)) //yes: now we can call ourselves without the risk of a endless loop (see "if" above) return GetSliceData(s,t,n,data,importMemoryManagement); else return NULL; } else { ImageDataItemPointer item = AllocateSliceData(s,t,n,data,importMemoryManagement); item->SetComplete(true); return item; } } mitk::Image::ImageDataItemPointer mitk::Image::GetVolumeData(int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) { if(IsValidVolume(t,n)==false) return NULL; ImageDataItemPointer ch, vol; // volume directly available? int pos=GetVolumeIndex(t,n); vol=m_Volumes[pos]; if((vol.GetPointer()!=NULL) && (vol->IsComplete())) return vol; const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); // is volume available as part of a channel that is available? ch=m_Channels[n]; if((ch.GetPointer()!=NULL) && (ch->IsComplete())) { vol=new ImageDataItem(*ch, m_ImageDescriptor, 3, data, importMemoryManagement == ManageMemory, (((size_t) t)*m_OffsetTable[3])*(ptypeSize)); vol->SetComplete(true); return m_Volumes[pos]=vol; } // let's see if all slices of the volume are set, so that we can (could) combine them to a volume bool complete=true; unsigned int s; for(s=0;sSetComplete(true); } else { mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(n); vol=m_Volumes[pos]; // ok, let's combine the slices! if(vol.GetPointer()==NULL) vol=new ImageDataItem( chPixelType, 3, m_Dimensions, NULL, true); vol->SetComplete(true); size_t size=m_OffsetTable[2]*(ptypeSize); for(s=0;sGetParent()!=vol) { // copy data of slices in volume size_t offset = ((size_t) s)*size; std::memcpy(static_cast(vol->GetData())+offset, sl->GetData(), size); // FIXME mitkIpPicDescriptor * pic = sl->GetPicDescriptor(); // replace old slice with reference to volume sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*size); sl->SetComplete(true); //mitkIpFuncCopyTags(sl->GetPicDescriptor(), pic); m_Slices[posSl]=sl; } } //if(vol->GetPicDescriptor()->info->tags_head==NULL) // mitkIpFuncCopyTags(vol->GetPicDescriptor(), m_Slices[GetSliceIndex(0,t,n)]->GetPicDescriptor()); } return m_Volumes[pos]=vol; } // volume is unavailable. Can we calculate it? if((GetSource().IsNotNull()) && (GetSource()->Updating()==false)) { // ... wir muessen rechnen!!! .... m_RequestedRegion.SetIndex(0, 0); m_RequestedRegion.SetIndex(1, 0); m_RequestedRegion.SetIndex(2, 0); m_RequestedRegion.SetIndex(3, t); m_RequestedRegion.SetIndex(4, n); m_RequestedRegion.SetSize(0, m_Dimensions[0]); m_RequestedRegion.SetSize(1, m_Dimensions[1]); m_RequestedRegion.SetSize(2, m_Dimensions[2]); m_RequestedRegion.SetSize(3, 1); m_RequestedRegion.SetSize(4, 1); m_RequestedRegionInitialized=true; GetSource()->Update(); if(IsVolumeSet(t,n)) //yes: now we can call ourselves without the risk of a endless loop (see "if" above) return GetVolumeData(t,n,data,importMemoryManagement); else return NULL; } else { ImageDataItemPointer item = AllocateVolumeData(t,n,data,importMemoryManagement); item->SetComplete(true); return item; } } mitk::Image::ImageDataItemPointer mitk::Image::GetChannelData(int n, void *data, ImportMemoryManagementType importMemoryManagement) { if(IsValidChannel(n)==false) return NULL; ImageDataItemPointer ch, vol; ch=m_Channels[n]; if((ch.GetPointer()!=NULL) && (ch->IsComplete())) return ch; // let's see if all volumes are set, so that we can (could) combine them to a channel if(IsChannelSet(n)) { // if there is only one time frame we do not need to combine anything if(m_Dimensions[3]<=1) { vol=GetVolumeData(0,n,data,importMemoryManagement); ch=new ImageDataItem(*vol, m_ImageDescriptor, m_ImageDescriptor->GetNumberOfDimensions(), data, importMemoryManagement == ManageMemory); ch->SetComplete(true); } else { const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); ch=m_Channels[n]; // ok, let's combine the volumes! if(ch.GetPointer()==NULL) ch=new ImageDataItem(this->m_ImageDescriptor, NULL, true); ch->SetComplete(true); size_t size=m_OffsetTable[m_Dimension-1]*(ptypeSize); unsigned int t; ImageDataItemPointerArray::iterator slicesIt = m_Slices.begin()+n*m_Dimensions[2]*m_Dimensions[3]; for(t=0;tGetParent()!=ch) { // copy data of volume in channel size_t offset = ((size_t) t)*m_OffsetTable[3]*(ptypeSize); std::memcpy(static_cast(ch->GetData())+offset, vol->GetData(), size); // REVEIW FIX mitkIpPicDescriptor * pic = vol->GetPicDescriptor(); // replace old volume with reference to channel vol=new ImageDataItem(*ch, m_ImageDescriptor, 3, data, importMemoryManagement == ManageMemory, offset); vol->SetComplete(true); //mitkIpFuncCopyTags(vol->GetPicDescriptor(), pic); m_Volumes[posVol]=vol; // get rid of slices - they may point to old volume ImageDataItemPointer dnull=NULL; for(unsigned int i = 0; i < m_Dimensions[2]; ++i, ++slicesIt) { assert(slicesIt != m_Slices.end()); *slicesIt = dnull; } } } // REVIEW FIX // if(ch->GetPicDescriptor()->info->tags_head==NULL) // mitkIpFuncCopyTags(ch->GetPicDescriptor(), m_Volumes[GetVolumeIndex(0,n)]->GetPicDescriptor()); } return m_Channels[n]=ch; } // channel is unavailable. Can we calculate it? if((GetSource().IsNotNull()) && (GetSource()->Updating()==false)) { // ... wir muessen rechnen!!! .... m_RequestedRegion.SetIndex(0, 0); m_RequestedRegion.SetIndex(1, 0); m_RequestedRegion.SetIndex(2, 0); m_RequestedRegion.SetIndex(3, 0); m_RequestedRegion.SetIndex(4, n); m_RequestedRegion.SetSize(0, m_Dimensions[0]); m_RequestedRegion.SetSize(1, m_Dimensions[1]); m_RequestedRegion.SetSize(2, m_Dimensions[2]); m_RequestedRegion.SetSize(3, m_Dimensions[3]); m_RequestedRegion.SetSize(4, 1); m_RequestedRegionInitialized=true; GetSource()->Update(); // did it work? if(IsChannelSet(n)) //yes: now we can call ourselves without the risk of a endless loop (see "if" above) return GetChannelData(n,data,importMemoryManagement); else return NULL; } else { ImageDataItemPointer item = AllocateChannelData(n,data,importMemoryManagement); item->SetComplete(true); return item; } } bool mitk::Image::IsSliceSet(int s, int t, int n) const { if(IsValidSlice(s,t,n)==false) return false; if(m_Slices[GetSliceIndex(s,t,n)].GetPointer()!=NULL) return true; ImageDataItemPointer ch, vol; vol=m_Volumes[GetVolumeIndex(t,n)]; if((vol.GetPointer()!=NULL) && (vol->IsComplete())) return true; ch=m_Channels[n]; if((ch.GetPointer()!=NULL) && (ch->IsComplete())) return true; return false; } bool mitk::Image::IsVolumeSet(int t, int n) const { if(IsValidVolume(t,n)==false) return false; ImageDataItemPointer ch, vol; // volume directly available? vol=m_Volumes[GetVolumeIndex(t,n)]; if((vol.GetPointer()!=NULL) && (vol->IsComplete())) return true; // is volume available as part of a channel that is available? ch=m_Channels[n]; if((ch.GetPointer()!=NULL) && (ch->IsComplete())) return true; // let's see if all slices of the volume are set, so that we can (could) combine them to a volume unsigned int s; for(s=0;sIsComplete())) return true; // let's see if all volumes are set, so that we can (could) combine them to a channel unsigned int t; for(t=0;t(data), s, t, n, CopyMemory); } bool mitk::Image::SetVolume(const void *data, int t, int n) { // const_cast is no risk for ImportMemoryManagementType == CopyMemory return SetImportVolume(const_cast(data), t, n, CopyMemory); } bool mitk::Image::SetChannel(const void *data, int n) { // const_cast is no risk for ImportMemoryManagementType == CopyMemory return SetImportChannel(const_cast(data), n, CopyMemory); } bool mitk::Image::SetImportSlice(void *data, int s, int t, int n, ImportMemoryManagementType importMemoryManagement) { if(IsValidSlice(s,t,n)==false) return false; ImageDataItemPointer sl; const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); if(IsSliceSet(s,t,n)) { sl=GetSliceData(s,t,n,data,importMemoryManagement); if(sl->GetManageMemory()==false) { sl=AllocateSliceData(s,t,n,data,importMemoryManagement); if(sl.GetPointer()==NULL) return false; } if ( sl->GetData() != data ) std::memcpy(sl->GetData(), data, m_OffsetTable[2]*(ptypeSize)); sl->Modified(); //we have changed the data: call Modified()! Modified(); } else { sl=AllocateSliceData(s,t,n,data,importMemoryManagement); if(sl.GetPointer()==NULL) return false; if ( sl->GetData() != data ) std::memcpy(sl->GetData(), data, m_OffsetTable[2]*(ptypeSize)); //we just added a missing slice, which is not regarded as modification. //Therefore, we do not call Modified()! } return true; } bool mitk::Image::SetImportVolume(void *data, int t, int n, ImportMemoryManagementType importMemoryManagement) { if(IsValidVolume(t,n)==false) return false; const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); ImageDataItemPointer vol; if(IsVolumeSet(t,n)) { vol=GetVolumeData(t,n,data,importMemoryManagement); if(vol->GetManageMemory()==false) { vol=AllocateVolumeData(t,n,data,importMemoryManagement); if(vol.GetPointer()==NULL) return false; } if ( vol->GetData() != data ) std::memcpy(vol->GetData(), data, m_OffsetTable[3]*(ptypeSize)); vol->Modified(); vol->SetComplete(true); //we have changed the data: call Modified()! Modified(); } else { vol=AllocateVolumeData(t,n,data,importMemoryManagement); if(vol.GetPointer()==NULL) return false; if ( vol->GetData() != data ) { std::memcpy(vol->GetData(), data, m_OffsetTable[3]*(ptypeSize)); } vol->SetComplete(true); this->m_ImageDescriptor->GetChannelDescriptor(n).SetData( vol->GetData() ); //we just added a missing Volume, which is not regarded as modification. //Therefore, we do not call Modified()! } return true; } bool mitk::Image::SetImportChannel(void *data, int n, ImportMemoryManagementType importMemoryManagement) { if(IsValidChannel(n)==false) return false; // channel descriptor const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); ImageDataItemPointer ch; if(IsChannelSet(n)) { ch=GetChannelData(n,data,importMemoryManagement); if(ch->GetManageMemory()==false) { ch=AllocateChannelData(n,data,importMemoryManagement); if(ch.GetPointer()==NULL) return false; } if ( ch->GetData() != data ) std::memcpy(ch->GetData(), data, m_OffsetTable[4]*(ptypeSize)); ch->Modified(); ch->SetComplete(true); //we have changed the data: call Modified()! Modified(); } else { ch=AllocateChannelData(n,data,importMemoryManagement); if(ch.GetPointer()==NULL) return false; if ( ch->GetData() != data ) std::memcpy(ch->GetData(), data, m_OffsetTable[4]*(ptypeSize)); ch->SetComplete(true); this->m_ImageDescriptor->GetChannelDescriptor(n).SetData( ch->GetData() ); //we just added a missing Channel, which is not regarded as modification. //Therefore, we do not call Modified()! } return true; } void mitk::Image::Initialize() { ImageDataItemPointerArray::iterator it, end; for( it=m_Slices.begin(), end=m_Slices.end(); it!=end; ++it ) { (*it)=NULL; } for( it=m_Volumes.begin(), end=m_Volumes.end(); it!=end; ++it ) { (*it)=NULL; } for( it=m_Channels.begin(), end=m_Channels.end(); it!=end; ++it ) { (*it)=NULL; } m_CompleteData = NULL; if( m_ImageStatistics == NULL) { m_ImageStatistics = new mitk::ImageStatisticsHolder( this ); } SetRequestedRegionToLargestPossibleRegion(); } void mitk::Image::Initialize(const mitk::ImageDescriptor::Pointer inDesc) { // store the descriptor this->m_ImageDescriptor = inDesc; // initialize image this->Initialize( inDesc->GetChannelDescriptor(0).GetPixelType(), inDesc->GetNumberOfDimensions(), inDesc->GetDimensions(), 1 ); } void mitk::Image::Initialize(const mitk::PixelType& type, unsigned int dimension, const unsigned int *dimensions, unsigned int channels) { Clear(); m_Dimension=dimension; if(!dimensions) itkExceptionMacro(<< "invalid zero dimension image"); unsigned int i; for(i=0;im_ImageDescriptor = mitk::ImageDescriptor::New(); this->m_ImageDescriptor->Initialize( this->m_Dimensions, this->m_Dimension ); for(i=0;i<4;++i) { m_LargestPossibleRegion.SetIndex(i, 0); m_LargestPossibleRegion.SetSize (i, m_Dimensions[i]); } m_LargestPossibleRegion.SetIndex(i, 0); m_LargestPossibleRegion.SetSize(i, channels); if(m_LargestPossibleRegion.GetNumberOfPixels()==0) { delete [] m_Dimensions; m_Dimensions = NULL; return; } for( unsigned int i=0u; im_ImageDescriptor->AddNewChannel( type ); } PlaneGeometry::Pointer planegeometry = PlaneGeometry::New(); planegeometry->InitializeStandardPlane(m_Dimensions[0], m_Dimensions[1]); SlicedGeometry3D::Pointer slicedGeometry = SlicedGeometry3D::New(); slicedGeometry->InitializeEvenlySpaced(planegeometry, m_Dimensions[2]); if(dimension>=4) { TimeBounds timebounds; timebounds[0] = 0.0; timebounds[1] = 1.0; slicedGeometry->SetTimeBounds(timebounds); } ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]); for (TimeStepType step = 0; step < timeGeometry->CountTimeSteps(); ++step) { timeGeometry->GetGeometryForTimeStep(step)->ImageGeometryOn(); } SetTimeGeometry(timeGeometry); ImageDataItemPointer dnull=NULL; m_Channels.assign(GetNumberOfChannels(), dnull); m_Volumes.assign(GetNumberOfChannels()*m_Dimensions[3], dnull); m_Slices.assign(GetNumberOfChannels()*m_Dimensions[3]*m_Dimensions[2], dnull); ComputeOffsetTable(); Initialize(); m_Initialized = true; } void mitk::Image::Initialize(const mitk::PixelType& type, const mitk::Geometry3D& geometry, unsigned int channels, int tDim ) { mitk::ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); Geometry3D::Pointer geometry3D = geometry.Clone(); timeGeometry->Initialize(geometry3D.GetPointer(), tDim); this->Initialize(type, *timeGeometry, channels, tDim); } void mitk::Image::Initialize(const mitk::PixelType& type, const mitk::TimeGeometry& geometry, unsigned int channels, int tDim ) { unsigned int dimensions[5]; dimensions[0] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(0)+0.5); dimensions[1] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(1)+0.5); dimensions[2] = (unsigned int)(geometry.GetGeometryForTimeStep(0)->GetExtent(2)+0.5); dimensions[3] = (tDim > 0) ? tDim : geometry.CountTimeSteps(); dimensions[4] = 0; unsigned int dimension = 2; if ( dimensions[2] > 1 ) dimension = 3; if ( dimensions[3] > 1 ) dimension = 4; Initialize( type, dimension, dimensions, channels ); if (geometry.CountTimeSteps() > 1) { TimeGeometry::Pointer cloned = geometry.Clone(); SetTimeGeometry(cloned.GetPointer()); } else Superclass::SetGeometry(geometry.GetGeometryForTimeStep(0)); /* //Old //TODO_GOETZ Really necessary? mitk::BoundingBox::BoundsArrayType bounds = geometry.GetBoundingBoxInWorld()->GetBounds(); if( (bounds[0] != 0.0) || (bounds[2] != 0.0) || (bounds[4] != 0.0) ) { SlicedGeometry3D* slicedGeometry = GetSlicedGeometry(0); mitk::Point3D origin; origin.Fill(0.0); slicedGeometry->IndexToWorld(origin, origin); bounds[1]-=bounds[0]; bounds[3]-=bounds[2]; bounds[5]-=bounds[4]; bounds[0] = 0.0; bounds[2] = 0.0; bounds[4] = 0.0; this->m_ImageDescriptor->Initialize( this->m_Dimensions, this->m_Dimension ); slicedGeometry->SetBounds(bounds); slicedGeometry->GetIndexToWorldTransform()->SetOffset(origin.GetVnlVector().data_block()); ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]); SetTimeGeometry(timeGeometry); }*/ } void mitk::Image::Initialize(const mitk::PixelType& type, int sDim, const mitk::Geometry2D& geometry2d, bool flipped, unsigned int channels, int tDim ) { SlicedGeometry3D::Pointer slicedGeometry = SlicedGeometry3D::New(); slicedGeometry->InitializeEvenlySpaced(static_cast(geometry2d.Clone().GetPointer()), sDim, flipped); Initialize(type, *slicedGeometry, channels, tDim); } void mitk::Image::Initialize(const mitk::Image* image) { Initialize(image->GetPixelType(), *image->GetTimeGeometry()); } void mitk::Image::Initialize(vtkImageData* vtkimagedata, int channels, int tDim, int sDim, int pDim) { if(vtkimagedata==NULL) return; m_Dimension=vtkimagedata->GetDataDimension(); unsigned int i, *tmpDimensions=new unsigned int[m_Dimension>4?m_Dimension:4]; for(i=0;iGetDimensions()[i]; if(m_Dimension<4) { unsigned int *p; for(i=0,p=tmpDimensions+m_Dimension;i<4-m_Dimension;++i, ++p) *p=1; } if(pDim>=0) { tmpDimensions[1]=pDim; if(m_Dimension < 2) m_Dimension = 2; } if(sDim>=0) { tmpDimensions[2]=sDim; if(m_Dimension < 3) m_Dimension = 3; } if(tDim>=0) { tmpDimensions[3]=tDim; if(m_Dimension < 4) m_Dimension = 4; } switch ( vtkimagedata->GetScalarType() ) { case VTK_BIT: case VTK_CHAR: //pixelType.Initialize(typeid(char), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_UNSIGNED_CHAR: //pixelType.Initialize(typeid(unsigned char), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_SHORT: //pixelType.Initialize(typeid(short), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_UNSIGNED_SHORT: //pixelType.Initialize(typeid(unsigned short), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_INT: //pixelType.Initialize(typeid(int), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_UNSIGNED_INT: //pixelType.Initialize(typeid(unsigned int), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_LONG: //pixelType.Initialize(typeid(long), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_UNSIGNED_LONG: //pixelType.Initialize(typeid(unsigned long), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_FLOAT: //pixelType.Initialize(typeid(float), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; case VTK_DOUBLE: //pixelType.Initialize(typeid(double), vtkimagedata->GetNumberOfScalarComponents()); Initialize(mitk::MakeScalarPixelType(), m_Dimension, tmpDimensions, channels); break; default: break; } /* Initialize(pixelType, m_Dimension, tmpDimensions, channels); */ const double *spacinglist = vtkimagedata->GetSpacing(); Vector3D spacing; FillVector3D(spacing, spacinglist[0], 1.0, 1.0); if(m_Dimension>=2) spacing[1]=spacinglist[1]; if(m_Dimension>=3) spacing[2]=spacinglist[2]; // access origin of vtkImage Point3D origin; - vtkFloatingPointType vtkorigin[3]; + double vtkorigin[3]; vtkimagedata->GetOrigin(vtkorigin); FillVector3D(origin, vtkorigin[0], 0.0, 0.0); if(m_Dimension>=2) origin[1]=vtkorigin[1]; if(m_Dimension>=3) origin[2]=vtkorigin[2]; SlicedGeometry3D* slicedGeometry = GetSlicedGeometry(0); // re-initialize PlaneGeometry with origin and direction PlaneGeometry* planeGeometry = static_cast(slicedGeometry->GetGeometry2D(0)); planeGeometry->SetOrigin(origin); // re-initialize SlicedGeometry3D slicedGeometry->SetOrigin(origin); slicedGeometry->SetSpacing(spacing); ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); timeGeometry->Initialize(slicedGeometry, m_Dimensions[3]); SetTimeGeometry(timeGeometry); delete [] tmpDimensions; } bool mitk::Image::IsValidSlice(int s, int t, int n) const { if(m_Initialized) return ((s>=0) && (s<(int)m_Dimensions[2]) && (t>=0) && (t< (int) m_Dimensions[3]) && (n>=0) && (n< (int)GetNumberOfChannels())); else return false; } bool mitk::Image::IsValidVolume(int t, int n) const { if(m_Initialized) return IsValidSlice(0, t, n); else return false; } bool mitk::Image::IsValidChannel(int n) const { if(m_Initialized) return IsValidSlice(0, 0, n); else return false; } void mitk::Image::ComputeOffsetTable() { if(m_OffsetTable!=NULL) delete [] m_OffsetTable; m_OffsetTable=new size_t[m_Dimension>4 ? m_Dimension+1 : 4+1]; unsigned int i; size_t num=1; m_OffsetTable[0] = 1; for (i=0; i < m_Dimension; ++i) { num *= m_Dimensions[i]; m_OffsetTable[i+1] = num; } for (;i < 4; ++i) m_OffsetTable[i+1] = num; } bool mitk::Image::IsValidTimeStep(int t) const { return ( ( m_Dimension >= 4 && t <= (int)m_Dimensions[3] && t > 0 ) || (t == 0) ); } void mitk::Image::Expand(unsigned int timeSteps) { if(timeSteps < 1) itkExceptionMacro(<< "Invalid timestep in Image!"); Superclass::Expand(timeSteps); } int mitk::Image::GetSliceIndex(int s, int t, int n) const { if(IsValidSlice(s,t,n)==false) return false; return ((size_t)s)+((size_t) t)*m_Dimensions[2]+((size_t) n)*m_Dimensions[3]*m_Dimensions[2]; //?? } int mitk::Image::GetVolumeIndex(int t, int n) const { if(IsValidVolume(t,n)==false) return false; return ((size_t)t)+((size_t) n)*m_Dimensions[3]; //?? } mitk::Image::ImageDataItemPointer mitk::Image::AllocateSliceData(int s, int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) { int pos; pos=GetSliceIndex(s,t,n); const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); // is slice available as part of a volume that is available? ImageDataItemPointer sl, ch, vol; vol=m_Volumes[GetVolumeIndex(t,n)]; if(vol.GetPointer()!=NULL) { sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*m_OffsetTable[2]*(ptypeSize)); sl->SetComplete(true); return m_Slices[pos]=sl; } // is slice available as part of a channel that is available? ch=m_Channels[n]; if(ch.GetPointer()!=NULL) { sl=new ImageDataItem(*ch, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, (((size_t) s)*m_OffsetTable[2]+((size_t) t)*m_OffsetTable[3])*(ptypeSize)); sl->SetComplete(true); return m_Slices[pos]=sl; } // allocate new volume (instead of a single slice to keep data together!) m_Volumes[GetVolumeIndex(t,n)]=vol=AllocateVolumeData(t,n,NULL,importMemoryManagement); sl=new ImageDataItem(*vol, m_ImageDescriptor, 2, data, importMemoryManagement == ManageMemory, ((size_t) s)*m_OffsetTable[2]*(ptypeSize)); sl->SetComplete(true); return m_Slices[pos]=sl; ////ALTERNATIVE: //// allocate new slice //sl=new ImageDataItem(*m_PixelType, 2, m_Dimensions); //m_Slices[pos]=sl; //return vol; } mitk::Image::ImageDataItemPointer mitk::Image::AllocateVolumeData(int t, int n, void *data, ImportMemoryManagementType importMemoryManagement) { int pos; pos=GetVolumeIndex(t,n); const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); // is volume available as part of a channel that is available? ImageDataItemPointer ch, vol; ch=m_Channels[n]; if(ch.GetPointer()!=NULL) { vol=new ImageDataItem(*ch, m_ImageDescriptor, 3, data,importMemoryManagement == ManageMemory, (((size_t) t)*m_OffsetTable[3])*(ptypeSize)); return m_Volumes[pos]=vol; } mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(n); // allocate new volume if(importMemoryManagement == CopyMemory) { vol=new ImageDataItem( chPixelType, 3, m_Dimensions, NULL, true); if(data != NULL) std::memcpy(vol->GetData(), data, m_OffsetTable[3]*(ptypeSize)); } else { vol=new ImageDataItem( chPixelType, 3, m_Dimensions, data, importMemoryManagement == ManageMemory); } m_Volumes[pos]=vol; return vol; } mitk::Image::ImageDataItemPointer mitk::Image::AllocateChannelData(int n, void *data, ImportMemoryManagementType importMemoryManagement) { ImageDataItemPointer ch; // allocate new channel if(importMemoryManagement == CopyMemory) { const size_t ptypeSize = this->m_ImageDescriptor->GetChannelTypeById(n).GetSize(); ch=new ImageDataItem(this->m_ImageDescriptor, NULL, true); if(data != NULL) std::memcpy(ch->GetData(), data, m_OffsetTable[4]*(ptypeSize)); } else { ch=new ImageDataItem(this->m_ImageDescriptor, data, importMemoryManagement == ManageMemory); } m_Channels[n]=ch; return ch; } unsigned int* mitk::Image::GetDimensions() const { return m_Dimensions; } void mitk::Image::Clear() { Superclass::Clear(); delete [] m_Dimensions; m_Dimensions = NULL; } void mitk::Image::SetGeometry(Geometry3D* aGeometry3D) { // Please be aware of the 0.5 offset/pixel-center issue! See Geometry documentation for further information if(aGeometry3D->GetImageGeometry()==false) { MITK_INFO << "WARNING: Applied a non-image geometry onto an image. Please be SURE that this geometry is pixel-center-based! If it is not, you need to call Geometry3D->ChangeImageGeometryConsideringOriginOffset(true) before calling image->setGeometry(..)\n"; } Superclass::SetGeometry(aGeometry3D); for (TimeStepType step = 0; step < GetTimeGeometry()->CountTimeSteps(); ++step) GetTimeGeometry()->GetGeometryForTimeStep(step)->ImageGeometryOn(); } void mitk::Image::PrintSelf(std::ostream& os, itk::Indent indent) const { unsigned char i; if(m_Initialized) { os << indent << " Dimension: " << m_Dimension << std::endl; os << indent << " Dimensions: "; for(i=0; i < m_Dimension; ++i) os << GetDimension(i) << " "; os << std::endl; for(unsigned int ch=0; ch < this->m_ImageDescriptor->GetNumberOfChannels(); ch++) { mitk::PixelType chPixelType = this->m_ImageDescriptor->GetChannelTypeById(ch); os << indent << " Channel: " << this->m_ImageDescriptor->GetChannelName(ch) << std::endl; os << indent << " PixelType: " << chPixelType.GetPixelTypeAsString() << std::endl; os << indent << " BytesPerElement: " << chPixelType.GetSize() << std::endl; os << indent << " ComponentType: " << chPixelType.GetComponentTypeAsString() << std::endl; os << indent << " NumberOfComponents: " << chPixelType.GetNumberOfComponents() << std::endl; os << indent << " BitsPerComponent: " << chPixelType.GetBitsPerComponent() << std::endl; } } else { os << indent << " Image not initialized: m_Initialized: false" << std::endl; } Superclass::PrintSelf(os,indent); } bool mitk::Image::IsRotated() const { const mitk::Geometry3D* geo = this->GetGeometry(); bool ret = false; if(geo) { const vnl_matrix_fixed & mx = geo->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix(); float ref = 0; for(short k = 0; k < 3; ++k) ref += mx[k][k]; ref/=1000; // Arbitrary value; if a non-diagonal (nd) element is bigger then this, matrix is considered nd. for(short i = 0; i < 3; ++i) { for(short j = 0; j < 3; ++j) { if(i != j) { if(std::abs(mx[i][j]) > ref) // matrix is nd ret = true; } } } } return ret; } mitk::ScalarType mitk::Image::GetScalarValueMin(int t) const { return m_ImageStatistics->GetScalarValueMin(t); } //## \brief Get the maximum for scalar images mitk::ScalarType mitk::Image::GetScalarValueMax(int t) const { return m_ImageStatistics->GetScalarValueMax(t); } //## \brief Get the second smallest value for scalar images mitk::ScalarType mitk::Image::GetScalarValue2ndMin(int t) const { return m_ImageStatistics->GetScalarValue2ndMin(t); } mitk::ScalarType mitk::Image::GetScalarValueMinNoRecompute( unsigned int t ) const { return m_ImageStatistics->GetScalarValueMinNoRecompute(t); } mitk::ScalarType mitk::Image::GetScalarValue2ndMinNoRecompute( unsigned int t ) const { return m_ImageStatistics->GetScalarValue2ndMinNoRecompute(t); } mitk::ScalarType mitk::Image::GetScalarValue2ndMax(int t) const { return m_ImageStatistics->GetScalarValue2ndMax(t); } mitk::ScalarType mitk::Image::GetScalarValueMaxNoRecompute( unsigned int t) const { return m_ImageStatistics->GetScalarValueMaxNoRecompute(t); } mitk::ScalarType mitk::Image::GetScalarValue2ndMaxNoRecompute( unsigned int t ) const { return m_ImageStatistics->GetScalarValue2ndMaxNoRecompute(t); } mitk::ScalarType mitk::Image::GetCountOfMinValuedVoxels(int t ) const { return m_ImageStatistics->GetCountOfMinValuedVoxels(t); } mitk::ScalarType mitk::Image::GetCountOfMaxValuedVoxels(int t) const { return m_ImageStatistics->GetCountOfMaxValuedVoxels(t); } unsigned int mitk::Image::GetCountOfMaxValuedVoxelsNoRecompute( unsigned int t ) const { return m_ImageStatistics->GetCountOfMaxValuedVoxelsNoRecompute(t); } unsigned int mitk::Image::GetCountOfMinValuedVoxelsNoRecompute( unsigned int t ) const { return m_ImageStatistics->GetCountOfMinValuedVoxelsNoRecompute(t); } bool mitk::Equal(const mitk::Image* rightHandSide, const mitk::Image* leftHandSide, ScalarType eps, bool verbose) { bool returnValue = true; if( rightHandSide == NULL ) { if(verbose) MITK_INFO << "[( Image )] rightHandSide is NULL."; return false; } if( leftHandSide == NULL ) { if(verbose) MITK_INFO << "[( Image )] leftHandSide is NULL."; return false; } // Dimensionality if( rightHandSide->GetDimension() != leftHandSide->GetDimension() ) { if(verbose) { MITK_INFO << "[( Image )] Dimensionality differs."; MITK_INFO << "rightHandSide is " << rightHandSide->GetDimension() << "leftHandSide is " << leftHandSide->GetDimension(); } returnValue = false; } // Pair-wise dimension (size) comparison unsigned int minDimensionality = std::min(rightHandSide->GetDimension(),leftHandSide->GetDimension()); for( unsigned int i=0; i< minDimensionality; ++i) { if( rightHandSide->GetDimension(i) != leftHandSide->GetDimension(i) ) { returnValue = false; if(verbose) { MITK_INFO << "[( Image )] dimension differs."; MITK_INFO << "rightHandSide->GetDimension("<GetDimension(i) << "leftHandSide->GetDimension("<GetDimension(i); } } } // Pixeltype mitk::PixelType pixelTypeRightHandSide = rightHandSide->GetPixelType(); mitk::PixelType pixelTypeLeftHandSide = leftHandSide->GetPixelType(); if( !( pixelTypeRightHandSide == pixelTypeLeftHandSide ) ) { if(verbose) { MITK_INFO << "[( Image )] PixelType differs."; MITK_INFO << "rightHandSide is " << pixelTypeRightHandSide.GetTypeAsString() << "leftHandSide is " << pixelTypeLeftHandSide.GetTypeAsString(); } returnValue = false; } // Geometries if( !mitk::Equal( leftHandSide->GetGeometry(), rightHandSide->GetGeometry(), eps, verbose) ) { if(verbose) { MITK_INFO << "[( Image )] Geometries differ."; } returnValue = false; } // Pixel values - default mode [ 0 threshold in difference ] // compare only if all previous checks were successfull, otherwise the ITK filter will throw an exception if( returnValue ) { mitk::CompareImageFilter::Pointer compareFilter = mitk::CompareImageFilter::New(); compareFilter->SetInput(0, rightHandSide); compareFilter->SetInput(1, leftHandSide); compareFilter->Update(); if(( !compareFilter->GetResult() ) ) { returnValue = false; if(verbose) { MITK_INFO << "[(Image)] Pixel values differ: "; } compareFilter->GetCompareResults().PrintSelf(); } } return returnValue; } diff --git a/Core/Code/DataManagement/mitkMaterial.cpp b/Core/Code/DataManagement/mitkMaterial.cpp index aeaa06cd63..e6ef53a423 100644 --- a/Core/Code/DataManagement/mitkMaterial.cpp +++ b/Core/Code/DataManagement/mitkMaterial.cpp @@ -1,389 +1,389 @@ /*=================================================================== 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 "mitkMaterial.h" #include "mitkProperties.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkRepresentationProperty.h" #include #include "mitkDataNode.h" #include "mitkBaseRenderer.h" -mitk::Material::Material( Color color, vtkFloatingPointType opacity ) +mitk::Material::Material( Color color, double opacity ) { InitializeStandardValues(); SetColor( color ); SetColorCoefficient( GetColorCoefficient() ); SetSpecularColor( GetSpecularColor() ); SetSpecularCoefficient( GetSpecularCoefficient() ); SetSpecularPower( GetSpecularPower() ); SetOpacity( opacity ); SetInterpolation( GetInterpolation() ); SetRepresentation( GetRepresentation() ); SetLineWidth( GetLineWidth() ); m_Name = ""; } -mitk::Material::Material( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType opacity ) +mitk::Material::Material( double red, double green, double blue, double opacity ) { InitializeStandardValues(); SetColor( red, green, blue ); SetColorCoefficient( GetColorCoefficient() ); SetSpecularColor( GetSpecularColor() ); SetSpecularCoefficient( GetSpecularCoefficient() ); SetSpecularPower( GetSpecularPower() ); SetOpacity( opacity ); SetInterpolation( GetInterpolation() ); SetRepresentation( GetRepresentation() ); SetLineWidth( GetLineWidth() ); m_Name = ""; } -mitk::Material::Material( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, - vtkFloatingPointType colorCoefficient, vtkFloatingPointType specularCoefficient, - vtkFloatingPointType specularPower, vtkFloatingPointType opacity ) +mitk::Material::Material( double red, double green, double blue, + double colorCoefficient, double specularCoefficient, + double specularPower, double opacity ) { InitializeStandardValues(); SetColor( red, green, blue ); SetColorCoefficient( colorCoefficient ); SetSpecularColor( GetSpecularColor() ); SetSpecularCoefficient( specularCoefficient ); SetSpecularPower( specularPower ); SetOpacity( opacity ); SetInterpolation( GetInterpolation() ); SetRepresentation( GetRepresentation() ); SetLineWidth( GetLineWidth() ); m_Name = ""; } -mitk::Material::Material( mitk::Material::Color color, vtkFloatingPointType colorCoefficient, vtkFloatingPointType specularCoefficient, vtkFloatingPointType specularPower, vtkFloatingPointType opacity ) +mitk::Material::Material( mitk::Material::Color color, double colorCoefficient, double specularCoefficient, double specularPower, double opacity ) { InitializeStandardValues(); SetColor( color ); SetColorCoefficient( colorCoefficient ); SetSpecularColor( GetSpecularColor() ); SetSpecularCoefficient( specularCoefficient ); SetSpecularPower( specularPower ); SetOpacity( opacity ); SetInterpolation( GetInterpolation() ); SetRepresentation( GetRepresentation() ); SetLineWidth( GetLineWidth() ); } mitk::Material::Material( ) { InitializeStandardValues(); SetColor( GetColor() ); SetColorCoefficient( GetColorCoefficient() ); SetSpecularColor( GetSpecularColor() ); SetSpecularCoefficient( GetSpecularCoefficient() ); SetSpecularPower( GetSpecularPower() ); SetOpacity( GetOpacity() ); SetInterpolation( GetInterpolation() ); SetRepresentation( GetRepresentation() ); SetLineWidth( GetLineWidth() ); } mitk::Material::Material( const Material& property ) : itk::Object() { Initialize( property ); } -mitk::Material::Material( const Material& property, vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType opacity, std::string name ) +mitk::Material::Material( const Material& property, double red, double green, double blue, double opacity, std::string name ) { Initialize( property ); SetColor( red, green, blue ); SetOpacity( opacity ); SetName( name ); } bool mitk::Material::Assignable(const Material& other) const { try { const Material& otherinstance = dynamic_cast(other); // dear compiler, please don't optimize this away! Thanks. otherinstance.GetOpacity(); return true; } catch (std::bad_cast) { } return false; } mitk::Material& mitk::Material::operator=(const mitk::Material& other) { try { const Self& otherProp( dynamic_cast(other) ); Initialize(otherProp); } catch (std::bad_cast) { // nothing to do then } return *this; } void mitk::Material::SetColor( mitk::Material::Color color ) { m_Color = color; Modified(); } -void mitk::Material::SetColor( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue ) +void mitk::Material::SetColor( double red, double green, double blue ) { m_Color.Set( red, green, blue ); Modified(); } -void mitk::Material::SetColorCoefficient( vtkFloatingPointType coefficient ) +void mitk::Material::SetColorCoefficient( double coefficient ) { m_ColorCoefficient = coefficient; Modified(); } void mitk::Material::SetSpecularColor( mitk::Material::Color specularColor ) { m_SpecularColor = specularColor; Modified(); } -void mitk::Material::SetSpecularColor( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue ) +void mitk::Material::SetSpecularColor( double red, double green, double blue ) { m_SpecularColor.Set( red, green, blue ); Modified(); } -void mitk::Material::SetSpecularCoefficient( vtkFloatingPointType specularCoefficient ) +void mitk::Material::SetSpecularCoefficient( double specularCoefficient ) { m_SpecularCoefficient = specularCoefficient; Modified(); } -void mitk::Material::SetSpecularPower( vtkFloatingPointType specularPower ) +void mitk::Material::SetSpecularPower( double specularPower ) { m_SpecularPower = specularPower; Modified(); } -void mitk::Material::SetOpacity( vtkFloatingPointType opacity ) +void mitk::Material::SetOpacity( double opacity ) { m_Opacity = opacity; Modified(); } void mitk::Material::SetInterpolation( InterpolationType interpolation ) { m_Interpolation = interpolation; Modified(); } void mitk::Material::SetRepresentation( RepresentationType representation ) { m_Representation = representation; Modified(); } void mitk::Material::SetLineWidth( float lineWidth ) { m_LineWidth = lineWidth; Modified(); } mitk::Material::Color mitk::Material::GetColor() const { return m_Color; } -vtkFloatingPointType mitk::Material::GetColorCoefficient() const +double mitk::Material::GetColorCoefficient() const { return m_ColorCoefficient; } mitk::Material::Color mitk::Material::GetSpecularColor() const { return m_SpecularColor; } -vtkFloatingPointType mitk::Material::GetSpecularCoefficient() const +double mitk::Material::GetSpecularCoefficient() const { return m_SpecularCoefficient; } -vtkFloatingPointType mitk::Material::GetSpecularPower() const +double mitk::Material::GetSpecularPower() const { return m_SpecularPower; } -vtkFloatingPointType mitk::Material::GetOpacity() const +double mitk::Material::GetOpacity() const { return m_Opacity; } mitk::Material::InterpolationType mitk::Material::GetInterpolation() const { return m_Interpolation; } mitk::Material::RepresentationType mitk::Material::GetRepresentation() const { return m_Representation; } int mitk::Material::GetVtkInterpolation() const { switch ( m_Interpolation ) { case( Flat ) : return VTK_FLAT; case( Gouraud ) : return VTK_GOURAUD; case( Phong ) : return VTK_PHONG; } return VTK_GOURAUD; } int mitk::Material::GetVtkRepresentation() const { switch ( m_Representation ) { case( Points ) : return VTK_POINTS; case( Wireframe ) : return VTK_WIREFRAME; case( Surface ) : return VTK_SURFACE; } return VTK_SURFACE; } float mitk::Material::GetLineWidth() const { return m_LineWidth; } void mitk::Material::Initialize( const Material& property ) { this->SetColor( property.GetColor() ); this->SetColorCoefficient( property.GetColorCoefficient() ); this->SetSpecularColor( property.GetSpecularColor() ); this->SetSpecularCoefficient( property.GetSpecularCoefficient() ); this->SetSpecularPower( property.GetSpecularPower() ); this->SetOpacity( property.GetOpacity() ); this->SetInterpolation( property.GetInterpolation() ); this->SetRepresentation( property.GetRepresentation() ); this->SetLineWidth( property.GetLineWidth() ); this->SetName( property.GetName() ); } bool mitk::Material::operator==( const Material& property ) const { const Self * other = dynamic_cast( &property ); if ( other == NULL ) return false; else return ( m_Color == other->GetColor() && m_ColorCoefficient == other->GetColorCoefficient() && m_SpecularColor == other->GetSpecularColor() && m_SpecularCoefficient == other->GetSpecularCoefficient() && m_SpecularPower == other->GetSpecularPower() && m_Opacity == other->GetOpacity() && m_Interpolation == other->GetInterpolation() && m_Name == other->GetName() && m_Representation == other->GetRepresentation() && m_LineWidth == other->GetLineWidth() ); } void mitk::Material::InitializeStandardValues() { m_Color.Set( 0.5, 0.5, 0.0 ); m_ColorCoefficient = 0.5 ; m_SpecularColor.Set( 1.0, 1.0, 1.0 ); m_SpecularCoefficient = 0.5; m_SpecularPower = 10.0; m_Opacity = 1.0 ; m_Interpolation = Gouraud; m_Representation = Surface; m_LineWidth = 1.0; m_Name = ""; } void mitk::Material::Update() { this->SetColor( this->GetColor() ); this->SetColorCoefficient( this->GetColorCoefficient() ); this->SetSpecularColor( this->GetSpecularColor() ); this->SetSpecularCoefficient( this->GetSpecularCoefficient() ); this->SetSpecularPower( this->GetSpecularPower() ); this->SetOpacity( this->GetOpacity() ); this->SetInterpolation( this->GetInterpolation() ); this->SetRepresentation( this->GetRepresentation() ); } void mitk::Material::PrintSelf ( std::ostream &os, itk::Indent /* unused */ ) const { os << "Name: " << GetName() << std::endl; os << "Color: " << GetColor() << std::endl; os << "ColorCoefficient" << GetColorCoefficient() << std::endl; os << "SpecularColor: " << GetSpecularColor() << std::endl; os << "SpecularCoefficient: " << GetSpecularCoefficient() << std::endl; os << "SpecularPower: " << GetSpecularPower() << std::endl; os << "Opacity: " << GetOpacity() << std::endl; os << "Line width: " << GetLineWidth() << std::endl; switch ( GetInterpolation() ) { case ( Flat ) : os << "Interpolation: Flat" << std::endl; break; case ( Gouraud ) : os << "Interpolation: Gouraud" << std::endl; break; case ( Phong ) : os << "Interpolation: Phong" << std::endl; break; } switch ( GetRepresentation() ) { case ( Points ) : os << "Representation: Points" << std::endl; break; case ( Wireframe ) : os << "Representation: Wireframe" << std::endl; break; case ( Surface ) : os << "Representation: Surface" << std::endl; break; } } diff --git a/Core/Code/DataManagement/mitkMaterial.h b/Core/Code/DataManagement/mitkMaterial.h index a39992f720..5fdac855ef 100644 --- a/Core/Code/DataManagement/mitkMaterial.h +++ b/Core/Code/DataManagement/mitkMaterial.h @@ -1,475 +1,475 @@ /*=================================================================== 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_MATERIAL_H_ #define _MITK_MATERIAL_H_ #include #include #include #include #include #include #include namespace mitk { /** * Encapsulates 3D visualization properties which are forwarded to vtk for * color mapping. This includes color, specular coefficient and power, opacity * interpolation type (flat, gouraud, phong) and representation (points, * wireframe or surface). * * @see vtkProperty */ class MITK_CORE_EXPORT Material : public itk::Object { public: mitkClassMacro( Material, itk::Object ); - typedef itk::RGBPixel Color; + typedef itk::RGBPixel Color; enum InterpolationType { Flat, Gouraud, Phong }; enum RepresentationType { Points, Wireframe, Surface }; /** * Constructor. Materials are set to the following default values: * Color (0.5, 0.5, 0.5) color coefficient 1.0, specular color (1.0, 1.0, 1.0), * specular coefficient 1.0, specular power 10, opacity 1.0, interpolation * Gouraud, representation Surface. * @param node optinally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ static Pointer New() { Pointer smartPtr = new Material( ); smartPtr->UnRegister(); return smartPtr; } /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * @param color the material color in RGB. Each RGB value should be in the * range [0..1] * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optinally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - static Pointer New( Color color, vtkFloatingPointType opacity = 1.0f) + static Pointer New( Color color, double opacity = 1.0f) { Pointer smartPtr = new Material(color, opacity ); smartPtr->UnRegister(); return smartPtr; } /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * @param red the red component of the materials color (range [0..1]) * @param green the green component of the materials color (range [0..1]) * @param blue the blue component of the materials color (range [0..1]) * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optionally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - static Pointer New( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType opacity = 1.0f) + static Pointer New( double red, double green, double blue, double opacity = 1.0f) { Pointer smartPtr = new Material(red, green, blue, opacity ); smartPtr->UnRegister(); return smartPtr; } /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * @param red the red component of the materials color (range [0..1]) * @param green the green component of the materials color (range [0..1]) * @param blue the blue component of the materials color (range [0..1]) * @param colorCoefficient a scaling factor for the color coefficient which * will be multiplied with each color component (range [0..1]). * @param specularCoefficient controls in combination with the specular power * how shiny the material will appear (range [0..1]). * @param specularPower controls in combination with the specular coefficient * how shiny the material will appear (range [0..inf]). * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optionally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - static Pointer New( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType colorCoefficient, - vtkFloatingPointType specularCoefficient, vtkFloatingPointType specularPower, vtkFloatingPointType opacity ) + static Pointer New( double red, double green, double blue, double colorCoefficient, + double specularCoefficient, double specularPower, double opacity ) { Pointer smartPtr = new Material(red, green, blue, colorCoefficient, specularCoefficient, specularPower, opacity ); smartPtr->UnRegister(); return smartPtr; } /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * * @param color the material color in RGB. Each RGB value should be in the * range [0..1] * @param colorCoefficient a scaling factor for the color coefficient which * will be multiplied with each color component (range [0..1]). * @param specularCoefficient controls in combination with the specular power * how shiny the material will appear (range [0..1]). * @param specularPower controls in combination with the specular coefficient * how shiny the material will appear (range [0..inf]). * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optionally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - static Pointer New( Color color, vtkFloatingPointType colorCoefficient, vtkFloatingPointType specularCoefficient, vtkFloatingPointType specularPower, vtkFloatingPointType opacity ) + static Pointer New( Color color, double colorCoefficient, double specularCoefficient, double specularPower, double opacity ) { Pointer smartPtr = new Material(color, colorCoefficient, specularCoefficient, specularPower, opacity ); smartPtr->UnRegister(); return smartPtr; } /** * Copy constructor */ mitkNewMacro1Param(Material, const Material&); /** * Copy constructor, provided for convinience. The values are copied from property * and afterwards the values provided for red green blue and opacity are written into the object. */ - static Pointer New( const Material& property, vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType opacity = 1.0, std::string name = "" ) + static Pointer New( const Material& property, double red, double green, double blue, double opacity = 1.0, std::string name = "" ) { Pointer smartPtr = new Material(property, red, green, blue, opacity, name ); smartPtr->UnRegister(); return smartPtr; } virtual bool Assignable(const Material& other) const; virtual Material& operator=(const Material& other); /* Sets the materials color in RGB space. The rgb components have to be * in the range [0..1] * @param color the new color of the material */ virtual void SetColor( Color color ); /** * Sets the materials color in RGB space. The rgb components have to be * in the range [0..1] * @param red the red component of the materials color (range [0..1]) * @param green the green component of the materials color (range [0..1]) * @param blue the blue component of the materials color (range [0..1]) */ - virtual void SetColor( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue ); + virtual void SetColor( double red, double green, double blue ); /** * Sets a attenuation coefficient for the color. A value of 0 results in * a black object. VAlid range is [0..1] * @param coefficient the color attenuation coefficient */ - virtual void SetColorCoefficient( vtkFloatingPointType coefficient ); + virtual void SetColorCoefficient( double coefficient ); /** * Sets the specular color * @param color the specular color in RGB. Each RGB value should be in the * range [0..1] */ virtual void SetSpecularColor( Color color ); /** * Sets the specular color * @param red the red component of the specular color (range [0..1]) * @param green the green component of the specular color (range [0..1]) * @param blue the blue component of the specular color (range [0..1]) */ - virtual void SetSpecularColor( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue ); + virtual void SetSpecularColor( double red, double green, double blue ); /** * Sets the specular coefficient which controls the shininess of the object * together with the specular power * @param specularCoefficient the new specular coefficient. Valid range * is [0..1] */ - virtual void SetSpecularCoefficient( vtkFloatingPointType specularCoefficient ); + virtual void SetSpecularCoefficient( double specularCoefficient ); /** * Sets the specular power which controls the shininess of the object * together with the specular coefficient * @param specularCoefficient the new specular coefficient. Valid range * is [0..inf] */ - virtual void SetSpecularPower( vtkFloatingPointType specularPower ); + virtual void SetSpecularPower( double specularPower ); /** * Sets the opacity of the material, which controls how transparent the * object appears. Valid range is [0..1], where 0 means fully transparent * and 1 means a solid surface. * @param opacity the new opacity of the material */ - virtual void SetOpacity( vtkFloatingPointType opacity ); + virtual void SetOpacity( double opacity ); /** * Sets the surface interpolation method of the object rendered using the * given materials. Valid Interopation types are Flat, Gouraud and Phong. * See any computer graphics book for their meaning * @param interpolation the interpolation method used for rendering of * surfaces. */ virtual void SetInterpolation( InterpolationType interpolation ); /** * Sets the surface representation method of the object rendered using the * given materials. Valid Interopation types are Points, Wireframe and * Surface. * @param representation the representation method used for rendering of * surfaces. */ virtual void SetRepresentation( RepresentationType representation ); /** * Set/Get the width of a Line. The width is expressed in screen units. The default is 1.0. */ virtual void SetLineWidth( float lineWidth ); /** * @returns the color of the material */ virtual Color GetColor() const; /** * @returns the color coefficient of the material. Range is [0..1] */ - virtual vtkFloatingPointType GetColorCoefficient() const; + virtual double GetColorCoefficient() const; /** * @returns the specular color of the material in rgb values, which * range from 0 .. 1 */ virtual Color GetSpecularColor() const; /** * @returns the specular coefficient used for rendering. Range is [0..1] */ - virtual vtkFloatingPointType GetSpecularCoefficient() const; + virtual double GetSpecularCoefficient() const; /** * @returns the specular power. Ranges from 0 to infinity */ - virtual vtkFloatingPointType GetSpecularPower() const; + virtual double GetSpecularPower() const; /** * @returns the opacity of the material. Ranges from 0 to 1 */ - virtual vtkFloatingPointType GetOpacity() const; + virtual double GetOpacity() const; /** * @returns the interpolation method used for rendering. */ virtual InterpolationType GetInterpolation() const; /** * @returns the representation type used for rendering. */ virtual RepresentationType GetRepresentation() const; /** * @returns the interpolation method used for rendering using the predefined * vtk constants. */ virtual int GetVtkInterpolation() const; /** * @returns the representation type used for rendering using the predefined * vtk constants. */ virtual int GetVtkRepresentation() const; /** * @returns the line width used for wireframe rendering as a fraction of screen units */ virtual float GetLineWidth() const; /** * Fills the current materials with the properties of the * given material. * @param property the materials which should be copied in the * current materials */ virtual void Initialize( const Material& property ); /** * comparison operator which uses the member variables for * comparison */ virtual bool operator==( const Material& property ) const; /** * Dumps the properties to the out stream out */ void PrintSelf ( std::ostream &os, itk::Indent ) const; /** * Sets an optional name which may be associated with the material property * Please note, that this name is NOT forwarded to the data tree node * as the node name */ itkSetMacro( Name, std::string ); /** * returns the name associated with the material property */ itkGetConstMacro( Name, std::string ); protected: /** * Constructor. Materials are set to the following default values: * Color (0.5, 0.5, 0.5) color coefficient 1.0, specular color (1.0, 1.0, 1.0), * specular coefficient 1.0, specular power 10, opacity 1.0, interpolation * Gouraud, representation Surface. * @param node optinally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ Material( ); /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * @param color the material color in RGB. Each RGB value should be in the * range [0..1] * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optinally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - Material( Color color, vtkFloatingPointType opacity = 1.0f ); + Material( Color color, double opacity = 1.0f ); /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * @param red the red component of the materials color (range [0..1]) * @param green the green component of the materials color (range [0..1]) * @param blue the blue component of the materials color (range [0..1]) * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optionally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - Material( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType opacity = 1.0f ); + Material( double red, double green, double blue, double opacity = 1.0f ); /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * @param red the red component of the materials color (range [0..1]) * @param green the green component of the materials color (range [0..1]) * @param blue the blue component of the materials color (range [0..1]) * @param colorCoefficient a scaling factor for the color coefficient which * will be multiplied with each color component (range [0..1]). * @param specularCoefficient controls in combination with the specular power * how shiny the material will appear (range [0..1]). * @param specularPower controls in combination with the specular coefficient * how shiny the material will appear (range [0..inf]). * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optionally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - Material( vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType colorCoefficient, - vtkFloatingPointType specularCoefficient, vtkFloatingPointType specularPower, vtkFloatingPointType opacity ); + Material( double red, double green, double blue, double colorCoefficient, + double specularCoefficient, double specularPower, double opacity ); /** * Constructor. All values besides the given ones are set to defaults as * described in the default constructor * * @param color the material color in RGB. Each RGB value should be in the * range [0..1] * @param colorCoefficient a scaling factor for the color coefficient which * will be multiplied with each color component (range [0..1]). * @param specularCoefficient controls in combination with the specular power * how shiny the material will appear (range [0..1]). * @param specularPower controls in combination with the specular coefficient * how shiny the material will appear (range [0..inf]). * @param opacity the opacity of the material. 0.0 means fully transparent * and 1.0 means solid. * @param node optionally a data tree node may be defined to which the properties * are forwarded. Please note, that if this node doesn't have the * needed properties associated, they will be added. */ - Material( Color color, vtkFloatingPointType colorCoefficient, vtkFloatingPointType specularCoefficient, vtkFloatingPointType specularPower, vtkFloatingPointType opacity ); + Material( Color color, double colorCoefficient, double specularCoefficient, double specularPower, double opacity ); /** * Copy constructor */ Material( const Material& property ); /** * Copy constructor, provided for convinience. The values are copied from property * and afterwards the values provided for red green blue and opacity are written into the object. */ - Material( const Material& property, vtkFloatingPointType red, vtkFloatingPointType green, vtkFloatingPointType blue, vtkFloatingPointType opacity = 1.0, std::string name = ""); + Material( const Material& property, double red, double green, double blue, double opacity = 1.0, std::string name = ""); virtual void InitializeStandardValues(); virtual void Update(); std::string m_Name; Color m_Color; Color m_SpecularColor; - vtkFloatingPointType m_ColorCoefficient; + double m_ColorCoefficient; - vtkFloatingPointType m_SpecularCoefficient; + double m_SpecularCoefficient; - vtkFloatingPointType m_SpecularPower; + double m_SpecularPower; - vtkFloatingPointType m_Opacity; + double m_Opacity; float m_LineWidth; InterpolationType m_Interpolation; RepresentationType m_Representation; }; typedef itk::VectorContainer< unsigned int, Material::Pointer > MaterialVectorContainer; } #endif diff --git a/Core/Code/DataManagement/mitkPlaneGeometry.cpp b/Core/Code/DataManagement/mitkPlaneGeometry.cpp index d6d98c3f8b..364fe98271 100644 --- a/Core/Code/DataManagement/mitkPlaneGeometry.cpp +++ b/Core/Code/DataManagement/mitkPlaneGeometry.cpp @@ -1,777 +1,777 @@ /*=================================================================== 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 "mitkPlaneGeometry.h" #include "mitkPlaneOperation.h" #include "mitkInteractionConst.h" #include "mitkLine.h" #include #include namespace mitk { mitk::PlaneGeometry::PlaneGeometry() { Initialize(); } mitk::PlaneGeometry::~PlaneGeometry() { } void PlaneGeometry::Initialize() { Superclass::Initialize(); } void PlaneGeometry::EnsurePerpendicularNormal(mitk::AffineTransform3D *transform) { //ensure row(2) of transform to be perpendicular to plane, keep length. VnlVector normal = vnl_cross_3d( transform->GetMatrix().GetVnlMatrix().get_column(0), transform->GetMatrix().GetVnlMatrix().get_column(1) ); normal.normalize(); ScalarType len = transform->GetMatrix() .GetVnlMatrix().get_column(2).two_norm(); if (len==0) len = 1; normal*=len; Matrix3D matrix = transform->GetMatrix(); matrix.GetVnlMatrix().set_column(2, normal); transform->SetMatrix(matrix); } void PlaneGeometry::SetIndexToWorldTransform(mitk::AffineTransform3D *transform) { EnsurePerpendicularNormal(transform); Superclass::SetIndexToWorldTransform(transform); } void PlaneGeometry::SetBounds(const BoundingBox::BoundsArrayType &bounds) { //currently the unit rectangle must be starting at the origin [0,0] assert(bounds[0]==0); assert(bounds[2]==0); //the unit rectangle must be two-dimensional assert(bounds[1]>0); assert(bounds[3]>0); Superclass::SetBounds(bounds); } void PlaneGeometry::IndexToWorld( const Point2D &pt_units, Point2D &pt_mm ) const { pt_mm[0]=m_ScaleFactorMMPerUnitX*pt_units[0]; pt_mm[1]=m_ScaleFactorMMPerUnitY*pt_units[1]; } void PlaneGeometry::WorldToIndex( const Point2D &pt_mm, Point2D &pt_units ) const { pt_units[0]=pt_mm[0]*(1.0/m_ScaleFactorMMPerUnitX); pt_units[1]=pt_mm[1]*(1.0/m_ScaleFactorMMPerUnitY); } void PlaneGeometry::IndexToWorld( const Point2D & /*atPt2d_units*/, const Vector2D &vec_units, Vector2D &vec_mm) const { MITK_WARN<<"Warning! Call of the deprecated function PlaneGeometry::IndexToWorld(point, vec, vec). Use PlaneGeometry::IndexToWorld(vec, vec) instead!"; this->IndexToWorld(vec_units, vec_mm); } void PlaneGeometry::IndexToWorld(const Vector2D &vec_units, Vector2D &vec_mm) const { vec_mm[0] = m_ScaleFactorMMPerUnitX * vec_units[0]; vec_mm[1] = m_ScaleFactorMMPerUnitY * vec_units[1]; } void PlaneGeometry::WorldToIndex( const Point2D & /*atPt2d_mm*/, const Vector2D &vec_mm, Vector2D &vec_units) const { MITK_WARN<<"Warning! Call of the deprecated function PlaneGeometry::WorldToIndex(point, vec, vec). Use PlaneGeometry::WorldToIndex(vec, vec) instead!"; this->WorldToIndex(vec_mm, vec_units); } void PlaneGeometry::WorldToIndex( const Vector2D &vec_mm, Vector2D &vec_units) const { vec_units[0] = vec_mm[0] * ( 1.0 / m_ScaleFactorMMPerUnitX ); vec_units[1] = vec_mm[1] * ( 1.0 / m_ScaleFactorMMPerUnitY ); } void PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width, ScalarType height, const Vector3D & spacing, PlaneGeometry::PlaneOrientation planeorientation, ScalarType zPosition, bool frontside, bool rotated ) { AffineTransform3D::Pointer transform; transform = AffineTransform3D::New(); AffineTransform3D::MatrixType matrix; AffineTransform3D::MatrixType::InternalMatrixType &vnlmatrix = matrix.GetVnlMatrix(); vnlmatrix.set_identity(); vnlmatrix(0,0) = spacing[0]; vnlmatrix(1,1) = spacing[1]; vnlmatrix(2,2) = spacing[2]; transform->SetIdentity(); transform->SetMatrix(matrix); InitializeStandardPlane(width, height, transform.GetPointer(), planeorientation, zPosition, frontside, rotated); } void PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width, ScalarType height, const AffineTransform3D* transform, PlaneGeometry::PlaneOrientation planeorientation, ScalarType zPosition, bool frontside, bool rotated ) { Superclass::Initialize(); //construct standard view Point3D origin; VnlVector rightDV(3), bottomDV(3); origin.Fill(0); int normalDirection; switch(planeorientation) { case Axial: if(frontside) { if(rotated==false) { FillVector3D(origin, 0, 0, zPosition); FillVector3D(rightDV, 1, 0, 0); FillVector3D(bottomDV, 0, 1, 0); } else { FillVector3D(origin, width, height, zPosition); FillVector3D(rightDV, -1, 0, 0); FillVector3D(bottomDV, 0, -1, 0); } } else { if(rotated==false) { FillVector3D(origin, width, 0, zPosition); FillVector3D(rightDV, -1, 0, 0); FillVector3D(bottomDV, 0, 1, 0); } else { FillVector3D(origin, 0, height, zPosition); FillVector3D(rightDV, 1, 0, 0); FillVector3D(bottomDV, 0, -1, 0); } } normalDirection = 2; break; case Frontal: if(frontside) { if(rotated==false) { FillVector3D(origin, 0, zPosition, 0); FillVector3D(rightDV, 1, 0, 0); FillVector3D(bottomDV, 0, 0, 1); } else { FillVector3D(origin, width, zPosition, height); FillVector3D(rightDV, -1, 0, 0); FillVector3D(bottomDV, 0, 0, -1); } } else { if(rotated==false) { FillVector3D(origin, width, zPosition, 0); FillVector3D(rightDV, -1, 0, 0); FillVector3D(bottomDV, 0, 0, 1); } else { FillVector3D(origin, 0, zPosition, height); FillVector3D(rightDV, 1, 0, 0); FillVector3D(bottomDV, 0, 0, -1); } } normalDirection = 1; break; case Sagittal: if(frontside) { if(rotated==false) { FillVector3D(origin, zPosition, 0, 0); FillVector3D(rightDV, 0, 1, 0); FillVector3D(bottomDV, 0, 0, 1); } else { FillVector3D(origin, zPosition, width, height); FillVector3D(rightDV, 0, -1, 0); FillVector3D(bottomDV, 0, 0, -1); } } else { if(rotated==false) { FillVector3D(origin, zPosition, width, 0); FillVector3D(rightDV, 0, -1, 0); FillVector3D(bottomDV, 0, 0, 1); } else { FillVector3D(origin, zPosition, 0, height); FillVector3D(rightDV, 0, 1, 0); FillVector3D(bottomDV, 0, 0, -1); } } normalDirection = 0; break; default: itkExceptionMacro("unknown PlaneOrientation"); } if ( transform != NULL ) { origin = transform->TransformPoint( origin ); rightDV = transform->TransformVector( rightDV ); bottomDV = transform->TransformVector( bottomDV ); } ScalarType bounds[6]= { 0, width, 0, height, 0, 1 }; this->SetBounds( bounds ); if ( transform == NULL ) { this->SetMatrixByVectors( rightDV, bottomDV ); } else { this->SetMatrixByVectors( rightDV, bottomDV, transform->GetMatrix().GetVnlMatrix() .get_column(normalDirection).magnitude() ); } this->SetOrigin(origin); } void PlaneGeometry::InitializeStandardPlane( const Geometry3D *geometry3D, PlaneOrientation planeorientation, ScalarType zPosition, bool frontside, bool rotated ) { this->SetReferenceGeometry( const_cast< Geometry3D * >( geometry3D ) ); ScalarType width, height; const BoundingBox::BoundsArrayType& boundsarray = geometry3D->GetBoundingBox()->GetBounds(); Vector3D originVector; FillVector3D(originVector, boundsarray[0], boundsarray[2], boundsarray[4]); if(geometry3D->GetImageGeometry()) { FillVector3D( originVector, originVector[0] - 0.5, originVector[1] - 0.5, originVector[2] - 0.5 ); } switch(planeorientation) { case Axial: width = geometry3D->GetExtent(0); height = geometry3D->GetExtent(1); break; case Frontal: width = geometry3D->GetExtent(0); height = geometry3D->GetExtent(2); break; case Sagittal: width = geometry3D->GetExtent(1); height = geometry3D->GetExtent(2); break; default: itkExceptionMacro("unknown PlaneOrientation"); } InitializeStandardPlane( width, height, geometry3D->GetIndexToWorldTransform(), planeorientation, zPosition, frontside, rotated ); ScalarType bounds[6]= { 0, width, 0, height, 0, 1 }; this->SetBounds( bounds ); Point3D origin; originVector = geometry3D->GetIndexToWorldTransform() ->TransformVector( originVector ); origin = GetOrigin() + originVector; SetOrigin(origin); } void PlaneGeometry::InitializeStandardPlane( const Geometry3D *geometry3D, bool top, PlaneOrientation planeorientation, bool frontside, bool rotated ) { ScalarType zPosition; switch(planeorientation) { case Axial: zPosition = (top ? 0.5 : geometry3D->GetExtent(2)-1+0.5); break; case Frontal: zPosition = (top ? 0.5 : geometry3D->GetExtent(1)-1+0.5); break; case Sagittal: zPosition = (top ? 0.5 : geometry3D->GetExtent(0)-1+0.5); break; default: itkExceptionMacro("unknown PlaneOrientation"); } InitializeStandardPlane( geometry3D, planeorientation, zPosition, frontside, rotated ); } void PlaneGeometry::InitializeStandardPlane( const Vector3D &rightVector, const Vector3D &downVector, const Vector3D *spacing ) { InitializeStandardPlane( rightVector.GetVnlVector(), downVector.GetVnlVector(), spacing ); } void PlaneGeometry::InitializeStandardPlane( const VnlVector& rightVector, const VnlVector &downVector, const Vector3D *spacing ) { ScalarType width = rightVector.magnitude(); ScalarType height = downVector.magnitude(); InitializeStandardPlane( width, height, rightVector, downVector, spacing ); } void PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width, ScalarType height, const Vector3D &rightVector, const Vector3D &downVector, const Vector3D *spacing ) { InitializeStandardPlane( width, height, rightVector.GetVnlVector(), downVector.GetVnlVector(), spacing ); } void PlaneGeometry::InitializeStandardPlane( mitk::ScalarType width, ScalarType height, const VnlVector &rightVector, const VnlVector &downVector, const Vector3D *spacing ) { assert(width > 0); assert(height > 0); VnlVector rightDV = rightVector; rightDV.normalize(); VnlVector downDV = downVector; downDV.normalize(); VnlVector normal = vnl_cross_3d(rightVector, downVector); normal.normalize(); if(spacing!=NULL) { rightDV *= (*spacing)[0]; downDV *= (*spacing)[1]; normal *= (*spacing)[2]; } AffineTransform3D::Pointer transform = AffineTransform3D::New(); Matrix3D matrix; matrix.GetVnlMatrix().set_column(0, rightDV); matrix.GetVnlMatrix().set_column(1, downDV); matrix.GetVnlMatrix().set_column(2, normal); transform->SetMatrix(matrix); transform->SetOffset(m_IndexToWorldTransform->GetOffset()); ScalarType bounds[6] = { 0, width, 0, height, 0, 1 }; this->SetBounds( bounds ); this->SetIndexToWorldTransform( transform ); } void PlaneGeometry::InitializePlane( const Point3D &origin, const Vector3D &normal ) { VnlVector rightVectorVnl(3), downVectorVnl; if( Equal( normal[1], 0.0f ) == false ) { FillVector3D( rightVectorVnl, 1.0f, -normal[0]/normal[1], 0.0f ); rightVectorVnl.normalize(); } else { FillVector3D( rightVectorVnl, 0.0f, 1.0f, 0.0f ); } downVectorVnl = vnl_cross_3d( normal.GetVnlVector(), rightVectorVnl ); downVectorVnl.normalize(); InitializeStandardPlane( rightVectorVnl, downVectorVnl ); SetOrigin(origin); } void PlaneGeometry::SetMatrixByVectors( const VnlVector &rightVector, const VnlVector &downVector, ScalarType thickness ) { VnlVector normal = vnl_cross_3d(rightVector, downVector); normal.normalize(); normal *= thickness; AffineTransform3D::Pointer transform = AffineTransform3D::New(); Matrix3D matrix; matrix.GetVnlMatrix().set_column(0, rightVector); matrix.GetVnlMatrix().set_column(1, downVector); matrix.GetVnlMatrix().set_column(2, normal); transform->SetMatrix(matrix); transform->SetOffset(m_IndexToWorldTransform->GetOffset()); SetIndexToWorldTransform(transform); } Vector3D PlaneGeometry::GetNormal() const { Vector3D frontToBack; frontToBack.SetVnlVector( m_IndexToWorldTransform ->GetMatrix().GetVnlMatrix().get_column(2) ); return frontToBack; } VnlVector PlaneGeometry::GetNormalVnl() const { return m_IndexToWorldTransform ->GetMatrix().GetVnlMatrix().get_column(2); } ScalarType PlaneGeometry::DistanceFromPlane( const Point3D &pt3d_mm ) const { return fabs(SignedDistance( pt3d_mm )); } ScalarType PlaneGeometry::SignedDistance( const Point3D &pt3d_mm ) const { return SignedDistanceFromPlane(pt3d_mm); } bool PlaneGeometry::IsAbove( const Point3D &pt3d_mm ) const { return SignedDistanceFromPlane(pt3d_mm) > 0; } bool PlaneGeometry::IntersectionLine( const PlaneGeometry* plane, Line3D& crossline ) const { Vector3D normal = this->GetNormal(); normal.Normalize(); Vector3D planeNormal = plane->GetNormal(); planeNormal.Normalize(); Vector3D direction = itk::CrossProduct( normal, planeNormal ); if ( direction.GetSquaredNorm() < eps ) return false; crossline.SetDirection( direction ); double N1dN2 = normal * planeNormal; double determinant = 1.0 - N1dN2 * N1dN2; Vector3D origin = this->GetOrigin().GetVectorFromOrigin(); Vector3D planeOrigin = plane->GetOrigin().GetVectorFromOrigin(); double d1 = normal * origin; double d2 = planeNormal * planeOrigin; double c1 = ( d1 - d2 * N1dN2 ) / determinant; double c2 = ( d2 - d1 * N1dN2 ) / determinant; Vector3D p = normal * c1 + planeNormal * c2; crossline.GetPoint().GetVnlVector() = p.GetVnlVector(); return true; } unsigned int PlaneGeometry::IntersectWithPlane2D( const PlaneGeometry* plane, Point2D& lineFrom, Point2D &lineTo ) const { Line3D crossline; if ( this->IntersectionLine( plane, crossline ) == false ) return 0; Point2D point2; Vector2D direction2; this->Map( crossline.GetPoint(), point2 ); this->Map( crossline.GetPoint(), crossline.GetDirection(), direction2 ); return Line3D::RectangleLineIntersection( 0, 0, GetExtentInMM(0), GetExtentInMM(1), point2, direction2, lineFrom, lineTo ); } double PlaneGeometry::Angle( const PlaneGeometry *plane ) const { return angle(plane->GetMatrixColumn(2), GetMatrixColumn(2)); } double PlaneGeometry::Angle( const Line3D &line ) const { return vnl_math::pi_over_2 - angle( line.GetDirection().GetVnlVector(), GetMatrixColumn(2) ); } bool PlaneGeometry::IntersectionPoint( const Line3D &line, Point3D &intersectionPoint ) const { Vector3D planeNormal = this->GetNormal(); planeNormal.Normalize(); Vector3D lineDirection = line.GetDirection(); lineDirection.Normalize(); double t = planeNormal * lineDirection; if ( fabs( t ) < eps ) { return false; } Vector3D diff; diff = this->GetOrigin() - line.GetPoint(); t = ( planeNormal * diff ) / t; intersectionPoint = line.GetPoint() + lineDirection * t; return true; } bool PlaneGeometry::IntersectionPointParam( const Line3D &line, double &t ) const { Vector3D planeNormal = this->GetNormal(); Vector3D lineDirection = line.GetDirection(); t = planeNormal * lineDirection; if ( fabs( t ) < eps ) { return false; } Vector3D diff; diff = this->GetOrigin() - line.GetPoint(); t = ( planeNormal * diff ) / t; return true; } bool PlaneGeometry::IsParallel( const PlaneGeometry *plane ) const { return ( (Angle(plane) < 10.0 * mitk::sqrteps ) || ( Angle(plane) > ( vnl_math::pi - 10.0 * sqrteps ) ) ) ; } bool PlaneGeometry::IsOnPlane( const Point3D &point ) const { return Distance(point) < eps; } bool PlaneGeometry::IsOnPlane( const Line3D &line ) const { return ( (Distance( line.GetPoint() ) < eps) && (Distance( line.GetPoint2() ) < eps) ); } bool PlaneGeometry::IsOnPlane( const PlaneGeometry *plane ) const { return ( IsParallel( plane ) && (Distance( plane->GetOrigin() ) < eps) ); } Point3D PlaneGeometry::ProjectPointOntoPlane( const Point3D& pt ) const { ScalarType len = this->GetNormalVnl().two_norm(); return pt - this->GetNormal() * this->SignedDistanceFromPlane( pt ) / len; } itk::LightObject::Pointer PlaneGeometry::InternalClone() const { Self::Pointer newGeometry = new PlaneGeometry(*this); newGeometry->UnRegister(); return newGeometry.GetPointer(); } void PlaneGeometry::ExecuteOperation( Operation *operation ) { vtkTransform *transform = vtkTransform::New(); transform->SetMatrix( m_VtkMatrix ); switch ( operation->GetOperationType() ) { case OpORIENT: { mitk::PlaneOperation *planeOp = dynamic_cast< mitk::PlaneOperation * >( operation ); if ( planeOp == NULL ) { return; } Point3D center = planeOp->GetPoint(); Vector3D orientationVector = planeOp->GetNormal(); Vector3D defaultVector; FillVector3D( defaultVector, 0.0, 0.0, 1.0 ); Vector3D rotationAxis = itk::CrossProduct( orientationVector, defaultVector ); - //vtkFloatingPointType rotationAngle = acos( orientationVector[2] / orientationVector.GetNorm() ); + //double rotationAngle = acos( orientationVector[2] / orientationVector.GetNorm() ); - vtkFloatingPointType rotationAngle = atan2( (double) rotationAxis.GetNorm(), (double) (orientationVector * defaultVector) ); + double rotationAngle = atan2( (double) rotationAxis.GetNorm(), (double) (orientationVector * defaultVector) ); rotationAngle *= 180.0 / vnl_math::pi; transform->PostMultiply(); transform->Identity(); transform->Translate( center[0], center[1], center[2] ); transform->RotateWXYZ( rotationAngle, rotationAxis[0], rotationAxis[1], rotationAxis[2] ); transform->Translate( -center[0], -center[1], -center[2] ); break; } case OpRESTOREPLANEPOSITION: { RestorePlanePositionOperation *op = dynamic_cast< mitk::RestorePlanePositionOperation* >(operation); if(op == NULL) { return; } AffineTransform3D::Pointer transform2 = AffineTransform3D::New(); Matrix3D matrix; matrix.GetVnlMatrix().set_column(0, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(0)); matrix.GetVnlMatrix().set_column(1, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(1)); matrix.GetVnlMatrix().set_column(2, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(2)); transform2->SetMatrix(matrix); Vector3D offset = op->GetTransform()->GetOffset(); transform2->SetOffset(offset); this->SetIndexToWorldTransform(transform2); ScalarType bounds[6] = {0, op->GetWidth(), 0, op->GetHeight(), 0 ,1 }; this->SetBounds(bounds); TransferItkToVtkTransform(); this->Modified(); transform->Delete(); return; } default: Superclass::ExecuteOperation( operation ); transform->Delete(); return; } m_VtkMatrix->DeepCopy(transform->GetMatrix()); this->TransferVtkToItkTransform(); this->Modified(); transform->Delete(); } void PlaneGeometry::PrintSelf( std::ostream& os, itk::Indent indent ) const { Superclass::PrintSelf(os,indent); os << indent << " Normal: " << GetNormal() << std::endl; } } // namespace diff --git a/Core/Code/DataManagement/mitkSurface.cpp b/Core/Code/DataManagement/mitkSurface.cpp index ed93ff4ee2..f204f90d42 100644 --- a/Core/Code/DataManagement/mitkSurface.cpp +++ b/Core/Code/DataManagement/mitkSurface.cpp @@ -1,541 +1,541 @@ /*=================================================================== 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 "mitkSurface.h" #include "mitkInteractionConst.h" #include "mitkSurfaceOperation.h" #include #include #include static vtkPolyData* DeepCopy(vtkPolyData* other) { if (other == NULL) return NULL; vtkPolyData* copy = vtkPolyData::New(); copy->DeepCopy(other); return copy; } static void Delete(vtkPolyData* polyData) { if (polyData != NULL) polyData->Delete(); } static void Update(vtkPolyData* polyData) { if (polyData != NULL) polyData->Update(); } mitk::Surface::Surface() : m_CalculateBoundingBox(false) { this->InitializeEmpty(); } mitk::Surface::Surface(const mitk::Surface& other) : BaseData(other), m_LargestPossibleRegion(other.m_LargestPossibleRegion), m_RequestedRegion(other.m_RequestedRegion), m_CalculateBoundingBox(other.m_CalculateBoundingBox) { if(!other.m_PolyDatas.empty()) { m_PolyDatas.resize(other.m_PolyDatas.size()); std::transform(other.m_PolyDatas.begin(), other.m_PolyDatas.end(), m_PolyDatas.begin(), DeepCopy); } else { this->InitializeEmpty(); } } void mitk::Surface::Swap(mitk::Surface& other) { std::swap(m_PolyDatas, other.m_PolyDatas); std::swap(m_LargestPossibleRegion, other.m_LargestPossibleRegion); std::swap(m_RequestedRegion, other.m_RequestedRegion); std::swap(m_CalculateBoundingBox, other.m_CalculateBoundingBox); } mitk::Surface& mitk::Surface::operator=(Surface other) { this->Swap(other); return *this; } mitk::Surface::~Surface() { this->ClearData(); } void mitk::Surface::ClearData() { using ::Delete; std::for_each(m_PolyDatas.begin(), m_PolyDatas.end(), Delete); m_PolyDatas.clear(); Superclass::ClearData(); } const mitk::Surface::RegionType& mitk::Surface::GetLargestPossibleRegion() const { m_LargestPossibleRegion.SetIndex(3, 0); m_LargestPossibleRegion.SetSize(3, GetTimeGeometry()->CountTimeSteps()); return m_LargestPossibleRegion; } const mitk::Surface::RegionType& mitk::Surface::GetRequestedRegion() const { return m_RequestedRegion; } void mitk::Surface::InitializeEmpty() { if (!m_PolyDatas.empty()) this->ClearData(); Superclass::InitializeTimeGeometry(); m_PolyDatas.push_back(NULL); m_Initialized = true; } void mitk::Surface::SetVtkPolyData(vtkPolyData* polyData, unsigned int t) { this->Expand(t + 1); if (m_PolyDatas[t] != NULL) { if (m_PolyDatas[t] == polyData) return; m_PolyDatas[t]->Delete(); } m_PolyDatas[t] = polyData; if(polyData != NULL) polyData->Register(NULL); m_CalculateBoundingBox = true; this->Modified(); this->UpdateOutputInformation(); } bool mitk::Surface::IsEmptyTimeStep(unsigned int t) const { if(!IsInitialized()) return false; vtkPolyData* polyData = const_cast(this)->GetVtkPolyData(t); return polyData == NULL || ( polyData->GetNumberOfLines() == 0 && polyData->GetNumberOfPolys() == 0 && polyData->GetNumberOfStrips() == 0 && polyData->GetNumberOfVerts() == 0 ); } vtkPolyData* mitk::Surface::GetVtkPolyData(unsigned int t) { if (t < m_PolyDatas.size()) { if(m_PolyDatas[t] == NULL && this->GetSource().IsNotNull()) { RegionType requestedRegion; requestedRegion.SetIndex(3, t); requestedRegion.SetSize(3, 1); this->SetRequestedRegion(&requestedRegion); this->GetSource()->Update(); } return m_PolyDatas[t]; } return NULL; } void mitk::Surface::UpdateOutputInformation() { if (this->GetSource().IsNotNull()) this->GetSource()->UpdateOutputInformation(); if (m_CalculateBoundingBox == true && !m_PolyDatas.empty()) this->CalculateBoundingBox(); else this->GetTimeGeometry()->Update(); } void mitk::Surface::CalculateBoundingBox() { TimeGeometry* timeGeometry = this->GetTimeGeometry(); if (timeGeometry->CountTimeSteps() != m_PolyDatas.size()) mitkThrow() << "Number of geometry time steps is inconsistent with number of poly data pointers."; for (unsigned int i = 0; i < m_PolyDatas.size(); ++i) { vtkPolyData* polyData = m_PolyDatas[i]; - vtkFloatingPointType bounds[6] = {0}; + double bounds[6] = {0}; if (polyData != NULL && polyData->GetNumberOfPoints() > 0) { polyData->Update(); polyData->ComputeBounds(); polyData->GetBounds(bounds); } Geometry3D::Pointer geometry = timeGeometry->GetGeometryForTimeStep(i); if (geometry.IsNull()) mitkThrow() << "Time-sliced geometry is invalid (equals NULL)."; geometry->SetFloatBounds(bounds); } timeGeometry->Update(); m_CalculateBoundingBox = false; } void mitk::Surface::SetRequestedRegionToLargestPossibleRegion() { m_RequestedRegion = GetLargestPossibleRegion(); } bool mitk::Surface::RequestedRegionIsOutsideOfTheBufferedRegion() { RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3) + m_RequestedRegion.GetSize(3); if(static_cast(m_PolyDatas.size()) < end) return true; for(RegionType::IndexValueType t = m_RequestedRegion.GetIndex(3); t < end; ++t) { if(m_PolyDatas[t] == NULL) return true; } return false; } bool mitk::Surface::VerifyRequestedRegion() { if(m_RequestedRegion.GetIndex(3) >= 0 && m_RequestedRegion.GetIndex(3) + m_RequestedRegion.GetSize(3) <= m_PolyDatas.size()) return true; return false; } void mitk::Surface::SetRequestedRegion(const itk::DataObject* data ) { const mitk::Surface *surface = dynamic_cast(data); if (surface != NULL) m_RequestedRegion = surface->GetRequestedRegion(); else mitkThrow() << "Data object used to get requested region is not a mitk::Surface."; } void mitk::Surface::SetRequestedRegion(Surface::RegionType* region) { if (region == NULL) mitkThrow() << "Requested region is invalid (equals NULL)"; m_RequestedRegion = *region; } void mitk::Surface::CopyInformation(const itk::DataObject* data) { Superclass::CopyInformation(data); const mitk::Surface* surface = dynamic_cast(data); if (surface == NULL) mitkThrow() << "Data object used to get largest possible region is not a mitk::Surface."; m_LargestPossibleRegion = surface->GetLargestPossibleRegion(); } void mitk::Surface::Update() { using ::Update; if (this->GetSource().IsNull()) std::for_each(m_PolyDatas.begin(), m_PolyDatas.end(), Update); Superclass::Update(); } void mitk::Surface::Expand(unsigned int timeSteps) { if (timeSteps > m_PolyDatas.size()) { Superclass::Expand(timeSteps); m_PolyDatas.resize(timeSteps); m_CalculateBoundingBox = true; } } void mitk::Surface::ExecuteOperation(Operation* operation) { switch (operation->GetOperationType()) { case OpSURFACECHANGED: { mitk::SurfaceOperation* surfaceOperation = dynamic_cast(operation); if(surfaceOperation == NULL) break; unsigned int timeStep = surfaceOperation->GetTimeStep(); if(m_PolyDatas[timeStep] != NULL) { vtkPolyData* updatedPolyData = surfaceOperation->GetVtkPolyData(); if(updatedPolyData != NULL) { this->SetVtkPolyData(updatedPolyData, timeStep); this->CalculateBoundingBox(); this->Modified(); } } break; } default: return; } } unsigned int mitk::Surface::GetSizeOfPolyDataSeries() const { return m_PolyDatas.size(); } void mitk::Surface::Graft(const DataObject* data) { const Surface* surface = dynamic_cast(data); if(surface == NULL) mitkThrow() << "Data object used to graft surface is not a mitk::Surface."; this->CopyInformation(data); m_PolyDatas.clear(); for (unsigned int i = 0; i < surface->GetSizeOfPolyDataSeries(); ++i) { m_PolyDatas.push_back(vtkPolyData::New()); m_PolyDatas.back()->DeepCopy(const_cast(surface)->GetVtkPolyData(i)); } } void mitk::Surface::PrintSelf(std::ostream& os, itk::Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "\nNumber PolyDatas: " << m_PolyDatas.size() << "\n"; unsigned int count = 0; for (std::vector::const_iterator it = m_PolyDatas.begin(); it != m_PolyDatas.end(); ++it) { os << "\n"; if(*it != NULL) { os << indent << "PolyData at time step " << count << ":\n"; os << indent << "Number of cells: " << (*it)->GetNumberOfCells() << "\n"; os << indent << "Number of points: " << (*it)->GetNumberOfPoints() << "\n\n"; os << indent << "VTKPolyData:\n"; (*it)->Print(os); } else { os << indent << "Empty PolyData at time step " << count << "\n"; } ++count; } } bool mitk::Equal( vtkPolyData* leftHandSide, vtkPolyData* rightHandSide, mitk::ScalarType eps, bool verbose ) { bool noDifferenceFound = true; if( rightHandSide == NULL ) { if(verbose) { MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] rightHandSide NULL."; } return false; } if( leftHandSide == NULL ) { if(verbose) { MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] leftHandSide NULL."; } return false; } if( ! mitk::Equal( leftHandSide->GetNumberOfCells(), rightHandSide->GetNumberOfCells(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of cells not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide->GetNumberOfVerts(), rightHandSide->GetNumberOfVerts(), eps, verbose )) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of vertices not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide->GetNumberOfLines(), rightHandSide->GetNumberOfLines(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of lines not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide->GetNumberOfPolys(), rightHandSide->GetNumberOfPolys(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of polys not equal"; noDifferenceFound = false; } if( ! mitk::Equal( leftHandSide->GetNumberOfStrips(), rightHandSide->GetNumberOfStrips(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of strips not equal"; noDifferenceFound = false; } { unsigned int numberOfPointsRight = rightHandSide->GetPoints()->GetNumberOfPoints(); unsigned int numberOfPointsLeft = leftHandSide->GetPoints()->GetNumberOfPoints(); if(! mitk::Equal( numberOfPointsLeft, numberOfPointsRight, eps, verbose )) { if(verbose) MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Number of points not equal"; noDifferenceFound = false; } else { for( unsigned int i( 0 ); i < numberOfPointsRight; i++ ) { bool pointFound = false; double pointOne[3]; rightHandSide->GetPoints()->GetPoint(i, pointOne); for( unsigned int j( 0 ); j < numberOfPointsLeft; j++ ) { double pointTwo[3]; leftHandSide->GetPoints()->GetPoint(j, pointTwo); double x = pointOne[0] - pointTwo[0]; double y = pointOne[1] - pointTwo[1]; double z = pointOne[2] - pointTwo[2]; double distance = x*x + y*y + z*z; if( distance < eps ) { pointFound = true; break; } } if( !pointFound ) { if(verbose) { MITK_INFO << "[Equal( vtkPolyData*, vtkPolyData* )] Right hand side point with id " << i << " and coordinates ( " << std::setprecision(12) << pointOne[0] << " ; " << pointOne[1] << " ; " << pointOne[2] << " ) could not be found in left hand side with epsilon " << eps << "."; } noDifferenceFound = false; break; } } } } return noDifferenceFound; } bool mitk::Equal( mitk::Surface* leftHandSide, mitk::Surface* rightHandSide, mitk::ScalarType eps, bool verbose ) { bool noDifferenceFound = true; if( rightHandSide == NULL ) { if(verbose) MITK_INFO << "[Equal( mitk::surface*, mitk::surface* )] rightHandSide NULL."; return false; } if( leftHandSide == NULL ) { if(verbose) MITK_INFO << "[Equal( mitk::surface*, mitk::surface* )] leftHandSide NULL."; return false; } if( ! mitk::Equal( leftHandSide->GetSizeOfPolyDataSeries(), rightHandSide->GetSizeOfPolyDataSeries(), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( mitk::surface*, mitk::surface* )] Size of PolyData series not equal."; noDifferenceFound = false; } // No mitk::Equal for TimeGeometry implemented. //if( ! mitk::Equal( leftHandSide->GetTimeGeometry(), rightHandSide->GetTimeGeometry(), eps, verbose ) ) //{ // if(verbose) // MITK_INFO << "[Equal( mitk::surface*, mitk::surface* )] Time sliced geometries not equal"; // noDifferenceFound = false; //} for( unsigned int i( 0 ); i < rightHandSide->GetSizeOfPolyDataSeries(); i++ ) { if( ! mitk::Equal( leftHandSide->GetVtkPolyData( i ), rightHandSide->GetVtkPolyData( i ), eps, verbose ) ) { if(verbose) MITK_INFO << "[Equal( mitk::surface*, mitk::surface* )] Poly datas not equal."; noDifferenceFound = false; } } return noDifferenceFound; } \ No newline at end of file diff --git a/Core/Code/DataManagement/mitkTransferFunction.cpp b/Core/Code/DataManagement/mitkTransferFunction.cpp index 9c0ae8f9a9..e7afe33229 100644 --- a/Core/Code/DataManagement/mitkTransferFunction.cpp +++ b/Core/Code/DataManagement/mitkTransferFunction.cpp @@ -1,332 +1,332 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTransferFunction.h" #include "mitkImageToItk.h" #include "mitkHistogramGenerator.h" #include #include namespace mitk { TransferFunction::TransferFunction() { m_ScalarOpacityFunction = vtkSmartPointer::New(); m_ColorTransferFunction = vtkSmartPointer::New(); m_GradientOpacityFunction = vtkSmartPointer::New(); m_ScalarOpacityFunction->Initialize(); m_ScalarOpacityFunction->AddPoint(0,1); m_GradientOpacityFunction->Initialize(); m_GradientOpacityFunction->AddPoint(0,1); m_ColorTransferFunction->RemoveAllPoints(); m_ColorTransferFunction->SetColorSpaceToHSV(); m_ColorTransferFunction->AddRGBPoint(0,1,1,1); } TransferFunction::TransferFunction(const TransferFunction& other) : itk::Object() , m_ScalarOpacityFunction(other.m_ScalarOpacityFunction.New()) , m_GradientOpacityFunction(other.m_GradientOpacityFunction.New()) , m_ColorTransferFunction(other.m_ColorTransferFunction.New()) , m_Min(other.m_Min) , m_Max(other.m_Max) , m_Histogram(other.m_Histogram) , m_ScalarOpacityPoints(other.m_ScalarOpacityPoints) , m_GradientOpacityPoints(other.m_GradientOpacityPoints) , m_RGBPoints(other.m_RGBPoints) { m_ScalarOpacityFunction->DeepCopy(other.m_ScalarOpacityFunction); m_GradientOpacityFunction->DeepCopy(other.m_GradientOpacityFunction); m_ColorTransferFunction->DeepCopy(other.m_ColorTransferFunction); } TransferFunction::~TransferFunction() { } bool TransferFunction::operator==(Self& other) { if ((m_Min != other.m_Min) || (m_Max != other.m_Max)) return false; bool sizes = (m_ScalarOpacityFunction->GetSize() == other.m_ScalarOpacityFunction->GetSize()) && (m_GradientOpacityFunction->GetSize() == other.m_GradientOpacityFunction->GetSize()) && (m_ColorTransferFunction->GetSize() == other.m_ColorTransferFunction->GetSize()); if (sizes == false) return false; for (int i = 0; i < m_ScalarOpacityFunction->GetSize(); i++ ) { double myVal[4]; double otherVal[4]; m_ScalarOpacityFunction->GetNodeValue(i, myVal); other.m_ScalarOpacityFunction->GetNodeValue(i, otherVal); bool equal = (myVal[0] == otherVal[0]) && (myVal[1] == otherVal[1]) && (myVal[2] == otherVal[2]) && (myVal[3] == otherVal[3]); if (equal == false) return false; } for (int i = 0; i < m_GradientOpacityFunction->GetSize(); i++ ) { double myVal[4]; double otherVal[4]; m_GradientOpacityFunction->GetNodeValue(i, myVal); other.m_GradientOpacityFunction->GetNodeValue(i, otherVal); bool equal = (myVal[0] == otherVal[0]) && (myVal[1] == otherVal[1]) && (myVal[2] == otherVal[2]) && (myVal[3] == otherVal[3]); if (equal == false) return false; } for (int i = 0; i < m_ColorTransferFunction->GetSize(); i++ ) { double myVal[6]; double otherVal[6]; m_ColorTransferFunction->GetNodeValue(i, myVal); other.m_ColorTransferFunction->GetNodeValue(i, otherVal); bool equal = (myVal[0] == otherVal[0]) // X && (myVal[1] == otherVal[1]) // R && (myVal[2] == otherVal[2]) // G && (myVal[3] == otherVal[3]) // B && (myVal[4] == otherVal[4]) // midpoint && (myVal[5] == otherVal[5]); // sharpness if (equal == false) return false; } return true; } void TransferFunction::SetScalarOpacityPoints(TransferFunction::ControlPoints points) { m_ScalarOpacityFunction->RemoveAllPoints(); for(unsigned int i=0; i<=points.size()-1;i++) { this->AddScalarOpacityPoint(points[i].first, points[i].second); } } void TransferFunction::SetGradientOpacityPoints(TransferFunction::ControlPoints points) { m_GradientOpacityFunction->RemoveAllPoints(); for(unsigned int i=0; i<=points.size()-1;i++) { this->AddGradientOpacityPoint(points[i].first, points[i].second); } } void TransferFunction::SetRGBPoints(TransferFunction::RGBControlPoints rgbpoints) { m_ColorTransferFunction->RemoveAllPoints(); for(unsigned int i=0; i<=rgbpoints.size()-1;i++) { this->AddRGBPoint(rgbpoints[i].first, rgbpoints[i].second[0], rgbpoints[i].second[1], rgbpoints[i].second[2]); } } void TransferFunction::AddScalarOpacityPoint(double x, double value) { m_ScalarOpacityFunction->AddPoint(x, value); } void TransferFunction::AddGradientOpacityPoint(double x, double value) { m_GradientOpacityFunction->AddPoint(x, value); } void TransferFunction::AddRGBPoint(double x, double r, double g, double b) { m_ColorTransferFunction->AddRGBPoint(x, r, g, b); } TransferFunction::ControlPoints &TransferFunction::GetScalarOpacityPoints() { // Retrieve data points from VTK transfer function and store them in a vector m_ScalarOpacityPoints.clear(); - vtkFloatingPointType *data = m_ScalarOpacityFunction->GetDataPointer(); + double *data = m_ScalarOpacityFunction->GetDataPointer(); for ( int i = 0; i < m_ScalarOpacityFunction->GetSize(); ++i ) { m_ScalarOpacityPoints.push_back( std::make_pair( data[i*2], data[i*2+1] )); } return m_ScalarOpacityPoints; } TransferFunction::ControlPoints &TransferFunction::GetGradientOpacityPoints() { // Retrieve data points from VTK transfer function and store them in a vector m_GradientOpacityPoints.clear(); - vtkFloatingPointType *data = m_GradientOpacityFunction->GetDataPointer(); + double *data = m_GradientOpacityFunction->GetDataPointer(); for ( int i = 0; i < m_GradientOpacityFunction->GetSize(); ++i ) { m_GradientOpacityPoints.push_back( std::make_pair( data[i*2], data[i*2+1] )); } return m_GradientOpacityPoints; } TransferFunction::RGBControlPoints &TransferFunction::GetRGBPoints() { // Retrieve data points from VTK transfer function and store them in a vector m_RGBPoints.clear(); - vtkFloatingPointType *data = m_ColorTransferFunction->GetDataPointer(); + double *data = m_ColorTransferFunction->GetDataPointer(); for ( int i = 0; i < m_ColorTransferFunction->GetSize(); ++i ) { double rgb[] = { data[i*4+1], data[i*4+2], data[i*4+3] }; m_RGBPoints.push_back( std::make_pair( data[i*4], rgb )); } return m_RGBPoints; } int TransferFunction::RemoveScalarOpacityPoint(double x) { return m_ScalarOpacityFunction->RemovePoint(x); } int TransferFunction::RemoveGradientOpacityPoint(double x) { return m_GradientOpacityFunction->RemovePoint(x); } int TransferFunction::RemoveRGBPoint(double x) { return m_ColorTransferFunction->RemovePoint(x); } void TransferFunction::ClearScalarOpacityPoints() { m_ScalarOpacityFunction->RemoveAllPoints(); } void TransferFunction::ClearGradientOpacityPoints() { m_GradientOpacityFunction->RemoveAllPoints(); } void TransferFunction::ClearRGBPoints() { m_ColorTransferFunction->RemoveAllPoints(); } void TransferFunction::InitializeByItkHistogram( const itk::Statistics::Histogram* histogram) { m_Histogram = histogram; m_Min = (int)GetHistogram()->GetBinMin(0,0); m_Max = (int)GetHistogram()->GetBinMax(0, GetHistogram()->Size()-1); /* m_ScalarOpacityFunction->Initialize(); m_ScalarOpacityFunction->AddPoint(m_Min,0.0); m_ScalarOpacityFunction->AddPoint(0.0,0.0); m_ScalarOpacityFunction->AddPoint(m_Max,1.0); m_GradientOpacityFunction->Initialize(); m_GradientOpacityFunction->AddPoint(m_Min,0.0); m_GradientOpacityFunction->AddPoint(0.0,1.0); m_GradientOpacityFunction->AddPoint((m_Max*0.125),1.0); m_GradientOpacityFunction->AddPoint((m_Max*0.2),1.0); m_GradientOpacityFunction->AddPoint((m_Max*0.25),1.0); m_GradientOpacityFunction->AddPoint(m_Max,1.0); m_ColorTransferFunction->RemoveAllPoints(); m_ColorTransferFunction->AddRGBPoint(m_Min,1,0,0); m_ColorTransferFunction->AddRGBPoint(m_Max,1,1,0); m_ColorTransferFunction->SetColorSpaceToHSV(); MITK_INFO << "min/max in tf-c'tor:" << m_Min << "/" << m_Max << std::endl; */ } void TransferFunction::InitializeByMitkImage( const Image * image ) { HistogramGenerator::Pointer histGen= HistogramGenerator::New(); histGen->SetImage(image); histGen->SetSize(256); histGen->ComputeHistogram(); m_Histogram = histGen->GetHistogram(); m_Min = (int)GetHistogram()->GetBinMin(0,0); m_Max = (int)GetHistogram()->GetBinMax(0, GetHistogram()->Size()-1); m_ScalarOpacityFunction->Initialize(); m_ScalarOpacityFunction->AddPoint(m_Min,0.0); m_ScalarOpacityFunction->AddPoint(0.0,0.0); m_ScalarOpacityFunction->AddPoint(m_Max,1.0); m_GradientOpacityFunction->Initialize(); m_GradientOpacityFunction->AddPoint(m_Min,0.0); m_GradientOpacityFunction->AddPoint(0.0,1.0); m_GradientOpacityFunction->AddPoint((m_Max*0.125),1.0); m_GradientOpacityFunction->AddPoint((m_Max*0.2),1.0); m_GradientOpacityFunction->AddPoint((m_Max*0.25),1.0); m_GradientOpacityFunction->AddPoint(m_Max,1.0); m_ColorTransferFunction->RemoveAllPoints(); m_ColorTransferFunction->AddRGBPoint(m_Min,1,0,0); m_ColorTransferFunction->AddRGBPoint(m_Max,1,1,0); m_ColorTransferFunction->SetColorSpaceToHSV(); //MITK_INFO << "min/max in tf-c'tor:" << m_Min << "/" << m_Max << std::endl; } void TransferFunction::InitializeHistogram( const Image * image ) { HistogramGenerator::Pointer histGen= HistogramGenerator::New(); histGen->SetImage(image); histGen->SetSize(256); histGen->ComputeHistogram(); m_Histogram = histGen->GetHistogram(); m_Min = (int)GetHistogram()->GetBinMin(0,0); m_Max = (int)GetHistogram()->GetBinMax(0, GetHistogram()->Size()-1); } void TransferFunction::PrintSelf(std::ostream &os, itk::Indent indent) const { os << indent << "ScalarOpacity: "; m_ScalarOpacityFunction->PrintHeader(os, vtkIndent()); os << indent << "GradientOpacity: "; m_GradientOpacityFunction->PrintHeader(os, vtkIndent()); os << indent << "ColorTransfer: "; m_ColorTransferFunction->PrintHeader(os, vtkIndent()); os << indent << "Min: " << m_Min << ", Max: " << m_Max << std::endl; } itk::LightObject::Pointer mitk::TransferFunction::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); return result; } }// namespace diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp index 7479a9b534..484137f4d3 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp @@ -1,1099 +1,1099 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //MITK #include #include #include #include #include #include #include #include #include #include #include //#include #include #include "mitkImageStatisticsHolder.h" #include "mitkPlaneClipping.h" //MITK Rendering #include "mitkImageVtkMapper2D.h" #include "vtkMitkThickSlicesFilter.h" #include "vtkMitkLevelWindowFilter.h" #include "vtkNeverTranslucentTexture.h" //VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //ITK #include #include mitk::ImageVtkMapper2D::ImageVtkMapper2D() { } mitk::ImageVtkMapper2D::~ImageVtkMapper2D() { //The 3D RW Mapper (Geometry2DDataVtkMapper3D) is listening to this event, //in order to delete the images from the 3D RW. this->InvokeEvent( itk::DeleteEvent() ); } //set the two points defining the textured plane according to the dimension and spacing -void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]) +void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float depth = this->CalculateLayerDepth(renderer); //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct //plane size in crosshair rotation and swivel mode. localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); //These two points define the axes of the plane in combination with the origin. //Point 1 is the x-axis and point 2 the y-axis. //Each plane is transformed according to the view (axial, coronal and saggital) afterwards. localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth) localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) } float mitk::ImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) { //get the clipping range to check how deep into z direction we can render images double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined float depth = -maxRange*0.01; // divide by 100 int layer = 0; GetDataNode()->GetIntProperty( "layer", layer, renderer); //add the layer property for each image to render images with a higher layer on top of the others depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) if(depth > 0.0f) { depth = 0.0f; MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; } return depth; } const mitk::Image* mitk::ImageVtkMapper2D::GetInput( void ) { return static_cast< const mitk::Image * >( GetDataNode()->GetData() ); } vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actors; } void mitk::ImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); mitk::DataNode* datanode = this->GetDataNode(); if ( input == NULL || input->IsInitialized() == false ) { return; } //check if there is a valid worldGeometry const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) { return; } input->Update(); // early out if there is no intersection of the current rendering geometry // and the geometry of the image that is to be rendered. if ( !RenderingGeometryIntersectsImage( worldGeometry, input->GetSlicedGeometry() ) ) { // set image to NULL, to clear the texture in 3D, because // the latest image is used there if the plane is out of the geometry // see bug-13275 localStorage->m_ReslicedImage = NULL; localStorage->m_Mapper->SetInput( localStorage->m_EmptyPolyData ); return; } //set main input for ExtractSliceFilter localStorage->m_Reslicer->SetInput(input); localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); //set the transformation of the image to adapt reslice axis localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) ); //is the geometry of the slice based on the input image or the worldgeometry? bool inPlaneResampleExtentByGeometry = false; datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry); // Initialize the interpolation mode for resampling; switch to nearest // neighbor if the input image is too small. if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) { VtkResliceInterpolationProperty *resliceInterpolationProperty; datanode->GetProperty( resliceInterpolationProperty, "reslice interpolation" ); int interpolationMode = VTK_RESLICE_NEAREST; if ( resliceInterpolationProperty != NULL ) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } switch ( interpolationMode ) { case VTK_RESLICE_NEAREST: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); break; case VTK_RESLICE_LINEAR: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); break; case VTK_RESLICE_CUBIC: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); break; } } else { localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); } //set the vtk output property to true, makes sure that no unneeded mitk image convertion //is done. localStorage->m_Reslicer->SetVtkOutputRequest(true); //Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; // Thick slices parameters if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed { DataNode *dn=renderer->GetCurrentWorldGeometry2DNode(); if(dn) { ResliceMethodProperty *resliceMethodEnumProperty=0; if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); IntProperty *intProperty=0; if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) { thickSlicesNum = intProperty->GetValue(); if(thickSlicesNum < 1) thickSlicesNum=1; if(thickSlicesNum > 10) thickSlicesNum=10; } } else { MITK_WARN << "no associated widget plane data tree node found"; } } const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); if(thickSlicesMode > 0) { double dataZSpacing = 1.0; Vector3D normInIndex, normal; if ( planeGeometry != NULL ){ normal = planeGeometry->GetNormal(); }else{ const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); if(abstractGeometry != NULL) normal = abstractGeometry->GetPlane()->GetNormal(); else return; //no fitting geometry set } normal.Normalize(); input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); dataZSpacing = 1.0 / normInIndex.GetNorm(); localStorage->m_Reslicer->SetOutputDimensionality( 3 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); localStorage->m_TSFilter->SetInput( localStorage->m_Reslicer->GetVtkOutput() ); //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually localStorage->m_Reslicer->Modified(); localStorage->m_Reslicer->Update(); localStorage->m_TSFilter->Modified(); localStorage->m_TSFilter->Update(); localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput(); } else { //this is needed when thick mode was enable bevore. These variable have to be reset to default values localStorage->m_Reslicer->SetOutputDimensionality( 2 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0); localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 ); localStorage->m_Reslicer->Modified(); //start the pipeline with updating the largest possible, needed if the geometry of the input has changed localStorage->m_Reslicer->UpdateLargestPossibleRegion(); localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput(); } // Bounds information for reslicing (only reuqired if reference geometry // is present) //this used for generating a vtkPLaneSource with the right size - vtkFloatingPointType sliceBounds[6]; + double sliceBounds[6]; for ( int i = 0; i < 6; ++i ) { sliceBounds[i] = 0.0; } localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); //get the spacing of the slice localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); // calculate minimum bounding rect of IMAGE in texture { - vtkFloatingPointType textureClippingBounds[6]; + double textureClippingBounds[6]; for ( int i = 0; i < 6; ++i ) { textureClippingBounds[i] = 0.0; } // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. mitk::PlaneClipping::CalculateClippedPlaneBounds( input->GetGeometry(), planeGeometry, textureClippingBounds ); textureClippingBounds[0] = static_cast< int >( textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[1] = static_cast< int >( textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[2] = static_cast< int >( textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 ); textureClippingBounds[3] = static_cast< int >( textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 ); //clipping bounds for cutting the image localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds); } //get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); //get the binary property bool binary = false; bool binaryOutline = false; datanode->GetBoolProperty( "binary", binary, renderer ); if(binary) //binary image { datanode->GetBoolProperty( "outline binary", binaryOutline, renderer ); if(binaryOutline) //contour rendering { if ( input->GetPixelType().GetBpe() <= 8 ) { //generate contours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) ) { if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { float binaryOutlineShadowWidth(1.5); datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer ); dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) ->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth ); } localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth ); } } else { binaryOutline = false; this->ApplyLookuptable(renderer); MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!"; } } else //standard binary image { if(numberOfComponents != 1) { MITK_ERROR << "Rendering Error: Binary Images with more then 1 component are not supported!"; } } } this->ApplyOpacity( renderer ); this->ApplyRenderingMode(renderer); // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); int displayedComponent = 0; if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1) { localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent); localStorage->m_VectorComponentExtractor->SetInput(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0)); } else { //connect the input with the levelwindow filter localStorage->m_LevelWindowFilter->SetInput(localStorage->m_ReslicedImage); } // check for texture interpolation property bool textureInterpolation = false; GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); //set the interpolation modus according to the property localStorage->m_Texture->SetInterpolate(textureInterpolation); // connect the texture with the output of the levelwindow filter localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); this->TransformActor( renderer ); vtkActor* contourShadowActor = dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0)); if(binary && binaryOutline) //connect the mapper with the polyData which contains the lines { //We need the contour for the binary outline property as actor localStorage->m_Mapper->SetInput(localStorage->m_OutlinePolyData); localStorage->m_Actor->SetTexture(NULL); //no texture for contours bool binaryOutlineShadow( false ); datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer ); if ( binaryOutlineShadow ) contourShadowActor->SetVisibility( true ); else contourShadowActor->SetVisibility( false ); } else { //Connect the mapper with the input texture. This is the standard case. //setup the textured plane this->GeneratePlane( renderer, sliceBounds ); //set the plane as input for the mapper localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); //set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); contourShadowActor->SetVisibility( false ); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::ApplyLevelWindow(mitk::BaseRenderer *renderer) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); LevelWindow levelWindow; this->GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" ); localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); mitk::LevelWindow opacLevelWindow; if( this->GetDataNode()->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) { //pass the opaque level window to the filter localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); } else { //no opaque level window localStorage->m_LevelWindowFilter->SetMinOpacity(0.0); localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0); } } void mitk::ImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); float rgb[3]= { 1.0f, 1.0f, 1.0f }; // check for color prop and use it for rendering if it exists // binary image hovering & binary image selection bool hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); if(hover && !selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.hoveringcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetDataNode()->GetColor( rgb, renderer, "color" ); } } if(selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.selectedcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { GetDataNode()->GetColor(rgb, renderer, "color"); } } if(!hover && !selected) { GetDataNode()->GetColor( rgb, renderer, "color" ); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); localStorage->m_Actor->GetProperty()->SetColor(rgbConv); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { float rgb[3]= { 1.0f, 1.0f, 1.0f }; mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("outline binary shadow color", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetColor(rgbConv); } } void mitk::ImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = this->GetLocalStorage( renderer ); float opacity = 1.0f; // check for opacity prop and use it for rendering if it exists GetDataNode()->GetOpacity( opacity, renderer, "opacity" ); //set the opacity according to the properties localStorage->m_Actor->GetProperty()->SetOpacity(opacity); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity); } } void mitk::ImageVtkMapper2D::ApplyRenderingMode( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); bool binary = false; this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); if(binary) // is it a binary image? { //for binary images, we always use our default LuT and map every value to (0,1) //the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window. localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_BinaryLookupTable); } else { //all other image types can make use of the rendering mode int renderingMode = mitk::RenderingModeProperty::LEVELWINDOW_COLOR; mitk::RenderingModeProperty::Pointer mode = dynamic_cast(this->GetDataNode()->GetProperty( "Image Rendering.Mode", renderer )); if(mode.IsNotNull()) { renderingMode = mode->GetRenderingMode(); } switch(renderingMode) { case mitk::RenderingModeProperty::LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_Color"; localStorage->m_LevelWindowFilter->SetLookupTable( localStorage->m_DefaultLookupTable ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color"; this->ApplyLookuptable( renderer ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color"; this->ApplyColorTransferFunction( renderer ); this->ApplyLevelWindow( renderer ); break; case mitk::RenderingModeProperty::LOOKUPTABLE_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color"; this->ApplyLookuptable( renderer ); break; case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR: MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color"; this->ApplyColorTransferFunction( renderer ); break; default: MITK_ERROR << "No valid 'Image Rendering.Mode' set"; break; } } //we apply color for all images (including binaries). this->ApplyColor( renderer ); } void mitk::ImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable; // If lookup table or transferfunction use is requested... mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); if( lookupTableProp.IsNotNull() ) // is a lookuptable set? { usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else { //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'. //A default (rainbow) lookup table will be used. //Here have to do nothing. Warning for the user has been removed, due to unwanted console output //in every interation of the rendering. } localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable); } void mitk::ImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer *renderer) { mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); if( transferFunctionProp.IsNull() ) { MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image Rendering.Transfer Function'. Nothing will be done."; return; } LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); //pass the transfer function to our level window filter localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction()); } void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) { return; } mitk::Image* data = const_cast( this->GetInput() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->CountTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::Image::Pointer image = dynamic_cast(node->GetData()); // Properties common for both images and segmentations node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "outline binary shadow", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline binary shadow color", ColorProperty::New(0.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "outline shadow width", mitk::FloatProperty::New( 1.5 ), renderer, overwrite ); if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); mitk::RenderingModeProperty::Pointer renderingModeProperty = mitk::RenderingModeProperty::New(); node->AddProperty( "Image Rendering.Mode", renderingModeProperty); std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) ) { // modality provided by DICOM or other reader if ( photometricInterpretation.find("MONOCHROME1") != std::string::npos ) // meaning: display MINIMUM pixels as WHITE { // generate LUT (white to black) mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); vtkLookupTable* bwLut = mitkLut->GetVtkLookupTable(); bwLut->SetTableRange (0, 1); bwLut->SetSaturationRange (0, 0); bwLut->SetHueRange (0, 0); bwLut->SetValueRange (1, 0); bwLut->SetAlphaRange (1, 1); bwLut->SetRampToLinear(); bwLut->Build(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty( "LookupTable", mitkLutProp ); } else if ( photometricInterpretation.find("MONOCHROME2") != std::string::npos ) // meaning: display MINIMUM pixels as BLACK { // apply default LUT (black to white) node->SetProperty( "color", mitk::ColorProperty::New( 1,1,1 ), renderer ); } // PALETTE interpretation should be handled ok by RGB loading } bool isBinaryImage(false); if ( ! node->GetBoolProperty("binary", isBinaryImage) ) { // ok, property is not set, use heuristic to determine if this // is a binary image mitk::Image::Pointer centralSliceImage; ScalarType minValue = 0.0; ScalarType maxValue = 0.0; ScalarType min2ndValue = 0.0; ScalarType max2ndValue = 0.0; mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); sliceSelector->SetInput(image); sliceSelector->SetSliceNr(image->GetDimension(2)/2); sliceSelector->SetTimeNr(image->GetDimension(3)/2); sliceSelector->SetChannelNr(image->GetDimension(4)/2); sliceSelector->Update(); centralSliceImage = sliceSelector->GetOutput(); if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) { minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin(); max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax(); } if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue) { // centralSlice is strange, lets look at all data minValue = image->GetStatistics()->GetScalarValueMin(); maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); } // some more properties specific for a binary... if (isBinaryImage) { node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); } else //...or image type object { node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); std::string className = image->GetNameOfClass(); if (className != "TensorImage" && className != "QBallImage") { PixelType pixelType = image->GetPixelType(); size_t numComponents = pixelType.GetNumberOfComponents(); if ((pixelType.GetPixelTypeAsString() == "vector" && numComponents > 1) || numComponents == 2 || numComponents > 4) node->AddProperty("Image.Displayed Component", mitk::IntProperty::New(0), renderer, overwrite); } } if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; if ( image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowCenter", sLevel ) && image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowWidth", sWindow ) ) { float level = atof( sLevel.c_str() ); float window = atof( sWindow.c_str() ); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; if ( image->GetPropertyList()->GetStringProperty( "dicom.series.SmallestPixelValueInSeries", sSmallestPixelValueInSeries ) && image->GetPropertyList()->GetStringProperty( "dicom.series.LargestPixelValueInSeries", sLargestPixelValueInSeries ) ) { float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? // might remedy some l/w widget challenges } else { contrast.SetAuto( static_cast(node->GetData()), false, true ); // we need this as a fallback } contrast.SetLevelWindow( level, window, true ); node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer ); } } if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) && (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA) && (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR) ) { mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->SetProperty( "opaclevelwindow", prop, renderer ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } mitk::ImageVtkMapper2D::LocalStorage* mitk::ImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } vtkSmartPointer mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ){ LocalStorage* localStorage = this->GetLocalStorage(renderer); //get the min and max index values of each direction int* extent = localStorage->m_ReslicedImage->GetExtent(); int xMin = extent[0]; int xMax = extent[1]; int yMin = extent[2]; int yMax = extent[3]; int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image int line = dims[0]; //how many pixels per line? int x = xMin; //pixel index x int y = yMin; //pixel index y char* currentPixel; //get the depth for each contour float depth = CalculateLayerDepth(renderer); vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points // We take the pointer to the first pixel of the image currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer() ); while (y <= yMax) { //if the current pixel value is set to something if ((currentPixel) && (*currentPixel != 0)) { //check in which direction a line is necessary //a line is added if the neighbor of the current pixel has the value 0 //and if the pixel is located at the edge of the image //if vvvvv not the first line vvvvv if (y > yMin && *(currentPixel-line) == 0) { //x direction - bottom edge of the pixel //add the 2 points vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); //add the line between both points lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the last line vvvvv if (y < yMax && *(currentPixel+line) == 0) { //x direction - top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the first pixel vvvvv if ( (x > xMin || y > yMin) && *(currentPixel-1) == 0) { //y direction - left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the last pixel vvvvv if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) == 0) { //y direction - right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } /* now consider pixels at the edge of the image */ //if vvvvv left edge of image vvvvv if (x == xMin) { //draw left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv right edge of image vvvvv if (x == xMax) { //draw right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv bottom edge of image vvvvv if (y == yMin) { //draw bottom edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv top edge of image vvvvv if (y == yMax) { //draw top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } }//end if currentpixel is set x++; if (x > xMax) { //reached end of line x = xMin; y++; } // Increase the pointer-position to the next pixel. // This is safe, as the while-loop and the x-reset logic above makes // sure we do not exceed the bounds of the image currentPixel++; }//end of while // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); return polyData; } void mitk::ImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); trans->SetMatrix(matrix); //transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital) localStorage->m_Actor->SetUserTransform(trans); //transform the origin to center based coordinates, because MITK is center based. localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { vtkActor* secondaryActor = dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) ); secondaryActor->SetUserTransform(trans); secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); } } bool mitk::ImageVtkMapper2D::RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry ) { // if either one of the two geometries is NULL we return true // for safety reasons if ( renderingGeometry == NULL || imageGeometry == NULL ) return true; // get the distance for the first cornerpoint ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) ); for( int i=1; i<8; i++ ) { mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i ); // get the distance to the other cornerpoints ScalarType distance = renderingGeometry->SignedDistance( cornerPoint ); // if it has not the same signing as the distance of the first point if ( initialDistance * distance < 0 ) { // we have an intersection and return true return true; } } // all distances have the same sign, no intersection and we return false return false; } mitk::ImageVtkMapper2D::LocalStorage::~LocalStorage() { } mitk::ImageVtkMapper2D::LocalStorage::LocalStorage() : m_VectorComponentExtractor(vtkSmartPointer::New()) { m_LevelWindowFilter = vtkSmartPointer::New(); //Do as much actions as possible in here to avoid double executions. m_Plane = vtkSmartPointer::New(); m_Texture = vtkSmartPointer::New().GetPointer(); m_DefaultLookupTable = vtkSmartPointer::New(); m_BinaryLookupTable = vtkSmartPointer::New(); m_ColorLookupTable = vtkSmartPointer::New(); m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_Actors = vtkSmartPointer::New(); m_Reslicer = mitk::ExtractSliceFilter::New(); m_TSFilter = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_ReslicedImage = vtkSmartPointer::New(); m_EmptyPolyData = vtkSmartPointer::New(); //the following actions are always the same and thus can be performed //in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); //built a default lookuptable m_DefaultLookupTable->SetRampToLinear(); m_DefaultLookupTable->SetSaturationRange( 0.0, 0.0 ); m_DefaultLookupTable->SetHueRange( 0.0, 0.0 ); m_DefaultLookupTable->SetValueRange( 0.0, 1.0 ); m_DefaultLookupTable->Build(); m_BinaryLookupTable->SetRampToLinear(); m_BinaryLookupTable->SetSaturationRange( 0.0, 0.0 ); m_BinaryLookupTable->SetHueRange( 0.0, 0.0 ); m_BinaryLookupTable->SetValueRange( 0.0, 1.0 ); m_BinaryLookupTable->SetRange(0.0, 1.0); m_BinaryLookupTable->Build(); // add a default rainbow lookup table for color mapping m_ColorLookupTable->SetRampToLinear(); m_ColorLookupTable->SetHueRange(0.6667, 0.0); m_ColorLookupTable->SetTableRange(0.0, 20.0); m_ColorLookupTable->Build(); // make first value transparent { double rgba[4]; m_BinaryLookupTable->GetTableValue(0, rgba); m_BinaryLookupTable->SetTableValue(0, rgba[0], rgba[1], rgba[2], 0.0); // background to 0 } //do not repeat the texture (the image) m_Texture->RepeatOff(); //set the mapper for the actor m_Actor->SetMapper( m_Mapper ); vtkSmartPointer outlineShadowActor = vtkSmartPointer::New(); outlineShadowActor->SetMapper( m_Mapper ); m_Actors->AddPart( outlineShadowActor ); m_Actors->AddPart( m_Actor ); } diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.h b/Core/Code/Rendering/mitkImageVtkMapper2D.h index 3a87e50cba..3643d989aa 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.h +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.h @@ -1,306 +1,306 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E #define MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E //MITK #include //MITK Rendering #include "mitkBaseRenderer.h" #include "mitkVtkMapper.h" #include "mitkExtractSliceFilter.h" //VTK #include #include class vtkActor; class vtkPolyDataMapper; class vtkPlaneSource; class vtkImageData; class vtkLookupTable; class vtkImageExtractComponents; class vtkImageReslice; class vtkImageChangeInformation; class vtkPoints; class vtkMitkThickSlicesFilter; class vtkPolyData; class vtkMitkApplyLevelWindowToRGBFilter; class vtkMitkLevelWindowFilter; namespace mitk { /** \brief Mapper to resample and display 2D slices of a 3D image. * * The following image gives a brief overview of the mapping and the involved parts. * * \image html imageVtkMapper2Darchitecture.png * * First, the image is resliced by means of vtkImageReslice. The volume image * serves as input to the mapper in addition to spatial placement of the slice and a few other * properties such as thick slices. This code was already present in the old version * (mitkImageMapperGL2D). * * Next, the obtained slice (m_ReslicedImage) is put into a vtkMitkLevelWindowFilter * and the scalar levelwindow, opacity levelwindow and optional clipping to * local image bounds are applied * * Next, the output of the vtkMitkLevelWindowFilter is used to create a texture * (m_Texture) and a plane onto which the texture is rendered (m_Plane). For * mapping purposes, a vtkPolyDataMapper (m_Mapper) is utilized. Orthographic * projection is applied to create the effect of a 2D image. The mapper and the * texture are assigned to the actor (m_Actor) which is passed to the VTK rendering * pipeline via the method GetVtkProp(). * * In order to transform the textured plane to the correct position in space, the * same transformation as used for reslicing is applied to both the camera and the * vtkActor. All important steps are explained in more detail below. The resulting * 2D image (by reslicing the underlying 3D input image appropriately) can either * be directly rendered in a 2D view or just be calculated to be used later by another * rendering entity, e.g. in texture mapping in a 3D view. * * Properties that can be set for images and influence the imageMapper2D are: * * - \b "opacity": (FloatProperty) Opacity of the image * - \b "color": (ColorProperty) Color of the image * - \b "LookupTable": (mitkLookupTableProperty) If this property is set, * the default lookuptable will be ignored and the "LookupTable" value * will be used instead. * - \b "Image Rendering.Mode": This property decides which mode is used to render images. (E.g. if a lookup table or a transferfunction is applied). Detailed documentation about the modes can be found here: \link mitk::RenderingerModeProperty \endlink * - \b "Image Rendering.Transfer Function": (mitkTransferFunctionProperty) If this * property is set, a color transferfunction will be used to color the image. * - \b "binary": (BoolProperty) is the image a binary image or not * - \b "outline binary": (BoolProperty) show outline of the image or not * - \b "texture interpolation": (BoolProperty) texture interpolation of the image * - \b "reslice interpolation": (VtkResliceInterpolationProperty) reslice interpolation of the image * - \b "in plane resample extent by geometry": (BoolProperty) Do it or not * - \b "bounding box": (BoolProperty) Is the Bounding Box of the image shown or not * - \b "layer": (IntProperty) Layer of the image * - \b "volume annotation color": (ColorProperty) color of the volume annotation, TODO has to be reimplemented * - \b "volume annotation unit": (StringProperty) annotation unit as string (does not implicit convert the unit!) unit is ml or cm3, TODO has to be reimplemented * The default properties are: * - \b "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ) * - \b "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ) * - \b "binary", mitk::BoolProperty::New( true ), renderer, overwrite ) * - \b "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ) * - \b "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ) * - \b "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ) * - \b "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ) * - \b "bounding box", mitk::BoolProperty::New( false ) ) * - \b "layer", mitk::IntProperty::New(10), renderer, overwrite) * - \b "Image Rendering.Transfer Function": Default color transfer function for CTs * - \b "LookupTable": Rainbow color. * If the modality-property is set for an image, the mapper uses modality-specific default properties, * e.g. color maps, if they are defined. * \ingroup Mapper */ class MITK_CORE_EXPORT ImageVtkMapper2D : public VtkMapper { public: /** Standard class typedefs. */ mitkClassMacro( ImageVtkMapper2D,VtkMapper ); /** Method for creation through the object factory. */ itkNewMacro(Self); /** \brief Get the Image to map */ const mitk::Image *GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ /** * To render transveral, coronal, and sagittal, the mapper is called three times. * For performance reasons, the corresponding data for each view is saved in the * internal helper class LocalStorage. This allows rendering n views with just * 1 mitkMapper using n vtkMapper. * */ class MITK_CORE_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_Actor; vtkSmartPointer m_Actors; /** \brief Mapper of a 2D render window. */ vtkSmartPointer m_Mapper; vtkSmartPointer m_VectorComponentExtractor; /** \brief Current slice of a 2D render window.*/ vtkSmartPointer m_ReslicedImage; /** \brief Empty vtkPolyData that is set when rendering geometry does not * intersect the image geometry. * \warning This member variable is set to NULL, * if no image geometry is inside the plane geometry * of the respective render window. Any user of this * slice has to check whether it is set to NULL! */ vtkSmartPointer m_EmptyPolyData; /** \brief Plane on which the slice is rendered as texture. */ vtkSmartPointer m_Plane; /** \brief The texture which is used to render the current slice. */ vtkSmartPointer m_Texture; /** \brief The lookuptables for colors and level window */ vtkSmartPointer m_DefaultLookupTable; vtkSmartPointer m_BinaryLookupTable; vtkSmartPointer m_ColorLookupTable; /** \brief The actual reslicer (one per renderer) */ mitk::ExtractSliceFilter::Pointer m_Reslicer; /** \brief Filter for thick slices */ vtkSmartPointer m_TSFilter; /** \brief PolyData object containg all lines/points needed for outlining the contour. This container is used to save a computed contour for the next rendering execution. For instance, if you zoom or pann, there is no need to recompute the contour. */ vtkSmartPointer m_OutlinePolyData; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief mmPerPixel relation between pixel and mm. (World spacing).*/ mitk::ScalarType* m_mmPerPixel; /** \brief This filter is used to apply the level window to Grayvalue and RBG(A) images. */ vtkSmartPointer m_LevelWindowFilter; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage(); }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); /** \brief This method switches between different rendering modes (e.g. use a lookup table or a transfer function). * Detailed documentation about the modes can be found here: \link mitk::RenderingerModeProperty \endlink */ void ApplyRenderingMode(mitk::BaseRenderer *renderer); protected: /** \brief Transforms the actor to the actual position in 3D. * \param renderer The current renderer corresponding to the render window. */ void TransformActor(mitk::BaseRenderer* renderer); /** \brief Generates a plane according to the size of the resliced image in milimeters. * * \image html texturedPlane.png * * In VTK a vtkPlaneSource is defined through three points. The origin and two * points defining the axes of the plane (see VTK documentation). The origin is * set to (xMin; yMin; Z), where xMin and yMin are the minimal bounds of the * resliced image in space. Z is relevant for blending and the layer property. * The center of the plane (C) is also the center of the view plane (cf. the image above). * * \note For the standard MITK view with three 2D render windows showing three * different slices, three such planes are generated. All these planes are generated * in the XY-plane (even if they depict a YZ-slice of the volume). * */ - void GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]); + void GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]); /** \brief Generates a vtkPolyData object containing the outline of a given binary slice. \param renderer: Pointer to the renderer containing the needed information \note This code is based on code from the iil library. */ vtkSmartPointer CreateOutlinePolyData(mitk::BaseRenderer* renderer); /** Default constructor */ ImageVtkMapper2D(); /** Default deconstructor */ virtual ~ImageVtkMapper2D(); /** \brief Does the actual resampling, without rendering the image yet. * All the data is generated inside this method. The vtkProp (or Actor) * is filled with content (i.e. the resliced image). * * After generation, a 4x4 transformation matrix(t) of the current slice is obtained * from the vtkResliceImage object via GetReslicesAxis(). This matrix is * applied to each textured plane (actor->SetUserTransform(t)) to transform everything * to the actual 3D position (cf. the following image). * * \image html cameraPositioning3D.png * */ virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer); /** \brief This method uses the vtkCamera clipping range and the layer property * to calcualte the depth of the object (e.g. image or contour). The depth is used * to keep the correct order for the final VTK rendering.*/ float CalculateLayerDepth(mitk::BaseRenderer* renderer); /** \brief This method applies (or modifies) the lookuptable for all types of images. * \warning To use the lookup table, the property 'Lookup Table' must be set and a 'Image Rendering.Mode' * which uses the lookup table must be set. */ void ApplyLookuptable(mitk::BaseRenderer* renderer); /** \brief This method applies a color transfer function. * Internally, a vtkColorTransferFunction is used. This is usefull for coloring continous * images (e.g. float) * \warning To use the color transfer function, the property 'Image Rendering.Transfer Function' must be set and a 'Image Rendering.Mode' which uses the color transfer function must be set. */ void ApplyColorTransferFunction(mitk::BaseRenderer* renderer); /** * @brief ApplyLevelWindow Apply the level window for the given renderer. * \warning To use the level window, the property 'LevelWindow' must be set and a 'Image Rendering.Mode' which uses the level window must be set. * @param renderer Level window for which renderer? */ void ApplyLevelWindow(mitk::BaseRenderer* renderer); /** \brief Set the color of the image/polydata */ void ApplyColor( mitk::BaseRenderer* renderer ); /** \brief Set the opacity of the actor. */ void ApplyOpacity( mitk::BaseRenderer* renderer ); /** * \brief Calculates whether the given rendering geometry intersects the * given SlicedGeometry3D. * * This method checks if the given Geometry2D intersects the given * SlicedGeometry3D. It calculates the distance of the Geometry2D to all * 8 cornerpoints of the SlicedGeometry3D. If all distances have the same * sign (all positive or all negative) there is no intersection. * If the distances have different sign, there is an intersection. **/ bool RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry ); }; } // namespace mitk #endif /* MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E */ diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp b/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp index ce68a76cc4..889e2d5727 100644 --- a/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp +++ b/Core/Code/Rendering/mitkPointSetVtkMapper2D.cpp @@ -1,734 +1,734 @@ /*=================================================================== 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 "mitkPointSetVtkMapper2D.h" //mitk includes #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkVtkPropRenderer.h" #include "mitkPointSet.h" //vtk includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include // constructor LocalStorage mitk::PointSetVtkMapper2D::LocalStorage::LocalStorage() { // points m_UnselectedPoints = vtkSmartPointer::New(); m_SelectedPoints = vtkSmartPointer::New(); m_ContourPoints = vtkSmartPointer::New(); // scales m_UnselectedScales = vtkSmartPointer::New(); m_SelectedScales = vtkSmartPointer::New(); // distances m_DistancesBetweenPoints = vtkSmartPointer::New(); // lines m_ContourLines = vtkSmartPointer::New(); // glyph source (provides the different shapes) m_UnselectedGlyphSource2D = vtkSmartPointer::New(); m_SelectedGlyphSource2D = vtkSmartPointer::New(); // glyphs m_UnselectedGlyph3D = vtkSmartPointer::New(); m_SelectedGlyph3D = vtkSmartPointer::New(); // polydata m_VtkUnselectedPointListPolyData = vtkSmartPointer::New(); m_VtkSelectedPointListPolyData = vtkSmartPointer ::New(); m_VtkContourPolyData = vtkSmartPointer::New(); // actors m_UnselectedActor = vtkSmartPointer ::New(); m_SelectedActor = vtkSmartPointer ::New(); m_ContourActor = vtkSmartPointer ::New(); // mappers m_VtkUnselectedPolyDataMapper = vtkSmartPointer::New(); m_VtkSelectedPolyDataMapper = vtkSmartPointer::New(); m_VtkContourPolyDataMapper = vtkSmartPointer::New(); // propassembly m_PropAssembly = vtkSmartPointer ::New(); } // destructor LocalStorage mitk::PointSetVtkMapper2D::LocalStorage::~LocalStorage() { } // input for this mapper ( = point set) const mitk::PointSet* mitk::PointSetVtkMapper2D::GetInput() const { return static_cast ( GetDataNode()->GetData() ); } // constructor PointSetVtkMapper2D mitk::PointSetVtkMapper2D::PointSetVtkMapper2D() : m_ShowContour(false), m_CloseContour(false), m_ShowPoints(true), m_ShowDistances(false), m_DistancesDecimalDigits(1), m_ShowAngles(false), m_ShowDistantLines(false), m_LineWidth(1), m_PointLineWidth(1), m_Point2DSize(6), m_IDShapeProperty(mitk::PointSetShapeProperty::CROSS), m_FillShape(false), m_DistanceToPlane(4.0f) { } // destructor mitk::PointSetVtkMapper2D::~PointSetVtkMapper2D() { } // reset mapper so that nothing is displayed e.g. toggle visiblity of the propassembly void mitk::PointSetVtkMapper2D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_PropAssembly->VisibilityOff(); } // returns propassembly vtkProp* mitk::PointSetVtkMapper2D::GetVtkProp(mitk::BaseRenderer * renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_PropAssembly; } static bool makePerpendicularVector2D(const mitk::Vector2D& in, mitk::Vector2D& out) { // The dot product of orthogonal vectors is zero. // In two dimensions the slopes of perpendicular lines are negative reciprocals. if((fabs(in[0])>0) && ( (fabs(in[0])>fabs(in[1])) || (in[1] == 0) ) ) { // negative reciprocal out[0]=-in[1]/in[0]; out[1]=1; out.Normalize(); return true; } else if(fabs(in[1])>0) { out[0]=1; // negative reciprocal out[1]=-in[0]/in[1]; out.Normalize(); return true; } else return false; } void mitk::PointSetVtkMapper2D::CreateVTKRenderObjects(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); unsigned i = 0; // The vtk text actors need to be removed manually from the propassembly // since the same vtk text actors are not overwriten within this function, // but new actors are added to the propassembly each time this function is executed. // Thus, the actors from the last call must be removed in the beginning. for(i=0; i< ls->m_VtkTextLabelActors.size(); i++) { if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextLabelActors.at(i))) ls->m_PropAssembly->RemovePart(ls->m_VtkTextLabelActors.at(i)); } for(i=0; i< ls->m_VtkTextDistanceActors.size(); i++) { if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextDistanceActors.at(i))) ls->m_PropAssembly->RemovePart(ls->m_VtkTextDistanceActors.at(i)); } for(i=0; i< ls->m_VtkTextAngleActors.size(); i++) { if(ls->m_PropAssembly->GetParts()->IsItemPresent(ls->m_VtkTextAngleActors.at(i))) ls->m_PropAssembly->RemovePart(ls->m_VtkTextAngleActors.at(i)); } // initialize polydata here, otherwise we have update problems when // executing this function again ls->m_VtkUnselectedPointListPolyData = vtkSmartPointer::New(); ls->m_VtkSelectedPointListPolyData = vtkSmartPointer ::New(); ls->m_VtkContourPolyData = vtkSmartPointer::New(); // get input point set and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); // only update the input data, if the property tells us to bool update = true; this->GetDataNode()->GetBoolProperty("updateDataOnRender", update); if (update == true) input->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep ); if ( itkPointSet.GetPointer() == NULL) { ls->m_PropAssembly->VisibilityOff(); return; } //iterator for point set mitk::PointSet::PointsContainer::Iterator pointsIter = itkPointSet->GetPoints()->Begin(); // PointDataContainer has additional information to each point, e.g. whether // it is selected or not mitk::PointSet::PointDataContainer::Iterator pointDataIter; pointDataIter = itkPointSet->GetPointData()->Begin(); //check if the list for the PointDataContainer is the same size as the PointsContainer. //If not, then the points were inserted manually and can not be visualized according to the PointData (selected/unselected) bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); if(itkPointSet->GetPointData()->size() == 0 || pointDataBroken) { return; } // empty point sets, cellarrays, scalars ls->m_UnselectedPoints->Reset(); ls->m_SelectedPoints->Reset(); ls->m_ContourPoints->Reset(); ls->m_ContourLines->Reset(); ls->m_UnselectedScales->Reset(); ls->m_SelectedScales->Reset(); ls->m_DistancesBetweenPoints->Reset(); ls->m_VtkTextLabelActors.clear(); ls->m_VtkTextDistanceActors.clear(); ls->m_VtkTextAngleActors.clear(); ls->m_UnselectedScales->SetNumberOfComponents(3); ls->m_SelectedScales->SetNumberOfComponents(3); int NumberContourPoints = 0; bool pointsOnSameSideOfPlane = false; const int text2dDistance = 10; // initialize points with a random start value // current point in point set itk::Point point = pointsIter->Value(); mitk::Point3D p = point; // currently visited point mitk::Point3D lastP = point; // last visited point (predecessor in point set of "point") mitk::Vector3D vec; // p - lastP mitk::Vector3D lastVec; // lastP - point before lastP vec.Fill(0); lastVec.Fill(0); mitk::Point3D projected_p = point; // p projected on viewplane mitk::Point2D pt2d; pt2d[0] = point[0]; // projected_p in display coordinates pt2d[1] = point[1]; mitk::Point2D lastPt2d = pt2d; // last projected_p in display coordinates (predecessor in point set of "pt2d") mitk::Point2D preLastPt2d = pt2d ; // projected_p in display coordinates before lastPt2 mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); mitk::PlaneGeometry::ConstPointer planeGeometry = renderer->GetSliceNavigationController()->GetCurrentPlaneGeometry(); vtkLinearTransform* dataNodeTransform = input->GetGeometry()->GetVtkTransform(); int count = 0; for (pointsIter=itkPointSet->GetPoints()->Begin(); pointsIter!=itkPointSet->GetPoints()->End(); pointsIter++) { lastP = p; // valid for number of points count > 0 preLastPt2d = lastPt2d; // valid only for count > 1 lastPt2d = pt2d; // valid for number of points count > 0 lastVec = vec; // valid only for counter > 1 // get current point in point set point = pointsIter->Value(); // transform point { float vtkp[3]; itk2vtk(point, vtkp); dataNodeTransform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,point); } p[0] = point[0]; p[1] = point[1]; p[2] = point[2]; displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); vec = p-lastP; // valid only for counter > 0 // compute distance to current plane float diff = planeGeometry->DistanceFromPlane(point); diff = diff * diff; // draw markers on slices a certain distance away from the points true location according to the tolerance threshold (m_DistanceToPlane) if(diff < m_DistanceToPlane) { // is point selected or not? if (pointDataIter->Value().selected) { ls->m_SelectedPoints->InsertNextPoint(point[0],point[1],point[2]); // point is scaled according to its distance to the plane ls->m_SelectedScales->InsertNextTuple3(m_Point2DSize - (2*diff),0,0); } else { ls->m_UnselectedPoints->InsertNextPoint(point[0],point[1],point[2]); // point is scaled according to its distance to the plane ls->m_UnselectedScales->InsertNextTuple3(m_Point2DSize - (2*diff),0,0); } //---- LABEL -----// // paint label for each point if available if (dynamic_cast(this->GetDataNode()->GetProperty("label")) != NULL) { const char * pointLabel = dynamic_cast( this->GetDataNode()->GetProperty("label"))->GetValue(); std::string l = pointLabel; if (input->GetSize()>1) { std::stringstream ss; ss << pointsIter->Index(); l.append(ss.str()); } ls->m_VtkTextActor = vtkSmartPointer::New(); ls->m_VtkTextActor->SetPosition(pt2d[0] + text2dDistance, pt2d[1] + text2dDistance); ls->m_VtkTextActor->SetInput(l.c_str()); ls->m_VtkTextActor->GetTextProperty()->SetOpacity( 100 ); float unselectedColor[4]; //check if there is a color property GetDataNode()->GetColor(unselectedColor); if (unselectedColor != NULL) ls->m_VtkTextActor->GetTextProperty()->SetColor(unselectedColor[0], unselectedColor[1], unselectedColor[2]); else ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0f, 1.0f, 0.0f); ls->m_VtkTextLabelActors.push_back(ls->m_VtkTextActor); } } // draw contour, distance text and angle text in render window // lines between points, which intersect the current plane, are drawn if( m_ShowContour && count > 0 ) { ScalarType distance = displayGeometry->GetWorldGeometry()->SignedDistance(point); ScalarType lastDistance = displayGeometry->GetWorldGeometry()->SignedDistance(lastP); pointsOnSameSideOfPlane = (distance * lastDistance) > 0.5; // Points must be on different side of plane in order to draw a contour. // If "show distant lines" is enabled this condition is disregarded. if ( !pointsOnSameSideOfPlane || m_ShowDistantLines) { vtkSmartPointer line = vtkSmartPointer::New(); ls->m_ContourPoints->InsertNextPoint(lastP[0],lastP[1],lastP[2]); line->GetPointIds()->SetId(0, NumberContourPoints); NumberContourPoints++; ls->m_ContourPoints->InsertNextPoint(point[0], point[1], point[2]); line->GetPointIds()->SetId(1, NumberContourPoints); NumberContourPoints++; ls->m_ContourLines->InsertNextCell(line); if(m_ShowDistances) // calculate and print distance between adjacent points { float distancePoints = point.EuclideanDistanceTo(lastP); std::stringstream buffer; buffer<m_VtkTextActor = vtkSmartPointer::New(); ls->m_VtkTextActor->SetPosition(pos2d[0],pos2d[1]); ls->m_VtkTextActor->SetInput(buffer.str().c_str()); ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0, 1.0, 0.0); ls->m_VtkTextDistanceActors.push_back(ls->m_VtkTextActor); } if(m_ShowAngles && count > 1) // calculate and print angle between connected lines { std::stringstream buffer; //(char) 176 is the degree sign buffer << angle(vec.GetVnlVector(), -lastVec.GetVnlVector())*180/vnl_math::pi << (char)176; //compute desired display position of text Vector2D vec2d = pt2d-lastPt2d; // first arm enclosing the angle vec2d.Normalize(); Vector2D lastVec2d = lastPt2d-preLastPt2d; // second arm enclosing the angle lastVec2d.Normalize(); vec2d=vec2d-lastVec2d; // vector connecting both arms vec2d.Normalize(); // middle between two vectors that enclose the angle Vector2D pos2d = lastPt2d.GetVectorFromOrigin() + vec2d * text2dDistance * text2dDistance; ls->m_VtkTextActor = vtkSmartPointer::New(); ls->m_VtkTextActor->SetPosition(pos2d[0],pos2d[1]); ls->m_VtkTextActor->SetInput(buffer.str().c_str()); ls->m_VtkTextActor->GetTextProperty()->SetColor(0.0, 1.0, 0.0); ls->m_VtkTextAngleActors.push_back(ls->m_VtkTextActor); } } } if(pointDataIter != itkPointSet->GetPointData()->End()) { pointDataIter++; count++; } } // add each single text actor to the assembly for(i=0; i< ls->m_VtkTextLabelActors.size(); i++) { ls->m_PropAssembly->AddPart(ls->m_VtkTextLabelActors.at(i)); } for(i=0; i< ls->m_VtkTextDistanceActors.size(); i++) { ls->m_PropAssembly->AddPart(ls->m_VtkTextDistanceActors.at(i)); } for(i=0; i< ls->m_VtkTextAngleActors.size(); i++) { ls->m_PropAssembly->AddPart(ls->m_VtkTextAngleActors.at(i)); } //---- CONTOUR -----// //create lines between the points which intersect the plane if (m_ShowContour) { // draw line between first and last point which is rendered if(m_CloseContour && NumberContourPoints > 1){ vtkSmartPointer closingLine = vtkSmartPointer::New(); closingLine->GetPointIds()->SetId(0, 0); // index of first point closingLine->GetPointIds()->SetId(1, NumberContourPoints-1); // index of last point ls->m_ContourLines->InsertNextCell(closingLine); } ls->m_VtkContourPolyData->SetPoints(ls->m_ContourPoints); ls->m_VtkContourPolyData->SetLines(ls->m_ContourLines); ls->m_VtkContourPolyDataMapper->SetInput(ls->m_VtkContourPolyData); ls->m_ContourActor->SetMapper(ls->m_VtkContourPolyDataMapper); ls->m_ContourActor->GetProperty()->SetLineWidth(m_LineWidth); ls->m_PropAssembly->AddPart(ls->m_ContourActor); } // the point set must be transformed in order to obtain the appropriate glyph orientation // according to the current view vtkSmartPointer transform = vtkSmartPointer::New(); vtkSmartPointer a,b = vtkSmartPointer::New(); a = planeGeometry->GetVtkTransform()->GetMatrix(); b->DeepCopy( a ); // delete transformation from matrix, only take orientation b->SetElement(3,3,1); b->SetElement(2,3,0); b->SetElement(1,3,0); b->SetElement(0,3,0); b->SetElement(3,2,0); b->SetElement(3,1,0); b->SetElement(3,0,0); transform->SetMatrix( b ); //---- UNSELECTED POINTS -----// // apply properties to glyph ls->m_UnselectedGlyphSource2D->SetGlyphType(m_IDShapeProperty); if(m_FillShape) ls->m_UnselectedGlyphSource2D->FilledOn(); else ls->m_UnselectedGlyphSource2D->FilledOff(); // apply transform vtkSmartPointer transformFilterU = vtkSmartPointer::New(); transformFilterU->SetInputConnection(ls->m_UnselectedGlyphSource2D->GetOutputPort()); transformFilterU->SetTransform(transform); ls->m_VtkUnselectedPointListPolyData->SetPoints(ls->m_UnselectedPoints); ls->m_VtkUnselectedPointListPolyData->GetPointData()->SetVectors(ls->m_UnselectedScales); // apply transform of current plane to glyphs ls->m_UnselectedGlyph3D->SetSourceConnection(transformFilterU->GetOutputPort()); ls->m_UnselectedGlyph3D->SetInput(ls->m_VtkUnselectedPointListPolyData); ls->m_UnselectedGlyph3D->SetScaleModeToScaleByVector(); ls->m_UnselectedGlyph3D->SetVectorModeToUseVector(); ls->m_VtkUnselectedPolyDataMapper->SetInput(ls->m_UnselectedGlyph3D->GetOutput()); ls->m_UnselectedActor->SetMapper(ls->m_VtkUnselectedPolyDataMapper); ls->m_UnselectedActor->GetProperty()->SetLineWidth(m_PointLineWidth); ls->m_PropAssembly->AddPart(ls->m_UnselectedActor); //---- SELECTED POINTS -----// ls->m_SelectedGlyphSource2D->SetGlyphTypeToDiamond(); ls->m_SelectedGlyphSource2D->CrossOn(); ls->m_SelectedGlyphSource2D->FilledOff(); // apply transform vtkSmartPointer transformFilterS = vtkSmartPointer::New(); transformFilterS->SetInputConnection(ls->m_SelectedGlyphSource2D->GetOutputPort()); transformFilterS->SetTransform(transform); ls->m_VtkSelectedPointListPolyData->SetPoints(ls->m_SelectedPoints); ls->m_VtkSelectedPointListPolyData->GetPointData()->SetVectors(ls->m_SelectedScales); // apply transform of current plane to glyphs ls->m_SelectedGlyph3D->SetSourceConnection(transformFilterS->GetOutputPort()); ls->m_SelectedGlyph3D->SetInput(ls->m_VtkSelectedPointListPolyData); ls->m_SelectedGlyph3D->SetScaleModeToScaleByVector(); ls->m_SelectedGlyph3D->SetVectorModeToUseVector(); ls->m_VtkSelectedPolyDataMapper->SetInput(ls->m_SelectedGlyph3D->GetOutput()); ls->m_SelectedActor->SetMapper(ls->m_VtkSelectedPolyDataMapper); ls->m_SelectedActor->GetProperty()->SetLineWidth(m_PointLineWidth); ls->m_PropAssembly->AddPart(ls->m_SelectedActor); } void mitk::PointSetVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { const mitk::DataNode* node = GetDataNode(); if( node == NULL ) return; LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // check whether the input data has been changed bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); // toggle visibility bool visible = true; node->GetVisibility(visible, renderer, "visible"); if(!visible) { ls->m_UnselectedActor->VisibilityOff(); ls->m_SelectedActor->VisibilityOff(); ls->m_ContourActor->VisibilityOff(); ls->m_PropAssembly->VisibilityOff(); return; }else{ ls->m_PropAssembly->VisibilityOn(); } node->GetBoolProperty("show contour", m_ShowContour, renderer); node->GetBoolProperty("close contour", m_CloseContour, renderer); node->GetBoolProperty("show points", m_ShowPoints, renderer); node->GetBoolProperty("show distances", m_ShowDistances, renderer); node->GetIntProperty("distance decimal digits", m_DistancesDecimalDigits, renderer); node->GetBoolProperty("show angles", m_ShowAngles, renderer); node->GetBoolProperty("show distant lines", m_ShowDistantLines, renderer); node->GetIntProperty("line width", m_LineWidth, renderer); node->GetIntProperty("point line width", m_PointLineWidth, renderer); node->GetIntProperty("point 2D size", m_Point2DSize, renderer); node->GetBoolProperty("Pointset.2D.fill shape", m_FillShape, renderer); node->GetFloatProperty("Pointset.2D.distance to plane", m_DistanceToPlane, renderer ); mitk::PointSetShapeProperty::Pointer shape = dynamic_cast(this->GetDataNode()->GetProperty( "Pointset.2D.shape", renderer )); if(shape.IsNotNull()) { m_IDShapeProperty = shape->GetPointSetShape(); } //check for color props and use it for rendering of selected/unselected points and contour //due to different params in VTK (double/float) we have to convert float unselectedColor[4]; - vtkFloatingPointType selectedColor[4]={1.0f,0.0f,0.0f,1.0f}; //red - vtkFloatingPointType contourColor[4]={1.0f,0.0f,0.0f,1.0f}; //red + double selectedColor[4]={1.0f,0.0f,0.0f,1.0f}; //red + double contourColor[4]={1.0f,0.0f,0.0f,1.0f}; //red float opacity = 1.0; GetDataNode()->GetOpacity(opacity, renderer); // apply color and opacity if(m_ShowPoints) { ls->m_UnselectedActor->VisibilityOn(); ls->m_SelectedActor->VisibilityOn(); //check if there is a color property GetDataNode()->GetColor(unselectedColor); //get selected color property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; // alpha value } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; // alpha value } ls->m_SelectedActor->GetProperty()->SetColor(selectedColor); ls->m_SelectedActor->GetProperty()->SetOpacity(opacity); ls->m_UnselectedActor->GetProperty()->SetColor(unselectedColor[0],unselectedColor[1],unselectedColor[2]); ls->m_UnselectedActor->GetProperty()->SetOpacity(opacity); } else { ls->m_UnselectedActor->VisibilityOff(); ls-> m_SelectedActor->VisibilityOff(); } if (m_ShowContour) { ls->m_ContourActor->VisibilityOn(); //get contour color property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } ls->m_ContourActor->GetProperty()->SetColor(contourColor); ls->m_ContourActor->GetProperty()->SetOpacity(opacity); } else { ls->m_ContourActor->VisibilityOff(); } if(needGenerateData) { // create new vtk render objects (e.g. a circle for a point) this->CreateVTKRenderObjects(renderer); } } void mitk::PointSetVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "point line width", mitk::IntProperty::New(1), renderer, overwrite ); node->AddProperty( "point 2D size", mitk::IntProperty::New(6), renderer, overwrite ); node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "show distances", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "distance decimal digits", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "show angles", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "show distant lines", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "layer", mitk::IntProperty::New(1), renderer, overwrite ); node->AddProperty( "Pointset.2D.fill shape", mitk::BoolProperty::New(false), renderer, overwrite); // fill or do not fill the glyph shape mitk::PointSetShapeProperty::Pointer pointsetShapeProperty = mitk::PointSetShapeProperty::New(); node->AddProperty( "Pointset.2D.shape", pointsetShapeProperty, renderer, overwrite); node->AddProperty( "Pointset.2D.distance to plane", mitk::FloatProperty::New(4.0f), renderer, overwrite ); //show the point at a certain distance above/below the 2D imaging plane. Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp b/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp index 660387006a..f1f6069414 100644 --- a/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp @@ -1,642 +1,642 @@ /*=================================================================== 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 "mitkPointSetVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkPointSet.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const mitk::PointSet* mitk::PointSetVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } mitk::PointSetVtkMapper3D::PointSetVtkMapper3D() : m_vtkSelectedPointList(NULL), m_vtkUnselectedPointList(NULL), m_VtkSelectedPolyDataMapper(NULL), m_VtkUnselectedPolyDataMapper(NULL), m_vtkTextList(NULL), m_NumberOfSelectedAdded(0), m_NumberOfUnselectedAdded(0), m_PointSize(1.0), m_ContourRadius(0.5) { //propassembly m_PointsAssembly = vtkSmartPointer::New(); //creating actors to be able to set transform m_SelectedActor = vtkSmartPointer::New(); m_UnselectedActor = vtkSmartPointer::New(); m_ContourActor = vtkSmartPointer::New(); } mitk::PointSetVtkMapper3D::~PointSetVtkMapper3D() { } void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(vtkWindow *renWin) { m_PointsAssembly->ReleaseGraphicsResources(renWin); m_SelectedActor->ReleaseGraphicsResources(renWin); m_UnselectedActor->ReleaseGraphicsResources(renWin); m_ContourActor->ReleaseGraphicsResources(renWin); } void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(mitk::BaseRenderer* renderer) { m_PointsAssembly->ReleaseGraphicsResources(renderer->GetRenderWindow()); m_SelectedActor->ReleaseGraphicsResources(renderer->GetRenderWindow()); m_UnselectedActor->ReleaseGraphicsResources(renderer->GetRenderWindow()); m_ContourActor->ReleaseGraphicsResources(renderer->GetRenderWindow()); } void mitk::PointSetVtkMapper3D::CreateVTKRenderObjects() { m_vtkSelectedPointList = vtkSmartPointer::New(); m_vtkUnselectedPointList = vtkSmartPointer::New(); m_PointsAssembly->VisibilityOn(); if(m_PointsAssembly->GetParts()->IsItemPresent(m_SelectedActor)) m_PointsAssembly->RemovePart(m_SelectedActor); if(m_PointsAssembly->GetParts()->IsItemPresent(m_UnselectedActor)) m_PointsAssembly->RemovePart(m_UnselectedActor); if(m_PointsAssembly->GetParts()->IsItemPresent(m_ContourActor)) m_PointsAssembly->RemovePart(m_ContourActor); // exceptional displaying for PositionTracker -> MouseOrientationTool int mapperID; bool isInputDevice=false; if( this->GetDataNode()->GetBoolProperty("inputdevice",isInputDevice) && isInputDevice ) { if( this->GetDataNode()->GetIntProperty("BaseRendererMapperID",mapperID) && mapperID == 2) return; //The event for the PositionTracker came from the 3d widget and not needs to be displayed } // get and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); /* only update the input data, if the property tells us to */ bool update = true; this->GetDataNode()->GetBoolProperty("updateDataOnRender", update); if (update == true) input->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep ); if ( itkPointSet.GetPointer() == NULL) { m_PointsAssembly->VisibilityOff(); return; } mitk::PointSet::PointsContainer::Iterator pointsIter; mitk::PointSet::PointDataContainer::Iterator pointDataIter; int j; m_NumberOfSelectedAdded = 0; m_NumberOfUnselectedAdded = 0; //create contour bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour); if (makeContour) { this->CreateContour(); } //now fill selected and unselected pointList //get size of Points in Property m_PointSize = 2; mitk::FloatProperty::Pointer pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); if ( pointSizeProp.IsNotNull() ) m_PointSize = pointSizeProp->GetValue(); //get the property for creating a label onto every point only once bool showLabel = true; this->GetDataNode()->GetBoolProperty("show label", showLabel); const char * pointLabel=NULL; if(showLabel) { if(dynamic_cast(this->GetDataNode()->GetPropertyList()->GetProperty("label")) != NULL) pointLabel =dynamic_cast(this->GetDataNode()->GetPropertyList()->GetProperty("label"))->GetValue(); else showLabel = false; } //check if the list for the PointDataContainer is the same size as the PointsContainer. Is not, then the points were inserted manually and can not be visualized according to the PointData (selected/unselected) bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); //now add an object for each point in data pointDataIter = itkPointSet->GetPointData()->Begin(); for (j=0, pointsIter=itkPointSet->GetPoints()->Begin(); pointsIter!=itkPointSet->GetPoints()->End(); pointsIter++, j++) { //check for the pointtype in data and decide which geom-object to take and then add to the selected or unselected list int pointType; if(itkPointSet->GetPointData()->size() == 0 || pointDataBroken) pointType = mitk::PTUNDEFINED; else pointType = pointDataIter.Value().pointSpec; vtkSmartPointer source; switch (pointType) { case mitk::PTUNDEFINED: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); sphere->SetCenter(point1[0],point1[1],point1[2]); //sphere->SetCenter(pointsIter.Value()[0],pointsIter.Value()[1],pointsIter.Value()[2]); //MouseOrientation Tool (PositionTracker) if(isInputDevice) { sphere->SetThetaResolution(10); sphere->SetPhiResolution(10); } else { sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); } source = sphere; } break; case mitk::PTSTART: { vtkSmartPointer cube = vtkSmartPointer::New(); cube->SetXLength(m_PointSize/2); cube->SetYLength(m_PointSize/2); cube->SetZLength(m_PointSize/2); itk::Point point1 = pointsIter->Value(); cube->SetCenter(point1[0],point1[1],point1[2]); source = cube; } break; case mitk::PTCORNER: { vtkSmartPointer cone = vtkSmartPointer::New(); cone->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); cone->SetCenter(point1[0],point1[1],point1[2]); cone->SetResolution(20); source = cone; } break; case mitk::PTEDGE: { vtkSmartPointer cylinder = vtkSmartPointer::New(); cylinder->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); cylinder->SetCenter(point1[0],point1[1],point1[2]); cylinder->SetResolution(20); source = cylinder; } break; case mitk::PTEND: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize); //itk::Point point1 = pointsIter->Value(); sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); source = sphere; } break; default: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); sphere->SetCenter(point1[0],point1[1],point1[2]); sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); source = sphere; } break; } if (!pointDataBroken) { if (pointDataIter.Value().selected) { m_vtkSelectedPointList->AddInput(source->GetOutput()); ++m_NumberOfSelectedAdded; } else { m_vtkUnselectedPointList->AddInput(source->GetOutput()); ++m_NumberOfUnselectedAdded; } } else { m_vtkUnselectedPointList->AddInput(source->GetOutput()); ++m_NumberOfUnselectedAdded; } if (showLabel) { char buffer[20]; std::string l = pointLabel; if ( input->GetSize()>1 ) { sprintf(buffer,"%d",j+1); l.append(buffer); } // Define the text for the label vtkSmartPointer label = vtkSmartPointer::New(); label->SetText(l.c_str()); //# Set up a transform to move the label to a new position. vtkSmartPointer aLabelTransform = vtkSmartPointer::New(); aLabelTransform->Identity(); itk::Point point1 = pointsIter->Value(); aLabelTransform->Translate(point1[0]+2,point1[1]+2,point1[2]); aLabelTransform->Scale(5.7,5.7,5.7); //# Move the label to a new position. vtkSmartPointer labelTransform = vtkSmartPointer::New(); labelTransform->SetTransform(aLabelTransform); labelTransform->SetInput(label->GetOutput()); //add it to the wright PointList if (pointType) { m_vtkSelectedPointList->AddInput(labelTransform->GetOutput()); ++m_NumberOfSelectedAdded; } else { m_vtkUnselectedPointList->AddInput(labelTransform->GetOutput()); ++m_NumberOfUnselectedAdded; } } if(pointDataIter != itkPointSet->GetPointData()->End()) pointDataIter++; } // end FOR //now according to number of elements added to selected or unselected, build up the rendering pipeline if (m_NumberOfSelectedAdded > 0) { m_VtkSelectedPolyDataMapper = vtkSmartPointer::New(); m_VtkSelectedPolyDataMapper->SetInput(m_vtkSelectedPointList->GetOutput()); //create a new instance of the actor m_SelectedActor = vtkSmartPointer::New(); m_SelectedActor->SetMapper(m_VtkSelectedPolyDataMapper); m_PointsAssembly->AddPart(m_SelectedActor); } if (m_NumberOfUnselectedAdded > 0) { m_VtkUnselectedPolyDataMapper = vtkSmartPointer::New(); m_VtkUnselectedPolyDataMapper->SetInput(m_vtkUnselectedPointList->GetOutput()); //create a new instance of the actor m_UnselectedActor = vtkSmartPointer::New(); m_UnselectedActor->SetMapper(m_VtkUnselectedPolyDataMapper); m_PointsAssembly->AddPart(m_UnselectedActor); } } void mitk::PointSetVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) { m_UnselectedActor->VisibilityOff(); m_SelectedActor->VisibilityOff(); m_ContourActor->VisibilityOff(); return; } // create new vtk render objects (e.g. sphere for a point) SetVtkMapperImmediateModeRendering(m_VtkSelectedPolyDataMapper); SetVtkMapperImmediateModeRendering(m_VtkUnselectedPolyDataMapper); BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool needGenerateData = ls->IsGenerateDataRequired( renderer, this, GetDataNode() ); if(!needGenerateData) { mitk::FloatProperty * pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); mitk::FloatProperty * contourSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("contoursize")); // only create new vtk render objects if property values were changed if(pointSizeProp && m_PointSize!=pointSizeProp->GetValue() ) needGenerateData = true; if(contourSizeProp && m_ContourRadius!=contourSizeProp->GetValue() ) needGenerateData = true; } if(needGenerateData) { this->CreateVTKRenderObjects(); ls->UpdateGenerateDataTime(); } this->ApplyAllProperties(renderer, m_ContourActor); bool showPoints = true; this->GetDataNode()->GetBoolProperty("show points", showPoints); if(showPoints) { m_UnselectedActor->VisibilityOn(); m_SelectedActor->VisibilityOn(); } else { m_UnselectedActor->VisibilityOff(); m_SelectedActor->VisibilityOff(); } if(dynamic_cast(this->GetDataNode()->GetProperty("opacity")) != NULL) { mitk::FloatProperty::Pointer pointOpacity =dynamic_cast(this->GetDataNode()->GetProperty("opacity")); float opacity = pointOpacity->GetValue(); m_ContourActor->GetProperty()->SetOpacity(opacity); m_UnselectedActor->GetProperty()->SetOpacity(opacity); m_SelectedActor->GetProperty()->SetOpacity(opacity); } bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour); if (makeContour) { m_ContourActor->VisibilityOn(); } else { m_ContourActor->VisibilityOff(); } } void mitk::PointSetVtkMapper3D::ResetMapper( BaseRenderer* /*renderer*/ ) { m_PointsAssembly->VisibilityOff(); } vtkProp* mitk::PointSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_PointsAssembly; } void mitk::PointSetVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { vtkSmartPointer vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); m_SelectedActor->SetUserTransform(vtktransform); m_UnselectedActor->SetUserTransform(vtktransform); m_ContourActor->SetUserTransform(vtktransform); } void mitk::PointSetVtkMapper3D::ApplyAllProperties(mitk::BaseRenderer* renderer, vtkActor* actor) { Superclass::ApplyColorAndOpacityProperties(renderer, actor); //check for color props and use it for rendering of selected/unselected points and contour //due to different params in VTK (double/float) we have to convert! //vars to convert to - vtkFloatingPointType unselectedColor[4]={1.0f,1.0f,0.0f,1.0f};//yellow - vtkFloatingPointType selectedColor[4]={1.0f,0.0f,0.0f,1.0f};//red - vtkFloatingPointType contourColor[4]={1.0f,0.0f,0.0f,1.0f};//red + double unselectedColor[4]={1.0f,1.0f,0.0f,1.0f};//yellow + double selectedColor[4]={1.0f,0.0f,0.0f,1.0f};//red + double contourColor[4]={1.0f,0.0f,0.0f,1.0f};//red //different types for color!!! mitk::Color tmpColor; double opacity = 1.0; //check if there is an unselected property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor"))->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor"))->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else { //check if the node has a color float unselectedColorTMP[4]={1.0f,1.0f,0.0f,1.0f};//yellow m_DataNode->GetColor(unselectedColorTMP, NULL); unselectedColor[0] = unselectedColorTMP[0]; unselectedColor[1] = unselectedColorTMP[1]; unselectedColor[2] = unselectedColorTMP[2]; //unselectedColor[3] stays 1.0f } //get selected property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } //get contour property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } if(dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")) != NULL) { mitk::FloatProperty::Pointer pointOpacity =dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")); opacity = pointOpacity->GetValue(); } else if(dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("opacity")) != NULL) { mitk::FloatProperty::Pointer pointOpacity =dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("opacity")); opacity = pointOpacity->GetValue(); } //finished color / opacity fishing! //check if a contour shall be drawn bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour, renderer); if(makeContour && (m_ContourActor != NULL) ) { this->CreateContour(); m_ContourActor->GetProperty()->SetColor(contourColor); m_ContourActor->GetProperty()->SetOpacity(opacity); } m_SelectedActor->GetProperty()->SetColor(selectedColor); m_SelectedActor->GetProperty()->SetOpacity(opacity); m_UnselectedActor->GetProperty()->SetColor(unselectedColor); m_UnselectedActor->GetProperty()->SetOpacity(opacity); } void mitk::PointSetVtkMapper3D::CreateContour() { vtkSmartPointer vtkContourPolyData = vtkSmartPointer::New(); vtkSmartPointer vtkContourPolyDataMapper = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer polys = vtkSmartPointer::New(); mitk::PointSet::PointsContainer::Iterator pointsIter; // mitk::PointSet::PointDataContainer::Iterator pointDataIter; int j; // get and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep ); if ( itkPointSet.GetPointer() == NULL) { return; } for (j=0, pointsIter=itkPointSet->GetPoints()->Begin(); pointsIter!=itkPointSet->GetPoints()->End() ; pointsIter++,j++) { vtkIdType cell[2] = {j-1,j}; itk::Point point1 = pointsIter->Value(); points->InsertPoint(j,point1[0],point1[1],point1[2]); if (j>0) polys->InsertNextCell(2,cell); } bool close = false; this->GetDataNode()->GetBoolProperty("close contour", close); if (close) { vtkIdType cell[2] = {j-1,0}; polys->InsertNextCell(2,cell); } vtkSmartPointer contour = vtkSmartPointer::New(); contour->SetPoints(points); contour->SetLines(polys); contour->Update(); vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetNumberOfSides( 12 ); tubeFilter->SetInput(contour); //check for property contoursize. m_ContourRadius = 0.5; mitk::FloatProperty::Pointer contourSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("contoursize") ); if (contourSizeProp.IsNotNull()) m_ContourRadius = contourSizeProp->GetValue(); tubeFilter->SetRadius( m_ContourRadius ); tubeFilter->Update(); //add to pipeline vtkContourPolyData->AddInput(tubeFilter->GetOutput()); vtkContourPolyDataMapper->SetInput(vtkContourPolyData->GetOutput()); m_ContourActor->SetMapper(vtkContourPolyDataMapper); m_PointsAssembly->AddPart(m_ContourActor); } void mitk::PointSetVtkMapper3D::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, 0.0f, 0.0f), renderer, overwrite); //red node->AddProperty( "color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); //yellow node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "close 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( "updateDataOnRender", mitk::BoolProperty::New(true), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp b/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp index 3f163d46c5..41f832c138 100644 --- a/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp @@ -1,276 +1,276 @@ /*=================================================================== 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 "mitkPolyDataGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkSurface.h" #include "mitkColorProperty.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 void mitk::PolyDataGLMapper2D::Paint( mitk::BaseRenderer * renderer ) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; // ok, das ist aus GenerateData kopiert mitk::BaseData::Pointer input = const_cast( GetDataNode()->GetData() ); assert( input ); input->Update(); vtkPolyData * vtkpolydata = this->GetVtkPolyData(); assert( vtkpolydata ); vtkLinearTransform * vtktransform = GetDataNode() ->GetVtkTransform(); if (vtktransform) { vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); if ( vtkpolydata != NULL ) { 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; } - vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; + double vp[ 3 ], vnormal[ 3 ]; vnl2vtk(point.GetVnlVector(), vp); vnl2vtk(normal.GetVnlVector(), 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_Cutter->SetInput( vtkpolydata ); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); // calculate the cut m_Cutter->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_Cutter->GetOutput(); vtkPoints *vpoints = contour->GetPoints(); vtkCellArray *vpolys = contour->GetLines(); vtkPointData *vpointdata = contour->GetPointData(); vtkDataArray* vscalars = vpointdata->GetScalars(); vtkCellData *vcelldata = contour->GetCellData(); vtkDataArray* vcellscalars = vcelldata->GetScalars(); int i, numberOfCells = vpolys->GetNumberOfCells(); Point3D p; Point2D p2d, last, first; vpolys->InitTraversal(); vtkScalarsToColors* lut = GetVtkLUT(); assert ( lut != NULL ); for ( i = 0;i < numberOfCells;++i ) { vtkIdType *cell(NULL); vtkIdType cellSize(0); vpolys->GetNextCell( cellSize, cell ); if ( m_ColorByCellData ) { // color each cell according to cell data - vtkFloatingPointType* color = lut->GetColor( vcellscalars->GetComponent( i, 0 ) ); + double* color = lut->GetColor( vcellscalars->GetComponent( i, 0 ) ); glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] ); } if ( m_ColorByPointData ) { - vtkFloatingPointType* color = lut->GetColor( vscalars->GetComponent( cell[0], 0 ) ); + double* color = lut->GetColor( vscalars->GetComponent( cell[0], 0 ) ); glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] ); } 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 (); } } } } vtkPolyDataMapper* mitk::PolyDataGLMapper2D::GetVtkPolyDataMapper() { return NULL; /* mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return NULL; mitk::VtkMapper3D::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper3D* > ( node->GetMapper( 2 ) ); if ( mitkMapper.IsNull() ) return NULL; mitkMapper->Update(NULL); vtkActor* actor = dynamic_cast( mitkMapper->GetVtkProp(0) ); if ( actor == NULL ) return NULL; return dynamic_cast( actor->GetMapper() ); */ } vtkPolyData* mitk::PolyDataGLMapper2D::GetVtkPolyData( ) { vtkPolyDataMapper * polyDataMapper = GetVtkPolyDataMapper(); if ( polyDataMapper == NULL ) return NULL; else return polyDataMapper->GetInput(); } vtkScalarsToColors* mitk::PolyDataGLMapper2D::GetVtkLUT( ) { vtkPolyDataMapper * polyDataMapper = GetVtkPolyDataMapper(); if ( polyDataMapper == NULL ) return NULL; else return polyDataMapper->GetLookupTable(); } bool mitk::PolyDataGLMapper2D::IsConvertibleToVtkPolyData() { return ( GetVtkPolyDataMapper() != NULL ); } mitk::PolyDataGLMapper2D::PolyDataGLMapper2D() { m_Plane = vtkPlane::New(); m_Cutter = vtkCutter::New(); m_Cutter->SetCutFunction( m_Plane ); m_Cutter->GenerateValues( 1, 0, 1 ); m_ColorByCellData = false; m_ColorByPointData = false; //m_LUT = vtkLookupTable::New(); //m_LUT->SetTableRange( 0, 255 ); //m_LUT->SetNumberOfColors( 255 ); //m_LUT->SetRampToLinear (); //m_LUT->Build(); } mitk::PolyDataGLMapper2D::~PolyDataGLMapper2D() {} diff --git a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp index 8adf9d85ad..b9464cab0c 100644 --- a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp @@ -1,544 +1,544 @@ /*=================================================================== 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 "mitkSurfaceGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkSurface.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkVtkScalarModeProperty.h" #include "mitkAbstractTransformGeometry.h" #include "mitkLookupTableProperty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::SurfaceGLMapper2D::SurfaceGLMapper2D() : m_Plane( vtkPlane::New() ), m_Cutter( vtkCutter::New() ), m_LUT( vtkLookupTable::New() ), m_PointLocator( vtkPKdTree::New() ), m_Stripper( vtkStripper::New() ), m_DrawNormals(false), m_FrontNormalLengthInPixels(10.0), m_BackNormalLengthInPixels(10.0) { // default for normals on front side = green m_FrontSideColor[0] = 0.0; m_FrontSideColor[1] = 1.0; m_FrontSideColor[2] = 0.0; m_FrontSideColor[3] = 1.0; // default for normals on back side = red m_BackSideColor[0] = 1.0; m_BackSideColor[1] = 0.0; m_BackSideColor[2] = 0.0; m_BackSideColor[3] = 1.0; // default for line color = yellow m_LineColor[0] = 1.0; m_LineColor[1] = 1.0; m_LineColor[2] = 0.0; m_LineColor[3] = 1.0; m_Cutter->SetCutFunction(m_Plane); m_Cutter->GenerateValues(1,0,1); m_LUT->SetTableRange(0,255); m_LUT->SetNumberOfColors(255); m_LUT->SetRampToLinear(); m_LUT->Build(); } mitk::SurfaceGLMapper2D::~SurfaceGLMapper2D() { m_Plane->Delete(); m_Cutter->Delete(); m_LUT->Delete(); m_PointLocator->Delete(); m_Stripper->Delete(); } const mitk::Surface *mitk::SurfaceGLMapper2D::GetInput(void) { if(m_Surface.IsNotNull()) return m_Surface; return static_cast ( GetDataNode()->GetData() ); } void mitk::SurfaceGLMapper2D::SetDataNode( mitk::DataNode* node ) { Superclass::SetDataNode( node ); bool useCellData; if (dynamic_cast(node->GetProperty("deprecated useCellDataForColouring")) == NULL) useCellData = false; else useCellData = dynamic_cast(node->GetProperty("deprecated useCellDataForColouring"))->GetValue(); if (!useCellData) { // search min/max point scalars over all time steps - vtkFloatingPointType dataRange[2] = {0,0}; - vtkFloatingPointType range[2]; + double dataRange[2] = {0,0}; + double range[2]; Surface::Pointer input = const_cast< Surface* >(dynamic_cast( this->GetDataNode()->GetData() )); if(input.IsNull()) return; const TimeGeometry::Pointer inputTimeGeometry = input->GetTimeGeometry(); if(( inputTimeGeometry.IsNull() ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) ) return; for (unsigned int timestep=0; timestepCountTimeSteps(); timestep++) { vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep ); if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) continue; vtkDataArray *vpointscalars = vtkpolydata->GetPointData()->GetScalars(); if (vpointscalars) { vpointscalars->GetRange( range, 0 ); if (dataRange[0]==0 && dataRange[1]==0) { dataRange[0] = range[0]; dataRange[1] = range[1]; } else { if (range[0] < dataRange[0]) dataRange[0] = range[0]; if (range[1] > dataRange[1]) dataRange[1] = range[1]; } } } if (dataRange[1] - dataRange[0] > 0) { m_LUT->SetTableRange( dataRange ); m_LUT->Build(); } } } void mitk::SurfaceGLMapper2D::Paint(mitk::BaseRenderer * renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) return; Surface::Pointer input = const_cast(this->GetInput()); if(input.IsNull()) return; // // get the TimeGeometry of the input object // const TimeGeometry* inputTimeGeometry = input->GetTimeGeometry(); if(( inputTimeGeometry == NULL ) || ( inputTimeGeometry->CountTimeSteps() == 0 ) ) return; if (dynamic_cast(this->GetDataNode()->GetProperty("line width")) == NULL) m_LineWidth = 1; else m_LineWidth = dynamic_cast(this->GetDataNode()->GetProperty("line width"))->GetValue(); // // get the world time // Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry.IsNotNull() ); ScalarType time = worldGeometry->GetTimeBounds()[ 0 ]; int timestep=0; if( time > ScalarTypeNumericTraits::NonpositiveMin() ) timestep = inputTimeGeometry->TimePointToTimeStep( time ); // int timestep = this->GetTimestep(); if( inputTimeGeometry->IsValidTimeStep( timestep ) == false ) return; vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep ); if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) return; PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast(worldGeometry.GetPointer()); //apply color and opacity read from the PropertyList this->ApplyAllProperties(renderer); if (m_DrawNormals) { m_PointLocator->SetDataSet( vtkpolydata ); m_PointLocator->BuildLocatorFromPoints( vtkpolydata->GetPoints() ); } if(vtkpolydata!=NULL) { Point3D point; Vector3D normal; //Check if Lookup-Table is already given, else use standard one. - vtkFloatingPointType* scalarLimits = m_LUT->GetTableRange(); - vtkFloatingPointType scalarsMin = scalarLimits[0], scalarsMax = scalarLimits[1]; + double* scalarLimits = m_LUT->GetTableRange(); + double scalarsMin = scalarLimits[0], scalarsMax = scalarLimits[1]; vtkLookupTable *lut;// = vtkLookupTable::New(); LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull() ) { lut = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); // check if the scalar range has been changed, e.g. manually, for the data tree node, and rebuild the LUT if necessary. double* oldRange = lut->GetTableRange(); if( oldRange[0] != scalarsMin || oldRange[1] != scalarsMax ) { lut->SetTableRange(scalarsMin, scalarsMax); lut->Build(); } } else { lut = m_LUT; } vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(timestep); if(worldPlaneGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=worldPlaneGeometry->GetOrigin(); normal=worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform((vtkAbstractTransform*)NULL); } else { AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); if(worldAbstractGeometry.IsNotNull()) { AbstractTransformGeometry::ConstPointer surfaceAbstractGeometry = dynamic_cast(input->GetTimeGeometry()->GetGeometryForTimeStep(0).GetPointer()); if(surfaceAbstractGeometry.IsNotNull()) //@todo substitude by operator== after implementation, see bug id 28 { PaintCells(renderer, vtkpolydata, worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut); return; } else { //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "flat plane" into a "curved plane"? return; // 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; } - vtkFloatingPointType vp[3], vnormal[3]; + double vp[3], vnormal[3]; vnl2vtk(point.GetVnlVector(), vp); vnl2vtk(normal.GetVnlVector(), 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. vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); inversetransform->TransformPoint(vp, vp); inversetransform->TransformNormalAtPoint(vp, vnormal, vnormal); m_Plane->SetOrigin(vp); m_Plane->SetNormal(vnormal); //set data into cutter m_Cutter->SetInput(vtkpolydata); m_Cutter->Update(); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); if (m_DrawNormals) { m_Stripper->SetInput( m_Cutter->GetOutput() ); // calculate the cut m_Stripper->Update(); PaintCells(renderer, m_Stripper->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata); } else { PaintCells(renderer, m_Cutter->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata); } } } void mitk::SurfaceGLMapper2D::PaintCells(mitk::BaseRenderer* renderer, vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform * vtktransform, vtkLookupTable *lut, vtkPolyData* original3DObject) { // deprecated settings bool usePointData = false; bool useCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", useCellData); bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); if(scalarVisibility) { VtkScalarModeProperty* scalarMode; if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) { if( (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA) || (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT) ) { usePointData = true; } if(scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA) { useCellData = true; } } else { usePointData = true; } } vtkPoints *vpoints = contour->GetPoints(); vtkDataArray *vpointscalars = contour->GetPointData()->GetScalars(); vtkCellArray *vlines = contour->GetLines(); vtkDataArray* vcellscalars = contour->GetCellData()->GetScalars(); Point3D p; Point2D p2d, last; int i, j; int numberOfLines = vlines->GetNumberOfCells(); glLineWidth( m_LineWidth ); glBegin (GL_LINES); glColor4fv(m_LineColor); double distanceSinceLastNormal(0.0); vlines->InitTraversal(); for(i=0;iGetNextCell(cellSize, cell); vpoints->GetPoint(cell[0], 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 world coordinates) to display coordinates (units ) displayGeometry->WorldToDisplay(p2d, p2d); last=p2d; for(j=1; jGetPoint(cell[j], vp); Point3D originalPoint; vtk2itk(vp, originalPoint); //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 world coordinates) to display coordinates (units ) displayGeometry->WorldToDisplay(p2d, p2d); - vtkFloatingPointType color[3]; + double color[3]; if (useCellData && vcellscalars != NULL ) { // color each cell according to cell data lut->GetColor( vcellscalars->GetComponent(i,0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(last[0], last[1]); glVertex2f(p2d[0], p2d[1]); } else if (usePointData && vpointscalars != NULL ) { lut->GetColor( vpointscalars->GetComponent(cell[j-1],0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(last[0], last[1]); lut->GetColor( vpointscalars->GetComponent(cell[j],0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(p2d[0], p2d[1]); } else { glVertex2f(last[0], last[1]); glVertex2f(p2d[0], p2d[1]); // draw normals ? if (m_DrawNormals && original3DObject) { distanceSinceLastNormal += sqrt((p2d[0]-last[0])*(p2d[0]-last[0]) + (p2d[1]-last[1])*(p2d[1]-last[1])); if (distanceSinceLastNormal >= 5.0) { distanceSinceLastNormal = 0.0; vtkPointData* pointData = original3DObject->GetPointData(); if (!pointData) break; vtkDataArray* normalsArray = pointData->GetNormals(); if (!normalsArray) break; // find 3D point closest to the currently drawn point double distance(0.0); vtkIdType closestPointId = m_PointLocator->FindClosestPoint(originalPoint[0], originalPoint[1], originalPoint[2], distance); if (closestPointId >= 0) { // find normal of 3D object at this 3D point double* normal = normalsArray->GetTuple3(closestPointId); double transformedNormal[3]; vtktransform->TransformNormal(normal, transformedNormal); Vector3D normalITK; vtk2itk(transformedNormal, normalITK); normalITK.Normalize(); // calculate a point (point from the cut 3D object) + (normal vector of closest point) Point3D tip3D = p + normalITK; // map this point into our 2D coordinate system Point2D tip2D; worldGeometry->Map(tip3D, tip2D); displayGeometry->WorldToDisplay(tip2D, tip2D); // calculate 2D vector from point to point+normal, normalize it to standard length Vector2D tipVectorGLFront = tip2D - p2d; tipVectorGLFront.Normalize(); tipVectorGLFront *= m_FrontNormalLengthInPixels; Vector2D tipVectorGLBack = p2d - tip2D; tipVectorGLBack.Normalize(); tipVectorGLBack *= m_BackNormalLengthInPixels; Point2D tipPoint2D = p2d + tipVectorGLFront; Point2D backTipPoint2D = p2d + tipVectorGLBack; // draw normalized mapped normal vector glColor4f(m_BackSideColor[0], m_BackSideColor[1], m_BackSideColor[2], m_BackSideColor[3]); // red backside glVertex2f(p2d[0], p2d[1]); glVertex2f(tipPoint2D[0], tipPoint2D[1]); glColor4f(m_FrontSideColor[0], m_FrontSideColor[1], m_FrontSideColor[2], m_FrontSideColor[3]); // green backside glVertex2f(p2d[0], p2d[1]); glVertex2f(backTipPoint2D[0], backTipPoint2D[1]); glColor4fv(m_LineColor); // back to line color } } } } last=p2d; } } glEnd(); glLineWidth(1.0); } void mitk::SurfaceGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", IntProperty::New(2), renderer, overwrite ); node->AddProperty( "scalar mode", VtkScalarModeProperty::New(), renderer, overwrite ); node->AddProperty( "draw normals 2D", BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "invert normals", BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "front color", ColorProperty::New(0.0, 1.0, 0.0), renderer, overwrite ); node->AddProperty( "back color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite ); node->AddProperty( "front normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); node->AddProperty( "back normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); node->AddProperty( "layer", mitk::IntProperty::New(100), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::SurfaceGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) { ApplyColorAndOpacityProperties(renderer); DataNode * node = GetDataNode(); if(node == NULL) { return; } node->GetBoolProperty("draw normals 2D", m_DrawNormals, renderer); // check for color and opacity properties, use it for rendering if they exists node->GetColor(m_LineColor, renderer, "color"); node->GetOpacity(m_LineColor[3], renderer, "opacity"); bool invertNormals(false); node->GetBoolProperty("invert normals", invertNormals, renderer); if (!invertNormals) { node->GetColor(m_FrontSideColor, renderer, "front color"); node->GetOpacity(m_FrontSideColor[3], renderer, "opacity"); node->GetColor(m_BackSideColor, renderer, "back color"); node->GetOpacity(m_BackSideColor[3], renderer, "opacity"); node->GetFloatProperty( "front normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); node->GetFloatProperty( "back normal lenth (px)", m_BackNormalLengthInPixels, renderer ); } else { node->GetColor(m_FrontSideColor, renderer, "back color"); node->GetOpacity(m_FrontSideColor[3], renderer, "opacity"); node->GetColor(m_BackSideColor, renderer, "front color"); node->GetOpacity(m_BackSideColor[3], renderer, "opacity"); node->GetFloatProperty( "back normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); node->GetFloatProperty( "front normal lenth (px)", m_BackNormalLengthInPixels, renderer ); } } diff --git a/Core/Code/Rendering/mitkVtkPropRenderer.h b/Core/Code/Rendering/mitkVtkPropRenderer.h index d37cb46627..da0ed9642f 100644 --- a/Core/Code/Rendering/mitkVtkPropRenderer.h +++ b/Core/Code/Rendering/mitkVtkPropRenderer.h @@ -1,260 +1,260 @@ /*=================================================================== 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 MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D #define MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D #include #include "mitkBaseRenderer.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include #include #include class vtkRenderWindow; class vtkLight; class vtkLightKit; class vtkWorldPointPicker; class vtkPointPicker; class vtkCellPicker; class vtkTextActor; class vtkTextProperty; class vtkAssemblyPath; namespace mitk { class Mapper; /*! \brief VtkPropRenderer VtkPropRenderer organizes the MITK rendering process. The MITK rendering process is completely integrated into the VTK rendering pipeline. The vtkMitkRenderProp is a custom vtkProp derived class, which implements the rendering interface between MITK and VTK. It redirects render() calls to the VtkPropRenderer, which is responsible for rendering of the datatreenodes. VtkPropRenderer replaces the old OpenGLRenderer. \sa rendering \ingroup rendering */ class MITK_CORE_EXPORT VtkPropRenderer : public BaseRenderer { // Workaround for Displaylistbug private: bool didCount; void checkState(); // Workaround END public: mitkClassMacro(VtkPropRenderer,BaseRenderer); mitkNewMacro3Param(VtkPropRenderer, const char*, vtkRenderWindow *, mitk::RenderingManager* ); typedef std::map MappersMapType; // Render - called by vtkMitkRenderProp, returns the number of props rendered enum RenderType{Opaque,Translucent,Overlay,Volumetric}; int Render(RenderType type); /** \brief This methods contains all method neceassary before a VTK Render() call */ virtual void PrepareRender(); // Active current renderwindow virtual void MakeCurrent(); virtual void SetDataStorage( mitk::DataStorage* storage ); ///< set the datastorage that will be used for rendering virtual void InitRenderer(vtkRenderWindow* renderwindow); virtual void Update(mitk::DataNode* datatreenode); virtual void SetMapperID(const MapperSlotId mapperId); // Size virtual void InitSize(int w, int h); virtual void Resize(int w, int h); // Picking enum PickingMode{ WorldPointPicking, PointPicking, CellPicking}; /** \brief Set the picking mode. This method is used to set the picking mode for 3D object picking. The user can select one of the three options WorldPointPicking, PointPicking and CellPicking. The first option uses the zBuffer from graphics rendering, the second uses the 3D points from the closest surface mesh, and the third option uses the cells of that mesh. The last option is the slowest, the first one the fastest. However, the first option cannot use transparent data object and the tolerance of the picked position to the selected point should be considered. PointPicking also need a tolerance around the picking position to select the closest point in the mesh. The CellPicker performs very well, if the foreground surface part (i.e. the surfacepart that is closest to the scene's cameras) needs to be picked. */ itkSetEnumMacro( PickingMode, PickingMode ); itkGetEnumMacro( PickingMode, PickingMode ); virtual void PickWorldPoint(const Point2D& displayPoint, Point3D& worldPoint) const; virtual mitk::DataNode *PickObject( const Point2D &displayPosition, Point3D &worldPosition ) const; // Simple text rendering method int WriteSimpleText(std::string text, double posX, double posY, double color1 = 0.0, double color2 = 1.0, double color3 = 0.0, float opacity = 1.0); vtkTextProperty * GetTextLabelProperty(int text_id); // Initialization / geometry handling /** This method calculates the bounds of the DataStorage (if it contains any * valid data), creates a geometry from these bounds and sets it as world * geometry of the renderer. * * Call this method to re-initialize the renderer to the current DataStorage * (e.g. after loading an additional dataset), to ensure that the view is * aligned correctly. */ virtual bool SetWorldGeometryToDataStorageBounds(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ void InitPathTraversal(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ vtkAssemblyPath* GetNextPath(); const vtkWorldPointPicker *GetWorldPointPicker() const; const vtkPointPicker *GetPointPicker() const; const vtkCellPicker *GetCellPicker() const; /** * \brief Release vtk-based graphics resources. Called by * vtkMitkRenderProp::ReleaseGraphicsResources. */ virtual void ReleaseGraphicsResources(vtkWindow *renWin); MappersMapType GetMappersMap() const; static bool useImmediateModeRendering(); protected: VtkPropRenderer( const char* name = "VtkPropRenderer", vtkRenderWindow * renWin = NULL, mitk::RenderingManager* rm = NULL ); virtual ~VtkPropRenderer(); virtual void Update(); /** \brief Convert display geometry coordinates to VTK coordinates. For use within WriteSimpleText: the input is display geometry coordinates but the text actor needs positions that fit in a specified viewport. Conversion is done in this method. */ mitk::Point2D TransformOpenGLPointToViewport( mitk::Point2D point ); private: /** \brief This method sets up the camera on the actor (e.g. an image) of all * 2D vtkRenderWindows. The view is centered; zooming and panning of VTK are called inside. * * \image html ImageMapperdisplayGeometry.png * * Similar to the textured plane of an image * (cf. void mitkImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, - * vtkFloatingPointType planeBounds[6])), the mitkDisplayGeometry defines a view plane (or + * double planeBounds[6])), the mitkDisplayGeometry defines a view plane (or * projection plane). This plane is used to set the camera parameters. The view plane * center (VC) is important for camera positioning (cf. the image above). * * The following figure shows the combination of the textured plane and the view plane. * * \image html cameraPositioning.png * * The view plane center (VC) is the center of the textured plane (C) and the focal point * (FP) at the same time. The FP defines the direction the camera faces. Since * the textured plane is always in the XY-plane and orthographic projection is applied, the * distance between camera and plane is theoretically irrelevant (because in the orthographic * projection the center of projection is at infinity and the size of objects depends only on * a scaling parameter). As a consequence, the direction of projection (DOP) is (0; 0; -1). * The camera up vector is always defined as (0; 1; 0). * * \warning Due to a VTK clipping bug the distance between textured plane and camera is really huge. * Otherwise, VTK would clip off some slices. Same applies for the clipping range size. * * \note The camera position is defined through the mitkDisplayGeometry. * This facilitates zooming and panning, because the display * geometry changes and the textured plane does not. * * \image html scaling.png * * The textured plane is scaled to fill the render window via * camera->SetParallelScale( imageHeightInMM / 2). In the orthographic projection all extends, * angles and sizes are preserved. Therefore, the image is scaled by one parameter which defines * the size of the rendered image. A higher value will result in smaller images. In order to render * just the whole image, the scale is set to half of the image height in worldcoordinates * (cf. the picture above). * * For zooming purposes, a factor is computed as follows: * factor = image height / display height (in worldcoordinates). * When the display geometry gets smaller (zoom in), the factor becomes bigger. When the display * geometry gets bigger (zoom out), the factor becomes smaller. The used VTK method * camera->Zoom( factor ) also works with an inverse scale. */ void AdjustCameraToScene(); // switch between orthogonal opengl projection (2D rendering via mitk::GLMapper2D) and perspective projection (3D rendering) void Enable2DOpenGL(); void Disable2DOpenGL(); // prepare all mitk::mappers for rendering void PrepareMapperQueue(); /** \brief Set parallel projection, remove the interactor and the lights of VTK. */ bool Initialize2DvtkCamera(); bool m_InitNeeded; bool m_ResizeNeeded; bool m_VtkMapperPresent; MapperSlotId m_CameraInitializedForMapperID; // Picking vtkWorldPointPicker * m_WorldPointPicker; vtkPointPicker * m_PointPicker; vtkCellPicker * m_CellPicker; PickingMode m_PickingMode; // Explicit use of SmartPointer to avoid circular #includes itk::SmartPointer< mitk::Mapper > m_CurrentWorldGeometry2DMapper; vtkLightKit* m_LightKit; // sorted list of mappers MappersMapType m_MappersMap; // rendering of text vtkRenderer * m_TextRenderer; typedef std::map TextMapType; TextMapType m_TextCollection; DataStorage::SetOfObjects::ConstPointer m_PickingObjects; DataStorage::SetOfObjects::const_iterator m_PickingObjectsIterator; }; } // namespace mitk #endif /* MITKVtkPropRenderer_H_HEADER_INCLUDED_C1C29F6D */ diff --git a/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp b/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp index 8fc946cc36..3874b9995c 100644 --- a/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp +++ b/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp @@ -1,600 +1,600 @@ /*=================================================================== 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 "vtkMitkLevelWindowFilter.h" #include #include #include #include #include "vtkObjectFactory.h" //used for acos etc. #include //used for PI #include #include static const double PI = itk::Math::pi; vtkStandardNewMacro(vtkMitkLevelWindowFilter); vtkMitkLevelWindowFilter::vtkMitkLevelWindowFilter(): m_LookupTable(NULL), m_MinOpacity(0.0),m_MaxOpacity(255.0) { //MITK_INFO << "mitk level/window filter uses " << GetNumberOfThreads() << " thread(s)"; } vtkMitkLevelWindowFilter::~vtkMitkLevelWindowFilter() { } unsigned long int vtkMitkLevelWindowFilter::GetMTime() { unsigned long mTime=this->vtkObject::GetMTime(); unsigned long time; if ( this->m_LookupTable != NULL ) { time = this->m_LookupTable->GetMTime(); mTime = ( time > mTime ? time : mTime ); } return mTime; } void vtkMitkLevelWindowFilter::SetLookupTable(vtkScalarsToColors *lookupTable) { if (m_LookupTable != lookupTable) { m_LookupTable = lookupTable; this->Modified(); } } vtkScalarsToColors* vtkMitkLevelWindowFilter::GetLookupTable() { return m_LookupTable; } //This code was copied from the iil. The template works only for float and double. //Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (R,G,B) to (H,S,I). // Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002. template void RGBtoHSI(T* RGB, T* HSI) { T R = RGB[0], G = RGB[1], B = RGB[2], nR = (R<0?0:(R>255?255:R))/255, nG = (G<0?0:(G>255?255:G))/255, nB = (B<0?0:(B>255?255:B))/255, m = nR0) H = (nB<=nG)?theta:360-theta; if (sum>0) S = 1 - 3/sum*m; I = sum/3; HSI[0] = (T)H; HSI[1] = (T)S; HSI[2] = (T)I; } //This code was copied from the iil. The template works only for float and double. //Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (H,S,I) to (R,G,B). template void HSItoRGB(T* HSI, T* RGB) { T H = (T)HSI[0], S = (T)HSI[1], I = (T)HSI[2], a = I*(1-S), R = 0, G = 0, B = 0; if (H<120) { B = a; R = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); G = 3*I-(R+B); } else if (H<240) { H-=120; R = a; G = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); B = 3*I-(R+G); } else { H-=240; G = a; B = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); R = 3*I-(G+B); } R*=255; G*=255; B*=255; RGB[0] = (T)(R<0?0:(R>255?255:R)); RGB[1] = (T)(G<0?0:(G>255?255:G)); RGB[2] = (T)(B<0?0:(B>255?255:B)); } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnRGBA(vtkMitkLevelWindowFilter* self, vtkImageData* inData, vtkImageData* outData, int outExt[6], - vtkFloatingPointType* clippingBounds, + double* clippingBounds, T*) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkLookupTable* lookupTable; const int maxC = inData->GetNumberOfScalarComponents(); double tableRange[2]; lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); //parameters for RGB level window double scale = (tableRange[1] -tableRange[0] > 0 ? 255.0 / (tableRange[1] - tableRange[0]) : 0.0); double bias = tableRange[0] * scale; //parameters for opaque level window double scaleOpac = (self->GetMaxOpacity() -self->GetMinOpacity() > 0 ? 255.0 / (self->GetMaxOpacity() - self->GetMinOpacity()) : 0.0); double biasOpac = self->GetMinOpacity() * scaleOpac; int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { T* inputSI = inputIt.BeginSpan(); T* outputSI = outputIt.BeginSpan(); T* outputSIEnd = outputIt.EndSpan(); if( y >= clippingBounds[2] && y < clippingBounds[3] ) { int x = outExt[0]; while (outputSI != outputSIEnd) { if ( x >= clippingBounds[0] && x < clippingBounds[1]) { double rgb[3], alpha, hsi[3]; // level/window mechanism for intensity in HSI space rgb[0] = static_cast(*inputSI); inputSI++; rgb[1] = static_cast(*inputSI); inputSI++; rgb[2] = static_cast(*inputSI); inputSI++; RGBtoHSI(rgb,hsi); hsi[2] = hsi[2] * 255.0 * scale - bias; hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2])); hsi[2] /= 255.0; HSItoRGB(hsi,rgb); *outputSI = static_cast(rgb[0]); outputSI++; *outputSI = static_cast(rgb[1]); outputSI++; *outputSI = static_cast(rgb[2]); outputSI++; unsigned char finalAlpha = 255; //RGBA case if(maxC >= 4) { // level/window mechanism for opacity alpha = static_cast(*inputSI); inputSI++; alpha = alpha * scaleOpac - biasOpac; if(alpha > 255.0) { alpha = 255.0; } else if(alpha < 0.0) { alpha = 0.0; } finalAlpha = static_cast(alpha); for( int c = 4; c < maxC; c++ ) inputSI++; } *outputSI = static_cast(finalAlpha); outputSI++; } else { inputSI+=maxC; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } x++; } } else { while (outputSI != outputSIEnd) { *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsFast(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); double tableRange[2]; // access vtkLookupTable vtkLookupTable* lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); // access elements of the vtkLookupTable int * realLookupTable = reinterpret_cast(lookupTable->GetTable()->GetPointer(0)); int maxIndex = lookupTable->GetNumberOfColors() - 1; float scale = (tableRange[1] -tableRange[0] > 0 ? (maxIndex + 1) / (tableRange[1] - tableRange[0]) : 0.0); // ensuring that starting point is zero float bias = - tableRange[0] * scale; // due to later conversion to int for rounding bias += 0.5f; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); T* inputSI = inputIt.BeginSpan(); while (outputSI != outputSIEnd) { // map to an index int idx = static_cast( *inputSI * scale + bias ); if (idx < 0) idx = 0; else if (idx > maxIndex) idx = maxIndex; * reinterpret_cast(outputSI) = realLookupTable[idx]; inputSI++; outputSI+=4; } inputIt.NextSpan(); outputIt.NextSpan(); } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalars(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], - vtkFloatingPointType* clippingBounds, + double* clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkScalarsToColors* lookupTable = self->GetLookupTable(); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if( y >= clippingBounds[2] && y < clippingBounds[3] ) { T* inputSI = inputIt.BeginSpan(); int x= outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if ( x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying lookuptable - copy the 4 (RGBA) chars as a single int *reinterpret_cast(outputSI) = *reinterpret_cast(lookupTable->MapValue( grayValue )); } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI+=4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI+=4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsCTF(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], - vtkFloatingPointType* clippingBounds, + double* clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkColorTransferFunction* lookupTable = dynamic_cast(self->GetLookupTable()); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if( y >= clippingBounds[2] && y < clippingBounds[3] ) { T* inputSI = inputIt.BeginSpan(); int x= outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if ( x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying directly colortransferfunction // because vtkColorTransferFunction::MapValue is not threadsafe double rgb[3]; lookupTable->GetColor( grayValue, rgb ); outputSI[0] = static_cast(255.0*rgb[0] + 0.5); outputSI[1] = static_cast(255.0*rgb[1] + 0.5); outputSI[2] = static_cast(255.0*rgb[2] + 0.5); outputSI[3] = 255; } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI+=4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI+=4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } void vtkMitkLevelWindowFilter::ExecuteInformation() { vtkImageData *input = this->GetInput(); vtkImageData *output = this->GetOutput(); if (!input) { vtkErrorMacro(<< "Input not set."); return; } output->CopyTypeSpecificInformation( input ); // TODO make output RGBA output->SetScalarTypeToUnsignedChar(); output->SetNumberOfScalarComponents(4); int extent[6]; input->GetWholeExtent(extent); output->SetExtent(extent); output->SetWholeExtent(extent); output->SetUpdateExtent(extent); output->AllocateScalars(); } //Method to run the filter in different threads. void vtkMitkLevelWindowFilter::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, int extent[6], int /*id*/) { if(inData->GetNumberOfScalarComponents() > 2) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnRGBA( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { bool dontClip = extent[2] >= m_ClippingBounds[2] && extent[3] <= m_ClippingBounds[3] && extent[0] >= m_ClippingBounds[0] && extent[1] <= m_ClippingBounds[1]; if(this->GetLookupTable()) this->GetLookupTable()->Build(); vtkLookupTable *vlt = dynamic_cast(this->GetLookupTable()); vtkColorTransferFunction *ctf = dynamic_cast(this->GetLookupTable()); bool linearLookupTable = vlt && vlt->GetScale() == VTK_SCALE_LINEAR; bool useFast = dontClip && linearLookupTable; if(ctf) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsCTF( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else if(useFast) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsFast( this, inData, outData, extent, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalars( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } } } void vtkMitkLevelWindowFilter::ExecuteInformation( vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) { } void vtkMitkLevelWindowFilter::SetMinOpacity(double minOpacity) { m_MinOpacity = minOpacity; } inline double vtkMitkLevelWindowFilter::GetMinOpacity() const { return m_MinOpacity; } void vtkMitkLevelWindowFilter::SetMaxOpacity(double maxOpacity) { m_MaxOpacity = maxOpacity; } inline double vtkMitkLevelWindowFilter::GetMaxOpacity() const { return m_MaxOpacity; } -void vtkMitkLevelWindowFilter::SetClippingBounds(vtkFloatingPointType* bounds) // TODO does vtkFloatingPointType[4] work?? +void vtkMitkLevelWindowFilter::SetClippingBounds(double* bounds) // TODO does double[4] work?? { for (unsigned int i = 0 ; i < 4; ++i) m_ClippingBounds[i] = bounds[i]; } diff --git a/Core/Code/Rendering/vtkMitkLevelWindowFilter.h b/Core/Code/Rendering/vtkMitkLevelWindowFilter.h index 84279907aa..3d0ccb9e1d 100644 --- a/Core/Code/Rendering/vtkMitkLevelWindowFilter.h +++ b/Core/Code/Rendering/vtkMitkLevelWindowFilter.h @@ -1,92 +1,92 @@ /*=================================================================== 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 __vtkMitkLevelWindowFilter_h #define __vtkMitkLevelWindowFilter_h class vtkScalarsToColors; #include #include #include /** Documentation * \brief Applies the grayvalue or color/opacity level window to scalar or RGB(A) images. * * This filter is used to apply the color level window to RGB images (e.g. * diffusion tensor images). Therefore, the RGB channels are converted to * the HSI color space, where the level window can be applied. Afterwards, * the HSI values transformed back to the RGB space. * * The filter is also able to apply an opacity level window to RGBA images. * * \ingroup Renderer */ class MITK_CORE_EXPORT vtkMitkLevelWindowFilter : public vtkImageToImageFilter { public: vtkTypeMacro(vtkMitkLevelWindowFilter,vtkImageToImageFilter); static vtkMitkLevelWindowFilter *New(); virtual unsigned long int GetMTime(); /** \brief Get the lookup table for the RGB level window */ vtkScalarsToColors* GetLookupTable(); /** \brief Set the lookup table for the RGB level window */ void SetLookupTable(vtkScalarsToColors *lookupTable); /** \brief Get/Set the lower window opacity for the alpha level window */ void SetMinOpacity(double minOpacity); inline double GetMinOpacity() const; /** \brief Get/Set the upper window opacity for the alpha level window */ void SetMaxOpacity(double maxOpacity); inline double GetMaxOpacity() const; /** \brief Set clipping bounds for the opaque part of the resliced 2d image */ - void SetClippingBounds(vtkFloatingPointType*); + void SetClippingBounds(double*); /** Default constructor. */ vtkMitkLevelWindowFilter(); /** Default deconstructor. */ ~vtkMitkLevelWindowFilter(); protected: /** \brief Method for threaded execution of the filter. * \param *inData: The input. * \param *outData: The output of the filter. * \param extent: Specifies the region of the image to be updated inside this thread. * It is a six-component array of the form (xmin, xmax, ymin, ymax, zmin, zmax). * \param id: The thread id. */ void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,int extent[6], int id); /** Standard VTK filter method to apply the filter. See VTK documentation.*/ void ExecuteInformation(); /** Standard VTK filter method to apply the filter. See VTK documentation. Not used at the moment.*/ void ExecuteInformation(vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)); private: /** m_LookupTable contains the lookup table for the RGB level window.*/ vtkScalarsToColors* m_LookupTable; /** m_MinOpacity contains the lower bound for the alpha level window.*/ double m_MinOpacity; /** m_MaxOpacity contains the upper bound for the alpha level window.*/ double m_MaxOpacity; - vtkFloatingPointType m_ClippingBounds[4]; + double m_ClippingBounds[4]; }; #endif diff --git a/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp b/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp index db17edeedc..dbd63895d4 100644 --- a/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp +++ b/Core/Code/Testing/mitkGeometryDataToSurfaceFilterTest.cpp @@ -1,253 +1,253 @@ /*=================================================================== 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 "mitkGeometry2DDataToSurfaceFilter.h" #include "mitkSurface.h" #include "mitkPlaneGeometry.h" #include "mitkGeometry2DData.h" #include "vtkPolyData.h" #include template int testExpectedIndexBoundingBox(mitk::Geometry3D* geometry, TScalarType expectedIndexBounds[6]) { mitk::BoundingBox* bb = const_cast(geometry->GetBoundingBox()); mitk::BoundingBox::BoundsArrayType bounds = bb->GetBounds(); int i; for(i=0;i<6;++i) { if( mitk::Equal(bounds[i], expectedIndexBounds[i]) == false) { std::cout<<"[FAILED]"< int testExpectedAxisParallelBoundingBox(mitk::Geometry3D* geometry, TScalarType expectedAxisParallelBounds[6]) { mitk::BoundingBox::Pointer bb = geometry->CalculateBoundingBoxRelativeToTransform(NULL); mitk::BoundingBox::BoundsArrayType bounds = bb->GetBounds(); int i; for(i=0;i<6;++i) { if( mitk::Equal(bounds[i], expectedAxisParallelBounds[i]) == false) { std::cout<<"[FAILED]"<GetVtkPolyData() == NULL) || (surface->GetVtkPolyData()->GetNumberOfPoints() == 0 )) { std::cout<<"[FAILED]"<GetVtkPolyData(); polys->ComputeBounds(); polys->GetBounds( bounds ); int i; if(expectIdentityTransform == false) { mitk::Geometry2D::Pointer geometry = mitk::Geometry2D::New(); geometry->SetFloatBounds(bounds); geometry->SetIndexToWorldTransform(surface->GetGeometry()->GetIndexToWorldTransform()); mitk::BoundingBox::BoundsArrayType bb = const_cast(geometry->GetBoundingBox())->GetBounds(); for(i=0;i<6;++i) bounds[i]=bb[i]; } std::cout << " Testing GetBoundingBox() "; if((result=testExpectedIndexBoundingBox(surface->GetGeometry(), bounds)) != EXIT_SUCCESS) { std::cout<<"[FAILED]"<GetOutput()->SetRequestedRegionToLargestPossibleRegion(); std::cout<<"[PASSED]"<UpdateOutputInformation(); std::cout<<"[PASSED]"<GetOutput()->GetGeometry(), expectedIndexBounds)) != EXIT_SUCCESS) { return result; } std::cout << "Testing correctness of axis-parallel bounding-box after UpdateOutputInformation(): "; if((result=testExpectedAxisParallelBoundingBox(geometryToSurfaceFilter->GetOutput()->GetGeometry(), expectedAxisParallelBounds)) != EXIT_SUCCESS) { return result; } std::cout << "Testing Update(): "; geometryToSurfaceFilter->Update(); std::cout<<"[PASSED]"<GetOutput()->GetGeometry(), expectedIndexBounds)) != EXIT_SUCCESS) { return result; } std::cout << "Testing correctness of axis-parallel bounding-box after UpdateOutputInformation(): "; if((result=testExpectedAxisParallelBoundingBox(geometryToSurfaceFilter->GetOutput()->GetGeometry(), expectedAxisParallelBounds)) != EXIT_SUCCESS) { return result; } std::cout << "Testing bounding-box consistency: "<GetOutput(), expectIdentityTransform)) != EXIT_SUCCESS) { std::cout<<"[FAILED]"<InitializeStandardPlane(50, 100); mitk::FillVector3D(origin, 1.0, 2.0, 3.0); plane->SetOrigin(origin); mitk::Geometry2DData::Pointer geometryData = mitk::Geometry2DData::New(); geometryData->SetGeometry2D(plane); std::cout << "Testing SetInput(): "; geometryToSurfaceFilter->SetInput(geometryData); std::cout<<"[PASSED]"<GetInput() != geometryData ) { std::cout<<"[FAILED]"<GetPlaceByGeometry() != false ) { std::cout<<"[FAILED]"<SetPlaceByGeometry(true); if (geometryToSurfaceFilter->GetPlaceByGeometry() != true ) { std::cout<<"[FAILED]"<InsertElement( 0, bbMin ); pointsContainer->InsertElement( 1, bbMax ); boundingBox->SetPoints( pointsContainer ); boundingBox->ComputeBoundingBox(); geometryToSurfaceFilter->SetPlaceByGeometry( true ); geometryToSurfaceFilter->SetBoundingBox( boundingBox ); mitk::ScalarType expectedIndexBoundsWithBB[6] = {9.0, 39.0, 8.0, 88.0, 0.0, 0.0}; mitk::ScalarType expectedAxisParallelBoundsWithBB[6] = {10.0, 40.0, 10.0, 90.0, 3.0, 3.0}; if((result=testGeometryDataToSurfaceFilter(geometryToSurfaceFilter, expectedIndexBoundsWithBB, expectedAxisParallelBoundsWithBB, true)) != EXIT_SUCCESS) { return result; } std::cout<<"[TEST DONE]"< #include #include /** * Simple example for a test for the () class "ClassName". * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (). */ class MaterialTest { public: mitk::Material::Pointer myMP; MaterialTest(){myMP = NULL;} void testConstructor() { myMP = mitk::Material::New(); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") } void testConstructorWithColorOpacity() { mitk::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; + double opacity = 1.0f; myMP = mitk::Material::New(color, opacity); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") MITK_TEST_CONDITION( color==myMP->GetColor(), "Testing if a Color object was set correctly" ) MITK_TEST_CONDITION( opacity==myMP->GetOpacity(), "Testing if a Opacity object was set correctly" ) } void testConstructorWithRedGreenBlueOpacity() { mitk::Material::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; + double opacity = 1.0f; + double rgb = 0; myMP = mitk::Material::New(rgb, rgb, rgb, opacity); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") MITK_TEST_CONDITION( color==myMP->GetColor(), "Testing if a Color object was set correctly" ) MITK_TEST_CONDITION( opacity==myMP->GetOpacity(), "Testing if a Opacity object was set correctly" ) } void testConstructorRedGreenBlueColorCoefficientSpecularCoefficientSpecularPowerOpacity() { mitk::Material::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; - vtkFloatingPointType colorCoefficient = 0; - vtkFloatingPointType specularCoefficient = 0; - vtkFloatingPointType specularPower = 0; + double opacity = 1.0f; + double rgb = 0; + double colorCoefficient = 0; + double specularCoefficient = 0; + double specularPower = 0; myMP = mitk::Material::New(rgb, rgb, rgb, colorCoefficient, specularCoefficient, specularPower, opacity); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") MITK_TEST_CONDITION( color==myMP->GetColor(), "Testing if a Color object was set correctly" ) MITK_TEST_CONDITION( opacity==myMP->GetOpacity(), "Testing if a Opacity object was set correctly" ) MITK_TEST_CONDITION( specularCoefficient==myMP->GetSpecularCoefficient(), "Testing if a Coefficient object was set correctly" ) MITK_TEST_CONDITION( specularPower==myMP->GetSpecularPower(), "Testing if a SpecularPower object was set correctly" ) MITK_TEST_CONDITION( colorCoefficient==myMP->GetColorCoefficient(), "Testing if a colorCoefficient object was set correctly" ) } void testConstructorColorColorCoefficientSpecularCoefficientSpecularPowerOpacity() { mitk::Material::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; - vtkFloatingPointType colorCoefficient = 0; - vtkFloatingPointType specularCoefficient = 0; - vtkFloatingPointType specularPower = 0; + double opacity = 1.0f; + double rgb = 0; + double colorCoefficient = 0; + double specularCoefficient = 0; + double specularPower = 0; myMP = mitk::Material::New(rgb, rgb, rgb, colorCoefficient, specularCoefficient, specularPower, opacity); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") MITK_TEST_CONDITION( color==myMP->GetColor(), "Testing if a Color object was set correctly" ) MITK_TEST_CONDITION( opacity==myMP->GetOpacity(), "Testing if a Opacity object was set correctly" ) MITK_TEST_CONDITION( specularCoefficient==myMP->GetSpecularCoefficient(), "Testing if a Coefficient object was set correctly" ) MITK_TEST_CONDITION( specularPower==myMP->GetSpecularPower(), "Testing if a SpecularPower object was set correctly" ) } void testConstructorPropertyRedGreenBlueOpacityAndName() { mitk::Material::Pointer reference = myMP; - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; + double opacity = 1.0f; + double rgb = 0; std::string name = "Hans Wurst"; myMP = mitk::Material::New(*reference, rgb, rgb, rgb, opacity, name); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") MITK_TEST_CONDITION( opacity==myMP->GetOpacity(), "Testing if a Opacity object was set correctly" ) //MITK_TEST_CONDITION( name.compare(myMP->GetName(),0,9), "Testing if a Name object was set correctly" ) } void testSetColor() { mitk::Material::Color color; color.Set(0,0,0); myMP = mitk::Material::New(); myMP->SetColor(color); MITK_TEST_CONDITION_REQUIRED(myMP.IsNotNull(),"Testing instantiation") MITK_TEST_CONDITION(color==myMP->GetColor(),"Testing if a color was set correctly") color.Set(0,0,0); myMP->SetColor(color); MITK_TEST_CONDITION(color==myMP->GetColor(),"Testing if a color was set correctly") } void testSetColorCoefficient() { - vtkFloatingPointType colorCoefficient = 0; + double colorCoefficient = 0; myMP = mitk::Material::New(); myMP->SetColorCoefficient(colorCoefficient); MITK_TEST_CONDITION(colorCoefficient == myMP->GetColorCoefficient(), "Testing if a colorcoefficent was set correctly") } void testSetSpecularColor() { mitk::Material::Color color; color.Set(0,0,0); myMP = mitk::Material::New(); myMP->SetSpecularColor(color); MITK_TEST_CONDITION(color == myMP->GetSpecularColor(),"Testing if a SpecularColor was set correctly") } void testSetSpecularCoefficient() { myMP = mitk::Material::New(); - vtkFloatingPointType specularCoefficient = 1; + double specularCoefficient = 1; myMP->SetSpecularCoefficient(specularCoefficient); MITK_TEST_CONDITION(specularCoefficient == myMP->GetSpecularCoefficient(),"Testing if a SpecularCoefficient was set correctly") } void testSetSpecularPower() { myMP = mitk::Material::New(); - vtkFloatingPointType specularPower = 1; + double specularPower = 1; myMP->SetSpecularPower(specularPower); MITK_TEST_CONDITION(specularPower==myMP->GetSpecularPower(), "Testing if a SpecularPower was set correctly") } void testSetOpacity() { myMP = mitk::Material::New(); - vtkFloatingPointType opacity = 1; + double opacity = 1; myMP->SetOpacity(opacity); MITK_TEST_CONDITION(opacity==myMP->GetOpacity(), "Testing if a Opacity was set correctly") } void testSetInterpolation() { myMP = mitk::Material::New(); mitk::Material::InterpolationType interpolation = mitk::Material::Flat; myMP->SetInterpolation(interpolation); MITK_TEST_CONDITION(interpolation == myMP->GetInterpolation(), "Testing if a Interpolation was set correctly") } void testSetRepresentation() { myMP = mitk::Material::New(); mitk::Material::RepresentationType representation = mitk::Material::Wireframe; myMP->SetRepresentation(representation); MITK_TEST_CONDITION(representation == myMP->GetRepresentation(), "Testing if a Representation was set correctly") } void testSetLineWidth() { myMP = mitk::Material::New(); - vtkFloatingPointType lineWidth = 1; + double lineWidth = 1; myMP->SetLineWidth(lineWidth); MITK_TEST_CONDITION(lineWidth==myMP->GetLineWidth(), "Testing if a LineWidth was set correctly") } void testInitialize() { mitk::Material::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; - vtkFloatingPointType colorCoefficient = 0; - vtkFloatingPointType specularCoefficient = 0; - vtkFloatingPointType specularPower = 0; + double opacity = 1.0f; + double rgb = 0; + double colorCoefficient = 0; + double specularCoefficient = 0; + double specularPower = 0; myMP = mitk::Material::New(rgb, rgb, rgb, colorCoefficient, specularCoefficient, specularPower, opacity); - vtkFloatingPointType lineWidth = 1; + double lineWidth = 1; myMP->SetLineWidth(lineWidth); mitk::Material::RepresentationType representation = mitk::Material::Wireframe; myMP->SetRepresentation(representation);mitk::Material::InterpolationType interpolation = mitk::Material::Flat; myMP->SetInterpolation(interpolation); myMP->SetSpecularColor(color); std::string name = "Hans Wurst"; myMP->SetName(name); mitk::Material::Pointer myMP2 = mitk::Material::New(); myMP2->Initialize(*myMP); MITK_TEST_CONDITION(*myMP == *myMP2, "testing equality after .Intitialize") } void testOperatorequality() { { mitk::Material::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; - vtkFloatingPointType colorCoefficient = 0; - vtkFloatingPointType specularCoefficient = 0; - vtkFloatingPointType specularPower = 0; + double opacity = 1.0f; + double rgb = 0; + double colorCoefficient = 0; + double specularCoefficient = 0; + double specularPower = 0; myMP = mitk::Material::New(rgb, rgb, rgb, colorCoefficient, specularCoefficient, specularPower, opacity); - vtkFloatingPointType lineWidth = 1; + double lineWidth = 1; myMP->SetLineWidth(lineWidth); mitk::Material::RepresentationType representation = mitk::Material::Wireframe; myMP->SetRepresentation(representation);mitk::Material::InterpolationType interpolation = mitk::Material::Flat; myMP->SetInterpolation(interpolation); myMP->SetSpecularColor(color); std::string name = "Hans Wurst"; myMP->SetName(name); mitk::Material::Color color2; color2.Set(0, 0, 0); - vtkFloatingPointType opacity2 = 1.0f; - vtkFloatingPointType rgb2 = 0; - vtkFloatingPointType colorCoefficient2 = 0; - vtkFloatingPointType specularCoefficient2 = 0; - vtkFloatingPointType specularPower2 = 0; + double opacity2 = 1.0f; + double rgb2 = 0; + double colorCoefficient2 = 0; + double specularCoefficient2 = 0; + double specularPower2 = 0; mitk::Material::Pointer myMP2 = mitk::Material::New(rgb2, rgb2, rgb2, colorCoefficient2, specularCoefficient2, specularPower2, opacity2); - vtkFloatingPointType lineWidth2 = 1; + double lineWidth2 = 1; myMP2->SetLineWidth(lineWidth2); mitk::Material::RepresentationType representation2 = mitk::Material::Wireframe; myMP2->SetRepresentation(representation2); mitk::Material::InterpolationType interpolation2 = mitk::Material::Flat; myMP2->SetInterpolation(interpolation2); myMP2->SetSpecularColor(color2); std::string name2 = "Hans Wurst"; myMP2->SetName(name2); MITK_TEST_CONDITION(*myMP == *myMP2, "testing equality Operator") } { mitk::Material::Color color; color.Set(0, 0, 0); - vtkFloatingPointType opacity = 1.0f; - vtkFloatingPointType rgb = 0; - vtkFloatingPointType colorCoefficient = 0; - vtkFloatingPointType specularCoefficient = 0; - vtkFloatingPointType specularPower = 0; + double opacity = 1.0f; + double rgb = 0; + double colorCoefficient = 0; + double specularCoefficient = 0; + double specularPower = 0; myMP = mitk::Material::New(rgb, rgb, rgb, colorCoefficient, specularCoefficient, specularPower, opacity); - vtkFloatingPointType lineWidth = 1; + double lineWidth = 1; myMP->SetLineWidth(lineWidth); mitk::Material::RepresentationType representation = mitk::Material::Wireframe; myMP->SetRepresentation(representation);mitk::Material::InterpolationType interpolation = mitk::Material::Flat; myMP->SetInterpolation(interpolation); myMP->SetSpecularColor(color); std::string name = "Hans Wurst"; myMP->SetName(name); mitk::Material::Color color2; color2.Set(0, 0, 0); - vtkFloatingPointType opacity2 = 1.0f; - vtkFloatingPointType rgb2 = 1; - vtkFloatingPointType colorCoefficient2 = 0; - vtkFloatingPointType specularCoefficient2 = 0; - vtkFloatingPointType specularPower2 = 0; + double opacity2 = 1.0f; + double rgb2 = 1; + double colorCoefficient2 = 0; + double specularCoefficient2 = 0; + double specularPower2 = 0; mitk::Material::Pointer myMP2 = mitk::Material::New(rgb2, rgb2, rgb2, colorCoefficient2, specularCoefficient2, specularPower2, opacity2); - vtkFloatingPointType lineWidth2 = 1; + double lineWidth2 = 1; myMP2->SetLineWidth(lineWidth2); mitk::Material::RepresentationType representation2 = mitk::Material::Wireframe; myMP2->SetRepresentation(representation2); mitk::Material::InterpolationType interpolation2 = mitk::Material::Flat; myMP2->SetInterpolation(interpolation2); myMP2->SetSpecularColor(color2); std::string name2 = "Hans Wurst"; myMP2->SetName(name2); MITK_TEST_CONDITION(!(*myMP == *myMP2), "testing equality Operator") } } void testAssignable() { mitk::Material::Pointer materialProp = mitk::Material::New(); MITK_TEST_CONDITION(myMP->Assignable(*materialProp),"testing Assignable with Material" ) } void testOperatorAssign() { mitk::Material::Pointer myMP2 = mitk::Material::New(); *myMP2 = *myMP; MITK_TEST_CONDITION(*myMP == *myMP2, "Testing Assignment Operator") } }; int mitkMaterialTest(int /* argc */, char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("Material") MaterialTest materialTest; materialTest.testConstructor(); materialTest.testConstructorWithColorOpacity(); materialTest.testConstructorWithRedGreenBlueOpacity(); materialTest.testConstructorRedGreenBlueColorCoefficientSpecularCoefficientSpecularPowerOpacity(); materialTest.testConstructorColorColorCoefficientSpecularCoefficientSpecularPowerOpacity(); materialTest.testConstructorPropertyRedGreenBlueOpacityAndName(); materialTest.testAssignable(); materialTest.testOperatorAssign(); materialTest.testSetColor(); materialTest.testSetColorCoefficient(); materialTest.testSetSpecularColor(); materialTest.testSetSpecularCoefficient(); materialTest.testSetSpecularPower(); materialTest.testSetOpacity(); materialTest.testSetInterpolation(); materialTest.testSetRepresentation(); materialTest.testSetLineWidth(); materialTest.testInitialize(); materialTest.testOperatorequality(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. // write your own tests here and use the macros from mitkTestingMacros.h !!! // do not write to std::cout and do not return from this function yourself! // always end with this! MITK_TEST_END () } diff --git a/Core/Code/Testing/mitkSurfaceTest.cpp b/Core/Code/Testing/mitkSurfaceTest.cpp index d18eef4f17..66e95e50b7 100644 --- a/Core/Code/Testing/mitkSurfaceTest.cpp +++ b/Core/Code/Testing/mitkSurfaceTest.cpp @@ -1,150 +1,150 @@ /*=================================================================== 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 "mitkSurface.h" #include "mitkCommon.h" #include "mitkVector.h" #include "mitkTestingMacros.h" #include "vtkPolyData.h" #include "vtkSphereSource.h" #include int mitkSurfaceTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN("Surface"); mitk::Surface::Pointer surface = mitk::Surface::New(); MITK_TEST_CONDITION_REQUIRED( surface.GetPointer(), "Testing initialization!" ); mitk::Surface::Pointer cloneSurface = surface->Clone(); MITK_TEST_CONDITION_REQUIRED( cloneSurface.GetPointer(), "Testing clone surface initialization!" ); vtkSphereSource* sphereSource = vtkSphereSource::New(); sphereSource->SetCenter(0,0,0); sphereSource->SetRadius(5.0); sphereSource->SetThetaResolution(10); sphereSource->SetPhiResolution(10); sphereSource->Update(); vtkPolyData* polys = sphereSource->GetOutput(); MITK_TEST_CONDITION_REQUIRED(surface->GetVtkPolyData() == NULL, "Testing initial state of vtkPolyData"); surface->SetVtkPolyData( polys ); sphereSource->Delete(); MITK_TEST_CONDITION_REQUIRED(surface->GetVtkPolyData()!= NULL, "Testing set vtkPolyData"); cloneSurface= NULL; cloneSurface = surface->Clone(); MITK_TEST_CONDITION_REQUIRED(cloneSurface->GetVtkPolyData()!= NULL, "Testing set vtkPolyData of cloned surface!"); cloneSurface = NULL; - vtkFloatingPointType bounds[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + double bounds[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; polys->ComputeBounds(); polys->GetBounds( bounds ); surface->UpdateOutputInformation(); surface->SetRequestedRegionToLargestPossibleRegion(); mitk::BoundingBox* bb = const_cast(surface->GetGeometry()->GetBoundingBox()); mitk::BoundingBox::BoundsArrayType surfBounds = bb->GetBounds(); bool passed = false; if ( bounds[0] == surfBounds[0] && bounds[1] == surfBounds[1] && bounds[2] == surfBounds[2] && bounds[3] == surfBounds[3] && bounds[4] == surfBounds[4] && bounds[5] == surfBounds[5] ) { passed = true; } MITK_TEST_CONDITION_REQUIRED(passed, "Testing GetBoundingBox()!"); surface->Expand(5); surface->Update(); surface->SetRequestedRegionToLargestPossibleRegion(); mitk::Surface::RegionType requestedRegion = surface->GetRequestedRegion(); MITK_TEST_CONDITION_REQUIRED(requestedRegion.GetSize(3) == 5, "Testing mitk::Surface::Expand( timesteps ): "); - vtkFloatingPointType boundsMat[5][6]; + double boundsMat[5][6]; for (int i=0;i<5;i++) { vtkSphereSource* sphereSource = vtkSphereSource::New(); sphereSource->SetCenter(0,0,0); sphereSource->SetRadius(1.0 * (i+1.0)); sphereSource->SetThetaResolution(10); sphereSource->SetPhiResolution(10); sphereSource->Update(); sphereSource->GetOutput()->ComputeBounds(); sphereSource->GetOutput()->GetBounds( boundsMat[i] ); surface->SetVtkPolyData( sphereSource->GetOutput(),i ); sphereSource->Delete(); } surface->UpdateOutputInformation(); surface->SetRequestedRegionToLargestPossibleRegion(); passed = true; for (int i=0;i<5;i++) { mitk::BoundingBox::BoundsArrayType surfBounds = (const_cast(surface->GetTimeGeometry()->GetGeometryForTimeStep(i)->GetBoundingBox()))->GetBounds(); if ( boundsMat[i][0] != surfBounds[0] || boundsMat[i][1] != surfBounds[1] || boundsMat[i][2] != surfBounds[2] || boundsMat[i][3] != surfBounds[3] || boundsMat[i][4] != surfBounds[4] || boundsMat[i][5] != surfBounds[5] ) { passed = false; break; } } MITK_TEST_CONDITION_REQUIRED(passed, "Testing mitk::Surface::Testing 4D surface data creation!" ); const mitk::TimeGeometry* inputTimeGeometry = surface->GetUpdatedTimeGeometry(); int time = 3; int timestep=0; timestep = inputTimeGeometry->TimePointToTimeStep( time ); MITK_TEST_CONDITION_REQUIRED(time == timestep, "Testing correctness of geometry for surface->GetUpdatedTimeGeometry()!"); sphereSource = vtkSphereSource::New(); sphereSource->SetCenter(0,0,0); sphereSource->SetRadius( 100.0 ); sphereSource->SetThetaResolution(10); sphereSource->SetPhiResolution(10); sphereSource->Update(); surface->SetVtkPolyData( sphereSource->GetOutput(), 3 ); sphereSource->Delete(); inputTimeGeometry = surface->GetUpdatedTimeGeometry(); time = 3; timestep=0; timestep = inputTimeGeometry->TimePointToTimeStep( time ); MITK_TEST_CONDITION_REQUIRED(time == timestep, "Explicitly changing the data of timestep 3 and checking for timebounds correctness of surface's geometry again!"); unsigned int numberoftimesteps = surface->GetTimeSteps(); mitk::Surface::Pointer dummy = mitk::Surface::New(); dummy->Graft(surface); MITK_TEST_CONDITION_REQUIRED( dummy->GetVtkPolyData() != NULL, "Testing copying a Surface with Graft()!"); MITK_TEST_CONDITION_REQUIRED( dummy->GetTimeSteps() == numberoftimesteps, "orig-numberofTimeSteps:" << numberoftimesteps << " copy-numberofTimeSteps:" << dummy->GetTimeSteps()); surface = NULL; MITK_TEST_CONDITION_REQUIRED( surface.IsNull(), "Testing destruction of surface!"); MITK_TEST_END(); } diff --git a/Core/Code/Testing/mitkTransferFunctionTest.cpp b/Core/Code/Testing/mitkTransferFunctionTest.cpp index 4aa61872f7..9b57da5b3b 100644 --- a/Core/Code/Testing/mitkTransferFunctionTest.cpp +++ b/Core/Code/Testing/mitkTransferFunctionTest.cpp @@ -1,277 +1,277 @@ /*=================================================================== 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 "mitkTransferFunction.h" #include "mitkTransferFunctionInitializer.h" #include "mitkTestingMacros.h" #include /** * Unit test for class mitk::TransferFunction. * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ int mitkTransferFunctionTest(int /* argc */, char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("TransferFunction"); // let's create an object of our class mitk::TransferFunction::Pointer myTransferFunction = mitk::TransferFunction::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED( myTransferFunction.IsNotNull(), "Testing instantiation" ); /*************************************************************************/ // Create and set control point arrays for scalar opacity transfer function mitk::TransferFunction::ControlPoints scalarOpacityPoints; scalarOpacityPoints.push_back( std::make_pair( 0.0, 0.0 ) ); scalarOpacityPoints.push_back( std::make_pair( 5.0, 0.3 ) ); scalarOpacityPoints.push_back( std::make_pair( 10.0, 1.0 ) ); myTransferFunction->SetScalarOpacityPoints( scalarOpacityPoints ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetScalarOpacityFunction()->GetSize() == 3, "Adding three point/value pairs to scalar opacity transfer function via VTK interface" ); // Create and set control point arrays for gradient opacity transfer function mitk::TransferFunction::ControlPoints gradientOpacityPoints; gradientOpacityPoints.push_back( std::make_pair( 0.0, 0.2 ) ); gradientOpacityPoints.push_back( std::make_pair( 3.0, 0.7 ) ); gradientOpacityPoints.push_back( std::make_pair( 7.0, 0.8 ) ); gradientOpacityPoints.push_back( std::make_pair( 15.0, 0.9 ) ); myTransferFunction->SetGradientOpacityPoints( gradientOpacityPoints ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetGradientOpacityFunction()->GetSize() == 4, "Adding four point/value pairs to gradient opacity transfer function via VTK interface" ); // Create and set control point arrays for color transfer function mitk::TransferFunction::RGBControlPoints colorPoints; itk::RGBPixel< double > rgb0, rgb1, rgb2, rgb3; rgb0[0] = 0.1f; rgb0[1] = 0.3f; rgb0[2] = 0.5f; colorPoints.push_back( std::make_pair( 2.0, rgb0 ) ); rgb1[0] = 0.3; rgb1[1] = 0.8; rgb1[2] = 0.9; colorPoints.push_back( std::make_pair( 3.0, rgb1 ) ); rgb2[0] = 0.6; rgb2[1] = 0.5; rgb2[2] = 0.4; colorPoints.push_back( std::make_pair( 4.0, rgb2 ) ); rgb3[0] = 0.7; rgb3[1] = 0.1; rgb3[2] = 0.2; colorPoints.push_back( std::make_pair( 5.0, rgb3 ) ); myTransferFunction->SetRGBPoints( colorPoints ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetColorTransferFunction()->GetSize() == 4, "Adding four point/value pairs to color transfer function via VTK interface" ); /*************************************************************************/ // Add a new point to scalar opacity transfer function myTransferFunction->AddScalarOpacityPoint( 3.0, 0.2 ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetScalarOpacityFunction()->GetSize() == 4, "Adding new point/value to scalar opacity transfer function via MITK interface" ); // Add a new point to gradient opacity transfer function myTransferFunction->AddGradientOpacityPoint( 19.0, 1.0 ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetGradientOpacityFunction()->GetSize() == 5, "Adding new point/value to gradient opacity transfer function via MITK interface" ); // Add a new point to color transfer function myTransferFunction->AddRGBPoint( 1.0, 0.0, 0.1, 0.2 ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetColorTransferFunction()->GetSize() == 5, "Adding new point/value to color transfer function via MITK interface" ); /*************************************************************************/ // Retrieve two points from scalar opacity transfer function double v1, v2; v1 = myTransferFunction->GetScalarOpacityFunction()->GetValue( 3.0 ); v2 = myTransferFunction->GetScalarOpacityFunction()->GetValue( 10.0 ); MITK_TEST_CONDITION_REQUIRED( (fabs( v1 - 0.2 ) < 1.0e-5) && (fabs( v2 - 1.0 ) < 1.0e-5), "Retrieving values at two points from scalar opacity transfer function" ); // Retrieve two points from gradient opacity transfer function v1 = myTransferFunction->GetGradientOpacityFunction()->GetValue( 0.0 ); v2 = myTransferFunction->GetGradientOpacityFunction()->GetValue( 19.0 ); MITK_TEST_CONDITION_REQUIRED( (fabs( v1 - 0.2 ) < 1.0e-5) && (fabs( v2 - 1.0 ) < 1.0e-5), "Retrieving values at two points from gradient opacity transfer function" ); // Retrieve two points from color transfer function - vtkFloatingPointType vrgb1[3], vrgb2[3]; + double vrgb1[3], vrgb2[3]; myTransferFunction->GetColorTransferFunction()->GetColor( 1.0, vrgb1 ); myTransferFunction->GetColorTransferFunction()->GetColor( 4.0, vrgb2 ); std::cout << vrgb2[0] << ", " << vrgb2[1] << ", " << vrgb2[2] << std::endl; MITK_TEST_CONDITION_REQUIRED( (fabs( vrgb1[0] - 0.0 ) < 1.0e-5) && (fabs( vrgb1[1] - 0.1 ) < 1.0e-5) && (fabs( vrgb1[2] - 0.2 ) < 1.0e-5) && (fabs( vrgb2[0] - 0.6 ) < 1.0e-5) && (fabs( vrgb2[1] - 0.5 ) < 1.0e-5) && (fabs( vrgb2[2] - 0.4 ) < 1.0e-5), "Retrieving values at two points from color transfer function" ); /*************************************************************************/ // Remove point from scalar opacity transfer function (should return new // number of points) MITK_TEST_CONDITION_REQUIRED( myTransferFunction->RemoveScalarOpacityPoint( 3.0 ) == 1, "Removing point from scalar opacity transfer function (should return point index)" ); // Remove point from scalar opacity transfer function (should return new // number of points) MITK_TEST_CONDITION_REQUIRED( myTransferFunction->RemoveGradientOpacityPoint( 0.0 ) == 0, "Removing point from gradient opacity transfer function (should return point index)" ); // Remove point from color transfer function (should return new // number of points) MITK_TEST_CONDITION_REQUIRED( myTransferFunction->RemoveRGBPoint( 5.0 ) == 4, "Removing point from color transfer function (should return point ndex)" ); /*************************************************************************/ // Try to remove non-existing point from scalar opacity transfer function (should return -1) MITK_TEST_CONDITION_REQUIRED( myTransferFunction->RemoveScalarOpacityPoint( 2.5 ) == -1, "Trying to remove non-existing point from scalar opacity transfer function (should return -1)" ); // Try to remove non-existing point from gradient opacity transfer function (should return -1) MITK_TEST_CONDITION_REQUIRED( myTransferFunction->RemoveGradientOpacityPoint( 2.5 ) == -1, "Trying to remove non-existing point from gradient opacity transfer function (should return -1)" ); // Try to remove non-existing point from color transfer function (should return -1) MITK_TEST_CONDITION_REQUIRED( myTransferFunction->RemoveRGBPoint( 2.5 ) == -1, "Trying to remove non-existing point from color transfer function (should return -1)" ); /*************************************************************************/ // Retrieve copy of scalar opacity points (check for correct content and size) mitk::TransferFunction::ControlPoints newScalarOpacityPoints = myTransferFunction->GetScalarOpacityPoints(); MITK_TEST_CONDITION_REQUIRED( (newScalarOpacityPoints.size() == 3) && (fabs(newScalarOpacityPoints[2].first - 10.0) < 1.0e-5) && (fabs(newScalarOpacityPoints[2].second - 1.0) < 1.0e-5), "Retrieving copy of scalar opacity points (checking for correct content and size)" ); // Retrieve copy of gradient opacity points (check for correct content and size) mitk::TransferFunction::ControlPoints newGradientOpacityPoints = myTransferFunction->GetGradientOpacityPoints(); MITK_TEST_CONDITION_REQUIRED( (newGradientOpacityPoints.size() == 4) && (fabs(newGradientOpacityPoints[3].first - 19.0) < 1.0e-5) && (fabs(newGradientOpacityPoints[3].second - 1.0) < 1.0e-5), "Retrieving copy of gradient opacity points (checking for correct content and size)" ); // Retrieve copy of color transfer points (check for correct content and size) mitk::TransferFunction::RGBControlPoints newRGBPoints = myTransferFunction->GetRGBPoints(); MITK_TEST_CONDITION_REQUIRED( (newRGBPoints.size() == 4) && (fabs(newRGBPoints[3].first - 4.0) < 1.0e-5) && (fabs(newRGBPoints[3].second[0] - 0.6) < 1.0e-5) && (fabs(newRGBPoints[3].second[1] - 0.5) < 1.0e-5) && (fabs(newRGBPoints[3].second[2] - 0.4) < 1.0e-5), "Retrieving copy of color transfer function points (checking for correct content and size)" ); /*************************************************************************/ // Clear scalar opacity points (resulting array should be empty) myTransferFunction->ClearScalarOpacityPoints(); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetScalarOpacityPoints().size() == 0, "Clearing scalar opacity points (resulting array should be empty)" ); myTransferFunction->ClearGradientOpacityPoints(); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetGradientOpacityPoints().size() == 0, "Clearing gradient opacity points (resulting array should be empty)" ); myTransferFunction->ClearRGBPoints(); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetRGBPoints().size() == 0, "Clearing color transfer function points (resulting array should be empty)" ); /******************TRANSFERFUNCTION INITIALIZER TEST***************************/ mitk::TransferFunction::Pointer dummyTransferFunction = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer transferInit = mitk::TransferFunctionInitializer::New(dummyTransferFunction); MITK_TEST_CONDITION_REQUIRED( transferInit->GetTransferFunction().IsNotNull(), "Testing if Transferfunction is set" ); MITK_TEST_CONDITION_REQUIRED( transferInit->GetTransferFunction() == dummyTransferFunction, "Testing if Transferfunction is the correct one" ); transferInit->SetTransferFunction(myTransferFunction); MITK_TEST_CONDITION_REQUIRED( transferInit->GetTransferFunction().IsNotNull(), "Testing if Set Transferfunction works" ); MITK_TEST_CONDITION_REQUIRED( transferInit->GetTransferFunction() == myTransferFunction, "Testing if Set Transferfunction sets the correct one" ); const int size = 8; int arPointNumbers[size][3] = {{3,1,6}, {2,1,2}, {4,1,5}, {3,1,5}, {4,1,7}, {4,2,7}, {4,1,4}, {6,2,6}}; std::string names[size] = {"SetDefaultMode", "SetCtBlackWhiteMode", "SetCtThoraxLargeMode", "SetCtThoraxSmallMode", "SetCtBoneMode", "SetCtBoneGradientMode", "SetCtCardiacMode", "SetMrGenericMode"}; for(int i =0; iSetTransferFunctionMode(i); std::cout << "Punkte: " << myTransferFunction->GetScalarOpacityFunction()->GetSize() << std::endl; MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetScalarOpacityFunction()->GetSize() == arPointNumbers[i][0], "Testing if in " << names[i] << " the Scalar Opacity Function is set" ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetGradientOpacityFunction()->GetSize() == arPointNumbers[i][1], "Testing if in " << names[i] << " the Gradient Opacity Function is set" ); MITK_TEST_CONDITION_REQUIRED( myTransferFunction->GetColorTransferFunction()->GetSize() == arPointNumbers[i][2], "Testing if in " << names[i] << " the Color Transfer Function is set" ); } // always end with this! MITK_TEST_END() } diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h index 374a018ef2..77c39f5106 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h @@ -1,145 +1,145 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef ODFVTKMAPPER2D_H_HEADER_INCLUDED #define ODFVTKMAPPER2D_H_HEADER_INCLUDED #include "mitkVtkMapper.h" #include "vtkPropAssembly.h" #include "vtkAppendPolyData.h" #include "vtkActor.h" #include "vtkPolyDataMapper.h" #include "vtkPlane.h" #include "vtkCutter.h" #include "vtkClipPolyData.h" #include "vtkTransform.h" #include "vtkDataArrayTemplate.h" #include "vtkSmartPointer.h" #include "vtkOdfSource.h" #include "vtkThickPlane.h" namespace mitk { //##Documentation //## @brief Mapper for spherical object densitiy function representations //## template class OdfVtkMapper2D : public VtkMapper { struct OdfDisplayGeometry { - vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; + double vp[ 3 ], vnormal[ 3 ]; Vector3D normal; double d, d1, d2; mitk::Point3D M3D, L3D, O3D; - vtkFloatingPointType vp_original[ 3 ], vnormal_original[ 3 ]; + double vp_original[ 3 ], vnormal_original[ 3 ]; mitk::Vector2D size, origin; bool Equals(OdfDisplayGeometry other) { return other.vp_original[0] == vp[0] && other.vp_original[1] == vp[1] && other.vp_original[2] == vp[2] && other.vnormal_original[0] == vnormal[0] && other.vnormal_original[1] == vnormal[1] && other.vnormal_original[2] == vnormal[2] && other.size[0] == size[0] && other.size[1] == size[1] && other.origin[0] == origin[0] && other.origin[1] == origin[1]; } }; public: mitkClassMacro(OdfVtkMapper2D,VtkMapper) itkNewMacro(Self) virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); bool IsVisibleOdfs(mitk::BaseRenderer* renderer); virtual void MitkRenderOverlay(mitk::BaseRenderer* renderer); virtual void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer* /*renderer*/){} OdfDisplayGeometry MeasureDisplayedGeometry(mitk::BaseRenderer* renderer); double GetMinImageSpacing( int index ); void ApplyPropertySettings(); virtual void Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo); virtual int GetIndex(mitk::BaseRenderer* renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); virtual void Update(mitk::BaseRenderer * renderer); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const { return true; } class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: std::vector< vtkSmartPointer > m_PropAssemblies; std::vector< vtkSmartPointer > m_OdfsPlanes; std::vector< vtkSmartPointer > m_OdfsActors; std::vector< vtkSmartPointer > m_OdfsMappers; vtkSmartPointer< vtkPolyData > m_TemplateOdf; itk::TimeStamp m_LastUpdateTime; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; protected: OdfVtkMapper2D(); virtual ~OdfVtkMapper2D(); static void GlyphMethod(void *arg); bool IsPlaneRotated(mitk::BaseRenderer* renderer); private: mitk::Image* GetInput(); static vtkSmartPointer m_OdfTransform; static vtkSmartPointer m_OdfSource; static float m_Scaling; static int m_Normalization; static int m_ScaleBy; static float m_IndexParam1; static float m_IndexParam2; int m_ShowMaxNumber; std::vector< vtkSmartPointer > m_Planes; std::vector< vtkSmartPointer > m_Cutters; std::vector< vtkSmartPointer > m_ThickPlanes1; std::vector< vtkSmartPointer > m_Clippers1; std::vector< vtkSmartPointer > m_ThickPlanes2; std::vector< vtkSmartPointer > m_Clippers2; vtkImageData* m_VtkImage ; OdfDisplayGeometry m_LastDisplayGeometry; mitk::LocalStorageHandler m_LSH; }; } // namespace mitk #include "mitkOdfVtkMapper2D.txx" #endif /* ODFVTKMAPPER2D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx index 3f5318d042..f7a58dcb56 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx @@ -1,885 +1,885 @@ /*=================================================================== 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 __mitkOdfVtkMapper2D_txx__ #define __mitkOdfVtkMapper2D_txx__ #include "mitkOdfVtkMapper2D.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkMatrixConvert.h" #include "mitkGeometry3D.h" #include "mitkTimeGeometry.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkProperties.h" #include "mitkTensorImage.h" #include "vtkSphereSource.h" #include "vtkPropCollection.h" #include "vtkMaskedGlyph3D.h" #include "vtkGlyph2D.h" #include "vtkGlyph3D.h" #include "vtkMaskedProgrammableGlyphFilter.h" #include "vtkImageData.h" #include "vtkLinearTransform.h" #include "vtkCamera.h" #include "vtkPointData.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkOdfSource.h" #include "vtkDoubleArray.h" #include "vtkLookupTable.h" #include "vtkProperty.h" #include "vtkPolyDataNormals.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkFloatArray.h" #include "vtkDelaunay2D.h" #include "vtkMapper.h" #include "vtkRenderer.h" #include "itkOrientationDistributionFunction.h" #include "itkFixedArray.h" #include #include "vtkOpenGLRenderer.h" #define _USE_MATH_DEFINES #include template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfTransform = vtkSmartPointer::New(); template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfSource = vtkSmartPointer::New(); template float mitk::OdfVtkMapper2D::m_Scaling; template int mitk::OdfVtkMapper2D::m_Normalization; template int mitk::OdfVtkMapper2D::m_ScaleBy; template float mitk::OdfVtkMapper2D::m_IndexParam1; template float mitk::OdfVtkMapper2D::m_IndexParam2; #define ODF_MAPPER_PI M_PI template mitk::OdfVtkMapper2D::LocalStorage::LocalStorage() { m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes[0]->AddInput(vtkPolyData::New()); m_OdfsPlanes[1]->AddInput(vtkPolyData::New()); m_OdfsPlanes[2]->AddInput(vtkPolyData::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud(); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); vtkLookupTable *lut = vtkLookupTable::New(); m_OdfsMappers[0]->SetLookupTable(lut); m_OdfsMappers[1]->SetLookupTable(lut); m_OdfsMappers[2]->SetLookupTable(lut); m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]); m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]); m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]); } template mitk::OdfVtkMapper2D ::OdfVtkMapper2D() { m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters[0]->SetCutFunction( m_Planes[0] ); m_Cutters[0]->GenerateValues( 1, 0, 1 ); m_Cutters[1]->SetCutFunction( m_Planes[1] ); m_Cutters[1]->GenerateValues( 1, 0, 1 ); m_Cutters[2]->SetCutFunction( m_Planes[2] ); m_Cutters[2]->GenerateValues( 1, 0, 1 ); // Windowing the cutted planes in direction 1 m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] ); m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] ); m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] ); // Windowing the cutted planes in direction 2 m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] ); m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] ); m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] ); m_ShowMaxNumber = 500; } template mitk::OdfVtkMapper2D ::~OdfVtkMapper2D() { } template mitk::Image* mitk::OdfVtkMapper2D ::GetInput() { return static_cast ( m_DataNode->GetData() ); } template vtkProp* mitk::OdfVtkMapper2D ::GetVtkProp(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); return localStorage->m_PropAssemblies[GetIndex(renderer)]; } template int mitk::OdfVtkMapper2D ::GetIndex(mitk::BaseRenderer* renderer) { if(!strcmp(renderer->GetName(),"stdmulti.widget1")) return 0; if(!strcmp(renderer->GetName(),"stdmulti.widget2")) return 1; if(!strcmp(renderer->GetName(),"stdmulti.widget3")) return 2; return 0; } template void mitk::OdfVtkMapper2D ::GlyphMethod(void *arg) { vtkMaskedProgrammableGlyphFilter* pfilter=(vtkMaskedProgrammableGlyphFilter*)arg; double point[3]; double debugpoint[3]; pfilter->GetPoint(point); pfilter->GetPoint(debugpoint); itk::Point p(point); Vector3D spacing = pfilter->GetGeometry()->GetSpacing(); p[0] /= spacing[0]; p[1] /= spacing[1]; p[2] /= spacing[2]; mitk::Point3D p2; pfilter->GetGeometry()->IndexToWorld( p, p2 ); point[0] = p2[0]; point[1] = p2[1]; point[2] = p2[2]; vtkPointData* data = pfilter->GetPointData(); vtkDataArray* odfvals = data->GetArray("vector"); vtkIdType id = pfilter->GetPointId(); m_OdfTransform->Identity(); m_OdfTransform->Translate(point[0],point[1],point[2]); typedef itk::OrientationDistributionFunction OdfType; OdfType odf; if(odfvals->GetNumberOfComponents()==6) { float tensorelems[6] = { (float)odfvals->GetComponent(id,0), (float)odfvals->GetComponent(id,1), (float)odfvals->GetComponent(id,2), (float)odfvals->GetComponent(id,3), (float)odfvals->GetComponent(id,4), (float)odfvals->GetComponent(id,5), }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); } else { for(int i=0; iGetComponent(id,i); } switch(m_ScaleBy) { case ODFSB_NONE: m_OdfSource->SetScale(m_Scaling); break; case ODFSB_GFA: m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); break; case ODFSB_PC: m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); break; } m_OdfSource->SetNormalization(m_Normalization); m_OdfSource->SetOdf(odf); m_OdfSource->Modified(); } template typename mitk::OdfVtkMapper2D::OdfDisplayGeometry mitk::OdfVtkMapper2D ::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); // set up the cutter orientation according to the current geometry of // the renderers plane - vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; + double vp[ 3 ], vnormal[ 3 ]; Point3D point = worldPlaneGeometry->GetOrigin(); Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( point.Get_vnl_vector(), vp ); vnl2vtk( normal.Get_vnl_vector(), vnormal ); mitk::DisplayGeometry::Pointer dispGeometry = renderer->GetDisplayGeometry(); mitk::Vector2D size = dispGeometry->GetSizeInMM(); mitk::Vector2D origin = dispGeometry->GetOriginInMM(); // // |------O------| // | d2 | // L d1 M | // | | // |-------------| // mitk::Vector2D M; mitk::Vector2D L; mitk::Vector2D O; M[0] = origin[0] + size[0]/2; M[1] = origin[1] + size[1]/2; L[0] = origin[0]; L[1] = origin[1] + size[1]/2; O[0] = origin[0] + size[0]/2; O[1] = origin[1] + size[1]; mitk::Point2D point1; point1[0] = M[0]; point1[1] = M[1]; mitk::Point3D M3D; dispGeometry->Map(point1, M3D); point1[0] = L[0]; point1[1] = L[1]; mitk::Point3D L3D; dispGeometry->Map(point1, L3D); point1[0] = O[0]; point1[1] = O[1]; mitk::Point3D O3D; dispGeometry->Map(point1, O3D); double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0]) + (M3D[1]-L3D[1])*(M3D[1]-L3D[1]) + (M3D[2]-L3D[2])*(M3D[2]-L3D[2])); double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0]) + (M3D[1]-O3D[1])*(M3D[1]-O3D[1]) + (M3D[2]-O3D[2])*(M3D[2]-O3D[2])); double d = d1>d2 ? d1 : d2; d = d2; OdfDisplayGeometry retval; retval.vp[0] = vp[0]; retval.vp[1] = vp[1]; retval.vp[2] = vp[2]; retval.vnormal[0] = vnormal[0]; retval.vnormal[1] = vnormal[1]; retval.vnormal[2] = vnormal[2]; retval.normal[0] = normal[0]; retval.normal[1] = normal[1]; retval.normal[2] = normal[2]; retval.d = d; retval.d1 = d1; retval.d2 = d2; retval.M3D[0] = M3D[0]; retval.M3D[1] = M3D[1]; retval.M3D[2] = M3D[2]; retval.L3D[0] = L3D[0]; retval.L3D[1] = L3D[1]; retval.L3D[2] = L3D[2]; retval.O3D[0] = O3D[0]; retval.O3D[1] = O3D[1]; retval.O3D[2] = O3D[2]; retval.vp_original[0] = vp[0]; retval.vp_original[1] = vp[1]; retval.vp_original[2] = vp[2]; retval.vnormal_original[0] = vnormal[0]; retval.vnormal_original[1] = vnormal[1]; retval.vnormal_original[2] = vnormal[2]; retval.size[0] = size[0]; retval.size[1] = size[1]; retval.origin[0] = origin[0]; retval.origin[1] = origin[1]; return retval; } template void mitk::OdfVtkMapper2D ::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); int index = GetIndex(renderer); vtkSmartPointer inversetransform = vtkSmartPointer::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); // 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]; m_VtkImage->GetDimensions(dims); double spac[3]; m_VtkImage->GetSpacing(spac); if(fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[0]/spac[0]) < 0.4) dispGeo.vp[0] = 0.4*spac[0]; if(fabs(dispGeo.vp[0]/spac[0]) > (dims[0]-1)-0.4) dispGeo.vp[0] = ((dims[0]-1)-0.4)*spac[0]; dispGeo.vnormal[1] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[0]) && fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[1]/spac[1]) < 0.4) dispGeo.vp[1] = 0.4*spac[1]; if(fabs(dispGeo.vp[1]/spac[1]) > (dims[1]-1)-0.4) dispGeo.vp[1] = ((dims[1]-1)-0.4)*spac[1]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[0]) ) { if(fabs(dispGeo.vp[2]/spac[2]) < 0.4) dispGeo.vp[2] = 0.4*spac[2]; if(fabs(dispGeo.vp[2]/spac[2]) > (dims[2]-1)-0.4) dispGeo.vp[2] = ((dims[2]-1)-0.4)*spac[2]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[1] = 0; } m_Planes[index]->SetTransform( (vtkAbstractTransform*)NULL ); m_Planes[index]->SetOrigin( dispGeo.vp ); m_Planes[index]->SetNormal( dispGeo.vnormal ); vtkSmartPointer points; vtkSmartPointer tmppoints; vtkSmartPointer polydata; vtkSmartPointer pointdata; vtkSmartPointer delaunay; vtkSmartPointer cuttedPlane; // the cutter only works if we do not have a 2D-image // or if we have a 2D-image and want to see the whole image. // // for side views of 2D-images, we need some special treatment if(!( (dims[0] == 1 && dispGeo.vnormal[0] != 0) || (dims[1] == 1 && dispGeo.vnormal[1] != 0) || (dims[2] == 1 && dispGeo.vnormal[2] != 0) )) { m_Cutters[index]->SetCutFunction( m_Planes[index] ); m_Cutters[index]->SetInput( m_VtkImage ); m_Cutters[index]->Update(); cuttedPlane = m_Cutters[index]->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); points = vtkPoints::New(); points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) { points->SetPoint(i, m_VtkImage->GetPoint(i)); } cuttedPlane->SetPoints(points); pointdata = vtkFloatArray::New(); int comps = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,m_VtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); int nZero1, nZero2; if(dims[0]==1) { nZero1 = 1; nZero2 = 2; } else if(dims[1]==1) { nZero1 = 0; nZero2 = 2; } else { nZero1 = 0; nZero2 = 1; } tmppoints = vtkPoints::New(); for(int j=0; jGetNumberOfPoints(); j++){ double pt[3]; m_VtkImage->GetPoint(j,pt); tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0); } polydata = vtkPolyData::New(); polydata->SetPoints( tmppoints ); delaunay = vtkDelaunay2D::New(); delaunay->SetInput( polydata ); delaunay->Update(); vtkCellArray* polys = delaunay->GetOutput()->GetPolys(); cuttedPlane->SetPolys(polys); } if(cuttedPlane->GetNumberOfPoints()) { // WINDOWING HERE inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.O3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.O3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.O3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes1[index]->count = 0; m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes1[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes1[index]->SetThickness(dispGeo.d2); m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] ); m_Clippers1[index]->SetInput( cuttedPlane ); m_Clippers1[index]->SetInsideOut(1); m_Clippers1[index]->Update(); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.L3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.L3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.L3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes2[index]->count = 0; m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes2[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes2[index]->SetThickness(dispGeo.d1); m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] ); m_Clippers2[index]->SetInput( m_Clippers1[index]->GetOutput() ); m_Clippers2[index]->SetInsideOut(1); m_Clippers2[index]->Update(); cuttedPlane = m_Clippers2[index]->GetOutput (); if(cuttedPlane->GetNumberOfPoints()) { localStorage->m_OdfsPlanes[index]->RemoveAllInputs(); vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetInputConnection( m_OdfSource->GetOutputPort() ); normals->SplittingOff(); normals->ConsistencyOff(); normals->AutoOrientNormalsOff(); normals->ComputePointNormalsOn(); normals->ComputeCellNormalsOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); vtkSmartPointer trans = vtkSmartPointer::New(); trans->SetInputConnection( normals->GetOutputPort() ); trans->SetTransform(m_OdfTransform); vtkSmartPointer glyphGenerator = vtkSmartPointer::New(); glyphGenerator->SetMaximumNumberOfPoints(std::min(m_ShowMaxNumber,(int)cuttedPlane->GetNumberOfPoints())); glyphGenerator->SetRandomMode(0); glyphGenerator->SetUseMaskPoints(1); glyphGenerator->SetSource( trans->GetOutput() ); glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetColorModeToColorBySource(); glyphGenerator->SetInputArrayToProcess(0,0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry()); glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator); try { glyphGenerator->Update(); } catch( itk::ExceptionObject& err ) { std::cout << err << std::endl; } localStorage->m_OdfsPlanes[index]->AddInput(glyphGenerator->GetOutput()); localStorage->m_OdfsPlanes[index]->Update(); } } localStorage->m_PropAssemblies[index]->VisibilityOn(); if(localStorage->m_PropAssemblies[index]->GetParts()->IsItemPresent(localStorage->m_OdfsActors[index])) localStorage->m_PropAssemblies[index]->RemovePart(localStorage->m_OdfsActors[index]); localStorage->m_OdfsMappers[index]->SetInput(localStorage->m_OdfsPlanes[index]->GetOutput()); localStorage->m_PropAssemblies[index]->AddPart(localStorage->m_OdfsActors[index]); } template bool mitk::OdfVtkMapper2D ::IsVisibleOdfs(mitk::BaseRenderer* renderer) { mitk::Image::Pointer input = const_cast(this->GetInput()); const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); if(inputTimeGeometry==NULL || inputTimeGeometry->CountTimeSteps()==0 || !inputTimeGeometry->IsValidTimeStep(this->GetTimestep())) return false; if(this->IsPlaneRotated(renderer)) return false; bool retval = false; switch(GetIndex(renderer)) { case 0: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_T"); break; case 1: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_S"); break; case 2: GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_C"); break; } return retval; } template void mitk::OdfVtkMapper2D ::MitkRenderOverlay(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { // adapt cam pos OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } } template void mitk::OdfVtkMapper2D ::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::Update(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; std::string classname("TensorImage"); if(classname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); std::string qclassname("QBallImage"); if(qclassname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); if( m_VtkImage ) { // make sure, that we have point data with more than 1 component (as vectors) vtkPointData* pointData = m_VtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() != N && pointData->GetArray(0)->GetNumberOfComponents() != 6 /*for tensor visualization*/) { itkWarningMacro( << "number of components != number of directions in ODF!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { m_VtkImage->GetPointData()->GetArray(0)->SetName("vector"); } GenerateDataForRenderer(renderer); } else { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } } template void mitk::OdfVtkMapper2D ::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); if ( (localStorage->m_LastUpdateTime >= m_DataNode->GetMTime()) //was the node modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList()->GetMTime()) //was a property modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList(renderer)->GetMTime()) && dispGeo.Equals(m_LastDisplayGeometry)) return; localStorage->m_LastUpdateTime.Modified(); if(!IsVisibleOdfs(renderer)) { localStorage->m_OdfsActors[0]->VisibilityOff(); localStorage->m_OdfsActors[1]->VisibilityOff(); localStorage->m_OdfsActors[2]->VisibilityOff(); } else { localStorage->m_OdfsActors[0]->VisibilityOn(); localStorage->m_OdfsActors[1]->VisibilityOn(); localStorage->m_OdfsActors[2]->VisibilityOn(); m_OdfSource->SetAdditionalScale(GetMinImageSpacing(GetIndex(renderer))); ApplyPropertySettings(); Slice(renderer, dispGeo); m_LastDisplayGeometry = dispGeo; } } template double mitk::OdfVtkMapper2D::GetMinImageSpacing( int index ) { // Spacing adapted scaling double spacing[3]; m_VtkImage->GetSpacing(spacing); double min; if(index==0) { min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; } if(index==1) { min = spacing[1]; min = min > spacing[2] ? spacing[2] : min; } if(index==2) { min = spacing[0]; min = min > spacing[2] ? spacing[2] : min; } return min; } template void mitk::OdfVtkMapper2D ::ApplyPropertySettings() { this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling ); this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber ); OdfNormalizationMethodProperty* nmp = dynamic_cast(this->GetDataNode()->GetProperty( "Normalization" )); if(nmp) m_Normalization = nmp->GetNormalization(); OdfScaleByProperty* sbp = dynamic_cast(this->GetDataNode()->GetProperty( "ScaleBy" )); if(sbp) m_ScaleBy = sbp->GetScaleBy(); this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1); this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2); } template bool mitk::OdfVtkMapper2D ::IsPlaneRotated(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); - vtkFloatingPointType vnormal[ 3 ]; + double vnormal[ 3 ]; Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( normal.Get_vnl_vector(), vnormal ); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); vtkSmartPointer inversetransform = vtkSmartPointer::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double* n = inversetransform->TransformNormal(vnormal); int nonZeros = 0; for (int j=0; j<3; j++) { if (fabs(n[j])>mitk::eps){ nonZeros++; } } if(nonZeros>1) return true; return false; } template void mitk::OdfVtkMapper2D ::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 150 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs_T", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); } #endif // __mitkOdfVtkMapper2D_txx__ diff --git a/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.h b/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.h index 8fdee475c2..27cdb77075 100644 --- a/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.h +++ b/Modules/DiffusionImaging/FiberTracking/Interactions/mitkFiberBundleInteractor.h @@ -1,99 +1,99 @@ /*=================================================================== 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 MITKFiberBundleINTERACTOR_H_HEADER_INCLUDED #define MITKFiberBundleINTERACTOR_H_HEADER_INCLUDED #include "mitkCommon.h" #include "MitkExtExports.h" #include #include #include "FiberTrackingExports.h" #include namespace mitk { class DataNode; //##Documentation //## @brief Just select a point, that's the only way to interact with the point //## //## Interact with a point: Select the point without moving to get parameters that does not change //## All Set-operations would be done through the method "ExecuteAction", if there would be anyone. //## the identificationnumber of this point is set by this points and evalued from an empty place in the DataStructure //## @ingroup Interaction class FiberTracking_EXPORT FiberBundleInteractor : public Interactor { public: mitkClassMacro(FiberBundleInteractor, Interactor); mitkNewMacro2Param(Self, const char*, DataNode*); //##Documentation //## @brief Sets the amount of precision void SetPrecision(unsigned int precision); //##Documentation //## @brief derived from mitk::Interactor; calculates Jurisdiction according to points //## //## standard method can not be used, since it doesn't calculate in points, only in BoundingBox of Points virtual float CanHandleEvent(StateEvent const* stateEvent) const; protected: //##Documentation //##@brief Constructor FiberBundleInteractor(const char * type, DataNode* dataNode); //##Documentation //##@brief Destructor virtual ~FiberBundleInteractor(); //##Documentation //## @brief select the point on the given position virtual void SelectFiber(int position); //##Documentation //## @brief unselect all points that exist in mesh virtual void DeselectAllFibers(); //##Documentation //## @brief Executes Actions virtual bool ExecuteAction(Action* action, mitk::StateEvent const* stateEvent); private: //##Documentation //## @brief to calculate a direction vector from last point and actual point Point3D m_LastPoint; //##Documentation //## @brief to store a position unsigned int m_LastPosition; // Point3D m_InitialPickedPoint; // Point2D m_InitialPickedDisplayPoint; -// vtkFloatingPointType m_InitialPickedPointWorld[4]; +// double m_InitialPickedPointWorld[4]; Point3D m_CurrentPickedPoint; Point2D m_CurrentPickedDisplayPoint; - vtkFloatingPointType m_CurrentPickedPointWorld[4]; + double m_CurrentPickedPointWorld[4]; }; } #endif /* MITKFiberBundleInteractor_H_HEADER_INCLUDED */ diff --git a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.cpp index cff4ff37ce..cbeac65937 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 ); m_Reslicer->SetInput( 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, vtkFloatingPointType *bounds ) + 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, - vtkFloatingPointType *bounds ) + double *bounds ) { - vtkFloatingPointType point1[3]; - vtkFloatingPointType point2[3]; + 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/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h index f438e297a7..04e756fd52 100644 --- a/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h +++ b/Modules/ImageExtraction/mitkExtractDirectedPlaneImageFilter.h @@ -1,124 +1,124 @@ /*=================================================================== 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 mitkExtractDirectedPlaneImageFilter_h_Included #define mitkExtractDirectedPlaneImageFilter_h_Included #include "ImageExtractionExports.h" #include "mitkImageToImageFilter.h" #include "vtkImageReslice.h" #include "mitkVtkResliceInterpolationProperty.h" #define setMacro(name,type) \ virtual void Set##name (type _arg) \ { \ if (this->m_##name != _arg) \ { \ this->m_##name = _arg; \ } \ } #define getMacro(name,type) \ virtual type Get##name () \ { \ return m_##name; \ } class vtkPoints; namespace mitk { /** \deprecated This class is deprecated. Use mitk::ExtractSliceFilter instead. \sa ExtractSliceFilter \brief Extracts a 2D slice of arbitrary geometry from a 3D or 4D image. \sa mitkImageMapper2D \ingroup ImageToImageFilter This class takes a 3D or 4D mitk::Image as input and tries to extract one slice from it. This slice can be arbitrary oriented in space. The 2D slice is resliced by a vtk::ResliceImage filter if not perpendicular to the input image. The world geometry of the plane to be extracted image must be given as an input to the filter in order to correctly calculate world coordinates of the extracted slice. Setting a timestep from which the plane should be extracted is optional. Output will not be set if there was a problem extracting the desired slice. Last contributor: $Author: T. Schwarz$ */ class ImageExtraction_EXPORT ExtractDirectedPlaneImageFilter : public ImageToImageFilter { public: mitkClassMacro(ExtractDirectedPlaneImageFilter, ImageToImageFilter); itkNewMacro(ExtractDirectedPlaneImageFilter); itkSetMacro( WorldGeometry, Geometry2D* ); // The Reslicer is accessible to configure the desired interpolation; // (See vtk::ImageReslice class for documentation). // Misusage is at your own risk... itkGetMacro( Reslicer, vtkImageReslice* ); // The target timestep in a 4D image from which the 2D plane is supposed // to be extracted. itkSetMacro( TargetTimestep, unsigned int ); itkGetMacro( TargetTimestep, unsigned int ); itkSetMacro( InPlaneResampleExtentByGeometry, bool ); itkGetMacro( InPlaneResampleExtentByGeometry, bool ); setMacro( ResliceInterpolationProperty, VtkResliceInterpolationProperty* ); itkGetMacro( ResliceInterpolationProperty, VtkResliceInterpolationProperty* ); setMacro( IsMapperMode, bool ); getMacro( IsMapperMode, bool ); protected: ExtractDirectedPlaneImageFilter(); // purposely hidden virtual ~ExtractDirectedPlaneImageFilter(); virtual void GenerateData(); virtual void GenerateOutputInformation(); bool CalculateClippedPlaneBounds( const Geometry3D *boundingGeometry, - const PlaneGeometry *planeGeometry, vtkFloatingPointType *bounds ); + const PlaneGeometry *planeGeometry, double *bounds ); bool LineIntersectZero( vtkPoints *points, int p1, int p2, - vtkFloatingPointType *bounds ); + double *bounds ); const Geometry2D* m_WorldGeometry; vtkImageReslice * m_Reslicer; unsigned int m_TargetTimestep; bool m_InPlaneResampleExtentByGeometry; int m_ThickSlicesMode; int m_ThickSlicesNum; bool m_IsMapperMode; VtkResliceInterpolationProperty* m_ResliceInterpolationProperty; }; } // namespace mitk #endif // mitkExtractDirectedPlaneImageFilter_h_Included diff --git a/Modules/MitkExt/Algorithms/mitkHeightFieldSurfaceClipImageFilter.cpp b/Modules/MitkExt/Algorithms/mitkHeightFieldSurfaceClipImageFilter.cpp index f601e0f196..93183c5751 100644 --- a/Modules/MitkExt/Algorithms/mitkHeightFieldSurfaceClipImageFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkHeightFieldSurfaceClipImageFilter.cpp @@ -1,465 +1,465 @@ /*=================================================================== 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 "mitkHeightFieldSurfaceClipImageFilter.h" #include "mitkImageTimeSelector.h" #include "mitkTimeHelper.h" #include "mitkProperties.h" #include "mitkImageToItk.h" #include "mitkImageAccessByItk.h" #include #include #include #include #include #include namespace mitk { HeightFieldSurfaceClipImageFilter::HeightFieldSurfaceClipImageFilter() : m_ClippingMode( CLIPPING_MODE_CONSTANT ), m_ClippingConstant( 0.0 ), m_MultiplicationFactor( 2.0 ), m_HeightFieldResolutionX( 256 ), m_HeightFieldResolutionY( 256 ), m_MaxHeight( 1024.0 ), m_MultiPlaneValue(2) { this->SetNumberOfIndexedInputs(8); this->SetNumberOfRequiredInputs(2); m_InputTimeSelector = ImageTimeSelector::New(); m_OutputTimeSelector = ImageTimeSelector::New(); } HeightFieldSurfaceClipImageFilter::~HeightFieldSurfaceClipImageFilter() { } void HeightFieldSurfaceClipImageFilter::SetClippingSurface( Surface *clippingSurface ) { this->SetNthInput( 1, clippingSurface ); } void HeightFieldSurfaceClipImageFilter::SetClippingSurfaces(ClippingPlaneList planeList) { if(planeList.size() > 7) { MITK_WARN<<"Only 7 clipping planes are allowed!"; } for (unsigned int i = 0; i < planeList.size(); ++i) { this->SetNthInput(i+1, planeList.at(i)); } } const Surface* HeightFieldSurfaceClipImageFilter::GetClippingSurface() const { return dynamic_cast< const Surface * >( itk::ProcessObject::GetInput( 1 ) ); } void HeightFieldSurfaceClipImageFilter::SetClippingMode( int mode ) { m_ClippingMode = mode; } int HeightFieldSurfaceClipImageFilter::GetClippingMode() { return m_ClippingMode; } void HeightFieldSurfaceClipImageFilter::SetClippingModeToConstant() { m_ClippingMode = CLIPPING_MODE_CONSTANT; } void HeightFieldSurfaceClipImageFilter::SetClippingModeToMultiplyByFactor() { m_ClippingMode = CLIPPING_MODE_MULTIPLYBYFACTOR; } void HeightFieldSurfaceClipImageFilter::SetClippingModeToMultiPlaneValue() { m_ClippingMode = CLIPPING_MODE_MULTIPLANE; } void HeightFieldSurfaceClipImageFilter::GenerateInputRequestedRegion() { Image *outputImage = this->GetOutput(); Image *inputImage = const_cast< Image * >( this->GetInput( 0 ) ); const Surface *inputSurface = dynamic_cast< const Surface * >( this->GetInput( 1 ) ); if ( !outputImage->IsInitialized() || inputSurface == NULL ) { return; } inputImage->SetRequestedRegionToLargestPossibleRegion(); GenerateTimeInInputRegion( outputImage, inputImage ); } void HeightFieldSurfaceClipImageFilter::GenerateOutputInformation() { const Image *inputImage = this->GetInput( 0 ); Image *outputImage = this->GetOutput(); if ( outputImage->IsInitialized() && (this->GetMTime() <= m_TimeOfHeaderInitialization.GetMTime()) ) { return; } itkDebugMacro(<<"GenerateOutputInformation()"); unsigned int i; unsigned int *tmpDimensions = new unsigned int[inputImage->GetDimension()]; for ( i = 0; i < inputImage->GetDimension(); ++i ) { tmpDimensions[i] = inputImage->GetDimension( i ); } outputImage->Initialize( inputImage->GetPixelType(), inputImage->GetDimension(), tmpDimensions, inputImage->GetNumberOfChannels() ); delete[] tmpDimensions; outputImage->SetGeometry( static_cast< Geometry3D * >( inputImage->GetGeometry()->Clone().GetPointer() ) ); outputImage->SetPropertyList( inputImage->GetPropertyList()->Clone() ); m_TimeOfHeaderInitialization.Modified(); } template < typename TPixel, unsigned int VImageDimension > void HeightFieldSurfaceClipImageFilter::_InternalComputeClippedImage( itk::Image< TPixel, VImageDimension > *inputItkImage, HeightFieldSurfaceClipImageFilter *clipImageFilter, vtkPolyData *clippingPolyData, AffineTransform3D *imageToPlaneTransform ) { typedef itk::Image< TPixel, VImageDimension > ItkInputImageType; typedef itk::Image< TPixel, VImageDimension > ItkOutputImageType; typedef itk::ImageSliceConstIteratorWithIndex< ItkInputImageType > ItkInputImageIteratorType; typedef itk::ImageRegionIteratorWithIndex< ItkOutputImageType > ItkOutputImageIteratorType; typename ImageToItk::Pointer outputimagetoitk = ImageToItk::New(); outputimagetoitk->SetInput( clipImageFilter->m_OutputTimeSelector->GetOutput() ); outputimagetoitk->Update(); typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput(); std::vector< double > test; // create the iterators typename ItkInputImageType::RegionType inputRegionOfInterest = inputItkImage->GetLargestPossibleRegion(); ItkInputImageIteratorType inputIt( inputItkImage, inputRegionOfInterest ); ItkOutputImageIteratorType outputIt( outputItkImage, inputRegionOfInterest ); // Get bounds of clipping data clippingPolyData->ComputeBounds(); - vtkFloatingPointType *bounds = clippingPolyData->GetBounds(); + double *bounds = clippingPolyData->GetBounds(); double xWidth = bounds[1] - bounds[0]; double yWidth = bounds[3] - bounds[2]; // Create vtkCellLocator for clipping poly data vtkCellLocator *cellLocator = vtkCellLocator::New(); cellLocator->SetDataSet( clippingPolyData ); cellLocator->CacheCellBoundsOn(); cellLocator->AutomaticOn(); cellLocator->BuildLocator(); // Allocate memory for 2D image to hold the height field generated by // projecting the clipping data onto the plane double *heightField = new double[m_HeightFieldResolutionX * m_HeightFieldResolutionY]; // Walk through height field and for each entry calculate height of the // clipping poly data at this point by means of vtkCellLocator. The // clipping data x/y bounds are used for converting from poly data space to // image (height-field) space. MITK_INFO << "Calculating Height Field..." << std::endl; for ( unsigned int y = 0; y < m_HeightFieldResolutionY; ++y ) { for ( unsigned int x = 0; x < m_HeightFieldResolutionX; ++x ) { - vtkFloatingPointType p0[3], p1[3], surfacePoint[3], pcoords[3]; + double p0[3], p1[3], surfacePoint[3], pcoords[3]; p0[0] = bounds[0] + xWidth * x / (double) m_HeightFieldResolutionX; p0[1] = bounds[2] + yWidth * y / (double) m_HeightFieldResolutionY; p0[2] = -m_MaxHeight; p1[0] = p0[0]; p1[1] = p0[1]; p1[2] = m_MaxHeight; double t, distance; int subId; if ( cellLocator->IntersectWithLine( p0, p1, 0.1, t, surfacePoint, pcoords, subId ) ) { distance = (2.0 * t - 1.0) * m_MaxHeight; } else { distance = -65536.0; } heightField[y * m_HeightFieldResolutionX + x] = distance; itk::Image::IndexType index; index[0] = x; index[1] = y; } } // Walk through entire input image and for each point determine its distance // from the x/y plane. MITK_INFO << "Performing clipping..." << std::endl; TPixel factor = static_cast< TPixel >( clipImageFilter->m_MultiplicationFactor ); TPixel clippingConstant = clipImageFilter->m_ClippingConstant; inputIt.SetFirstDirection( 0 ); inputIt.SetSecondDirection( 1 ); //through all slices for ( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); inputIt.NextSlice() ) { //through all lines of a slice for ( ; !inputIt.IsAtEndOfSlice(); inputIt.NextLine() ) { //Transform the start(line) point from the image to the plane Point3D imageP0, planeP0; imageP0[0] = inputIt.GetIndex()[0]; imageP0[1] = inputIt.GetIndex()[1]; imageP0[2] = inputIt.GetIndex()[2]; planeP0 = imageToPlaneTransform->TransformPoint( imageP0 ); //Transform the end point (line) from the image to the plane Point3D imageP1, planeP1; imageP1[0] = imageP0[0] + inputRegionOfInterest.GetSize( 0 ); imageP1[1] = imageP0[1]; imageP1[2] = imageP0[2]; planeP1 = imageToPlaneTransform->TransformPoint( imageP1 ); //calculate the step size (if the plane is rotate, you go "crossway" through the image) Vector3D step = (planeP1 - planeP0) / (double) inputRegionOfInterest.GetSize( 0 ); //over all pixel for ( ; !inputIt.IsAtEndOfLine(); ++inputIt, ++outputIt, planeP0 += step ) { //Only ConstantMode: if image pixel value == constant mode value-->set output pixel value directly if ( (clipImageFilter->m_ClippingMode == CLIPPING_MODE_CONSTANT) && ((TPixel)inputIt.Get() == clippingConstant ) ) { outputIt.Set( clippingConstant ); } else { int x0 = (int) ((double)(m_HeightFieldResolutionX) * (planeP0[0] - bounds[0]) / xWidth); int y0 = (int) ((double)(m_HeightFieldResolutionY) * (planeP0[1] - bounds[2]) / yWidth); bool clip; //if the current point is outside of the plane region (RegionOfInterest)-->clip the pixel allways if ( (x0 < 0) || (x0 >= (int)m_HeightFieldResolutionX) || (y0 < 0) || (y0 >= (int)m_HeightFieldResolutionY) ) { clip = true; } else { // Calculate bilinearly interpolated height field value at plane point int x1 = x0 + 1; int y1 = y0 + 1; if ( x1 >= (int)m_HeightFieldResolutionX ) { x1 = x0; } if ( y1 >= (int)m_HeightFieldResolutionY ) { y1 = y0; } //Get the neighbour points for the interpolation ScalarType q00, q01, q10, q11; q00 = heightField[y0 * m_HeightFieldResolutionX + x0]; q01 = heightField[y0 * m_HeightFieldResolutionX + x1]; q10 = heightField[y1 * m_HeightFieldResolutionX + x0]; q11 = heightField[y1 * m_HeightFieldResolutionX + x1]; double p00 = ((double)(m_HeightFieldResolutionX) * (planeP0[0] - bounds[0]) / xWidth); double p01 = ((double)(m_HeightFieldResolutionY) * (planeP0[1] - bounds[2]) / yWidth); ScalarType q = q00 * ((double) x1 - p00) * ((double) y1 - p01) + q01 * (p00 - (double) x0) * ((double) y1 - p01) + q10 * ((double) x1 - p00) * (p01 - (double) y0) + q11 * (p00 - (double) x0) * (p01 - (double) y0); if ( q - planeP0[2] < 0 ) { clip = true; } else { clip = false; } } //different modes: differnt values for the clipped pixel if ( clip ) { if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_CONSTANT ) { outputIt.Set( clipImageFilter->m_ClippingConstant ); } else if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_MULTIPLYBYFACTOR ) { outputIt.Set( inputIt.Get() * factor ); } else if ( clipImageFilter->m_ClippingMode == CLIPPING_MODE_MULTIPLANE ) { if(inputIt.Get() != 0) outputIt.Set( inputIt.Get() + m_MultiPlaneValue); else outputIt.Set( inputIt.Get() ); } } // the non-clipped pixel keeps his value else { outputIt.Set( inputIt.Get() ); } } } } } MITK_INFO << "DONE!" << std::endl; // Clean-up cellLocator->Delete(); } void HeightFieldSurfaceClipImageFilter::GenerateData() { const Image *inputImage = this->GetInput( 0 ); const Image *outputImage = this->GetOutput(); m_InputTimeSelector->SetInput( inputImage ); m_OutputTimeSelector->SetInput( outputImage ); Image::RegionType outputRegion = outputImage->GetRequestedRegion(); const TimeGeometry *outputTimeGeometry = outputImage->GetTimeGeometry(); const TimeGeometry *inputTimeGeometry = inputImage->GetTimeGeometry(); ScalarType timeInMS; int timestep = 0; int tstart = outputRegion.GetIndex( 3 ); int tmax = tstart + outputRegion.GetSize( 3 ); for (unsigned int i = 1; i < this->GetNumberOfInputs(); ++i) { Surface *inputSurface = const_cast< Surface * >( dynamic_cast< Surface * >( itk::ProcessObject::GetInput( i ) ) ); if ( !outputImage->IsInitialized() || inputSurface == NULL ) return; MITK_INFO<<"Plane: "<TimeStepToTimePoint( t ); timestep = inputTimeGeometry->TimePointToTimeStep( timeInMS ); m_InputTimeSelector->SetTimeNr( timestep ); m_InputTimeSelector->UpdateLargestPossibleRegion(); m_OutputTimeSelector->SetTimeNr( t ); m_OutputTimeSelector->UpdateLargestPossibleRegion(); // Compose IndexToWorld transform of image with WorldToIndexTransform of // clipping data for conversion from image index space to plane index space AffineTransform3D::Pointer planeWorldToIndexTransform = AffineTransform3D::New(); inputSurface->GetGeometry( t )->GetIndexToWorldTransform() ->GetInverse( planeWorldToIndexTransform ); AffineTransform3D::Pointer imageToPlaneTransform = AffineTransform3D::New(); imageToPlaneTransform->SetIdentity(); imageToPlaneTransform->Compose( inputTimeGeometry->GetGeometryForTimeStep( t )->GetIndexToWorldTransform() ); imageToPlaneTransform->Compose( planeWorldToIndexTransform ); MITK_INFO << "Accessing ITK function...\n"; if(i==1) { AccessByItk_3( m_InputTimeSelector->GetOutput(), _InternalComputeClippedImage, this, inputSurface->GetVtkPolyData( t ), imageToPlaneTransform ); } else { mitk::Image::Pointer extensionImage = m_OutputTimeSelector->GetOutput()->Clone(); AccessByItk_3( extensionImage, _InternalComputeClippedImage, this, inputSurface->GetVtkPolyData( t ), imageToPlaneTransform ); } if (m_ClippingMode == CLIPPING_MODE_MULTIPLANE) m_MultiPlaneValue = m_MultiPlaneValue*2; } } m_TimeOfHeaderInitialization.Modified(); } } // namespace diff --git a/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp b/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp index 8d40accd49..ceb16e6d83 100644 --- a/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkLabeledImageToSurfaceFilter.cpp @@ -1,365 +1,365 @@ /*=================================================================== 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->SetOutputOrigin(0.0,0.0,0.0); vtkImageThreshold* threshold = vtkImageThreshold::New(); threshold->SetInput( 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() ); //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++ 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->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->SetTargetReduction(m_TargetReduction); decimate->SetMaximumError(0.002); polydata->Delete();//RC-- polydata = decimate->GetOutput(); polydata->Register(NULL);//RC++ decimate->Delete(); } polydata->Update(); 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(); - vtkFloatingPointType point[3]; + 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/mitkMeshUtil.h b/Modules/MitkExt/Algorithms/mitkMeshUtil.h index 784dad5881..e4b7528102 100644 --- a/Modules/MitkExt/Algorithms/mitkMeshUtil.h +++ b/Modules/MitkExt/Algorithms/mitkMeshUtil.h @@ -1,1604 +1,1604 @@ /*=================================================================== 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 MITKMESHUTIL_H_INCLUDED #define MITKMESHUTIL_H_INCLUDED #if(_MSC_VER==1200) #error MeshUtils currently not supported for MS Visual C++ 6.0. Sorry. #endif //#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 template class NullScalarAccessor { public: - static inline vtkFloatingPointType GetPointScalar(typename MeshType::PointDataContainer* /*pointData*/, typename MeshType::PointIdentifier /*idx*/, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) + static inline double GetPointScalar(typename MeshType::PointDataContainer* /*pointData*/, typename MeshType::PointIdentifier /*idx*/, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) { - return (vtkFloatingPointType) 0.0; + return (double) 0.0; }; - static inline vtkFloatingPointType GetCellScalar(typename MeshType::CellDataContainer* /*cellData*/, typename MeshType::CellIdentifier /*idx*/, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) + static inline double GetCellScalar(typename MeshType::CellDataContainer* /*cellData*/, typename MeshType::CellIdentifier /*idx*/, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) { - return (vtkFloatingPointType) 0.0; + return (double) 0.0; }; }; template class MeshScalarAccessor { public: - static inline vtkFloatingPointType GetPointScalar(typename MeshType::PointDataContainer* pointData, typename MeshType::PointIdentifier idx, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) + static inline double GetPointScalar(typename MeshType::PointDataContainer* pointData, typename MeshType::PointIdentifier idx, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) { - return (vtkFloatingPointType)pointData->GetElement(idx); + return (double)pointData->GetElement(idx); }; - static inline vtkFloatingPointType GetCellScalar(typename MeshType::CellDataContainer* cellData, typename MeshType::CellIdentifier idx, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) + static inline double GetCellScalar(typename MeshType::CellDataContainer* cellData, typename MeshType::CellIdentifier idx, MeshType* /*mesh*/ = NULL, unsigned int /*type*/ = 0) { - return (vtkFloatingPointType)cellData->GetElement(idx); + return (double)cellData->GetElement(idx); }; }; template class MeanCurvatureAccessor : public NullScalarAccessor { public: - static inline vtkFloatingPointType GetPointScalar(typename MeshType::PointDataContainer* /*point*/, typename MeshType::PointIdentifier idx, MeshType* mesh, unsigned int /*type*/ = 0) + static inline double GetPointScalar(typename MeshType::PointDataContainer* /*point*/, typename MeshType::PointIdentifier idx, MeshType* mesh, unsigned int /*type*/ = 0) { typename MeshType::PixelType dis = 0; mesh->GetPointData(idx, &dis); - return (vtkFloatingPointType) dis; + return (double) dis; }; }; template class SimplexMeshAccessor : public NullScalarAccessor { public: - static inline vtkFloatingPointType GetPointScalar(typename MeshType::PointDataContainer* point, typename MeshType::PointIdentifier idx, MeshType* mesh, unsigned int type = 0 ) + static inline double GetPointScalar(typename MeshType::PointDataContainer* point, typename MeshType::PointIdentifier idx, MeshType* mesh, unsigned int type = 0 ) { typename MeshType::GeometryMapPointer geometryData = mesh->GetGeometryData(); if (type == 0) { double val = mesh->GetMeanCurvature( idx ); mesh->SetPointData(idx, val); return val; } else if (type == 1) { double val = geometryData->GetElement(idx)->meanTension; mesh->SetPointData(idx, val); return val; } else if (type == 2) { double val = geometryData->GetElement(idx)->externalForce.GetNorm(); mesh->SetPointData(idx, val); return val; } else if (type == 3) return geometryData->GetElement(idx)->internalForce.GetNorm(); else if (type == 4) return geometryData->GetElement(idx)->externalForce.GetNorm() * mesh->GetDistance(idx); else if (type == 5) { typename MeshType::PixelType dis = 0; mesh->GetPointData(idx, &dis); - return (vtkFloatingPointType) dis; + return (double) dis; } else if (type == 6) { - return (vtkFloatingPointType) ((geometryData->GetElement(idx))->allowSplitting); + return (double) ((geometryData->GetElement(idx))->allowSplitting); } else - return (vtkFloatingPointType) 0; + return (double) 0; }; }; /*! \brief The class provides mehtods for ITK - VTK mesh conversion * * \todo document the inner class * \todo maybe inner class should be moved out */ template > class MeshUtil { /*! \brief A visitor to create VTK cells by means of a class defining the InsertImplementation interface The InsertImplementation interface defines the methods \code void InsertLine(vtkIdType *pts); void InsertTriangle(vtkIdType *pts); void InsertPolygon(vtkIdType npts, vtkIdType *pts); void InsertQuad(vtkIdType *pts); void InsertTetra(vtkIdType *pts); void InsertHexahedron(vtkIdType *pts); \endcode This class calls the appropriate insert-method of the InsertImplementation according to the cell type of the visited cell \em and its actual contents: e.g., for a polygon cell with just two points, a line will be created by calling InsertLine. \sa ExactSwitchByCellType \sa SingleCellArrayInsertImplementation \sa DistributeInsertImplementation */ template class SwitchByCellType : public InsertImplementation { // typedef the itk cells we are interested in typedef typename itk::CellInterface< typename MeshType::CellPixelType, typename MeshType::CellTraits > CellInterfaceType; typedef itk::LineCell floatLineCell; typedef itk::TriangleCell floatTriangleCell; typedef itk::PolygonCell floatPolygonCell; typedef itk::QuadrilateralCell floatQuadrilateralCell; typedef itk::TetrahedronCell floatTetrahedronCell; typedef itk::HexahedronCell floatHexahedronCell; typedef typename CellInterfaceType::PointIdConstIterator PointIdIterator; public: /*! Visit a line and create the VTK_LINE cell */ void Visit(unsigned long cellId, floatLineCell* t) { vtkIdType pts[2]; int i=0; unsigned long num = t->GetNumberOfVertices(); vtkIdType vtkCellId = -1; if (num==2) { // useless because itk::LineCell always returns 2 for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertLine( (vtkIdType*)pts ); } if (this->m_UseCellScalarAccessor && vtkCellId >= 0) { this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); } } /*! Visit a polygon and create the VTK_POLYGON cell */ void Visit(unsigned long cellId, floatPolygonCell* t) { vtkIdType pts[4096]; int i=0; unsigned long num = t->GetNumberOfVertices(); vtkIdType vtkCellId = -1; if (num > 4096) { MITK_ERROR << "Problem in mitkMeshUtil: Polygon with more than maximum number of vertices encountered." << std::endl; } else if (num > 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertPolygon( num, (vtkIdType*)pts ); } else if (num == 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertTriangle( (vtkIdType*)pts ); } else if (num==2) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertLine( (vtkIdType*)pts ); } if (this->m_UseCellScalarAccessor && vtkCellId >= 0) { this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); } } /*! Visit a triangle and create the VTK_TRIANGLE cell */ void Visit(unsigned long cellId, floatTriangleCell* t) { vtkIdType pts[3]; int i=0; unsigned long num = t->GetNumberOfVertices(); vtkIdType vtkCellId = -1; if (num == 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertTriangle( (vtkIdType*)pts ); } else if (num==2) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertLine( (vtkIdType*)pts ); } if (this->m_UseCellScalarAccessor && vtkCellId >= 0) { this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); } } /*! Visit a quad and create the VTK_QUAD cell */ void Visit(unsigned long cellId, floatQuadrilateralCell* t) { vtkIdType pts[4]; int i=0; unsigned long num = t->GetNumberOfVertices(); vtkIdType vtkCellId = -1; if (num == 4) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) { if (i == 2) pts[3] = *it; else if (i == 3) pts[2] = *it; else pts[i] = *it; i++; //pts[i++] = *it; } vtkCellId = this->InsertQuad( (vtkIdType*)pts ); } else if (num == 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertTriangle( (vtkIdType*)pts ); } else if (num==2) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertLine( (vtkIdType*)pts ); } if (this->m_UseCellScalarAccessor && vtkCellId >= 0) { this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); } } /*! Visit a tetrahedra and create the VTK_TETRA cell */ void Visit(unsigned long cellId, floatTetrahedronCell* t) { vtkIdType pts[4]; int i=0; unsigned long num = t->GetNumberOfVertices(); vtkIdType vtkCellId = -1; if (num == 4) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertTetra( (vtkIdType*)pts ); } else if (num == 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertTriangle( (vtkIdType*)pts ); } else if (num==2) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertLine( (vtkIdType*)pts ); } if (this->m_UseCellScalarAccessor && vtkCellId >= 0) { this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); } } /*! Visit a hexahedron and create the VTK_HEXAHEDRON cell */ void Visit(unsigned long cellId, floatHexahedronCell* t) { vtkIdType pts[8]; int i=0; unsigned long num = t->GetNumberOfVertices(); vtkIdType vtkCellId = -1; if (num == 8) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) { if (i == 2) pts[i++] = *(it+1); else if (i == 3) pts[i++] = *(it-1); else if (i == 6) pts[i++] = *(it+1); else if (i == 7) pts[i++] = *(it-1); else pts[i++] = *it; } vtkCellId = this->InsertHexahedron( (vtkIdType*)pts ); } else if (num == 4) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertQuad( (vtkIdType*)pts ); } else if (num == 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertTriangle( (vtkIdType*)pts ); } else if (num==2) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkCellId = this->InsertLine( (vtkIdType*)pts ); } if (this->m_UseCellScalarAccessor && vtkCellId >= 0) { this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); } } }; /*! \brief A visitor similar to SwitchByCellType, but with exact matching of cell types Works as described in SwitchByCellType, but does exact matching of cell types, e.g., for a polygon cell with just two points, \em no insert-method will be called, because a polygon must have at least three points. \sa SwitchByCellType \sa SingleCellArrayInsertImplementation \sa DistributeInsertImplementation */ template class ExactSwitchByCellType : public InsertImplementation { // typedef the itk cells we are interested in typedef typename itk::CellInterface< typename MeshType::CellPixelType, typename MeshType::CellTraits > CellInterfaceType; typedef itk::LineCell floatLineCell; typedef itk::TriangleCell floatTriangleCell; typedef itk::PolygonCell floatPolygonCell; typedef itk::QuadrilateralCell floatQuadrilateralCell; typedef itk::TetrahedronCell floatTetrahedronCell; typedef itk::HexahedronCell floatHexahedronCell; typedef typename CellInterfaceType::PointIdConstIterator PointIdIterator; public: /*! Visit a line and create the VTK_LINE cell */ void Visit(unsigned long , floatLineCell* t) { unsigned long num = t->GetNumberOfVertices(); vtkIdType pts[2]; int i = 0; if (num==2) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; this->InsertLine(pts); } } /*! Visit a polygon and create the VTK_POLYGON cell */ void Visit(unsigned long , floatPolygonCell* t) { vtkIdType pts[4096]; unsigned long num = t->GetNumberOfVertices(); if (num > 4096) { MITK_ERROR << "Problem in mitkMeshUtil: Polygon with more than maximum number of vertices encountered." << std::endl; } int i = 0; if (num > 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; this->InsertPolygon(num, pts); } } /*! Visit a triangle and create the VTK_TRIANGLE cell */ void Visit(unsigned long , floatTriangleCell* t) { unsigned long num = t->GetNumberOfVertices(); vtkIdType pts[3]; int i = 0; if (num == 3) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; this->InsertTriangle(pts); } } /*! Visit a quadrilateral and create the VTK_QUAD cell */ void Visit(unsigned long , floatQuadrilateralCell* t) { unsigned long num = t->GetNumberOfVertices(); vtkIdType pts[4]; int i = 0; if (num == 4) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkIdType tmpId = pts[2]; pts[2] = pts[3]; pts[3] = tmpId; this->InsertQuad(pts); } } /*! Visit a tetrahedron and create the VTK_TETRA cell */ void Visit(unsigned long , floatTetrahedronCell* t) { unsigned long num = t->GetNumberOfVertices(); vtkIdType pts[4]; int i = 0; if (num == 4) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; this->InsertTetra(pts); } } /*! Visit a hexahedron and create the VTK_HEXAHEDRON cell */ void Visit(unsigned long , floatHexahedronCell* t) { unsigned long num = t->GetNumberOfVertices(); vtkIdType pts[8]; int i = 0; if (num == 8) { for (PointIdIterator it=t->PointIdsBegin(); it!=t->PointIdsEnd(); it++) pts[i++] = *it; vtkIdType tmp[8]; for (unsigned int i = 0; i < 8; i++) tmp[i] = pts[i]; pts[2] = tmp[3]; pts[3] = tmp[2]; pts[6] = tmp[7]; pts[7] = tmp[6]; this->InsertHexahedron(pts); } } }; /*! \brief Implementation of the InsertImplementation interface of SwitchByCellType to define a visitor that create cells according to their types and put them in a single vtkCellArray (for vtkUnstructuredGrid construction) */ class SingleCellArrayInsertImplementation { vtkCellArray* m_Cells; int* m_TypeArray; //vtkIdType cellId; protected: bool m_UseCellScalarAccessor; vtkFloatArray* m_CellScalars; typename MeshType::CellDataContainer::Pointer m_CellData; public: SingleCellArrayInsertImplementation() : m_UseCellScalarAccessor(false) {} /*! Set the vtkCellArray that will be constructed */ void SetCellArray(vtkCellArray* cells) { m_Cells = cells; } /*! Set the type array for storing the vtk cell types */ void SetTypeArray(int* i) { m_TypeArray = i; } void SetUseCellScalarAccessor(bool flag) { m_UseCellScalarAccessor = flag; } void SetCellScalars(vtkFloatArray* scalars) { m_CellScalars = scalars; } vtkFloatArray* GetCellScalars() { return m_CellScalars; } void SetMeshCellData(typename MeshType::CellDataContainer* data) { m_CellData = data; } vtkIdType InsertLine(vtkIdType *pts) { vtkIdType cellId = m_Cells->InsertNextCell(2, pts); m_TypeArray[cellId] = VTK_LINE; return cellId; } vtkIdType InsertTriangle(vtkIdType *pts) { vtkIdType cellId = m_Cells->InsertNextCell(3, pts); m_TypeArray[cellId] = VTK_TRIANGLE; return cellId; } vtkIdType InsertPolygon(vtkIdType npts, vtkIdType *pts) { vtkIdType cellId = m_Cells->InsertNextCell(npts, pts); m_TypeArray[cellId] = VTK_POLYGON; return cellId; } vtkIdType InsertQuad(vtkIdType *pts) { vtkIdType cellId = m_Cells->InsertNextCell(4, pts); m_TypeArray[cellId] = VTK_QUAD; return cellId; } vtkIdType InsertTetra(vtkIdType *pts) { vtkIdType cellId = m_Cells->InsertNextCell(4, pts); m_TypeArray[cellId] = VTK_TETRA; return cellId; } vtkIdType InsertHexahedron(vtkIdType *pts) { vtkIdType cellId = m_Cells->InsertNextCell(8, pts); m_TypeArray[cellId] = VTK_HEXAHEDRON; return cellId; } }; /*! \brief Implementation of the InsertImplementation interface of SwitchByCellType to define a visitor that distributes cells according to their types (for vtkPolyData construction) */ class DistributeInsertImplementation { vtkCellArray* m_LineCells; vtkCellArray* m_TriangleCells; vtkCellArray* m_PolygonCells; vtkCellArray* m_QuadCells; protected: bool m_UseCellScalarAccessor; vtkFloatArray* m_CellScalars; typename MeshType::CellDataContainer::Pointer m_CellData; public: DistributeInsertImplementation() : m_UseCellScalarAccessor(false) {} /*! Set the vtkCellArray that will be constructed */ void SetCellArrays(vtkCellArray* lines, vtkCellArray* triangles, vtkCellArray* polygons, vtkCellArray* quads) { m_LineCells = lines; m_TriangleCells = triangles; m_PolygonCells = polygons; m_QuadCells = quads; } vtkIdType InsertLine(vtkIdType *pts) { return m_LineCells->InsertNextCell(2, pts); } vtkIdType InsertTriangle(vtkIdType *pts) { return m_TriangleCells->InsertNextCell(3, pts); } vtkIdType InsertPolygon(vtkIdType npts, vtkIdType *pts) { return m_PolygonCells->InsertNextCell(npts, pts); } vtkIdType InsertQuad(vtkIdType *pts) { return m_QuadCells->InsertNextCell(4, pts); } vtkIdType InsertTetra(vtkIdType *pts) { return -1; } // ignored vtkIdType InsertHexahedron(vtkIdType *pts) { return -1; } // ignored }; //typedef typename MeshType::CellType CellType; //typedef typename itk::LineCell< CellType > LineType; //typedef typename itk::PolygonCell< CellType > PolygonType; //typedef typename itk::TriangleCell< CellType > TriangleType; typedef SwitchByCellType SingleCellArrayUserVisitorType; typedef SwitchByCellType DistributeUserVisitorType; typedef ExactSwitchByCellType ExactUserVisitorType; public: typedef itk::MatrixOffsetTransformBase ITKTransformType; typedef itk::MatrixOffsetTransformBase MITKTransformType; /*! Convert a MITK transformation to an ITK transformation Necessary because ITK uses double and MITK uses float values */ static void ConvertTransformToItk(const MITKTransformType* mitkTransform, ITKTransformType* itkTransform) { typename MITKTransformType::MatrixType mitkM = mitkTransform->GetMatrix(); typename ITKTransformType::MatrixType itkM; typename MITKTransformType::OffsetType mitkO = mitkTransform->GetOffset(); typename ITKTransformType::OffsetType itkO; for(short i = 0; i < 3; ++i) { for(short j = 0; j<3; ++j) { itkM[i][j] = (double)mitkM[i][j]; } itkO[i] = (double)mitkO[i]; } itkTransform->SetMatrix(itkM); itkTransform->SetOffset(itkO); } /*! create an itkMesh object from a vtkPolyData */ static typename MeshType::Pointer MeshFromPolyData(vtkPolyData* poly, mitk::Geometry3D* geometryFrame=NULL, mitk::Geometry3D* polyDataGeometryFrame=NULL) { // Create a new mesh typename MeshType::Pointer output = MeshType::New(); output->SetCellsAllocationMethod( MeshType::CellsAllocatedDynamicallyCellByCell ); typedef typename MeshType::CellDataContainer MeshCellDataContainerType; output->SetCellData(MeshCellDataContainerType::New()); // Get the points from vtk vtkPoints* vtkpoints = poly->GetPoints(); const unsigned int numPoints = poly->GetNumberOfPoints(); // Create a compatible point container for the mesh // the mesh is created with a null points container // MeshType::PointsContainer::Pointer points = // MeshType::PointsContainer::New(); // // Resize the point container to be able to fit the vtk points // points->Reserve(numPoints); // // Set the point container on the mesh //output->SetPoints(points); - vtkFloatingPointType vtkpoint[3]; + double vtkpoint[3]; typename MeshType::PointType itkPhysicalPoint; if(geometryFrame==NULL) { if(polyDataGeometryFrame==NULL) { for(unsigned int i=0; i < numPoints; ++i) { vtkpoints->GetPoint(i, vtkpoint); //MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; //typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); mitk::vtk2itk(vtkpoint, itkPhysicalPoint); output->SetPoint( i, itkPhysicalPoint ); } } else { for(unsigned int i=0; i < numPoints; ++i) { vtkpoints->GetPoint(i, vtkpoint); //MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; //typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); mitk::Point3D mitkWorldPoint; mitk::vtk2itk(vtkpoint, mitkWorldPoint); polyDataGeometryFrame->IndexToWorld(mitkWorldPoint, mitkWorldPoint); mitk::vtk2itk(mitkWorldPoint, itkPhysicalPoint); output->SetPoint( i, itkPhysicalPoint ); } } } else { mitk::Point3D mitkWorldPoint; if(polyDataGeometryFrame==NULL) { for(unsigned int i=0; i < numPoints; ++i) { vtkpoints->GetPoint(i, vtkpoint); //MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; //typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); mitk::vtk2itk(vtkpoint, mitkWorldPoint); geometryFrame->WorldToItkPhysicalPoint(mitkWorldPoint, itkPhysicalPoint); output->SetPoint( i, itkPhysicalPoint ); } } else { for(unsigned int i=0; i < numPoints; ++i) { vtkpoints->GetPoint(i, vtkpoint); //MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; //typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); mitk::vtk2itk(vtkpoint, mitkWorldPoint); polyDataGeometryFrame->IndexToWorld(mitkWorldPoint, mitkWorldPoint); geometryFrame->WorldToItkPhysicalPoint(mitkWorldPoint, itkPhysicalPoint); output->SetPoint( i, itkPhysicalPoint ); } } } vtkCellArray* vtkcells = poly->GetPolys(); // vtkCellArray* vtkcells = poly->GetStrips(); //MeshType::CellsContainerPointer cells = MeshType::CellsContainer::New(); //output->SetCells(cells); // extract the cell id's from the vtkUnstructuredGrid int numcells = vtkcells->GetNumberOfCells(); int* vtkCellTypes = new int[numcells]; int cellId = 0; // poly ids start after verts and lines! int cellIdOfs = poly->GetNumberOfVerts() + poly->GetNumberOfLines(); for(; cellId < numcells; cellId++) { vtkCellTypes[cellId] = poly->GetCellType( cellId+cellIdOfs ); } // cells->Reserve(numcells); vtkIdType npts; vtkIdType* pts; cellId = 0; typedef typename MeshType::MeshTraits OMeshTraits; typedef typename OMeshTraits::PixelType OPixelType; typedef typename MeshType::CellTraits CellTraits; typedef typename itk::CellInterface CellInterfaceType; typedef typename itk::TriangleCell TriCellType; typedef typename TriCellType::CellAutoPointer TriCellPointer; TriCellPointer newCell; output->GetCells()->Reserve( poly->GetNumberOfPolys() + poly->GetNumberOfStrips() ); output->GetCellData()->Reserve( poly->GetNumberOfPolys() + poly->GetNumberOfStrips() ); for(vtkcells->InitTraversal(); vtkcells->GetNextCell(npts, pts); cellId++) { switch(vtkCellTypes[cellId]) { case VTK_TRIANGLE: { if (npts != 3) continue; // skip non-triangles; unsigned long pointIds[3]; pointIds[0] = (unsigned long) pts[0]; pointIds[1] = (unsigned long) pts[1]; pointIds[2] = (unsigned long) pts[2]; newCell.TakeOwnership( new TriCellType ); newCell->SetPointIds(pointIds);//(unsigned long*)pts); output->SetCell(cellId, newCell ); output->SetCellData(cellId, (typename MeshType::PixelType)3); break; } case VTK_QUAD: { if (npts != 4 ) continue; // skip non-quadrilateral unsigned long pointIds[3]; pointIds[0] = (unsigned long) pts[0]; pointIds[1] = (unsigned long) pts[1]; pointIds[2] = (unsigned long) pts[2]; newCell.TakeOwnership( new TriCellType ); newCell->SetPointIds(pointIds); output->SetCell(cellId, newCell ); output->SetCellData(cellId, (typename MeshType::PixelType)3); cellId++; pointIds[0] = (unsigned long) pts[2]; pointIds[1] = (unsigned long) pts[3]; pointIds[2] = (unsigned long) pts[0]; newCell.TakeOwnership( new TriCellType ); newCell->SetPointIds(pointIds); output->SetCell(cellId, newCell ); output->SetCellData(cellId, (typename MeshType::PixelType)3); break; } case VTK_EMPTY_CELL: { if (npts != 3) { MITK_ERROR << "Only empty triangle cell supported by now..." << std::endl; // skip non-triangle empty cells; continue; } unsigned long pointIds[3]; pointIds[0] = (unsigned long) pts[0]; pointIds[1] = (unsigned long) pts[1]; pointIds[2] = (unsigned long) pts[2]; newCell.TakeOwnership( new TriCellType ); newCell->SetPointIds(pointIds); output->SetCell(cellId, newCell ); output->SetCellData(cellId, (typename MeshType::PixelType)3); break; } //case VTK_VERTEX: // If need to implement use //case VTK_POLY_VERTEX: // the poly->GetVerts() and //case VTK_LINE: // poly->GetLines() routines //case VTK_POLY_LINE: // outside of the switch..case. case VTK_POLYGON: case VTK_PIXEL: { if (npts != 4 ) continue;// skip non-quadrilateral unsigned long pointIds[3]; for ( unsigned int idx = 0; idx <= 1; idx++ ) { pointIds[0] = (unsigned long) pts[idx]; pointIds[1] = (unsigned long) pts[idx+1]; pointIds[2] = (unsigned long) pts[idx+2]; newCell.TakeOwnership( new TriCellType ); newCell->SetPointIds(pointIds); output->SetCell(cellId+idx, newCell ); output->SetCellData(cellId+idx, (typename MeshType::PixelType)3); } cellId++; break; } case VTK_TETRA: case VTK_VOXEL: case VTK_HEXAHEDRON: case VTK_WEDGE: case VTK_PYRAMID: case VTK_PARAMETRIC_CURVE: case VTK_PARAMETRIC_SURFACE: default: MITK_WARN << "Warning, unhandled cell type " << vtkCellTypes[cellId] << std::endl; } } if (poly->GetNumberOfStrips() != 0) { vtkcells = poly->GetStrips(); numcells = vtkcells->GetNumberOfCells(); vtkCellTypes = new int[numcells]; int stripId = 0; // strip ids start after verts, lines and polys! int stripIdOfs = poly->GetNumberOfVerts() + poly->GetNumberOfLines() + poly->GetNumberOfPolys(); for(; stripId < numcells; stripId++) { vtkCellTypes[stripId] = poly->GetCellType( stripId+stripIdOfs ); } stripId = 0; vtkcells->InitTraversal(); while( vtkcells->GetNextCell(npts, pts) ) { if (vtkCellTypes[stripId] != VTK_TRIANGLE_STRIP) { MITK_ERROR << "Only triangle strips supported!" << std::endl; continue; } stripId++; unsigned int numberOfTrianglesInStrip = npts - 2; unsigned long pointIds[3]; pointIds[0] = (unsigned long) pts[0]; pointIds[1] = (unsigned long) pts[1]; pointIds[2] = (unsigned long) pts[2]; for( unsigned int t=0; t < numberOfTrianglesInStrip; t++ ) { newCell.TakeOwnership( new TriCellType ); newCell->SetPointIds(pointIds); output->SetCell(cellId, newCell ); output->SetCellData(cellId, (typename MeshType::PixelType)3); cellId++; pointIds[0] = pointIds[1]; pointIds[1] = pointIds[2]; pointIds[2] = pts[t+3]; } } } //output->Print(std::cout); output->BuildCellLinks(); delete[] vtkCellTypes; return output; } /*! create an itkMesh object from an mitk::Surface */ static typename MeshType::Pointer MeshFromSurface(mitk::Surface* surface, mitk::Geometry3D* geometryFrame=NULL) { if(surface == NULL) return NULL; return MeshFromPolyData(surface->GetVtkPolyData(), geometryFrame, surface->GetGeometry()); } /*! create an vtkUnstructuredGrid object from an itkMesh */ static vtkUnstructuredGrid* MeshToUnstructuredGrid( MeshType* mesh, bool usePointScalarAccessor = false, bool useCellScalarAccessor = false, unsigned int pointDataType = 0, mitk::Geometry3D* geometryFrame=NULL) { /*! default SingleCellArray line cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation, SingleCellArrayUserVisitorType> SingleCellArrayLineVisitor; /*! default SingleCellArray polygon cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation, SingleCellArrayUserVisitorType> SingleCellArrayPolygonVisitor; /*! default SingleCellArray triangle cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, SingleCellArrayUserVisitorType> SingleCellArrayTriangleVisitor; /*! default SingleCellArray quad cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, SingleCellArrayUserVisitorType> SingleCellArrayQuadrilateralVisitor; /*! default SingleCellArray tetra cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, SingleCellArrayUserVisitorType> SingleCellArrayTetrahedronVisitor; /*! default SingleCellArray hex cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, SingleCellArrayUserVisitorType> SingleCellArrayHexahedronVisitor; // Get the number of points in the mesh int numPoints = mesh->GetNumberOfPoints(); if(numPoints == 0) { //mesh->Print(std::cerr); MITK_FATAL << "no points in Grid " << std::endl; exit(-1); } // Create a vtkUnstructuredGrid vtkUnstructuredGrid* vgrid = vtkUnstructuredGrid::New(); // Create the vtkPoints object and set the number of points vtkPoints* vpoints = vtkPoints::New( VTK_DOUBLE ); vtkFloatArray* pointScalars = vtkFloatArray::New(); vtkFloatArray* cellScalars = vtkFloatArray::New(); pointScalars->SetNumberOfComponents(1); cellScalars->SetNumberOfComponents(1); typename MeshType::PointsContainer::Pointer points = mesh->GetPoints(); typename MeshType::PointsContainer::Iterator i; // iterate over all the points in the itk mesh to find // the maximal index unsigned int maxIndex = 0; for(i = points->Begin(); i != points->End(); ++i) { if(maxIndex < i->Index()) maxIndex = i->Index(); } // initialize vtk-classes for points and scalars vpoints->SetNumberOfPoints(maxIndex+1); pointScalars->SetNumberOfTuples(maxIndex+1); cellScalars->SetNumberOfTuples(mesh->GetNumberOfCells()); - vtkFloatingPointType vtkpoint[3]; + double vtkpoint[3]; typename MeshType::PointType itkPhysicalPoint; if (geometryFrame == 0) { for(i = points->Begin(); i != points->End(); ++i) { // Get the point index from the point container iterator int idx = i->Index(); itkPhysicalPoint = i->Value(); mitk::itk2vtk(itkPhysicalPoint, vtkpoint); // Set the vtk point at the index with the the coord array from itk vpoints->SetPoint(idx, vtkpoint); if(usePointScalarAccessor) { pointScalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) ); } } } else { mitk::Point3D mitkWorldPoint; for(i = points->Begin(); i != points->End(); ++i) { // Get the point index from the point container iterator int idx = i->Index(); itkPhysicalPoint = i->Value(); geometryFrame->ItkPhysicalPointToWorld(itkPhysicalPoint, mitkWorldPoint); mitk::itk2vtk(mitkWorldPoint, vtkpoint); // Set the vtk point at the index with the the coord array from itk vpoints->SetPoint(idx, vtkpoint); if(usePointScalarAccessor) { pointScalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) ); } } } // Set the points on the vtk grid vgrid->SetPoints(vpoints); if (usePointScalarAccessor) vgrid->GetPointData()->SetScalars(pointScalars); // Now create the cells using the MultiVisitor // 1. Create a MultiVisitor typename MeshType::CellType::MultiVisitor::Pointer mv = MeshType::CellType::MultiVisitor::New(); // 2. Create visitors typename SingleCellArrayLineVisitor::Pointer lv = SingleCellArrayLineVisitor::New(); typename SingleCellArrayPolygonVisitor::Pointer pv = SingleCellArrayPolygonVisitor::New(); typename SingleCellArrayTriangleVisitor::Pointer tv = SingleCellArrayTriangleVisitor::New(); typename SingleCellArrayQuadrilateralVisitor::Pointer qv = SingleCellArrayQuadrilateralVisitor::New(); typename SingleCellArrayTetrahedronVisitor::Pointer tetv = SingleCellArrayTetrahedronVisitor::New(); typename SingleCellArrayHexahedronVisitor::Pointer hv = SingleCellArrayHexahedronVisitor::New(); // 3. Set up the visitors //int vtkCellCount = 0; // running counter for current cell being inserted into vtk int numCells = mesh->GetNumberOfCells(); int *types = new int[numCells]; // type array for vtk // create vtk cells and estimate the size vtkCellArray* cells = vtkCellArray::New(); cells->Allocate(numCells); // Set the TypeArray CellCount and CellArray for the visitors lv->SetTypeArray(types); lv->SetCellArray(cells); pv->SetTypeArray(types); pv->SetCellArray(cells); tv->SetTypeArray(types); //tv->SetCellCounter(&vtkCellCount); tv->SetCellArray(cells); qv->SetTypeArray(types); //qv->SetCellCounter(&vtkCellCount); qv->SetCellArray(cells); tetv->SetTypeArray(types); tetv->SetCellArray(cells); hv->SetTypeArray(types); hv->SetCellArray(cells); if (useCellScalarAccessor) { lv->SetUseCellScalarAccessor(true); lv->SetCellScalars(cellScalars); lv->SetMeshCellData(mesh->GetCellData()); pv->SetUseCellScalarAccessor(true); pv->SetCellScalars(cellScalars); pv->SetMeshCellData(mesh->GetCellData()); tv->SetUseCellScalarAccessor(true); tv->SetCellScalars(cellScalars); tv->SetMeshCellData(mesh->GetCellData()); qv->SetUseCellScalarAccessor(true); qv->SetCellScalars(cellScalars); qv->SetMeshCellData(mesh->GetCellData()); tetv->SetUseCellScalarAccessor(true); tetv->SetCellScalars(cellScalars); tetv->SetMeshCellData(mesh->GetCellData()); hv->SetUseCellScalarAccessor(true); hv->SetCellScalars(cellScalars); hv->SetMeshCellData(mesh->GetCellData()); } // add the visitors to the multivisitor mv->AddVisitor(lv); mv->AddVisitor(pv); mv->AddVisitor(tv); mv->AddVisitor(qv); mv->AddVisitor(tetv); mv->AddVisitor(hv); // Now ask the mesh to accept the multivisitor which // will Call Visit for each cell in the mesh that matches the // cell types of the visitors added to the MultiVisitor mesh->Accept(mv); // Now set the cells on the vtk grid with the type array and cell array vgrid->SetCells(types, cells); vgrid->GetCellData()->SetScalars(cellScalars); // Clean up vtk objects (no vtkSmartPointer ... ) cells->Delete(); vpoints->Delete(); delete[] types; pointScalars->Delete(); cellScalars->Delete(); //MITK_INFO << "meshToUnstructuredGrid end" << std::endl; return vgrid; } /*! create a vtkPolyData object from an itkMesh */ static vtkPolyData* MeshToPolyData(MeshType* mesh, bool onlyTriangles = false, bool useScalarAccessor = false, unsigned int pointDataType = 0, mitk::Geometry3D* geometryFrame=NULL, vtkPolyData* polydata = NULL) { /*! default Distribute line cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation, DistributeUserVisitorType> DistributeLineVisitor; /*! default Distribute polygon cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation, DistributeUserVisitorType> DistributePolygonVisitor; /*! default Distribute triangle cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, DistributeUserVisitorType> DistributeTriangleVisitor; /*! default Distribute quad cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, DistributeUserVisitorType> DistributeQuadrilateralVisitor; /*! default Distribute triangle cell visitior definition */ typedef typename itk::CellInterfaceVisitorImplementation >, ExactUserVisitorType> ExactTriangleVisitor; // Get the number of points in the mesh int numPoints = mesh->GetNumberOfPoints(); if(numPoints == 0) { //mesh->Print(std::cerr); MITK_ERROR << "no points in Grid " << std::endl; } // Create a vtkPolyData if(polydata == NULL) polydata = vtkPolyData::New(); else polydata->Initialize(); // Create the vtkPoints object and set the number of points vtkPoints* vpoints = vtkPoints::New( VTK_DOUBLE ); vtkFloatArray * scalars = vtkFloatArray::New(); scalars->SetNumberOfComponents(1); typename MeshType::PointsContainer::Pointer points = mesh->GetPoints(); typename MeshType::PointsContainer::Iterator i; // iterate over all the points in the itk mesh to find // the maximal index unsigned int maxIndex = 0; for(i = points->Begin(); i != points->End(); ++i) { if(maxIndex < i->Index()) maxIndex = i->Index(); } // initialize vtk-classes for points and scalars vpoints->SetNumberOfPoints(maxIndex+1); scalars->SetNumberOfTuples(maxIndex+1); // iterate over all the points in the itk mesh filling in // the vtkPoints object as we go - vtkFloatingPointType vtkpoint[3]; + double vtkpoint[3]; typename MeshType::PointType itkPhysicalPoint; if(geometryFrame==NULL) { for(i = points->Begin(); i != points->End(); ++i) { // Get the point index from the point container iterator int idx = i->Index(); itkPhysicalPoint = i->Value(); mitk::itk2vtk(itkPhysicalPoint, vtkpoint); // Set the vtk point at the index with the the coord array from itk // itk returns a const pointer, but vtk is not const correct, so // we have to use a const cast to get rid of the const // vpoints->SetPoint(idx, const_cast(i->Value().GetDataPointer())); vpoints->SetPoint(idx, vtkpoint); if(useScalarAccessor) { scalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) ); } } } else { mitk::Point3D mitkWorldPoint; for(i = points->Begin(); i != points->End(); ++i) { // Get the point index from the point container iterator int idx = i->Index(); itkPhysicalPoint = i->Value(); geometryFrame->ItkPhysicalPointToWorld(itkPhysicalPoint, mitkWorldPoint); mitk::itk2vtk(mitkWorldPoint, vtkpoint); // Set the vtk point at the index with the the coord array from itk // itk returns a const pointer, but vtk is not const correct, so // we have to use a const cast to get rid of the const // vpoints->SetPoint(idx, const_cast(i->Value().GetDataPointer())); vpoints->SetPoint(idx, vtkpoint); if(useScalarAccessor) { scalars->InsertTuple1( idx, ScalarAccessor::GetPointScalar( mesh->GetPointData(), i->Index(), mesh, pointDataType ) ); } } } // Set the points on the vtk grid polydata->SetPoints(vpoints); if (useScalarAccessor) polydata->GetPointData()->SetScalars(scalars); polydata->GetPointData()->CopyAllOn(); // Now create the cells using the MulitVisitor // 1. Create a MultiVisitor typedef typename MeshType::CellType::MultiVisitor MeshMV; typename MeshMV::Pointer mv = MeshMV::New(); int numCells = mesh->GetNumberOfCells(); if (onlyTriangles) { // create vtk cells and allocate vtkCellArray* trianglecells = vtkCellArray::New(); trianglecells->Allocate(numCells); // 2. Create a triangle visitor and add it to the multivisitor typename ExactTriangleVisitor::Pointer tv = ExactTriangleVisitor::New(); tv->SetCellArrays(NULL, trianglecells, NULL, NULL); mv->AddVisitor(tv); // 3. Now ask the mesh to accept the multivisitor which // will Call Visit for each cell in the mesh that matches the // cell types of the visitors added to the MultiVisitor mesh->Accept(mv); // 4. Set the result into our vtkPolyData if(trianglecells->GetNumberOfCells()>0) polydata->SetStrips(trianglecells); // 5. Clean up vtk objects (no vtkSmartPointer ... ) trianglecells->Delete(); } else { // create vtk cells and allocate vtkCellArray* linecells = vtkCellArray::New(); vtkCellArray* trianglecells = vtkCellArray::New(); vtkCellArray* polygoncells = vtkCellArray::New(); linecells->Allocate(numCells); trianglecells->Allocate(numCells); polygoncells->Allocate(numCells); // 2. Create visitors typename DistributeLineVisitor::Pointer lv = DistributeLineVisitor::New(); typename DistributePolygonVisitor::Pointer pv = DistributePolygonVisitor::New(); typename DistributeTriangleVisitor::Pointer tv = DistributeTriangleVisitor::New(); typename DistributeQuadrilateralVisitor::Pointer qv = DistributeQuadrilateralVisitor::New(); lv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); pv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); tv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); qv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); // add the visitors to the multivisitor mv->AddVisitor(tv); mv->AddVisitor(lv); mv->AddVisitor(pv); mv->AddVisitor(qv); // 3. Now ask the mesh to accept the multivisitor which // will Call Visit for each cell in the mesh that matches the // cell types of the visitors added to the MultiVisitor mesh->Accept(mv); // 4. Set the result into our vtkPolyData if(linecells->GetNumberOfCells()>0) polydata->SetLines(linecells); if(trianglecells->GetNumberOfCells()>0) polydata->SetStrips(trianglecells); if(polygoncells->GetNumberOfCells()>0) polydata->SetPolys(polygoncells); // 5. Clean up vtk objects (no vtkSmartPointer ... ) linecells->Delete(); trianglecells->Delete(); polygoncells->Delete(); } vpoints->Delete(); scalars->Delete(); //MITK_INFO << "meshToPolyData end" << std::endl; return polydata; } static typename MeshType::Pointer CreateRegularSphereMesh(typename MeshType::PointType center, typename MeshType::PointType::VectorType scale, int resolution) { typedef itk::RegularSphereMeshSource SphereSourceType; typename SphereSourceType::Pointer mySphereSource = SphereSourceType::New(); mySphereSource->SetCenter(center); mySphereSource->SetScale(scale); mySphereSource->SetResolution( resolution ); mySphereSource->Update(); typename MeshType::Pointer resultMesh = mySphereSource->GetOutput(); resultMesh->Register(); // necessary ???? return resultMesh; } static typename MeshType::Pointer CreateSphereMesh(typename MeshType::PointType center, typename MeshType::PointType scale, int* resolution) { typedef typename itk::SphereMeshSource SphereSource; typename SphereSource::Pointer mySphereSource = SphereSource::New(); mySphereSource->SetCenter(center); mySphereSource->SetScale(scale); mySphereSource->SetResolutionX(resolution[0]); mySphereSource->SetResolutionY(resolution[1]); mySphereSource->SetSquareness1(1); mySphereSource->SetSquareness2(1); mySphereSource->Update(); mySphereSource->GetOutput(); typename MeshType::Pointer resultMesh = mySphereSource->GetOutput(); resultMesh->Register(); return resultMesh; } // static typename MeshType::Pointer TranslateMesh(typename MeshType::PointType vec, MeshType* input) // { // // typename MeshType::Pointer output = MeshType::New(); // { // output->SetPoints(input->GetPoints()); // output->SetPointData(input->GetPointData()); // output->SetCells(input->GetCells()); // output->SetLastCellId( input->GetLastCellId() ); // typename MeshType::GeometryMapIterator pointDataIterator = input->GetGeometryData()->Begin(); // typename MeshType::GeometryMapIterator pointDataEnd = input->GetGeometryData()->End(); // // typename MeshType::PointType inputPoint,outputPoint; // // while (pointDataIterator != pointDataEnd) // { // unsigned long pointId = pointDataIterator->Index(); // itk::SimplexMeshGeometry* newGeometry = new itk::SimplexMeshGeometry(); // itk::SimplexMeshGeometry* refGeometry = pointDataIterator->Value(); // // input->GetPoint(pointId, &inputPoint ); // outputPoint[0] = inputPoint[0] + vec[0]; // outputPoint[1] = inputPoint[1] + vec[1]; // outputPoint[2] = inputPoint[2] + vec[2]; // output->SetPoint( pointId, outputPoint ); // // // newGeometry->pos = outputPoint; // newGeometry->neighborIndices = refGeometry->neighborIndices; // newGeometry->meanCurvature = refGeometry->meanCurvature; // newGeometry->neighbors = refGeometry->neighbors; // newGeometry->oldPos = refGeometry->oldPos; // newGeometry->eps = refGeometry->eps; // newGeometry->referenceMetrics = refGeometry->referenceMetrics; // newGeometry->neighborSet = refGeometry->neighborSet; // newGeometry->distance = refGeometry->distance; // newGeometry->externalForce = refGeometry->externalForce; // newGeometry->internalForce = refGeometry->internalForce; // output->SetGeometryData(pointId, newGeometry); // pointDataIterator++; // } // } //// output->SetGeometryData( inputMesh->GetGeometryData() ); // return output; // } static typename MeshType::Pointer CreateRegularSphereMesh2(typename MeshType::PointType center, typename MeshType::PointType scale, int resolution) { typedef typename itk::AutomaticTopologyMeshSource MeshSourceType; typename MeshSourceType::Pointer mySphereSource = MeshSourceType::New(); typename MeshType::PointType pnt0, pnt1, pnt2, pnt3, pnt4, pnt5, pnt6, pnt7, pnt8, pnt9, pnt10, pnt11; double c1= 0.5 * (1.0 + sqrt(5.0)); double c2= 1.0; double len = sqrt( c1*c1 + c2*c2 ); c1 /= len; c2 /= len; pnt0[0] = center[0] - c1*scale[0]; pnt0[1] = center[1]; pnt0[2] = center[2] + c2*scale[2]; pnt1[0] = center[0]; pnt1[1] = center[1] + c2*scale[1]; pnt1[2] = center[2] - c1*scale[2]; pnt2[0] = center[0]; pnt2[1] = center[1] + c2*scale[1]; pnt2[2] = center[2] + c1*scale[2]; pnt3[0] = center[0] + c1*scale[0]; pnt3[1] = center[1]; pnt3[2] = center[2] - c2*scale[2]; pnt4[0] = center[0] - c2*scale[0]; pnt4[1] = center[1] - c1*scale[1]; pnt4[2] = center[2]; pnt5[0] = center[0] - c2*scale[0]; pnt5[1] = center[1] + c1*scale[1]; pnt5[2] = center[2]; pnt6[0] = center[0]; pnt6[1] = center[1] - c2*scale[1]; pnt6[2] = center[2] + c1*scale[2]; pnt7[0] = center[0] + c2*scale[0]; pnt7[1] = center[1] + c1*scale[1]; pnt7[2] = center[2]; pnt8[0] = center[0]; pnt8[1] = center[1] - c2*scale[1]; pnt8[2] = center[2] - c1*scale[2]; pnt9[0] = center[0] + c1*scale[0]; pnt9[1] = center[1]; pnt9[2] = center[2] + c2*scale[2]; pnt10[0]= center[0] + c2*scale[0]; pnt10[1]= center[1] - c1*scale[1]; pnt10[2]= center[2]; pnt11[0]= center[0] - c1*scale[0]; pnt11[1]= center[1]; pnt11[2]= center[2] - c2*scale[2]; addTriangle( mySphereSource, scale, pnt9, pnt2, pnt6, resolution ); addTriangle( mySphereSource, scale, pnt1, pnt11, pnt5, resolution ); addTriangle( mySphereSource, scale, pnt11, pnt1, pnt8, resolution ); addTriangle( mySphereSource, scale, pnt0, pnt11, pnt4, resolution ); addTriangle( mySphereSource, scale, pnt3, pnt1, pnt7, resolution ); addTriangle( mySphereSource, scale, pnt3, pnt8, pnt1, resolution ); addTriangle( mySphereSource, scale, pnt9, pnt3, pnt7, resolution ); addTriangle( mySphereSource, scale, pnt0, pnt6, pnt2, resolution ); addTriangle( mySphereSource, scale, pnt4, pnt10, pnt6, resolution ); addTriangle( mySphereSource, scale, pnt1, pnt5, pnt7, resolution ); addTriangle( mySphereSource, scale, pnt7, pnt5, pnt2, resolution ); addTriangle( mySphereSource, scale, pnt8, pnt3, pnt10, resolution ); addTriangle( mySphereSource, scale, pnt4, pnt11, pnt8, resolution ); addTriangle( mySphereSource, scale, pnt9, pnt7, pnt2, resolution ); addTriangle( mySphereSource, scale, pnt10, pnt9, pnt6, resolution ); addTriangle( mySphereSource, scale, pnt0, pnt5, pnt11, resolution ); addTriangle( mySphereSource, scale, pnt0, pnt2, pnt5, resolution ); addTriangle( mySphereSource, scale, pnt8, pnt10, pnt4, resolution ); addTriangle( mySphereSource, scale, pnt3, pnt9, pnt10, resolution ); addTriangle( mySphereSource, scale, pnt6, pnt0, pnt4, resolution ); return mySphereSource->GetOutput(); } private: static void addTriangle( typename itk::AutomaticTopologyMeshSource::Pointer meshSource, typename MeshType::PointType scale, typename MeshType::PointType pnt0, typename MeshType::PointType pnt1, typename MeshType::PointType pnt2, int resolution ) { if (resolution==0) { // add triangle meshSource->AddTriangle( meshSource->AddPoint( pnt0 ), meshSource->AddPoint( pnt1 ), meshSource->AddPoint( pnt2 ) ); } else { vnl_vector_fixed v1, v2, res, pv; v1 = (pnt1-pnt0).Get_vnl_vector(); v2 = (pnt2-pnt0).Get_vnl_vector(); res = vnl_cross_3d( v1, v2 ); pv = pnt0.GetVectorFromOrigin().Get_vnl_vector(); //double d = res[0]*pv[0] + res[1]*pv[1] + res[2]*pv[2]; // subdivision typename MeshType::PointType pnt01, pnt12, pnt20; for (int d=0; d<3; d++) { pnt01[d] = (pnt0[d] + pnt1[d]) / 2.0; pnt12[d] = (pnt1[d] + pnt2[d]) / 2.0; pnt20[d] = (pnt2[d] + pnt0[d]) / 2.0; } // map new points to sphere double lenPnt01=0; for (int d=0; d<3; d++) lenPnt01 += pnt01[d]*pnt01[d]; lenPnt01 = sqrt( lenPnt01 ); double lenPnt12=0; for (int d=0; d<3; d++) lenPnt12 += pnt12[d]*pnt12[d]; lenPnt12 = sqrt( lenPnt12 ); double lenPnt20=0; for (int d=0; d<3; d++) lenPnt20 += pnt20[d]*pnt20[d]; lenPnt20 = sqrt( lenPnt20 ); for (int d=0; d<3; d++) { pnt01[d] *= scale[d]/lenPnt01; pnt12[d] *= scale[d]/lenPnt12; pnt20[d] *= scale[d]/lenPnt20; } addTriangle( meshSource, scale, pnt0, pnt01, pnt20, resolution-1 ); addTriangle( meshSource, scale, pnt01, pnt1, pnt12, resolution-1 ); addTriangle( meshSource, scale, pnt20, pnt12, pnt2, resolution-1 ); addTriangle( meshSource, scale, pnt01, pnt12, pnt20, resolution-1 ); } } }; #endif // MITKMESHUTIL_H_INCLUDED diff --git a/Modules/MitkExt/Algorithms/mitkPointLocator.cpp b/Modules/MitkExt/Algorithms/mitkPointLocator.cpp index 0a870888f0..7c550fb45a 100644 --- a/Modules/MitkExt/Algorithms/mitkPointLocator.cpp +++ b/Modules/MitkExt/Algorithms/mitkPointLocator.cpp @@ -1,259 +1,259 @@ /*=================================================================== 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 "mitkPointLocator.h" #include #include mitk::PointLocator::PointLocator() : m_SearchTreeInitialized(false), m_VtkPoints(NULL), m_MitkPoints(NULL), m_ItkPoints(NULL), m_ANNK(1), m_ANNDimension(3), m_ANNEpsilon(0), m_ANNDataPoints(NULL), m_ANNQueryPoint(NULL), m_ANNPointIndexes(NULL), m_ANNDistances(NULL), m_ANNTree(NULL) { } mitk::PointLocator::~PointLocator() { if ( m_SearchTreeInitialized ) DestroyANN(); } void mitk::PointLocator::SetPoints( vtkPointSet* pointSet ) { if ( pointSet == NULL ) { itkWarningMacro("Points are NULL!"); return; } vtkPoints* points = pointSet->GetPoints(); if(m_VtkPoints) { if ( (m_VtkPoints == points) && (m_VtkPoints->GetMTime() == points->GetMTime()) ) { return; //no need to recalculate search tree } } m_VtkPoints = points; size_t size = points->GetNumberOfPoints(); if ( m_ANNDataPoints != NULL ) delete[] m_ANNDataPoints; m_ANNDataPoints = annAllocPts( size, m_ANNDimension ); m_IndexToPointIdContainer.clear(); m_IndexToPointIdContainer.resize( size ); for( vtkIdType i = 0; (unsigned)i < size; ++i ) { - vtkFloatingPointType* currentPoint = points->GetPoint( i ); + double* currentPoint = points->GetPoint( i ); (m_ANNDataPoints[i])[0] = currentPoint[0]; (m_ANNDataPoints[i])[1] = currentPoint[1]; (m_ANNDataPoints[i])[2] = currentPoint[2]; m_IndexToPointIdContainer[i] = i; } InitANN(); } void mitk::PointLocator::SetPoints( mitk::PointSet* points ) { if ( points == NULL ) { itkWarningMacro("Points are NULL!"); return; } if(m_MitkPoints) { if ( (m_MitkPoints == points) && (m_MitkPoints->GetMTime() == points->GetMTime()) ) { return; //no need to recalculate search tree } } m_MitkPoints = points; size_t size = points->GetSize(); if ( m_ANNDataPoints != NULL ) delete[] m_ANNDataPoints; m_ANNDataPoints = annAllocPts( size, m_ANNDimension ); m_IndexToPointIdContainer.clear(); m_IndexToPointIdContainer.resize( size ); size_t counter = 0; mitk::PointSet::PointsContainer* pointsContainer = points->GetPointSet()->GetPoints(); mitk::PointSet::PointsContainer::Iterator it; mitk::PointSet::PointType currentPoint; mitk::PointSet::PointsContainer::ElementIdentifier currentId; for( it = pointsContainer->Begin(); it != pointsContainer->End(); ++it, ++counter ) { currentPoint = it->Value(); currentId = it->Index(); (m_ANNDataPoints[counter])[0] = currentPoint[0]; (m_ANNDataPoints[counter])[1] = currentPoint[1]; (m_ANNDataPoints[counter])[2] = currentPoint[2]; m_IndexToPointIdContainer[counter] = currentId; } InitANN(); } void mitk::PointLocator::SetPoints( ITKPointSet* pointSet ) { if ( pointSet == NULL ) { itkWarningMacro("Points are NULL!"); return; } if(m_ItkPoints) { if ( (m_ItkPoints == pointSet) && (m_ItkPoints->GetMTime() == pointSet->GetMTime()) ) { return; //no need to recalculate search tree } } m_ItkPoints = pointSet; size_t size = pointSet->GetNumberOfPoints(); if ( m_ANNDataPoints != NULL ) delete[] m_ANNDataPoints; m_ANNDataPoints = annAllocPts( size, m_ANNDimension ); m_IndexToPointIdContainer.clear(); m_IndexToPointIdContainer.resize( size ); size_t counter = 0; ITKPointSet::PointsContainerConstPointer pointsContainer = pointSet->GetPoints(); ITKPointSet::PointsContainer::ConstIterator it; ITKPointSet::PointType currentPoint; ITKPointSet::PointsContainer::ElementIdentifier currentId; for( it = pointsContainer->Begin(); it != pointsContainer->End(); ++it, ++counter ) { currentPoint = it->Value(); currentId = it->Index(); (m_ANNDataPoints[counter])[0] = currentPoint[0]; (m_ANNDataPoints[counter])[1] = currentPoint[1]; (m_ANNDataPoints[counter])[2] = currentPoint[2]; m_IndexToPointIdContainer[counter] = currentId; } InitANN(); } -mitk::PointLocator::IdType mitk::PointLocator::FindClosestPoint( const vtkFloatingPointType point[3] ) +mitk::PointLocator::IdType mitk::PointLocator::FindClosestPoint( const double point[3] ) { m_ANNQueryPoint[0] = point[0]; m_ANNQueryPoint[1] = point[1]; m_ANNQueryPoint[2] = point[2]; return FindClosestANNPoint( m_ANNQueryPoint ); } -mitk::PointLocator::IdType mitk::PointLocator::FindClosestPoint( vtkFloatingPointType x, vtkFloatingPointType y, vtkFloatingPointType z ) +mitk::PointLocator::IdType mitk::PointLocator::FindClosestPoint( double x, double y, double z ) { m_ANNQueryPoint[0] = x; m_ANNQueryPoint[1] = y; m_ANNQueryPoint[2] = z; return FindClosestANNPoint( m_ANNQueryPoint ); } mitk::PointLocator::IdType mitk::PointLocator::FindClosestPoint( mitk::PointSet::PointType point ) { m_ANNQueryPoint[0] = point[0]; m_ANNQueryPoint[1] = point[1]; m_ANNQueryPoint[2] = point[2]; return FindClosestANNPoint( m_ANNQueryPoint ); } mitk::PointLocator::IdType mitk::PointLocator::FindClosestANNPoint( const ANNpoint& point) { if ( ! m_SearchTreeInitialized ) return -1; m_ANNTree->annkSearch(point, m_ANNK, m_ANNPointIndexes, m_ANNDistances); return m_IndexToPointIdContainer[m_ANNPointIndexes[0]]; } mitk::PointLocator::DistanceType mitk::PointLocator::GetMinimalDistance( mitk::PointSet::PointType point ) { m_ANNQueryPoint[0] = point[0]; m_ANNQueryPoint[1] = point[1]; m_ANNQueryPoint[2] = point[2]; return GetMinimalDistance( m_ANNQueryPoint ); } mitk::PointLocator::DistanceType mitk::PointLocator::GetMinimalDistance( const ANNpoint& point) { if ( ! m_SearchTreeInitialized ) return -1; m_ANNTree->annkSearch(point, m_ANNK, m_ANNPointIndexes, m_ANNDistances); return m_ANNDistances[0]; } void mitk::PointLocator::InitANN() { if ( m_SearchTreeInitialized ) DestroyANN(); m_ANNQueryPoint = annAllocPt( m_ANNDimension ); m_ANNPointIndexes = new ANNidx[m_ANNK]; m_ANNDistances = new ANNdist[m_ANNK]; m_ANNTree = new ANNkd_tree( m_ANNDataPoints, m_IndexToPointIdContainer.size(), m_ANNDimension ); m_SearchTreeInitialized = true; } void mitk::PointLocator::DestroyANN() { m_SearchTreeInitialized = false; if ( m_ANNQueryPoint != NULL ) annDeallocPt( m_ANNQueryPoint ); if ( m_ANNDataPoints != NULL ) annDeallocPts( m_ANNDataPoints ); if ( m_ANNPointIndexes != NULL ) delete[] m_ANNPointIndexes; if ( m_ANNDistances != NULL ) delete[] m_ANNDistances; if ( m_ANNTree != NULL ) delete m_ANNTree; } bool mitk::PointLocator::FindClosestPointAndDistance( mitk::PointSet::PointType point, IdType* id, DistanceType* dist ) { m_ANNQueryPoint[0] = point[0]; m_ANNQueryPoint[1] = point[1]; m_ANNQueryPoint[2] = point[2]; m_ANNTree->annkSearch( m_ANNQueryPoint, m_ANNK, m_ANNPointIndexes, m_ANNDistances); *id = m_IndexToPointIdContainer[m_ANNPointIndexes[0]]; *dist = m_ANNDistances[0]; return true; } diff --git a/Modules/MitkExt/Algorithms/mitkPointLocator.h b/Modules/MitkExt/Algorithms/mitkPointLocator.h index ed8f67684a..e6eca0a380 100644 --- a/Modules/MitkExt/Algorithms/mitkPointLocator.h +++ b/Modules/MitkExt/Algorithms/mitkPointLocator.h @@ -1,225 +1,225 @@ /*=================================================================== 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_POINT_LOCATOR__H__ #define _MITK_POINT_LOCATOR__H__ #include #include "MitkExtExports.h" #include "mitkPointSet.h" #include //forward declarations class vtkPointSet; class ANNkd_tree; namespace mitk { /** * Convenience wrapper around ANN to provide fast nearest neighbour searches. * Usage: set your points via SetPoints( vtkPointSet* Points ) or SetPoints(mitk::PointSet*). * Then, you may query the closest point to an arbitrary coordinate by FindClosestPoint(). * There is no further call to update etc. needed. * Currently only calls for 1 nearest neighbour are supported. Feel free to add functions * for K nearest neighbours. * NOTE: At least 1 point must be contained in the point set. */ class MitkExt_EXPORT PointLocator : public itk::Object { public: mitkClassMacro( PointLocator, Object ); itkNewMacro( Self ); typedef int IdType; typedef float DistanceType; typedef float PixelType; typedef double CoordRepType; typedef itk::DefaultStaticMeshTraits MeshTraits; typedef itk::PointSet ITKPointSet; /** * Sets the point which will be used for nearest-neighbour searches. Note * there must be at least one point in the point set. * @param points the point set containing points for nearest neighbours searches. */ void SetPoints( vtkPointSet* points ); /** * Sets the point which will be used for nearest-neighbour searches. Note * there must be at least one point in the point set. * @param points the point set containing points for nearest neighbours searches. */ void SetPoints( mitk::PointSet* points ); /** * Sets the point which will be used for nearest-neighbour searches. Note * there must be at least one point in the point set. * @param pointSet the point set containing points for nearest neighbours searches. */ void SetPoints( ITKPointSet* pointSet ); /** * Finds the nearest neighbour in the point set previously defined by SetPoints(). * The Id of the point is returned. Please note, that there is no case, in which * no point is found, since as a precondition at least one point has to be contained * in the point set. * @param point the query point, for whom the nearest neighbour will be determined * @returns the id of the nearest neighbour of the given point. The id corresponds to the id * which is given in the original point set. */ - IdType FindClosestPoint( const vtkFloatingPointType point[3] ); + IdType FindClosestPoint( const double point[3] ); /** * Finds the nearest neighbour in the point set previously defined by SetPoints(). * The Id of the point is returned. Please note, that there is no case, in which * no point is found, since as a precondition at least one point has to be contained * in the point set. * @param x the x coordinated of the query point, for whom the nearest neighbour will be determined * @param y the x coordinated of the query point, for whom the nearest neighbour will be determined * @param z the x coordinated of the query point, for whom the nearest neighbour will be determined * @returns the id of the nearest neighbour of the given point. The id corresponds to the id * which is given in the original point set. */ - IdType FindClosestPoint( vtkFloatingPointType x, vtkFloatingPointType y, vtkFloatingPointType z ); + IdType FindClosestPoint( double x, double y, double z ); /** * Finds the nearest neighbour in the point set previously defined by SetPoints(). * The Id of the point is returned. Please note, that there is no case, in which * no point is found, since as a precondition at least one point has to be contained * in the point set. * @param point the query point, for whom the nearest neighbour will be determined * @returns the id of the nearest neighbour of the given point. The id corresponds to the id * which is given in the original point set. */ IdType FindClosestPoint( mitk::PointSet::PointType point ); /** * Finds the nearest neighbour in the point set previously defined by SetPoints(). * The minimal distance between this point and the closest point of the point set is returned. * Please note, that there is no case, in which * no point is found, since as a precondition at least one point has to be contained * in the point set. * @param point the query point, for whom the minimal distance will be determined * @returns the distance in world coordinates between the nearest point in point set and the given point */ DistanceType GetMinimalDistance( mitk::PointSet::PointType point ); /** * Finds the nearest neighbour in the point set previously defined by SetPoints(). * The Index and minimal distance between this point and the closest point of the point set is returned. * Please note, that there is no case, in which * no point is found, since as a precondition at least one point has to be contained * in the point set. * @param point the query point, for whom the minimal distance will be determined * @returns the index of and distance (in world coordinates) between the nearest point in point set and the given point */ bool FindClosestPointAndDistance( mitk::PointSet::PointType point, IdType* id, DistanceType* dist); protected: // // Definition of a vector of ids // typedef std::vector IdVectorType; // // ANN related typedefs, to prevent ANN from being in the global include path. // Please note, that these line are prone to failure, if the point type in // ANN changes. Please note also, that these typedefs are only used in the header // file. The implementation always refers to the original types // typedef double* MyANNpoint; typedef int MyANNidx; typedef double MyANNdist; typedef MyANNpoint* MyANNpointArray; typedef MyANNidx* MyANNidxArray; typedef MyANNdist* MyANNdistArray; /** * constructor */ PointLocator(); /** * destructor */ ~PointLocator(); /** * Initializes the ann search tree using previously defined points */ void InitANN(); /** * releases all memory occupied by the ann search tree and internal point set arrays */ void DestroyANN(); /** * Finds the nearest neighbour in the point set previously defined by SetPoints(). * The Id of the point is returned. Please note, that there is no case, in which * no point is found, since as a precondition at least one point has to be contained * in the point set. * @param point the query point, for whom the nearest neighbour will be determined * @returns the id of the nearest neighbour of the given point. The id corresponds to the id * which is given in the original point set. */ IdType FindClosestANNPoint( const MyANNpoint& point); /** * Finds the minimal distance between the given point and a point in the previously defined point set. * The distance is returned. Please note, that there is no case, in which * no distance is found, since as a precondition at least one point has to be contained * in the point set. * @param point the query point, for whom the minimal distance to a point in the previously defined point set will be determined * @returns the squared distance in world coordinates between the given point and the nearest neighbour. */ DistanceType GetMinimalDistance( const MyANNpoint& point); bool m_SearchTreeInitialized; IdVectorType m_IndexToPointIdContainer; vtkPoints* m_VtkPoints; mitk::PointSet* m_MitkPoints; ITKPointSet* m_ItkPoints; // // ANN related variables // unsigned int m_ANNK; unsigned int m_ANNDimension; double m_ANNEpsilon; MyANNpointArray m_ANNDataPoints; MyANNpoint m_ANNQueryPoint; MyANNidxArray m_ANNPointIndexes; MyANNdistArray m_ANNDistances; ANNkd_tree* m_ANNTree; }; } #endif diff --git a/Modules/MitkExt/Algorithms/mitkPolygonToRingFilter.cpp b/Modules/MitkExt/Algorithms/mitkPolygonToRingFilter.cpp index e3035df2c8..d6d8fa0c06 100644 --- a/Modules/MitkExt/Algorithms/mitkPolygonToRingFilter.cpp +++ b/Modules/MitkExt/Algorithms/mitkPolygonToRingFilter.cpp @@ -1,341 +1,341 @@ /*=================================================================== 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 "mitkPolygonToRingFilter.h" #include "mitkMesh.h" #include "mitkSurface.h" #include "mitkPlaneGeometry.h" #include #include #include #include #include #include #include #include mitk::PolygonToRingFilter::PolygonToRingFilter() : m_RingRadius(3.5f), m_RingResolution(30), m_SplineResolution(20) { m_SplineX = vtkCardinalSpline::New(); m_SplineY = vtkCardinalSpline::New(); m_SplineZ = vtkCardinalSpline::New(); } mitk::PolygonToRingFilter::~PolygonToRingFilter() { m_SplineX->Delete(); m_SplineY->Delete(); m_SplineZ->Delete(); } void mitk::PolygonToRingFilter::GenerateOutputInformation() { mitk::Mesh::ConstPointer input = this->GetInput(); mitk::Surface::Pointer output = this->GetOutput(0); itkDebugMacro(<<"GenerateOutputInformation()"); if(input.IsNull()) return; output->SetGeometry(static_cast(input->GetGeometry()->Clone().GetPointer())); output->Expand( input->GetPointSetSeriesSize() ); } void mitk::PolygonToRingFilter::GenerateData() { mitk::Mesh::ConstPointer input = this->GetInput(); mitk::Surface::Pointer output = this->GetOutput(0); unsigned int t; for ( t = 0; t < input->GetPointSetSeriesSize(); ++t ) { vtkPolyData *polyData = vtkPolyData::New(); vtkPoints *vPoints = vtkPoints::New(); vtkCellArray *polys = vtkCellArray::New(); mitk::Mesh::PointType thisPoint; // iterate through all cells and build tubes Mesh::ConstCellIterator cellIt, cellEnd; cellEnd = input->GetMesh( t )->GetCells()->End(); for ( cellIt = input->GetMesh( t )->GetCells()->Begin(); cellIt != cellEnd; ++cellIt ) { m_PointList.clear(); m_VectorList.clear(); this->BuildPointAndVectorList( *cellIt->Value(), m_PointList, m_VectorList, t ); this->BuildVtkTube( vPoints, polys, m_PointList, m_VectorList ); } polyData->SetPoints( vPoints ); vPoints->Delete(); polyData->SetPolys( polys ); polys->Delete(); output->SetVtkPolyData( polyData, t ); polyData->Delete(); } } //sl: last star //sc: current star //idmax: Id of the current star ray (sc), which matchs proberly to the first ray of the last star (sl). //last_p: center of the last star //cur_p: center of the current star void mitk::PolygonToRingFilter::DrawCyl(vtkPoints *vPoints, vtkCellArray *polys, VectorListType &sl, VectorListType &sc, int idmax, Point3D & last_p, Point3D & cur_p) { unsigned int i; //now we finished:sl0 will be connected with sc->at(idmax) VectorListType::iterator slit=sl.begin(), scit=sc.begin(), scend=sc.end(); scit+=idmax; Point3D a,b; Point3D a_first,b_first; int a_firstID = 0, b_firstID = 0; vtkIdType front[4]; for(i=0;iInsertNextPoint(v0[0],v0[1],v0[2]); front[2]=vPoints->InsertNextPoint(v1[0],v1[1],v1[2]); front[1]=vPoints->InsertNextPoint(v2[0],v2[1],v2[2]); front[0]=vPoints->InsertNextPoint(v3[0],v3[1],v3[2]); polys->InsertNextCell( (vtkIdType) 4, front ); if(i==1) { a_firstID=front[3]; b_firstID=front[2]; //continue; } } ++slit; ++scit; if(scit==scend) scit=sc.begin(); } front[3]=front[0]; front[2]=front[1]; front[1]=b_firstID; front[0]=a_firstID; polys->InsertNextCell( 4, front ); } void mitk::PolygonToRingFilter::BuildVtkTube(vtkPoints *vPoints, vtkCellArray *polys, PointListType& ptList, VectorListType& vecList) { PointListType::iterator pit = ptList.begin(), pend = ptList.end(); VectorListType::iterator vit = vecList.begin(); Vector3D axis, last_v, next_v, s; Point3D cur_p,last_p; //lists for the star VectorListType *sl, *sc, *swp, sfirst, buf1, buf2; sl=&buf1; sc=&buf2; Vector3D a,b; Matrix3D m; //Initialization for the first point //alternative1: // last_v=*(vl.getLast()); next_v=*vit.current(); axis=last_v+next_v; s.cross(last_v,next_v); s.normalize(); //alternative2: // last_v=*(vl.getLast()); next_v=*vit.current(); s.cross(last_v,next_v); s.normalize(); // axis=next_v-last_v; axis.normalize(); aa.set(s, M_PI/2.0); m.set(aa); m.transform(&axis); //alternative3: last_v=vecList.back(); next_v=*vit; s.SetVnlVector( vnl_cross_3d(last_v.GetVnlVector(),next_v.GetVnlVector()) ); s.Normalize(); a=last_v; b=next_v; a.Normalize(); b.Normalize(); axis=a+b; axis.Normalize(); //build the star at the first point m = vnl_quaternion(axis.GetVnlVector(),2*vnl_math::pi/(double)m_RingResolution).rotation_matrix_transpose(); unsigned int i; for(i=0;ibegin()); m = vnl_quaternion(axis.GetVnlVector(),2*vnl_math::pi/(double)m_RingResolution).rotation_matrix_transpose(); for(i=0;ipush_back(s); double tmp=s*sl0; if(tmp>max) { max=tmp; idmax=i; } s=m*s; } //sl: last star //sc: current star //idmax: Id of the current star ray (sc), which matchs proberly to the first ray of the last star (sl). //last_p: center of the last star //cur_p: center of the current star DrawCyl(vPoints, polys, *sl, *sc, idmax, last_p, cur_p); //Crossover to the next last_p=cur_p; swp=sl; sl=sc; sc=swp; sc->clear(); } //calcutate idmax for connection: double max=0; int idmax=0; Vector3D sl0=*(sl->begin()); for(i=0;imax) { max=tmp; idmax=i; } } cur_p=*ptList.begin(); DrawCyl(vPoints, polys, *sl, sfirst, idmax, last_p, cur_p); } void mitk::PolygonToRingFilter ::BuildPointAndVectorList( mitk::Mesh::CellType& cell, PointListType& ptList, VectorListType& vecList, int timeStep ) { // This method constructs a spline from the given point list and retrieves // a number of interpolated points from it to form a ring-like structure. // // To make the spline "closed", the end point is connected to the start // point. For ensuring smoothness at the start-end-point transition, the // (intrinsically non-circular) spline array is extended on both sides // by wrapping a number of points from the respective other side. // // The used VTK filters do principally support this kind of "closed" spline, // but it does not produce results as consistent as with the method used // here. Also, the spline class of VTK 4.4 has only poor support for // arbitrary parametric coordinates (t values in vtkSpline). VTK 5.0 has // better support, and also provides a new class vtkParametricSpline for // directly calculating 3D splines. // Remove points from previous call of this method m_SplineX->RemoveAllPoints(); m_SplineY->RemoveAllPoints(); m_SplineZ->RemoveAllPoints(); int numberOfPoints = cell.GetNumberOfPoints(); Mesh::PointType inputPoint; - vtkFloatingPointType t, tStart(0), tEnd(0); + double t, tStart(0), tEnd(0); // Add input points to the spline and assign each the parametric value t // derived from the point euclidean distances. int i; Mesh::PointIdIterator pit = cell.PointIdsEnd() - 3; for ( i = -3, t = 0.0; i < numberOfPoints + 3; ++i ) { if ( i == 0 ) { tStart = t; } if ( i == numberOfPoints ) { tEnd = t; } inputPoint = this->GetInput()->GetPoint( *pit, timeStep ); m_SplineX->AddPoint( t, inputPoint[0] ); m_SplineY->AddPoint( t, inputPoint[1] ); m_SplineZ->AddPoint( t, inputPoint[2] ); ++pit; if ( pit == cell.PointIdsEnd() ) { pit = cell.PointIdsBegin(); } t += inputPoint.EuclideanDistanceTo( this->GetInput()->GetPoint( *pit, timeStep ) ); } // Evaluate the spline for the desired number of points // (number of input points) * (spline resolution) Point3D point, firstPoint, lastPoint; firstPoint.Fill(0); lastPoint.Fill(0); int numberOfSegments = numberOfPoints * m_SplineResolution; - vtkFloatingPointType step = (tEnd - tStart) / numberOfSegments; + double step = (tEnd - tStart) / numberOfSegments; for ( i = 0, t = tStart; i < numberOfSegments; ++i, t += step ) { FillVector3D( point, m_SplineX->Evaluate(t), m_SplineY->Evaluate(t), m_SplineZ->Evaluate(t) ); ptList.push_back( point ); if ( i == 0 ) { firstPoint = point; } else { vecList.push_back( point - lastPoint ); } lastPoint = point; } vecList.push_back( firstPoint - lastPoint ); } const mitk::Mesh *mitk::PolygonToRingFilter::GetInput(void) { if (this->GetNumberOfInputs() < 1) { return 0; } return static_cast (this->ProcessObject::GetInput(0) ); } void mitk::PolygonToRingFilter::SetInput(const mitk::Mesh *input) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(0, const_cast< mitk::Mesh * >( input ) ); } diff --git a/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.cpp b/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.cpp index 81b15a7286..0fb3509445 100644 --- a/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.cpp +++ b/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.cpp @@ -1,138 +1,138 @@ /*=================================================================== 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 "mitkLabeledImageLookupTable.h" #include #include /** * Default constructor. Protected to prevent "normal" creation */ mitk::LabeledImageLookupTable::LabeledImageLookupTable() : m_LevelWindow(128,256) { if ( m_LookupTable == NULL ) { itkWarningMacro("LookupTable is NULL, it should have been initialized by the default constructor of mitk::LookupTable"); m_LookupTable = vtkLookupTable::New(); } m_LookupTable->SetNumberOfTableValues(256); // set the background to black and fully transparent m_LookupTable->SetTableValue( 0, 0.0, 0.0, 0.0, 0.0 ); // initialize the remaining 255 colors with random values and // an alpha value of 1.0 - vtkFloatingPointType r, g, b; + double r, g, b; // // Initialize the random number generator with an arbitrary seed. // This way, the generated colors are random, but always the same... std::srand( 2 ); for ( vtkIdType index = 1 ; index < 256 ; ++index ) { GenerateRandomColor(r, g, b); m_LookupTable->SetTableValue(index, r, g, b); } // initialize the default level/window settings, // which can be accessed via GetLevelWindow(); m_LevelWindow.SetRangeMinMax(0,255); m_LevelWindow.SetWindowBounds(0,255); m_LevelWindow.SetFixed(true); } mitk::LabeledImageLookupTable::LabeledImageLookupTable(const mitk::LabeledImageLookupTable &other) : LookupTable(other) , m_LevelWindow(other.m_LevelWindow) { } /** * Virtual destructor */ mitk::LabeledImageLookupTable::~LabeledImageLookupTable() { } /** * Sets the color for a given label * @param label The pixel value used as a label in the image * @param r The red component of the rgba color value. Values sould be given in the range [0,1] * @param g The green component of the rgba color value. Values sould be given in the range [0,1] * @param b The blue component of the rgba color value. Values sould be given in the range [0,1] * @param a The alpha component of the rgba color value. Values sould be given in the range [0,1]. Default is 1. */ -void mitk::LabeledImageLookupTable::SetColorForLabel ( const mitk::LabeledImageLookupTable::LabelType& label, const vtkFloatingPointType& r, const vtkFloatingPointType& g, const vtkFloatingPointType& b, const vtkFloatingPointType a ) +void mitk::LabeledImageLookupTable::SetColorForLabel ( const mitk::LabeledImageLookupTable::LabelType& label, const double& r, const double& g, const double& b, const double a ) { if ( m_LookupTable == NULL ) { itkWarningMacro("LookupTable is NULL, but it should have been initialized by the constructor"); return; } m_LookupTable->SetTableValue(label, r, g, b, a); } /** * Determines the color which will be used for coloring a given label. * @param label the label for which the color should be returned * @returns an rgba array containing the color information for the given label * Color components are expressed as [0,1] double values. */ -vtkFloatingPointType* mitk::LabeledImageLookupTable::GetColorForLabel ( const mitk::LabeledImageLookupTable::LabelType& label ) +double* mitk::LabeledImageLookupTable::GetColorForLabel ( const mitk::LabeledImageLookupTable::LabelType& label ) { if ( m_LookupTable == NULL ) { itkWarningMacro("LookupTable is NULL, but it should have been initialized by the constructor"); return NULL; } return m_LookupTable->GetTableValue( label ); } /** * Generates a random rgb color value. Values for rgb are in the range * [0,1] */ -void mitk::LabeledImageLookupTable::GenerateRandomColor ( vtkFloatingPointType& r, vtkFloatingPointType& g, vtkFloatingPointType& b ) +void mitk::LabeledImageLookupTable::GenerateRandomColor ( double& r, double& g, double& b ) { r = GenerateRandomNumber(); g = GenerateRandomNumber(); b = GenerateRandomNumber(); } /** * Generates a radnom number drawn from a uniform * distribution in the range [0,1]. */ -vtkFloatingPointType mitk::LabeledImageLookupTable::GenerateRandomNumber() +double mitk::LabeledImageLookupTable::GenerateRandomNumber() { - return ( ( ( vtkFloatingPointType ) ( std::rand( ) ) ) / ( ( vtkFloatingPointType ) ( RAND_MAX ) ) ); + return ( ( ( double ) ( std::rand( ) ) ) / ( ( double ) ( RAND_MAX ) ) ); } itk::LightObject::Pointer mitk::LabeledImageLookupTable::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); return result; } diff --git a/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.h b/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.h index 439edf79cd..9ce21b6844 100644 --- a/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.h +++ b/Modules/MitkExt/DataManagement/mitkLabeledImageLookupTable.h @@ -1,117 +1,117 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMITKLABELEDIMAGELOOKUPTABLE_H #define MITKMITKLABELEDIMAGELOOKUPTABLE_H #include "mitkLookupTable.h" #include "MitkExtExports.h" #include "mitkLevelWindow.h" #include #include namespace mitk { /** * A lookup table for 2D mapping of labeled images. The lookup table supports * images with up to 256 unsigned labels. Negative labels are not supported. * Please use the level/window settings as given by the GetLevelWindow() method * to make sure, that the colors are rendered correctly. * The colors are initialized with random colors as default. As background * the label 0 is assumed. The color for the background is set to fully transparent * as default. */ class MitkExt_EXPORT LabeledImageLookupTable : public LookupTable { public: /** * Standard mitk typedefs are generated by the mitkClassMacro */ mitkClassMacro(LabeledImageLookupTable, LookupTable); /** * Make this object constructable by the ::New() Method. */ itkNewMacro(Self); /** * The data type for a label. Currently only images with labels * in the range [0,255] are supported. */ typedef unsigned char LabelType; /** * Sets the color for a given label * @param label The pixel value used as a label in the image * @param r The red component of the rgba color value. Values sould be given in the range [0,1] * @param g The green component of the rgba color value. Values sould be given in the range [0,1] * @param b The blue component of the rgba color value. Values sould be given in the range [0,1] * @param a The alpha component of the rgba color value. Values sould be given in the range [0,1]. Default is 1. */ - virtual void SetColorForLabel( const LabelType& label, const vtkFloatingPointType& r, const vtkFloatingPointType& g, const vtkFloatingPointType& b, const vtkFloatingPointType a = 1.0 ); + virtual void SetColorForLabel( const LabelType& label, const double& r, const double& g, const double& b, const double a = 1.0 ); /** * Determines the color which will be used for coloring a given label. * @param label the label for which the color should be returned * @returns an rgba array containing the color information for the given label. * Color components are expressed as [0,1] double values. */ - virtual vtkFloatingPointType* GetColorForLabel(const LabelType& label); + virtual double* GetColorForLabel(const LabelType& label); /** * Provides access to level window settings, which should be used * in combination with the LUTs generated by this filter (at lease for * 2D visualization. If you use other level/window settings, it is not * guaranteed, that scalar values are mapped to the correct colors. */ mitk::LevelWindow GetLevelWindow(){return m_LevelWindow;} protected: /** * Default constructor. Protected to prevent "normal" creation */ LabeledImageLookupTable(); LabeledImageLookupTable(const LabeledImageLookupTable& other); /** * Virtual destructor */ virtual ~LabeledImageLookupTable(); /** * Generates a random rgb color value. Values for rgb are in the range * [0,1] */ - virtual void GenerateRandomColor( vtkFloatingPointType& r, vtkFloatingPointType& g, vtkFloatingPointType& b); + virtual void GenerateRandomColor( double& r, double& g, double& b); /** * Generates a radnom number drawn from a uniform * distribution in the range [0,1]. */ - virtual vtkFloatingPointType GenerateRandomNumber(); + virtual double GenerateRandomNumber(); mitk::LevelWindow m_LevelWindow; private: itk::LightObject::Pointer InternalClone() const; }; } #endif diff --git a/Modules/MitkExt/DataManagement/mitkUSLookupTableSource.cpp b/Modules/MitkExt/DataManagement/mitkUSLookupTableSource.cpp index 4dd9ee6ab5..1e701ac02e 100644 --- a/Modules/MitkExt/DataManagement/mitkUSLookupTableSource.cpp +++ b/Modules/MitkExt/DataManagement/mitkUSLookupTableSource.cpp @@ -1,408 +1,408 @@ /*=================================================================== 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 "mitkUSLookupTableSource.h" #include #include #include extern "C" { #include "uscfunctions/usc.h" } mitk::USLookupTableSource::~USLookupTableSource() {} mitk::USLookupTableSource::USLookupTableSource() : mitk::LookupTableSource() { std::cout << "creating USLookupTableSource ... " << std::endl; m_Mode = DefaultLUT; m_LookupTable = NULL; this->Modified(); std::cout << "creating USLookupTableSource OK! " << std::endl; } void mitk::USLookupTableSource::GenerateData() { std::cout << "USLookupTableSource::generate data!" << std::endl; OutputType::Pointer output = this->GetOutput(); output->SetVtkLookupTable( this->BuildVtkLookupTable( ) ); } vtkLookupTable* mitk::USLookupTableSource::BuildDSRDopplerLookupTable() { std::cout << " creating HP LookupTable ... " << std::endl; mitkIpPicDescriptor *HPMap; char MapFilename[ 20 ] = "a.map"; int failed ; ifstream infile ( MapFilename, ios::in ); failed = infile.fail() ; infile.close() ; if ( !failed ) // do we have a HP LUT ? { std::cout << " reading a.map ... " << std::endl; HPMap = usReadMap( "a.map", ".", -1000, -1000 ); vtkLookupTable *vtkLookupTable = vtkLookupTable::New(); mitkIpUInt1_t *data = ( ( mitkIpUInt1_t * ) HPMap->data ); vtkLookupTable->SetTableRange(0,255); int LookupTablesize = 256; - vtkFloatingPointType rgba[ 4 ]; + double rgba[ 4 ]; vtkLookupTable->SetNumberOfColors( LookupTablesize ); for ( int i = 0; i < LookupTablesize; i++ ) { rgba[ 0 ] = ( ( mitkIpUInt1_t * ) data ) [ 0 + i * 3 * LookupTablesize ] / 255.0f; rgba[ 1 ] = ( ( mitkIpUInt1_t * ) data ) [ 1 + i * 3 * LookupTablesize ] / 255.0f ; rgba[ 2 ] = ( ( mitkIpUInt1_t * ) data ) [ 2 + i * 3 * LookupTablesize ] / 255.0f ; rgba[ 3 ] = 1; vtkLookupTable->SetTableValue ( i, rgba ); } return ( vtkLookupTable ); } // do we have a HP LUT ? else // no HP lut -> create custom LUT { std::cout << " no a.map available! creating custom Doppler LookUpTable ... " << std::endl; vtkLookupTable *vtkLookupTable = vtkLookupTable::New(); vtkLookupTable->SetTableRange(0,255); // size is the no of different colors in the lut int size = 256; int lutSize = 256; int repeats = lutSize / size; int factor = 1; int i, n; - vtkFloatingPointType rgba[ 4 ]; + double rgba[ 4 ]; //int xDim = lutSize; //int yDim = 3; int quartalSize = size / 4; int index; for ( i = 1; i <= quartalSize ; i++ ) { for ( n = 0; n < repeats ; n++ ) { index = ( i - 1 ) * repeats + n; rgba[ 0 ] = 0; // rot rgba[ 1 ] = 1 - i / 2.0 / quartalSize; // gruen rgba[ 2 ] = 1; // blau rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } } // dunkelblau for ( i = 1; i <= quartalSize ; i++ ) { for ( n = 0; n < repeats ; n++ ) { index = ( i - 1 ) * repeats + repeats * quartalSize + n; rgba[ 0 ] = 0; rgba[ 1 ] = 0.5 - i / 2.0 / quartalSize; rgba[ 2 ] = 1 - i / ( float ) ( 2 * quartalSize ); rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } } // dunkelrot for ( i = 1; i <= quartalSize ; i++ ) { for ( n = 0; n < repeats ; n++ ) { index = ( i - 1 ) * repeats + ( 2 * repeats * quartalSize ) + n; rgba[ 0 ] = 0.5 + i / ( float ) ( 2 * quartalSize ); rgba[ 1 ] = i / 2.0 / quartalSize; rgba[ 2 ] = 0; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } } // hellrot for ( i = 1; i <= quartalSize ; i++ ) { for ( n = 0; n < repeats ; n++ ) { index = ( i - 1 ) * repeats + ( 3 * repeats * quartalSize ) + n; rgba[ 0 ] = 1; rgba[ 1 ] = 0.5 + i / 2.0 / quartalSize; rgba[ 2 ] = 0; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } } // the value 0 is mapped to black // so we see the field-out-of-view as black index = 0; rgba[ 0 ] = 0; rgba[ 1 ] = 0; rgba[ 2 ] = 0; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue( index, rgba ); int mapZeroVelocityToBlack = 1; if ( mapZeroVelocityToBlack == 1 ) { // map the middle value to black, so no velocity (v=0) // is displayed as black, otherwise darkred rgba[ 0 ] = 0; rgba[ 1 ] = 0; rgba[ 2 ] = 0; rgba[ 3 ] = factor * 1; index = lutSize / 2 ; vtkLookupTable->SetTableValue( index, rgba ); // index = lutSize / 2 - 1; // vtkLookupTable->SetTableValue( index, rgba ); // index = lutSize / 2 + 1; vtkLookupTable->SetTableValue( index, rgba ); } // for (int i=0; iGetTableValue(i,&rgba[0]); // cout << "i=" << i << " r=" << rgba[0] << " g=" << rgba[1]<< " b=" << rgba[2] << endl; // } return( vtkLookupTable ); } // no HP lut -> create custom LUT } vtkLookupTable* mitk::USLookupTableSource::BuildStrainRateLookupTable() { std::cout << " creating StrainRate LookupTable ... " << std::endl; vtkLookupTable *vtkLookupTable = vtkLookupTable::New(); vtkLookupTable->SetTableRange(0,255); int lutSize = 256; vtkLookupTable->SetNumberOfTableValues(lutSize); // xDim = size; // yDim = 3; - vtkFloatingPointType rgba[ 4 ]; + double rgba[ 4 ]; float quartal = lutSize / 8.0f; float sizeQuartal1 = 3 * quartal; //quartal-1; float sizeQuartal2 = 0.9375 * quartal; float sizeZeroStrain = 0.125 * quartal; float sizeQuartal3 = 0.9375 * quartal; // float sizeQuartal2 = 0.875 * quartal; // float sizeZeroStrain = 0.25* quartal; // float sizeQuartal3 = 0.875 * quartal; // float sizeQuartal2 = 0.975 * quartal; // float sizeZeroStrain = 0.05* quartal; // float sizeQuartal3 = 0.975 * quartal; float sizeQuartal4 = 3 * quartal; // std::cout << "quartal = " << quartal << std::endl; // std::cout << "quartal 1 = " << sizeQuartal1 << std::endl; // std::cout << "quartal 2 = " << sizeQuartal2 << std::endl; // std::cout << "quartal 3 = " << sizeQuartal3 << std::endl; // std::cout << "quartal 4 = " << sizeQuartal4 << std::endl; // std::cout << "quartal zero = " << sizeZeroStrain << std::endl; int factor = 1; int i; // dunkelrot for ( i = 1; i <= sizeQuartal1; i++ ) { int index = i - 1; rgba[ 0 ] = factor * ( 0.5 + i / ( 2 * sizeQuartal1 ) ); // rot rgba[ 1 ] = factor * 0; // gruen rgba[ 2 ] = factor * 0; // blau rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } // hellrot bis gelb for ( i = 1 ; i <= sizeQuartal2 ; i++ ) { int index = ( i - 1 ) + ( int ) sizeQuartal1; rgba[ 0 ] = factor * 1; rgba[ 1 ] = factor * ( i / sizeQuartal2 ); rgba[ 2 ] = factor * 0; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } //gruen for ( i = 1 ; i <= sizeZeroStrain ; i++ ) { int index = ( i - 1 ) + ( int ) ( sizeQuartal1 + sizeQuartal2 ); rgba[ 0 ] = factor * 0; //1 - i/sizeZeroStrain; rgba[ 1 ] = factor * 1; rgba[ 2 ] = factor * 0; //i/sizeZeroStrain; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } // hellblau for ( i = 1 ; i <= sizeQuartal3; i++ ) { int index = ( i - 1 ) + ( int ) ( sizeQuartal1 + sizeQuartal2 + sizeZeroStrain ); rgba[ 0 ] = factor * 0; rgba[ 1 ] = factor * ( 1 - i / sizeQuartal3 ); rgba[ 2 ] = factor * 1; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } // blau for ( i = 1 ; i <= sizeQuartal4 ; i++ ) { int index = ( i - 1 ) + ( int ) ( sizeQuartal1 + sizeQuartal2 + sizeQuartal3 + sizeZeroStrain ); rgba[ 0 ] = factor * 0; rgba[ 1 ] = factor * 0; rgba[ 2 ] = factor * ( 1 - i / sizeQuartal4 ); rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); } // the value 0 is mapped to black // so we see the field-out-of-view as black int index = 0; rgba[ 0 ] = 0; rgba[ 1 ] = 0; rgba[ 2 ] = 0; rgba[ 3 ] = factor * 1; vtkLookupTable->SetTableValue ( index, rgba ); vtkLookupTable->SetTableValue ( index + 1, rgba ); bool mapZeroStrainRateToBlack = true; if ( mapZeroStrainRateToBlack ) { // map the middle value to black, so no velocity (v=0) // is displayed as black rgba[ 0 ] = 0; rgba[ 1 ] = 0; rgba[ 2 ] = 0; rgba[ 3 ] = factor * 1; // index = lutSize / 2 -1; // FIXME: this should be lutSize/2 !!!!???? index = 128 ; // FIXME: this should be lutSize/2 !!!!???? std::cout << " setting table value " << index << " to zero " << std::endl; vtkLookupTable->SetTableValue( index, rgba ); } // for (int i=0; iGetTableValue(i,&rgba[0]); // cout << "i=" << i << " r=" << rgba[0] << " g=" << rgba[1]<< " b=" << rgba[2] << endl; // } // std::cout << " created with " << vtkLookupTable->GetNumberOfColors() << " colors .. " << std::endl; // std::cout << " created with " << vtkLookupTable->GetNumberOfTableValues() << " colors .. " << std::endl; // float data[2]; // vtkLookupTable->GetTableRange (data); // std::cout << " data0=" << data[0] << " data1=" << data[1] << std::endl; // vtkLookupTable->GetTableValue (200, rgba); // std::cout << " r=" << rgba[0] << " g=" << rgba[1] << " b=" << rgba[2]<< " a=" << rgba[3]<< std::endl; // float rgb[3]; // vtkLookupTable->GetColor (200, rgb); // std::cout << " r=" << rgb[0] << " g=" << rgb[1] << " b=" << rgb[2]<< std::endl; // unsigned char *p = vtkLookupTable->GetPointer(200); // std::cout << " p0=" << (int)p[0] << " p1=" << (int)p[1] << " p2=" << (int)p[2]<< std::endl; // p = vtkLookupTable->GetPointer(128); // std::cout << " p0=" << (unsigned int)p[0] << " p1=" <<(unsigned int) p[1] << " p2=" << (unsigned int)p[2]<< std::endl; return( vtkLookupTable ); } vtkLookupTable* mitk::USLookupTableSource::BuildDefaultLookupTable(){ std::cout << " creating default LookupTable... " << std::endl; vtkLookupTable *vtkLookupTable = vtkLookupTable::New(); int size = 256; vtkLookupTable->SetTableRange(0,255); vtkLookupTable->SetNumberOfColors( size ); vtkLookupTable->Build(); return( vtkLookupTable ); } vtkLookupTable* mitk::USLookupTableSource::BuildVtkLookupTable() { std::cout << "mitk::USLookupTableSource::BuildVtkLookupTable() ... " << std::endl; if ( m_Mode == DSRDoppler ) { return BuildDSRDopplerLookupTable(); } else if ( m_Mode == StrainRate ) { return BuildStrainRateLookupTable(); } else { return BuildDefaultLookupTable(); } } diff --git a/Modules/MitkExt/DataManagement/mitkUnstructuredGrid.cpp b/Modules/MitkExt/DataManagement/mitkUnstructuredGrid.cpp index 05ebcd8b1c..0abe926dee 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 ]; - vtkFloatingPointType bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + double bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; if ( ( grid != 0 ) && ( grid->GetNumberOfCells() > 0 ) ) { grid->Update(); 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(); } } Superclass::Update(); } diff --git a/Modules/MitkExt/Interactions/mitkAffineInteractor3D.cpp b/Modules/MitkExt/Interactions/mitkAffineInteractor3D.cpp index 20945e0036..c34ddabfe4 100644 --- a/Modules/MitkExt/Interactions/mitkAffineInteractor3D.cpp +++ b/Modules/MitkExt/Interactions/mitkAffineInteractor3D.cpp @@ -1,488 +1,488 @@ /*=================================================================== 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 "mitkAffineInteractor3D.h" #include "mitkPointOperation.h" #include "mitkPositionEvent.h" #include "mitkStatusBar.h" #include "mitkDataNode.h" #include "mitkInteractionConst.h" #include "mitkAction.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkStateMachineFactory.h" #include "mitkStateTransitionOperation.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkRotationOperation.h" #include #include #include #include #include #include #include #include namespace mitk { //how precise must the user pick the point //default value AffineInteractor3D ::AffineInteractor3D(const char * type, DataNode* dataNode, int /* n */ ) : Interactor( type, dataNode ), m_Precision( 6.5 ), m_InteractionMode( INTERACTION_MODE_TRANSLATION ) { m_OriginalGeometry = Geometry3D::New(); // Initialize vector arithmetic m_ObjectNormal[0] = 0.0; m_ObjectNormal[1] = 0.0; m_ObjectNormal[2] = 1.0; } AffineInteractor3D::~AffineInteractor3D() { } void AffineInteractor3D::SetInteractionMode( unsigned int interactionMode ) { m_InteractionMode = interactionMode; } void AffineInteractor3D::SetInteractionModeToTranslation() { m_InteractionMode = INTERACTION_MODE_TRANSLATION; } void AffineInteractor3D::SetInteractionModeToRotation() { m_InteractionMode = INTERACTION_MODE_ROTATION; } unsigned int AffineInteractor3D::GetInteractionMode() const { return m_InteractionMode; } void AffineInteractor3D::SetPrecision( ScalarType precision ) { m_Precision = precision; } // Overwritten since this class can handle it better! float AffineInteractor3D ::CanHandleEvent(StateEvent const* stateEvent) const { float returnValue = 0.5; // If it is a key event that can be handled in the current state, // then return 0.5 DisplayPositionEvent const *disPosEvent = dynamic_cast (stateEvent->GetEvent()); // Key event handling: if (disPosEvent == NULL) { // Check if the current state has a transition waiting for that key event. if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { return 0.5; } else { return 0.0; } } //on MouseMove do nothing! //if (stateEvent->GetEvent()->GetType() == Type_MouseMove) //{ // return 0.0; //} //if the event can be understood and if there is a transition waiting for that event if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { returnValue = 0.5;//it can be understood } //int timeStep = disPosEvent->GetSender()->GetTimeStep(); //CurveModel *curveModel = dynamic_cast( // m_DataNode->GetData() ); //if ( curveModel != NULL ) //{ // // Get the Geometry2D of the window the user interacts with (for 2D point // // projection) // BaseRenderer *renderer = stateEvent->GetEvent()->GetSender(); // const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D(); // // For reading on the points, Ids etc // //CurveModel::PointSetType *pointSet = curveModel->GetPointSet( timeStep ); // //if ( pointSet == NULL ) // //{ // // return 0.0; // //} //} return returnValue; } bool AffineInteractor3D ::ExecuteAction( Action *action, StateEvent const *stateEvent ) { bool ok = false; // Get data object BaseData *data = m_DataNode->GetData(); if ( data == NULL ) { MITK_ERROR << "No data object present!"; return ok; } // Get Event and extract renderer const Event *event = stateEvent->GetEvent(); BaseRenderer *renderer = NULL; vtkRenderWindow *renderWindow = NULL; vtkRenderWindowInteractor *renderWindowInteractor = NULL; vtkRenderer *currentVtkRenderer = NULL; vtkCamera *camera = NULL; if ( event != NULL ) { renderer = event->GetSender(); if ( renderer != NULL ) { renderWindow = renderer->GetRenderWindow(); if ( renderWindow != NULL ) { renderWindowInteractor = renderWindow->GetInteractor(); if ( renderWindowInteractor != NULL ) { currentVtkRenderer = renderWindowInteractor ->GetInteractorStyle()->GetCurrentRenderer(); if ( currentVtkRenderer != NULL ) { camera = currentVtkRenderer->GetActiveCamera(); } } } } } // Check if we have a DisplayPositionEvent const DisplayPositionEvent *dpe = dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() ); if ( dpe != NULL ) { m_CurrentPickedPoint = dpe->GetWorldPosition(); m_CurrentPickedDisplayPoint = dpe->GetDisplayPosition(); } // Get the timestep to also support 3D+t int timeStep = 0; ScalarType timeInMS = 0.0; if ( renderer != NULL ) { timeStep = renderer->GetTimeStep( data ); timeInMS = renderer->GetTime(); } // If data is an mitk::Surface, extract it Surface *surface = dynamic_cast< Surface * >( data ); vtkPolyData *polyData = NULL; if ( surface != NULL ) { polyData = surface->GetVtkPolyData( timeStep ); // Extract surface normal from surface (if existent, otherwise use default) vtkPointData *pointData = polyData->GetPointData(); if ( pointData != NULL ) { vtkDataArray *normal = polyData->GetPointData()->GetVectors( "planeNormal" ); if ( normal != NULL ) { m_ObjectNormal[0] = normal->GetComponent( 0, 0 ); m_ObjectNormal[1] = normal->GetComponent( 0, 1 ); m_ObjectNormal[2] = normal->GetComponent( 0, 2 ); } } } // Get geometry object m_Geometry = data->GetGeometry( timeStep ); // Make sure that the data (if time-resolved) has enough entries; // if not, create the required extra ones (empty) data->Expand( timeStep+1 ); switch (action->GetActionId()) { case AcDONOTHING: ok = true; break; case AcCHECKOBJECT: { // Re-enable VTK interactor (may have been disabled previously) if ( renderWindowInteractor != NULL ) { renderWindowInteractor->Enable(); } // Check if we have a DisplayPositionEvent const DisplayPositionEvent *dpe = dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() ); if ( dpe == NULL ) { ok = true; break; } // Check if an object is present at the current mouse position DataNode *pickedNode = dpe->GetPickedObjectNode(); StateEvent *newStateEvent; if ( pickedNode == m_DataNode ) { // Yes: object will be selected newStateEvent = new StateEvent( EIDYES ); } else { // No: back to start state newStateEvent = new StateEvent( EIDNO ); } this->HandleEvent( newStateEvent ); ok = true; break; } case AcDESELECTOBJECT: { // Color object white m_DataNode->SetColor( 1.0, 1.0, 1.0 ); RenderingManager::GetInstance()->RequestUpdateAll(); // Colorize surface / wireframe as inactive this->ColorizeSurface( polyData, m_CurrentPickedPoint, -1.0 ); ok = true; break; } case AcSELECTPICKEDOBJECT: { // Color object red m_DataNode->SetColor( 1.0, 0.0, 0.0 ); RenderingManager::GetInstance()->RequestUpdateAll(); // Colorize surface / wireframe dependend on distance from picked point this->ColorizeSurface( polyData, m_CurrentPickedPoint, 0.0 ); ok = true; break; } case AcINITMOVE: { // Disable VTK interactor until MITK interaction has been completed if ( renderWindowInteractor != NULL ) { renderWindowInteractor->Disable(); } // Check if we have a DisplayPositionEvent const DisplayPositionEvent *dpe = dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() ); if ( dpe == NULL ) { ok = true; break; } //DataNode *pickedNode = dpe->GetPickedObjectNode(); m_InitialPickedPoint = m_CurrentPickedPoint; m_InitialPickedDisplayPoint = m_CurrentPickedDisplayPoint; if ( currentVtkRenderer != NULL ) { vtkInteractorObserver::ComputeDisplayToWorld( currentVtkRenderer, m_InitialPickedDisplayPoint[0], m_InitialPickedDisplayPoint[1], 0.0, //m_InitialInteractionPickedPoint[2], m_InitialPickedPointWorld ); } // Make deep copy of current Geometry3D of the plane data->UpdateOutputInformation(); // make sure that the Geometry is up-to-date m_OriginalGeometry = static_cast< Geometry3D * >( data->GetGeometry( timeStep )->Clone().GetPointer() ); ok = true; break; } case AcMOVE: { // Check if we have a DisplayPositionEvent const DisplayPositionEvent *dpe = dynamic_cast< const DisplayPositionEvent * >( stateEvent->GetEvent() ); if ( dpe == NULL ) { ok = true; break; } if ( currentVtkRenderer != NULL ) { vtkInteractorObserver::ComputeDisplayToWorld( currentVtkRenderer, m_CurrentPickedDisplayPoint[0], m_CurrentPickedDisplayPoint[1], 0.0, //m_InitialInteractionPickedPoint[2], m_CurrentPickedPointWorld ); } Vector3D interactionMove; interactionMove[0] = m_CurrentPickedPointWorld[0] - m_InitialPickedPointWorld[0]; interactionMove[1] = m_CurrentPickedPointWorld[1] - m_InitialPickedPointWorld[1]; interactionMove[2] = m_CurrentPickedPointWorld[2] - m_InitialPickedPointWorld[2]; if ( m_InteractionMode == INTERACTION_MODE_TRANSLATION ) { Point3D origin = m_OriginalGeometry->GetOrigin(); Vector3D transformedObjectNormal; data->GetGeometry( timeStep )->IndexToWorld( m_ObjectNormal, transformedObjectNormal ); data->GetGeometry( timeStep )->SetOrigin( origin + transformedObjectNormal * (interactionMove * transformedObjectNormal) ); } else if ( m_InteractionMode == INTERACTION_MODE_ROTATION ) { if ( camera ) { - vtkFloatingPointType vpn[3]; + double vpn[3]; camera->GetViewPlaneNormal( vpn ); Vector3D viewPlaneNormal; viewPlaneNormal[0] = vpn[0]; viewPlaneNormal[1] = vpn[1]; viewPlaneNormal[2] = vpn[2]; Vector3D rotationAxis = itk::CrossProduct( viewPlaneNormal, interactionMove ); rotationAxis.Normalize(); int *size = currentVtkRenderer->GetSize(); double l2 = (m_CurrentPickedDisplayPoint[0] - m_InitialPickedDisplayPoint[0]) * (m_CurrentPickedDisplayPoint[0] - m_InitialPickedDisplayPoint[0]) + (m_CurrentPickedDisplayPoint[1] - m_InitialPickedDisplayPoint[1]) * (m_CurrentPickedDisplayPoint[1] - m_InitialPickedDisplayPoint[1]); double rotationAngle = 360.0 * sqrt(l2/(size[0]*size[0]+size[1]*size[1])); // Use center of data bounding box as center of rotation Point3D rotationCenter = m_OriginalGeometry->GetCenter();; // Reset current Geometry3D to original state (pre-interaction) and // apply rotation RotationOperation op( OpROTATE, rotationCenter, rotationAxis, rotationAngle ); Geometry3D::Pointer newGeometry = static_cast< Geometry3D * >( m_OriginalGeometry->Clone().GetPointer() ); newGeometry->ExecuteOperation( &op ); data->SetClonedGeometry(newGeometry, timeStep); } } RenderingManager::GetInstance()->RequestUpdateAll(); ok = true; break; } default: return Superclass::ExecuteAction( action, stateEvent ); } return ok; } bool AffineInteractor3D::ColorizeSurface( vtkPolyData *polyData, const Point3D & /*pickedPoint*/, double scalar ) { if ( polyData == NULL ) { return false; } //vtkPoints *points = polyData->GetPoints(); vtkPointData *pointData = polyData->GetPointData(); if ( pointData == NULL ) { return false; } vtkDataArray *scalars = pointData->GetScalars(); if ( scalars == NULL ) { return false; } for ( unsigned int i = 0; i < pointData->GetNumberOfTuples(); ++i ) { scalars->SetComponent( i, 0, scalar ); } polyData->Modified(); pointData->Update(); return true; } } // namespace diff --git a/Modules/MitkExt/Interactions/mitkAffineInteractor3D.h b/Modules/MitkExt/Interactions/mitkAffineInteractor3D.h index 1a83deeb3a..9bc2bd6690 100644 --- a/Modules/MitkExt/Interactions/mitkAffineInteractor3D.h +++ b/Modules/MitkExt/Interactions/mitkAffineInteractor3D.h @@ -1,114 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKAFFINEINTERACTOR3D_H_HEADER_INCLUDED #define MITKAFFINEINTERACTOR3D_H_HEADER_INCLUDED #include "mitkInteractor.h" #include "MitkExtExports.h" #include "mitkCommon.h" #include "mitkSurface.h" #include #include namespace mitk { class DataNode; /** * \brief Affine interaction with objects in 3D windows. * * NOTE: The interaction mechanism is similar to that of vtkPlaneWidget * * \ingroup Interaction */ class MitkExt_EXPORT AffineInteractor3D : public Interactor { public: enum { INTERACTION_MODE_TRANSLATION, INTERACTION_MODE_ROTATION }; mitkClassMacro(AffineInteractor3D, Interactor); mitkNewMacro3Param(Self, const char *, DataNode *, int); mitkNewMacro2Param(Self, const char *, DataNode *); void SetInteractionMode( unsigned int interactionMode ); void SetInteractionModeToTranslation(); void SetInteractionModeToRotation(); unsigned int GetInteractionMode() const; /** \brief Sets the amount of precision */ void SetPrecision( ScalarType precision ); /** * \brief calculates how good the data, this statemachine handles, is hit * by the event. * * overwritten, cause we don't look at the boundingbox, we look at each point */ virtual float CanHandleEvent(StateEvent const *stateEvent) const; protected: /** * \brief Constructor with Param n for limited Set of Points * * if no n is set, then the number of points is unlimited* */ AffineInteractor3D(const char *type, DataNode *dataNode, int n = -1); /** * \brief Default Destructor **/ virtual ~AffineInteractor3D(); virtual bool ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ); bool ColorizeSurface( vtkPolyData *polyData, const Point3D &pickedPoint, double scalar = 0.0 ); private: /** \brief to store the value of precision to pick a point */ ScalarType m_Precision; bool m_InteractionMode; Point3D m_InitialPickedPoint; Point2D m_InitialPickedDisplayPoint; - vtkFloatingPointType m_InitialPickedPointWorld[4]; + double m_InitialPickedPointWorld[4]; Point3D m_CurrentPickedPoint; Point2D m_CurrentPickedDisplayPoint; - vtkFloatingPointType m_CurrentPickedPointWorld[4]; + double m_CurrentPickedPointWorld[4]; Geometry3D::Pointer m_Geometry; Geometry3D::Pointer m_OriginalGeometry; Vector3D m_ObjectNormal; }; } #endif /* MITKAFFINEINTERACTOR3D_H_HEADER_INCLUDED */ diff --git a/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp b/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp index d2e3e2b69a..749af5cc05 100644 --- a/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp +++ b/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.cpp @@ -1,498 +1,498 @@ /*=================================================================== 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 "mitkSurfaceDeformationInteractor3D.h" #include "mitkPointOperation.h" #include "mitkDisplayPositionEvent.h" #include "mitkWheelEvent.h" #include "mitkStatusBar.h" #include "mitkDataNode.h" #include "mitkInteractionConst.h" #include "mitkAction.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkStateMachineFactory.h" #include "mitkStateTransitionOperation.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" #include "mitkSurface.h" #include #include #include #include #include #include #include #include //how precise must the user pick the point //default value mitk::SurfaceDeformationInteractor3D ::SurfaceDeformationInteractor3D(const char * type, DataNode* dataNode, int /* n */ ) : Interactor( type, dataNode ), m_Precision( 6.5 ), m_PickedSurfaceNode( NULL ), m_PickedSurface( NULL ), m_GaussSigma( 30.0 ) { m_OriginalPolyData = vtkPolyData::New(); // Initialize vector arithmetic m_ObjectNormal[0] = 0.0; m_ObjectNormal[1] = 0.0; m_ObjectNormal[2] = 1.0; } mitk::SurfaceDeformationInteractor3D::~SurfaceDeformationInteractor3D() { m_OriginalPolyData->Delete(); } void mitk::SurfaceDeformationInteractor3D::SetPrecision( mitk::ScalarType precision ) { m_Precision = precision; } // Overwritten since this class can handle it better! float mitk::SurfaceDeformationInteractor3D ::CanHandleEvent(StateEvent const* stateEvent) const { float returnValue = 0.5; // If it is a key event that can be handled in the current state, // then return 0.5 mitk::DisplayPositionEvent const *disPosEvent = dynamic_cast (stateEvent->GetEvent()); // Key event handling: if (disPosEvent == NULL) { // Check if the current state has a transition waiting for that key event. if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { return 0.5; } else { return 0.0; } } //on MouseMove do nothing! //if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove) //{ // return 0.0; //} //if the event can be understood and if there is a transition waiting for that event if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) { returnValue = 0.5;//it can be understood } //int timeStep = disPosEvent->GetSender()->GetTimeStep(); //mitk::CurveModel *curveModel = dynamic_cast( // m_DataNode->GetData() ); //if ( curveModel != NULL ) //{ // // Get the Geometry2D of the window the user interacts with (for 2D point // // projection) // mitk::BaseRenderer *renderer = stateEvent->GetEvent()->GetSender(); // const Geometry2D *projectionPlane = renderer->GetCurrentWorldGeometry2D(); // // For reading on the points, Ids etc // //mitk::CurveModel::PointSetType *pointSet = curveModel->GetPointSet( timeStep ); // //if ( pointSet == NULL ) // //{ // // return 0.0; // //} //} return returnValue; } bool mitk::SurfaceDeformationInteractor3D ::ExecuteAction( Action *action, mitk::StateEvent const *stateEvent ) { bool ok = false; // Get data object mitk::BaseData *data = m_DataNode->GetData(); if ( data == NULL ) { MITK_ERROR << "No data object present!"; return ok; } // Get mitk::Event and extract renderer const mitk::Event *event = stateEvent->GetEvent(); mitk::BaseRenderer *renderer = NULL; vtkRenderWindow *renderWindow = NULL; vtkRenderWindowInteractor *renderWindowInteractor = NULL; if ( event != NULL ) { renderer = event->GetSender(); if ( renderer != NULL ) { renderWindow = renderer->GetRenderWindow(); if ( renderWindow != NULL ) { renderWindowInteractor = renderWindow->GetInteractor(); } } } // Check if we have a DisplayPositionEvent const mitk::DisplayPositionEvent *dpe = dynamic_cast< const mitk::DisplayPositionEvent * >( stateEvent->GetEvent() ); if ( dpe != NULL ) { m_PickedSurfaceNode = dpe->GetPickedObjectNode(); m_CurrentPickedPoint = dpe->GetWorldPosition(); m_CurrentPickedDisplayPoint = dpe->GetDisplayPosition(); } // Get the timestep to also support 3D+t int timeStep = 0; mitk::ScalarType timeInMS = 0.0; if ( renderer != NULL ) { timeStep = renderer->GetTimeStep( data ); timeInMS = renderer->GetTime(); } // Extract surface m_Surface = dynamic_cast< Surface * >( data ); if ( m_Surface != NULL ) { m_PolyData = m_Surface->GetVtkPolyData( timeStep ); } else { m_PolyData = NULL; } // Extract surface normal from surface (if existent, otherwise use default) vtkPointData *pointData = m_PolyData->GetPointData(); if ( pointData != NULL ) { vtkDataArray *normal = m_PolyData->GetPointData()->GetVectors( "planeNormal" ); if ( normal != NULL ) { m_ObjectNormal[0] = normal->GetComponent( 0, 0 ); m_ObjectNormal[1] = normal->GetComponent( 0, 1 ); m_ObjectNormal[2] = normal->GetComponent( 0, 2 ); } } // Get geometry object m_Geometry = data->GetGeometry( timeStep ); // Make sure that the data (if time-resolved) has enough entries; // if not, create the required extra ones (empty) data->Expand( timeStep+1 ); switch (action->GetActionId()) { case AcDONOTHING: ok = true; break; case AcCHECKOBJECT: { // Check if an object is present at the current mouse position m_PickedSurface = NULL; m_PickedPolyData = NULL; if ( m_PickedSurfaceNode != NULL ) { m_PickedSurface = dynamic_cast< mitk::Surface * >( m_PickedSurfaceNode->GetData() ); if ( m_PickedSurface != NULL ) { m_PickedPolyData = m_PickedSurface->GetVtkPolyData( timeStep ); } } mitk::StateEvent *newStateEvent; if ( (m_PickedSurfaceNode == m_DataNode) && (m_PickedSurface != NULL) ) { // Yes: object will be selected newStateEvent = new mitk::StateEvent( EIDYES ); // Disable VTK interactor until MITK interaction has been completed if ( renderWindowInteractor != NULL ) { renderWindowInteractor->Disable(); } } else { // No: back to start state newStateEvent = new mitk::StateEvent( EIDNO ); // Re-enable VTK interactor (may have been disabled previously) if ( renderWindowInteractor != NULL ) { renderWindowInteractor->Enable(); } } this->HandleEvent( newStateEvent ); // Colorized surface at current picked position m_SurfaceColorizationCenter = m_CurrentPickedPoint; ok = true; break; } case AcDESELECTOBJECT: { // Color object white m_DataNode->SetColor( 1.0, 1.0, 1.0 ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // Colorize surface / wireframe as inactive this->ColorizeSurface( m_PolyData, m_SurfaceColorizationCenter, COLORIZATION_CONSTANT, -1.0 ); ok = true; break; } case AcSELECTPICKEDOBJECT: { // Color object red m_DataNode->SetColor( 1.0, 0.0, 0.0 ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // Colorize surface / wireframe dependend on distance from picked point this->ColorizeSurface( m_PolyData, m_SurfaceColorizationCenter, COLORIZATION_GAUSS ); ok = true; break; } case AcINITMOVE: { // Store current picked point m_InitialPickedPoint = m_CurrentPickedPoint; m_InitialPickedDisplayPoint = m_CurrentPickedDisplayPoint; if ( renderWindowInteractor != NULL ) { vtkInteractorObserver::ComputeDisplayToWorld( renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer(), m_InitialPickedDisplayPoint[0], m_InitialPickedDisplayPoint[1], 0.0, //m_InitialInteractionPickedPoint[2], m_InitialPickedPointWorld ); } // Make deep copy of vtkPolyData interacted on m_OriginalPolyData->DeepCopy( m_PolyData ); ok = true; break; } case AcMOVE: { if ( renderWindowInteractor != NULL ) { vtkInteractorObserver::ComputeDisplayToWorld( renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer(), m_CurrentPickedDisplayPoint[0], m_CurrentPickedDisplayPoint[1], 0.0, //m_InitialInteractionPickedPoint[2], m_CurrentPickedPointWorld ); } // Calculate mouse move in 3D space mitk::Vector3D interactionMove; interactionMove[0] = m_CurrentPickedPointWorld[0] - m_InitialPickedPointWorld[0]; interactionMove[1] = m_CurrentPickedPointWorld[1] - m_InitialPickedPointWorld[1]; interactionMove[2] = m_CurrentPickedPointWorld[2] - m_InitialPickedPointWorld[2]; // Transform mouse move into geometry space data->UpdateOutputInformation(); // make sure that the Geometry is up-to-date mitk::Point3D origin; origin.Fill( 0.0 ); mitk::Vector3D interactionMoveIndex; m_Geometry->WorldToIndex( interactionMove, interactionMoveIndex ); // Get picked point and transform into local coordinates mitk::Point3D pickedPoint; m_Geometry->WorldToIndex( m_InitialPickedPoint, pickedPoint ); mitk::Vector3D v1 = pickedPoint.GetVectorFromOrigin(); mitk::Vector3D v2 = m_ObjectNormal * (interactionMoveIndex * m_ObjectNormal); vtkPoints *originalPoints = m_OriginalPolyData->GetPoints(); vtkPoints *deformedPoints = m_PolyData->GetPoints(); double denom = m_GaussSigma * m_GaussSigma * 2; double point[3]; for ( unsigned int i = 0; i < deformedPoints->GetNumberOfPoints(); ++i ) { // Get original point - vtkFloatingPointType *originalPoint = originalPoints->GetPoint( i ); + double *originalPoint = originalPoints->GetPoint( i ); mitk::Vector3D v0; v0[0] = originalPoint[0]; v0[1] = originalPoint[1]; v0[2] = originalPoint[2]; // Calculate distance of this point from line through picked point double d = itk::CrossProduct( m_ObjectNormal, (v1 - v0) ).GetNorm(); mitk::Vector3D t = v2 * exp( - d * d / denom ); point[0] = originalPoint[0] + t[0]; point[1] = originalPoint[1] + t[1]; point[2] = originalPoint[2] + t[2]; deformedPoints->SetPoint( i, point ); } // Make sure that surface is colorized at initial picked position // as long as we are in deformation state m_SurfaceColorizationCenter = m_InitialPickedPoint; m_PolyData->Modified(); m_Surface->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); ok = false; break; } case AcMODIFY: { // Check if we have an mitk::WheelEvent const mitk::WheelEvent *we = dynamic_cast< const mitk::WheelEvent * >( stateEvent->GetEvent() ); if ( we == NULL ) { ok = true; break; } m_GaussSigma += (double) (we->GetDelta()) / 20;; if ( m_GaussSigma < 10.0 ) { m_GaussSigma = 10.0; } else if ( m_GaussSigma > 128.0 ) { m_GaussSigma = 128.0; } // Colorize surface / wireframe dependend on sigma and distance from picked point this->ColorizeSurface( m_PolyData, m_SurfaceColorizationCenter, COLORIZATION_GAUSS ); mitk::RenderingManager::GetInstance()->RequestUpdateAll( mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS ); ok = true; break; } default: return Superclass::ExecuteAction( action, stateEvent ); } return ok; } bool mitk::SurfaceDeformationInteractor3D::ColorizeSurface( vtkPolyData *polyData, const Point3D &pickedPoint, int mode, double scalar ) { if ( polyData == NULL ) { return false; } vtkPoints *points = polyData->GetPoints(); vtkPointData *pointData = polyData->GetPointData(); if ( pointData == NULL ) { return false; } vtkDataArray *scalars = pointData->GetScalars(); if ( scalars == NULL ) { return false; } if ( mode == COLORIZATION_GAUSS ) { // Get picked point and transform into local coordinates mitk::Point3D localPickedPoint; m_Geometry->WorldToIndex( pickedPoint, localPickedPoint ); mitk::Vector3D v1 = localPickedPoint.GetVectorFromOrigin(); double denom = m_GaussSigma * m_GaussSigma * 2; for ( unsigned int i = 0; i < points->GetNumberOfPoints(); ++i ) { // Get original point - vtkFloatingPointType *point = points->GetPoint( i ); + double *point = points->GetPoint( i ); mitk::Vector3D v0; v0[0] = point[0]; v0[1] = point[1]; v0[2] = point[2]; // Calculate distance of this point from line through picked point double d = itk::CrossProduct( m_ObjectNormal, (v1 - v0) ).GetNorm(); double t = exp( - d * d / denom ); scalars->SetComponent( i, 0, t ); } } else if ( mode == COLORIZATION_CONSTANT ) { for ( unsigned int i = 0; i < pointData->GetNumberOfTuples(); ++i ) { scalars->SetComponent( i, 0, scalar ); } } polyData->Modified(); pointData->Update(); return true; } diff --git a/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.h b/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.h index 879850e226..d31c0faabc 100644 --- a/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.h +++ b/Modules/MitkExt/Interactions/mitkSurfaceDeformationInteractor3D.h @@ -1,122 +1,122 @@ /*=================================================================== 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 MITKSURFACEDEFORMATIONINTERACTOR3D_H_HEADER_INCLUDED #define MITKSURFACEDEFORMATIONINTERACTOR3D_H_HEADER_INCLUDED #include "mitkInteractor.h" #include "MitkExtExports.h" #include "mitkCommon.h" #include class vtkPolyData; namespace mitk { class DataNode; class Surface; /** * \brief Affine interaction with objects in 3D windows. * * NOTE: The interaction mechanism is similar to that of vtkPlaneWidget * * \ingroup Interaction */ class MitkExt_EXPORT SurfaceDeformationInteractor3D : public Interactor { public: mitkClassMacro(SurfaceDeformationInteractor3D, Interactor); mitkNewMacro3Param(Self, const char *, DataNode *, int); mitkNewMacro2Param(Self, const char *, DataNode *); /** \brief Sets the amount of precision */ void SetPrecision( ScalarType precision ); /** * \brief calculates how good the data, this statemachine handles, is hit * by the event. * * overwritten, cause we don't look at the boundingbox, we look at each point */ virtual float CanHandleEvent(StateEvent const *stateEvent) const; protected: /** * \brief Constructor with Param n for limited Set of Points * * if no n is set, then the number of points is unlimited* */ SurfaceDeformationInteractor3D(const char *type, DataNode *dataNode, int n = -1); /** * \brief Default Destructor **/ virtual ~SurfaceDeformationInteractor3D(); virtual bool ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ); enum { COLORIZATION_GAUSS, COLORIZATION_CONSTANT }; bool ColorizeSurface( vtkPolyData *polyData, const Point3D &pickedPoint, int mode, double scalar = 0.0 ); private: /** \brief to store the value of precision to pick a point */ ScalarType m_Precision; Point3D m_InitialPickedPoint; Point2D m_InitialPickedDisplayPoint; - vtkFloatingPointType m_InitialPickedPointWorld[4]; + double m_InitialPickedPointWorld[4]; Point3D m_CurrentPickedPoint; Point2D m_CurrentPickedDisplayPoint; - vtkFloatingPointType m_CurrentPickedPointWorld[4]; + double m_CurrentPickedPointWorld[4]; Point3D m_SurfaceColorizationCenter; Vector3D m_ObjectNormal; Geometry3D::Pointer m_Geometry; Surface *m_Surface; vtkPolyData *m_PolyData; DataNode *m_PickedSurfaceNode; Surface *m_PickedSurface; vtkPolyData *m_PickedPolyData; vtkPolyData *m_OriginalPolyData; double m_GaussSigma; }; } #endif /* MITKSURFACEDEFORMATIONINTERACTOR3D_H_HEADER_INCLUDED */ diff --git a/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp index 67625fb791..3615b86be2 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}; - vtkFloatingPointType doubleRgba[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()); sphere->Delete(); } // setup mapper, actor and add to assembly m_SpheresMapper->SetInput(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); 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/mitkSplineMapper2D.cpp b/Modules/MitkExt/Rendering/mitkSplineMapper2D.cpp index 18d1f35445..7174bbb6a9 100755 --- a/Modules/MitkExt/Rendering/mitkSplineMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkSplineMapper2D.cpp @@ -1,193 +1,193 @@ /*=================================================================== 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 "mitkSplineMapper2D.h" #include "mitkSplineVtkMapper3D.h" #include #include #include #include #include #include #include #include void mitk::SplineMapper2D::Paint ( mitk::BaseRenderer * renderer ) { Superclass::Paint ( renderer ); bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; // // get the poly data of the splines in 3D // mitk::SplineVtkMapper3D::Pointer mapper3D = dynamic_cast ( this->GetDataNode()->GetMapper ( 2 ) ); if ( mapper3D.IsNull() ) { itkWarningMacro ( "Mapper used for 3D mapping is not a mitk::SplineVtkMapper3D!" ); return; } // // update the 3D spline, if the accoring mapper has not been updated yet // //if ( mapper3D->GetLastUpdateTime() < GetDataNode()->GetData()->GetMTime() ) mapper3D->UpdateSpline(); vtkPolyData* spline3D = NULL; if ( mapper3D->SplinesAreAvailable() ) spline3D = mapper3D->GetSplinesPolyData(); else return; if ( spline3D == NULL ) { itkWarningMacro ( "3D spline is not available!" ); return; } // // get the transform associated with the data tree node // vtkLinearTransform* transform = this->GetDataNode()->GetVtkTransform(); if ( transform == NULL ) { itkWarningMacro("transfrom is NULL"); } // // get the plane geometry of the current renderer // mitk::Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); if ( worldGeometry.IsNull() ) { itkWarningMacro("worldGeometry is NULL!"); return; } PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast ( worldGeometry.GetPointer() ); if ( worldPlaneGeometry.IsNull() ) { itkWarningMacro("worldPlaneGeometry is NULL!"); return; } // // determine color of the spline // float color[3]; this->GetDataNode()->GetColor ( color, renderer ); // // iterate over the points // vtkPoints *vpoints = spline3D->GetPoints(); vtkCellArray *vlines = spline3D->GetLines(); if (vpoints == NULL) { itkWarningMacro("points are NULL!"); return; } if (vlines == NULL) { itkWarningMacro("lines are NULL!"); return; } mitk::Point3D currentPoint3D; mitk::Point2D currentPoint2D; - vtkFloatingPointType currentPoint3DVtk[3]; + double currentPoint3DVtk[3]; vlines->InitTraversal(); int numberOfLines = vlines->GetNumberOfCells(); - vtkFloatingPointType currentPointDistance; + double currentPointDistance; for ( int i = 0;i < numberOfLines; ++i ) { bool previousPointOnPlane = false; bool currentPointOnPlane = false; vtkIdType* cell ( NULL ); vtkIdType cellSize ( 0 ); vlines->GetNextCell ( cellSize, cell ); for ( int j = 0 ; j < cellSize; ++j ) { vpoints->GetPoint ( cell[j], currentPoint3DVtk ); // take transformation via vtktransform into account transform->TransformPoint ( currentPoint3DVtk, currentPoint3DVtk ); vtk2itk ( currentPoint3DVtk, currentPoint3D ); // check if the point has a distance to the plane // which is smaller than m_MaxProjectionDistance currentPointDistance = worldPlaneGeometry->DistanceFromPlane ( currentPoint3D ); if ( currentPointDistance < m_MaxProjectionDistance ) { currentPointOnPlane = true; //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map ( currentPoint3D, currentPoint2D ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) renderer->GetDisplayGeometry()->WorldToDisplay ( currentPoint2D, currentPoint2D ); } else currentPointOnPlane = false; // // check if we have to begin or end a GL_LINE // if ( ( previousPointOnPlane == false ) && ( currentPointOnPlane == true ) ) { glLineWidth ( m_LineWidth ); glColor3f ( color[0], color[1], color[2] ); glBegin ( GL_LINE_STRIP ); } else if ( ( previousPointOnPlane == true ) && ( currentPointOnPlane == false ) ) { glEnd (); glLineWidth ( 1.0 ); } // the current ponit is on the plane, add it as point to the // line segment if ( currentPointOnPlane == true ) { glVertex2f ( currentPoint2D[0], currentPoint2D[1] ); } previousPointOnPlane = currentPointOnPlane; } // the last point of the spline segment is on the plane, thus we have to // close the GL_LINE if ( previousPointOnPlane == true ) { glEnd (); glLineWidth ( 1.0 ); } previousPointOnPlane = false; } } void mitk::SplineMapper2D::ApplyProperties ( mitk::BaseRenderer* renderer ) { ApplyColorAndOpacityProperties ( renderer ); } mitk::SplineMapper2D::SplineMapper2D() { m_MaxProjectionDistance = 1; m_ShowDistantLines = false ; m_LineWidth = 1; } mitk::SplineMapper2D::~SplineMapper2D() {} diff --git a/Modules/MitkExt/Rendering/mitkSplineMapper2D.h b/Modules/MitkExt/Rendering/mitkSplineMapper2D.h index 6743f83f85..82923ed312 100755 --- a/Modules/MitkExt/Rendering/mitkSplineMapper2D.h +++ b/Modules/MitkExt/Rendering/mitkSplineMapper2D.h @@ -1,85 +1,85 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSplineMapper2D_H_HEADER_INCLUDED #define MITKSplineMapper2D_H_HEADER_INCLUDED #include "mitkCommon.h" #include "MitkExtExports.h" #include "mitkGLMapper.h" #include "mitkPointSetGLMapper2D.h" #include namespace mitk { class BaseRenderer; class PointSet; //##Documentation //## @brief OpenGL-based mapper to display a spline based on a mitk::PointSet in a 2D window. //## /** This mapper can actually more than just draw a number of points of a * mitk::PointSet. If you set the right properties of the mitk::DataNode, * which contains the point set, then this mapper will also draw lines * connecting the points, and calculate and display distances and angles * between adjacent points. Here is a complete list of boolean properties, * which might be of interest: * * - \b "show contour": Draw not only the points but also the connections between * them (default false) * - \b "line width": IntProperty which gives the width of the contour lines * - \b "show points": Wheter or not to draw the actual points (default true) * - \b "show distances": Wheter or not to calculate and print the distance * between adjacent points (default false) * - \b "show angles": Wheter or not to calculate and print the angle between * adjacent points (default false) * - \b "show distant lines": When true, the mapper will also draw contour * lines that are far away form the current slice (default true) * - \b "label": StringProperty with a label for this point set */ //## @ingroup Mapper /** \deprecatedSince{2013_06} This mapper is deprecated. */ class DEPRECATED() MitkExt_EXPORT SplineMapper2D : public PointSetGLMapper2D { public: mitkClassMacro ( SplineMapper2D, PointSetGLMapper2D ); itkNewMacro ( Self ); virtual void Paint ( mitk::BaseRenderer * renderer ); virtual void ApplyProperties ( mitk::BaseRenderer* renderer ); - itkSetMacro ( MaxProjectionDistance, vtkFloatingPointType ); + itkSetMacro ( MaxProjectionDistance, double ); - itkGetMacro ( MaxProjectionDistance, vtkFloatingPointType ); + itkGetMacro ( MaxProjectionDistance, double ); protected: SplineMapper2D(); virtual ~SplineMapper2D(); - vtkFloatingPointType m_MaxProjectionDistance; + double m_MaxProjectionDistance; }; } // namespace mitk #endif /* MITKSplineMapper2D_H_HEADER_INCLUDED */ diff --git a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp index a7108fceaf..9723e63bf8 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 - vtkFloatingPointType rgba[ 4 ] = {1.0f, 1.0f, 1.0f, 1.0f};//white + 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 ); 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 11c4748d44..adfc70113f 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; } - vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; + 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_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/mitkVectorImageMapper2D.cpp b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp index df31c17e23..7592f714a5 100644 --- a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp @@ -1,538 +1,538 @@ /*=================================================================== 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 ; } - vtkFloatingPointType vp[ 3 ], vp_slice[ 3 ], vnormal[ 3 ]; + 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->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); - vtkFloatingPointType inVector[ 3 ], outVector[3], wnormal[3]; //, tmpVector[ 3 ], outVector[ 3 ]; - vtkFloatingPointType k = 0.0; + 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->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, vtkFloatingPointType *spacing ) +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; - vtkFloatingPointType offset[3]; + 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 ) { - vtkFloatingPointType vp[ 3 ]; + double vp[ 3 ]; cell = glyphs->GetCell( cellId ); idList = cell->GetPointIds(); int numPoints = idList->GetNumberOfIds(); if(numPoints == 1) { //take transformation via vtktransform into account - vtkFloatingPointType pos[ 3 ],vp_raster[3]; + 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]; - vtkFloatingPointType tmp[ 3 ]; + 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 - vtkFloatingPointType * color; + 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/mitkVectorImageMapper2D.h b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h index 28013b1380..cfca9d892e 100644 --- a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h +++ b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h @@ -1,93 +1,93 @@ /*=================================================================== 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_VECTOR_IMAGE_MAPPER_2D__H_ #define _MITK_VECTOR_IMAGE_MAPPER_2D__H_ #include "MitkExtExports.h" #include "mitkCommon.h" #include "mitkGLMapper.h" #include "mitkImage.h" class vtkLookupTable; class vtkScalarsToColors; class vtkImageReslice; class vtkPolyData; class vtkGlyph2D; class vtkPlane; class vtkCutter; namespace mitk { class BaseRenderer; class Geometry2D; class DisplayGeometry; class MitkExt_EXPORT VectorImageMapper2D : public GLMapper { public: mitkClassMacro( VectorImageMapper2D, GLMapper ); itkNewMacro( Self ); - typedef vtkFloatingPointType vtkScalarType; + typedef double vtkScalarType; /** * @returns the image held by the associated with the mapper or the image * which has been explicitly set by SetImage(...) */ const mitk::Image * GetInput( void ); virtual void Paint( mitk::BaseRenderer * renderer ); /** * Explicitly set an vector image. This image will be used for * rendering instead of the image returned by GetData() */ itkSetConstObjectMacro( Image, mitk::Image ); /** * Get the explicitly set image * @returns NULL if no Image has been set instead of GetData(); */ itkGetConstObjectMacro( Image, mitk::Image ); - virtual void PaintCells( vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, BaseRenderer* renderer, vtkScalarsToColors *lut, mitk::Color color, float lwidth, vtkFloatingPointType *spacing ); + virtual void PaintCells( vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, BaseRenderer* renderer, vtkScalarsToColors *lut, mitk::Color color, float lwidth, double *spacing ); protected: int GetCurrentTimeStep( mitk::BaseData* data, mitk::BaseRenderer* renderer ); VectorImageMapper2D(); virtual ~VectorImageMapper2D(); mitk::Image::ConstPointer m_Image; vtkLookupTable *m_LUT; vtkPlane* m_Plane; vtkCutter* m_Cutter; }; } // namespace mitk #endif diff --git a/Modules/MitkExt/Testing/mitkPointLocatorTest.cpp b/Modules/MitkExt/Testing/mitkPointLocatorTest.cpp index b9745a583b..3dbff18e17 100644 --- a/Modules/MitkExt/Testing/mitkPointLocatorTest.cpp +++ b/Modules/MitkExt/Testing/mitkPointLocatorTest.cpp @@ -1,167 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include -vtkFloatingPointType GenerateRandomNumber( const vtkFloatingPointType& min = 0.0, const vtkFloatingPointType& max = 100.0 ) +double GenerateRandomNumber( const double& min = 0.0, const double& max = 100.0 ) { - return ( ( ( vtkFloatingPointType ) ( std::rand( ) ) ) / ( ( vtkFloatingPointType ) ( RAND_MAX ) ) ) * ( max - min) + min; + return ( ( ( double ) ( std::rand( ) ) ) / ( ( double ) ( RAND_MAX ) ) ) * ( max - min) + min; } -void GenerateRandomPoint( vtkFloatingPointType& x, vtkFloatingPointType& y, vtkFloatingPointType& z, const vtkFloatingPointType& min = 0.0, const vtkFloatingPointType& max = 100.0 ) +void GenerateRandomPoint( double& x, double& y, double& z, const double& min = 0.0, const double& max = 100.0 ) { x = GenerateRandomNumber(min, max); y = GenerateRandomNumber(min, max); z = GenerateRandomNumber(min, max); } int mitkPointLocatorTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN("mitkPointLocator"); std::srand( 1 ); unsigned int num_points = 10000; // Create PointSet with randomly defined point MITK_TEST_OUTPUT(<< "Creating random point set of 10000 points "); vtkPoints* points = vtkPoints::New(); for (unsigned int i = 0; i < num_points ; ++i ) { points->InsertPoint(i, GenerateRandomNumber(), GenerateRandomNumber(), GenerateRandomNumber()); } vtkPolyData* pointSet = vtkPolyData::New(); pointSet->SetPoints( points ); points->Delete(); MITK_TEST_CONDITION_REQUIRED((unsigned) pointSet->GetNumberOfPoints()== num_points,"Test number of points in vtkPointSet"); // feed the point set into a vtk point locator MITK_TEST_OUTPUT(<< "Building vtkPointLocator "); vtkPointLocator* vtkPointLoc = vtkPointLocator::New(); vtkPointLoc->SetDataSet( pointSet ); vtkPointLoc->BuildLocator(); MITK_TEST_OUTPUT(<< "[PASSED]"); // feed the point set into the mitk point locator MITK_TEST_OUTPUT(<< "Building mitkPointLocator "); mitk::PointLocator::Pointer mitkPointLocatorInitializedByVtkPointSet = mitk::PointLocator::New(); mitk::PointLocator::Pointer mitkPointLocatorInitializedByMITKPointSet = mitk::PointLocator::New(); mitk::PointLocator::Pointer mitkPointLocatorInitializedByITKPointSet = mitk::PointLocator::New(); MITK_TEST_CONDITION_REQUIRED(mitkPointLocatorInitializedByVtkPointSet.IsNotNull(), "Test whether mitkPointLocator is not null"); mitk::PointSet::Pointer mitkPointSet = mitk::PointSet::New(); mitk::PointLocator::ITKPointSet::Pointer itkPointSet = mitk::PointLocator::ITKPointSet::New(); for ( int i=0; iGetNumberOfPoints();i++ ) { mitk::Point3D pnt; pnt[0] = pointSet->GetPoint( i )[0]; pnt[1] = pointSet->GetPoint( i )[1]; pnt[2] = pointSet->GetPoint( i )[2]; mitkPointSet->InsertPoint(i, pnt ); mitk::PointLocator::ITKPointSet::PointType itkPoint; itkPoint[0] = pointSet->GetPoint( i )[0]; itkPoint[1] = pointSet->GetPoint( i )[1]; itkPoint[2] = pointSet->GetPoint( i )[2]; itkPointSet->SetPoint(i,itkPoint); } MITK_TEST_OUTPUT(<< "Setting random point set "); mitkPointLocatorInitializedByVtkPointSet->SetPoints( pointSet ); mitkPointLocatorInitializedByMITKPointSet->SetPoints( mitkPointSet ); mitkPointLocatorInitializedByITKPointSet->SetPoints( itkPointSet ); MITK_TEST_OUTPUT(<< "[PASSED]"); MITK_TEST_OUTPUT(<< "Testing 1000 random points "); // generate N random points and calculate the closest // points with both the vtk and mitk pointlocator. // verify, that the point ids are the same. - vtkFloatingPointType p[3], x, y, z; + double p[3], x, y, z; mitk::PointSet::PointType pointType; for ( unsigned int i = 0 ; i < 100 ; ++i ) { GenerateRandomPoint( x, y, z ); p[0] = x; p[1] = y; p[2] = z; pointType[0] = p[0]; pointType[1] = p[1]; pointType[2] = p[2]; int closestPointReference = vtkPointLoc->FindClosestPoint(p); // ground truth vtkPointLocator int closestPointVTK1 = mitkPointLocatorInitializedByVtkPointSet->FindClosestPoint(p); int closestPointVTK2 = mitkPointLocatorInitializedByVtkPointSet->FindClosestPoint(x, y, z); int closestPointVTK3 = mitkPointLocatorInitializedByVtkPointSet->FindClosestPoint(pointType); int closestPointMITK1 = mitkPointLocatorInitializedByMITKPointSet->FindClosestPoint(p); int closestPointMITK2 = mitkPointLocatorInitializedByMITKPointSet->FindClosestPoint(x, y, z); int closestPointMITK3 = mitkPointLocatorInitializedByMITKPointSet->FindClosestPoint(pointType); int closestPointITK1 = mitkPointLocatorInitializedByITKPointSet->FindClosestPoint(p); int closestPointITK2 = mitkPointLocatorInitializedByITKPointSet->FindClosestPoint(x, y, z); int closestPointITK3 = mitkPointLocatorInitializedByITKPointSet->FindClosestPoint(pointType); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointVTK1,"Test FindClosestPoint() using a point array with a PointLocator initialized with a vtkPointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointVTK2,"Test FindClosestPoint() using single coordinates with a PointLocator initialized with a vtkPointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointVTK3,"Test FindClosestPoint() using an mitk::PointSet with a PointLocator initialized with a vtkPointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointMITK1,"Test FindClosestPoint() using a point array with a PointLocator initialized with a mitk::PointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointMITK2,"Test FindClosestPoint() using single coordinates with a PointLocator initialized with a mitk::PointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointMITK3,"Test FindClosestPoint() using an mitk::PointSet with a PointLocator initialized with a mitk::PointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointITK1,"Test FindClosestPoint() using a point array with a PointLocator initialized with a itk::PointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointITK2,"Test FindClosestPoint() using single coordinates with a PointLocator initialized with a itk::PointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointITK3,"Test FindClosestPoint() using an mitk::PointSet with a PointLocator initialized with a itk::PointSet"); //Test GetMinimalDistance // Get closest point //double* closestPoint = vtkPointLoc->GetPoints()->GetPoint(closestPointReference); double* closestPoint = pointSet->GetPoint(closestPointReference); mitk::PointSet::PointType cP; cP[0] = closestPoint[0]; cP[1] = closestPoint[1]; cP[2] = closestPoint[2]; mitk::PointLocator::DistanceType minimalDistanceReference = cP.SquaredEuclideanDistanceTo(pointType); //mitk::PointLocator::DistanceType minimalDistanceReference = // (x-closestPoint[0])*(x-closestPoint[0])+(y-closestPoint[1])*(y-closestPoint[1])+(z-closestPoint[2])*(z-closestPoint[2]); mitk::PointLocator::DistanceType minimalDistanceVtk = mitkPointLocatorInitializedByVtkPointSet->GetMinimalDistance(pointType); mitk::PointLocator::DistanceType minimalDistanceItk = mitkPointLocatorInitializedByITKPointSet->GetMinimalDistance(pointType); mitk::PointLocator::DistanceType minimalDistanceMITK = mitkPointLocatorInitializedByMITKPointSet->GetMinimalDistance(pointType); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(minimalDistanceReference,minimalDistanceVtk), "Test GetMinimalDistance() using a PointLocator initialized with a vtkPointSet" ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(minimalDistanceReference,minimalDistanceItk), "Test GetMinimalDistance() using a PointLocator initialized with a itkPointSet" ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(minimalDistanceReference,minimalDistanceMITK), "Test GetMinimalDistance() using a PointLocator initialized with a MITKPointSet" ); int closestPointCombinedVtk; mitk::PointLocator::DistanceType minimalDistanceCombinedVtk; mitkPointLocatorInitializedByVtkPointSet->FindClosestPointAndDistance(pointType,&closestPointCombinedVtk,&minimalDistanceCombinedVtk); int closestPointCombinedITK; mitk::PointLocator::DistanceType minimalDistanceCombinedITK; mitkPointLocatorInitializedByITKPointSet->FindClosestPointAndDistance(pointType,&closestPointCombinedITK,&minimalDistanceCombinedITK); int closestPointCombinedMITK; mitk::PointLocator::DistanceType minimalDistanceCombinedMITK; mitkPointLocatorInitializedByMITKPointSet->FindClosestPointAndDistance(pointType,&closestPointCombinedMITK,&minimalDistanceCombinedMITK); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(minimalDistanceReference,minimalDistanceCombinedVtk), "Test distance returned by FindClosestPointAndDistance() using a PointLocator initialized with a vtkPointSet" ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(minimalDistanceReference,minimalDistanceCombinedITK), "Test distance returned by FindClosestPointAndDistance() using a PointLocator initialized with a itkPointSet" ); MITK_TEST_CONDITION_REQUIRED(mitk::Equal(minimalDistanceReference,minimalDistanceCombinedMITK), "Test distance returned by FindClosestPointAndDistance() using a PointLocator initialized with a MITKPointSet" ); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointCombinedVtk,"Test closest point returned by FindClosestPointAndDistance() using a point array with a PointLocator initialized with a vtkPointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointCombinedITK,"Test closest point returned by FindClosestPointAndDistance() using a point array with a PointLocator initialized with a itkPointSet"); MITK_TEST_CONDITION_REQUIRED(closestPointReference==closestPointCombinedMITK,"Test closest point returned by FindClosestPointAndDistance() using a point array with a PointLocator initialized with a MITKPointSet"); } vtkPointLoc->Delete(); pointSet->Delete(); MITK_TEST_END(); } diff --git a/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.cpp b/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.cpp index 8bcc8b5d57..7f4631b38f 100755 --- a/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.cpp +++ b/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.cpp @@ -1,171 +1,171 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkColorTransferFunctionCanvas.h" #include #include #include QmitkColorTransferFunctionCanvas::QmitkColorTransferFunctionCanvas( QWidget * parent, Qt::WindowFlags f) : QmitkTransferFunctionCanvas(parent, f), m_ColorTransferFunction(0) { // used for drawing a border setContentsMargins(1,1,1,1); } void QmitkColorTransferFunctionCanvas::SetTitle(const QString& title) { m_Title=title; } void QmitkColorTransferFunctionCanvas::paintEvent(QPaintEvent*) { QPainter painter(this); // Render gray background QRect contentsRect = this->contentsRect(); painter.setPen(Qt::gray); painter.drawRect(0, 0, contentsRect.width()+1, contentsRect.height()+1); if( ! this->isEnabled() ) return; if (m_ColorTransferFunction) { for (int x = contentsRect.x(); x < contentsRect.x() + contentsRect.width(); x++) { - vtkFloatingPointType xVal = m_Min + ((float) x) / contentsRect.width() * (m_Max + double xVal = m_Min + ((float) x) / contentsRect.width() * (m_Max - m_Min); QColor col((int) (m_ColorTransferFunction->GetRedValue(xVal) * 255), (int) (m_ColorTransferFunction->GetGreenValue(xVal) * 255), (int) (m_ColorTransferFunction->GetBlueValue(xVal) * 255)); painter.setPen(col); painter.drawLine(x, 1, x, contentsRect.height()); } } //paint title if (m_Title.size()>0) { painter.setPen(Qt::black); painter.drawText(QPoint(11,21),m_Title); painter.setPen(Qt::white); painter.drawText(QPoint(10,20),m_Title); } //paint min and max QString qs_min = QString::number( m_Min ); QString qs_max = QString::number( m_Max ); QRect qr_min = painter.fontMetrics().boundingRect( qs_min ); QRect qr_max = painter.fontMetrics().boundingRect( qs_max ); int y,x; y=this->contentsRect().height()-qr_min.height()+5; x=10; painter.setPen(Qt::black); painter.drawText(QPoint(x+1,y+1),qs_min); painter.setPen(Qt::white); painter.drawText(QPoint(x ,y ),qs_min); y=this->contentsRect().height()-qr_max.height()+5; x=this->contentsRect().width()-qr_max.width()-6; painter.setPen(Qt::black); painter.drawText(QPoint(x,y+1),qs_max); painter.setPen(Qt::white); painter.drawText(QPoint(x,y ),qs_max); if (m_ColorTransferFunction) { // now paint the handles painter.setBrush(Qt::black); painter.setPen(Qt::black); for (int i = 0; i < this->GetFunctionSize(); i++) { int handleHeight = (i == m_GrabbedHandle) ? (int) (contentsRect.height() / 1.5) : contentsRect.height() / 2; int handleWidth = (i == m_GrabbedHandle) ? 6 : 4; std::pair point = this->FunctionToCanvas(std::make_pair( GetFunctionX(i), 0.0f)); int y = height() / 2; painter.drawRoundRect(point.first - handleWidth / 2, y - handleHeight / 2, handleWidth, handleHeight, 50, 50); if (i == m_GrabbedHandle) { if (m_LineEditAvailable) { m_XEdit->setText(QString::number(GetFunctionX(m_GrabbedHandle))); //m_YEdit->setText(QString::number(GetFunctionY(m_GrabbedHandle))); } } } } } int QmitkColorTransferFunctionCanvas::GetNearHandle(int x, int /*y*/, unsigned int maxSquaredDistance) { for (int i = 0; i < this->GetFunctionSize(); i++) { std::pair point = this->FunctionToCanvas(std::make_pair( - GetFunctionX(i), (vtkFloatingPointType) 0.0)); + GetFunctionX(i), (double) 0.0)); if ((unsigned int) ((point.first - x) * (point.first - x)) < maxSquaredDistance) { return i; } } return -1; } void QmitkColorTransferFunctionCanvas::DoubleClickOnHandle(int handle) { - vtkFloatingPointType xVal = GetFunctionX(handle); + double xVal = GetFunctionX(handle); QColor col((int) (m_ColorTransferFunction->GetRedValue(xVal) * 255), (int) (m_ColorTransferFunction->GetGreenValue(xVal) * 255), (int) (m_ColorTransferFunction->GetBlueValue(xVal) * 255)); QColor result = QColorDialog::getColor(col); if (result.isValid()) { m_ColorTransferFunction->AddRGBPoint(xVal, result.red() / 255.0, result.green() / 255.0, result.blue() / 255.0); this->update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkColorTransferFunctionCanvas::MoveFunctionPoint(int index, - std::pair pos) + std::pair pos) { - vtkFloatingPointType color[3]; + double color[3]; m_ColorTransferFunction->GetColor(GetFunctionX(index), color); RemoveFunctionPoint( GetFunctionX(index)); m_ColorTransferFunction->AddRGBPoint(pos.first, color[0], color[1], color[2]); } void QmitkColorTransferFunctionCanvas::AddRGB(double x, double r, double g, double b) { m_ColorTransferFunction->AddRGBPoint(x, r, g, b); } diff --git a/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.h b/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.h index 6cfc209d87..50081b90be 100755 --- a/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.h +++ b/Modules/QmitkExt/QmitkColorTransferFunctionCanvas.h @@ -1,117 +1,117 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKCOLORTRANSFERFUNCTIONCANVAS_H_INCLUDED #define QMITKCOLORTRANSFERFUNCTIONCANVAS_H_INCLUDED #include "QmitkTransferFunctionCanvas.h" #include "QmitkExtExports.h" #include class QmitkExt_EXPORT QmitkColorTransferFunctionCanvas: public QmitkTransferFunctionCanvas { Q_OBJECT public: QmitkColorTransferFunctionCanvas( QWidget* parent = 0, Qt::WindowFlags f = 0 ) ; virtual void paintEvent( QPaintEvent* e ); int GetNearHandle(int x,int y,unsigned int maxSquaredDistance = 32); void SetTitle(const QString& title); void SetColorTransferFunction(vtkColorTransferFunction* colorTransferFunction) { this->m_ColorTransferFunction = colorTransferFunction; this->SetMin(colorTransferFunction->GetRange()[0]); this->SetMax(colorTransferFunction->GetRange()[1]); setEnabled(true); update(); } - void AddFunctionPoint(vtkFloatingPointType x,vtkFloatingPointType /*val*/) + void AddFunctionPoint(double x,double /*val*/) { m_ColorTransferFunction->AddRGBPoint(x,m_ColorTransferFunction->GetRedValue(x),m_ColorTransferFunction->GetGreenValue(x),m_ColorTransferFunction->GetBlueValue(x)); } - void RemoveFunctionPoint(vtkFloatingPointType x) + void RemoveFunctionPoint(double x) { int old_size = GetFunctionSize(); m_ColorTransferFunction->RemovePoint(x); if (GetFunctionSize() + 1 != old_size) { std::cout << "old/new size" << old_size << "/" << GetFunctionSize() << std::endl; std::cout << "called with x=" << x << std::endl; } } - vtkFloatingPointType GetFunctionX(int index) + double GetFunctionX(int index) { return m_ColorTransferFunction->GetDataPointer()[index*4]; } int GetFunctionSize() { return m_ColorTransferFunction->GetSize(); } void DoubleClickOnHandle(int handle); - void MoveFunctionPoint(int index, std::pair pos); + void MoveFunctionPoint(int index, std::pair pos); void AddRGB(double x, double r, double g, double b); double GetFunctionMax() { return m_ColorTransferFunction->GetRange()[1]; } double GetFunctionMin() { return m_ColorTransferFunction->GetRange()[0]; } double GetFunctionRange() { double range; if((m_ColorTransferFunction->GetRange()[0])==0) { range = m_ColorTransferFunction->GetRange()[1]; return range; } else { range = (m_ColorTransferFunction->GetRange()[1])-(m_ColorTransferFunction->GetRange()[0]); return range; } } void RemoveAllFunctionPoints() { m_ColorTransferFunction->AddRGBSegment(this->GetFunctionMin(),1,0,0,this->GetFunctionMax(),1,1,0); } float GetFunctionY(int) { return 0.0; } protected: vtkColorTransferFunction* m_ColorTransferFunction; QString m_Title; }; #endif diff --git a/Modules/QmitkExt/QmitkPiecewiseFunctionCanvas.cpp b/Modules/QmitkExt/QmitkPiecewiseFunctionCanvas.cpp index f68b8b6ba5..38e053b221 100755 --- a/Modules/QmitkExt/QmitkPiecewiseFunctionCanvas.cpp +++ b/Modules/QmitkExt/QmitkPiecewiseFunctionCanvas.cpp @@ -1,158 +1,158 @@ /*=================================================================== 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 "QmitkPiecewiseFunctionCanvas.h" #include #include QmitkPiecewiseFunctionCanvas::QmitkPiecewiseFunctionCanvas(QWidget * parent, Qt::WindowFlags f) : QmitkTransferFunctionCanvas(parent, f), m_PiecewiseFunction(0) { // used for drawing a border setContentsMargins(1,1,1,1); } void QmitkPiecewiseFunctionCanvas::SetTitle(const QString& title) { m_Title=title; } void QmitkPiecewiseFunctionCanvas::paintEvent(QPaintEvent*) { QPainter painter(this); PaintHistogram(painter); if (m_Title.size()>0) { painter.setPen(Qt::black); painter.drawText(QPoint(11,21),m_Title); painter.setPen(Qt::white); painter.drawText(QPoint(10,20),m_Title); } { QString qs_min = QString::number( m_Min ); QString qs_max = QString::number( m_Max ); QRect qr_min = painter.fontMetrics().boundingRect( qs_min ); QRect qr_max = painter.fontMetrics().boundingRect( qs_max ); int y,x; y=this->contentsRect().height()-qr_min.height()+5; x=10; // Fill the tf presets in the generator widget painter.setPen(Qt::black); painter.drawText(QPoint(x+1,y+1),qs_min); painter.setPen(Qt::white); painter.drawText(QPoint(x ,y ),qs_min); y=this->contentsRect().height()-qr_max.height()+5; x=this->contentsRect().width()-qr_max.width()-6; painter.setPen(Qt::black); painter.drawText(QPoint(x,y+1),qs_max); painter.setPen(Qt::white); painter.drawText(QPoint(x,y ),qs_max); } painter.setPen(Qt::gray); QRect contentsRect = this->contentsRect(); painter.drawRect(0, 0, contentsRect.width()+1, contentsRect.height()+1); if (m_PiecewiseFunction && this->isEnabled()) { - vtkFloatingPointType* dp = m_PiecewiseFunction->GetDataPointer(); + double* dp = m_PiecewiseFunction->GetDataPointer(); // Render lines painter.setPen(Qt::black); for (int i = -1; i < m_PiecewiseFunction->GetSize(); i++) { std::pair left; std::pair right; if(i < 0) left = this->FunctionToCanvas(std::make_pair(-32768, dp[0 * 2 + 1])); else left = this->FunctionToCanvas(std::make_pair(dp[i * 2], dp[i * 2 + 1])); if(i+1 >= m_PiecewiseFunction->GetSize()) right = this->FunctionToCanvas(std::make_pair(32768, dp[(i ) * 2 + 1])); else right = this->FunctionToCanvas(std::make_pair(dp[(i+1) * 2], dp[(i+1) * 2 + 1])); painter.drawLine(left.first, left.second, right.first, right.second); } // Render Points for (int i = 0; i < m_PiecewiseFunction->GetSize(); i++) { std::pair point = this->FunctionToCanvas(std::make_pair( dp[i * 2], dp[i * 2 + 1])); if (i == m_GrabbedHandle) { painter.setBrush(QBrush(Qt::red)); if (m_LineEditAvailable) { m_XEdit->setText(QString::number(GetFunctionX(m_GrabbedHandle))); m_YEdit->setText(QString::number(GetFunctionY(m_GrabbedHandle))); } } else { painter.setBrush(QBrush(Qt::green)); } painter.drawEllipse(point.first - 4, point.second - 4, 8, 8); } painter.setBrush(Qt::NoBrush); } } int QmitkPiecewiseFunctionCanvas::GetNearHandle(int x, int y, unsigned int maxSquaredDistance) { - vtkFloatingPointType* dp = m_PiecewiseFunction->GetDataPointer(); + double* dp = m_PiecewiseFunction->GetDataPointer(); for (int i = 0; i < m_PiecewiseFunction->GetSize(); i++) { std::pair point = this->FunctionToCanvas(std::make_pair(dp[i * 2], dp[i * 2 + 1])); if ((unsigned int) ((point.first - x) * (point.first - x) + (point.second - y) * (point.second - y)) <= maxSquaredDistance) { return i; } } return -1; } void QmitkPiecewiseFunctionCanvas::MoveFunctionPoint(int index, - std::pair pos) + std::pair pos) { RemoveFunctionPoint(GetFunctionX(index)); AddFunctionPoint(pos.first, pos.second); //std::cout<<" AddFunctionPoint x: "< class QmitkExt_EXPORT QmitkPiecewiseFunctionCanvas: public QmitkTransferFunctionCanvas { Q_OBJECT public: QmitkPiecewiseFunctionCanvas( QWidget * parent=0, Qt::WindowFlags f = 0 ); virtual void paintEvent( QPaintEvent* e ); void SetTitle(const QString& title); int GetNearHandle(int x,int y,unsigned int maxSquaredDistance = 32); void SetPiecewiseFunction(vtkPiecewiseFunction* piecewiseFunction) { this->m_PiecewiseFunction = piecewiseFunction; this->SetMin(m_PiecewiseFunction->GetRange()[0]); this->SetMax(m_PiecewiseFunction->GetRange()[1]); setEnabled(true); update(); } - void AddFunctionPoint(vtkFloatingPointType x,vtkFloatingPointType val) + void AddFunctionPoint(double x,double val) { m_PiecewiseFunction->AddPoint(x,val); } - void RemoveFunctionPoint(vtkFloatingPointType x) + void RemoveFunctionPoint(double x) { int old_size = GetFunctionSize(); m_PiecewiseFunction->RemovePoint(x); if (GetFunctionSize() + 1 != old_size) { std::cout << "old/new size" << old_size << "/" << GetFunctionSize() << std::endl; std::cout << "called with x=" << x << std::endl; } } - vtkFloatingPointType GetFunctionX(int index) + double GetFunctionX(int index) { return m_PiecewiseFunction->GetDataPointer()[index*2]; } float GetFunctionY(int index) { return m_PiecewiseFunction->GetValue(m_PiecewiseFunction->GetDataPointer()[index*2]); } int GetFunctionSize() { return m_PiecewiseFunction->GetSize(); } void DoubleClickOnHandle(int /*handle*/) {} - void MoveFunctionPoint(int index, std::pair pos); + void MoveFunctionPoint(int index, std::pair pos); double GetFunctionMax() { return m_PiecewiseFunction->GetRange()[1]; } double GetFunctionMin() { return m_PiecewiseFunction->GetRange()[0]; } double GetFunctionRange() { double range; if((m_PiecewiseFunction->GetRange()[0])<0) { range = (m_PiecewiseFunction->GetRange()[1])-(m_PiecewiseFunction->GetRange()[0]); return range; } else { range = m_PiecewiseFunction->GetRange()[1]; return range; } } void RemoveAllFunctionPoints() { m_PiecewiseFunction->AddSegment(this->GetFunctionMin(),0,this->GetFunctionMax(),1); m_PiecewiseFunction->AddPoint(0.0,0.0); } void ResetGO() { //Gradient Opacity m_PiecewiseFunction->AddSegment(this->GetFunctionMin(),0,0,1); m_PiecewiseFunction->AddSegment(0,1,((this->GetFunctionRange())*0.125),1); m_PiecewiseFunction->AddSegment(((this->GetFunctionRange())*0.125),1,((this->GetFunctionRange())*0.2),1); m_PiecewiseFunction->AddSegment(((this->GetFunctionRange())*0.2),1,((this->GetFunctionRange())*0.25),1); } protected: vtkPiecewiseFunction* m_PiecewiseFunction; QString m_Title; }; #endif diff --git a/Modules/QmitkExt/QmitkTransferFunctionCanvas.cpp b/Modules/QmitkExt/QmitkTransferFunctionCanvas.cpp index bacf287557..a758d3ad4c 100755 --- a/Modules/QmitkExt/QmitkTransferFunctionCanvas.cpp +++ b/Modules/QmitkExt/QmitkTransferFunctionCanvas.cpp @@ -1,249 +1,249 @@ /*=================================================================== 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 "QmitkTransferFunctionCanvas.h" #include #include #include #include QmitkTransferFunctionCanvas::QmitkTransferFunctionCanvas(QWidget * parent, Qt::WindowFlags f) : QWidget(parent, f), m_GrabbedHandle(-1), m_Lower(0.0f), m_Upper(1.0f), m_Min( 0.0f), m_Max(1.0f) { setEnabled(false); setFocusPolicy(Qt::ClickFocus); m_LineEditAvailable = false; } void QmitkTransferFunctionCanvas::paintEvent(QPaintEvent* ev) { QWidget::paintEvent(ev); } std::pair QmitkTransferFunctionCanvas::FunctionToCanvas( - std::pair functionPoint) + std::pair functionPoint) { //std::cout<<"F2C.first: "<<(int)((functionPoint.first - m_Lower) / (m_Upper - m_Lower) * width())<<" F2C.second: "<<(int)(height() * (1 - functionPoint.second))< QmitkTransferFunctionCanvas::CanvasToFunction( +std::pair QmitkTransferFunctionCanvas::CanvasToFunction( std::pair canvasPoint) { - //std::cout<<"C2F.first: "<<(canvasPoint.first * (m_Upper - m_Lower) / width() + m_Lower)<<" C2F.second: "<<(1.0 - (vtkFloatingPointType)canvasPoint.second / height())<pos().x(), mouseEvent->pos().y()); if (nearHandle != -1) { this->DoubleClickOnHandle(nearHandle); } } /** returns index of a near handle or -1 if none is near */ int QmitkTransferFunctionCanvas::GetNearHandle(int /*x*/, int /*y*/, unsigned int /*maxSquaredDistance*/) { return -1; } void QmitkTransferFunctionCanvas::mousePressEvent(QMouseEvent* mouseEvent) { if (m_LineEditAvailable) { m_XEdit->clear(); if(m_YEdit) m_YEdit->clear(); } m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y()); if ( (mouseEvent->button() & Qt::LeftButton) && m_GrabbedHandle == -1) { this->AddFunctionPoint( this->CanvasToFunction(std::make_pair(mouseEvent->pos().x(), mouseEvent->pos().y())).first, this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())).second); m_GrabbedHandle = GetNearHandle(mouseEvent->pos().x(), mouseEvent->pos().y()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } else if ((mouseEvent->button() & Qt::RightButton) && m_GrabbedHandle != -1 && this->GetFunctionSize() > 1) { this->RemoveFunctionPoint(this->GetFunctionX(m_GrabbedHandle)); m_GrabbedHandle = -1; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } update(); // m_TransferFunction->UpdateVtkFunctions(); } void QmitkTransferFunctionCanvas::mouseMoveEvent(QMouseEvent* mouseEvent) { if (m_GrabbedHandle != -1) { - std::pair + std::pair newPos = this->CanvasToFunction(std::make_pair(mouseEvent->x(), mouseEvent->y())); // X Clamping { // Check with predecessor if( m_GrabbedHandle > 0 ) if (newPos.first <= this->GetFunctionX(m_GrabbedHandle - 1)) newPos.first = this->GetFunctionX(m_GrabbedHandle); // Check with sucessor if( m_GrabbedHandle < this->GetFunctionSize()-1 ) if (newPos.first >= this->GetFunctionX(m_GrabbedHandle + 1)) newPos.first = this->GetFunctionX(m_GrabbedHandle); // Clamping to histogramm if (newPos.first < m_Min) newPos.first = m_Min; else if (newPos.first > m_Max) newPos.first = m_Max; } // Y Clamping { if (newPos.second < 0.0) newPos.second = 0.0; else if (newPos.second > 1.0) newPos.second = 1.0; } // Move selected point this->MoveFunctionPoint(m_GrabbedHandle, newPos); /* // Search again selected point ??????? should not be required, seems like a legacy workaround/bugfix // and no longer required m_GrabbedHandle = -1; for (int i = 0; i < this->GetFunctionSize(); i++) { if (this->GetFunctionX(i) == newPos.first) { m_GrabbedHandle = i; break; } } */ update(); //if (m_ImmediateUpdate) mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkTransferFunctionCanvas::mouseReleaseEvent(QMouseEvent*) { // m_GrabbedHandle = -1; update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkTransferFunctionCanvas::PaintHistogram(QPainter &p) { if(m_Histogram) { p.save(); p.setPen(Qt::gray); int displayWidth = contentsRect().width(); int displayHeight = contentsRect().height(); double windowLeft = m_Lower; double windowRight = m_Upper; double step = (windowRight-windowLeft)/double(displayWidth); double pos = windowLeft; for (int x = 0; x < displayWidth; x++) { double left = pos; double right = pos + step; float height = m_Histogram->GetRelativeBin( left , right ); if (height >= 0) p.drawLine(x, displayHeight*(1-height), x, displayHeight); pos += step; } p.restore(); } } void QmitkTransferFunctionCanvas::keyPressEvent(QKeyEvent * e) { if( m_GrabbedHandle == -1) return; switch(e->key()) { case Qt::Key_Delete: if(this->GetFunctionSize() > 1) { this->RemoveFunctionPoint(GetFunctionX(m_GrabbedHandle)); m_GrabbedHandle = -1; } break; case Qt::Key_Left: this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)-1 , GetFunctionY(m_GrabbedHandle)))); break; case Qt::Key_Right: this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle)+1 , GetFunctionY(m_GrabbedHandle)))); break; case Qt::Key_Up: this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)+0.001))); break; case Qt::Key_Down: this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair( GetFunctionX(m_GrabbedHandle) , GetFunctionY(m_GrabbedHandle)-0.001))); break; } update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } // Update immediatly while changing the transfer function void QmitkTransferFunctionCanvas::SetImmediateUpdate(bool state) { m_ImmediateUpdate = state; } diff --git a/Modules/QmitkExt/QmitkTransferFunctionCanvas.h b/Modules/QmitkExt/QmitkTransferFunctionCanvas.h index 21e692daf6..1b95363a69 100755 --- a/Modules/QmitkExt/QmitkTransferFunctionCanvas.h +++ b/Modules/QmitkExt/QmitkTransferFunctionCanvas.h @@ -1,167 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKTRANSFERFUNCTIONCANVAS_H_INCLUDED #define QMITKTRANSFERFUNCTIONCANVAS_H_INCLUDED #include "QmitkExtExports.h" #include #include #include #include class QmitkExt_EXPORT QmitkTransferFunctionCanvas : public QWidget { Q_OBJECT public: QmitkTransferFunctionCanvas( QWidget * parent=0, Qt::WindowFlags f = 0 ); mitk::SimpleHistogram* GetHistogram() { return m_Histogram; } void SetHistogram(mitk::SimpleHistogram *histogram) { m_Histogram = histogram; } - vtkFloatingPointType GetMin() + double GetMin() { return m_Min; } - void SetMin(vtkFloatingPointType min) + void SetMin(double min) { this->m_Min = min; SetLower(min); } - vtkFloatingPointType GetMax() + double GetMax() { return m_Max; } - void SetMax(vtkFloatingPointType max) + void SetMax(double max) { this->m_Max = max; SetUpper(max); } - vtkFloatingPointType GetLower() + double GetLower() { return m_Lower; } - void SetLower(vtkFloatingPointType lower) + void SetLower(double lower) { this->m_Lower = lower; } - vtkFloatingPointType GetUpper() + double GetUpper() { return m_Upper; } - void SetUpper(vtkFloatingPointType upper) + void SetUpper(double upper) { this->m_Upper = upper; } // itkGetConstObjectMacro(Histogram,mitk::HistogramGenerator::HistogramType); // itkSetObjectMacro(Histogram,mitk::HistogramGenerator::HistogramType); void mousePressEvent( QMouseEvent* mouseEvent ); virtual void paintEvent( QPaintEvent* e ); virtual void DoubleClickOnHandle(int handle) = 0; void mouseMoveEvent( QMouseEvent* mouseEvent ); void mouseReleaseEvent( QMouseEvent* mouseEvent ); void mouseDoubleClickEvent( QMouseEvent* mouseEvent ); void PaintHistogram(QPainter &p); virtual int GetNearHandle(int x,int y,unsigned int maxSquaredDistance = 32) = 0; - virtual void AddFunctionPoint(vtkFloatingPointType x,vtkFloatingPointType val) = 0; - virtual void RemoveFunctionPoint(vtkFloatingPointType x) = 0; - virtual void MoveFunctionPoint(int index, std::pair pos) = 0; - virtual vtkFloatingPointType GetFunctionX(int index) = 0; + virtual void AddFunctionPoint(double x,double val) = 0; + virtual void RemoveFunctionPoint(double x) = 0; + virtual void MoveFunctionPoint(int index, std::pair pos) = 0; + virtual double GetFunctionX(int index) = 0; virtual float GetFunctionY(int index) = 0; virtual int GetFunctionSize() = 0; int m_GrabbedHandle; double m_Lower, m_Upper, m_Min, m_Max; - std::pair FunctionToCanvas(std::pair); - std::pair CanvasToFunction(std::pair); + std::pair FunctionToCanvas(std::pair); + std::pair CanvasToFunction(std::pair); mitk::SimpleHistogram *m_Histogram; void keyPressEvent ( QKeyEvent * e ); void SetImmediateUpdate(bool state); - static std::pair ValidateCoord( std::pair x ) + static std::pair ValidateCoord( std::pair x ) { if( x.first < -2048 ) x.first = -2048; if( x.first > 2048 ) x.first = 2048; if( x.second < 0 ) x.second = 0; if( x.second > 1 ) x.second = 1; return x; } void SetX(float x) { if (m_GrabbedHandle != -1) { this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair(x,GetFunctionY(m_GrabbedHandle)))); update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void SetY(float y) { if (m_GrabbedHandle != -1) { this->MoveFunctionPoint(m_GrabbedHandle, ValidateCoord(std::make_pair(GetFunctionX(m_GrabbedHandle),y))); update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void SetQLineEdits(QLineEdit* xEdit, QLineEdit* yEdit) { m_XEdit = xEdit; m_YEdit = yEdit; m_LineEditAvailable = true; } protected: bool m_ImmediateUpdate; float m_Range; bool m_LineEditAvailable; QLineEdit* m_XEdit; QLineEdit* m_YEdit; }; #endif diff --git a/Modules/QmitkExt/QmitkTransferFunctionGeneratorWidget.cpp b/Modules/QmitkExt/QmitkTransferFunctionGeneratorWidget.cpp index ab202ccfc1..b2048626ca 100644 --- a/Modules/QmitkExt/QmitkTransferFunctionGeneratorWidget.cpp +++ b/Modules/QmitkExt/QmitkTransferFunctionGeneratorWidget.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 "QmitkTransferFunctionGeneratorWidget.h" #include #include #include #include #include #include #include #include QmitkTransferFunctionGeneratorWidget::QmitkTransferFunctionGeneratorWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), deltaScale(1.0), deltaMax(1024), deltaMin(1) { histoGramm = NULL; this->setupUi(this); // LevelWindow Tab { connect( m_CrossLevelWindow, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaLevelWindow( int, int ) ) ); } // Threshold Tab { connect( m_CrossThreshold, SIGNAL( SignalDeltaMove( int, int ) ), this, SLOT( OnDeltaThreshold( int, int ) ) ); thDelta = 100; } // Presets Tab { m_TransferFunctionComboBox->setVisible(false); connect( m_TransferFunctionComboBox, SIGNAL( activated( int ) ), this, SIGNAL(SignalTransferFunctionModeChanged(int)) ); connect( m_TransferFunctionComboBox, SIGNAL( activated( int ) ), this, SLOT(OnPreset(int)) ); connect( m_SavePreset, SIGNAL( clicked() ), this, SLOT( OnSavePreset() ) ); connect( m_LoadPreset, SIGNAL( clicked() ), this, SLOT( OnLoadPreset() ) ); } presetFileName = "."; } int QmitkTransferFunctionGeneratorWidget::AddPreset(const QString &presetName) { m_TransferFunctionComboBox->setVisible(true); m_TransferFunctionComboBox->addItem( presetName); return m_TransferFunctionComboBox->count()-1; } void QmitkTransferFunctionGeneratorWidget::SetPresetsTabEnabled(bool enable) { m_PresetTab->setEnabled(enable); } void QmitkTransferFunctionGeneratorWidget::SetThresholdTabEnabled(bool enable) { m_ThresholdTab->setEnabled(enable); } void QmitkTransferFunctionGeneratorWidget::SetBellTabEnabled(bool enable) { m_BellTab->setEnabled(enable); } void QmitkTransferFunctionGeneratorWidget::OnSavePreset( ) { if(tfpToChange.IsNull()) return; mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); std::string fileName; std::string fileNameOutput; presetFileName = QFileDialog::getSaveFileName( this,"Choose a filename to save the transferfunction",presetFileName, "Transferfunction (*.xml)" ); fileName=presetFileName.toLocal8Bit().constData(); MITK_INFO << "Saving Transferfunction under path: " << fileName; fileNameOutput= ReduceFileName(fileName); if ( mitk::TransferFunctionPropertySerializer::SerializeTransferFunction( fileName.c_str(), tf )) m_InfoPreset->setText( QString( (std::string("saved ")+ fileNameOutput).c_str() ) ); else m_InfoPreset->setText( QString( std::string("saving failed").c_str() ) ); /* FILE *f=fopen("c:\\temp.txt","w"); // grayvalue -> opacity { mitk::TransferFunction::ControlPoints scalarOpacityPoints = tf->GetScalarOpacityPoints(); fprintf(f,"// grayvalue->opacity \n" "{\n" " vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction();\n" " f->RemoveAllPoints();\n"); for ( mitk::TransferFunction::ControlPoints::iterator iter = scalarOpacityPoints.begin(); iter != scalarOpacityPoints.end(); ++iter ) fprintf(f," f->AddPoint(%f,%f);\n",iter->first, iter->second); fprintf(f," f->Modified();\n" "}\n"); } // gradient { mitk::TransferFunction::ControlPoints gradientOpacityPoints = tf->GetGradientOpacityPoints(); fprintf(f,"// gradient at grayvalue->opacity \n" "{\n" " vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction();\n" " f->RemoveAllPoints();\n"); for ( mitk::TransferFunction::ControlPoints::iterator iter = gradientOpacityPoints.begin(); iter != gradientOpacityPoints.end(); ++iter ) fprintf(f," f->AddPoint(%f,%f);\n",iter->first, iter->second); fprintf(f," f->Modified();\n" "}\n"); } // color { mitk::TransferFunction::RGBControlPoints points = tf->GetRGBPoints(); fprintf(f,"// grayvalue->color \n" "{\n" " vtkColorTransferFunction *f=tf->GetColorTransferFunction();\n" " f->RemoveAllPoints();\n"); for ( mitk::TransferFunction::RGBControlPoints::iterator iter = points.begin(); iter != points.end(); ++iter ) fprintf(f," f->AddRGBPoint(%f,%f,%f,%f);\n",iter->first, iter->second[0], iter->second[1], iter->second[2]); fprintf(f," f->Modified();\n" "}\n"); } fclose(f); MITK_INFO << "saved under C:\\temp.txt"; */ } void QmitkTransferFunctionGeneratorWidget::OnLoadPreset( ) { if(tfpToChange.IsNull()) return; std::string fileName; std::string fileNameOutput; presetFileName = QFileDialog::getOpenFileName( this,"Choose a file to open the transferfunction from",presetFileName, "Transferfunction (*.xml)" ); fileName=presetFileName.toLocal8Bit().constData(); MITK_INFO << "Loading Transferfunction from path: " << fileName; fileNameOutput= ReduceFileName(fileName); mitk::TransferFunction::Pointer tf = mitk::TransferFunctionPropertySerializer::DeserializeTransferFunction(fileName.c_str()); if(tf.IsNotNull()) { /* if( histoGramm ) tf->InitializeByItkHistogram( histoGramm ); */ tfpToChange->SetValue( tf ); m_InfoPreset->setText( QString( (std::string("loaded ")+ fileNameOutput).c_str() ) ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); emit SignalUpdateCanvas(); /* - vtkFloatingPointType* dp = tf->GetScalarOpacityFunction()->GetDataPointer(); + double* dp = tf->GetScalarOpacityFunction()->GetDataPointer(); for (int i = 0; i < tf->GetScalarOpacityFunction()->GetSize(); i++) { MITK_INFO << "x: " << dp[i * 2] << " y: " << dp[i * 2 + 1]; } */ } } void QmitkTransferFunctionGeneratorWidget::OnPreset(int mode) { //first item is only information if( --mode == -1 ) return; m_InfoPreset->setText(QString("selected ") + m_TransferFunctionComboBox->currentText()); //revert to first item m_TransferFunctionComboBox->setCurrentIndex( 0 ); } static double transformationGlocke ( double x ) { double z = 0.1; double a = 2 - 2 * z; double b = 2 * z - 1; x = a * x + b; return x; } static double stepFunctionGlocke ( double x ) { x = 1-(2*x -1.0); // map [0.5;1] to [0,1] x = x * ( 3*x - 2*x*x ); // apply smoothing function x = x * x; return x; } double QmitkTransferFunctionGeneratorWidget::ScaleDelta(int d) const { //MITK_INFO << "Scaling (int) " << d << "to (double) " << deltaScale*(double)d; return deltaScale*(double)d; } void QmitkTransferFunctionGeneratorWidget::OnDeltaLevelWindow(int dx, int dy) // bell { //std::string infoText; // m_InfoThreshold->setText( QString( x.c_str() ) ); if(tfpToChange.IsNull()) return; thPos += ScaleDelta(dx); thDelta -= ScaleDelta(dy); if(thDelta < deltaMin) thDelta = deltaMin; if(thDelta > deltaMax) thDelta = deltaMax; if(thPos < histoMinimum) thPos = histoMinimum; if(thPos > histoMaximum) thPos = histoMaximum; std::stringstream ss; ss << "Click on the cross and move the mouse"<<"\n" <<"\n" << "center at " << thPos << "\n" << "width " << thDelta * 2; m_InfoLevelWindow->setText( QString( ss.str().c_str() ) ); mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); // grayvalue->opacity { vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction(); f->RemoveAllPoints(); for( int r = 0; r<= 6; r++) { double relPos = (r / 6.0) * 0.5 + 0.5; f->AddPoint(thPos+thDelta*(-transformationGlocke(relPos)),stepFunctionGlocke(relPos)); f->AddPoint(thPos+thDelta*( transformationGlocke(relPos)),stepFunctionGlocke(relPos)); } f->Modified(); } // gradient at grayvalue->opacity { vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction(); f->RemoveAllPoints(); f->AddPoint( 0, 1.0 ); f->Modified(); } /* // grayvalue->color { vtkColorTransferFunction *ctf=tf->GetColorTransferFunction(); ctf->RemoveAllPoints(); ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 ); ctf->Modified(); } */ tf->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); emit SignalUpdateCanvas(); } static double stepFunctionThreshold ( double x ) { x = 0.5*x + 0.5; // map [-1;1] to [0,1] x = x * ( 3*x - 2*x*x ); // apply smoothing function x = x * x; return x; } void QmitkTransferFunctionGeneratorWidget::OnDeltaThreshold(int dx, int dy) // LEVELWINDOW { if(tfpToChange.IsNull()) return; thPos += ScaleDelta(dx); thDelta += ScaleDelta(dy); if(thDelta < deltaMin) thDelta = deltaMin; if(thDelta > deltaMax) thDelta = deltaMax; if(thPos < histoMinimum) thPos = histoMinimum; if(thPos > histoMaximum) thPos = histoMaximum; //MITK_INFO << "threshold pos: " << thPos << " delta: " << thDelta; //MITK_INFO << "histoMinimum: " << histoMinimum << " max: " << histoMaximum; std::stringstream ss; ss << "Click on the cross and move the mouse"<<"\n" <<"\n" << "threshold at " << thPos << "\n" << "width " << thDelta * 2; m_InfoThreshold->setText( QString( ss.str().c_str() ) ); mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); // grayvalue->opacity { vtkPiecewiseFunction *f=tf->GetScalarOpacityFunction(); f->RemoveAllPoints(); for( int r = 1; r<= 4; r++) { double relPos = r / 4.0; f->AddPoint(thPos+thDelta*(-relPos),stepFunctionThreshold(-relPos)); f->AddPoint(thPos+thDelta*( relPos),stepFunctionThreshold( relPos)); } f->Modified(); } // gradient at grayvalue->opacity { vtkPiecewiseFunction *f=tf->GetGradientOpacityFunction(); f->RemoveAllPoints(); f->AddPoint( 0, 1.0 ); f->Modified(); } /* // grayvalue->color { vtkColorTransferFunction *ctf=tf->GetColorTransferFunction(); ctf->RemoveAllPoints(); ctf->AddRGBPoint( 0, 1.0, 1.0, 1.0 ); ctf->Modified(); } */ tf->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); emit SignalUpdateCanvas(); } std::string QmitkTransferFunctionGeneratorWidget::ReduceFileName(std::string fileNameLong ) { if (fileNameLong.length()< 40) return fileNameLong; //MITK_INFO <<" fileName > 20 "; std::string fileNameShort; std::string fileNameRevert; for(unsigned int i=0; i< fileNameLong.length(); i++) { if(i<3) { char x= fileNameLong[i]; fileNameShort= fileNameShort+x; } if(i==3) { fileNameShort= fileNameShort+"..."; break; } } //MITK_INFO <<" fileNameShort: " << fileNameShort.c_str(); unsigned int len( fileNameLong.length() ); for(unsigned int i=len-1; i <= len; i--) { std::string x=std::string("")+fileNameLong[i]; if ( x.compare("/")==0 || x.compare("\\")==0) { fileNameRevert= "/" + fileNameRevert; break; } if (i>=fileNameLong.length()-24) { fileNameRevert= x+ fileNameRevert; //MITK_INFO <<" fileNameRevert: " << fileNameRevert.c_str(); } else { fileNameRevert= "/..." + fileNameRevert; break; } } return fileNameShort+fileNameRevert; } QmitkTransferFunctionGeneratorWidget::~QmitkTransferFunctionGeneratorWidget() { } void QmitkTransferFunctionGeneratorWidget::SetDataNode(mitk::DataNode* node) { histoGramm = NULL; if (node) { tfpToChange = dynamic_cast(node->GetProperty("TransferFunction")); if(!tfpToChange) { node->SetProperty("TransferFunction", tfpToChange = mitk::TransferFunctionProperty::New() ); dynamic_cast(node->GetProperty("TransferFunction")); } mitk::TransferFunction::Pointer tf = tfpToChange->GetValue(); if( mitk::Image* image = dynamic_cast( node->GetData() ) ) { // tf->InitializeByItkHistogram( histoGramm = image->GetScalarHistogram() ); histoMinimum= image->GetScalarValueMin(); histoMaximum= image->GetScalarValueMax(); } else if (mitk::UnstructuredGrid* grid = dynamic_cast( node->GetData() ) ) { double* range = grid->GetVtkUnstructuredGrid()->GetScalarRange(); histoMinimum = range[0]; histoMaximum = range[1]; double histoRange = histoMaximum - histoMinimum; deltaMax = histoRange/4.0; deltaMin = histoRange/400.0; deltaScale = histoRange/1024.0; } else { MITK_WARN << "QmitkTransferFunctonGeneratorWidget does not support " << node->GetData()->GetNameOfClass() << " instances"; } thPos = ( histoMinimum + histoMaximum ) / 2.0; } else { tfpToChange = 0; m_InfoPreset->setText( QString( "" ) ); } } diff --git a/Modules/Segmentation/Interactions/mitkContourInteractor.cpp b/Modules/Segmentation/Interactions/mitkContourInteractor.cpp index 6b04b0e090..25e9326f38 100644 --- a/Modules/Segmentation/Interactions/mitkContourInteractor.cpp +++ b/Modules/Segmentation/Interactions/mitkContourInteractor.cpp @@ -1,183 +1,183 @@ /*=================================================================== 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 "mitkContourInteractor.h" #include //#include "ipSegmentation.h" //#include "mitkDataNode.h" #include #include #include #include #include #include #include #include #include #include mitk::ContourInteractor::ContourInteractor(const char * type, mitk::DataNode* dataNode) : mitk::Interactor(type, dataNode), m_Started(false) { assert(m_DataNode != NULL); m_DataNode->SetProperty("layer", mitk::IntProperty::New(100) ); m_DataNode->SetProperty("name", mitk::StringProperty::New("InteractiveFeedbackData") ); m_DataNode->SetOpacity(1); m_DataNode->SetColor(0.4,0.9,0.0); m_DataNode->SetProperty( "Width", mitk::FloatProperty::New(2.0) ); m_Started = false; } mitk::ContourInteractor::~ContourInteractor() { } //mitk::Contour::Pointer ContourInteractor::ExtractContour(mitkIpPicDescriptor* pic) //{ // int idx; // int size = _mitkIpPicElements (pic); // for (idx = 0; idx < size; idx++) // if ( ((mitkIpUInt1_t*) pic->data)[idx]> 0) break; // // int sizePoints; // size of the _points buffer (number of coordinate pairs that fit in) // int numPoints; // number of coordinate pairs stored in _points buffer // float *points = 0; // // points = ipSegmentationGetContour8N( pic, idx, numPoints, sizePoints, points ); // // mitk::Contour::Pointer contour = mitk::Contour::New(); // contour->Initialize(); // mitk::Point3D pointInMM, pointInUnits; // mitk::Point3D itkPoint; // for (int pointIdx = 0; pointIdx < numPoints; pointIdx++) // { // pointInUnits[0] = points[2*pointIdx]; // pointInUnits[1] = points[2*pointIdx+1]; // pointInUnits[2] = m_ZCoord; // m_SelectedImageGeometry->IndexToWorld(CorrectPointCoordinates(pointInUnits),pointInMM); // contour->AddVertex(pointInMM); // } // return contour; //} bool mitk::ContourInteractor::ExecuteAction(mitk::Action* action, mitk::StateEvent const* stateEvent) { mitk::Point3D eventPoint; const mitk::PositionEvent* posEvent = dynamic_cast(stateEvent->GetEvent()); if(posEvent==NULL) { const mitk::DisplayPositionEvent* displayPosEvent = dynamic_cast(stateEvent->GetEvent()); mitk::VtkPropRenderer* sender = (mitk::VtkPropRenderer*) stateEvent->GetEvent()->GetSender(); if((displayPosEvent == NULL) || (sender == NULL)) return false; eventPoint[0] = displayPosEvent->GetDisplayPosition()[0]; eventPoint[1] = displayPosEvent->GetDisplayPosition()[1]; eventPoint[2] = 0; typedef itk::Point DoublePoint3D; DoublePoint3D p; p.CastFrom(eventPoint); sender->GetVtkRenderer()->SetDisplayPoint(p.GetDataPointer()); sender->GetVtkRenderer()->DisplayToWorld(); - vtkFloatingPointType *vtkwp = sender->GetVtkRenderer()->GetWorldPoint(); + double *vtkwp = sender->GetVtkRenderer()->GetWorldPoint(); vtk2itk(vtkwp, eventPoint); } else { eventPoint = posEvent->GetWorldPosition(); } bool ok = false; switch (action->GetActionId()) { case mitk::AcNEWPOINT: { Press(eventPoint); ok = true; m_Started = true; break; } case mitk::AcINITMOVEMENT: { if (m_Started) { Move(eventPoint); ok = true; break; } } case mitk::AcMOVEPOINT: { if (m_Started) { Move(eventPoint); ok = true; break; } } case mitk::AcFINISHMOVEMENT: { if (m_Started) { Release(eventPoint); ok = true; m_Started = false; } break; } default: ok = false; break; } return ok; } void mitk::ContourInteractor::Press(mitk::Point3D& point) { mitk::Contour* contour = dynamic_cast(m_DataNode->GetData()); assert(contour!=NULL); if (!m_Positive) m_DataNode->SetColor(1.0,0.0,0.0); contour->Initialize(); contour->AddVertex( point ); } void mitk::ContourInteractor::Move(mitk::Point3D& point) { mitk::Contour* contour = dynamic_cast(m_DataNode->GetData()); assert(contour!=NULL); contour->AddVertex( point ); // m_Parent->UpdateWidgets(); } void mitk::ContourInteractor::Release(mitk::Point3D& /*point*/) { //vermutlich m_Parent->UpdateWidgets(); } diff --git a/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp b/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp index df216bafa7..49752564fb 100644 --- a/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp @@ -1,166 +1,166 @@ /*=================================================================== 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 "mitkContourSetVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::ContourSetVtkMapper3D::ContourSetVtkMapper3D() { m_VtkPolyDataMapper = vtkPolyDataMapper::New(); m_Actor = vtkActor::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); m_ContourSet = vtkPolyData::New(); m_TubeFilter = vtkTubeFilter::New(); } mitk::ContourSetVtkMapper3D::~ContourSetVtkMapper3D() { if( m_VtkPolyDataMapper ) m_VtkPolyDataMapper->Delete();; if( m_TubeFilter ) m_TubeFilter->Delete();; if( m_ContourSet ) m_ContourSet->Delete();; if( m_Actor ) m_Actor->Delete();; } vtkProp* mitk::ContourSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Actor; } void mitk::ContourSetVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if(!visible) { m_Actor->VisibilityOff(); return; } m_Actor->VisibilityOn(); mitk::ContourSet::Pointer input = const_cast(this->GetInput()); if ( renderer->GetDisplayGeometryUpdateTime() > this->GetInput()->GetMTime() ) { m_ContourSet = vtkPolyData::New(); vtkPoints *points = vtkPoints::New(); vtkCellArray *lines = vtkCellArray::New(); mitk::ContourSet::Pointer input = const_cast(this->GetInput()); mitk::ContourSet::ContourVectorType contourVec = input->GetContours(); mitk::ContourSet::ContourIterator contourIt = contourVec.begin(); vtkIdType firstPointIndex= 0, lastPointIndex=0; vtkIdType ptIndex = 0; while ( contourIt != contourVec.end() ) { mitk::Contour* nextContour = (mitk::Contour*) (*contourIt).second; Contour::InputType idx = nextContour->GetContourPath()->StartOfInput(); Contour::InputType end = nextContour->GetContourPath()->EndOfInput(); if (end > 50000) end = 0; mitk::Contour::PointsContainerPointer contourPoints = nextContour->GetPoints(); mitk::Contour::PointsContainerIterator pointsIt = contourPoints->Begin(); unsigned int counter = 0; firstPointIndex=ptIndex; while ( pointsIt != contourPoints->End() ) { if (counter %2 == 0) { Contour::BoundingBoxType::PointType point; point = pointsIt.Value(); points->InsertPoint(ptIndex, point[0],point[1],point[2]); if (ptIndex > firstPointIndex) { int cell[2] = {ptIndex-1,ptIndex}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } lastPointIndex=ptIndex; ptIndex++; } pointsIt++; idx+=1; } if (nextContour->GetClosed()) { int cell[2] = {lastPointIndex,firstPointIndex}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } contourIt++; } m_ContourSet->SetPoints(points); m_ContourSet->SetLines(lines); m_ContourSet->Update(); m_TubeFilter->SetInput(m_ContourSet); m_TubeFilter->SetRadius(1); m_TubeFilter->Update(); m_VtkPolyDataMapper->SetInput(m_TubeFilter->GetOutput()); - vtkFloatingPointType rgba[4]={0.0f,1.0f,0.0f,0.6f}; + double rgba[4]={0.0f,1.0f,0.0f,0.6f}; m_Actor->GetProperty()->SetColor(rgba); m_Actor->SetMapper(m_VtkPolyDataMapper); } SetVtkMapperImmediateModeRendering(m_VtkPolyDataMapper); } const mitk::ContourSet* mitk::ContourSetVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); } diff --git a/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp b/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp index 4a4c5be811..f11fc32859 100644 --- a/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp @@ -1,183 +1,183 @@ /*=================================================================== 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 "mitkContourVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkContour.h" #include #include #include #pragma GCC diagnostic ignored "-Wstrict-aliasing" #include #pragma GCC diagnostic warning "-Wstrict-aliasing" #include #include #include #include #include #include #include #include #include #include mitk::ContourVtkMapper3D::ContourVtkMapper3D() { m_VtkPolyDataMapper = vtkPolyDataMapper::New(); m_VtkPointList = vtkAppendPolyData::New(); m_Actor = vtkActor::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); m_TubeFilter = vtkTubeFilter::New(); } mitk::ContourVtkMapper3D::~ContourVtkMapper3D() { if(m_VtkPolyDataMapper) m_VtkPolyDataMapper->Delete(); if(m_TubeFilter) m_TubeFilter->Delete(); if(m_VtkPointList) m_VtkPointList->Delete(); if(m_Contour) m_Contour->Delete(); if(m_Actor) m_Actor->Delete(); } vtkProp* mitk::ContourVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Actor; } void mitk::ContourVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) { m_Actor->VisibilityOff(); return; } m_Actor->VisibilityOn(); m_Contour = vtkPolyData::New(); mitk::Contour::Pointer input = const_cast(this->GetInput()); bool makeContour = true; if ( makeContour ) { vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer lines = vtkSmartPointer::New(); int numPts=input->GetNumberOfPoints(); if ( numPts > 200000 ) numPts = 200000; mitk::Contour::PathPointer path = input->GetContourPath(); mitk::Contour::PathType::InputType cstart = path->StartOfInput(); mitk::Contour::PathType::InputType cend = path->EndOfInput(); mitk::Contour::PathType::InputType cstep = (cend-cstart+1)/numPts; mitk::Contour::PathType::InputType ccur; vtkIdType ptIndex = 0; vtkIdType lastPointIndex = 0; mitk::Contour::PointsContainerPointer contourPoints = input->GetPoints(); mitk::Contour::PointsContainerIterator pointsIt = contourPoints->Begin(); - vtkFloatingPointType vtkpoint[3]; + double vtkpoint[3]; int i; float pointSize = 2; this->GetDataNode()->GetFloatProperty("spheres size", pointSize); bool showPoints = true; this->GetDataNode()->GetBoolProperty("show points", showPoints); if ( showPoints ) { m_VtkPointList = vtkAppendPolyData::New(); } for ( i=0, ccur=cstart; iEvaluate(ccur), vtkpoint); points->InsertPoint(ptIndex, vtkpoint); if ( ptIndex > 0 ) { int cell[2] = {ptIndex-1,ptIndex}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } lastPointIndex = ptIndex; ++ptIndex; if ( showPoints ) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(pointSize); sphere->SetCenter(vtkpoint); m_VtkPointList->AddInput(sphere->GetOutput()); sphere->Update(); } } if ( input->GetClosed() ) { int cell[2] = {lastPointIndex,0}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } m_Contour->SetPoints(points); m_Contour->SetLines(lines); m_Contour->Update(); m_TubeFilter->SetInput(m_Contour); m_TubeFilter->SetRadius(pointSize / 2.0f); m_TubeFilter->SetNumberOfSides(8); m_TubeFilter->Update(); if ( showPoints ) { m_VtkPointList->AddInput(m_TubeFilter->GetOutput()); m_VtkPolyDataMapper->SetInput(m_VtkPointList->GetOutput()); } else { m_VtkPolyDataMapper->SetInput(m_TubeFilter->GetOutput()); } - vtkFloatingPointType rgba[4]={0.0f,1.0f,0.0f,0.6f}; + double rgba[4]={0.0f,1.0f,0.0f,0.6f}; m_Actor->GetProperty()->SetColor(rgba); m_Actor->SetMapper(m_VtkPolyDataMapper); } SetVtkMapperImmediateModeRendering(m_VtkPolyDataMapper); } const mitk::Contour* mitk::ContourVtkMapper3D::GetInput() { return static_cast ( GetDataNode()->GetData() ); }