diff --git a/Modules/Classification/CLUtilities/include/itkNeighborhoodFunctorImageFilter.h b/Modules/Classification/CLUtilities/include/itkNeighborhoodFunctorImageFilter.h index e40a3c790b..49ebff7a87 100644 --- a/Modules/Classification/CLUtilities/include/itkNeighborhoodFunctorImageFilter.h +++ b/Modules/Classification/CLUtilities/include/itkNeighborhoodFunctorImageFilter.h @@ -1,140 +1,140 @@ #ifndef itkNeighborhoodFunctorImageFilter_h #define itkNeighborhoodFunctorImageFilter_h #include "itkImageToImageFilter.h" #include "itkZeroFluxNeumannBoundaryCondition.h" #include "itkConstNeighborhoodIterator.h" #include "itkImage.h" #include "stdio.h" #include #include "itkHistogram.h" namespace itk { template class NeighborhoodFunctorImageFilter : public ImageToImageFilter< TInputImageType, TFeatureImageType> { public: typedef NeighborhoodFunctorImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; itkNewMacro(Self); itkTypeMacro(NeighborhoodFunctorImageFilter, ImageToImageFilter); /** Extract some information from the image types. Dimensionality * of the two images is assumed to be the same. */ itkStaticConstMacro(ImageDimension, unsigned int, TFeatureImageType::ImageDimension); itkStaticConstMacro(InputImageDimension, unsigned int, TInputImageType::ImageDimension); typedef TInputImageType InputImageType; typedef typename TInputImageType::PixelType InputImagePixelType; typedef itk::Image MaskImageType; typedef typename MaskImageType::PixelType MaskImagePixelType; typedef TFeatureImageType FeatureImageType; typedef typename FeatureImageType::PixelType FeaturePixelType; typedef itk::Size SizeType; /** Typedef for generic boundary condition pointer. */ typedef ImageBoundaryCondition< InputImageType > * ImageBoundaryConditionPointerType; /** Typedef for the default boundary condition */ typedef ZeroFluxNeumannBoundaryCondition< InputImageType > DefaultBoundaryCondition; /** Superclass typedefs. */ typedef typename Superclass::OutputImageRegionType OutputImageRegionType; typedef Neighborhood< InputImagePixelType, InputImageDimension > NeighborhoodType; /** Allows a user to override the internal boundary condition. Care should be * be taken to ensure that the overriding boundary condition is a persistent * object during the time it is referenced. The overriding condition * can be of a different type than the default type as long as it is * a subclass of ImageBoundaryCondition. */ void OverrideBoundaryCondition(const ImageBoundaryConditionPointerType i) { m_BoundsCondition = i; } /** Get the boundary condition specified */ ImageBoundaryConditionPointerType GetBoundaryCondition() { return m_BoundsCondition; } void SetNeighborhoodSize(SizeType size){m_Size = size;} void SetNeighborhoodSize(unsigned int size){m_Size.Fill(size);} SizeType GetNeighborhoodSize(){return m_Size;} void SetMask(const typename MaskImageType::Pointer & ptr){m_MaskImage = ptr;} const FunctorType & GetFunctorReference() const { return m_Functor; } FunctorType & GetFunctorReference() { return m_Functor; } void SetFunctor(const FunctorType & func) { m_Functor = func; } protected: NeighborhoodFunctorImageFilter() { m_Size.Fill(0); m_MaskImage = nullptr; m_BoundsCondition = static_cast< ImageBoundaryConditionPointerType >( &m_DefaultBoundaryCondition ); this->SetNumberOfIndexedOutputs(FunctorType::OutputCount); } ~NeighborhoodFunctorImageFilter(){} void BeforeThreadedGenerateData(); void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, ThreadIdType threadId); /** NeighborhoodFunctorImageFilter needs a larger input requested * region than the output requested region. As such, * NeighborhoodOperatorImageFilter needs to provide an implementation for * GenerateInputRequestedRegion() in order to inform the pipeline * execution model. * * \sa ProcessObject::GenerateInputRequestedRegion() */ - virtual void GenerateInputRequestedRegion() throw ( InvalidRequestedRegionError ); + void GenerateInputRequestedRegion() override; private: NeighborhoodFunctorImageFilter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented /** Pointer to a persistent boundary condition object used * for the image iterator. */ ImageBoundaryConditionPointerType m_BoundsCondition; /** Default boundary condition */ DefaultBoundaryCondition m_DefaultBoundaryCondition; /** Internal operator used to filter the image. */ FunctorType m_Functor; itk::Size m_Size; typename MaskImageType::Pointer m_MaskImage; }; } #ifndef ITK_MANUAL_INSTANTIATION #include "../src/Features/itkNeighborhoodFunctorImageFilter.cpp" #endif #endif // itkFeatureImageFilter_h diff --git a/Modules/Classification/CLUtilities/src/Features/itkNeighborhoodFunctorImageFilter.cpp b/Modules/Classification/CLUtilities/src/Features/itkNeighborhoodFunctorImageFilter.cpp index f79399fe8e..47287c8f9f 100644 --- a/Modules/Classification/CLUtilities/src/Features/itkNeighborhoodFunctorImageFilter.cpp +++ b/Modules/Classification/CLUtilities/src/Features/itkNeighborhoodFunctorImageFilter.cpp @@ -1,157 +1,156 @@ #ifndef itkNeighborhoodFunctorImageFilter_cpp #define itkNeighborhoodFunctorImageFilter_cpp #include "itkNeighborhoodFunctorImageFilter.h" #include "itkNeighborhoodAlgorithm.h" #include namespace itk { template< typename TInputImage, typename TFeatureImageType , class FunctorType> void NeighborhoodFunctorImageFilter< TInputImage, TFeatureImageType, FunctorType > ::BeforeThreadedGenerateData() { const TInputImage * input = this->GetInput(0); for(unsigned int i = 0 ; i < FunctorType::OutputCount; i ++) { typename FeatureImageType::Pointer output = TFeatureImageType::New(); output->SetRegions(input->GetLargestPossibleRegion()); output->SetSpacing(input->GetSpacing()); output->SetOrigin(input->GetOrigin()); output->SetDirection(input->GetDirection()); output->Allocate(); this->SetNthOutput( i, output.GetPointer() ); } if(m_MaskImage.IsNull()) { m_MaskImage = MaskImageType::New(); m_MaskImage->SetRegions(input->GetLargestPossibleRegion()); m_MaskImage->Allocate(); m_MaskImage->FillBuffer(1); } } template< typename TInputImage, typename TFeatureImageType , class FunctorType> void NeighborhoodFunctorImageFilter< TInputImage, TFeatureImageType, FunctorType > ::GenerateInputRequestedRegion() -throw ( InvalidRequestedRegionError ) { // call the superclass' implementation of this method. this should // copy the output requested region to the input requested region Superclass::GenerateInputRequestedRegion(); // get pointers to the input and output TInputImage * inputPtr = const_cast< TInputImage * >( this->GetInput() ); if ( !inputPtr ) { return; } // get a copy of the input requested region (should equal the output // requested region) typename TInputImage::RegionType inputRequestedRegion; inputRequestedRegion = inputPtr->GetRequestedRegion(); // pad the input requested region by the operator radius inputRequestedRegion.PadByRadius( m_Size ); // crop the input requested region at the input's largest possible region if ( inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() ) ) { inputPtr->SetRequestedRegion(inputRequestedRegion); return; } else { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) inputPtr->SetRequestedRegion(inputRequestedRegion); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); e.SetDescription("Requested region is (at least partially) outside the largest possible region."); e.SetDataObject(inputPtr); throw e; } } template< typename TInputImage, typename TFeatureImageType, class FunctorType > void NeighborhoodFunctorImageFilter< TInputImage, TFeatureImageType, FunctorType > ::ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, ThreadIdType /*threadId*/) { typedef NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< InputImageType > BFC; typedef typename BFC::FaceListType FaceListType; BFC faceCalculator; FaceListType faceList; // Allocate output const InputImageType *input = this->GetInput(); // Break the input into a series of regions. The first region is free // of boundary conditions, the rest with boundary conditions. Note, // we pass in the input image and the OUTPUT requested region. We are // only concerned with centering the neighborhood operator at the // pixels that correspond to output pixels. faceList = faceCalculator( input, outputRegionForThread, m_Size ); typename FaceListType::iterator fit; ImageRegionConstIterator< MaskImageType > mit; // Process non-boundary region and each of the boundary faces. // These are N-d regions which border the edge of the buffer. ConstNeighborhoodIterator< InputImageType > bit; // for ( fit = faceList.begin(); fit != faceList.end(); ++fit ) // { bit = ConstNeighborhoodIterator< InputImageType >(m_Size, input, outputRegionForThread); mit = ImageRegionConstIterator< MaskImageType >(m_MaskImage, outputRegionForThread); std::vector > featureImageIterators; for(unsigned int i = 0; i < FunctorType::OutputCount; i++) { featureImageIterators.push_back(ImageRegionIterator< FeatureImageType >(this->GetOutput(i), outputRegionForThread)); featureImageIterators[i].GoToBegin(); } mit.GoToBegin(); bit.GoToBegin(); while ( !bit.IsAtEnd() || !mit.IsAtEnd() ) { if(mit.Value() != 0) { //bit.GetNeighborhood().Print(std::cout); typename FunctorType::OutputVectorType features = ( m_Functor( bit ) ); for(unsigned int i = 0 ; i < FunctorType::OutputCount; i++) featureImageIterators[i].Set(features[i]); } for(unsigned int i = 0 ; i < FunctorType::OutputCount; i++) ++featureImageIterators[i]; ++bit; ++mit; } // } std::cout << "Thread done!" << std::endl; } } // end namespace itk #endif //itkNeighborhoodFunctorImageFilter_cpp diff --git a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h index 4150f9f33a..1b16a5d87a 100644 --- a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h +++ b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.h @@ -1,153 +1,152 @@ /*=================================================================== 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 __itkRegularizedIVIMLocalVariationImageFilter_h #define __itkRegularizedIVIMLocalVariationImageFilter_h #include "itkImageToImageFilter.h" #include "itkImage.h" namespace itk { template class IVIMSquaredEuclideanMetric { public: static double Calc(TPixelType p) { return p*p; } }; template<> class IVIMSquaredEuclideanMetric > { public: static double Calc(itk::Vector p) { return p[1]*p[1]; } }; template<> class IVIMSquaredEuclideanMetric > { public: static double Calc(itk::VariableLengthVector p) { return p.GetSquaredNorm(); } }; template<> class IVIMSquaredEuclideanMetric > { public: static double Calc(itk::VariableLengthVector p) { return p.GetSquaredNorm(); } }; /** \class RegularizedIVIMLocalVariationImageFilter * \brief Calculates the local variation in each pixel * * Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising * * \sa Image * \sa Neighborhood * \sa NeighborhoodOperator * \sa NeighborhoodIterator * * \ingroup IntensityImageFilters */ template class RegularizedIVIMLocalVariationImageFilter : public ImageToImageFilter< TInputImage, TOutputImage > { public: /** Extract dimension from input and output image. */ itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension); /** Convenient typedefs for simplifying declarations. */ typedef TInputImage InputImageType; typedef TOutputImage OutputImageType; /** Standard class typedefs. */ typedef RegularizedIVIMLocalVariationImageFilter Self; typedef ImageToImageFilter< InputImageType, OutputImageType> Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(RegularizedIVIMLocalVariationImageFilter, ImageToImageFilter); /** Image typedef support. */ typedef typename InputImageType::PixelType InputPixelType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename InputImageType::RegionType InputImageRegionType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef typename InputImageType::SizeType InputSizeType; /** MedianImageFilter needs a larger input requested region than * the output requested region. As such, MedianImageFilter needs * to provide an implementation for GenerateInputRequestedRegion() * in order to inform the pipeline execution model. * * \sa ImageToImageFilter::GenerateInputRequestedRegion() */ - virtual void GenerateInputRequestedRegion() - throw(InvalidRequestedRegionError); + virtual void GenerateInputRequestedRegion(); protected: RegularizedIVIMLocalVariationImageFilter(); virtual ~RegularizedIVIMLocalVariationImageFilter() {} void PrintSelf(std::ostream& os, Indent indent) const; /** MedianImageFilter can be implemented as a multithreaded filter. * Therefore, this implementation provides a ThreadedGenerateData() * routine which is called for each processing thread. The output * image data is allocated automatically by the superclass prior to * calling ThreadedGenerateData(). ThreadedGenerateData can only * write to the portion of the output image specified by the * parameter "outputRegionForThread" * * \sa ImageToImageFilter::ThreadedGenerateData(), * ImageToImageFilter::GenerateData() */ void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType threadId ); private: RegularizedIVIMLocalVariationImageFilter(const Self&); //purposely not implemented void operator=(const Self&); //purposely not implemented }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkRegularizedIVIMLocalVariationImageFilter.txx" #endif #endif //RegularizedIVIMLocalVariationImageFilter diff --git a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx index 48bbada5f6..41e8b98647 100644 --- a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx +++ b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMLocalVariationImageFilter.txx @@ -1,192 +1,192 @@ /*=================================================================== 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 _itkRegularizedIVIMLocalVariationImageFilter_txx #define _itkRegularizedIVIMLocalVariationImageFilter_txx #include "itkConstShapedNeighborhoodIterator.h" #include "itkNeighborhoodInnerProduct.h" #include "itkImageRegionIterator.h" #include "itkNeighborhoodAlgorithm.h" #include "itkZeroFluxNeumannBoundaryCondition.h" #include "itkOffset.h" #include "itkProgressReporter.h" #include "itkVectorImage.h" #include #include namespace itk { template RegularizedIVIMLocalVariationImageFilter ::RegularizedIVIMLocalVariationImageFilter() {} template void RegularizedIVIMLocalVariationImageFilter - ::GenerateInputRequestedRegion() throw (InvalidRequestedRegionError) + ::GenerateInputRequestedRegion() { // call the superclass' implementation of this method Superclass::GenerateInputRequestedRegion(); // get pointers to the input and output typename Superclass::InputImagePointer inputPtr = const_cast< TInputImage * >( this->GetInput() ); typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); if ( !inputPtr || !outputPtr ) { return; } // get a copy of the input requested region (should equal the output // requested region) typename TInputImage::RegionType inputRequestedRegion; inputRequestedRegion = inputPtr->GetRequestedRegion(); // pad the input requested region by 1 inputRequestedRegion.PadByRadius( 1 ); // crop the input requested region at the input's largest possible region if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) ) { inputPtr->SetRequestedRegion( inputRequestedRegion ); return; } else { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) inputPtr->SetRequestedRegion( inputRequestedRegion ); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); e.SetDescription("Requested region outside possible region."); e.SetDataObject(inputPtr); throw e; } } template< class TInputImage, class TOutputImage> void RegularizedIVIMLocalVariationImageFilter< TInputImage, TOutputImage> ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType threadId) { // Allocate output typename OutputImageType::Pointer output = this->GetOutput(); typename InputImageType::ConstPointer input = this->GetInput(); itk::Size size; for(unsigned int i=0; i bC; typename NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator::FaceListType faceList = bC(input, outputRegionForThread, size); // support progress methods/callbacks ProgressReporter progress( this, threadId, outputRegionForThread.GetNumberOfPixels()); ZeroFluxNeumannBoundaryCondition nbc; std::vector pixels; // Process each of the boundary faces. These are N-d regions which border // the edge of the buffer. for ( typename NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator::FaceListType::iterator fit=faceList.begin(); fit != faceList.end(); ++fit) { // iterators over output and input ImageRegionIterator output_image_it(output, *fit); ImageRegionConstIterator input_image_it(input.GetPointer(), *fit); // neighborhood iterator for input image ConstShapedNeighborhoodIterator input_image_neighbors_it(size, input, *fit); typename ConstShapedNeighborhoodIterator:: OffsetType offset; input_image_neighbors_it.OverrideBoundaryCondition(&nbc); input_image_neighbors_it.ClearActiveList(); for(unsigned int i=0; i:: ConstIterator input_neighbors_it; for (input_neighbors_it = input_image_neighbors_it.Begin(); ! input_neighbors_it.IsAtEnd(); input_neighbors_it++) { typename TInputImage::PixelType diffVec = input_neighbors_it.Get()-input_image_it.Get(); locVariation += IVIMSquaredEuclideanMetric ::Calc(diffVec); } locVariation = sqrt(locVariation + 0.0001); output_image_it.Set(locVariation); // update iterators ++input_image_neighbors_it; ++output_image_it; ++input_image_it; // report progress progress.CompletedPixel(); } } } /** * Standard "PrintSelf" method */ template void RegularizedIVIMLocalVariationImageFilter ::PrintSelf( std::ostream& os, Indent indent) const { Superclass::PrintSelf( os, indent ); } } // end namespace itk #endif //_itkRegularizedIVIMLocalVariationImageFilter_txx diff --git a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h index b75361b4d0..96e01e8548 100644 --- a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h +++ b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.h @@ -1,142 +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 __itkRegularizedIVIMReconstructionSingleIteration_h #define __itkRegularizedIVIMReconstructionSingleIteration_h #include "itkImageToImageFilter.h" #include "itkImage.h" #include "itkVectorImage.h" namespace itk { /** \class RegularizedIVIMReconstructionSingleIteration * \brief Applies a total variation denoising filter to an image * * Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising * * \sa Image * \sa Neighborhood * \sa NeighborhoodOperator * \sa NeighborhoodIterator * * \ingroup IntensityImageFilters */ template class RegularizedIVIMReconstructionSingleIteration : public ImageToImageFilter< itk::Image, 3>, itk::Image, 3> > { public: /** Convenient typedefs for simplifying declarations. */ typedef itk::Image, 3> InputImageType; typedef itk::Image, 3> OutputImageType; typedef itk::VectorImage RefImageType; /** Extract dimension from input and output image. */ itkStaticConstMacro(InputImageDimension, unsigned int, InputImageType::ImageDimension); itkStaticConstMacro(OutputImageDimension, unsigned int, OutputImageType::ImageDimension); typedef itk::Image LocalVariationImageType; /** Standard class typedefs. */ typedef RegularizedIVIMReconstructionSingleIteration Self; typedef ImageToImageFilter< InputImageType, OutputImageType> Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(RegularizedIVIMReconstructionSingleIteration, ImageToImageFilter); /** Image typedef support. */ typedef typename InputImageType::PixelType InputPixelType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename InputImageType::RegionType InputImageRegionType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef typename InputImageType::SizeType InputSizeType; /** A larger input requested region than * the output requested region is required. * Therefore, an implementation for GenerateInputRequestedRegion() * is provided. * * \sa ImageToImageFilter::GenerateInputRequestedRegion() */ - virtual void GenerateInputRequestedRegion() - throw(InvalidRequestedRegionError); + virtual void GenerateInputRequestedRegion(); itkSetMacro(Lambda, double); itkGetMacro(Lambda, double); void SetBValues(vnl_vector bvals) { this->m_BValues = bvals; } vnl_vector GetBValues() { return this->m_BValues; } void SetOriginalImage(RefImageType* in) { this->m_OriginalImage = in; } typename RefImageType::Pointer GetOriginialImage() { return this->m_OriginalImage; } protected: RegularizedIVIMReconstructionSingleIteration(); virtual ~RegularizedIVIMReconstructionSingleIteration() {} void PrintSelf(std::ostream& os, Indent indent) const; /** MedianImageFilter can be implemented as a multithreaded filter. * Therefore, this implementation provides a ThreadedGenerateData() * routine which is called for each processing thread. The output * image data is allocated automatically by the superclass prior to * calling ThreadedGenerateData(). ThreadedGenerateData can only * write to the portion of the output image specified by the * parameter "outputRegionForThread" * * \sa ImageToImageFilter::ThreadedGenerateData(), * ImageToImageFilter::GenerateData() */ void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType threadId ); void BeforeThreadedGenerateData(); typename LocalVariationImageType::Pointer m_LocalVariation; typename RefImageType::Pointer m_OriginalImage; double m_Lambda; vnl_vector m_BValues; private: RegularizedIVIMReconstructionSingleIteration(const Self&); void operator=(const Self&); }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkRegularizedIVIMReconstructionSingleIteration.txx" #endif #endif //__itkRegularizedIVIMReconstructionSingleIteration__ diff --git a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx index 379820a986..c9b2f4dad5 100644 --- a/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx +++ b/Modules/DiffusionImaging/Quantification/Algorithms/itkRegularizedIVIMReconstructionSingleIteration.txx @@ -1,310 +1,310 @@ /*=================================================================== 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 _itkRegularizedIVIMReconstructionSingleIteration_txx #define _itkRegularizedIVIMReconstructionSingleIteration_txx // itk includes #include "itkConstShapedNeighborhoodIterator.h" #include "itkNeighborhoodInnerProduct.h" #include "itkImageRegionIterator.h" #include "itkNeighborhoodAlgorithm.h" #include "itkZeroFluxNeumannBoundaryCondition.h" #include "itkOffset.h" #include "itkProgressReporter.h" #include "itkRegularizedIVIMLocalVariationImageFilter.h" // other includes #include #include #define IVIM_FOO -100000 namespace itk { /** * constructor */ template RegularizedIVIMReconstructionSingleIteration ::RegularizedIVIMReconstructionSingleIteration() { m_Lambda = 1.0; m_LocalVariation = LocalVariationImageType::New(); } /** * generate requested region */ template void RegularizedIVIMReconstructionSingleIteration - ::GenerateInputRequestedRegion() throw (InvalidRequestedRegionError) + ::GenerateInputRequestedRegion() { // call the superclass' implementation of this method Superclass::GenerateInputRequestedRegion(); // get pointers to the input and output typename Superclass::InputImagePointer inputPtr = const_cast< InputImageType * >( this->GetInput() ); typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); if ( !inputPtr || !outputPtr ) { return; } // get a copy of the input requested region (should equal the output // requested region) typename InputImageType::RegionType inputRequestedRegion; inputRequestedRegion = inputPtr->GetRequestedRegion(); // pad the input requested region by 1 inputRequestedRegion.PadByRadius( 1 ); // crop the input requested region at the input's largest possible region if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) ) { inputPtr->SetRequestedRegion( inputRequestedRegion ); return; } else { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) inputPtr->SetRequestedRegion( inputRequestedRegion ); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); e.SetDescription("Requested region outside possible region."); e.SetDataObject(inputPtr); throw e; } } /** * generate output */ template void RegularizedIVIMReconstructionSingleIteration ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, ThreadIdType) { typename OutputImageType::Pointer output = this->GetOutput(); typename InputImageType::ConstPointer input = this->GetInput(); // Find the data-set boundary "faces" itk::Size size; for( unsigned int i=0; i bC; typename NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator::FaceListType faceList = bC(input, outputRegionForThread, size); NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator lv_bC; typename NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator::FaceListType lv_faceList = lv_bC(m_LocalVariation, outputRegionForThread, size); ZeroFluxNeumannBoundaryCondition nbc; ZeroFluxNeumannBoundaryCondition lv_nbc; std::vector ws; std::vector hs; typename NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator::FaceListType::iterator lv_fit=lv_faceList.begin(); // Process each of the boundary faces. These are N-d regions which border // the edge of the buffer. for ( typename NeighborhoodAlgorithm:: ImageBoundaryFacesCalculator::FaceListType::iterator fit=faceList.begin(); fit != faceList.end(); ++fit) { // iterators over output, input, original and local variation image ImageRegionIterator output_image_it = ImageRegionIterator(output, *fit); ImageRegionConstIterator input_image_it = ImageRegionConstIterator(input, *fit); ImageRegionConstIterator orig_image_it = ImageRegionConstIterator(m_OriginalImage, *fit); ImageRegionConstIterator loc_var_image_it = ImageRegionConstIterator( m_LocalVariation, *fit); // neighborhood in input image ConstShapedNeighborhoodIterator input_image_neighbors_it(size, input, *fit); typename ConstShapedNeighborhoodIterator:: OffsetType offset; input_image_neighbors_it.OverrideBoundaryCondition(&nbc); input_image_neighbors_it.ClearActiveList(); for(unsigned int i=0; i loc_var_image_neighbors_it(size, m_LocalVariation, *lv_fit); loc_var_image_neighbors_it.OverrideBoundaryCondition(&lv_nbc); loc_var_image_neighbors_it.ClearActiveList(); for(unsigned int i=0; i:: ConstIterator loc_var_neighbors_it; for (loc_var_neighbors_it = loc_var_image_neighbors_it.Begin(); ! loc_var_neighbors_it.IsAtEnd(); loc_var_neighbors_it++) { // w_alphabeta(u) = // 1 / ||nabla_alpha(u)||_a + 1 / ||nabla_beta(u)||_a ws[count] = locvar_alpha_inv + (1.0/(double)loc_var_neighbors_it.Get()); wsum += ws[count++]; //MITK_INFO << "nb var: " << count << ": " << loc_var_neighbors_it.Get(); } //MITK_INFO << "wsum: " << wsum; // h_alphaalpha * u_alpha^zero typename RefImageType::PixelType orig = orig_image_it.Get(); // vnl_vector estim(orig.GetSize()); // vnl_matrix diff(orig.GetSize(),1); // vnl_matrix estimdash(orig.GetSize(),2); vnl_vector_fixed step; step[0] = 0; step[1]=0; for(size_t ind=0; ind:: ConstIterator input_neighbors_it; for (input_neighbors_it = input_image_neighbors_it.Begin(); ! input_neighbors_it.IsAtEnd(); input_neighbors_it++) { step[1] += (input_neighbors_it.Get()[1] - input_image_it.Get()[1]) * (ws[count++] / (m_Lambda+wsum)); } //MITK_INFO << "stepfinal: " << step[0] << "; " << step[1]; // set output result OutputPixelType out; out[0] = input_image_it.Get()[0] + .001*step[0]; out[1] = input_image_it.Get()[1] + .00001*step[1]; output_image_it.Set( out ); //MITK_INFO << "(" << input_image_it.Get()[0] << " ; " << input_image_it.Get()[1] << ") => (" << out[0] << " ; " << out[1] << ")"; // increment iterators ++output_image_it; ++input_image_it; ++orig_image_it; ++loc_var_image_it; ++input_image_neighbors_it; ++loc_var_image_neighbors_it; } ++lv_fit; } } /** * first calculate local variation in the image */ template void RegularizedIVIMReconstructionSingleIteration ::BeforeThreadedGenerateData() { typedef typename itk::RegularizedIVIMLocalVariationImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); filter->SetInput(this->GetInput(0)); filter->SetNumberOfThreads(this->GetNumberOfThreads()); filter->Update(); this->m_LocalVariation = filter->GetOutput(); } /** * Standard "PrintSelf" method */ template void RegularizedIVIMReconstructionSingleIteration ::PrintSelf( std::ostream& os, Indent indent) const { Superclass::PrintSelf( os, indent ); } } // end namespace itk #endif diff --git a/Modules/ImageDenoising/itkLocalVariationImageFilter.h b/Modules/ImageDenoising/itkLocalVariationImageFilter.h index 1bf29aa388..3023028660 100644 --- a/Modules/ImageDenoising/itkLocalVariationImageFilter.h +++ b/Modules/ImageDenoising/itkLocalVariationImageFilter.h @@ -1,113 +1,113 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkLocalVariationImageFilter_h #define __itkLocalVariationImageFilter_h #include "itkImage.h" #include "itkImageToImageFilter.h" namespace itk { template class SquaredEuclideanMetric { public: static double Calc(TPixelType p); }; /** \class LocalVariationImageFilter * \brief Calculates the local variation in each pixel * * Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising * * \sa Image * \sa Neighborhood * \sa NeighborhoodOperator * \sa NeighborhoodIterator * * \ingroup IntensityImageFilters */ template class LocalVariationImageFilter : public ImageToImageFilter { public: /** Extract dimension from input and output image. */ itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension); /** Convenient typedefs for simplifying declarations. */ typedef TInputImage InputImageType; typedef TOutputImage OutputImageType; /** Standard class typedefs. */ typedef LocalVariationImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(LocalVariationImageFilter, ImageToImageFilter); /** Image typedef support. */ typedef typename InputImageType::PixelType InputPixelType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename InputImageType::RegionType InputImageRegionType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef typename InputImageType::SizeType InputSizeType; /** MedianImageFilter needs a larger input requested region than * the output requested region. As such, MedianImageFilter needs * to provide an implementation for GenerateInputRequestedRegion() * in order to inform the pipeline execution model. * * \sa ImageToImageFilter::GenerateInputRequestedRegion() */ - virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError); + virtual void GenerateInputRequestedRegion(); protected: LocalVariationImageFilter(); virtual ~LocalVariationImageFilter() {} void PrintSelf(std::ostream &os, Indent indent) const; /** MedianImageFilter can be implemented as a multithreaded filter. * Therefore, this implementation provides a ThreadedGenerateData() * routine which is called for each processing thread. The output * image data is allocated automatically by the superclass prior to * calling ThreadedGenerateData(). ThreadedGenerateData can only * write to the portion of the output image specified by the * parameter "outputRegionForThread" * * \sa ImageToImageFilter::ThreadedGenerateData(), * ImageToImageFilter::GenerateData() */ void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId); private: LocalVariationImageFilter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkLocalVariationImageFilter.txx" #endif #endif // LocalVariationImageFilter diff --git a/Modules/ImageDenoising/itkLocalVariationImageFilter.txx b/Modules/ImageDenoising/itkLocalVariationImageFilter.txx index 3048232a6c..3cc4a1823e 100644 --- a/Modules/ImageDenoising/itkLocalVariationImageFilter.txx +++ b/Modules/ImageDenoising/itkLocalVariationImageFilter.txx @@ -1,193 +1,192 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef _itkLocalVariationImageFilter_txx #define _itkLocalVariationImageFilter_txx #include "itkLocalVariationImageFilter.h" #include "itkConstShapedNeighborhoodIterator.h" #include "itkImageRegionIterator.h" #include "itkNeighborhoodAlgorithm.h" #include "itkNeighborhoodInnerProduct.h" #include "itkOffset.h" #include "itkProgressReporter.h" #include "itkVectorImage.h" #include "itkZeroFluxNeumannBoundaryCondition.h" #include #include namespace itk { template LocalVariationImageFilter::LocalVariationImageFilter() { } template - void LocalVariationImageFilter::GenerateInputRequestedRegion() throw( - InvalidRequestedRegionError) + void LocalVariationImageFilter::GenerateInputRequestedRegion() { // call the superclass' implementation of this method Superclass::GenerateInputRequestedRegion(); // get pointers to the input and output typename Superclass::InputImagePointer inputPtr = const_cast(this->GetInput()); typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); if (!inputPtr || !outputPtr) { return; } // get a copy of the input requested region (should equal the output // requested region) typename TInputImage::RegionType inputRequestedRegion; inputRequestedRegion = inputPtr->GetRequestedRegion(); // pad the input requested region by 1 inputRequestedRegion.PadByRadius(1); // crop the input requested region at the input's largest possible region if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion())) { inputPtr->SetRequestedRegion(inputRequestedRegion); return; } else { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) inputPtr->SetRequestedRegion(inputRequestedRegion); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); e.SetDescription("Requested region outside possible region."); e.SetDataObject(inputPtr); throw e; } } template <> double SquaredEuclideanMetric>::Calc(itk::VariableLengthVector p) { return p.GetSquaredNorm(); } template <> double SquaredEuclideanMetric>::Calc(itk::VariableLengthVector p) { return p.GetSquaredNorm(); } template double SquaredEuclideanMetric::Calc(TPixelType p) { return p * p; } template void LocalVariationImageFilter::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) { // Allocate output typename OutputImageType::Pointer output = this->GetOutput(); typename InputImageType::ConstPointer input = this->GetInput(); itk::Size size; for (unsigned int i = 0; i < InputImageDimension; i++) size[i] = 1; // Find the data-set boundary "faces" NeighborhoodAlgorithm::ImageBoundaryFacesCalculator bC; typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator::FaceListType faceList = bC(input, outputRegionForThread, size); // support progress methods/callbacks ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); ZeroFluxNeumannBoundaryCondition nbc; std::vector pixels; // Process each of the boundary faces. These are N-d regions which border // the edge of the buffer. for (auto fit = faceList.begin(); fit != faceList.end(); ++fit) { // iterators over output and input ImageRegionIterator output_image_it(output, *fit); ImageRegionConstIterator input_image_it(input.GetPointer(), *fit); // neighborhood iterator for input image ConstShapedNeighborhoodIterator input_image_neighbors_it(size, input, *fit); typename ConstShapedNeighborhoodIterator::OffsetType offset; input_image_neighbors_it.OverrideBoundaryCondition(&nbc); input_image_neighbors_it.ClearActiveList(); for (unsigned int i = 0; i < InputImageDimension; i++) { offset.Fill(0); offset[i] = -1; input_image_neighbors_it.ActivateOffset(offset); offset[i] = 1; input_image_neighbors_it.ActivateOffset(offset); } input_image_neighbors_it.GoToBegin(); // const unsigned int neighborhoodSize = InputImageDimension*2; while (!input_image_neighbors_it.IsAtEnd()) { // collect all the pixels in the neighborhood, note that we use // GetPixel on the NeighborhoodIterator to honor the boundary conditions typename OutputImageType::PixelType locVariation = 0; typename ConstShapedNeighborhoodIterator::ConstIterator input_neighbors_it; for (input_neighbors_it = input_image_neighbors_it.Begin(); !input_neighbors_it.IsAtEnd(); input_neighbors_it++) { typename TInputImage::PixelType diffVec = input_neighbors_it.Get() - input_image_it.Get(); locVariation += SquaredEuclideanMetric::Calc(diffVec); } locVariation = sqrt(locVariation + 0.0001); output_image_it.Set(locVariation); // update iterators ++input_image_neighbors_it; ++output_image_it; ++input_image_it; // report progress progress.CompletedPixel(); } } } /** * Standard "PrintSelf" method */ template void LocalVariationImageFilter::PrintSelf(std::ostream &os, Indent indent) const { Superclass::PrintSelf(os, indent); } } // end namespace itk #endif //_itkLocalVariationImageFilter_txx diff --git a/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.h b/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.h index 912ad6c035..dc54372cd4 100644 --- a/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.h +++ b/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.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 __itkTotalVariationSingleIterationImageFilter_h #define __itkTotalVariationSingleIterationImageFilter_h #include "itkImage.h" #include "itkImageToImageFilter.h" namespace itk { /** \class TotalVariationSingleIterationImageFilter * \brief Applies a total variation denoising filter to an image * * Reference: Tony F. Chan et al., The digital TV filter and nonlinear denoising * * \sa Image * \sa Neighborhood * \sa NeighborhoodOperator * \sa NeighborhoodIterator * * \ingroup IntensityImageFilters */ template class TotalVariationSingleIterationImageFilter : public ImageToImageFilter { public: /** Extract dimension from input and output image. */ itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension); /** Convenient typedefs for simplifying declarations. */ typedef TInputImage InputImageType; typedef TOutputImage OutputImageType; typedef itk::Image LocalVariationImageType; /** Standard class typedefs. */ typedef TotalVariationSingleIterationImageFilter Self; typedef ImageToImageFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(TotalVariationSingleIterationImageFilter, ImageToImageFilter); /** Image typedef support. */ typedef typename InputImageType::PixelType InputPixelType; typedef typename OutputImageType::PixelType OutputPixelType; typedef typename InputImageType::RegionType InputImageRegionType; typedef typename OutputImageType::RegionType OutputImageRegionType; typedef typename InputImageType::SizeType InputSizeType; /** A larger input requested region than * the output requested region is required. * Therefore, an implementation for GenerateInputRequestedRegion() * is provided. * * \sa ImageToImageFilter::GenerateInputRequestedRegion() */ - virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError); + virtual void GenerateInputRequestedRegion(); itkSetMacro(Lambda, double); itkGetMacro(Lambda, double); void SetOriginalImage(InputImageType *in) { this->m_OriginalImage = in; } typename InputImageType::Pointer GetOriginialImage() { return this->m_OriginalImage; } protected: TotalVariationSingleIterationImageFilter(); virtual ~TotalVariationSingleIterationImageFilter() {} void PrintSelf(std::ostream &os, Indent indent) const; /** MedianImageFilter can be implemented as a multithreaded filter. * Therefore, this implementation provides a ThreadedGenerateData() * routine which is called for each processing thread. The output * image data is allocated automatically by the superclass prior to * calling ThreadedGenerateData(). ThreadedGenerateData can only * write to the portion of the output image specified by the * parameter "outputRegionForThread" * * \sa ImageToImageFilter::ThreadedGenerateData(), * ImageToImageFilter::GenerateData() */ void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId); void BeforeThreadedGenerateData(); typename LocalVariationImageType::Pointer m_LocalVariation; typename InputImageType::Pointer m_OriginalImage; double m_Lambda; private: TotalVariationSingleIterationImageFilter(const Self &); void operator=(const Self &); }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkTotalVariationSingleIterationImageFilter.txx" #endif #endif //__itkTotalVariationSingleIterationImageFilter__ diff --git a/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.txx b/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.txx index 13bd039e27..488730a2ad 100644 --- a/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.txx +++ b/Modules/ImageDenoising/itkTotalVariationSingleIterationImageFilter.txx @@ -1,256 +1,255 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef _itkTotalVariationSingleIterationImageFilter_txx #define _itkTotalVariationSingleIterationImageFilter_txx #include "itkTotalVariationSingleIterationImageFilter.h" // itk includes #include "itkConstShapedNeighborhoodIterator.h" #include "itkImageRegionIterator.h" #include "itkLocalVariationImageFilter.h" #include "itkNeighborhoodAlgorithm.h" #include "itkNeighborhoodInnerProduct.h" #include "itkOffset.h" #include "itkProgressReporter.h" #include "itkZeroFluxNeumannBoundaryCondition.h" // other includes #include #include namespace itk { /** * constructor */ template TotalVariationSingleIterationImageFilter::TotalVariationSingleIterationImageFilter() { m_Lambda = 1.0; m_LocalVariation = LocalVariationImageType::New(); } /** * generate requested region */ template - void TotalVariationSingleIterationImageFilter::GenerateInputRequestedRegion() throw( - InvalidRequestedRegionError) + void TotalVariationSingleIterationImageFilter::GenerateInputRequestedRegion() { // call the superclass' implementation of this method Superclass::GenerateInputRequestedRegion(); // get pointers to the input and output typename Superclass::InputImagePointer inputPtr = const_cast(this->GetInput()); typename Superclass::OutputImagePointer outputPtr = this->GetOutput(); if (!inputPtr || !outputPtr) { return; } // get a copy of the input requested region (should equal the output // requested region) typename TInputImage::RegionType inputRequestedRegion; inputRequestedRegion = inputPtr->GetRequestedRegion(); // pad the input requested region by 1 inputRequestedRegion.PadByRadius(1); // crop the input requested region at the input's largest possible region if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion())) { inputPtr->SetRequestedRegion(inputRequestedRegion); return; } else { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) inputPtr->SetRequestedRegion(inputRequestedRegion); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); e.SetDescription("Requested region outside possible region."); e.SetDataObject(inputPtr); throw e; } } /** * generate output */ template void TotalVariationSingleIterationImageFilter::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, ThreadIdType threadId) { typename OutputImageType::Pointer output = this->GetOutput(); typename InputImageType::ConstPointer input = this->GetInput(); // Find the data-set boundary "faces" itk::Size size; for (unsigned int i = 0; i < InputImageDimension; i++) size[i] = 1; NeighborhoodAlgorithm::ImageBoundaryFacesCalculator bC; typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator::FaceListType faceList = bC(input, outputRegionForThread, size); NeighborhoodAlgorithm::ImageBoundaryFacesCalculator lv_bC; typename NeighborhoodAlgorithm::ImageBoundaryFacesCalculator::FaceListType lv_faceList = lv_bC(m_LocalVariation, outputRegionForThread, size); // support progress methods/callbacks ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); ZeroFluxNeumannBoundaryCondition nbc; ZeroFluxNeumannBoundaryCondition lv_nbc; std::vector ws; std::vector hs; auto lv_fit = lv_faceList.begin(); // Process each of the boundary faces. These are N-d regions which border // the edge of the buffer. for (auto fit = faceList.begin(); fit != faceList.end(); ++fit) { // iterators over output, input, original and local variation image ImageRegionIterator output_image_it = ImageRegionIterator(output, *fit); ImageRegionConstIterator input_image_it = ImageRegionConstIterator(input, *fit); ImageRegionConstIterator orig_image_it = ImageRegionConstIterator(m_OriginalImage, *fit); ImageRegionConstIterator loc_var_image_it = ImageRegionConstIterator(m_LocalVariation, *fit); // neighborhood in input image ConstShapedNeighborhoodIterator input_image_neighbors_it(size, input, *fit); typename ConstShapedNeighborhoodIterator::OffsetType offset; input_image_neighbors_it.OverrideBoundaryCondition(&nbc); input_image_neighbors_it.ClearActiveList(); for (unsigned int i = 0; i < InputImageDimension; i++) { offset.Fill(0); offset[i] = -1; input_image_neighbors_it.ActivateOffset(offset); offset[i] = 1; input_image_neighbors_it.ActivateOffset(offset); } input_image_neighbors_it.GoToBegin(); // neighborhood in local variation image ConstShapedNeighborhoodIterator loc_var_image_neighbors_it( size, m_LocalVariation, *lv_fit); loc_var_image_neighbors_it.OverrideBoundaryCondition(&lv_nbc); loc_var_image_neighbors_it.ClearActiveList(); for (unsigned int i = 0; i < InputImageDimension; i++) { offset.Fill(0); offset[i] = -1; loc_var_image_neighbors_it.ActivateOffset(offset); offset[i] = 1; loc_var_image_neighbors_it.ActivateOffset(offset); } loc_var_image_neighbors_it.GoToBegin(); const unsigned int neighborhoodSize = InputImageDimension * 2; ws.resize(neighborhoodSize); while (!output_image_it.IsAtEnd()) { // 1 / ||nabla_alpha(u)||_a double locvar_alpha_inv = 1.0 / loc_var_image_it.Get(); // compute w_alphabetas int count = 0; double wsum = 0; typename ConstShapedNeighborhoodIterator::ConstIterator loc_var_neighbors_it; for (loc_var_neighbors_it = loc_var_image_neighbors_it.Begin(); !loc_var_neighbors_it.IsAtEnd(); loc_var_neighbors_it++) { // w_alphabeta(u) = // 1 / ||nabla_alpha(u)||_a + 1 / ||nabla_beta(u)||_a ws[count] = locvar_alpha_inv + (1.0 / (double)loc_var_neighbors_it.Get()); wsum += ws[count++]; } // h_alphaalpha * u_alpha^zero typename OutputImageType::PixelType res = static_cast( ((typename OutputImageType::PixelType)orig_image_it.Get()) * (m_Lambda / (m_Lambda + wsum))); // add the different h_alphabeta * u_beta count = 0; typename ConstShapedNeighborhoodIterator::ConstIterator input_neighbors_it; for (input_neighbors_it = input_image_neighbors_it.Begin(); !input_neighbors_it.IsAtEnd(); input_neighbors_it++) { res += input_neighbors_it.Get() * (ws[count++] / (m_Lambda + wsum)); } // set output result output_image_it.Set(res); // increment iterators ++output_image_it; ++input_image_it; ++orig_image_it; ++loc_var_image_it; ++input_image_neighbors_it; ++loc_var_image_neighbors_it; // report progress progress.CompletedPixel(); } ++lv_fit; } } /** * first calculate local variation in the image */ template void TotalVariationSingleIterationImageFilter::BeforeThreadedGenerateData() { typedef typename itk::LocalVariationImageFilter FilterType; typename FilterType::Pointer filter = FilterType::New(); filter->SetInput(this->GetInput(0)); filter->SetNumberOfThreads(this->GetNumberOfThreads()); filter->Update(); this->m_LocalVariation = filter->GetOutput(); } /** * Standard "PrintSelf" method */ template void TotalVariationSingleIterationImageFilter::PrintSelf(std::ostream &os, Indent indent) const { Superclass::PrintSelf(os, indent); } } // end namespace itk #endif diff --git a/Modules/MapperExt/src/mitkMeshMapper2D.cpp b/Modules/MapperExt/src/mitkMeshMapper2D.cpp index 8e0f3a790c..2160a83302 100644 --- a/Modules/MapperExt/src/mitkMeshMapper2D.cpp +++ b/Modules/MapperExt/src/mitkMeshMapper2D.cpp @@ -1,482 +1,483 @@ /*=================================================================== 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 "mitkMeshMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkColorProperty.h" #include "mitkGL.h" #include "mitkLine.h" #include "mitkMesh.h" #include "mitkPlaneGeometry.h" #include "mitkProperties.h" #include #include const float selectedColor[] = {1.0f, 0.0f, 0.6f}; // for selected! mitk::MeshMapper2D::MeshMapper2D() { } mitk::MeshMapper2D::~MeshMapper2D() { } const mitk::Mesh *mitk::MeshMapper2D::GetInput(void) { return static_cast(GetDataNode()->GetData()); } // Return whether a point is "smaller" than the second static bool point3DSmaller(const mitk::Point3D &elem1, const mitk::Point3D &elem2) { if (elem1[0] != elem2[0]) return elem1[0] < elem2[0]; if (elem1[1] != elem2[1]) return elem1[1] < elem2[1]; return elem1[2] < elem2[2]; } void mitk::MeshMapper2D::Paint(mitk::BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) return; // @FIXME: Logik fuer update bool updateNeccesary = true; if (updateNeccesary) { // aus GenerateData mitk::Mesh::Pointer input = const_cast(this->GetInput()); // Get the TimeGeometry of the input object const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); if ((inputTimeGeometry == nullptr) || (inputTimeGeometry->CountTimeSteps() == 0)) { return; } // // get the world time // ScalarType time = renderer->GetTime(); // // convert the world time in time steps of the input object // int timeStep = 0; if (time > itk::NumericTraits::NonpositiveMin()) timeStep = inputTimeGeometry->TimePointToTimeStep(time); if (inputTimeGeometry->IsValidTimeStep(timeStep) == false) { return; } mitk::Mesh::MeshType::Pointer itkMesh = input->GetMesh(timeStep); if (itkMesh.GetPointer() == nullptr) { return; } const PlaneGeometry *worldplanegeometry = (renderer->GetCurrentWorldPlaneGeometry()); // apply color and opacity read from the PropertyList ApplyColorAndOpacityProperties(renderer); vtkLinearTransform *transform = GetDataNode()->GetVtkTransform(); // List of the Points Mesh::DataType::PointsContainerConstIterator it, end; it = itkMesh->GetPoints()->Begin(); end = itkMesh->GetPoints()->End(); // iterator on the additional data of each point Mesh::PointDataIterator dataIt; //, dataEnd; dataIt = itkMesh->GetPointData()->Begin(); // for switching back to old color after using selected color float unselectedColor[4]; glGetFloatv(GL_CURRENT_COLOR, unselectedColor); while (it != end) { mitk::Point3D p, projected_p; float vtkp[3]; itk2vtk(it->Value(), vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->GetCurrentWorldPlaneGeometry()->Project(p, projected_p); Vector3D diff = p - projected_p; if (diff.GetSquaredNorm() < 4.0) { Point2D pt2d, tmp; renderer->WorldToDisplay(p, pt2d); Vector2D horz, vert; horz[0] = 5; horz[1] = 0; vert[0] = 0; vert[1] = 5; // check if the point is to be marked as selected if (dataIt->Value().selected) { horz[0] = 8; vert[1] = 8; glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red switch (dataIt->Value().pointSpec) { case PTSTART: { // a quad glBegin(GL_LINE_LOOP); tmp = pt2d - horz + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz - vert; glVertex2dv(&tmp[0]); tmp = pt2d - horz - vert; glVertex2dv(&tmp[0]); glEnd(); } break; case PTUNDEFINED: { // a diamond around the point glBegin(GL_LINE_LOOP); tmp = pt2d - horz; glVertex2dv(&tmp[0]); tmp = pt2d + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz; glVertex2dv(&tmp[0]); tmp = pt2d - vert; glVertex2dv(&tmp[0]); glEnd(); } break; default: break; } // switch // the actual point glBegin(GL_POINTS); tmp = pt2d; glVertex2dv(&tmp[0]); glEnd(); } else // if not selected { + // TODO: check if this is used anywhere, since it never worked before the last fix glColor3f(unselectedColor[0], unselectedColor[1], unselectedColor[2]); switch (dataIt->Value().pointSpec) { case PTSTART: { // a quad glBegin(GL_LINE_LOOP); tmp = pt2d - horz + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz + vert; glVertex2dv(&tmp[0]); tmp = pt2d + horz - vert; glVertex2dv(&tmp[0]); tmp = pt2d - horz - vert; glVertex2dv(&tmp[0]); glEnd(); } case PTUNDEFINED: { // drawing crosses glBegin(GL_LINES); tmp = pt2d - horz; glVertex2dv(&tmp[0]); tmp = pt2d + horz; glVertex2dv(&tmp[0]); tmp = pt2d - vert; glVertex2dv(&tmp[0]); tmp = pt2d + vert; glVertex2dv(&tmp[0]); glEnd(); } default: { break; } } // switch } // else } ++it; ++dataIt; } // now connect the lines inbetween mitk::Mesh::PointType thisPoint; thisPoint.Fill(0); Point2D *firstOfCell = nullptr; Point2D *lastPoint = nullptr; unsigned int lastPointId = 0; bool lineSelected = false; Point3D firstOfCell3D; Point3D lastPoint3D; bool first; mitk::Line line; std::vector intersectionPoints; double t; // iterate through all cells and then iterate through all indexes of points in that cell Mesh::CellIterator cellIt, cellEnd; Mesh::CellDataIterator cellDataIt; //, cellDataEnd; Mesh::PointIdIterator cellIdIt, cellIdEnd; cellIt = itkMesh->GetCells()->Begin(); cellEnd = itkMesh->GetCells()->End(); cellDataIt = itkMesh->GetCellData()->Begin(); while (cellIt != cellEnd) { unsigned int numOfPointsInCell = cellIt->Value()->GetNumberOfPoints(); if (numOfPointsInCell > 1) { // iterate through all id's in the cell cellIdIt = cellIt->Value()->PointIdsBegin(); cellIdEnd = cellIt->Value()->PointIdsEnd(); firstOfCell3D = input->GetPoint(*cellIdIt, timeStep); intersectionPoints.clear(); intersectionPoints.reserve(numOfPointsInCell); first = true; while (cellIdIt != cellIdEnd) { lastPoint3D = thisPoint; thisPoint = input->GetPoint(*cellIdIt, timeStep); // search in data (vector<> selectedLines) if the index of the point is set. if so, then the line is selected. lineSelected = false; Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines; // a line between 1(lastPoint) and 2(pt2d) has the Id 1, so look for the Id of lastPoint // since we only start, if we have more than one point in the cell, lastPointId is initiated with 0 Mesh::SelectedLinesIter position = std::find(selectedLines.begin(), selectedLines.end(), lastPointId); if (position != selectedLines.end()) { lineSelected = true; } mitk::Point3D p, projected_p; float vtkp[3]; itk2vtk(thisPoint, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->GetCurrentWorldPlaneGeometry()->Project(p, projected_p); Vector3D diff = p - projected_p; if (diff.GetSquaredNorm() < 4.0) { Point2D pt2d, tmp; renderer->WorldToDisplay(p, pt2d); if (lastPoint == nullptr) { // set the first point in the cell. This point in needed to close the polygon firstOfCell = new Point2D; *firstOfCell = pt2d; lastPoint = new Point2D; *lastPoint = pt2d; lastPointId = *cellIdIt; } else { if (lineSelected) { glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red // a line from lastPoint to thisPoint glBegin(GL_LINES); glVertex2dv(&(*lastPoint)[0]); glVertex2dv(&pt2d[0]); glEnd(); } else // if not selected { glColor3f(unselectedColor[0], unselectedColor[1], unselectedColor[2]); // drawing crosses glBegin(GL_LINES); glVertex2dv(&(*lastPoint)[0]); glVertex2dv(&pt2d[0]); glEnd(); } // to draw the line to the next in iteration step *lastPoint = pt2d; // and to search for the selection state of the line lastPointId = *cellIdIt; } // if..else } // if <4.0 // fill off-plane polygon part 1 if ((!first) && (worldplanegeometry != nullptr)) { line.SetPoints(lastPoint3D, thisPoint); if (worldplanegeometry->IntersectionPointParam(line, t) && ((t >= 0) && (t <= 1))) { intersectionPoints.push_back(line.GetPoint(t)); } } ++cellIdIt; first = false; } // while cellIdIter // closed polygon? if (cellDataIt->Value().closed) { // close the polygon if needed if (firstOfCell != nullptr) { lineSelected = false; Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines; Mesh::SelectedLinesIter position = std::find(selectedLines.begin(), selectedLines.end(), lastPointId); if (position != selectedLines.end()) // found the index { glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red // a line from lastPoint to firstPoint glBegin(GL_LINES); glVertex2dv(&(*lastPoint)[0]); glVertex2dv(&(*firstOfCell)[0]); glEnd(); } else { glColor3f(unselectedColor[0], unselectedColor[1], unselectedColor[2]); glBegin(GL_LINES); glVertex2dv(&(*lastPoint)[0]); glVertex2dv(&(*firstOfCell)[0]); glEnd(); } } } // if closed // Axis-aligned bounding box(AABB) around the cell if selected and set in Property bool showBoundingBox; if (dynamic_cast(this->GetDataNode()->GetProperty("showBoundingBox")) == nullptr) showBoundingBox = false; else showBoundingBox = dynamic_cast(this->GetDataNode()->GetProperty("showBoundingBox"))->GetValue(); if (showBoundingBox) { if (cellDataIt->Value().selected) { mitk::Mesh::DataType::BoundingBoxPointer aABB = input->GetBoundingBoxFromCell(cellIt->Index()); if (aABB.IsNotNull()) { mitk::Mesh::PointType min, max; min = aABB->GetMinimum(); max = aABB->GetMaximum(); // project to the displayed geometry Point2D min2D, max2D; Point3D p, projected_p; float vtkp[3]; itk2vtk(min, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->WorldToDisplay(p, min2D); itk2vtk(max, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp, p); renderer->GetCurrentWorldPlaneGeometry()->Project(p, projected_p); Vector3D diff = p - projected_p; if (diff.GetSquaredNorm() < 4.0) { renderer->WorldToDisplay(p, max2D); // draw the BoundingBox glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red // a line from lastPoint to firstPoint glBegin(GL_LINE_LOOP); glVertex2f(min2D[0], min2D[1]); glVertex2f(min2D[0], max2D[1]); glVertex2f(max2D[0], max2D[1]); glVertex2f(max2D[0], min2D[1]); glEnd(); } // draw bounding-box } // bounding-box exists } // cell selected } // show bounding-box // fill off-plane polygon part 2 if (worldplanegeometry != nullptr) { // consider line from last to first line.SetPoints(thisPoint, firstOfCell3D); if (worldplanegeometry->IntersectionPointParam(line, t) && ((t >= 0) && (t <= 1))) { intersectionPoints.push_back(line.GetPoint(t)); } std::sort(intersectionPoints.begin(), intersectionPoints.end(), point3DSmaller); std::vector::iterator it, end; end = intersectionPoints.end(); if ((intersectionPoints.size() % 2) != 0) { --end; // ensure even number of intersection-points } Point2D pt2d; for (it = intersectionPoints.begin(); it != end; ++it) { glBegin(GL_LINES); renderer->WorldToDisplay(*it, pt2d); glVertex2dv(pt2d.GetDataPointer()); ++it; renderer->WorldToDisplay(*it, pt2d); glVertex2dv(pt2d.GetDataPointer()); glEnd(); } if (it != intersectionPoints.end()) { glBegin(GL_LINES); renderer->WorldToDisplay(*it, pt2d); glVertex2dv(pt2d.GetDataPointer()); glVertex2dv(pt2d.GetDataPointer()); glEnd(); } } // fill off-plane polygon part 2 } // if numOfPointsInCell>1 delete firstOfCell; delete lastPoint; lastPoint = nullptr; firstOfCell = nullptr; lastPointId = 0; ++cellIt; ++cellDataIt; } } } diff --git a/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.h b/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.h index 6daf407f3d..ac83fc8041 100644 --- a/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.h +++ b/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.h @@ -1,284 +1,284 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkContourExtractor2DImageFilter_h #define __itkContourExtractor2DImageFilter_h #include "itkConceptChecking.h" #include "itkImageToPathFilter.h" #include "itkNumericTraits.h" #include "itkPolyLineParametricPath.h" #include "vcl_deque.h" #include "vcl_list.h" #include namespace itk { /** \class ContourExtractor2DImageFilter * \brief Computes a list of PolyLineParametricPath objects from the contours in * a 2D image. * * Uses the "marching squares" method to compute a the iso-valued contours of * the input 2D image for a given intensity value. Multiple outputs may be * produced because an image can have multiple contours at a given level, so it * is advised to call GetNumberOfOutputs() and GetOutput(n) to retrieve all of * the contours. The contour value to be extracted can be set with * SetContourValue(). Image intensities will be linearly interpolated to provide * sub-pixel resolution for the output contours. * * The marching squares algorithm is a special case of the marching cubes * algorithm (Lorensen, William and Harvey E. Cline. Marching Cubes: A High * Resolution 3D Surface Construction Algorithm. Computer Graphics (SIGGRAPH 87 * Proceedings) 21(4) July 1987, p. 163-170). A simple explanation is available * here: http://www.essi.fr/~lingrand/MarchingCubes/algo.html * * There is a single ambiguous case in the marching squares algorithm: if a * given 2x2-pixel square has two high-valued and two low-valued pixels, each * pair diagonally adjacent. (Where high- and low-valued is with respect to the * contour value sought.) In this case, either the high-valued pixels can be * connected into the same "object" (where groups of pixels encircled by a given * contour are considered an object), or the low-valued pixels can be connected. * This is the "face connected" versus "face + vertex connected" (or 4- versus * 4-connected) distinction: high-valued pixels most be treated as one, and * low-valued as the other. By default, high-valued pixels are treated as * "face-connected" and low-valued pixels are treated as "face + vertex" * connected. To reverse this, call VertexConnectHighPixelsOn(); * * Outputs are not guaranteed to be closed paths: contours which intersect the * image edge will be left open. All other paths will be closed. (The * closed-ness of a path can be tested by checking whether the beginning point * is the same as the end point.) * * Produced paths are oriented. Following the path from beginning to end, image * intensity values lower than the contour value are to the left of the path and * intensity values grater than the contour value are to the right. In other * words, the image gradient at a path segment is (approximately) in the direct * of that segment rotated right by 90 degrees, because the image intensity * values increase from left-to-right across the segment. This means that the * generated contours will circle clockwise around "hills" of * above-contour-value intensity, and counter-clockwise around "depressions" of * below-contour-value intensity. This convention can be reversed by calling * ReverseContourOrientationOn(). * * By default the input image's largest possible region will be processed; call * SetRequestedRegion() to process a different region, or ClearRequestedRegion() * to revert to the default value. Note that the requested regions are usually * set on the output; however since paths have no notion of a "region", this * must be set at the filter level. * * This class was contributed to the Insight Journal by Zachary Pincus. * http://insight-journal.org/midas/handle.php?handle=1926/165 * * \sa Image * \sa Path * \sa PolyLineParametricPath * */ template class ITK_EXPORT ContourExtractor2DImageFilter : public ImageToPathFilter> { public: /** Extract dimension from input and output image. */ itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); /** Convenient typedefs for simplifying declarations. */ typedef TInputImage InputImageType; typedef PolyLineParametricPath<2> OutputPathType; /** Standard class typedefs. */ typedef ContourExtractor2DImageFilter Self; typedef ImageToPathFilter Superclass; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(ContourExtractor2DImageFilter, ImageToPathFilter); /** Image and path typedef support. */ typedef typename InputImageType::Pointer InputImagePointer; typedef typename InputImageType::PixelType InputPixelType; typedef typename InputImageType::IndexType InputIndexType; typedef typename InputImageType::OffsetType InputOffsetType; typedef typename InputImageType::RegionType InputRegionType; typedef typename OutputPathType::Pointer OutputPathPointer; typedef typename OutputPathType::VertexType VertexType; typedef typename OutputPathType::VertexListType VertexListType; /** Real type associated to the input pixel type. */ typedef typename NumericTraits::RealType InputRealType; typedef typename VertexListType::ConstPointer VertexListConstPointer; /** Control the orientation of the contours with reference to the image * gradient. (See class documentation.) */ itkSetMacro(ReverseContourOrientation, bool); itkGetConstReferenceMacro(ReverseContourOrientation, bool); itkBooleanMacro(ReverseContourOrientation); /** Control whether high- or low-valued pixels are vertex-connected. * Default is for low-valued pixels to be vertex-connected. * (See class documentation.) */ itkSetMacro(VertexConnectHighPixels, bool); itkGetConstReferenceMacro(VertexConnectHighPixels, bool); itkBooleanMacro(VertexConnectHighPixels); /** Control whether the largest possible input region is used, or if a * custom requested region is to be used. */ void SetRequestedRegion(const InputRegionType region); itkGetConstReferenceMacro(RequestedRegion, InputRegionType); void ClearRequestedRegion(); /** Set/Get the image intensity value that the contours should follow. * This is the equivalent of an iso-value in Marching Squares. */ itkSetMacro(ContourValue, InputRealType); itkGetConstReferenceMacro(ContourValue, InputRealType); #ifdef ITK_USE_CONCEPT_CHECKING /** Begin concept checking */ itkConceptMacro(DimensionShouldBe2, (Concept::SameDimension)); itkConceptMacro(InputPixelTypeComparable, (Concept::Comparable)); itkConceptMacro(InputHasPixelTraitsCheck, (Concept::HasPixelTraits)); itkConceptMacro(InputHasNumericTraitsCheck, (Concept::HasNumericTraits)); /** End concept checking */ #endif protected: ContourExtractor2DImageFilter(); virtual ~ContourExtractor2DImageFilter(); void PrintSelf(std::ostream &os, Indent indent) const; void GenerateData(); /** ContourExtractor2DImageFilter manually controls the input requested * region via SetRequestedRegion and ClearRequestedRegion, so it must * override the superclass method. */ - virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError); + virtual void GenerateInputRequestedRegion(); private: VertexType InterpolateContourPosition(InputPixelType fromValue, InputPixelType toValue, InputIndexType fromIndex, InputOffsetType toOffset); void AddSegment(const VertexType from, const VertexType to); void FillOutputs(); ContourExtractor2DImageFilter(const Self &); // purposely not implemented void operator=(const Self &); // purposely not implemented InputRealType m_ContourValue; bool m_ReverseContourOrientation; bool m_VertexConnectHighPixels; bool m_UseCustomRegion; InputRegionType m_RequestedRegion; unsigned int m_NumberOfContoursCreated; // Represent each contour as deque of vertices to facilitate addition of // nodes at beginning or end. At the end of the processing, we will copy // the contour into a PolyLineParametricPath. // We subclass the deque to store an additional bit of information: an // identification number for each growing contour. We use this number so // that when it becomes necessary to merge two growing contours, we can // merge the newer one into the older one. This helps because then we can // guarantee that the output contour list is ordered from left to right, // top to bottom (in terms of the first pixel of the contour encountered // by the marching squares). Currently we make no guarantees that this // pixel is the first pixel in the contour list, just that the contours // are so ordered in the output. Ensuring this latter condition (first // pixel traversed = first pixel in contour) would be possible by either // changing the merging rules, which would make the contouring operation // slower, or by storing additional data as to which pixel was first. class ContourType : public vcl_deque { public: unsigned int m_ContourNumber; }; // Store all the growing contours in a list. We may need to delete contours // from anywhere in the sequence (when we merge them together), so we need to // use a list instead of a vector or similar. typedef vcl_list ContourContainer; typedef typename ContourContainer::iterator ContourRef; // declare the hash function we are using for the hash_map. struct VertexHash { typedef typename VertexType::CoordRepType CoordinateType; inline size_t operator()(const VertexType &k) const { // Xor the hashes of the vertices together, after multiplying the // first by some number, so that identical (x,y) vertex indices // don't all hash to the same bucket. This is a decent if not // optimal hash. const size_t hashVertex1 = this->float_hash(k[0] * 0xbeef); const size_t hashVertex2 = this->float_hash(k[1]); const size_t hashValue = hashVertex1 ^ hashVertex2; return hashValue; } // Define hash function for floats. Based on method from // http://www.brpreiss.com/books/opus4/html/page217.html inline size_t float_hash(const CoordinateType &k) const { if (k == 0) { return 0; } int exponent; CoordinateType mantissa = vcl_frexp(k, &exponent); size_t value = static_cast(vcl_fabs(mantissa)); value = (2 * value - 1) * ~0U; return value; } }; // We use a hash to associate the endpoints of each contour with the // contour itself. This makes it easy to look up which contour we should add // a new arc to. // We can't store the contours themselves in the hashtable because we // need to have two tables (one to hash from beginpoint -> contour and one // for endpoint -> contour), and sometimes will remove a contour from the // tables (if it has been closed or merged with another contour). So in the // hash table we store a reference to the contour. Because sometimes we will // need to merge contours, we need to be able to quickly remove contours // from our list when they have been merged into another. Thus, we store // an iterator pointing to the contour in the list. typedef itksys::hash_map VertexToContourMap; typedef typename VertexToContourMap::iterator VertexMapIterator; typedef typename VertexToContourMap::value_type VertexContourRefPair; // The contours we find in the image are stored here ContourContainer m_Contours; // And indexed by their beginning and ending points here VertexToContourMap m_ContourStarts; VertexToContourMap m_ContourEnds; }; } // end namespace itk #ifndef ITK_MANUAL_INSTANTIATION #include "itkContourExtractor2DImageFilter.txx" #endif #endif diff --git a/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.txx b/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.txx index fb2b9ccd14..1ca4de4ba8 100644 --- a/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.txx +++ b/Modules/Segmentation/Algorithms/itkContourExtractor2DImageFilter.txx @@ -1,540 +1,540 @@ /*=================================================================== 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. ===================================================================*/ /*=================================================================== This file is based heavily on a corresponding ITK filter. ===================================================================*/ #ifndef __itkContourExtractor2DImageFilter_txx #define __itkContourExtractor2DImageFilter_txx #include "itkConstShapedNeighborhoodIterator.h" #include "itkConstShapedNeighborhoodIterator.h" #include "itkContourExtractor2DImageFilter.h" #include "itkProgressReporter.h" #include "vcl_cmath.h" namespace itk { // Constructor template ContourExtractor2DImageFilter::ContourExtractor2DImageFilter() { this->m_ContourValue = NumericTraits::Zero; this->m_ReverseContourOrientation = false; this->m_VertexConnectHighPixels = false; this->m_UseCustomRegion = false; this->m_NumberOfContoursCreated = 0; } // Destructor template ContourExtractor2DImageFilter::~ContourExtractor2DImageFilter() { } template void ContourExtractor2DImageFilter::GenerateData() { // Make sure the structures for containing, looking up, and numbering the // growing contours are empty and ready. m_Contours.clear(); m_ContourStarts.clear(); m_ContourEnds.clear(); m_NumberOfContoursCreated = 0; // Set up an iterator to "march the squares" across the image. // We associate each 2px-by-2px square with the pixel in the upper left of // that square. We then iterate across the image, examining these 2x2 squares // and building the contour. By iterating the upper-left pixel of our // "current square" across every pixel in the image except those on the // bottom row and rightmost column, we have visited every valid square in the // image. InputRegionType region = this->GetInput()->GetRequestedRegion(); typename InputRegionType::SizeType shrunkSize = region.GetSize(); shrunkSize[0] -= 1; shrunkSize[1] -= 1; InputRegionType shrunkRegion(region.GetIndex(), shrunkSize); // Set up a progress reporter ProgressReporter progress(this, 0, shrunkRegion.GetNumberOfPixels()); // A 1-pixel radius sets up a neighborhood with the following indices: // 0 1 2 // 3 4 5 // 6 7 8 // We are interested only in the square of 4,5,7,8 which is the 2x2 square // with the center pixel at the top-left. So we only activate the // coresponding offsets, and only query pixels 4, 5, 7, and 8 with the // iterator's GetPixel method. typedef ConstShapedNeighborhoodIterator SquareIterator; typename SquareIterator::RadiusType radius = {{1, 1}}; SquareIterator it(radius, this->GetInput(), shrunkRegion); InputOffsetType none = {{0, 0}}; InputOffsetType right = {{1, 0}}; InputOffsetType down = {{0, 1}}; InputOffsetType diag = {{1, 1}}; it.ActivateOffset(none); it.ActivateOffset(right); it.ActivateOffset(down); it.ActivateOffset(diag); for (it.GoToBegin(); !it.IsAtEnd(); ++it) { // There are sixteen different possible square types, diagramed below. // A + indicates that the vertex is above the contour value, and a - // indicates that the vertex is below or equal to the contour value. // The vertices of each square are here numbered: // 01 // 23 // and treated as a binary value with the bits in that order. Thus each // square can be so numbered: // 0-- 1+- 2-+ 3++ 4-- 5+- 6-+ 7++ // -- -- -- -- +- +- +- +- // // 8-- 9+- 10-+ 11++ 12-- 13+- 14-+ 15++ // -+ -+ -+ -+ ++ ++ ++ ++ // // The position of the line segment that cuts through (or doesn't, in case // 0 and 15) each square is clear, except in cases 6 and 9. In this case, // where the segments are placed is determined by // m_VertexConnectHighPixels. If m_VertexConnectHighPixels is false, then // lines like are drawn through square 6, and lines like are drawn through // square 9. Otherwise, the situation is reversed. // Finally, recall that we draw the lines so that (moving from tail to // head) the lower-valued pixels are on the left of the line. So, for // example, case 1 entails a line slanting from the middle of the top of // the square to the middle of the left side of the square. // (1) Determine what number square we are currently inspecting. Remember // that as far as the neighborhood iterator is concerned, our square // 01 is numbered as 45 // 23 78 InputPixelType v0, v1, v2, v3; v0 = it.GetPixel(4); v1 = it.GetPixel(5); v2 = it.GetPixel(7); v3 = it.GetPixel(8); InputIndexType index = it.GetIndex(); unsigned char squareCase = 0; if (v0 > m_ContourValue) squareCase += 1; if (v1 > m_ContourValue) squareCase += 2; if (v2 > m_ContourValue) squareCase += 4; if (v3 > m_ContourValue) squareCase += 8; // Set up macros to find the ContinuousIndex where the contour intersects // one of the sides of the square. Normally macros should, of course, be // eschewed, but since this is an inner loop not calling the function four // times when two would do is probably worth while. Plus, copy-pasting // these into the switch below is even worse. InterpolateContourPosition // takes the values at two vertices, the index of the first vertex, and the // offset between the two vertices. #define TOP_ this->InterpolateContourPosition(v0, v1, index, right) #define BOTTOM_ this->InterpolateContourPosition(v2, v3, index + down, right) #define LEFT_ this->InterpolateContourPosition(v0, v2, index, down) #define RIGHT_ this->InterpolateContourPosition(v1, v3, index + right, down) // (2) Add line segments to the growing contours as defined by the cases. // AddSegment takes a "from" vertex and a "to" vertex, and adds it to the // a growing contour, creates a new contour, or merges two together. switch (squareCase) { case 0: // no line break; case 1: // top to left this->AddSegment(TOP_, LEFT_); break; case 2: // right to top this->AddSegment(RIGHT_, TOP_); break; case 3: // right to left this->AddSegment(RIGHT_, LEFT_); break; case 4: // left to bottom this->AddSegment(LEFT_, BOTTOM_); break; case 5: // top to bottom this->AddSegment(TOP_, BOTTOM_); break; case 6: if (m_VertexConnectHighPixels) { // left to top this->AddSegment(LEFT_, TOP_); // right to bottom this->AddSegment(RIGHT_, BOTTOM_); } else { // right to top this->AddSegment(RIGHT_, TOP_); // left to bottom this->AddSegment(LEFT_, BOTTOM_); } break; case 7: // right to bottom this->AddSegment(RIGHT_, BOTTOM_); break; case 8: // bottom to right this->AddSegment(BOTTOM_, RIGHT_); break; case 9: if (m_VertexConnectHighPixels) { // top to right this->AddSegment(TOP_, RIGHT_); // bottom to left this->AddSegment(BOTTOM_, LEFT_); } else { // top to left this->AddSegment(TOP_, LEFT_); // bottom to right this->AddSegment(BOTTOM_, RIGHT_); } break; case 10: // bottom to top this->AddSegment(BOTTOM_, TOP_); break; case 11: // bottom to left this->AddSegment(BOTTOM_, LEFT_); break; case 12: // left to right this->AddSegment(LEFT_, RIGHT_); break; case 13: // top to right this->AddSegment(TOP_, RIGHT_); break; case 14: // left to top this->AddSegment(LEFT_, TOP_); break; case 15: // no line break; } // switch squareCase progress.CompletedPixel(); } // iteration // Now create the outputs paths from the deques we've been using. this->FillOutputs(); m_Contours.clear(); m_ContourStarts.clear(); m_ContourEnds.clear(); m_NumberOfContoursCreated = 0; } template inline typename ContourExtractor2DImageFilter::VertexType ContourExtractor2DImageFilter::InterpolateContourPosition(InputPixelType fromValue, InputPixelType toValue, InputIndexType fromIndex, InputOffsetType toOffset) { VertexType output; // Now calculate the fraction of the way from 'from' to 'to' that the contour // crosses. Interpolate linearly: y = v0 + (v1 - v0) * x, and solve for the // x that gives y = m_ContourValue: x = (m_ContourValue - v0) / (v1 - v0). // This assumes that v0 and v1 are separated by exactly ONE unit. So the to // Offset. value must have exactly one component 1 and the other component 0. // Also this assumes that fromValue and toValue are different. Otherwise we // can't interpolate anything! itkAssertOrThrowMacro((fromValue != toValue), "source and destination are the same"); itkAssertOrThrowMacro(((toOffset[0] == 0 && toOffset[1] == 1) || (toOffset[0] == 1 && toOffset[1] == 0)), "toOffset has unexpected values"); double x = (m_ContourValue - static_cast(fromValue)) / (toValue - static_cast(fromValue)); output[0] = fromIndex[0] + x * toOffset[0]; output[1] = fromIndex[1] + x * toOffset[1]; return output; } template void ContourExtractor2DImageFilter::AddSegment(VertexType from, VertexType to) { if (from == to) { // Arc is degenerate: ignore, and the from/two point will be connected // later by other squares. Degeneracy happens when (and only when) a square // has exactly one vertex that is the contour value, and the rest are above // that value. return; } // Try to find an existing contour that starts where the new segment ends. VertexMapIterator newTail = m_ContourStarts.find(to); // Try to find an existing contour that ends where the new segment starts. VertexMapIterator newHead = m_ContourEnds.find(from); if (newTail != m_ContourStarts.end() && newHead != m_ContourEnds.end()) { // We need to connect these two contours. The act of connecting them will // add the needed arc. auto tail = newTail->second; itkAssertOrThrowMacro((tail->front() == to), "End doesn't match Beginning"); auto head = newHead->second; itkAssertOrThrowMacro((head->back() == from), "Beginning doesn't match End"); if (head == tail) { // We've closed a contour. Add the end point, and remove from the maps head->push_back(to); m_ContourStarts.erase(newTail); // erase the front of tail. Because head and tail are the same contour, // don't worry about erasing the front of head! m_ContourEnds.erase(newHead); // erase the end of head/tail. } else { // We have found two distinct contours that need to be joined. Careful // here: we want to keep the first segment in the list when merging so // that contours are always returned in top-to-bottom, right-to-left // order (with regard to the image pixel found to be inside the contour). if (tail->m_ContourNumber > head->m_ContourNumber) { // if tail was created later than head... // Copy tail to the end of head and remove // tail from everything. head->insert(head->end(), tail->begin(), tail->end()); // Now remove 'tail' from the list and the maps because it has been // subsumed. m_ContourStarts.erase(newTail); int erased = m_ContourEnds.erase(tail->back()); // There should be exactly one entry in the hash for that endpoint if (erased != 1) { itkWarningMacro(<< "There should be exactly one entry in the hash for that endpoint, but there are " << erased); } m_Contours.erase(tail); // remove from the master list // Now remove the old end of 'head' from the ends map and add // the new end. m_ContourEnds.erase(newHead); m_ContourEnds.insert(VertexContourRefPair(head->back(), head)); } else { // Copy head to the beginning of tail and remove // head from everything. tail->insert(tail->begin(), head->begin(), head->end()); // Now remove 'head' from the list and the maps because // it has been subsumed. m_ContourEnds.erase(newHead); int erased = m_ContourStarts.erase(head->front()); if (erased != 1) { itkWarningMacro(<< "There should be exactly one entry in the hash for that endpoint, but there are " << erased); } m_Contours.erase(head); // remove from the master list // Now remove the old start of 'tail' from the starts map and // add the new start. m_ContourStarts.erase(newTail); m_ContourStarts.insert(VertexContourRefPair(tail->front(), tail)); } } } else if (newTail == m_ContourStarts.end() && newHead == m_ContourEnds.end()) { // No contours found: add a new one. // Make it on the heap. It will be copied into m_Contours. ContourType contour; // Add the endpoints contour.push_front(from); contour.push_back(to); contour.m_ContourNumber = m_NumberOfContoursCreated++; // Add the contour to the end of the list and get a reference to it. m_Contours.push_back(contour); // recall that end() is an iterator to one past the back! auto newContour = --m_Contours.end(); // add the endpoints and an iterator pointing to the contour // in the list to the maps. m_ContourStarts.insert(VertexContourRefPair(from, newContour)); m_ContourEnds.insert(VertexContourRefPair(to, newContour)); } else if (newTail != m_ContourStarts.end() && newHead == m_ContourEnds.end()) { // Found a single contour to which the new arc should be prepended. auto tail = newTail->second; itkAssertOrThrowMacro((tail->front() == to), "End doesn't match Beginning"); tail->push_front(from); // erase the old start of this contour m_ContourStarts.erase(newTail); // Now add the new start of this contour. m_ContourStarts.insert(VertexContourRefPair(from, tail)); } else if (newTail == m_ContourStarts.end() && newHead != m_ContourEnds.end()) { // Found a single contour to which the new arc should be appended. auto head = newHead->second; itkAssertOrThrowMacro((head->back() == from), "Beginning doesn't match End"); head->push_back(to); // erase the old end of this contour m_ContourEnds.erase(newHead); // Now add the new start of this contour. m_ContourEnds.insert(VertexContourRefPair(to, head)); } } template void ContourExtractor2DImageFilter::FillOutputs() { this->SetNumberOfIndexedOutputs(m_Contours.size()); int i = 0; for (auto it = m_Contours.begin(); it != m_Contours.end(); it++, i++) { OutputPathPointer output = this->GetOutput(i); if (output.IsNull()) { // Static cast is OK because we know PathSource will make its templated // class type output = static_cast(this->MakeOutput(i).GetPointer()); this->SetNthOutput(i, output.GetPointer()); } typename VertexListType::Pointer path = const_cast(output->GetVertexList()); path->Initialize(); path->reserve(it->size()); // use std::vector version of 'reserve()' // instead of VectorContainer::Reserve() to work around // the fact that the latter is essentially std::vector::resize(), // which is not what we want. // Now put all the points from the contour deque into the path and // mark output as modified typedef typename ContourType::const_iterator ConstIteratorType; if (m_ReverseContourOrientation) { ConstIteratorType itC = (*it).end(); do { itC--; path->push_back(*itC); } while (itC != (*it).begin()); } else { ConstIteratorType itC = (*it).begin(); while (itC != (*it).end()) { path->push_back(*itC); itC++; } } output->Modified(); } } template void ContourExtractor2DImageFilter::SetRequestedRegion(const InputRegionType region) { itkDebugMacro("setting RequestedRegion to " << region); m_UseCustomRegion = true; if (this->m_RequestedRegion != region) { this->m_RequestedRegion = region; this->Modified(); } } template void ContourExtractor2DImageFilter::ClearRequestedRegion() { itkDebugMacro("Clearing RequestedRegion."); if (this->m_UseCustomRegion == true) { this->m_UseCustomRegion = false; this->Modified(); } } template - void ContourExtractor2DImageFilter::GenerateInputRequestedRegion() throw(InvalidRequestedRegionError) + void ContourExtractor2DImageFilter::GenerateInputRequestedRegion() { InputImageType *input = const_cast(this->GetInput()); if (!input) return; if (m_UseCustomRegion) { InputRegionType requestedRegion = m_RequestedRegion; if (requestedRegion.Crop(input->GetLargestPossibleRegion())) { input->SetRequestedRegion(requestedRegion); return; } else { // Couldn't crop the region (requested region is outside the largest // possible region). Throw an exception. // store what we tried to request (prior to trying to crop) input->SetRequestedRegion(requestedRegion); // build an exception InvalidRequestedRegionError e(__FILE__, __LINE__); e.SetLocation(ITK_LOCATION); e.SetDescription("Requested region is outside the largest possible region."); e.SetDataObject(input); throw e; } } else { input->SetRequestedRegion(input->GetLargestPossibleRegion()); } } /** * Standard "PrintSelf" method */ template void ContourExtractor2DImageFilter::PrintSelf(std::ostream &os, Indent indent) const { Superclass::PrintSelf(os, indent); os << indent << "ReverseContourOrientation: " << m_ReverseContourOrientation << std::endl; os << indent << "VertexConnectHighPixels: " << m_VertexConnectHighPixels << std::endl; os << indent << "UseCustomRegion: " << m_UseCustomRegion << std::endl; os << indent << "NumericTraits: " << m_UseCustomRegion << std::endl; os << indent << "NumberOfContoursCreated: " << m_NumberOfContoursCreated << std::endl; if (m_UseCustomRegion) { os << indent << "Custom region: " << m_RequestedRegion << std::endl; } typedef typename NumericTraits::PrintType InputRealPrintType; os << indent << "Contour value: " << static_cast(m_ContourValue) << std::endl; } } // end namespace itk #endif diff --git a/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.cpp b/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.cpp index 2d345754fd..09e38483fd 100644 --- a/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.cpp +++ b/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.cpp @@ -1,449 +1,449 @@ /*=================================================================== BlueBerry Platform Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define NOMINMAX #include "berryInternalJob.h" #include #include "berryJob.h" #include "berryJobManager.h" #include "berryJobExceptions.h" #include #include namespace berry { InternalJob::InternalJob(const QString& name) : jobNumber(nextJobNumber++) , flags(Job::NONE) , name(name) , next(nullptr) , previous(nullptr) , priority(Job::LONG) , sptr_schedulingRule(nullptr) , sptr_monitor(nullptr) , m_startTime() , waitQueueStamp(T_NONE) , ptr_thread(nullptr) { jobEvents.SetExceptionHandler(MessageExceptionHandler(&ptr_manager->m_JobListeners, &JobListeners::HandleException)); } JobManager* const InternalJob::ptr_manager = JobManager::GetInstance(); // time_variables definitions // implemented as TimeDiff, if needed can be used to create a Poco::Timestamp with the given value const Poco::Timestamp::TimeDiff InternalJob::T_INFINITE = std::numeric_limits::max(); // indicates if a job has a scheduling time // implemented as TimeDiff, if needed can be used to create a Poco::Timestamp with the given value const Poco::Timestamp::TimeDiff InternalJob::T_NONE = -1; void InternalJob::AddLast(InternalJob::Pointer entry) { InternalJob::Pointer last; last = this; //find the end of the queue while (last->previous) last = last->previous; //add the new entry to the end of the queue last->previous = entry.GetPointer(); entry->next = last; entry->previous = nullptr; } bool InternalJob::operator==(const Object* otherJob) const { if (const InternalJob* temp = dynamic_cast(otherJob)) { return temp->m_startTime >= m_startTime; } else return false; } const IJobChangeListener::Events& InternalJob::GetListeners() const { return jobEvents; } IProgressMonitor::Pointer InternalJob::GetProgressMonitor() const { return sptr_monitor; } Poco::Timestamp InternalJob::GetStartTime() const { return m_startTime; } int InternalJob::InternalGetState() const { return flags & M_STATE; } void InternalJob::InternalSetPriority(int newPriority) { this->priority = newPriority; } void InternalJob::InternalSetRule(ISchedulingRule::Pointer rule) { sptr_schedulingRule = rule; } //TODO InternalSetState void InternalJob::InternalSetState(int i) { flags = (flags & ~M_STATE) | i; } bool InternalJob::IsAboutToRunCanceled() const { return (flags & M_ABOUT_TO_RUN_CANCELED) != 0; } bool InternalJob::IsRunCanceled() const { return (flags & M_RUN_CANCELED) != 0; } bool InternalJob::IsConflicting(InternalJob::Pointer otherJob) const { ISchedulingRule::Pointer otherRule = otherJob->GetRule(); if (sptr_schedulingRule.GetPointer() == nullptr || otherRule.GetPointer() == nullptr) return false; // TODO MultiRule: extend the IsConflicting (...) method with MultiRule // if one of the rules is a compound rule, it must be asked the question. //if (schedulingRule.GetClass() == MultiRule.class) // return schedulingRule.IsConflicting(otherRule); return otherRule->IsConflicting(sptr_schedulingRule); } InternalJob::Pointer InternalJob::Next() const { return next; } InternalJob::Pointer InternalJob::Previous() const { return InternalJob::Pointer(previous); } InternalJob::Pointer InternalJob::Remove() { if (next != 0) next->SetPrevious(InternalJob::Pointer(previous)); if (previous != nullptr) previous->SetNext(next); next = previous = nullptr; return InternalJob::Pointer(this); } -void InternalJob::SetAboutToRunCanceled(bool value) throw (JobRuntimeException) +void InternalJob::SetAboutToRunCanceled(bool value) { flags = value ? flags | M_ABOUT_TO_RUN_CANCELED : flags & ~M_ABOUT_TO_RUN_CANCELED; } void InternalJob::SetRunCanceled(bool value) { flags = value ? flags | M_RUN_CANCELED : flags & ~M_RUN_CANCELED; } void InternalJob::SetNext(InternalJob::Pointer entry) { this->next = entry; } void InternalJob::SetPrevious(InternalJob::Pointer entry) { this->previous = entry.GetPointer(); } void InternalJob::SetProgressMonitor(IProgressMonitor::Pointer monitor) { sptr_monitor = monitor; } void InternalJob::SetResult(IStatus::Pointer result) { m_result = result; } void InternalJob::SetStartTime(Poco::Timestamp::TimeDiff time) { m_startTime = m_startTime + time; } void InternalJob::SetStartTime(const Poco::Timestamp& newtime) { m_startTime = newtime; } QString InternalJob::ToString() const { return GetName() + "(" + QString::number(jobNumber) + ")"; } void InternalJob::SetWaitQueueStamp(Poco::Timestamp waitQueueStamp) { this->waitQueueStamp = waitQueueStamp; } Poco::Timestamp InternalJob::GetWaitQueueStamp() { return waitQueueStamp; } int InternalJob::nextJobNumber = 0; void InternalJob::AddJobChangeListener(IJobChangeListener* listener) { jobEvents.AddListener(listener); } bool InternalJob::BelongsTo(Object::Pointer /*family*/) { return false; } bool InternalJob::Cancel() { return ptr_manager->Cancel(InternalJob::Pointer(this)); } void InternalJob::Canceling() { //default implementation does nothing } void InternalJob::Done(IStatus::Pointer endResult) { ptr_manager->EndJob(InternalJob::Pointer(this),endResult, true); } QString InternalJob::GetName() const { return name; } int InternalJob::GetPriority() const { return priority; } //TODO QualifiedName GetProperty //Object::Pointer //InternalJob //::GetProperty(QualifiedName key) { // // thread safety: (Concurrency001 - copy on write) // std::map temp (properties); // if (temp.empty()) return Object::Pointer(0); // else return temp[key]; // } IStatus::Pointer InternalJob::GetResult() const { return m_result; } ISchedulingRule::Pointer InternalJob::GetRule() const { return sptr_schedulingRule; } int InternalJob::GetState() const { int state = flags & M_STATE; switch (state) { //blocked state is equivalent to waiting state for clients case BLOCKED: return Job::WAITING; case ABOUT_TO_RUN: return Job::RUNNING; case ABOUT_TO_SCHEDULE: return Job::WAITING; default: return state; } } Poco::Thread* InternalJob::GetThread() const { return ptr_thread; } bool InternalJob::IsSystem() const { return (flags & M_SYSTEM) != 0; } bool InternalJob::IsBlocking() { return ptr_manager->IsBlocking(InternalJob::Pointer(this)); } bool InternalJob::IsUser() const { return (flags & M_USER) != 0; } //void //InternalJob //::Join() throws InterruptedException { // manager.join(this); // } void InternalJob::RemoveJobChangeListener(IJobChangeListener* listener) { jobEvents.RemoveListener(listener); } void InternalJob::Schedule(Poco::Timestamp::TimeDiff delay) { if (ShouldSchedule()) ptr_manager->Schedule(InternalJob::Pointer(this), delay, false); } void InternalJob::SetName(const QString& name) { Q_ASSERT(!name.isEmpty()); this->name = name; } void InternalJob::SetPriority(int newPriority) { switch (newPriority) { case Job::INTERACTIVE: case Job::SHORT: case Job::LONG: case Job::BUILD: case Job::DECORATE: ptr_manager->SetPriority(InternalJob::Pointer(this), newPriority); break; default: throw IllegalArgumentException(newPriority); } } void InternalJob::SetProgressGroup(IProgressMonitor::Pointer group, int ticks) { assert(group.GetPointer() != nullptr); InternalJob::Pointer sptr_temp(this); IProgressMonitor::Pointer sptr_pm = ptr_manager->CreateMonitor(sptr_temp, group, ticks); if (sptr_pm != 0) SetProgressMonitor(sptr_pm); } //TODO QualifiedName SetProperty //void //InternalJob //::SetProperty(QualifiedName key, Object value) { // // thread safety: (Concurrency001 - copy on write) // if (value == nullptr) { // if (properties == nullptr) // return; // ObjectMap temp = (ObjectMap) properties.Clone(); // temp.Remove(key); // if (temp.isEmpty()) // properties = nullptr; // else // properties = temp; // } else { // ObjectMap temp = properties; // if (temp == nullptr) // temp = new ObjectMap(5); // else // temp = (ObjectMap) properties.Clone(); // temp.Put(key, value); // properties = temp; // } // } void InternalJob::SetRule(ISchedulingRule::Pointer rule) { ptr_manager->SetRule(InternalJob::Pointer(this), rule); } void InternalJob::SetSystem(bool value) { //TODO Error Exception Problem IllegalStateException //if (GetState() != Job.NONE) //throw IllegalStateException(); flags = value ? flags | M_SYSTEM : flags & ~M_SYSTEM; } void InternalJob::SetThread(Poco::Thread* thread) { ptr_thread = thread; } void InternalJob::SetUser(bool value) { //TODO Error Exception Problem IllegalStateException if (GetState() != Job::NONE) throw IllegalStateException(); flags = value ? flags | M_USER : flags & ~M_USER; } bool InternalJob::ShouldSchedule() { return true; } bool InternalJob::Sleep() { return ptr_manager->Sleep(InternalJob::Pointer(this)); } void InternalJob::WakeUp(long delay) { ptr_manager->WakeUp(InternalJob::Pointer(this), delay); } } diff --git a/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.h b/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.h index 08782e2d07..ac4268f023 100644 --- a/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.h +++ b/Plugins/org.blueberry.core.jobs/src/internal/berryInternalJob.h @@ -1,467 +1,467 @@ /*=================================================================== BlueBerry Platform 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 BERRY_INTERNALJOB_H #define BERRY_INTERNALJOB_H #include #include #include #include #include "berryJobExceptions.h" #include "berryISchedulingRule.h" #include "berryIProgressMonitor.h" #include "berryIJobChangeListener.h" #include #include #include #include #include #include namespace berry { struct JobManager; /** * Internal implementation class for jobs. Clients must not implement this class * directly. All jobs must be subclasses of the API org.blueberry_core_jobs.Job class. */ // struct BERRY_JOBS InternalJob: public Object, public Comparable struct BERRY_JOBS InternalJob : public Object { friend struct JobQueue; friend struct JobManager; berryObjectMacro(InternalJob); bool operator==(const Object* otherJob) const override; /** * Adds an entry at the end of the list of which this item is the head. */ void AddLast(InternalJob::Pointer entry); /* * Returns the job listeners that are only listening to this job. */ const IJobChangeListener::Events& GetListeners() const; /** * Returns the job's progress monitor, or null if it is not running. */ IProgressMonitor::Pointer GetProgressMonitor() const; /** * Returns the time that this job should be started, awakened, or * rescheduled, depending on the current state. * @return time in milliseconds */ Poco::Timestamp GetStartTime() const; /** * Returns the raw job state, including internal states no exposed as API. */ int InternalGetState() const; /* * @see Job#GetState() */ int GetState() const; /** * @see Job#GetName() */ QString GetName() const; /* * @see Job#setRule(ISchedulingRule::Pointer) */ void InternalSetRule(ISchedulingRule::Pointer rule); /** * Must be called from JobManager#setPriority */ void InternalSetPriority(int newPriority); /** * Must be called from JobManager#ChangeState */ void InternalSetState(int i); /** * Returns whether this job was canceled when it was about to run */ bool IsAboutToRunCanceled() const; /** * Returns whether this job was canceled when it was running. */ bool IsRunCanceled() const ; /** * Returns true if this job conflicts with the given job, and false otherwise. */ bool IsConflicting(InternalJob::Pointer otherJob) const; /** * Returns the next entry (ahead of this one) in the list, or null if there is no next entry */ InternalJob::Pointer Next() const; /** * Returns the previous entry (behind this one) in the list, or null if there is no previous entry */ InternalJob::Pointer Previous() const; /** * Removes this entry from any list it belongs to. Returns the receiver. */ InternalJob::Pointer Remove(); /* * @see Job#run(IProgressMonitor) */ virtual IStatus::Pointer Run(IProgressMonitor::Pointer myProgressMonitor) = 0 ; /** * Sets whether this job was canceled when it was about to run */ - void SetAboutToRunCanceled(bool value) throw (JobRuntimeException); + void SetAboutToRunCanceled(bool value); /** * Sets the next entry in this linked list of jobs. * @param entry */ /** * Sets whether this job was canceled when it was running */ void SetRunCanceled(bool value) ; void SetNext(InternalJob::Pointer entry); /** * Sets the previous entry in this linked list of jobs. * @param entry */ void SetPrevious(InternalJob::Pointer entry); /** * Sets the progress monitor to use for the next execution of this job, * or for clearing the monitor when a job completes. * @param monitor a progress monitor */ void SetProgressMonitor(IProgressMonitor::Pointer monitor); /** * Sets or clears the result of an execution of this job. * @param result a result status, or null */ void SetResult(IStatus::Pointer result) ; /** * Sets a time to start, wake up, or schedule this job, * depending on the current state * @param time a time in milliseconds */ void SetStartTime(Poco::Timestamp::TimeDiff time); void SetStartTime(const Poco::Timestamp& newtime); /* * @see Job.SetThread */ void SetThread(Poco::Thread* thread); /* * @see Job.GetThread */ Poco::Thread* GetThread() const; /* * Prints a string-based representation of this job instance. * For debugging purposes only. */ QString ToString() const override; /** * @param waitQueueStamp The waitQueueStamp to set. */ void SetWaitQueueStamp(Poco::Timestamp waitQueueStamp); /** * @return Returns the waitQueueStamp. */ Poco::Timestamp GetWaitQueueStamp(); protected: InternalJob(const QString& name); /* * @see Job#AddJobListener(IJobChangeListener*) */ void AddJobChangeListener(IJobChangeListener* listener); /* * @see Job#BelongsTo(Object) */ virtual bool BelongsTo(Object::Pointer family); /* * @see Job#Cancel() */ bool Cancel(); /* * @see Job#Canceling() */ virtual void Canceling(); /* * * @see Job#Done(IStatus:.Pointer) */ void Done(IStatus::Pointer endResult); /* * @see Job#GetPriority() */ int GetPriority() const; /* * @see Job#GetProperty */ /// Object GetProperty(QualifiedName key) ; /* * @see Job#GetResult */ IStatus::Pointer GetResult() const ; /* * @see Job#GetRule */ ISchedulingRule::Pointer GetRule() const; /* * @see Job.IsSystem() */ bool IsSystem() const; /* * @see Job.IsUser() */ bool IsUser() const; /* * @see Job#Join() */ /// void Join() throws InterruptedException ; /* * @see Job#RemoveJobListener(IJobChangeListener) */ void RemoveJobChangeListener(IJobChangeListener* listener); /* * @see Job#Schedule(long) */ void Schedule(Poco::Timestamp::TimeDiff delay); /* * @see Job#SetName(std::string) */ void SetName(const QString& name); /* * @see Job#SetPriority(int) */ void SetPriority(int newPriority); /* * @see Job#SetProgressGroup(IProgressMonitor::Pointer, int ticks) */ void SetProgressGroup(IProgressMonitor::Pointer group, int ticks); /* * @see Job#SetProperty(QualifiedName,Object) */ /// void SetProperty(QualifiedName key, Object value) ; /* internalSetRule * @see Job#SetRule(ISchedulingRule::Pointer) */ void SetRule(ISchedulingRule::Pointer rule); /* * @see Job.SetSystem */ void SetSystem(bool value); /* * @see Job.SetUser */ void SetUser(bool value); /* * @see Job#ShouldSchedule */ virtual bool ShouldSchedule(); /* * @see Job#Sleep() */ bool Sleep(); /* * @see Job#WakeUp(long) */ void WakeUp(long delay); public: /** * Flag on a job indicating that it was canceled when running. This flag * is used to ensure that #canceling is only ever called once on a job in * case of recursive cancellation attempts. */ static const int M_RUN_CANCELED = 0x0800; /** * Job state code (value 16) indicating that a job has been removed from * the wait queue and is about to start running. From an API point of view, * this is the same as RUNNING. */ static const int ABOUT_TO_RUN = 0x10; /** * Job state code (value 32) indicating that a job has passed scheduling * precondition checks and is about to be added to the wait queue. From an API point of view, * this is the same as WAITING. */ static const int ABOUT_TO_SCHEDULE = 0x20; /** * Job state code (value 8) indicating that a job is blocked by another currently * running job. From an API point of view, this is the same as WAITING. */ static const int BLOCKED = 0x08; /** * Start time constant indicating a job should be started at * a time in the infinite future, causing it to sleep forever. */ static const Poco::Timestamp::TimeDiff T_INFINITE; /** * Start time constant indicating that the job has no start time. */ static const Poco::Timestamp::TimeDiff T_NONE; private: //flag mask bits static const int M_STATE = 0xFF; static const int M_SYSTEM = 0x0100; static const int M_USER = 0x0200; /** * flag on a job indicating that it was about to run, but has been canceled */ static const int M_ABOUT_TO_RUN_CANCELED = 0x0400; static int nextJobNumber; int jobNumber; volatile int flags; /// ListenerList listeners ; QString name; /** * The job ahead of me in a queue or list. */ InternalJob::Pointer next; /** * The job behind me in a queue or list. */ InternalJob* previous; int priority; /** * Arbitrary properties (key,value) pairs, attached * to a job instance by a third party. */ //std::map properties ; IStatus::Pointer m_result; // Pointer to the ISchedulingRule belonging to the particular job ISchedulingRule::Pointer sptr_schedulingRule; IProgressMonitor::Pointer sptr_monitor; /** * If the job is waiting, this represents the time the job should start by. * If this job is sleeping, this represents the time the job should wake up. * If this job is running, this represents the delay automatic rescheduling, * or -1 if the job should not be rescheduled. */ Poco::Timestamp m_startTime; /** * Stamp added when a job is added to the wait queue. Used to ensure * jobs in the wait queue maintain their insertion order even if they are * removed from the wait queue temporarily while blocked */ Poco::Timestamp waitQueueStamp; /* * The that is currently running this job */ Poco::Thread* ptr_thread; InternalJob(const Self&); protected: static JobManager* const ptr_manager; IJobChangeListener::Events jobEvents; /* * @see Job#isBlocking() */ bool IsBlocking(); }; } #endif /* BERRY_INTERNALJOB_H */ diff --git a/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.cpp b/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.cpp index ab8f462892..ff523f11e6 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.cpp +++ b/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.cpp @@ -1,121 +1,121 @@ /*=================================================================== BlueBerry Platform 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 "berryViewIntroAdapterPart.h" #include "berryIntroPartAdapterSite.h" #include "internal/berryWorkbench.h" #include "berryWorkbenchPlugin.h" namespace berry { ViewIntroAdapterPart::ViewIntroAdapterPart() : propChangeListener(new PropertyChangeIntAdapter(this, &ViewIntroAdapterPart::PropertyChange)) { } void ViewIntroAdapterPart::SetStandby(bool standby) { // final Control control = ((PartSite) getSite()).getPane().getControl(); // BusyIndicator.showWhile(control.getDisplay(), new Runnable() { // public void run() { // try { // control.setRedraw(false); introPart->StandbyStateChanged(standby); // } finally { // control.setRedraw(true); // } // // setBarVisibility(standby); // } // }); } void ViewIntroAdapterPart::CreatePartControl(QWidget* parent) { //addPaneListener(); introPart->CreatePartControl(parent); } ViewIntroAdapterPart::~ViewIntroAdapterPart() { //setBarVisibility(true); introPart->RemovePropertyListener(propChangeListener.data()); GetSite()->GetWorkbenchWindow()->GetWorkbench()->GetIntroManager()->CloseIntro( introPart); } QIcon ViewIntroAdapterPart::GetTitleImage() const { return introPart->GetTitleImage(); } QString ViewIntroAdapterPart::GetPartName() const { // this method is called eagerly before our init method is called (and // therefore before our intropart is created). By default return // the view title from the view declaration. We will fire a property // change to set the title to the proper value in the init method. return introPart.IsNull() ? ViewPart::GetPartName() : introPart->GetPartName(); } void ViewIntroAdapterPart::Init(IViewSite::Pointer site, - IMemento::Pointer memento) throw (PartInitException) + IMemento::Pointer memento) { ViewPart::Init(site); Workbench* workbench = dynamic_cast(site->GetWorkbenchWindow()->GetWorkbench()); try { introPart = workbench->GetWorkbenchIntroManager() ->CreateNewIntroPart(); // reset the part name of this view to be that of the intro title SetPartName(introPart->GetPartName()); introPart->AddPropertyListener(propChangeListener.data()); introSite = IIntroSite::Pointer(new IntroPartAdapterSite(site, workbench->GetIntroDescriptor())); introPart->Init(introSite, memento); } catch (CoreException& e) { //TODO IStatus // WorkbenchPlugin.log( // IntroMessages.Intro_could_not_create_proxy, // new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, // IStatus.ERROR, IntroMessages.Intro_could_not_create_proxy, e)); WorkbenchPlugin::Log("Could not create intro view proxy.", e); } } void ViewIntroAdapterPart::PropertyChange(const Object::Pointer& /*source*/, int propId) { FirePropertyChange(propId); } void ViewIntroAdapterPart::SetFocus() { introPart->SetFocus(); } void ViewIntroAdapterPart::SaveState(IMemento::Pointer memento) { introPart->SaveState(memento); } } diff --git a/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.h b/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.h index 5214c83ec4..806137b62f 100644 --- a/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.h +++ b/Plugins/org.blueberry.ui.qt/src/internal/intro/berryViewIntroAdapterPart.h @@ -1,155 +1,155 @@ /*=================================================================== BlueBerry Platform 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 BERRYVIEWINTROADAPTERPART_H_ #define BERRYVIEWINTROADAPTERPART_H_ #include #include #include namespace berry { /** * Simple view that will wrap an IIntroPart. * * @since 3.0 */ class ViewIntroAdapterPart: public ViewPart { private: IIntroPart::Pointer introPart; IIntroSite::Pointer introSite; QScopedPointer propChangeListener; friend struct PropertyChangeIntAdapter ; void PropertyChange(const Object::Pointer& source, int propId); // bool handleZoomEvents = true; // /** // * Adds a listener that toggles standby state if the view pane is zoomed. // */ // void AddPaneListener() { // IWorkbenchPartSite site = getSite(); // if (site instanceof PartSite) { // final WorkbenchPartReference ref = ((WorkbenchPartReference)((PartSite) site).getPartReference()); // ref.addInternalPropertyListener( // new IPropertyListener() { // public void propertyChanged(Object source, int propId) { // if (handleZoomEvents) { // if (propId == WorkbenchPartReference.INTERNAL_PROPERTY_ZOOMED) { // setStandby(!ref.getPane().isZoomed()); // } // } // } // }); // } // } // /** // * Sets whether the CoolBar/PerspectiveBar should be visible. // * // * @param visible whether the CoolBar/PerspectiveBar should be visible // */ // void SetBarVisibility(bool visible) { // WorkbenchWindow window = (WorkbenchWindow) getSite() // .getWorkbenchWindow(); // // final boolean layout = (visible != window.getCoolBarVisible()) // || (visible != window.getPerspectiveBarVisible()); // don't layout unless things have actually changed // if (visible) { // window.setCoolBarVisible(true); // window.setPerspectiveBarVisible(true); // } else { // window.setCoolBarVisible(false); // window.setPerspectiveBarVisible(false); // } // // if (layout) { // window.getShell().layout(); // } // } public: ViewIntroAdapterPart(); /** * Forces the standby state of the intro part. * * @param standby update the standby state */ void SetStandby(bool standby); // /** // * Toggles handling of zoom events. // * // * @param handle whether to handle zoom events // */ // void SetHandleZoomEvents(boolean handle) { // handleZoomEvents = handle; // } /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ void CreatePartControl(QWidget* parent) override; /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPart#dispose() */ ~ViewIntroAdapterPart(); /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchPart#getTitleImage() */ QIcon GetTitleImage() const override; /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#GetPartName() */ QString GetPartName() const override; /* (non-Javadoc) * @see org.eclipse.ui.IViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento) */ void Init(IViewSite::Pointer site, IMemento::Pointer memento = - IMemento::Pointer(nullptr)) throw (PartInitException) override; + IMemento::Pointer(nullptr)) override; /* * (non-Javadoc) * * @see org.eclipse.ui.IWorkbenchPart#setFocus() */ void SetFocus() override; /* (non-Javadoc) * @see org.eclipse.ui.IViewPart#saveState(org.eclipse.ui.IMemento) */ void SaveState(IMemento::Pointer memento) override; }; } #endif /* BERRYVIEWINTROADAPTERPART_H_ */ diff --git a/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.cpp b/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.cpp index b31a756bc3..7f63b06a55 100644 --- a/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.cpp +++ b/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.cpp @@ -1,184 +1,183 @@ /*=================================================================== BlueBerry Platform 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 "berryIntroPart.h" #include #include #include #include #include #include "util/berrySafeRunnable.h" #include "internal/berryWorkbenchRegistryConstants.h" namespace berry { class PropChangedRunnable: public SafeRunnable { public: berryObjectMacro(PropChangedRunnable) IPropertyChangeListener::Events::EventType::AbstractDelegate* delegate; PropChangedRunnable(PropertyChangeEvent::Pointer event) : event(event) { } void Run() override { delegate->Execute(event); } private: PropertyChangeEvent::Pointer event; }; QString IntroPart::GetDefaultTitle() const { return "Welcome"; } void IntroPart::FirePropertyChange(int propertyId) { ObjectInt::Pointer val(new ObjectInt(propertyId)); Object::Pointer source(this); PropertyChangeEvent::Pointer event(new PropertyChangeEvent(source, IWorkbenchPartConstants::INTEGER_PROPERTY, val, val)); typedef IPropertyChangeListener::Events::EventType::ListenerList ListenerList; PropChangedRunnable::Pointer runnable(new PropChangedRunnable(event)); const ListenerList& listeners = propChangeEvents.propertyChange.GetListeners(); for (auto iter = listeners.begin(); iter != listeners.end(); ++iter) { runnable->delegate = *iter; SafeRunner::Run(runnable); } } IConfigurationElement::Pointer IntroPart::GetConfigurationElement() { return configElement; } QIcon IntroPart::GetDefaultImage() const { return QIcon(); } void IntroPart::SetSite(IIntroSite::Pointer site) { this->partSite = site; } void IntroPart::SetTitleImage(const QIcon& titleImage) { //Do not send changes if they are the same if (this->imageDescriptor.cacheKey() == titleImage.cacheKey()) { return; } this->imageDescriptor = titleImage; FirePropertyChange(IWorkbenchPartConstants::PROP_TITLE); } void IntroPart::SetTitle(const QString& titleLabel) { if (this->titleLabel == titleLabel) return; this->titleLabel = titleLabel; FirePropertyChange(IWorkbenchPartConstants::PROP_TITLE); } void IntroPart::AddPropertyListener(IPropertyChangeListener *l) { propChangeEvents.AddListener(l); } IntroPart::~IntroPart() { } IIntroSite::Pointer IntroPart::GetIntroSite() const { return partSite; } QIcon IntroPart::GetTitleImage() const { if (!this->imageDescriptor.isNull()) { return this->imageDescriptor; } return GetDefaultImage(); } QString IntroPart::GetPartName() const { if (!titleLabel.isEmpty()) { return titleLabel; } return GetDefaultTitle(); } void IntroPart::Init(IIntroSite::Pointer site, IMemento::Pointer /*memento*/) - throw (PartInitException) { SetSite(site); } void IntroPart::RemovePropertyListener(IPropertyChangeListener *l) { propChangeEvents.RemoveListener(l); } void IntroPart::SaveState(IMemento::Pointer /*memento*/) { //no-op } void IntroPart::SetInitializationData(const IConfigurationElement::Pointer& cfig, const QString& /*propertyName*/, const Object::Pointer& /*data*/) { // Save config element. configElement = cfig; titleLabel = cfig->GetAttribute(WorkbenchRegistryConstants::ATT_LABEL); // Icon. QString strIcon = cfig->GetAttribute(WorkbenchRegistryConstants::ATT_ICON); if (strIcon.isEmpty()) { return; } imageDescriptor = AbstractUICTKPlugin::ImageDescriptorFromPlugin( configElement->GetContributor()->GetName(), strIcon); } } diff --git a/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.h b/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.h index 8b13f31b0f..b156823b2b 100644 --- a/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.h +++ b/Plugins/org.blueberry.ui.qt/src/intro/berryIntroPart.h @@ -1,224 +1,223 @@ /*=================================================================== BlueBerry Platform 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 BERRYINTROPART_H_ #define BERRYINTROPART_H_ #include "berryIIntroPart.h" #include "berryIIntroSite.h" #include #include #include #include namespace berry { /** * Abstract base implementation of an intro part. *

* Subclasses must implement the following methods: *

    *
  • CreatePartControl- to create the intro part's controls *
  • *
  • SetFocus- to accept focus
  • *
  • StandbyStateChanged- to change the standby mode
  • *
*

*

* Subclasses may extend or reimplement the following methods as required: *

    *
  • SetInitializationData- extend to provide additional * initialization when the intro extension is instantiated
  • *
  • Init(IIntroSite::Pointer, IMemento::Pointer)- extend to provide additional * initialization when intro is assigned its site
  • *
  • GetAdapter- reimplement to make their intro adaptable *
  • *
*

*/ class BERRY_UI_QT IntroPart: public QObject, public IIntroPart, public IExecutableExtension { Q_OBJECT Q_INTERFACES(berry::IIntroPart berry::IExecutableExtension) private: IConfigurationElement::Pointer configElement; QIcon imageDescriptor; IIntroSite::Pointer partSite; QString titleLabel; IPropertyChangeListener::Events propChangeEvents; /** * Return the default title string. * * @return the default title string */ QString GetDefaultTitle() const; protected: /** * Fires a property changed event. * * @param propertyId * the id of the property that changed */ void FirePropertyChange(int propertyId); /** * Returns the configuration element for this part. The configuration * element comes from the plug-in registry entry for the extension defining * this part. * * @return the configuration element for this part */ IConfigurationElement::Pointer GetConfigurationElement(); /** * Returns the default title image. * * @return the default image */ QIcon GetDefaultImage() const; /** * Sets the part site. *

* Subclasses must invoke this method from {@link org.eclipse.ui.intro.IIntroPart#init(IIntroSite, IMemento)}. *

* * @param site the intro part site */ void SetSite(IIntroSite::Pointer site); /** * Sets or clears the title image of this part. * * @param titleImage * the title image, or null to clear */ void SetTitleImage(const QIcon& titleImage); /** * Set the title string for this part. * * @param titleLabel the title string. Must not be null. * @since 3.2 */ void SetTitle(const QString& titleLabel); public: /* (non-Javadoc) * @see org.eclipse.ui.intro.IIntroPart#addPropertyListener(org.eclipse.ui.IPropertyListener) */ void AddPropertyListener(IPropertyChangeListener* l) override; /** * The IntroPart implementation of this * IIntroPart method disposes the title image loaded by * setInitializationData. Subclasses may extend. */ ~IntroPart(); /** * This implementation of the method declared by IAdaptable * passes the request along to the platform's adapter manager; roughly * Platform.getAdapterManager().getAdapter(this, adapter). * Subclasses may override this method (however, if they do so, they should * invoke the method on their superclass to ensure that the Platform's * adapter manager is consulted). */ // Object getAdapter(Class adapter) { // return Platform.getAdapterManager().getAdapter(this, adapter); // } /* * (non-Javadoc) * * @see org.eclipse.ui.intro.IIntroPart#getIntroSite() */ IIntroSite::Pointer GetIntroSite() const override; /* (non-Javadoc) * @see org.eclipse.ui.intro.IIntroPart#getTitleImage() */ QIcon GetTitleImage() const override; /* (non-Javadoc) * @see org.eclipse.ui.intro.IIntroPart#getTitle() */ QString GetPartName() const override; /** * The base implementation of this {@link org.eclipse.ui.intro.IIntroPart}method ignores the * memento and initializes the part in a fresh state. Subclasses may extend * to perform any state restoration, but must call the super method. * * @param site * the intro site * @param memento * the intro part state or null if there is no * previous saved state * @exception PartInitException * if this part was not initialized successfully */ - void Init(IIntroSite::Pointer site, IMemento::Pointer memento) - throw (PartInitException) override; + void Init(IIntroSite::Pointer site, IMemento::Pointer memento) override; /* (non-Javadoc) * @see org.eclipse.ui.intro.IIntroPart#removePropertyListener(org.eclipse.ui.IPropertyListener) */ void RemovePropertyListener(IPropertyChangeListener* l) override; /** * The base implementation of this {@link org.eclipse.ui.intro.IIntroPart} method does nothing. * Subclasses may override. * * @param memento * a memento to receive the object state */ void SaveState(IMemento::Pointer memento) override; /** * The IntroPart implementation of this * IExecutableExtension records the configuration element in * and internal state variable (accessible via getConfigElement). * It also loads the title image, if one is specified in the configuration * element. Subclasses may extend. * * Should not be called by clients. It is called by the core plugin when * creating this executable extension. */ void SetInitializationData(const IConfigurationElement::Pointer& cfig, const QString& propertyName, const Object::Pointer& data) override; }; } #endif /* BERRYINTROPART_H_ */