]> Creatis software - cpPlugins.git/commitdiff
yet another refactoring
authorLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Thu, 2 Feb 2017 18:44:54 +0000 (13:44 -0500)
committerLeonardo Flórez-Valencia <florez-l@javeriana.edu.co>
Thu, 2 Feb 2017 18:44:54 +0000 (13:44 -0500)
358 files changed:
CMakeLists.txt [new file with mode: 0644]
appli/CMakeLists.txt [new file with mode: 0644]
appli/PipelineEditor/CMakeLists.txt [new file with mode: 0644]
appli/PipelineEditor/PipelineEditor.cxx [new file with mode: 0644]
appli/PipelineEditor/PipelineEditor.h [new file with mode: 0644]
appli/PipelineEditor/PipelineEditor.ui [new file with mode: 0644]
bash/CMakeLists.txt [new file with mode: 0644]
bash/Config.h.in [new file with mode: 0644]
bash/CreateDemanglers.cxx [new file with mode: 0644]
bash/CreateInstances.cxx [new file with mode: 0644]
bash/CreateRealConfig.cxx [new file with mode: 0644]
bash/HostCreator.cxx [new file with mode: 0644]
cmake/BaseConfig.cmake [new file with mode: 0644]
cmake/CMakeLists.txt [new file with mode: 0644]
cmake/Functions.cmake [new file with mode: 0644]
cmake/KitwareTools.cmake [new file with mode: 0644]
cmake/Options.cmake [new file with mode: 0644]
cmake/QtTools.cmake [new file with mode: 0644]
cmake/cpPluginsConfig.cmake.in [new file with mode: 0644]
lib/CMakeLists.txt [new file with mode: 0644]
lib/cpBaseQtApplication/Blocker.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Blocker.h [new file with mode: 0644]
lib/cpBaseQtApplication/MainHelper.h [new file with mode: 0644]
lib/cpBaseQtApplication/MainWindow.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/MainWindow.h [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Block.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Block.h [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Canvas.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Canvas.h [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Connection.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Connection.h [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/EventFilter.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/EventFilter.h [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Port.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Pipeline/Port.h [new file with mode: 0644]
lib/cpBaseQtApplication/Plugins/Navigator.cxx [new file with mode: 0644]
lib/cpBaseQtApplication/Plugins/Navigator.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/BezierCurveFunction.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/BezierCurveFunction.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/CPRImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/CPRImageFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/FluxMedialness.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/FluxMedialness.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/GradientImageFunctionBase.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/GulsunTekMedialness.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageBlender.cxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageBlender.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageFunctionFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageFunctorFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/InertiaMedialness.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/InertiaTensorFunction.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/IsoImageSlicer.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/IsoImageSlicer.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanConstantFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanFilter.cxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/KalmanVelocityFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/LightCompensationFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/LightCompensationFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/MFluxMedialness.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/MFluxMedialness.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/MacheteImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/MacheteImageFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/ParallelImageMean.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/ParallelImageMean.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.cxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/RGBExtractFunction.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/RGBToHSVFunction.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/RasterContourFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/RasterContourFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/SkeletonReader.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/SkeletonReader.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/SkeletonToImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/SkeletonToImageFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/SkeletonWriter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/SkeletonWriter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h [new file with mode: 0644]
lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx [new file with mode: 0644]
lib/cpExtensions/Config.h.in [new file with mode: 0644]
lib/cpExtensions/DataStructures/Graph.h [new file with mode: 0644]
lib/cpExtensions/DataStructures/Graph.hxx [new file with mode: 0644]
lib/cpExtensions/DataStructures/PolyLineParametricPath.h [new file with mode: 0644]
lib/cpExtensions/DataStructures/PolyLineParametricPath.hxx [new file with mode: 0644]
lib/cpExtensions/DataStructures/Simple3DCurve.cxx [new file with mode: 0644]
lib/cpExtensions/DataStructures/Simple3DCurve.h [new file with mode: 0644]
lib/cpExtensions/DataStructures/Skeleton.h [new file with mode: 0644]
lib/cpExtensions/DataStructures/Skeleton.hxx [new file with mode: 0644]
lib/cpExtensions/Interaction/BaseStyle.cxx [new file with mode: 0644]
lib/cpExtensions/Interaction/BaseStyle.h [new file with mode: 0644]
lib/cpExtensions/Interaction/ImageSlicePointPlacer.cxx [new file with mode: 0644]
lib/cpExtensions/Interaction/ImageSlicePointPlacer.h [new file with mode: 0644]
lib/cpExtensions/Interaction/ImageSliceStyle.cxx [new file with mode: 0644]
lib/cpExtensions/Interaction/ImageSliceStyle.h [new file with mode: 0644]
lib/cpExtensions/Interaction/SeedWidget.cxx [new file with mode: 0644]
lib/cpExtensions/Interaction/SeedWidget.h [new file with mode: 0644]
lib/cpExtensions/QT/ActorsWidgetInterface.h [new file with mode: 0644]
lib/cpExtensions/QT/ConfigurationChooser.cxx [new file with mode: 0644]
lib/cpExtensions/QT/ConfigurationChooser.h [new file with mode: 0644]
lib/cpExtensions/QT/ConfigurationChooser.ui [new file with mode: 0644]
lib/cpExtensions/QT/ImageWidget.cxx [new file with mode: 0644]
lib/cpExtensions/QT/ImageWidget.h [new file with mode: 0644]
lib/cpExtensions/QT/MPR3DWidget.cxx [new file with mode: 0644]
lib/cpExtensions/QT/MPR3DWidget.h [new file with mode: 0644]
lib/cpExtensions/QT/MPRInteractionCommand.cxx [new file with mode: 0644]
lib/cpExtensions/QT/MPRInteractionCommand.h [new file with mode: 0644]
lib/cpExtensions/QT/RendererWidget.cxx [new file with mode: 0644]
lib/cpExtensions/QT/RendererWidget.h [new file with mode: 0644]
lib/cpExtensions/QT/SimpleMPRWidget.cxx [new file with mode: 0644]
lib/cpExtensions/QT/SimpleMPRWidget.h [new file with mode: 0644]
lib/cpExtensions/QT/SimpleMPRWidget.ui [new file with mode: 0644]
lib/cpExtensions/QT/WindowLevelImageConfiguration.cxx [new file with mode: 0644]
lib/cpExtensions/QT/WindowLevelImageConfiguration.h [new file with mode: 0644]
lib/cpExtensions/QT/WindowLevelImageConfiguration.ui [new file with mode: 0644]
lib/cpExtensions/Visualization/CursorActors.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/CursorActors.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageActor.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageActor.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageOutlineActor.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageOutlineActor.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageOutlineSource.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageOutlineSource.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageSliceActors.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageSliceActors.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageSliceMapper.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageSliceMapper.h [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageViewerActors.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/ImageViewerActors.h [new file with mode: 0644]
lib/cpExtensions/Visualization/LUTImageActor.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/LUTImageActor.h [new file with mode: 0644]
lib/cpExtensions/Visualization/LineSource.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/LineSource.h [new file with mode: 0644]
lib/cpExtensions/Visualization/MPR3DActors.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/MPR3DActors.h [new file with mode: 0644]
lib/cpExtensions/Visualization/MeshActor.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/MeshActor.h [new file with mode: 0644]
lib/cpExtensions/Visualization/OutlineSource.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/OutlineSource.h [new file with mode: 0644]
lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h [new file with mode: 0644]
lib/cpExtensions/Visualization/Simple3DCurveToPolyData.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/Simple3DCurveToPolyData.h [new file with mode: 0644]
lib/cpExtensions/Visualization/SkeletonToPolyData.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/SkeletonToPolyData.h [new file with mode: 0644]
lib/cpExtensions/Visualization/WindowLevelImageActor.cxx [new file with mode: 0644]
lib/cpExtensions/Visualization/WindowLevelImageActor.h [new file with mode: 0644]
lib/cpInstances/BaseObjects/ITKBaseObjects.i [new file with mode: 0644]
lib/cpInstances/BaseObjects/ITKBoundingBoxes.i [new file with mode: 0644]
lib/cpInstances/BaseObjects/ITKTransforms.i [new file with mode: 0644]
lib/cpInstances/CMakeLists.txt [new file with mode: 0644]
lib/cpInstances/DataObjects/BoundingBox.cxx [new file with mode: 0644]
lib/cpInstances/DataObjects/BoundingBox.h [new file with mode: 0644]
lib/cpInstances/DataObjects/Image.cxx [new file with mode: 0644]
lib/cpInstances/DataObjects/Image.d [new file with mode: 0644]
lib/cpInstances/DataObjects/Image.h [new file with mode: 0644]
lib/cpInstances/DataObjects/Mesh.cxx [new file with mode: 0644]
lib/cpInstances/DataObjects/Mesh.d [new file with mode: 0644]
lib/cpInstances/DataObjects/Mesh.h [new file with mode: 0644]
lib/cpInstances/DataObjects/PolyLineParametricPath.cxx [new file with mode: 0644]
lib/cpInstances/DataObjects/PolyLineParametricPath.d [new file with mode: 0644]
lib/cpInstances/DataObjects/PolyLineParametricPath.h [new file with mode: 0644]
lib/cpInstances/DataObjects/Simple3DCurve.cxx [new file with mode: 0644]
lib/cpInstances/DataObjects/Simple3DCurve.d [new file with mode: 0644]
lib/cpInstances/DataObjects/Simple3DCurve.h [new file with mode: 0644]
lib/cpInstances/DataObjects/Skeleton.cxx [new file with mode: 0644]
lib/cpInstances/DataObjects/Skeleton.d [new file with mode: 0644]
lib/cpInstances/DataObjects/Skeleton.h [new file with mode: 0644]
lib/cpInstances/Extensions/Paths.i [new file with mode: 0644]
lib/cpInstances/Extensions/Skeleton.i [new file with mode: 0644]
lib/cpInstances/Geometries/ITKMeshes.i [new file with mode: 0644]
lib/cpInstances/Geometries/ITKPaths.i [new file with mode: 0644]
lib/cpInstances/Images/ITK2VTKImageFilters.i [new file with mode: 0644]
lib/cpInstances/Images/ITKImageFunctions.i [new file with mode: 0644]
lib/cpInstances/Images/ITKImageInterpolators.i [new file with mode: 0644]
lib/cpInstances/Images/ITKImages.i [new file with mode: 0644]
lib/cpInstances/Images/ITKImagesBaseFilters.i [new file with mode: 0644]
lib/cpInstances/Images/ITKImagesNeighborhoodIterators.i [new file with mode: 0644]
lib/cpInstances/Images/ITKImagesSimpleIterators.i [new file with mode: 0644]
lib/cpInstances/Images/itkImageToVTKImageFilter.h [new file with mode: 0644]
lib/cpInstances/Images/itkImageToVTKImageFilter.hxx [new file with mode: 0644]
lib/cpInstances/Images/itkVTKImageToImageFilter.h [new file with mode: 0644]
lib/cpInstances/Images/itkVTKImageToImageFilter.hxx [new file with mode: 0644]
lib/cpPlugins/Config.h.in [new file with mode: 0644]
lib/cpPlugins/Interface/Loader.cxx [new file with mode: 0644]
lib/cpPlugins/Interface/Loader.h [new file with mode: 0644]
lib/cpPlugins/Interface/Workspace.cxx [new file with mode: 0644]
lib/cpPlugins/Interface/Workspace.h [new file with mode: 0644]
lib/cpPlugins/Interface/WorkspaceIO.cxx [new file with mode: 0644]
lib/cpPlugins/OS/Chrono.h [new file with mode: 0644]
lib/cpPlugins/OS/DLLManager.cxx [new file with mode: 0644]
lib/cpPlugins/OS/DLLManager.h [new file with mode: 0644]
lib/cpPlugins/OS/FileSystem.cxx [new file with mode: 0644]
lib/cpPlugins/OS/FileSystem.h [new file with mode: 0644]
lib/cpPlugins/OS/String.cxx [new file with mode: 0644]
lib/cpPlugins/OS/String.h [new file with mode: 0644]
lib/cpPlugins/OS/tinydir.h [new file with mode: 0644]
lib/cpPlugins/OS/tinydir_COPYING.txt [new file with mode: 0644]
lib/cpPlugins/OS/tinydir_README.md.txt [new file with mode: 0644]
lib/cpPlugins/Pipeline/DataObject.cxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/DataObject.h [new file with mode: 0644]
lib/cpPlugins/Pipeline/Events.h [new file with mode: 0644]
lib/cpPlugins/Pipeline/Object.cxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/Object.h [new file with mode: 0644]
lib/cpPlugins/Pipeline/Parameters.cxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/Parameters.h [new file with mode: 0644]
lib/cpPlugins/Pipeline/Port.cxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/Port.h [new file with mode: 0644]
lib/cpPlugins/Pipeline/ProcessObject.cxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/ProcessObject.h [new file with mode: 0644]
lib/cpPlugins/Pipeline/ProcessObject.hxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/Widget.cxx [new file with mode: 0644]
lib/cpPlugins/Pipeline/Widget.h [new file with mode: 0644]
lib/cpPlugins/QT/OpenFileDialog.cxx [new file with mode: 0644]
lib/cpPlugins/QT/OpenFileDialog.h [new file with mode: 0644]
lib/cpPlugins/QT/ParametersDialog.cxx [new file with mode: 0644]
lib/cpPlugins/QT/ParametersDialog.h [new file with mode: 0644]
lib/cpPlugins/QT/SaveFileDialog.cxx [new file with mode: 0644]
lib/cpPlugins/QT/SaveFileDialog.h [new file with mode: 0644]
lib/cpPlugins/tinyxml2/OLD_CMakeLists.txt.old [new file with mode: 0644]
lib/cpPlugins/tinyxml2/readme.md [new file with mode: 0644]
lib/cpPlugins/tinyxml2/tinyxml2.cpp [new file with mode: 0644]
lib/cpPlugins/tinyxml2/tinyxml2.h [new file with mode: 0644]
plugins/CMakeLists.txt [new file with mode: 0644]
plugins/GenericPlugins/DataReproducer.cxx [new file with mode: 0644]
plugins/GenericPlugins/DataReproducer.h [new file with mode: 0644]
plugins/GenericPlugins/JoinBoundingBoxes.cxx [new file with mode: 0644]
plugins/GenericPlugins/JoinBoundingBoxes.h [new file with mode: 0644]
plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.cxx [new file with mode: 0644]
plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h [new file with mode: 0644]
plugins/ITKAnisotropicSmoothing/ITKAnisotropicSmoothing.i [new file with mode: 0644]
plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.cxx [new file with mode: 0644]
plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h [new file with mode: 0644]
plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.cxx [new file with mode: 0644]
plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h [new file with mode: 0644]
plugins/ITKBinaryFunctorFilters/ITKBinaryFunctorFilters.i [new file with mode: 0644]
plugins/ITKDistanceMapFilters/BinaryContourImageFilter.cxx [new file with mode: 0644]
plugins/ITKDistanceMapFilters/BinaryContourImageFilter.h [new file with mode: 0644]
plugins/ITKDistanceMapFilters/ITKDistanceMapFilters.i [new file with mode: 0644]
plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.cxx [new file with mode: 0644]
plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h [new file with mode: 0644]
plugins/ITKFiniteDifference/ITKFiniteDifference.i [new file with mode: 0644]
plugins/ITKIO/DicomSeriesReader.cxx [new file with mode: 0644]
plugins/ITKIO/DicomSeriesReader.h [new file with mode: 0644]
plugins/ITKIO/DicomSeriesReaderQDialog.h [new file with mode: 0644]
plugins/ITKIO/DicomSeriesReaderQDialog.ui [new file with mode: 0644]
plugins/ITKIO/DicomSeriesSelectorWidget.cxx [new file with mode: 0644]
plugins/ITKIO/DicomSeriesSelectorWidget.h [new file with mode: 0644]
plugins/ITKIO/DicomSeriesSelectorWidget.ui [new file with mode: 0644]
plugins/ITKIO/ITKIO.i [new file with mode: 0644]
plugins/ITKIO/ImageReader.cxx [new file with mode: 0644]
plugins/ITKIO/ImageReader.h [new file with mode: 0644]
plugins/ITKIO/ImageWriter.cxx [new file with mode: 0644]
plugins/ITKIO/ImageWriter.h [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/CastImageFilter.cxx [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/CastImageFilter.h [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/ITKImageGenericFilters_1.i [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.cxx [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.cxx [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.cxx [new file with mode: 0644]
plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.h [new file with mode: 0644]
plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.cxx [new file with mode: 0644]
plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.h [new file with mode: 0644]
plugins/ITKImageInterpolators/ITKImageInterpolators.i [new file with mode: 0644]
plugins/ITKImageInterpolators/InterpolateImageFunction.cxx [new file with mode: 0644]
plugins/ITKImageInterpolators/InterpolateImageFunction.h [new file with mode: 0644]
plugins/ITKImageInterpolators/LinearInterpolateImageFunction.cxx [new file with mode: 0644]
plugins/ITKImageInterpolators/LinearInterpolateImageFunction.h [new file with mode: 0644]
plugins/ITKLevelSetFilters/ITKLevelSetFilters.i [new file with mode: 0644]
plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.cxx [new file with mode: 0644]
plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h [new file with mode: 0644]
plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.cxx [new file with mode: 0644]
plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h [new file with mode: 0644]
plugins/ITKMorphology/ITKMorphology.i [new file with mode: 0644]
plugins/ITKNeighborhoodOperatorFilters/ITKNeighborhoodOperatorFilters.i [new file with mode: 0644]
plugins/ITKParaMorphology/BinaryDilateParaImageFilter.cxx [new file with mode: 0644]
plugins/ITKParaMorphology/BinaryDilateParaImageFilter.h [new file with mode: 0644]
plugins/ITKParaMorphology/BinaryErodeParaImageFilter.cxx [new file with mode: 0644]
plugins/ITKParaMorphology/BinaryErodeParaImageFilter.h [new file with mode: 0644]
plugins/ITKParaMorphology/ITKParaMorphology.i [new file with mode: 0644]
plugins/ITKSeparableFilters/ITKSeparableFilters.i [new file with mode: 0644]
plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.cxx [new file with mode: 0644]
plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h [new file with mode: 0644]
plugins/ITKSliceFilters/CPRImageFilter.cxx [new file with mode: 0644]
plugins/ITKSliceFilters/CPRImageFilter.h [new file with mode: 0644]
plugins/ITKSliceFilters/ITKSliceFilters.i [new file with mode: 0644]
plugins/ITKSliceFilters/IsoResampleImageFilter.cxx [new file with mode: 0644]
plugins/ITKSliceFilters/IsoResampleImageFilter.h [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/AbsImageFilter.cxx [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/AbsImageFilter.h [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.cxx [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/ITKUnaryFunctorFilters.i [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.cxx [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.h [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.cxx [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.cxx [new file with mode: 0644]
plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h [new file with mode: 0644]
plugins/VTKFilters/CylinderSource.cxx [new file with mode: 0644]
plugins/VTKFilters/CylinderSource.h [new file with mode: 0644]
plugins/VTKFilters/MarchingCubes.cxx [new file with mode: 0644]
plugins/VTKFilters/MarchingCubes.h [new file with mode: 0644]
plugins/VTKFilters/SphereSource.cxx [new file with mode: 0644]
plugins/VTKFilters/SphereSource.h [new file with mode: 0644]
plugins/VTKIO/MeshReader.cxx [new file with mode: 0644]
plugins/VTKIO/MeshReader.h [new file with mode: 0644]
plugins/VTKIO/MeshWriter.cxx [new file with mode: 0644]
plugins/VTKIO/MeshWriter.h [new file with mode: 0644]
plugins/VTKWidgets/LineWidget.cxx [new file with mode: 0644]
plugins/VTKWidgets/LineWidget.h [new file with mode: 0644]
plugins/VTKWidgets/SeedWidget.cxx [new file with mode: 0644]
plugins/VTKWidgets/SeedWidget.h [new file with mode: 0644]
plugins/VTKWidgets/SplineWidget.cxx [new file with mode: 0644]
plugins/VTKWidgets/SplineWidget.h [new file with mode: 0644]
plugins/change.csv [new file with mode: 0644]
plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.cxx [new file with mode: 0644]
plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.h [new file with mode: 0644]
plugins/cpExtensions/PolyLineParametricPathWriter.cxx [new file with mode: 0644]
plugins/cpExtensions/PolyLineParametricPathWriter.h [new file with mode: 0644]
plugins/cpExtensions/SkeletonReader.cxx [new file with mode: 0644]
plugins/cpExtensions/SkeletonReader.h [new file with mode: 0644]
plugins/cpExtensions/SkeletonToImageFilter.cxx [new file with mode: 0644]
plugins/cpExtensions/SkeletonToImageFilter.h [new file with mode: 0644]
plugins/cpExtensions/SkeletonWriter.cxx [new file with mode: 0644]
plugins/cpExtensions/SkeletonWriter.h [new file with mode: 0644]
plugins/cpExtensions/cpExtensions.i [new file with mode: 0644]
tools/CMakeLists.txt [new file with mode: 0644]
tools/ExecutePipeline.cxx [new file with mode: 0644]
tools/PrintDirInfo.cxx [new file with mode: 0644]
tools/PrintFileInfo.cxx [new file with mode: 0644]
tools/PrintGuessInfo.cxx [new file with mode: 0644]
tools/RenameImageFile.cxx [new file with mode: 0644]

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d584f6e
--- /dev/null
@@ -0,0 +1,50 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
+
+## ========================
+## == Project definition ==
+## ========================
+
+SET(prj_NAME cpPlugins)
+SET(prj_MAJ_VERSION 0)
+SET(prj_MIN_VERSION 1)
+SET(prj_REL_VERSION 0)
+SET(_subdirs cmake bash lib tools plugins appli)
+SET(_policies CMP0015 CMP0020 CMP0042)
+
+## ==========================
+## == Some useful policies ==
+## ==========================
+
+FOREACH(_p ${_policies})
+  IF(POLICY ${_p})
+    CMAKE_POLICY(SET ${_p} NEW)
+  ENDIF(POLICY ${_p})
+ENDFOREACH(_p)
+
+## ===========================
+## == Project configuration ==
+## ===========================
+
+PROJECT(${prj_NAME})
+SET(prj_VERSION"${prj_MAJ_VERSION}.${prj_MIN_VERSION}.${prj_REL_VERSION}")
+SET(prj_SHORT_VERSION "${prj_MAJ_VERSION}")
+
+## =====================================
+## == Functions, packages and options ==
+## =====================================
+
+INCLUDE(cmake/BaseConfig.cmake)
+INCLUDE(cmake/Options.cmake)
+INCLUDE(cmake/KitwareTools.cmake)
+INCLUDE(cmake/QtTools.cmake)
+INCLUDE(cmake/Functions.cmake)
+
+## ===========================
+## == Build different parts ==
+## ===========================
+
+FOREACH(_s ${_subdirs})
+  SUBDIRS(${_s})
+ENDFOREACH(_s)
+
+## eof - $RCSfile$
diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt
new file mode 100644 (file)
index 0000000..414db20
--- /dev/null
@@ -0,0 +1,10 @@
+
+## ===================================
+## == One directory per application ==
+## ===================================
+
+SUBDIRS(
+  PipelineEditor
+  )
+
+## eof - $RCSfile$
diff --git a/appli/PipelineEditor/CMakeLists.txt b/appli/PipelineEditor/CMakeLists.txt
new file mode 100644 (file)
index 0000000..11b7d77
--- /dev/null
@@ -0,0 +1,14 @@
+IF(BUILD_QT4_COMPONENTS)
+  INCLUDE_DIRECTORIES(
+    ${PROJECT_SOURCE_DIR}/lib
+    ${PROJECT_BINARY_DIR}/lib
+    ${PROJECT_SOURCE_DIR}/appli/PipelineEditor
+    ${PROJECT_BINARY_DIR}/appli/PipelineEditor
+    )
+  cpPlugins_BuildApplication(PipelineEditor ${CMAKE_CURRENT_SOURCE_DIR})
+  IF(BUILD_PipelineEditor)
+    TARGET_LINK_LIBRARIES(PipelineEditor cpBaseQtApplication)
+  ENDIF(BUILD_PipelineEditor)
+ENDIF(BUILD_QT4_COMPONENTS)
+
+## eof - $RCSfile$
diff --git a/appli/PipelineEditor/PipelineEditor.cxx b/appli/PipelineEditor/PipelineEditor.cxx
new file mode 100644 (file)
index 0000000..c55920f
--- /dev/null
@@ -0,0 +1,157 @@
+#include <PipelineEditor.h>
+#include <ui_PipelineEditor.h>
+
+#include <cpPlugins/OS/String.h>
+#include <cpExtensions/QT/SimpleMPRWidget.h>
+#include <cpExtensions/QT/ImageWidget.h>
+#include <cpExtensions/QT/ActorsWidgetInterface.h>
+#include <vtkImageData.h>
+#include <vtkPolyData.h>
+
+// -------------------------------------------------------------------------
+PipelineEditor::
+PipelineEditor( int argc, char* argv[], QWidget* parent )
+  : Superclass( argc, argv, parent ),
+    m_UI( new Ui::PipelineEditor )
+{
+  // Basic configuration
+  this->m_BaseWindowTitle = "PipelineEditor - ";
+  this->m_UI->setupUi( this );
+  this->setCanvas( this->m_UI->Canvas );
+  this->setNavigator( this->m_UI->Navigator );
+  this->m_UI->Navigator->Update( );
+
+  // Connect slots <-> signals
+  cpBaseQtApplication_ConnectAction( actionLoadDirectory, _loadPluginsFromPath );
+  cpBaseQtApplication_ConnectAction( actionLoadLibrary, _loadPlugins );
+  cpBaseQtApplication_ConnectAction( actionOpenWorkspace, _loadWorkspace );
+  cpBaseQtApplication_ConnectAction( actionSaveWorkspace, _saveWorkspace );
+  cpBaseQtApplication_ConnectAction( actionSaveWorkspaceAs, _saveWorkspace );
+  cpBaseQtApplication_ConnectAction( actionActorsProperties, _actorsProperties );
+  this->m_UI->Canvas->connectOutputPortSlot(
+    this, SLOT( _slotView( const std::string&, bool ) )
+    );
+  this->connect(
+    this->m_UI->actionPrintExecutionInformation, SIGNAL( triggered( bool ) ),
+    this, SLOT( _slotPrintExecutionInformation( bool ) )
+    );
+
+  // Load command-line given workspace (if any)
+  if( argc > 1 )
+    this->_loadWorkspace( argv[ 1 ] );
+}
+
+// -------------------------------------------------------------------------
+PipelineEditor::
+~PipelineEditor( )
+{
+  delete this->m_UI;
+}
+
+// -------------------------------------------------------------------------
+void PipelineEditor::
+_slotView( const std::string& name, bool show )
+{
+  typedef cpExtensions::QT::ActorsWidgetInterface _TViewer;
+
+  // Get filter parameters
+  std::vector< std::string > tokens =
+    cpPlugins::OS::String::Tokenize( name, "@" );
+  if( tokens.size( ) != 2 )
+    return;
+  auto filter_name = tokens[ 1 ];
+  auto output_name = tokens[ 0 ];
+
+  // Process data
+  if( show )
+  {
+    try
+    {
+      auto ws = this->workspace( );
+      auto filter = ws->GetFilter( filter_name );
+      cpBaseQtApplication_Execute( filter->Update( ) );
+      auto image = filter->GetOutputData< vtkImageData >( output_name );
+      auto mesh = filter->GetOutputData< vtkPolyData >( output_name );
+      _TViewer* viewer = NULL;
+      if( image != NULL )
+      {
+        int dim = image->GetDataDimension( );
+        if( dim == 2 )
+          viewer =
+            this->_configureViewer< cpExtensions::QT::ImageWidget >(
+              this->m_UI->Viewer
+              );
+        else if( dim == 3 )
+          viewer =
+            this->_configureViewer< cpExtensions::QT::SimpleMPRWidget >(
+              this->m_UI->Viewer
+              );
+      }
+      else if( mesh != NULL )
+      {
+        viewer =
+          this->_configureViewer< cpExtensions::QT::SimpleMPRWidget >(
+            this->m_UI->Viewer
+            );
+
+      } // fi
+      if(
+        dynamic_cast< QWidget* >( viewer ) !=
+        dynamic_cast< QWidget* >( this->m_UI->Viewer ) &&
+        viewer != NULL
+        )
+      {
+        delete this->m_UI->Viewer;
+        this->m_UI->Viewer = dynamic_cast< QWidget* >( viewer );
+        this->m_UI->MainSplitter->insertWidget( 0, this->m_UI->Viewer );
+        this->setViewer( viewer );
+
+      } // fi
+      if( image != NULL )
+      {
+        this->m_Blocker.block( );
+        auto mpr = dynamic_cast< cpExtensions::QT::SimpleMPRWidget* >( viewer );
+        auto imv = dynamic_cast< cpExtensions::QT::ImageWidget* >( viewer );
+        if( mpr != NULL )
+          mpr->SetImage( image, name );
+        else if( imv != NULL )
+          imv->SetImage( image, name );
+        this->m_Blocker.unblock( );
+      }
+      else if( mesh != NULL )
+      {
+        this->m_Blocker.block( );
+        auto mpr = dynamic_cast< cpExtensions::QT::SimpleMPRWidget* >( viewer );
+        if( mpr != NULL )
+          mpr->Add( mesh, name );
+        this->m_Blocker.unblock( );
+
+      } // fi
+    }
+    catch( std::exception& err )
+    {
+      QMessageBox::critical(
+        NULL,
+        QMessageBox::tr( "Error showing data" ),
+        QMessageBox::tr( err.what( ) )
+        );
+
+    } // yrt
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void PipelineEditor::
+_slotPrintExecutionInformation( bool show )
+{
+  if( this->m_Workspace.IsNotNull( ) )
+    this->m_Workspace->SetPrintExecution( show );
+}
+
+// -------------------------------------------------------------------------
+#include <cpBaseQtApplication/MainHelper.h>
+cpBaseQtApplication_Main( PipelineEditor );
+cpBaseQtApplication_MainComplement;
+
+// eof - $RCSfile$
diff --git a/appli/PipelineEditor/PipelineEditor.h b/appli/PipelineEditor/PipelineEditor.h
new file mode 100644 (file)
index 0000000..1b6674e
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __PipelineEditor__h__
+#define __PipelineEditor__h__
+
+#include <QMainWindow>
+#include <cpBaseQtApplication/MainWindow.h>
+
+namespace Ui { class PipelineEditor; }
+
+/**
+ */
+class PipelineEditor
+  : public cpBaseQtApplication::MainWindow
+{
+  Q_OBJECT;
+public:
+  typedef PipelineEditor                  Self;
+  typedef cpBaseQtApplication::MainWindow Superclass;
+
+public:
+  explicit PipelineEditor(
+    int argc, char* argv[],
+    QWidget* parent = NULL
+    );
+  virtual ~PipelineEditor( );
+
+protected slots:
+  void _slotView( const std::string& name, bool show );
+  void _slotPrintExecutionInformation( bool show );
+
+private:
+  Ui::PipelineEditor* m_UI;
+};
+
+#endif // __PipelineEditor__h__
+
+// eof - $RCSfile$
diff --git a/appli/PipelineEditor/PipelineEditor.ui b/appli/PipelineEditor/PipelineEditor.ui
new file mode 100644 (file)
index 0000000..0e61512
--- /dev/null
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>PipelineEditor</class>
+ <widget class="QMainWindow" name="PipelineEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>PipelineEditor</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <property name="margin">
+     <number>2</number>
+    </property>
+    <property name="spacing">
+     <number>2</number>
+    </property>
+    <item row="0" column="0">
+     <widget class="QSplitter" name="MainSplitter">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <widget class="QWidget" name="Viewer" native="true"/>
+      <widget class="QSplitter" name="second_splitter">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <widget class="cpBaseQtApplication::Plugins::Navigator" name="Navigator" native="true"/>
+       <widget class="cpBaseQtApplication::Pipeline::Canvas" name="Canvas" native="true"/>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>800</width>
+     <height>25</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>&amp;File</string>
+    </property>
+    <addaction name="actionOpenWorkspace"/>
+    <addaction name="actionSaveWorkspace"/>
+    <addaction name="actionSaveWorkspaceAs"/>
+    <addaction name="separator"/>
+    <addaction name="actionExit"/>
+   </widget>
+   <widget class="QMenu" name="menu_Properties">
+    <property name="title">
+     <string>&amp;Properties</string>
+    </property>
+    <addaction name="actionActorsProperties"/>
+   </widget>
+   <widget class="QMenu" name="menuPlu_gins">
+    <property name="title">
+     <string>Plu&amp;gins</string>
+    </property>
+    <addaction name="actionLoadLibrary"/>
+    <addaction name="actionLoadDirectory"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menu_Properties"/>
+   <addaction name="menuPlu_gins"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar">
+   <property name="windowTitle">
+    <string>toolBar</string>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionPrintExecutionInformation"/>
+  </widget>
+  <action name="actionExit">
+   <property name="text">
+    <string>E&amp;xit</string>
+   </property>
+  </action>
+  <action name="actionOpenWorkspace">
+   <property name="text">
+    <string>&amp;Open workspace</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+O</string>
+   </property>
+  </action>
+  <action name="actionSaveWorkspace">
+   <property name="text">
+    <string>&amp;Save workspace</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+S</string>
+   </property>
+  </action>
+  <action name="actionSaveWorkspaceAs">
+   <property name="text">
+    <string>Sa&amp;ve workspace as...</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+S</string>
+   </property>
+  </action>
+  <action name="actionActorsProperties">
+   <property name="text">
+    <string>&amp;Actors</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+P</string>
+   </property>
+  </action>
+  <action name="actionLoadLibrary">
+   <property name="text">
+    <string>Load &amp;library</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+L</string>
+   </property>
+  </action>
+  <action name="actionLoadDirectory">
+   <property name="text">
+    <string>Load &amp;directory</string>
+   </property>
+   <property name="shortcut">
+    <string>Ctrl+Shift+D</string>
+   </property>
+  </action>
+  <action name="actionPrintExecutionInformation">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Print execution information?</string>
+   </property>
+   <property name="toolTip">
+    <string>Print execution information?</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>cpBaseQtApplication::Plugins::Navigator</class>
+   <extends>QWidget</extends>
+   <header location="global">cpBaseQtApplication/Plugins/Navigator.h</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>cpBaseQtApplication::Pipeline::Canvas</class>
+   <extends>QWidget</extends>
+   <header location="global">cpBaseQtApplication/Pipeline/Canvas.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>actionExit</sender>
+   <signal>triggered()</signal>
+   <receiver>PipelineEditor</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>399</x>
+     <y>299</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/bash/CMakeLists.txt b/bash/CMakeLists.txt
new file mode 100644 (file)
index 0000000..36c5075
--- /dev/null
@@ -0,0 +1,25 @@
+CONFIGURE_FILE(
+  ${CMAKE_CURRENT_SOURCE_DIR}/Config.h.in
+  ${CMAKE_CURRENT_BINARY_DIR}/Config.h
+  @ONLY
+  )
+INCLUDE_DIRECTORIES(
+  ${PROJECT_SOURCE_DIR}
+  ${PROJECT_BINARY_DIR}
+  )
+SET(
+  _progs
+  CreateDemanglers
+  CreateInstances
+  CreateRealConfig
+  HostCreator
+  )
+FOREACH(_p ${_progs})
+  ADD_EXECUTABLE(cpPlugins_bash_${_p} ${_p})
+  SET(
+    cpPlugins_bash_${_p}_APP cpPlugins_bash_${_p}
+    CACHE INTERNAL "bash program cpPlugins_bash_${_p}"
+    )
+ENDFOREACH(_p)
+
+## eof - $RCSfile$
diff --git a/bash/Config.h.in b/bash/Config.h.in
new file mode 100644 (file)
index 0000000..1d53531
--- /dev/null
@@ -0,0 +1,274 @@
+#ifndef __cpPlugins__bash__Config__h__
+#define __cpPlugins__bash__Config__h__
+
+// -------------------------------------------------------------------------
+#include <cmath>
+#include <cstring>
+#include <deque>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <queue>
+#include <sstream>
+#include <string>
+
+// -------------------------------------------------------------------------
+#define cpPlugins_PROCESS_DIMS    "@cpPlugins_PROCESS_DIMS@"
+#define cpPlugins_VISUAL_DIMS     "@cpPlugins_VISUAL_DIMS@"
+#define cpPlugins_ALL_CONFIGS     "@cpPlugins_ALL_CONFIGS@"
+#define cpPlugins_NUMBER_OF_FILES @cpPlugins_NUMBER_OF_FILES@
+
+// -------------------------------------------------------------------------
+#define cpPlugins_bash_OS_@CMAKE_SYSTEM_NAME@
+#ifdef cpPlugins_bash_OS_Windows
+#  define cpPlugins_bash_STRTOK( A, B, N )  strtok_s(  A, B, N )
+#  define cpPlugins_bash_SPRINTF( B, S, O ) sprintf_s( B, S, "%s", O );
+#else // cpPlugins_bash_OS_Windows
+#  define cpPlugins_bash_STRTOK( A, B, N )  std::strtok( A, B )
+#  define cpPlugins_bash_SPRINTF( B, S, O ) std::sprintf( B, "%s", O );
+#endif // cpPlugins_bash_OS_Windows
+
+// -------------------------------------------------------------------------
+typedef std::deque< std::string > TStrings;
+typedef std::map< std::string, TStrings > TCommands;
+
+/**
+ */
+namespace cpPlugins_bash
+{
+  // -----------------------------------------------------------------------
+  template< class _TTokens >
+  inline void Tokenize(
+    _TTokens& tokens, const std::string& str, const std::string& delims
+    )
+  {
+    tokens.clear( );
+    if( str.size( ) > 0 )
+    {
+      auto ssize = str.size( );
+      char* buffer = new char[ ssize + 1 ];
+      for( unsigned long i = 0; i < ssize; ++i )
+        buffer[ i ] = str[ i ];
+      buffer[ ssize ] = '\0';
+      char* next;
+      char* it = cpPlugins_bash_STRTOK( buffer, delims.c_str( ), &next );
+      while( it != NULL )
+      {
+        tokens.push_back( std::string( it ) );
+        it = cpPlugins_bash_STRTOK( NULL, delims.c_str( ), &next );
+
+      } // elihw
+      delete [] buffer;
+
+    } // fi
+  }
+
+  // -----------------------------------------------------------------------
+  inline std::string Replace(
+    const std::string& str, const std::string& sub, const std::string& nsub
+    )
+  {
+    std::string res = str;
+    size_t index;
+    while( ( index = res.find( sub ) ) != std::string::npos )
+      res.replace( index, sub.size( ), nsub );
+    return( res );
+  }
+
+  // -----------------------------------------------------------------------
+  inline bool Read( std::string& buffer, const std::string& fname )
+  {
+    buffer = "";
+    std::ifstream file_stream( fname.c_str( ) );
+    if( !file_stream )
+      return( false );
+    file_stream.seekg( 0, std::ios::end );
+    buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) );
+    file_stream.seekg( 0, std::ios::beg );
+    buffer.assign(
+      ( std::istreambuf_iterator< char >( file_stream ) ),
+      std::istreambuf_iterator< char >( )
+      );
+    file_stream.close( );
+    return( true );
+  }
+
+  // -----------------------------------------------------------------------
+  inline bool Write( const std::string& buffer, const std::string& fname )
+  {
+    std::ofstream file_stream( fname.c_str( ), std::ofstream::binary );
+    if( !file_stream )
+      return( false );
+    file_stream.write( buffer.c_str( ), buffer.size( ) );
+    return( true );
+  }
+
+  // -----------------------------------------------------------------------
+  inline void Parse( TCommands& commands, const TStrings& lines )
+  {
+    for( auto l = lines.begin( ); l != lines.end( ); ++l )
+    {
+      auto line = l->substr( l->find_first_not_of( " " ) );
+      if( line != "" )
+      {
+        if( line[ 0 ] != '*' )
+        {
+          auto cmd = line.substr( 0, line.find( " " ) );
+          auto args = line.substr( line.find( " " ) + 1 );
+          commands[ cmd ].push_back( args );
+
+        } // fi
+
+      } // fi
+
+    } // rof
+  }
+
+  // -----------------------------------------------------------------------
+  inline void LoadDefinitions( TCommands& commands )
+  {
+    // Dimensions
+    commands[ "define" ].push_back(
+      std::string( "pdims=" ) +
+      std::string( cpPlugins_PROCESS_DIMS )
+      );
+    commands[ "define" ].push_back(
+      std::string( "vdims=" ) +
+      std::string( cpPlugins_VISUAL_DIMS )
+      );
+
+    // Base c++ types
+    commands[ "define" ].push_back(
+      std::string( "int_types=char;short;int;long" )
+      );
+    commands[ "define" ].push_back(
+      std::string( "uint_types=unsigned #int_types#" )
+      );
+    commands[ "define" ].push_back(
+      std::string( "sint_types=signed char" )
+      );
+    commands[ "define" ].push_back(
+      std::string( "real_types=float;double" )
+      );
+    commands[ "define" ].push_back(
+      std::string(
+        "scalar_types=#int_types#;#uint_types#;#real_types#"
+        )
+      );
+  }
+
+  // -----------------------------------------------------------------------
+  inline void ExpandDefinitions(
+    TCommands& definitions, const TCommands& commands
+    )
+  {
+    definitions.clear( );
+    auto defs = commands.find( "define" );
+    if( defs == commands.end( ) )
+      return;
+
+    std::map< std::string, std::string > values;
+    for( auto dIt = defs->second.begin( ); dIt != defs->second.end( ); ++dIt )
+    {
+      TStrings toks;
+      cpPlugins_bash::Tokenize( toks, *dIt, "=" );
+      if( toks.size( ) == 2 )
+      {
+        auto name = toks[ 0 ].substr( toks[ 0 ].find_first_not_of( " " ) );
+        auto val = toks[ 1 ].substr( toks[ 1 ].find_first_not_of( " " ) );
+        values[ name ] = val;
+
+      } // fi
+
+    } // rof
+    for( auto vIt = values.begin( ); vIt != values.end( ); ++vIt )
+    {
+      TStrings toks;
+      cpPlugins_bash::Tokenize( toks, vIt->second, ";" );
+      for( auto tIt = toks.begin( ); tIt != toks.end( ); ++tIt )
+        definitions[ vIt->first ].push_back( *tIt );
+
+    } // rof
+    for( auto dIt = definitions.begin( ); dIt != definitions.end( ); ++dIt )
+    {
+      auto name = std::string( "#" ) + dIt->first + std::string( "#" );
+      for( auto eIt = definitions.begin( ); eIt != definitions.end( ); ++eIt )
+      {
+        if( eIt != dIt )
+        {
+          auto vIt = eIt->second.begin( );
+          while( vIt != eIt->second.end( ) )
+          {
+            if( vIt->find( name ) != std::string::npos )
+            {
+              for(
+                auto wIt = dIt->second.begin( );
+                wIt != dIt->second.end( );
+                ++wIt
+                )
+                eIt->second.push_back(
+                  cpPlugins_bash::Replace( *vIt, name, *wIt )
+                  );
+              vIt = eIt->second.erase( vIt );
+            }
+            else
+              ++vIt;
+
+          } // elihw
+
+        } // fi
+
+      } // rof
+
+    } // rof
+  }
+
+  // -----------------------------------------------------------------------
+  inline void Expand(
+    TStrings& tfiles,
+    const TCommands& definitions,
+    const TCommands& commands,
+    const std::string& cmd
+    )
+  {
+    tfiles.clear( );
+    auto tIt = commands.find( cmd );
+    if( tIt == commands.end( ) )
+      return;
+
+    for( auto fIt = tIt->second.begin( ); fIt != tIt->second.end( ); ++fIt )
+    {
+      std::queue< std::string > q;
+      q.push( *fIt );
+      while( q.size( ) > 0 )
+      {
+        auto value = q.front( );
+        q.pop( );
+        auto spos = value.find( "#" );
+        if( spos != std::string::npos )
+        {
+          auto name = value.substr( spos + 1 );
+          auto epos = name.find( "#" );
+          name = name.substr( 0, epos );
+          auto dIt = definitions.find( name );
+          if( dIt != definitions.end( ) )
+          {
+            name = std::string( "#" ) + name + std::string( "#" );
+            for( auto vIt = dIt->second.begin( ); vIt != dIt->second.end( ); ++vIt )
+              q.push( cpPlugins_bash::Replace( value, name, *vIt ) );
+
+          } // fi
+        }
+        else
+          tfiles.push_back( value );
+
+      } // rof
+
+    } // rof
+  }
+
+} // ecapseman
+
+#endif // __cpPlugins__bash__Config__h__
+
+// eof - $RCSfile$
diff --git a/bash/CreateDemanglers.cxx b/bash/CreateDemanglers.cxx
new file mode 100644 (file)
index 0000000..a68117f
--- /dev/null
@@ -0,0 +1,121 @@
+#include <bash/Config.h>
+
+#define MAX_NUMBER_OF_INPUTS 9
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get inputs
+  if( argc < 4 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " definitons_file object_name output_file"
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string definitions_filename = argv[ 1 ];
+  std::string object_name = argv[ 2 ];
+  std::string output_filename = argv[ 3 ];
+
+  // Read inputs
+  std::string definitions_buffer;
+  if( !( cpPlugins_bash::Read( definitions_buffer, definitions_filename ) ) )
+  {
+    std::cerr
+      << argv[ 0 ]
+      <<  ": Error reading definitions file \"" << definitions_filename
+      << "\"" << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Put it in a line-by-line structure
+  TStrings definitions_lines;
+  cpPlugins_bash::Tokenize( definitions_lines, definitions_buffer, "\n" );
+
+  // Parse input file
+  TCommands commands;
+  cpPlugins_bash::Parse( commands, definitions_lines );
+
+  // Load pre-compiled definitions
+  cpPlugins_bash::LoadDefinitions( commands );
+
+  // Expand definitions
+  TCommands definitions;
+  cpPlugins_bash::ExpandDefinitions( definitions, commands );
+
+  // Expand data
+  std::stringstream data;
+  data
+    << "#ifndef __cpPlugins__Demanglers__" << object_name << "__h__" << std::endl
+    << "#define __cpPlugins__Demanglers__" << object_name << "__h__" << std::endl
+    << std::endl;
+
+  for( auto cIt = commands.begin( ); cIt != commands.end( ); ++cIt )
+  {
+    if( cIt->first == "define" )
+      continue;
+
+    TStrings instances;
+    cpPlugins_bash::Expand( instances, definitions, commands, cIt->first );
+    TStrings toks;
+    cpPlugins_bash::Tokenize( toks, cIt->first, "|" );
+    for( unsigned int nIns = 1; nIns <= MAX_NUMBER_OF_INPUTS; ++nIns )
+    {
+      if( toks.size( ) > 1 )
+      {
+        data
+          << "#define cpPlugins_Demangle_" << object_name << "_"
+          << toks[ 0 ] << "_" << nIns << "( o, f";
+        for( unsigned int i = 1; i < toks.size( ); ++i )
+          data << ", " << toks[ i ];
+      }
+      else
+        data
+          << "#define cpPlugins_Demangle_" << object_name << "_"
+          << toks[ 0 ] << "_" << nIns << "( o, f";
+
+      for( unsigned int i = 1; i < nIns; ++i )
+        data << ", X" << i;
+      data << " ) \\";
+
+      data << std::endl;
+      std::string prefix = "";
+      for( auto iIt = instances.begin( ); iIt != instances.end( ); ++iIt )
+      {
+        data
+          << "  " << prefix
+          << "if( dynamic_cast< " << *iIt << "* >( o ) != NULL ) \\"
+          << std::endl
+          << "    this->f( dynamic_cast< " << *iIt << "* >( o )";
+
+        for( unsigned int i = 1; i < nIns; ++i )
+          data << ", X" << i;
+        data
+          << " ); \\"
+          << std::endl;
+        prefix = "else ";
+
+      } // rof
+      data << "  " << prefix << std::endl << std::endl;
+
+    } // rof
+
+  } // rof
+
+  data
+    << "#endif // __cpPlugins__Demanglers__" << object_name << "__h__"
+    << std::endl;
+  if( !( cpPlugins_bash::Write( data.str( ), output_filename ) ) )
+  {
+    std::cerr << "Error writing file." << std::endl;
+    return( 1 );
+
+  } // fi
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/bash/CreateInstances.cxx b/bash/CreateInstances.cxx
new file mode 100644 (file)
index 0000000..a107c26
--- /dev/null
@@ -0,0 +1,168 @@
+#include <bash/Config.h>
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get inputs
+  if( argc < 4 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " definitons_file library_name output_prefix"
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string definitions_filename = argv[ 1 ];
+  std::string library_name = argv[ 2 ];
+  std::string output_prefix = argv[ 3 ];
+  unsigned int number_of_sources = cpPlugins_NUMBER_OF_FILES;
+
+  // Read inputs
+  std::string definitions_buffer;
+  if( !( cpPlugins_bash::Read( definitions_buffer, definitions_filename ) ) )
+  {
+    std::cerr
+      << argv[ 0 ]
+      <<  ": Error reading definitions file \"" << definitions_filename
+      << "\"" << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Put it in a line-by-line structure
+  TStrings definitions_lines;
+  cpPlugins_bash::Tokenize( definitions_lines, definitions_buffer, "\n" );
+
+  // Parse input file
+  TCommands commands;
+  cpPlugins_bash::Parse( commands, definitions_lines );
+
+  // Load pre-compiled definitions
+  cpPlugins_bash::LoadDefinitions( commands );
+
+  // Expand definitions
+  TCommands definitions;
+  cpPlugins_bash::ExpandDefinitions( definitions, commands );
+  definitions[ "_export_" ].clear( );
+  definitions[ "_export_" ].push_back( library_name + std::string( "_EXPORT" ) );
+
+  // Expand data
+  TStrings tfiles, cfiles, instances, minstances;
+  cpPlugins_bash::Expand( tfiles, definitions, commands, "tinclude" );
+  cpPlugins_bash::Expand( cfiles, definitions, commands, "cinclude" );
+  cpPlugins_bash::Expand( instances, definitions, commands, "instances" );
+  cpPlugins_bash::Expand( minstances, definitions, commands, "minstances" );
+
+  // Build all instances
+  TStrings all_instances;
+  for( auto iIt = instances.begin( ); iIt != instances.end( ); ++iIt )
+  {
+    std::stringstream str;
+    str << "template class " << library_name << "_EXPORT " << *iIt;
+    all_instances.push_back( str.str( ) );
+
+  } // rof
+  for( auto iIt = minstances.begin( ); iIt != minstances.end( ); ++iIt )
+  {
+    std::stringstream str;
+    str << "template " << *iIt;
+    all_instances.push_back( str.str( ) );
+
+  } // rof
+
+  // Write source code
+  unsigned int instances_per_file =
+    ( unsigned int )(
+      std::floor( double( all_instances.size( ) ) / double( number_of_sources ) )
+      );
+  if( instances_per_file == 0 )
+    instances_per_file = 1;
+  std::vector< std::vector< std::string > > all_lines( 1 );
+  for( unsigned int c_id = 0; c_id < all_instances.size( ); ++c_id )
+  {
+    all_lines[ all_lines.size( ) - 1 ].push_back( all_instances[ c_id ] );
+    if( c_id % instances_per_file == instances_per_file - 1 )
+      all_lines.push_back( std::vector< std::string >( ) );
+
+  } // rof
+
+  // Paranoiac code
+  while( all_lines.size( ) > number_of_sources )
+  {
+    all_lines[ all_lines.size( ) - 2 ].insert(
+      all_lines[ all_lines.size( ) - 2 ].end( ),
+      all_lines[ all_lines.size( ) - 1 ].begin( ),
+      all_lines[ all_lines.size( ) - 1 ].end( )
+      );
+    all_lines.pop_back( );
+
+  } // elihw
+  while( all_lines.size( ) < number_of_sources )
+    all_lines.push_back( std::vector< std::string >( ) );
+
+  // Real write
+  for( unsigned int f_id = 0; f_id < all_lines.size( ); ++f_id )
+  {
+    std::stringstream source;
+    source
+      << "#include <" << library_name << "_Export.h>"
+      << std::endl;
+    auto hIt = commands.find( "header" );
+    if( hIt != commands.end( ) )
+    {
+      source << std::endl;
+      for( auto vIt = hIt->second.begin( ); vIt != hIt->second.end( ); ++vIt )
+        source << *vIt << std::endl;
+      source << std::endl;
+
+    } // fi
+
+    if( tfiles.size( ) > 0 )
+    {
+      for( auto tIt = tfiles.begin( ); tIt != tfiles.end( ); ++tIt )
+      {
+        TStrings toks;
+        cpPlugins_bash::Tokenize( toks, *tIt, ":|" );
+        if( toks.size( ) == 3 )
+        {
+          source << "#include <" << toks[ 0 ] << "." << toks[ 1 ] << ">" << std::endl;
+          source << "#include <" << toks[ 0 ] << "." << toks[ 2 ] << ">" << std::endl;
+
+        } // fi
+
+      } // rof
+      source << std::endl;
+
+    } // fi
+
+    if( cfiles.size( ) > 0 )
+    {
+      for( auto cIt = cfiles.begin( ); cIt != cfiles.end( ); ++cIt )
+        source << "#include <" << *cIt << ">" << std::endl;
+      source << std::endl;
+
+    } // fi
+
+    for(
+      auto c_it = all_lines[ f_id ].begin( );
+      c_it != all_lines[ f_id ].end( );
+      ++c_it
+      )
+      source << *c_it << ";" << std::endl;
+    source << std::endl << "// eof" << std::endl;
+    std::stringstream source_file;
+    source_file
+      << output_prefix << "_" << f_id << ".cxx";
+    if( !( cpPlugins_bash::Write( source.str( ), source_file.str( ) ) ) )
+    {
+      std::cerr << "Error writing source code." << std::endl;
+      return( 1 );
+
+    } // fi
+
+  } // rof
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/bash/CreateRealConfig.cxx b/bash/CreateRealConfig.cxx
new file mode 100644 (file)
index 0000000..e9737d5
--- /dev/null
@@ -0,0 +1,37 @@
+#include <bash/Config.h>
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  // Get inputs
+  if( argc < 2 )
+  {
+    std::cerr << "Usage: " << argv[ 0 ] << " output_file" << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string output_filename = argv[ 1 ];
+
+  std::stringstream data;
+  data
+    << "#ifndef __cpPlugins__RealConfig__h__" << std::endl
+    << "#define __cpPlugins__RealConfig__h__" << std::endl
+    << std::endl;
+
+  TStrings tokens;
+  cpPlugins_bash::Tokenize( tokens, cpPlugins_ALL_CONFIGS, ";" );
+  for( auto t = tokens.begin( ); t != tokens.end( ); ++t )
+    data << "#define " << *t << std::endl;
+
+  data << std::endl << "#endif // __cpPlugins__RealConfig__h__" << std::endl;
+  if( !( cpPlugins_bash::Write( data.str( ), output_filename ) ) )
+  {
+    std::cerr << "Error writing file." << std::endl;
+    return( 1 );
+
+  } // fi
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/bash/HostCreator.cxx b/bash/HostCreator.cxx
new file mode 100644 (file)
index 0000000..8e6f274
--- /dev/null
@@ -0,0 +1,193 @@
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <utility>
+#include <vector>
+#include <bash/Config.h>
+
+// -------------------------------------------------------------------------
+typedef std::pair< std::string, std::string > TPair;
+typedef std::map< std::string, TPair >        TInfo;
+
+// -------------------------------------------------------------------------
+bool is_valid_class( const std::string& str )
+{
+  return( str.find( "cpPluginsObject" ) != std::string::npos );
+}
+
+// -------------------------------------------------------------------------
+void process_header( TInfo& info, const std::string& file_name )
+{
+  std::string buffer;
+  if( !( cpPlugins_bash::Read( buffer, file_name ) ) )
+    return;
+
+  auto prev_pos = std::string::npos;
+  prev_pos = 0;
+  auto pos = buffer.find( "cpPluginsObject" );
+  while( pos != std::string::npos )
+  {
+    // Get class names
+    auto op = buffer.find( "(", pos );
+    auto cl = buffer.find( ")", pos );
+    std::vector< std::string > tokens;
+    cpPlugins_bash::Tokenize(
+      tokens,
+      buffer.substr( op + 1, cl - op - 2 ),
+      ",\n "
+      );
+
+    std::string namespace_name = "";
+    auto preamble = buffer.substr( prev_pos, pos );
+    auto napos = preamble.find( "namespace" );
+    while( napos != std::string::npos )
+    {
+      auto enapos = preamble.find( "{", napos + 1 );
+      auto tmp = preamble.substr( napos, enapos - napos + 1 );
+      std::vector< std::string > tokens2;
+      cpPlugins_bash::Tokenize( tokens2, tmp, " \n\t{" );
+      namespace_name = tokens2.back( );
+      napos = preamble.find( "namespace", napos + 1 );
+
+    } // elihw
+
+    auto class_name = tokens[ 0 ];
+    auto superclass_name = tokens[ 1 ];
+    auto category_name = tokens[ 2 ];
+    if( info.find( class_name ) == info.end( ) )
+      info[ class_name ] = TPair( category_name, namespace_name );
+    prev_pos = pos;
+    pos = buffer.find( "cpPluginsObject", pos + 1 );
+
+  } // elihw
+}
+
+// -------------------------------------------------------------------------
+int main( int argc, char* argv[] )
+{
+  if( argc < 4 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " plugins_name output_file header_file_0.h header_file_0.h ..."
+      << std::endl;
+    return( 1 );
+
+  } // fi
+  std::string plugins_name = argv[ 1 ];
+  std::string output_filename = argv[ 2 ];
+
+  // Parse all header files
+  TInfo info;
+  for( int i = 3; i < argc; ++i )
+    process_header( info, argv[ i ] );
+  if( info.size( ) == 0 )
+  {
+    std::cerr << "ERROR: No valid input headers." << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Prepare prefixes
+#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
+  std::string export_prefix = "__declspec(dllexport)";
+#else // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
+  std::string export_prefix = "__attribute__((visibility(\"default\")))";
+#endif // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ )
+
+  // Output data
+  std::stringstream out;
+
+  // Include section
+  out
+    << "#include <map>" << std::endl
+    << "#include <string>" << std::endl
+    << "#include <vector>" << std::endl
+    << "#include <itkLightObject.h>" << std::endl
+    << std::endl;
+  for( int i = 3; i < argc; ++i )
+    out << "#include \"" << argv[ i ] << "\"" <<std::endl;
+  out << std::endl;
+
+  // Common header section
+  out
+    << "// -------------------------------------------------------------------------" << std::endl
+    << "std::map< std::string, itk::LightObject::Pointer > "
+    << plugins_name << "_Data;" << std::endl
+    << std::endl
+    << "// -------------------------------------------------------------------------" << std::endl
+    << "extern \"C\" void __attribute__ ((constructor))" << std::endl
+    << plugins_name << "_Init( )" << std::endl
+    << "{" << std::endl
+    << "}" << std::endl
+    << std::endl
+    << "// -------------------------------------------------------------------------" << std::endl
+    << "extern \"C\" void __attribute__ ((destructor))" << std::endl
+    << plugins_name << "_Finish( )" << std::endl
+    << "{" << std::endl
+    << "  // " << plugins_name << "_Data.clear( );" << std::endl
+    << "}" << std::endl
+    << std::endl
+    << "// -------------------------------------------------------------------------" << std::endl
+    << "extern \"C\" " << export_prefix << std::endl
+    << "void " << plugins_name << "_LoadContents( )" << std::endl
+    << "{" << std::endl
+    << "  if( " << plugins_name << "_Data.size( ) == 0 )" << std::endl
+    << "  {" << std::endl
+    << "    std::string sep = \"@\";" << std::endl;
+
+  // Classes
+  int id = 1;
+  for( auto iIt = info.begin( ); iIt != info.end( ); ++iIt, ++id )
+  {
+    std::string class_name = iIt->second.second;
+    if( class_name != "" )
+      class_name += std::string( "::" );
+    class_name += iIt->first;
+    out
+      << "    " << class_name << "::Pointer ptr" << id << " =" << std::endl
+      << "      " << class_name << "::New( );" << std::endl
+      << "    std::string id" << id << " = ptr" << id << "->GetClassName( )"
+      << " + sep + ptr" << id << "->GetClassCategory( );" << std::endl
+      << "    " << plugins_name << "_Data[ id" << id << " ] = ptr" << id << ";"
+      << std::endl;
+
+  } // rof
+
+  // Remaining header
+  out
+    << std::endl << "  } // fi" << std::endl << "}" << std::endl << std::endl
+    << "// -------------------------------------------------------------------------" << std::endl
+    << "extern \"C\" " << export_prefix << std::endl
+    << "void cpPlugins_Contents( std::vector< std::string >* c )" << std::endl
+    << "{" << std::endl
+    << "  " << plugins_name << "_LoadContents( );" << std::endl
+    << "  for( auto d : " << plugins_name << "_Data )" << std::endl
+    << "    c->push_back( d.first );" << std::endl
+    << "}" << std::endl
+    << std::endl
+    << "// -------------------------------------------------------------------------" << std::endl
+    << "extern \"C\" " << export_prefix << std::endl
+    << "void cpPlugins_Creator( itk::LightObject::Pointer& ptr, const std::string& c, const std::string& f )" << std::endl
+    << "{" << std::endl
+    << "  " << plugins_name << "_LoadContents( );" << std::endl
+    << "  ptr = NULL;" << std::endl
+    << "  std::string id = f + \"@\" + c;" << std::endl
+    << "  auto fIt = " << plugins_name << "_Data.find( id );" << std::endl
+    << "  if( fIt != " << plugins_name << "_Data.end( ) )" << std::endl
+    << "    ptr = fIt->second->CreateAnother( );" << std::endl
+    << "}" << std::endl << std::endl
+    << "// eof - $Automatic generated file$"
+    << std::endl;
+
+  // Real write
+  if( !( cpPlugins_bash::Write( out.str( ), output_filename ) ) )
+  {
+    std::cerr << "ERROR: Could not write file." << std::endl;
+    return( 1 );
+
+  } // fi
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/cmake/BaseConfig.cmake b/cmake/BaseConfig.cmake
new file mode 100644 (file)
index 0000000..d177604
--- /dev/null
@@ -0,0 +1,51 @@
+## =======================================================================
+## == Force c++11 language version                                      ==
+## == NOTE: It seems that by default on Visual Studio Compiler supports ==
+## ==       c++11, so it only need to be tested on other OS.            ==
+## =======================================================================
+
+IF(NOT MSVC)
+  INCLUDE(CheckCXXCompilerFlag)
+  CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
+  IF(COMPILER_SUPPORTS_CXX11)
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+  ELSE(COMPILER_SUPPORTS_CXX11)
+    CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
+    IF(COMPILER_SUPPORTS_CXX0X)
+      SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
+    ELSE(COMPILER_SUPPORTS_CXX0X)
+      MESSAGE(
+        FATAL_ERROR
+        "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support."
+        )
+    ENDIF(COMPILER_SUPPORTS_CXX0X)
+  ENDIF(COMPILER_SUPPORTS_CXX11)
+ENDIF(NOT MSVC)
+
+## ===================================================
+## == Prepare header generator to build shared libs ==
+## ===================================================
+
+INCLUDE(GenerateExportHeader)
+
+## ==================================================
+## == Do not allow to build inside the source tree ==
+## ==================================================
+
+IF(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR})
+  MESSAGE(FATAL_ERROR "Building in the source tree is not allowed.")
+ENDIF(PROJECT_BINARY_DIR STREQUAL ${PROJECT_SOURCE_DIR})
+
+## =================================================
+## == Where to put targets (executables and libs) ==
+## =================================================
+
+SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR})
+SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR})
+MARK_AS_ADVANCED(
+  CMAKE_BACKWARDS_COMPATIBILITY
+  EXECUTABLE_OUTPUT_PATH
+  LIBRARY_OUTPUT_PATH
+  )
+
+## eof - $RCSfile$
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e942ae9
--- /dev/null
@@ -0,0 +1,11 @@
+## =====================
+## == Configure files ==
+## =====================
+
+CONFIGURE_FILE(
+  cpPluginsConfig.cmake.in
+  ${PROJECT_BINARY_DIR}/cpPluginsConfig.cmake
+  @ONLY
+  )
+
+## eof - $RCSfile$
diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake
new file mode 100644 (file)
index 0000000..d755587
--- /dev/null
@@ -0,0 +1,328 @@
+## -------------------------------------------------------------------------
+FUNCTION(NormPaths output_files)
+SET(_out)
+FOREACH(_f ${ARGN})
+  SET(_d)
+  FILE(TO_CMAKE_PATH ${_f} _d)
+  LIST(APPEND _out ${_d})
+ENDFOREACH(_f)
+SET(${output_files} "${_out}" PARENT_SCOPE)
+ENDFUNCTION()
+
+## -------------------------------------------------------------------------
+FUNCTION(Wrap_Qt_CPP output_files)
+SET(_out)
+FOREACH(_f ${ARGN})
+  IF(EXISTS ${_f})
+    FILE(READ ${_f} _txt)
+    STRING(FIND "${_txt}" "Q_OBJECT" _pos)
+    IF(NOT ${_pos} EQUAL -1)
+      SET(_s)
+      QT4_WRAP_CPP(_s ${_f})
+      SET(_out ${_out} ${_s})
+    ENDIF(NOT ${_pos} EQUAL -1)
+  ENDIF(EXISTS ${_f})
+ENDFOREACH(_f)
+SET(${output_files} "${_out}" PARENT_SCOPE)
+ENDFUNCTION()
+
+## -------------------------------------------------------------------------
+FUNCTION(Wrap_Qt_UI output_files)
+NormPaths(_source_dir ${PROJECT_SOURCE_DIR})
+NormPaths(_binary_dir ${PROJECT_BINARY_DIR})
+SET(_out)
+FOREACH(_f ${ARGN})
+  IF(EXISTS ${_f})
+    GET_FILENAME_COMPONENT(_name ${_f} NAME_WE)
+    GET_FILENAME_COMPONENT(_dir ${_f} DIRECTORY)
+    SET(_base_dir ${_source_dir})
+    STRING(FIND "${_dir}" "${_base_dir}" _pos)
+    IF(${_pos} EQUAL -1)
+      SET(_base_dir ${_binary_dir})
+      STRING(FIND "${_dir}" "${_base_dir}" _pos)
+    ENDIF(${_pos} EQUAL -1)
+    IF(NOT ${_pos} EQUAL -1)
+      STRING(REPLACE "${_base_dir}/" "" _dir ${_dir})
+      SET(_out_f ${_binary_dir}/${_dir}/ui_${_name}.h)
+      LIST(APPEND _out ${_out_f})
+      ADD_CUSTOM_COMMAND(
+        OUTPUT ${_out_f}
+        COMMAND Qt4::uic
+        ARGS -o ${_out_f} ${_f}
+        MAIN_DEPENDENCY ${_f} VERBATIM
+        )
+    ENDIF(NOT ${_pos} EQUAL -1)
+  ENDIF(EXISTS ${_f})
+ENDFOREACH(_f)
+SET(${output_files} "${_out}" PARENT_SCOPE)
+ENDFUNCTION()
+
+## -------------------------------------------------------------------------
+FUNCTION(
+  PrepareSourceFiles
+  lib_name
+  out_sources_list
+  out_headers_list
+  out_headers_paths
+  )
+SET(_config_extensions .c.in .cpp.in .cxx.in .h.in .hpp.in .hxx.in .ui.in)
+SET(_sources_extensions .c .cpp .cxx)
+SET(_headers_extensions .h .hpp .hxx)
+SET(_qt_ui_extensions .ui)
+SET(_demangler_extensions .d)
+SET(_instances_extensions .i)
+
+## -- Configure inputs
+SET(_all_files)
+FOREACH(_file ${ARGN})
+  GET_FILENAME_COMPONENT(_ext ${_file} EXT)
+  LIST(FIND _config_extensions ${_ext} _cfg)
+  IF(NOT ${_cfg} EQUAL -1)
+    STRING(
+      REPLACE
+      ${PROJECT_SOURCE_DIR}
+      ${PROJECT_BINARY_DIR}
+      _file_bin
+      ${_file}
+      )
+    STRING(LENGTH ${_file_bin} _file_bin_len)
+    MATH(EXPR _file_bin_len "${_file_bin_len}-3")
+    STRING(SUBSTRING ${_file_bin} 0 ${_file_bin_len} _file_bin)
+    CONFIGURE_FILE(${_file} ${_file_bin} @ONLY)
+    LIST(APPEND _all_files ${_file_bin})
+  ELSE(NOT ${_cfg} EQUAL -1)
+    LIST(APPEND _all_files ${_file})
+  ENDIF(NOT ${_cfg} EQUAL -1)
+ENDFOREACH(_file)
+
+## -- Separate files
+SET(_srcs)
+SET(_hdrs)
+SET(_qts)
+SET(_demanglers)
+SET(_instances)
+FOREACH(_file ${_all_files})
+  GET_FILENAME_COMPONENT(_ext ${_file} EXT)
+  LIST(FIND _sources_extensions ${_ext} _src)
+  LIST(FIND _headers_extensions ${_ext} _hdr)
+  LIST(FIND _qt_ui_extensions ${_ext} _ui)
+  LIST(FIND _demangler_extensions ${_ext} _dem)
+  LIST(FIND _instances_extensions ${_ext} _ins)
+  IF(NOT ${_src} EQUAL -1)
+    LIST(APPEND _srcs ${_file})
+  ENDIF(NOT ${_src} EQUAL -1)
+  IF(NOT ${_hdr} EQUAL -1)
+    LIST(APPEND _hdrs ${_file})
+  ENDIF(NOT ${_hdr} EQUAL -1)
+  IF(NOT ${_ui} EQUAL -1)
+    LIST(APPEND _qts ${_file})
+  ENDIF(NOT ${_ui} EQUAL -1)
+  IF(NOT ${_dem} EQUAL -1)
+    LIST(APPEND _demanglers ${_file})
+  ENDIF(NOT ${_dem} EQUAL -1)
+  IF(NOT ${_ins} EQUAL -1)
+    LIST(APPEND _instances ${_file})
+  ENDIF(NOT ${_ins} EQUAL -1)
+ENDFOREACH(_file)
+
+# -- Prepare Qt4-based code
+IF(Qt4_FOUND)
+  ## -- Guess what headers sould be qt-moc'ed
+  Wrap_Qt_CPP(_moc ${_hdrs})
+  IF(_moc)
+    LIST(APPEND _srcs ${_moc})
+  ENDIF(_moc)
+
+  ## -- Guess what qt-ui's sould be qt-uic'ed
+  ## -- Wrap qt-ui headers: this is equivalent to QT4_WRAP_UI except to change
+  ## -- the output file
+  Wrap_Qt_UI(_qt_hdrs ${_qts})
+  IF(_qt_hdrs)
+    LIST(APPEND _hdrs ${_qt_hdrs})
+  ENDIF(_qt_hdrs)
+ENDIF(Qt4_FOUND)
+
+## -- Create demanglers
+FOREACH(_d ${_demanglers})
+  STRING(
+    REPLACE
+    ${PROJECT_SOURCE_DIR}
+    ${PROJECT_BINARY_DIR}
+    _d_bin
+    ${_d}
+    )
+  GET_FILENAME_COMPONENT(_d_path ${_d_bin} DIRECTORY)
+  GET_FILENAME_COMPONENT(_out_name ${_d_bin} NAME_WE)
+  SET(_d_out ${_d_path}/${_out_name}_Demanglers.h)
+  ADD_CUSTOM_COMMAND(
+    OUTPUT ${_d_out}
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${_d_path}
+    COMMAND ${cpPlugins_bash_CreateDemanglers_APP} ${_d} ${_out_name} ${_d_out}
+    DEPENDS ${cpPlugins_bash_CreateDemanglers_APP} ${_d}
+    )
+  LIST(APPEND _hdrs ${_d_out})
+ENDFOREACH(_d)
+
+## -- Create instances
+FOREACH(_i ${_instances})
+  STRING(
+    REPLACE
+    ${PROJECT_SOURCE_DIR}
+    ${PROJECT_BINARY_DIR}
+    _i_bin
+    ${_i}
+    )
+  GET_FILENAME_COMPONENT(_i_path ${_i_bin} DIRECTORY)
+  GET_FILENAME_COMPONENT(_out_name ${_i} NAME_WE)
+
+  ## -- Infere source code filenames
+  MATH(EXPR _last_range "${cpPlugins_NUMBER_OF_FILES}-1")
+  SET(_out_code)
+  FOREACH(_n RANGE 0 ${_last_range})
+    LIST(APPEND _out_code ${_i_path}/${_out_name}_${_n}.cxx)
+    LIST(APPEND _srcs ${_i_path}/${_out_name}_${_n}.cxx)
+  ENDFOREACH(_n)
+
+  ## -- Command to write source code
+  ADD_CUSTOM_COMMAND(
+    OUTPUT ${_out_code}
+    DEPENDS ${cpPlugins_bash_CreateInstances_APP} ${_i}
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${_i_path}
+    COMMAND ${cpPlugins_bash_CreateInstances_APP} ${_i} ${lib_name} ${_i_path}/${_out_name}
+    )
+ENDFOREACH(_i)
+
+## -- Real compilation
+SET(_hdrs_paths)
+FOREACH(_hdr ${_hdrs})
+  GET_FILENAME_COMPONENT(_path ${_hdr} DIRECTORY)
+  LIST(FIND _hdrs_paths ${_path} _path_idx)
+  IF(${_path_idx} EQUAL -1)
+    LIST(APPEND _hdrs_paths ${_path})
+  ENDIF(${_path_idx} EQUAL -1)
+ENDFOREACH(_hdr)
+
+SET(${out_sources_list} ${_srcs} PARENT_SCOPE)
+SET(${out_headers_list} ${_hdrs} PARENT_SCOPE)
+SET(${out_headers_paths} ${_hdrs_paths} PARENT_SCOPE)
+
+ENDFUNCTION()
+
+## -------------------------------------------------------------------------
+FUNCTION(cpPlugins_BuildLibrary lib_name lib_type)
+# -- Detect all source files
+SET(_all_files)
+FOREACH(_c ${ARGN})
+  GET_FILENAME_COMPONENT(_cname ${_c} ABSOLUTE)
+  SET(_files)
+  IF(IS_DIRECTORY ${_cname})
+    FILE(GLOB_RECURSE _files "${_cname}/*")
+  ELSE(IS_DIRECTORY ${_cname})
+    SET(_files ${_cname})
+  ENDIF(IS_DIRECTORY ${_cname})
+  LIST(APPEND _all_files ${_files})
+ENDFOREACH(_c ${ARGN})
+
+## -- Prepare sources by types
+PrepareSourceFiles(${lib_name} _srcs _hdrs _paths ${_all_files})
+
+## -- Build library
+IF(_srcs)
+  INCLUDE_DIRECTORIES(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}
+    )
+  ADD_LIBRARY(${lib_name} ${lib_type} ${_srcs} ${_hdrs})
+  GENERATE_EXPORT_HEADER(
+    ${lib_name}
+    BASE_NAME ${lib_name}
+    EXPORT_MACRO_NAME ${lib_name}_EXPORT
+    EXPORT_FILE_NAME ${lib_name}_Export.h
+    STATIC_DEFINE ${lib_name}_BUILT_AS_STATIC
+    )
+ENDIF(_srcs)
+
+ENDFUNCTION()
+
+## -------------------------------------------------------------------------
+FUNCTION(cpPlugins_BuildPluginsLibrary lib_name)
+# -- Detect all source files
+SET(_all_files)
+FOREACH(_c ${ARGN})
+  GET_FILENAME_COMPONENT(_cname ${_c} ABSOLUTE)
+  SET(_files)
+  IF(IS_DIRECTORY ${_cname})
+    FILE(GLOB_RECURSE _files "${_cname}/*")
+  ELSE(IS_DIRECTORY ${_cname})
+    SET(_files ${_cname})
+  ENDIF(IS_DIRECTORY ${_cname})
+  LIST(APPEND _all_files ${_files})
+ENDFOREACH(_c ${ARGN})
+
+## -- Prepare sources by types
+PrepareSourceFiles(${lib_name} _srcs _hdrs _paths ${_all_files})
+
+## -- Check which headers need to be wrapped to build host code
+SET(_hdrs_to_wrap)
+FOREACH(_hdr ${_hdrs})
+  IF(EXISTS ${_hdr})
+    FILE(READ ${_hdr} _txt)
+    STRING(FIND "${_txt}" "cpPluginsObject" _res)
+    IF(NOT ${_res} EQUAL -1)
+      LIST(APPEND _hdrs_to_wrap ${_hdr})
+    ENDIF(NOT ${_res} EQUAL -1)
+  ENDIF(EXISTS ${_hdr})
+ENDFOREACH(_hdr)
+
+## -- Wrap headers
+IF(_hdrs_to_wrap)
+  SET(_host ${CMAKE_CURRENT_BINARY_DIR}/${lib_name}_host.cxx)
+  ADD_CUSTOM_COMMAND(
+    OUTPUT ${_host}
+    DEPENDS ${cpPlugins_bash_HostCreator_APP} ${_hdrs_to_wrap}
+    COMMAND ${cpPlugins_bash_HostCreator_APP} ${lib_name} ${_host} ${_hdrs_to_wrap}
+    )
+  LIST(APPEND _all_files ${_host})
+ENDIF(_hdrs_to_wrap)
+
+cpPlugins_BuildLibrary(${lib_name} SHARED ${_all_files})
+ENDFUNCTION()
+
+## -------------------------------------------------------------------------
+FUNCTION(cpPlugins_BuildApplication app_name)
+OPTION(BUILD_${app_name} "Build \"${app_name}\" application?" OFF)
+IF(BUILD_${app_name})
+  # -- Detect all source files
+  SET(_all_files)
+  FOREACH(_c ${ARGN})
+    GET_FILENAME_COMPONENT(_cname ${_c} ABSOLUTE)
+    SET(_files)
+    IF(IS_DIRECTORY ${_cname})
+      FILE(GLOB_RECURSE _files "${_cname}/*")
+    ELSE(IS_DIRECTORY ${_cname})
+      SET(_files ${_cname})
+    ENDIF(IS_DIRECTORY ${_cname})
+    LIST(APPEND _all_files ${_files})
+  ENDFOREACH(_c ${ARGN})
+
+  ## -- Prepare sources by types
+  PrepareSourceFiles(${app_name} _srcs _hdrs _paths ${_all_files})
+
+  ## -- Build library
+  IF(_srcs)
+    INCLUDE_DIRECTORIES(
+      ${CMAKE_CURRENT_SOURCE_DIR}
+      ${CMAKE_CURRENT_BINARY_DIR}
+      )
+    SET(_app_os_target)
+    IF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+      SET(_app_os_target WIN32)
+      ELSEIF(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
+      SET(_app_os_target MACOSX_BUNDLE)
+    ENDIF(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+    ADD_EXECUTABLE(${app_name} ${_app_os_target} ${_srcs} ${_hdrs})
+  ENDIF(_srcs)
+ENDIF(BUILD_${app_name})
+ENDFUNCTION()
+
+## eof - $RCSfile$
diff --git a/cmake/KitwareTools.cmake b/cmake/KitwareTools.cmake
new file mode 100644 (file)
index 0000000..b4493d2
--- /dev/null
@@ -0,0 +1,19 @@
+# ======================
+# == Find ITK and VTK ==
+# ======================
+
+FIND_PACKAGE(ITK REQUIRED)
+FIND_PACKAGE(VTK REQUIRED)
+
+INCLUDE(${ITK_USE_FILE})
+INCLUDE(${VTK_USE_FILE})
+
+# ===================================================
+# == Do not use itk-vtk glue --> problems ahead!!! ==
+# ===================================================
+
+IF(ITKVtkGlue_LOADED)
+  MESSAGE(FATAL_ERROR "ITKVtkGlue module is available. Please re-compile your ITK without it. It could lead to nasty compilation problems... Just waiting for Kitware to solve it.")
+ENDIF(ITKVtkGlue_LOADED)
+
+## eof - $RCSfile$
diff --git a/cmake/Options.cmake b/cmake/Options.cmake
new file mode 100644 (file)
index 0000000..6800c63
--- /dev/null
@@ -0,0 +1,25 @@
+## ===============================
+## == Some configurable options ==
+## ===============================
+
+SET(cpPlugins_NUMBER_OF_FILES "10" CACHE STRING "Number of compiled files.")
+SET(cpPlugins_PROCESS_DIMS "1;2;3" CACHE STRING "Accepted processing dimensions.")
+SET(cpPlugins_VISUAL_DIMS "2;3" CACHE STRING "Accepted visual dimensions.")
+
+OPTION(BUILD_EXAMPLES "Build examples" OFF)
+OPTION(BUILD_QT4_COMPONENTS "Build Qt4-based code" OFF)
+
+SET(
+  _all_configs
+  cpPlugins_PROCESS_DIMS
+  cpPlugins_VISUAL_DIMS
+  )
+SET(_real_configs)
+FOREACH(_cfg ${_all_configs})
+  FOREACH(_type ${${_cfg}})
+    LIST(APPEND _real_configs "${_cfg}_${_type}")
+  ENDFOREACH(_type)
+ENDFOREACH(_cfg)
+SET(cpPlugins_ALL_CONFIGS "${_real_configs}" CACHE INTERNAL "All valid configurations." FORCE)
+
+## eof - $RCSfile$
diff --git a/cmake/QtTools.cmake b/cmake/QtTools.cmake
new file mode 100644 (file)
index 0000000..4f1e574
--- /dev/null
@@ -0,0 +1,28 @@
+## ==================================================
+## == Find Qt4 and check if it was well configured ==
+## ==================================================
+
+IF(BUILD_QT4_COMPONENTS)
+  FIND_PACKAGE(Qt4 REQUIRED)
+  INCLUDE(${QT_USE_FILE})
+  SET(
+    _modules
+    vtkGUISupportQt
+    )
+  FOREACH(_m ${_modules})
+    IF(NOT ${_m}_LOADED)
+      MESSAGE(FATAL_ERROR "${_m} module is required but not available.")
+      BREAK()
+    ENDIF(NOT ${_m}_LOADED)
+  ENDFOREACH(_m)
+  SET(
+    cpPlugins_Qt4_VTKWidget
+    QVTKWidget
+    CACHE STRING "Base Qt4-based vtkRenderWindow"
+    )
+  # ADD_DEFINITIONS(-DcpPlugins_QT4 -DcpExtensions_QT4)
+ELSE(BUILD_QT4_COMPONENTS)
+  # ADD_DEFINITIONS(-UcpPlugins_QT4 -UcpExtensions_QT4)
+ENDIF(BUILD_QT4_COMPONENTS)
+
+## eof - $RCSfile$
diff --git a/cmake/cpPluginsConfig.cmake.in b/cmake/cpPluginsConfig.cmake.in
new file mode 100644 (file)
index 0000000..2f2fdd2
--- /dev/null
@@ -0,0 +1,119 @@
+## ================================
+## == Find cpPlugins-cmake tools ==
+## ================================
+
+SET(ITK_DIR "@ITK_DIR@")
+SET(VTK_DIR "@VTK_DIR@")
+IF("@Qt4_FOUND@" STREQUAL "TRUE")
+  SET(USE_QT4 ON)
+  SET(QT_QMAKE_EXECUTABLE "@QT_QMAKE_EXECUTABLE@")
+ENDIF("@Qt4_FOUND@" STREQUAL "TRUE")
+
+## ====================
+## == Find libraries ==
+## ====================
+
+SET(
+  cpPlugins_AllInstances
+  cpInstances_BaseObjects
+  cpInstances_Images
+  cpInstances_Geometries
+  cpInstances_Extensions
+  CACHE STRING "All instances from templated code"
+  )
+MARK_AS_ADVANCED(FORCE cpPlugins_AllInstances)
+
+SET(
+  _all_libs
+  cpExtensions
+  cpPlugins
+  cpPluginsDataObjects
+  )
+IF(USE_QT4)
+  LIST(APPEND _all_libs cpBaseQtApplication)
+ENDIF(USE_QT4)
+SET(cpPlugins_Libraries ${_all_libs} CACHE STRING "cpPlugins base libraries")
+MARK_AS_ADVANCED(FORCE cpPlugins_Libraries)
+
+SET(_all_libs ${cpPlugins_AllInstances} ${cpPlugins_Libraries})
+SET(_l_locations)
+FOREACH(_l ${_all_libs})
+  FIND_LIBRARY(
+    ${_l}_LIB NAMES ${_l}
+    PATHS
+    @PROJECT_BINARY_DIR@
+    @CMAKE_INSTALL_PREFIX@/bin
+    @CMAKE_INSTALL_PREFIX@/lib
+    ${_l_locations}
+    )
+  IF(${_l}_LIB)
+    MARK_AS_ADVANCED(FORCE ${_l}_LIB)
+    GET_FILENAME_COMPONENT(_dir ${${_l}_LIB} DIRECTORY)
+    LIST(APPEND _l_locations ${_dir})
+    LIST(REMOVE_DUPLICATES _l_locations)
+  ENDIF(${_l}_LIB)
+ENDFOREACH(_l)
+IF(_l_locations)
+  LINK_DIRECTORIES(${_l_locations})
+ENDIF(_l_locations)
+
+## ==============================
+## == Find include directories ==
+## ==============================
+
+## TODO: this is not completely correct!!!
+INCLUDE_DIRECTORIES(
+  @CMAKE_INSTALL_PREFIX@/include
+  @CMAKE_INSTALL_PREFIX@/include/cpPlugins/cpInstances
+  @PROJECT_SOURCE_DIR@
+  @PROJECT_BINARY_DIR@
+  @PROJECT_SOURCE_DIR@/lib
+  @PROJECT_BINARY_DIR@/lib
+  @PROJECT_SOURCE_DIR@/lib/cpInstances
+  @PROJECT_BINARY_DIR@/lib/cpInstances
+  )
+
+## ============================
+## == Find bash applications ==
+## ============================
+
+SET(
+  _exec_programs
+  "@cpPlugins_bash_CreateRealConfig_APP@"
+  "@cpPlugins_bash_CreateInstances_APP@"
+  "@cpPlugins_bash_CreateDemanglers_APP@"
+  "@cpPlugins_bash_CreatePlugins_APP@"
+  "@cpPlugins_bash_HostCreator_APP@"
+  )
+
+SET(_b_locations)
+FOREACH(_p ${_exec_programs})
+  FIND_PROGRAM(
+    ${_p}_APP
+    NAMES ${_p}
+    HINTS /usr /usr/local
+    PATHS @CMAKE_INSTALL_PREFIX@/bin @PROJECT_BINARY_DIR@ ${_b_locations}
+    PATH_SUFFIXES bin sbin
+    DOC "Where is ${_prog}?"
+    )
+  IF(${_p}_APP)
+    MARK_AS_ADVANCED(FORCE ${_p}_APP)
+    GET_FILENAME_COMPONENT(_dir ${${_p}_APP} DIRECTORY)
+    LIST(APPEND _b_locations ${_dir})
+    LIST(REMOVE_DUPLICATES _b_locations)
+  ENDIF(${_p}_APP)
+ENDFOREACH(_p)
+
+## ==========================
+## == Configuration values ==
+## ==========================
+
+SET(cpPlugins_NUMBER_OF_FILES "@cpPlugins_NUMBER_OF_FILES@" CACHE STRING "Internal")
+SET(cpPlugins_PROCESS_DIMS "@cpPlugins_PROCESS_DIMS@" CACHE STRING "Internal")
+SET(cpPlugins_VISUAL_DIMS "@cpPlugins_VISUAL_DIMS@" CACHE STRING "Internal")
+
+MARK_AS_ADVANCED(FORCE cpPlugins_NUMBER_OF_FILES)
+MARK_AS_ADVANCED(FORCE cpPlugins_PROCESS_DIMS)
+MARK_AS_ADVANCED(FORCE cpPlugins_VISUAL_DIMS)
+
+## eof - $RCSfile$
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..52132e6
--- /dev/null
@@ -0,0 +1,73 @@
+
+## ======================
+## == Helper libraries ==
+## ======================
+
+SET(
+  _cpExtensions_components
+  cpExtensions/Config.h.in
+  cpExtensions/DataStructures
+  cpExtensions/Algorithms
+  cpExtensions/Interaction
+  cpExtensions/Visualization
+  )
+
+IF(BUILD_QT4_COMPONENTS)
+  LIST(APPEND _cpExtensions_components "cpExtensions/QT")
+ENDIF(BUILD_QT4_COMPONENTS)
+cpPlugins_BuildLibrary(cpExtensions SHARED ${_cpExtensions_components})
+TARGET_LINK_LIBRARIES(
+  cpExtensions
+  ${QT_LIBRARIES} ${ITK_LIBRARIES} ${VTK_LIBRARIES}
+  )
+
+## ============================================
+## == Explicit instances from templated code ==
+## ============================================
+
+SUBDIRS(
+  cpInstances
+  )
+
+## ==================
+## == Base library ==
+## ==================
+
+SET(_real_config ${CMAKE_CURRENT_BINARY_DIR}/cpPlugins/RealConfig.h)
+ADD_CUSTOM_COMMAND(
+  OUTPUT ${_real_config}
+  COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/cpPlugins
+  COMMAND ${cpPlugins_bash_CreateRealConfig_APP} ${_real_config}
+  DEPENDS ${cpPlugins_bash_CreateRealConfig_APP}
+  )
+SET(
+  _cpPlugins_components
+  ${_real_config}
+  cpPlugins/Config.h.in
+  cpPlugins/tinyxml2
+  cpPlugins/OS
+  cpPlugins/Pipeline
+  cpPlugins/Interface
+  )
+IF(BUILD_QT4_COMPONENTS)
+  LIST(APPEND _cpPlugins_components "cpPlugins/QT")
+ENDIF(BUILD_QT4_COMPONENTS)
+cpPlugins_BuildLibrary(cpPlugins SHARED ${_cpPlugins_components})
+TARGET_LINK_LIBRARIES(cpPlugins ${ITK_LIBRARIES} ${VTK_LIBRARIES})
+IF(BUILD_QT4_COMPONENTS)
+  TARGET_LINK_LIBRARIES(cpPlugins ${QT_LIBRARIES})
+ENDIF(BUILD_QT4_COMPONENTS)
+
+## ===================================
+## == Base library for applications ==
+## ===================================
+
+IF(BUILD_QT4_COMPONENTS)
+  cpPlugins_BuildLibrary(cpBaseQtApplication SHARED cpBaseQtApplication)
+  TARGET_LINK_LIBRARIES(
+    cpBaseQtApplication
+    cpExtensions cpPlugins
+    )
+ENDIF(BUILD_QT4_COMPONENTS)
+
+## eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/Blocker.cxx b/lib/cpBaseQtApplication/Blocker.cxx
new file mode 100644 (file)
index 0000000..634f25b
--- /dev/null
@@ -0,0 +1,67 @@
+#include <cpBaseQtApplication/Blocker.h>
+#include <QApplication>
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Blocker::
+Blocker( )
+  : QObject( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Blocker::
+~Blocker( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Blocker::
+block( )
+{
+  QApplication* app =
+    dynamic_cast< QApplication* >( QApplication::instance( ) );
+  if( app != NULL )
+  {
+    app->setOverrideCursor( Qt::WaitCursor );
+    app->installEventFilter( this );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Blocker::
+unblock( )
+{
+  QApplication* app =
+    dynamic_cast< QApplication* >( QApplication::instance( ) );
+  if( app != NULL )
+  {
+    while( app->overrideCursor( ) )
+      app->restoreOverrideCursor( );
+    app->removeEventFilter( this );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+bool cpBaseQtApplication::Blocker::
+eventFilter( QObject* obj, QEvent* event )
+{
+  return( true ); // -> Block all events
+  /* NOTE: this should be the correct implementation:
+     switch( event->type( ) )
+     {
+     //list event you want to prevent here ...
+     case QEvent::KeyPress:
+     case QEvent::KeyRelease:
+     case QEvent::MouseButtonRelease:
+     case QEvent::MouseButtonPress:
+     case QEvent::MouseButtonDblClick:
+     //...
+     return( true );
+     } // hctiws
+     return( this->QObject::eventFilter( obj, event ) );
+  */
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/Blocker.h b/lib/cpBaseQtApplication/Blocker.h
new file mode 100644 (file)
index 0000000..6e7abf8
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __cpBaseQtApplication__Blocker__h__
+#define __cpBaseQtApplication__Blocker__h__
+
+#include <cpBaseQtApplication_Export.h>
+#include <QObject>
+
+// -------------------------------------------------------------------------
+namespace cpBaseQtApplication
+{
+  /**
+   */
+  class cpBaseQtApplication_EXPORT Blocker
+    : public QObject
+  {
+  public:
+    Blocker( );
+    virtual ~Blocker( );
+
+    void block( );
+    void unblock( );
+
+  protected:
+    virtual bool eventFilter( QObject* obj, QEvent* event );
+  };
+
+} // ecapseman
+
+#endif // __cpBaseQtApplication__Blocker__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/MainHelper.h b/lib/cpBaseQtApplication/MainHelper.h
new file mode 100644 (file)
index 0000000..d850b25
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __cpBaseQtApplication__MainHelper__h__
+#define __cpBaseQtApplication__MainHelper__h__
+
+#include <cstdlib>
+#include <QApplication>
+
+// -------------------------------------------------------------------------
+#define cpBaseQtApplication_Main( _window_class_ )              \
+  int main( int argc, char* argv[] )                            \
+  {                                                             \
+    QApplication a( argc, argv );                               \
+    _window_class_ w( argc, argv );                             \
+    w.show( );                                                  \
+    return( a.exec( ) );                                        \
+  }
+
+// -------------------------------------------------------------------------
+#include <cpPlugins/Config.h>
+
+#ifdef cpPlugins_OS_Windows
+
+#  include <memory>
+#  include <vector>
+#  include <windows.h>
+#  include <shellapi.h>
+
+// -------------------------------------------------------------------------
+namespace cpBaseQtApplication
+{
+  /**
+   */
+  class Win32CommandLineConverter
+  {
+  private:
+    std::unique_ptr< char*[ ] > argv_;
+    std::vector< std::unique_ptr< char[ ] > > storage_;
+
+  public:
+    Win32CommandLineConverter( )
+      {
+        LPWSTR cmd_line = GetCommandLineW( );
+        int argc;
+        LPWSTR* w_argv = CommandLineToArgvW( cmd_line, &argc );
+        argv_ = std::unique_ptr< char*[ ] >( new char*[ argc ] );
+        storage_.reserve( argc );
+        for( int i = 0; i < argc; ++i )
+        {
+          storage_.push_back( ConvertWArg( w_argv[ i ] ) );
+          argv_[ i ] = storage_.back( ).get( );
+
+        } // rof
+        LocalFree( w_argv );
+      }
+    int argc( ) const
+      {
+        return( static_cast< int >(storage_.size( ) ) );
+      }
+    char** argv( ) const
+      {
+        return( argv_.get( ) );
+      }
+    static std::unique_ptr< char[ ] > ConvertWArg( LPWSTR w_arg )
+      {
+        int size = WideCharToMultiByte(
+          CP_UTF8, 0, w_arg, -1, nullptr, 0, nullptr, nullptr
+          );
+        std::unique_ptr< char[ ] > ret( new char[ size ] );
+        WideCharToMultiByte(
+          CP_UTF8, 0, w_arg, -1, ret.get( ), size, nullptr, nullptr
+          );
+        return( ret );
+      }
+  };
+
+} // ecapseman
+
+// -------------------------------------------------------------------------
+#  define cpBaseQtApplication_MainComplement                            \
+  int CALLBACK WinMain( HINSTANCE i, HINSTANCE p, LPSTR c, int s )      \
+  {                                                                     \
+    cpBaseQtApplication::Win32CommandLineConverter cmd_line;            \
+    return( main( cmd_line.argc( ), cmd_line.argv( ) ) );               \
+  }
+#else  // cpPlugins_OS_Windows
+#  define cpBaseQtApplication_MainComplement
+#endif // cpPlugins_OS_Windows
+
+#endif // __cpBaseQtApplication__MainHelper__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/MainWindow.cxx b/lib/cpBaseQtApplication/MainWindow.cxx
new file mode 100644 (file)
index 0000000..668eb3b
--- /dev/null
@@ -0,0 +1,309 @@
+#include <cpBaseQtApplication/MainWindow.h>
+#include <cpBaseQtApplication/Plugins/Navigator.h>
+#include <cpBaseQtApplication/Pipeline/Canvas.h>
+#include <cpExtensions/QT/ConfigurationChooser.h>
+#include <cpExtensions/QT/ActorsWidgetInterface.h>
+
+#include <QDir>
+#include <QFileDialog>
+#include <QInputDialog>
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::MainWindow::
+MainWindow( int argc, char* argv[], QWidget* parent )
+  : Superclass( parent ),
+    m_LastSaveFileName( "" ),
+    m_BaseWindowTitle( "cpBaseQtApplication" ),
+    m_Canvas( NULL ),
+    m_Navigator( NULL ),
+    m_Viewer( NULL )
+{
+  this->m_RunPath = QDir( "." ).canonicalPath( ).toStdString( );
+  this->m_Loader.GuessEnvironment( this->m_RunPath );
+  this->m_Loader.SaveEnvironment( this->m_RunPath );
+  this->_clearWorkspace( );
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::MainWindow::
+~MainWindow( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::MainWindow::
+TWorkspace* cpBaseQtApplication::MainWindow::
+workspace( )
+{
+  return( this->m_Workspace );
+}
+
+// -------------------------------------------------------------------------
+const cpBaseQtApplication::MainWindow::
+TWorkspace* cpBaseQtApplication::MainWindow::
+workspace( ) const
+{
+  return( this->m_Workspace );
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Pipeline::Canvas*
+cpBaseQtApplication::MainWindow::
+canvas( )
+{
+  return( this->m_Canvas );
+}
+
+// -------------------------------------------------------------------------
+const cpBaseQtApplication::Pipeline::Canvas*
+cpBaseQtApplication::MainWindow::
+canvas( ) const
+{
+  return( this->m_Canvas );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+setCanvas( cpBaseQtApplication::Pipeline::Canvas* c )
+{
+  this->m_Canvas = c;
+  if( this->m_Canvas != NULL )
+    this->m_Canvas->setWorkspace( this->m_Workspace );
+
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Plugins::Navigator*
+cpBaseQtApplication::MainWindow::
+navigator( )
+{
+  return( this->m_Navigator );
+}
+
+// -------------------------------------------------------------------------
+const cpBaseQtApplication::Plugins::Navigator*
+cpBaseQtApplication::MainWindow::
+navigator( ) const
+{
+  return( this->m_Navigator );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+setNavigator( cpBaseQtApplication::Plugins::Navigator* n )
+{
+  this->m_Navigator = n;
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::ActorsWidgetInterface*
+cpBaseQtApplication::MainWindow::
+viewer( )
+{
+  return( this->m_Viewer );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::QT::ActorsWidgetInterface*
+cpBaseQtApplication::MainWindow::
+viewer( ) const
+{
+  return( this->m_Viewer );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+setViewer( cpExtensions::QT::ActorsWidgetInterface* v )
+{
+  this->m_Viewer = v;
+  if( this->m_Viewer != NULL )
+  {
+    auto interactors = this->m_Viewer->GetInteractors( );
+    for( auto i : interactors )
+      this->m_Workspace->AddInteractor( i );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_loadPlugins( const std::string& filename )
+{
+  try
+  {
+    this->m_Loader.Register( filename );
+    if( this->m_Navigator != NULL )
+      this->m_Navigator->Update( );
+  }
+  catch( std::exception& err )
+  {
+    QMessageBox::critical(
+      this,
+      "Error loading plugins path",
+      err.what( )
+      );
+
+  } // yrt
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_loadPlugins( )
+{
+  QFileDialog dlg( this );
+  dlg.setFileMode( QFileDialog::ExistingFiles );
+
+  std::stringstream filter;
+  std::string suffix = std::string( cpPlugins_LIB_EXT );
+  filter << "Plugins file (*" << cpPlugins_LIB_EXT << ");;All files (*)";
+  dlg.setNameFilter( filter.str( ).c_str( ) );
+  dlg.setDefaultSuffix( suffix.c_str( ) );
+  if( !( dlg.exec( ) ) )
+    return;
+  QStringList names = dlg.selectedFiles( );
+  for( auto qIt = names.begin( ); qIt != names.end( ); ++qIt )
+    this->_loadPlugins( qIt->toStdString( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_loadPluginsFromPath( const std::string& path )
+{
+  try
+  {
+    this->m_Loader.RegisterFromDirectory( path );
+    this->m_Loader.SaveEnvironment( this->m_RunPath );
+    if( this->m_Navigator != NULL )
+      this->m_Navigator->Update( );
+  }
+  catch( std::exception& err )
+  {
+    QMessageBox::critical(
+      this,
+      "Error loading plugins path",
+      err.what( )
+      );
+
+  } // yrt
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_loadPluginsFromPath( )
+{
+  QFileDialog d( this );
+  d.setFileMode( QFileDialog::DirectoryOnly );
+  if( !( d.exec( ) ) )
+    return;
+  this->_loadPluginsFromPath( d.selectedFiles( ).begin( )->toStdString( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_clearWorkspace( )
+{
+  this->setWindowTitle( this->m_BaseWindowTitle.c_str( ) );
+  this->m_Workspace = TWorkspace::New( );
+  if( this->m_Canvas != NULL )
+  {
+    this->m_Canvas->clear( );
+    this->m_Canvas->setWorkspace( this->m_Workspace );
+
+  } // fi
+  if( this->m_Viewer != NULL )
+  {
+    // TODO: this->m_Viewer->clear( );
+    auto interactors = this->m_Viewer->GetInteractors( );
+    for( auto i : interactors )
+      this->m_Workspace->AddInteractor( i );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_saveWorkspace( const std::string& fname )
+{
+  this->m_LastSaveFileName = fname;
+  this->m_Workspace->Save( this->m_LastSaveFileName );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_saveWorkspace( )
+{
+  if( this->m_LastSaveFileName == "" )
+  {
+    QFileDialog dlg( this );
+    dlg.setFileMode( QFileDialog::AnyFile );
+    dlg.setDirectory( "." );
+    dlg.setAcceptMode( QFileDialog::AcceptSave );
+    dlg.setNameFilter(
+      QFileDialog::tr( "Workspace file (*.wxml);;All files (*)" )
+      );
+    dlg.setDefaultSuffix( QFileDialog::tr( "wxml" ) );
+    dlg.setWindowTitle( "Saving workspace" );
+    if( dlg.exec( ) )
+      this->_saveWorkspace( dlg.selectedFiles( ).begin( )->toStdString( ) );
+  }
+  else
+    this->_saveWorkspace( this->m_LastSaveFileName );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_loadWorkspace( const std::string& fname )
+{
+  try
+  {
+    this->_clearWorkspace( );
+    this->m_Workspace->Load( fname );
+    this->m_LastSaveFileName = "";
+    if( this->m_Canvas != NULL )
+      this->m_Canvas->setWorkspace( this->m_Workspace );
+  }
+  catch( std::exception& err )
+  {
+    QMessageBox::critical(
+      this,
+      QMessageBox::tr( "Error loading workspace" ),
+      QMessageBox::tr( err.what( ) )
+      );
+
+  } // yrt
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_loadWorkspace( )
+{
+  QFileDialog dlg( this );
+  dlg.setFileMode( QFileDialog::ExistingFile );
+  dlg.setDirectory( "." );
+  dlg.setNameFilter(
+    QFileDialog::tr( "Workspace file (*.wxml);;All files (*)" )
+    );
+  dlg.setDefaultSuffix( QFileDialog::tr( "wxml" ) );
+  if( !( dlg.exec( ) ) )
+    return;
+  this->_loadWorkspace( dlg.selectedFiles( ).begin( )->toStdString( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::MainWindow::
+_actorsProperties( )
+{
+  auto data =
+    dynamic_cast< cpExtensions::QT::ActorsWidgetInterface* >(
+      this->m_Viewer
+      );
+  if( data != NULL )
+  {
+    auto dlg = new cpExtensions::QT::ConfigurationChooser( this );
+    dlg->setData( data );
+    dlg->exec( );
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/MainWindow.h b/lib/cpBaseQtApplication/MainWindow.h
new file mode 100644 (file)
index 0000000..2e967d9
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef __cpBaseQtApplication__MainWindow__h__
+#define __cpBaseQtApplication__MainWindow__h__
+
+#include <cpBaseQtApplication_Export.h>
+#include <QMainWindow>
+#include <QMessageBox>
+#include <cpPlugins/Interface/Loader.h>
+#include <cpPlugins/Interface/Workspace.h>
+#include <cpBaseQtApplication/Blocker.h>
+
+// -------------------------------------------------------------------------
+#define cpBaseQtApplication_ConnectAction( _act_, _slt_ )               \
+  this->connect(                                                        \
+    this->m_UI->_act_, SIGNAL( triggered( ) ), this, SLOT( _slt_( ) )   \
+    )
+
+// -------------------------------------------------------------------------
+#define cpBaseQtApplication_Execute( _cmd_ )            \
+  {                                                     \
+    this->m_Blocker.block( );                           \
+    try                                                 \
+    {                                                   \
+      _cmd_;                                            \
+      this->m_Blocker.unblock( );                       \
+    }                                                   \
+    catch( std::exception& err )                        \
+    {                                                   \
+      this->m_Blocker.unblock( );                       \
+      QMessageBox::critical(                            \
+        this,                                           \
+        QMessageBox::tr( "Error executing filter" ),    \
+        QMessageBox::tr( err.what( ) )                  \
+        );                                              \
+    }                                                   \
+    catch( ... )                                        \
+    {                                                   \
+      this->m_Blocker.unblock( );                       \
+      QMessageBox::critical(                            \
+        this,                                           \
+        QMessageBox::tr( "Error executing filter" ),    \
+        QMessageBox::tr( "Unknown error" )              \
+        );                                              \
+    }                                                   \
+    this->m_Blocker.unblock( );                         \
+  }
+
+// -------------------------------------------------------------------------
+namespace cpExtensions { namespace QT { class ActorsWidgetInterface; } }
+
+// -------------------------------------------------------------------------
+namespace cpBaseQtApplication
+{
+  namespace Pipeline { class Canvas; }
+  namespace Plugins  { class Navigator; }
+
+  /**
+   */
+  class cpBaseQtApplication_EXPORT MainWindow
+    : public QMainWindow
+  {
+    Q_OBJECT;
+
+  public:
+    typedef MainWindow  Self;
+    typedef QMainWindow Superclass;
+
+    typedef cpPlugins::Interface::Loader    TLoader;
+    typedef cpPlugins::Interface::Workspace TWorkspace;
+
+  public:
+    explicit MainWindow(
+      int argc, char* argv[],
+      QWidget* parent = NULL
+      );
+    virtual ~MainWindow( );
+
+    TWorkspace* workspace( );
+    const TWorkspace* workspace( ) const;
+
+    Pipeline::Canvas* canvas( );
+    const Pipeline::Canvas* canvas( ) const;
+    void setCanvas( Pipeline::Canvas* c );
+
+    Plugins::Navigator* navigator( );
+    const Plugins::Navigator* navigator( ) const;
+    void setNavigator( Plugins::Navigator* n );
+
+    cpExtensions::QT::ActorsWidgetInterface* viewer( );
+    const cpExtensions::QT::ActorsWidgetInterface* viewer( ) const;
+    void setViewer( cpExtensions::QT::ActorsWidgetInterface* v );
+
+  protected:
+    template< class _TViewer >
+    _TViewer* _configureViewer( QWidget* w )
+      {
+        _TViewer* v = dynamic_cast< _TViewer* >( w );
+        if( v == NULL )
+          v = new _TViewer( );
+        return( v );
+      }
+
+  protected slots:
+    void _loadPlugins( const std::string& filename );
+    void _loadPlugins( );
+    void _loadPluginsFromPath( const std::string& path );
+    void _loadPluginsFromPath( );
+
+    void _clearWorkspace( );
+
+    void _saveWorkspace( const std::string& fname );
+    void _saveWorkspace( );
+
+    void _loadWorkspace( const std::string& fname );
+    void _loadWorkspace( );
+
+    void _actorsProperties( );
+
+  protected:
+    Blocker             m_Blocker;
+    std::string         m_RunPath;
+    TLoader             m_Loader;
+    std::string         m_LastSaveFileName;
+    TWorkspace::Pointer m_Workspace;
+
+    std::string m_BaseWindowTitle;
+
+    Pipeline::Canvas*                        m_Canvas;
+    Plugins::Navigator*                      m_Navigator;
+    cpExtensions::QT::ActorsWidgetInterface* m_Viewer;
+  };
+
+} // ecapseman
+
+#endif // __cpBaseQtApplication__MainWindow__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/Pipeline/Block.cxx b/lib/cpBaseQtApplication/Pipeline/Block.cxx
new file mode 100644 (file)
index 0000000..3d235aa
--- /dev/null
@@ -0,0 +1,418 @@
+#include <cpBaseQtApplication/Pipeline/Block.h>\r
+\r
+#include <QDialog>\r
+#include <QFontMetrics>\r
+#include <QGraphicsScene>\r
+#include <QGraphicsSceneContextMenuEvent>\r
+#include <QGraphicsWidget>\r
+#include <QMenu>\r
+#include <QMessageBox>\r
+#include <QPainter>\r
+#include <QPen>\r
+#include <QStyleOptionGraphicsItem>\r
+\r
+#include <cpBaseQtApplication/Blocker.h>\r
+#include <cpBaseQtApplication/Pipeline/Port.h>\r
+#include <cpBaseQtApplication/Pipeline/Connection.h>\r
+#include <cpPlugins/Pipeline/Widget.h>\r
+#include <cpPlugins/Pipeline/Events.h>\r
+\r
+// -------------------------------------------------------------------------\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+SelectedAndUpdated = Qt::green;\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+NotSelectedAndUpdated = Qt::blue;\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+SelectedAndNotUpdated = Qt::yellow;\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+NotSelectedAndNotUpdated = Qt::lightGray;\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::_TFilterObserver::\r
+Execute( const itk::Object* c, const itk::EventObject& e )\r
+{\r
+  typedef cpPlugins::Pipeline::Events::Modified _TModified;\r
+  const _TModified* mod_evt = dynamic_cast< const _TModified* >( &e );\r
+  if( mod_evt != NULL )\r
+  {\r
+    std::stringstream str;\r
+    str\r
+      << "(" << mod_evt->Time << "/"\r
+      << double( mod_evt->Span ) / double( 1000 ) << "s)";\r
+    this->ObservedBlock->setInfoPort( str.str( ).c_str( ) );\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Block::\r
+Block(\r
+  TFilter* filter,\r
+  QGraphicsItem* parent, QGraphicsScene* scene\r
+  )\r
+  : Superclass( parent, scene ),\r
+    m_HorzMargin( 20 ),\r
+    m_VertMargin( 5 ),\r
+    m_NamePort( NULL ),\r
+    m_InfoPort( NULL ),\r
+    m_Filter( filter )\r
+{\r
+  QPainterPath p;\r
+  p.addRoundedRect( -50, -15, 100, 30, 5, 5 );\r
+\r
+  this->setPath( p );\r
+  this->setPen( QPen( Qt::darkGreen ) );\r
+  this->setBrush( Qt::green );\r
+  this->setFlag( QGraphicsItem::ItemIsMovable );\r
+  this->setFlag( QGraphicsItem::ItemIsSelectable );\r
+\r
+  this->m_Width = this->m_HorzMargin;\r
+  this->m_Height = this->m_VertMargin;\r
+\r
+  // Configure names\r
+  this->setNamePort( filter->GetName( ) );\r
+  this->setInfoPort( "(-/-)" );\r
+  this->_setTypeInfo(\r
+    (\r
+      std::string( this->m_Filter->GetClassCategory( ) ) +\r
+      std::string( "::" ) +\r
+      std::string( this->m_Filter->GetClassName( ) )\r
+      ).c_str( )\r
+    );\r
+\r
+  // Add input ports\r
+  auto inputs = this->m_Filter->GetInputsNames( );\r
+  for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )\r
+  {\r
+    this->addInputPort(\r
+      iIt->c_str( ),\r
+      this->m_Filter->IsInputMultiple( iIt->c_str( ) )\r
+      );\r
+\r
+  } // rof\r
+\r
+  // Add output ports\r
+  auto outputs = this->m_Filter->GetOutputsNames( );\r
+  for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )\r
+    this->addOutputPort( oIt->c_str( ) );\r
+\r
+  // Add obvserver\r
+  this->m_FilterObserver = _TFilterObserver::New( );\r
+  this->m_FilterObserver->ObservedBlock = this;\r
+  this->m_FilterObserverId =\r
+    this->m_Filter->AddObserver(\r
+      cpPlugins::Pipeline::Events::Modified( ), this->m_FilterObserver\r
+      );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Block::\r
+~Block( )\r
+{\r
+  this->m_Filter->RemoveObserver( this->m_FilterObserverId );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Block::\r
+TFilter* cpBaseQtApplication::Pipeline::Block::\r
+filter( )\r
+{\r
+  return( this->m_Filter );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::Block::\r
+TFilter* cpBaseQtApplication::Pipeline::Block::\r
+filter( ) const\r
+{\r
+  return( this->m_Filter );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setNamePort( const QString& txt )\r
+{\r
+  if( this->m_NamePort == NULL )\r
+    this->m_NamePort = new NamePort( this );\r
+  this->m_NamePort->setName( txt );\r
+  this->_configPort( this->m_NamePort );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setInfoPort( const QString& txt )\r
+{\r
+  if( this->m_InfoPort == NULL )\r
+    this->m_InfoPort = new InfoPort( this );\r
+  this->m_InfoPort->setName( txt );\r
+  this->_configPort( this->m_InfoPort );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+addInputPort( const QString& txt, bool multiple )\r
+{\r
+  InputPort* ip = new InputPort( this, multiple );\r
+  ip->setExtendedName( "" );\r
+  ip->setName( txt );\r
+  this->m_InputPorts[ txt.toStdString( ) ] = ip;\r
+  this->_configPort( ip );\r
+  return( ip );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+addOutputPort( const QString& txt )\r
+{\r
+  OutputPort* op = new OutputPort( this );\r
+  op->setExtendedName( "" );\r
+  op->setName( txt );\r
+  this->m_OutputPorts[ txt.toStdString( ) ] = op;\r
+  this->_configPort( op );\r
+  return( op );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+inputPort( const QString& txt )\r
+{\r
+  auto i = this->m_InputPorts.find( txt.toStdString( ) );\r
+  if( i != this->m_InputPorts.end( ) )\r
+    return( i->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+outputPort( const QString& txt )\r
+{\r
+  auto o = this->m_OutputPorts.find( txt.toStdString( ) );\r
+  if( o != this->m_OutputPorts.end( ) )\r
+    return( o->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QString cpBaseQtApplication::Pipeline::Block::\r
+namePort( ) const\r
+{\r
+  return( this->m_NamePort->name( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+inputPort( const QString& txt ) const\r
+{\r
+  auto i = this->m_InputPorts.find( txt.toStdString( ) );\r
+  if( i != this->m_InputPorts.end( ) )\r
+    return( i->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+outputPort( const QString& txt ) const\r
+{\r
+  auto o = this->m_OutputPorts.find( txt.toStdString( ) );\r
+  if( o != this->m_OutputPorts.end( ) )\r
+    return( o->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::Block::\r
+connectOutputPortSlot( QObject* receiver, const char* slot )\r
+{\r
+  bool ok = true;\r
+  for( auto p : this->m_OutputPorts )\r
+    ok &= QObject::connect(\r
+      p.second, SIGNAL( viewData( const std::string&, bool ) ),\r
+      receiver, slot\r
+      );\r
+  return( ok );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setPos( const QPointF& pos )\r
+{\r
+  this->m_Filter->SetViewCoords( pos.x( ), pos.y( ) );\r
+  this->Superclass::setPos( pos );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setPos( qreal x, qreal y )\r
+{\r
+  this->m_Filter->SetViewCoords( x, y );\r
+  this->Superclass::setPos( x, y );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+paint(\r
+  QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget\r
+  )\r
+{\r
+  Q_UNUSED( option );\r
+  Q_UNUSED( widget );\r
+\r
+  if( this->isSelected( ) )\r
+  {\r
+    painter->setPen( QPen( Qt::darkYellow ) );\r
+    painter->setBrush( Qt::yellow );\r
+  }\r
+  else\r
+  {\r
+    painter->setPen( QPen( Qt::darkGreen ) );\r
+    painter->setBrush( Qt::green );\r
+\r
+  } // fi\r
+  painter->drawPath( this->path( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QVariant cpBaseQtApplication::Pipeline::Block::\r
+itemChange( GraphicsItemChange change, const QVariant& value )\r
+{\r
+  return( value );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+_setTypeInfo( const QString& txt )\r
+{\r
+  this->setToolTip( txt );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+_configPort( Port* port )\r
+{\r
+  port->setBlock( this );\r
+\r
+  QFontMetrics fm( this->scene( )->font( ) );\r
+  this->m_Width = 0;\r
+  foreach( QGraphicsItem* i, this->children( ) )\r
+  {\r
+    Port* p = dynamic_cast< Port* >( i );\r
+    if( p == NULL )\r
+      continue;\r
+    int w = fm.width( p->name( ) ) + ( 4 * p->radius( ) );\r
+    if( w > this->m_Width - this->m_HorzMargin )\r
+      this->m_Width = w + this->m_HorzMargin;\r
+\r
+  } // rof\r
+  int h = fm.height( );\r
+  this->m_Height = this->m_InputPorts.size( ) + this->m_OutputPorts.size( );\r
+  this->m_Height += 4;\r
+  this->m_Height *= h;\r
+\r
+  QPainterPath pth;\r
+  pth.addRoundedRect(\r
+    -this->m_Width / 2,\r
+    -this->m_Height / 2,\r
+    this->m_Width,\r
+    this->m_Height, 5, 5\r
+    );\r
+  this->setPath( pth );\r
+\r
+  int y = -this->m_Height / 2 + this->m_VertMargin + port->radius( );\r
+  foreach( QGraphicsItem* i, this->children( ) )\r
+  {\r
+    Port* p = dynamic_cast< Port* >( i );\r
+    if( p == NULL )\r
+      continue;\r
+\r
+    if(\r
+      dynamic_cast< NamePort* >( i ) != NULL ||\r
+      dynamic_cast< InfoPort* >( i ) != NULL\r
+      )\r
+    {\r
+      i->setPos( -this->m_Width / 2 + port->radius( ), y );\r
+      y += h >> 1;\r
+    }\r
+    else if( dynamic_cast< InputPort* >( i ) != NULL )\r
+      i->setPos( -this->m_Width / 2 - 2 * port->radius( ), y );\r
+    else if( dynamic_cast< OutputPort* >( i ) != NULL )\r
+      i->setPos( this->m_Width / 2, y );\r
+    y += h;\r
+\r
+  } // rof\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+mouseReleaseEvent( QGraphicsSceneMouseEvent* evt )\r
+{\r
+  if( this->m_Filter.IsNotNull( ) )\r
+    this->m_Filter->SetViewCoords(\r
+      this->scenePos( ).x( ),\r
+      this->scenePos( ).y( )\r
+      );\r
+  this->Superclass::mouseReleaseEvent( evt );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+contextMenuEvent( QGraphicsSceneContextMenuEvent* evt )\r
+{\r
+  QMenu menu;\r
+  QAction* configureAction = menu.addAction( "Configure" );\r
+  QAction* updateAction = menu.addAction( "Update" );\r
+  auto widget =\r
+    dynamic_cast< cpPlugins::Pipeline::Widget* >(\r
+      this->m_Filter.GetPointer( )\r
+      );\r
+  QAction* enableAction = NULL;\r
+  if( widget != NULL )\r
+    enableAction =\r
+      menu.addAction( ( widget->GetEnabled( ) )? "Disable": "Enable" );\r
+\r
+  QAction* selectedAction = menu.exec( evt->screenPos( ) );\r
+  if( selectedAction == configureAction )\r
+  {\r
+    auto dlg = this->m_Filter->CreateQDialog( );\r
+    if( dlg != NULL )\r
+      dlg->exec( );\r
+  }\r
+  else if( selectedAction == enableAction )\r
+  {\r
+    if( widget != NULL )\r
+      widget->SetEnabled( !( widget->GetEnabled( ) ) );\r
+  }\r
+  else if( selectedAction == updateAction )\r
+  {\r
+    cpBaseQtApplication::Blocker blocker;\r
+    blocker.block( );\r
+    try\r
+    {\r
+      this->m_Filter->Update( );\r
+      blocker.unblock( );\r
+    }\r
+    catch( std::exception& err )\r
+    {\r
+      blocker.unblock( );\r
+      QMessageBox::critical(\r
+        NULL,\r
+        QMessageBox::tr( "Error updating filter" ),\r
+        QMessageBox::tr( err.what( ) )\r
+        );\r
+\r
+    } // yrt\r
+\r
+  } // fi\r
+}\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/Block.h b/lib/cpBaseQtApplication/Pipeline/Block.h
new file mode 100644 (file)
index 0000000..a61e00e
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef __cpBaseQtApplication__Pipeline__Block__h__\r
+#define __cpBaseQtApplication__Pipeline__Block__h__\r
+\r
+#include <cpBaseQtApplication_Export.h>\r
+#include <QGraphicsPathItem>\r
+#include <itkCommand.h>\r
+#include <cpPlugins/Pipeline/ProcessObject.h>\r
+\r
+namespace cpBaseQtApplication\r
+{\r
+  namespace Pipeline\r
+  {\r
+    class Port;\r
+    class NamePort;\r
+    class InfoPort;\r
+    class InputPort;\r
+    class OutputPort;\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT Block\r
+      : public QGraphicsPathItem\r
+    {\r
+    public:\r
+      typedef Block             Self;\r
+      typedef QGraphicsPathItem Superclass;\r
+      typedef cpPlugins::Pipeline::ProcessObject TFilter;\r
+\r
+    protected:\r
+      /**\r
+       */\r
+      class _TFilterObserver\r
+        : public itk::Command\r
+      {\r
+      public:\r
+        typedef itk::SmartPointer< _TFilterObserver >       Pointer;\r
+        typedef itk::SmartPointer< const _TFilterObserver > ConstPointer;\r
+        itkNewMacro( _TFilterObserver );\r
+      public:\r
+        void Execute( itk::Object* c, const itk::EventObject& e )\r
+          { this->Execute( const_cast< const itk::Object* >( c ), e ); }\r
+        void Execute( const itk::Object* c, const itk::EventObject& e );\r
+      public:\r
+        Block* ObservedBlock;\r
+      };\r
+\r
+    public:\r
+      enum { Type = QGraphicsItem::UserType + 6 };\r
+\r
+      Block(\r
+        TFilter* filter,\r
+        QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL\r
+        );\r
+      virtual ~Block( );\r
+\r
+      TFilter* filter( );\r
+      const TFilter* filter( ) const;\r
+\r
+      void setNamePort( const QString& txt );\r
+      void setInfoPort( const QString& txt );\r
+      InputPort* addInputPort( const QString& txt, bool multiple );\r
+      OutputPort* addOutputPort( const QString& txt );\r
+\r
+      InputPort* inputPort( const QString& txt );\r
+      OutputPort* outputPort( const QString& txt );\r
+\r
+      QString namePort( ) const;\r
+      const InputPort* inputPort( const QString& txt ) const;\r
+      const OutputPort* outputPort( const QString& txt ) const;\r
+\r
+      bool connectOutputPortSlot( QObject* receiver, const char* slot );\r
+\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+      virtual void setPos( const QPointF& pos );\r
+      virtual void setPos( qreal x, qreal y );\r
+\r
+      virtual void paint(\r
+        QPainter* painter,\r
+        const QStyleOptionGraphicsItem* option,\r
+        QWidget* widget\r
+        );\r
+\r
+    protected:\r
+      QVariant itemChange( GraphicsItemChange change, const QVariant& value );\r
+      void _setTypeInfo( const QString& txt );\r
+      void _configPort( Port* port );\r
+\r
+      virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent* evt );\r
+      virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent* evt );\r
+\r
+    private:\r
+      int m_HorzMargin;\r
+      int m_VertMargin;\r
+      int m_Width;\r
+      int m_Height;\r
+\r
+      NamePort* m_NamePort;\r
+      InfoPort* m_InfoPort;\r
+      std::map< std::string, InputPort* >  m_InputPorts;\r
+      std::map< std::string, OutputPort* > m_OutputPorts;\r
+\r
+      TFilter::Pointer m_Filter;\r
+      _TFilterObserver::Pointer m_FilterObserver;\r
+      unsigned long m_FilterObserverId;\r
+\r
+      static QColor SelectedAndUpdated;\r
+      static QColor NotSelectedAndUpdated;\r
+      static QColor SelectedAndNotUpdated;\r
+      static QColor NotSelectedAndNotUpdated;\r
+    };\r
+\r
+  } // ecapseman\r
+\r
+} // ecapseman\r
+\r
+#endif // __cpBaseQtApplication__Pipeline__Block__h__\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/Canvas.cxx b/lib/cpBaseQtApplication/Pipeline/Canvas.cxx
new file mode 100644 (file)
index 0000000..8457187
--- /dev/null
@@ -0,0 +1,452 @@
+#include <cpBaseQtApplication/Pipeline/Canvas.h>
+#include <cpBaseQtApplication/Pipeline/EventFilter.h>
+#include <cpBaseQtApplication/Pipeline/Block.h>
+#include <cpBaseQtApplication/Pipeline/Connection.h>
+#include <cpBaseQtApplication/Pipeline/Port.h>
+
+#include <QDragEnterEvent>
+#include <QInputDialog>
+#include <QMessageBox>
+#include <QWheelEvent>
+#include <QTreeWidget>
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Pipeline::Canvas::
+Canvas( QWidget* parent )
+  : Superclass( parent ),
+    m_Workspace( NULL ),
+    m_ActualConnection( NULL ),
+    m_OutputPortReceiver( NULL ),
+    m_OutputPortSlot( "" )
+{
+  this->m_Scene = new QGraphicsScene( this );
+  this->setScene( this->m_Scene );
+  this->setRenderHint( QPainter::Antialiasing );
+  this->setAcceptDrops( true );
+
+  this->m_EventFilter = new EventFilter( this );
+  this->m_EventFilter->setCanvas( this );
+  this->m_EventFilter->install( this->m_Scene );
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Pipeline::Canvas::
+~Canvas( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+clear( )
+{
+  qDeleteAll( this->m_Scene->items( ) );
+  this->m_Blocks.clear( );
+  this->m_ActualConnection = NULL;
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Pipeline::Canvas::
+TWorkspace* cpBaseQtApplication::Pipeline::Canvas::
+workspace( )
+{
+  return( this->m_Workspace );
+}
+
+// -------------------------------------------------------------------------
+const cpBaseQtApplication::Pipeline::Canvas::
+TWorkspace* cpBaseQtApplication::Pipeline::Canvas::
+workspace( ) const
+{
+  return( this->m_Workspace );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+setWorkspace( TWorkspace* ws )
+{
+  if( this->m_Workspace != ws )
+  {
+    this->clear( );
+    this->m_Workspace = ws;
+
+  } // fi
+  this->_redrawWorkspace( );
+}
+
+// -------------------------------------------------------------------------
+std::string cpBaseQtApplication::Pipeline::Canvas::
+addFilter( const std::string& cat, const std::string& fil, const QPointF& pos )
+{
+  auto filter = this->m_Workspace->CreateFilter( cat, fil );
+  Block* b = new Block( filter, NULL, this->m_Scene );
+  b->setPos( pos );
+  if( this->m_OutputPortReceiver != NULL )
+    b->connectOutputPortSlot(
+      this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( )
+      );
+  std::string name = filter->GetName( );
+  this->m_Blocks[ name ] = b;
+  return( name );
+}
+
+// -------------------------------------------------------------------------
+bool cpBaseQtApplication::Pipeline::Canvas::
+connectOutputPortSlot( QObject* receiver, const char* slot )
+{
+  this->m_OutputPortReceiver = receiver;
+  this->m_OutputPortSlot = slot;
+  bool ok = true;
+  for( auto b : this->m_Blocks )
+    ok &= b.second->connectOutputPortSlot( receiver, slot );
+  return( ok );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+rename( QGraphicsItem* item )
+{
+  if( this->m_Workspace == NULL )
+    return;
+
+  Block* b = dynamic_cast< Block* >( item );
+  if( b != NULL )
+  {
+    std::string old_n = b->filter( )->GetName( );
+    bool ok;
+    std::string new_n =
+      QInputDialog::getText(
+        dynamic_cast< QWidget* >( this->parent( ) ),
+        "Change filter name",
+        "Filter name:",
+        QLineEdit::Normal,
+        old_n.c_str( ),
+        &ok
+        ).toStdString( );
+    if( ok && new_n != "" && old_n != new_n )
+    {
+      if( this->m_Workspace->RenameFilter( old_n, new_n ) )
+      {
+        auto bIt = this->m_Blocks.find( old_n );
+        this->m_Blocks[ new_n ] = bIt->second;
+        bIt->second->setNamePort( new_n.c_str( ) );
+        this->m_Blocks.erase( bIt );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+exposePort( QGraphicsItem* item )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+moveConnection( const QPointF& pnt )
+{
+  if( this->m_ActualConnection != NULL )
+  {
+     if( this->m_ActualConnection->port1( ) == NULL )
+       this->m_ActualConnection->setPos1( pnt );
+     else if( this->m_ActualConnection->port2( ) == NULL )
+       this->m_ActualConnection->setPos2( pnt );
+     this->m_ActualConnection->updatePath( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+grab( const QPointF& pnt )
+{
+  QGraphicsItem* item = this->m_Scene->itemAt( pnt );
+  OutputPort* oport = dynamic_cast< OutputPort* >( item );
+  if( oport != NULL )
+  {
+    // Start new connection
+    this->m_ActualConnection = new Connection( 0, this->m_Scene );
+    this->m_ActualConnection->setPort1( oport );
+    this->m_ActualConnection->setPos1( oport->scenePos( ) );
+    this->m_ActualConnection->setPos2( pnt );
+    this->m_ActualConnection->updatePosFromPorts( );
+    this->m_ActualConnection->updatePath( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+release( const QPointF& pnt )
+{
+  if( this->m_ActualConnection == NULL || this->m_Workspace == NULL )
+    return;
+
+  QGraphicsItem* item = this->m_Scene->itemAt( pnt );
+  InputPort* iport = dynamic_cast< InputPort* >( item );
+  OutputPort* oport =
+    dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) );
+  if( iport != NULL && oport != NULL )
+  {
+    Block* iblock = iport->block( );
+    Block* oblock = oport->block( );
+    std::string ofil = oblock->namePort( ).toStdString( );
+    std::string dfil = iblock->namePort( ).toStdString( );
+    std::string oname = oport->name( ).toStdString( );
+    std::string dname = iport->name( ).toStdString( );
+    try
+    {
+      if( this->m_Workspace->Connect( ofil, oname, dfil, dname ) )
+      {
+        this->m_ActualConnection->setPos2( iport->scenePos( ) );
+        this->m_ActualConnection->setPort2( iport );
+        this->m_ActualConnection->updatePosFromPorts( );
+        this->m_ActualConnection->updatePath( );
+      }
+      else
+        delete this->m_ActualConnection;
+    }
+    catch( std::exception& err )
+    {
+      delete this->m_ActualConnection;
+      QMessageBox::critical(
+        NULL,
+        QMessageBox::tr( "Error connecting ports" ),
+        QMessageBox::tr( err.what( ) )
+        );
+
+    } // yrt
+    this->m_ActualConnection = NULL;
+  }
+  else
+  {
+    delete this->m_ActualConnection;
+    this->m_ActualConnection = NULL;
+    
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+keyPressEvent( QKeyEvent* event )
+{
+  static const int del_key = 16777223;
+  if( this->m_Workspace == NULL )
+    return;
+
+  switch( event->key( ) )
+  {
+  case del_key:
+  {
+    // Get items to delete
+    auto _items = this->items( );
+    auto i = _items.begin( );
+    std::set< Block* > blocks_to_delete;
+    std::set< Connection* > connections_to_delete;
+    while( i != _items.end( ) )
+    {
+      if( ( *i )->isSelected( ) )
+      {
+        Block* b = dynamic_cast< Block* >( *i );
+        Connection* c = dynamic_cast< Connection* >( *i );
+        if( b != NULL )
+        {
+          blocks_to_delete.insert( b );
+          auto inputs = b->filter( )->GetInputsNames( );
+          for( auto inIt : inputs )
+          {
+            InputPort* p = b->inputPort( inIt.c_str( ) );
+            for( unsigned int j = 0; j < p->numberOfConnections( ); ++j )
+              connections_to_delete.insert( p->connection( j ) );
+
+          } // rof
+          auto outputs = b->filter( )->GetOutputsNames( );
+          for( auto outIt : outputs )
+          {
+            OutputPort* p = b->outputPort( outIt.c_str( ) );
+            auto& conns = p->connections( );
+            for( unsigned int j = 0; j < conns.size( ); ++j )
+              connections_to_delete.insert( conns[ j ] );
+
+          } // rof
+        }
+        else if( c != NULL )
+          connections_to_delete.insert( c );
+
+      } // fi
+      i++;
+
+    } // elihw
+
+    // Delete connections
+    for( auto conn : connections_to_delete )
+    {
+      OutputPort* oport = conn->port1( );
+      InputPort* iport = conn->port2( );
+      Block* oblock = oport->block( );
+      Block* iblock = iport->block( );
+      if(
+        this->m_Workspace->Disconnect(
+          oblock->namePort( ).toStdString( ),
+          oport->name( ).toStdString( ),
+          iblock->namePort( ).toStdString( ),
+          iport->name( ).toStdString( )
+          )
+        )
+        delete conn;
+
+    } // rof
+
+    // Delete blocks
+    for( auto block : blocks_to_delete )
+      if(
+        this->m_Workspace->RemoveFilter( block->namePort( ).toStdString( ) )
+        )
+        delete block;
+  }
+  break;
+  default:
+    break;
+  } // hctiws
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+wheelEvent( QWheelEvent* event )
+{
+  this->_scaleView(
+    std::pow( double( 2 ), event->delta( ) / double( 240 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+dragEnterEvent( QDragEnterEvent* event )
+{
+  const QMimeData* mime = event->mimeData( );
+  if( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) )
+    event->acceptProposedAction( );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+dragLeaveEvent( QDragLeaveEvent* event )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+dragMoveEvent( QDragMoveEvent* event )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+dropEvent( QDropEvent* event )
+{
+  if( this->m_Workspace == NULL )
+    return;
+  const QMimeData* mime = event->mimeData( );
+  if( !( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) )
+    return;
+  event->acceptProposedAction( );
+  auto tree = dynamic_cast< QTreeWidget* >( event->source( ) );
+  if( tree == NULL )
+    return;
+
+  QPointF p = this->mapToScene( event->pos( ) );
+  QList< QTreeWidgetItem* > items = tree->selectedItems( );
+  for( auto iIt = items.begin( ); iIt != items.end( ); ++iIt )
+  {
+    auto parent = ( *iIt )->parent( );
+    if( parent != NULL )
+      this->addFilter(
+        parent->text( 0 ).toStdString( ),
+        ( *iIt )->text( 0 ).toStdString( ),
+        p
+        );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+_scaleView( qreal scaleFactor )
+{
+  qreal factor = this->transform( ).
+    scale( scaleFactor, scaleFactor ).
+    mapRect( QRectF( 0, 0, 1, 1 ) ).
+    width( );
+  if( factor < qreal( 0.07 ) || factor > qreal( 100 ) )
+    return;
+  this->scale( scaleFactor, scaleFactor );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Pipeline::Canvas::
+_redrawWorkspace( )
+{
+  // Get filters names
+  if( this->m_Workspace == NULL )
+    return;
+  auto fnames = this->m_Workspace->GetFiltersNames( );
+
+  // Create blocks
+  for( auto fname : fnames )
+  {
+    auto filter = this->m_Workspace->GetFilter( fname );
+    Block* b = new Block( filter, NULL, this->m_Scene );
+    b->setPos( filter->GetViewX( ), filter->GetViewY( ) );
+    if( this->m_OutputPortReceiver != NULL )
+      b->connectOutputPortSlot(
+        this->m_OutputPortReceiver, this->m_OutputPortSlot.c_str( )
+        );
+    this->m_Blocks[ filter->GetName( ) ] = b;
+
+  } // rof
+
+  // Create connections
+  for( auto b : this->m_Blocks )
+  {
+    auto filter = b.second->filter( );
+    auto inputs = filter->GetInputsNames( );
+    for( auto in : inputs )
+    {
+      for( unsigned int id = 0; id < filter->GetInputSize( in ); ++id )
+      {
+        auto inData = filter->GetInput( in, id );
+        if( inData != NULL )
+        {
+          auto src = inData->GetSource( );
+          auto outputs = src->GetOutputsNames( );
+          std::string outName = "";
+          for( auto out : outputs )
+            if( src->GetOutput( out ) == inData )
+              outName = out;
+          auto c = this->m_Blocks.find( src->GetName( ) );
+          auto b_src = c->second;
+          auto b_des = b.second;
+          auto oport = b_src->outputPort( outName.c_str( ) );
+          auto iport = b_des->inputPort( in.c_str( ) );
+
+          auto conn = new Connection( 0, this->m_Scene );
+          conn->setPort1( oport );
+          conn->setPort2( iport );
+          conn->setPos1( oport->scenePos( ) );
+          conn->setPos2( iport->scenePos( ) );
+          conn->updatePosFromPorts( );
+          conn->updatePath( );
+
+        } // fi
+
+      } // rof
+
+    } // rof
+
+  } // rof
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/Pipeline/Canvas.h b/lib/cpBaseQtApplication/Pipeline/Canvas.h
new file mode 100644 (file)
index 0000000..bdd487c
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __cpBaseQtApplication__Pipeline__Canvas__h__
+#define __cpBaseQtApplication__Pipeline__Canvas__h__
+
+#include <cpBaseQtApplication_Export.h>
+#include <QtGui/QGraphicsView>
+#include <cpPlugins/Interface/Workspace.h>
+
+class QGraphicsScene;
+
+namespace cpBaseQtApplication
+{
+  namespace Pipeline
+  {
+    // Some other forward declarations
+    class EventFilter;
+    class Block;
+    class Connection;
+
+    /**
+     */
+    class cpBaseQtApplication_EXPORT Canvas
+      : public QGraphicsView
+    {
+      Q_OBJECT;
+
+    public:
+      typedef Canvas        Self;
+      typedef QGraphicsView Superclass;
+      typedef cpPlugins::Interface::Workspace TWorkspace;
+
+    public:
+      Canvas( QWidget* parent = 0 );
+      virtual ~Canvas( );
+
+      void clear( );
+
+      TWorkspace* workspace( );
+      const TWorkspace* workspace( ) const;
+      void setWorkspace( TWorkspace* ws );
+
+      std::string addFilter(
+        const std::string& cat, const std::string& fil,
+        const QPointF& pos = QPointF( 0, 0 )
+        );
+      bool connectOutputPortSlot( QObject* receiver, const char* slot );
+
+      void rename( QGraphicsItem* item );
+      void exposePort( QGraphicsItem* item );
+      void moveConnection( const QPointF& pnt );
+      void grab( const QPointF& pnt );
+      void release( const QPointF& pnt );
+
+    protected:
+      void keyPressEvent( QKeyEvent* event );
+      void wheelEvent( QWheelEvent* event );
+
+      void dragEnterEvent( QDragEnterEvent* event );
+      void dragLeaveEvent( QDragLeaveEvent* event );
+      void dragMoveEvent( QDragMoveEvent* event );
+      void dropEvent( QDropEvent* event );
+
+      void _scaleView( qreal scaleFactor );
+      void _redrawWorkspace( );
+
+    protected:
+      QGraphicsScene* m_Scene;
+      EventFilter* m_EventFilter;
+      TWorkspace*  m_Workspace;
+      std::map< std::string, Block* > m_Blocks;
+
+      Connection* m_ActualConnection;
+
+      QObject* m_OutputPortReceiver;
+      std::string m_OutputPortSlot;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpBaseQtApplication__Pipeline__Canvas__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/Pipeline/Connection.cxx b/lib/cpBaseQtApplication/Pipeline/Connection.cxx
new file mode 100644 (file)
index 0000000..28bd39c
--- /dev/null
@@ -0,0 +1,135 @@
+#include <cpBaseQtApplication/Pipeline/Connection.h>\r
+#include <cpBaseQtApplication/Pipeline/Port.h>\r
+\r
+#include <QBrush>\r
+#include <QGraphicsScene>\r
+#include <QPainter>\r
+#include <QPen>\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Connection::\r
+Connection( QGraphicsItem* parent, QGraphicsScene* scene )\r
+  : Superclass( parent, scene )\r
+{\r
+  this->setPen( QPen( Qt::black, 2 ) );\r
+  this->setBrush( Qt::NoBrush );\r
+  this->setZValue( -1 );\r
+  this->m_Port1 = NULL;\r
+  this->m_Port2 = NULL;\r
+  this->setFlag( QGraphicsItem::ItemIsSelectable );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Connection::\r
+~Connection( )\r
+{\r
+  if( this->m_Port1 != NULL )\r
+    this->m_Port1->removeConnection( this );\r
+  if( this->m_Port2 != NULL )\r
+    this->m_Port2->removeConnection( this );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+setPos1( const QPointF& p )\r
+{\r
+  this->m_Pos1 = p;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+setPos2( const QPointF& p )\r
+{\r
+  this->m_Pos2 = p;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+setPort1( OutputPort* p )\r
+{\r
+  if( p != NULL )\r
+  {\r
+    p->connections( ).push_back( this );\r
+    this->m_Port1 = p;\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+setPort2( InputPort* p )\r
+{\r
+  if( p != NULL )\r
+  {\r
+    p->setConnection( this );\r
+    this->m_Port2 = p;\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+updatePosFromPorts( )\r
+{\r
+  if( this->m_Port1 != NULL )\r
+    this->m_Pos1 =\r
+      this->m_Port1->scenePos( ) +\r
+      QPointF( this->m_Port1->radius( ), this->m_Port1->radius( ) );\r
+  if( this->m_Port2 != NULL )\r
+    this->m_Pos2 =\r
+      this->m_Port2->scenePos( ) +\r
+      QPointF( this->m_Port2->radius( ), this->m_Port2->radius( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+updatePath( )\r
+{\r
+  QPainterPath p;\r
+  p.moveTo( this->m_Pos1 );\r
+\r
+  qreal dx = this->m_Pos2.x( ) - this->m_Pos1.x( );\r
+  qreal dy = this->m_Pos2.y( ) - this->m_Pos1.y( );\r
+  QPointF c1( this->m_Pos1.x( ) + dx * 0.25, this->m_Pos1.y( ) + dy * 0.1 );\r
+  QPointF c2( this->m_Pos1.x( ) + dx * 0.75, this->m_Pos1.y( ) + dy * 0.9 );\r
+  p.cubicTo( c1, c2, this->m_Pos2 );\r
+\r
+  this->setPath( p );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Connection::\r
+port1( ) const\r
+{\r
+  return( this->m_Port1 );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Connection::\r
+port2( ) const\r
+{\r
+  return( this->m_Port2 );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Connection::\r
+paint(\r
+  QPainter* painter,\r
+  const QStyleOptionGraphicsItem* option,\r
+  QWidget* widget\r
+  )\r
+{\r
+  Q_UNUSED( option );\r
+  Q_UNUSED( widget );\r
+\r
+  if( this->isSelected( ) )\r
+    painter->setPen( QPen( Qt::red, 5 ) );\r
+  else\r
+    painter->setPen( QPen( Qt::black, 2 ) );\r
+  this->setBrush( Qt::NoBrush );\r
+  painter->drawPath( this->path( ) );\r
+}\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/Connection.h b/lib/cpBaseQtApplication/Pipeline/Connection.h
new file mode 100644 (file)
index 0000000..ecfc8d2
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __cpBaseQtApplication__Pipeline__Connection__h__\r
+#define __cpBaseQtApplication__Pipeline__Connection__h__\r
+\r
+#include <cpBaseQtApplication_Export.h>\r
+#include <QGraphicsPathItem>\r
+\r
+namespace cpBaseQtApplication\r
+{\r
+  namespace Pipeline\r
+  {\r
+    class InputPort;\r
+    class OutputPort;\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT Connection\r
+      : public QGraphicsPathItem\r
+    {\r
+    public:\r
+      typedef Connection     Self;\r
+      typedef QGraphicsPathItem Superclass;\r
+\r
+    public:\r
+      enum { Type = QGraphicsItem::UserType + 5 };\r
+\r
+      Connection( QGraphicsItem* parent = 0, QGraphicsScene* scene = 0 );\r
+      virtual ~Connection( );\r
+\r
+      void setPos1( const QPointF& p );\r
+      void setPos2( const QPointF& p );\r
+      void setPort1( OutputPort* p );\r
+      void setPort2( InputPort* p );\r
+      void updatePosFromPorts( );\r
+      void updatePath( );\r
+      OutputPort* port1( ) const;\r
+      InputPort* port2( ) const;\r
+\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+      virtual void paint(\r
+        QPainter* painter,\r
+        const QStyleOptionGraphicsItem* option,\r
+        QWidget* widget\r
+        );\r
+\r
+    private:\r
+      QPointF m_Pos1;\r
+      QPointF m_Pos2;\r
+      OutputPort* m_Port1;\r
+      InputPort*  m_Port2;\r
+    };\r
+\r
+  } // ecapseman\r
+\r
+} // ecapseman\r
+\r
+#endif // __cpBaseQtApplication__Pipeline__Connection__h__\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/EventFilter.cxx b/lib/cpBaseQtApplication/Pipeline/EventFilter.cxx
new file mode 100644 (file)
index 0000000..5149c60
--- /dev/null
@@ -0,0 +1,227 @@
+#include <cpBaseQtApplication/Pipeline/EventFilter.h>\r
+#include <cpBaseQtApplication/Pipeline/Canvas.h>\r
+\r
+#include <QGraphicsScene>\r
+#include <QEvent>\r
+#include <QGraphicsItem>\r
+#include <QGraphicsSceneContextMenuEvent>\r
+#include <QGraphicsSceneDragDropEvent>\r
+#include <QGraphicsSceneHelpEvent>\r
+#include <QGraphicsSceneHoverEvent>\r
+#include <QGraphicsSceneMouseEvent>\r
+#include <QGraphicsSceneMoveEvent>\r
+#include <QGraphicsSceneResizeEvent>\r
+#include <QGraphicsSceneWheelEvent>\r
+#include <QGraphicsView>\r
+#include <QInputDialog>\r
+#include <QMessageBox>\r
+\r
+// -------------------------------------------------------------------------\r
+#define cpBaseQtApplicationPipelineEventFilterCbckSWITCH( E, e )        \\r
+  case QEvent::GraphicsScene##E:                                        \\r
+  {                                                                     \\r
+    QGraphicsScene##E##Event* evt =                                     \\r
+      dynamic_cast< QGraphicsScene##E##Event* >( e );                   \\r
+    if( evt != NULL )                                                   \\r
+      this->_##E##_cbk( evt );                                          \\r
+  }                                                                     \\r
+  break;\r
+\r
+// -------------------------------------------------------------------------\r
+#define cpBaseQtApplicationPipelineEventFilterCallbackCODE( E )      \\r
+  void cpBaseQtApplication::Pipeline::EventFilter::                  \\r
+  _##E##_cbk( QGraphicsScene##E##Event* evt )\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::EventFilter::\r
+EventFilter( QObject* parent )\r
+  : Superclass( parent ),\r
+    m_Scene( NULL ),\r
+    m_Canvas( NULL )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::EventFilter::\r
+~EventFilter( )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Canvas*\r
+cpBaseQtApplication::Pipeline::EventFilter::\r
+canvas( )\r
+{\r
+  return( this->m_Canvas );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::Canvas*\r
+cpBaseQtApplication::Pipeline::EventFilter::\r
+canvas( ) const\r
+{\r
+  return( this->m_Canvas );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::EventFilter::\r
+setCanvas( cpBaseQtApplication::Pipeline::Canvas* c )\r
+{\r
+  this->m_Canvas = c;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::EventFilter::\r
+install( QGraphicsScene* s )\r
+{\r
+  s->installEventFilter( this );\r
+  this->m_Scene = s;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::EventFilter::\r
+eventFilter( QObject* o, QEvent* e )\r
+{\r
+  // Event type\r
+  switch( int( e->type( ) ) )\r
+  {\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( ContextMenu, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( DragEnter, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( DragLeave, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( DragMove, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Drop, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Help, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( HoverEnter, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( HoverLeave, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( HoverMove, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MouseDoubleClick, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MouseMove, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MousePress, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( MouseRelease, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Move, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Resize, e );\r
+    cpBaseQtApplicationPipelineEventFilterCbckSWITCH( Wheel, e );\r
+  default:\r
+    break;\r
+  } // hctiws\r
+  return( this->Superclass::eventFilter( o, e ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QGraphicsItem* cpBaseQtApplication::Pipeline::EventFilter::\r
+itemAt( const QPointF& pos )\r
+{\r
+  QList< QGraphicsItem* > items =\r
+    this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );\r
+  QGraphicsItem* ret = NULL;\r
+  foreach( QGraphicsItem* item, items )\r
+    if( item->type( ) > QGraphicsItem::UserType )\r
+      ret = item;\r
+  return( ret );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( ContextMenu )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( DragEnter )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( DragLeave )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( DragMove )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( Drop )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( Help )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( HoverEnter )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( HoverLeave )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( HoverMove )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( MouseDoubleClick )\r
+{\r
+  // Get clicked item\r
+  QGraphicsItem* item = this->itemAt( evt->scenePos( ) );\r
+  if( item == NULL )\r
+    return;\r
+\r
+  if( evt->button( ) == Qt::LeftButton )\r
+  {\r
+    if( evt->modifiers( ) == Qt::NoModifier )\r
+      this->m_Canvas->rename( item );\r
+    else if( evt->modifiers( ) == Qt::ControlModifier )\r
+      this->m_Canvas->exposePort( item );\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( MouseMove )\r
+{\r
+  this->m_Canvas->moveConnection( evt->scenePos( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( MousePress )\r
+{\r
+  switch( evt->button( ) )\r
+  {\r
+  case Qt::LeftButton: this->m_Canvas->grab( evt->scenePos( ) ); break;\r
+  default: break;\r
+  } // hctiws\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( MouseRelease )\r
+{\r
+  switch( evt->button( ) )\r
+  {\r
+  case Qt::LeftButton: this->m_Canvas->release( evt->scenePos( ) ); break;\r
+  default: break;\r
+  } // hctiws\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( Move )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( Resize )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplicationPipelineEventFilterCallbackCODE( Wheel )\r
+{\r
+}\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/EventFilter.h b/lib/cpBaseQtApplication/Pipeline/EventFilter.h
new file mode 100644 (file)
index 0000000..0243b7c
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef __cpBaseQtApplication__Pipeline__EventFilter__h__\r
+#define __cpBaseQtApplication__Pipeline__EventFilter__h__\r
+\r
+#include <cpBaseQtApplication_Export.h>\r
+#include <QObject>\r
+#include <QPointF>\r
+\r
+class QGraphicsScene;\r
+class QGraphicsSceneMouseEvent;\r
+class QGraphicsItem;\r
+class QGraphicsSceneContextMenuEvent;\r
+class QGraphicsSceneDragDropEvent;\r
+class QGraphicsSceneHelpEvent;\r
+class QGraphicsSceneHoverEvent;\r
+class QGraphicsSceneMouseEvent;\r
+class QGraphicsSceneMoveEvent;\r
+class QGraphicsSceneResizeEvent;\r
+class QGraphicsSceneWheelEvent;\r
+\r
+// -------------------------------------------------------------------------\r
+#define cpBaseQtApplicationPipelineEventFilterCallbackDCL( E )  \\r
+  void _##E##_cbk( QGraphicsScene##E##Event* e );\r
+\r
+namespace cpBaseQtApplication\r
+{\r
+  namespace Pipeline\r
+  {\r
+    class Canvas;\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT EventFilter\r
+      : public QObject\r
+    {\r
+      Q_OBJECT;\r
+\r
+    public:\r
+      typedef EventFilter  Self;\r
+      typedef QObject Superclass;\r
+\r
+    public:\r
+      explicit EventFilter( QObject* parent = 0 );\r
+      virtual ~EventFilter( );\r
+\r
+      Canvas* canvas( );\r
+      const Canvas* canvas( ) const;\r
+      void setCanvas( Canvas* c );\r
+\r
+      void install( QGraphicsScene* s );\r
+      bool eventFilter( QObject* o, QEvent* e );\r
+\r
+    private:\r
+      QGraphicsItem* itemAt( const QPointF& pos );\r
+\r
+    protected:\r
+      typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragEnterEvent;\r
+      typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragLeaveEvent;\r
+      typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragMoveEvent;\r
+      typedef QGraphicsSceneDragDropEvent QGraphicsSceneDropEvent;\r
+      typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverEnterEvent;\r
+      typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverMoveEvent;\r
+      typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverLeaveEvent;\r
+      typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseDoubleClickEvent;\r
+      typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseMoveEvent;\r
+      typedef QGraphicsSceneMouseEvent    QGraphicsSceneMousePressEvent;\r
+      typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseReleaseEvent;\r
+\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( ContextMenu );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( DragEnter );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( DragLeave );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( DragMove );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( Drop );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( Help );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( HoverEnter );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( HoverLeave );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( HoverMove );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( MouseDoubleClick );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( MouseMove );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( MousePress );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( MouseRelease );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( Move );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( Resize );\r
+      cpBaseQtApplicationPipelineEventFilterCallbackDCL( Wheel );\r
+\r
+    private:\r
+      QGraphicsScene* m_Scene;\r
+      Canvas*         m_Canvas;\r
+    };\r
+\r
+  } // ecapseman\r
+\r
+} // ecapseman\r
+\r
+#endif // __cpBaseQtApplication__Pipeline__EventFilter__h__\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/Port.cxx b/lib/cpBaseQtApplication/Pipeline/Port.cxx
new file mode 100644 (file)
index 0000000..f5b0b01
--- /dev/null
@@ -0,0 +1,358 @@
+#include <cpBaseQtApplication/Pipeline/Port.h>\r
+#include <cpBaseQtApplication/Pipeline/Connection.h>\r
+#include <cpBaseQtApplication/Pipeline/Block.h>\r
+\r
+#include <QGraphicsScene>\r
+#include <QGraphicsSceneContextMenuEvent>\r
+#include <QFontMetrics>\r
+#include <QMenu>\r
+#include <QPainter>\r
+#include <QPen>\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Port::\r
+Port( QGraphicsItem* parent, QGraphicsScene* scene )\r
+  : QObject( ),\r
+    Superclass( parent, scene ),\r
+    m_Radius( 5 ),\r
+    m_Margin( 2 )\r
+{\r
+  this->m_Label = new QGraphicsTextItem( this );\r
+  this->m_ExtendedLabel = new QGraphicsTextItem( this );\r
+  this->setExtend( false );\r
+\r
+  QPainterPath p;\r
+  p.addEllipse( 0, 0, 2 * this->m_Radius, 2 * this->m_Radius );\r
+\r
+  this->setPath( p );\r
+  this->setPen( QPen( Qt::darkRed ) );\r
+  this->setBrush( Qt::red );\r
+  this->setFlag( QGraphicsItem::ItemSendsScenePositionChanges );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Port::\r
+~Port( )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Port::\r
+setBlock( Block* b )\r
+{\r
+  this->m_Block = b;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Port::\r
+setName( const QString& n )\r
+{\r
+  this->m_Label->setPlainText( n );\r
+  this->_updateLabels( );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Port::\r
+setExtendedName( const QString& n )\r
+{\r
+  this->m_ExtendedLabel->setPlainText( n );\r
+  this->_updateLabels( );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Port::\r
+setExtend( bool extend )\r
+{\r
+  // Do nothing!\r
+  this->m_IsExtended = false;\r
+  this->m_ExtendedLabel->setVisible( false );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Port::\r
+paint(\r
+  QPainter* painter,\r
+  const QStyleOptionGraphicsItem* option,\r
+  QWidget* widget\r
+  )\r
+{\r
+  Q_UNUSED( option );\r
+  Q_UNUSED( widget );\r
+\r
+  if( this->isExtended( ) )\r
+  {\r
+    painter->setPen( QPen( Qt::darkBlue ) );\r
+    painter->setBrush( Qt::blue );\r
+  }\r
+  else\r
+  {\r
+    painter->setPen( QPen( Qt::darkRed ) );\r
+    painter->setBrush( Qt::red );\r
+\r
+  } // fi\r
+  painter->drawPath( this->path( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::NamePort::\r
+NamePort( QGraphicsItem* parent, QGraphicsScene* scene )\r
+  : Superclass( parent, scene )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::NamePort::\r
+~NamePort( )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::NamePort::\r
+isConnected( Port* other )\r
+{\r
+  return( false );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::NamePort::\r
+_updateLabels( )\r
+{\r
+  QFont font( this->scene( )->font( ) );\r
+  font.setBold( true );\r
+  this->m_Label->setFont( font );\r
+  this->m_ExtendedLabel->setFont( font );\r
+  this->setPath( QPainterPath( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InfoPort::\r
+InfoPort( QGraphicsItem* parent, QGraphicsScene* scene )\r
+  : Superclass( parent, scene )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InfoPort::\r
+~InfoPort( )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::InfoPort::\r
+isConnected( Port* other )\r
+{\r
+  return( false );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::InfoPort::\r
+_updateLabels( )\r
+{\r
+  QFont font( this->scene( )->font( ) );\r
+  font.setBold( false );\r
+  this->m_Label->setFont( font );\r
+  this->m_ExtendedLabel->setFont( font );\r
+  this->setPath( QPainterPath( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort::\r
+InputPort( QGraphicsItem* parent, bool multiple, QGraphicsScene* scene )\r
+  : Superclass( parent, scene ),\r
+    m_IsMultiple( multiple )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort::\r
+~InputPort( )\r
+{\r
+   this->m_Connection.clear( );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::InputPort::\r
+_updateLabels( )\r
+{\r
+  QFontMetrics fm( this->scene( )->font( ) );\r
+  this->m_Label->setPos( this->m_Radius * 2, -fm.height( ) / 2 );\r
+  this->m_ExtendedLabel->setPos(\r
+    -fm.width( this->extendedName( ) ) - this->m_Radius * 2,\r
+    -fm.height( ) / 2\r
+    );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::InputPort::\r
+setExtend( bool extend )\r
+{\r
+  if( this->m_Connection.size( ) == 0 )\r
+  {\r
+    this->m_IsExtended = extend;\r
+    this->m_ExtendedLabel->setVisible( extend );\r
+  }\r
+  else\r
+    this->Superclass::setExtend( false );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::InputPort::\r
+isConnected( Port* other )\r
+{\r
+  bool conn = false;\r
+  auto i = this->m_Connection.begin( );\r
+  for( ; i != this->m_Connection.end( ); ++i )\r
+    conn |= ( ( *i )->port1( ) == other && ( *i )->port2( ) == this );\r
+  return( conn );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::InputPort::\r
+setConnection( Connection* c )\r
+{\r
+  if( this->m_IsMultiple || this->m_Connection.size( ) == 0 )\r
+    this->m_Connection.push_back( c );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::InputPort::\r
+removeConnection( Connection* c )\r
+{\r
+  auto i = std::find(\r
+    this->m_Connection.begin( ),\r
+    this->m_Connection.end( ),\r
+    c\r
+    );\r
+  if( i != this->m_Connection.end( ) )\r
+  {\r
+    *i = NULL;\r
+    this->m_Connection.erase( i );\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QVariant cpBaseQtApplication::Pipeline::InputPort::\r
+itemChange( GraphicsItemChange change, const QVariant& value )\r
+{\r
+  if( change == ItemScenePositionHasChanged )\r
+  {\r
+    for(\r
+      auto i = this->m_Connection.begin( );\r
+      i != this->m_Connection.end( );\r
+      ++i\r
+      )\r
+    {\r
+      ( *i )->updatePosFromPorts( );\r
+      ( *i )->updatePath( );\r
+\r
+    } // fi\r
+\r
+  } // fi\r
+  return( value );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort::\r
+OutputPort( QGraphicsItem* parent, QGraphicsScene* scene )\r
+  : Superclass( parent, scene )\r
+{\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort::\r
+~OutputPort( )\r
+{\r
+  foreach( Connection* conn, this->m_Connections )\r
+    delete conn;\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::OutputPort::\r
+_updateLabels( )\r
+{\r
+  QFontMetrics fm( this->scene( )->font( ) );\r
+  this->m_Label->setPos(\r
+    -fm.width( this->name( ) ) - this->m_Radius * 2, -fm.height( ) / 2\r
+    );\r
+  this->m_ExtendedLabel->setPos( this->m_Radius * 2, -fm.height( ) / 2 );\r
+\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::OutputPort::\r
+removeConnection( Connection* c )\r
+{\r
+  auto i = std::find(\r
+    this->m_Connections.begin( ),\r
+    this->m_Connections.end( ),\r
+    c\r
+    );\r
+  if( i != this->m_Connections.end( ) )\r
+  {\r
+    *i = NULL;\r
+    this->m_Connections.erase( i );\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::OutputPort::\r
+setExtend( bool extend )\r
+{\r
+  this->m_IsExtended = extend;\r
+  this->m_ExtendedLabel->setVisible( extend );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::OutputPort::\r
+isConnected( Port* other )\r
+{\r
+  auto i = this->m_Connections.begin( );\r
+  bool conn = false;\r
+  for( ; i != this->m_Connections.end( ) && !conn; ++i )\r
+    conn |= ( ( *i )->port1( ) == this && ( *i )->port2( ) == other );\r
+  return( conn );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QVariant cpBaseQtApplication::Pipeline::OutputPort::\r
+itemChange( GraphicsItemChange change, const QVariant& value )\r
+{\r
+  if( change == ItemScenePositionHasChanged )\r
+  {\r
+    foreach( Connection* conn, this->m_Connections )\r
+    {\r
+      conn->updatePosFromPorts( );\r
+      conn->updatePath( );\r
+\r
+    } // rof\r
+\r
+  } // fi\r
+  return( value );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::OutputPort::\r
+contextMenuEvent( QGraphicsSceneContextMenuEvent* evt )\r
+{\r
+  if( this->m_Block == NULL )\r
+    return;\r
+  \r
+  QMenu menu;\r
+  QAction* showAction = menu.addAction( "Show" );\r
+  QAction* hideAction = menu.addAction( "Hide" );\r
+  QAction* selectedAction = menu.exec( evt->screenPos( ) );\r
+\r
+  if( selectedAction == showAction || selectedAction == hideAction )\r
+  {\r
+    std::stringstream str;\r
+    str\r
+      << this->name( ).toStdString( ) << "@"\r
+      << this->m_Block->filter( )->GetName( );\r
+    emit viewData( str.str( ), ( selectedAction == showAction ) );\r
+\r
+  } // fi\r
+}\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Pipeline/Port.h b/lib/cpBaseQtApplication/Pipeline/Port.h
new file mode 100644 (file)
index 0000000..0622925
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef __cpBaseQtApplication__Pipeline__Port__h__\r
+#define __cpBaseQtApplication__Pipeline__Port__h__\r
+\r
+#include <cpBaseQtApplication_Export.h>\r
+#include <QGraphicsPathItem>\r
+\r
+namespace cpBaseQtApplication\r
+{\r
+  namespace Pipeline\r
+  {\r
+    class Block;\r
+    class Connection;\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT Port\r
+      : public QObject,\r
+        public QGraphicsPathItem\r
+    {\r
+      Q_OBJECT;\r
+    public:\r
+      typedef Port Self;\r
+      typedef QGraphicsPathItem Superclass;\r
+\r
+      enum { Type = QGraphicsItem::UserType + 1 };\r
+\r
+    public:\r
+      Port( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );\r
+      virtual ~Port( );\r
+\r
+      void setBlock( Block* b );\r
+      inline Block* block( ) const\r
+        { return( this->m_Block ); }\r
+\r
+      virtual void setName( const QString& n );\r
+      virtual void setExtendedName( const QString& n );\r
+      inline QString name( ) const\r
+        { return( this->m_Label->toPlainText( ) ); }\r
+      inline QString extendedName( ) const\r
+        { return( this->m_ExtendedLabel->toPlainText( ) ); }\r
+\r
+      inline int radius( ) const\r
+        { return( this->m_Radius ); }\r
+\r
+      inline bool isExtended( ) const\r
+        { return( this->m_IsExtended ); }\r
+      virtual void setExtend( bool extend );\r
+\r
+      virtual bool isConnected( Port* other ) = 0;\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+      virtual void paint(\r
+        QPainter* painter,\r
+        const QStyleOptionGraphicsItem* option,\r
+        QWidget* widget\r
+        );\r
+\r
+    protected:\r
+      virtual void _updateLabels( ) { }\r
+\r
+    protected:\r
+      Block* m_Block;\r
+\r
+      int  m_Radius;\r
+      int  m_Margin;\r
+      bool m_IsExtended;\r
+\r
+      QGraphicsTextItem* m_Label;\r
+      QGraphicsTextItem* m_ExtendedLabel;\r
+    };\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT NamePort\r
+      : public Port\r
+    {\r
+      Q_OBJECT;\r
+    public:\r
+      typedef NamePort Self;\r
+      typedef Port     Superclass;\r
+\r
+      enum { Type = Superclass::Type + 1 };\r
+\r
+    public:\r
+      NamePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );\r
+      virtual ~NamePort( );\r
+\r
+      virtual bool isConnected( Port* other );\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+    protected:\r
+      virtual void _updateLabels( );\r
+    };\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT InfoPort\r
+      : public Port\r
+    {\r
+      Q_OBJECT;\r
+    public:\r
+      typedef InfoPort Self;\r
+      typedef Port     Superclass;\r
+\r
+      enum { Type = Superclass::Type + 2 };\r
+\r
+    public:\r
+      InfoPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );\r
+      virtual ~InfoPort( );\r
+\r
+      virtual bool isConnected( Port* other );\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+    protected:\r
+      virtual void _updateLabels( );\r
+    };\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT InputPort\r
+      : public Port\r
+    {\r
+      Q_OBJECT;\r
+    public:\r
+      typedef InputPort Self;\r
+      typedef Port      Superclass;\r
+\r
+      enum { Type = Superclass::Type + 3 };\r
+\r
+    public:\r
+      InputPort(\r
+        QGraphicsItem* parent,\r
+        bool multiple,\r
+        QGraphicsScene* scene = NULL\r
+        );\r
+      virtual ~InputPort( );\r
+\r
+      virtual void setExtend( bool extend );\r
+\r
+      virtual bool isConnected( Port* other );\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+      void setConnection( Connection* c );\r
+      void removeConnection( Connection* c );\r
+      inline unsigned int numberOfConnections( ) const\r
+        { return( this->m_Connection.size( ) ); }\r
+      inline Connection* connection( unsigned int i )\r
+        { return( this->m_Connection[ i ] ); }\r
+      inline const Connection* connection( unsigned int i ) const\r
+        { return( this->m_Connection[ i ] ); }\r
+      inline bool hasConnection( ) const\r
+        { return( this->m_Connection.size( ) > 0 ); }\r
+      inline bool isMultiple( ) const\r
+        { return( this->m_IsMultiple ); }\r
+\r
+    protected:\r
+      QVariant itemChange( GraphicsItemChange change, const QVariant& value );\r
+      virtual void _updateLabels( );\r
+\r
+    protected:\r
+      std::vector< Connection* > m_Connection;\r
+      bool m_IsMultiple;\r
+    };\r
+\r
+    /**\r
+     */\r
+    class cpBaseQtApplication_EXPORT OutputPort\r
+      : public Port\r
+    {\r
+      Q_OBJECT;\r
+    public:\r
+      typedef OutputPort Self;\r
+      typedef Port       Superclass;\r
+\r
+      enum { Type = Superclass::Type + 4 };\r
+\r
+    public:\r
+      OutputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );\r
+      virtual ~OutputPort( );\r
+\r
+      void removeConnection( Connection* c );\r
+      virtual void setExtend( bool extend );\r
+\r
+      virtual bool isConnected( Port* other );\r
+      inline int type( ) const\r
+        { return( this->Type ); }\r
+\r
+      inline std::vector< Connection* >& connections( )\r
+        { return( this->m_Connections ); }\r
+      inline const std::vector< Connection* >& connections( ) const\r
+        { return( this->m_Connections ); }\r
+\r
+    signals:\r
+    void viewData( const std::string& name, bool show );\r
+\r
+    protected:\r
+      QVariant itemChange( GraphicsItemChange change, const QVariant& value );\r
+      virtual void _updateLabels( );\r
+\r
+      virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent* evt );\r
+\r
+    protected:\r
+      std::vector< Connection* > m_Connections;\r
+    };\r
+\r
+  } // ecapseman\r
+\r
+} // ecapseman\r
+\r
+#endif // __cpBaseQtApplication__Pipeline__Port__h__\r
+\r
+// eof - $RCSfile$\r
diff --git a/lib/cpBaseQtApplication/Plugins/Navigator.cxx b/lib/cpBaseQtApplication/Plugins/Navigator.cxx
new file mode 100644 (file)
index 0000000..8fa3048
--- /dev/null
@@ -0,0 +1,92 @@
+#include <cpBaseQtApplication/Plugins/Navigator.h>
+#include <cpPlugins/Interface/Loader.h>
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Plugins::Navigator::
+Navigator( QWidget* parent )
+  : Superclass( parent )
+{
+  this->setDragEnabled( true );
+  this->setDragDropMode( QAbstractItemView::DragOnly );
+  this->setAlternatingRowColors( true );
+  this->_Clear( );
+}
+
+// -------------------------------------------------------------------------
+cpBaseQtApplication::Plugins::Navigator::
+~Navigator( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Plugins::Navigator::
+Update( )
+{
+  this->_Clear( );
+  this->_Update( );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Plugins::Navigator::
+_Clear( )
+{
+  this->clear( );
+  this->setColumnCount( 1 );
+  QString header_txt = "Loaded plugins";
+  if( QTreeWidgetItem* header = this->headerItem( ) )
+    header->setText( 0, header_txt );
+  else
+    this->setHeaderLabel( header_txt );
+}
+
+// -------------------------------------------------------------------------
+void cpBaseQtApplication::Plugins::Navigator::
+_Update( )
+{
+  typedef cpPlugins::Interface::Loader _TLoader;
+  _TLoader loader;
+
+  // Iterate over categories and filters
+  auto filters = loader.GetFilters( );
+  for( auto catIt : filters )
+  {
+    const char* c_cat = catIt.first.c_str( );
+
+    // Create or get category
+    QList< QTreeWidgetItem* > cat_items =
+      this->findItems( c_cat, Qt::MatchExactly | Qt::MatchRecursive );
+    QTreeWidgetItem* cat = NULL;
+    if( cat_items.size( ) == 0 )
+    {
+      cat = new QTreeWidgetItem(
+        ( QTreeWidgetItem* )( NULL ), QStringList( c_cat )
+        );
+      this->addTopLevelItem( cat );
+    }
+    else
+      cat = cat_items[ 0 ];
+
+    for( auto filIt : catIt.second )
+    {
+      const char* c_fil = filIt.c_str( );
+      QList< QTreeWidgetItem* > filter_items =
+        this->findItems( c_fil, Qt::MatchExactly | Qt::MatchRecursive );
+      auto i = filter_items.begin( );
+      auto found_i = filter_items.end( );
+      for( ; i != filter_items.end( ); ++i )
+        if( ( *i )->parent( ) == cat )
+          found_i = i;
+
+      // Add filter
+      if( found_i == filter_items.end( ) )
+        QTreeWidgetItem* filter = new QTreeWidgetItem(
+          cat, QStringList( c_fil )
+          );
+
+    } // rof
+
+  } // rof
+  this->expandAll( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpBaseQtApplication/Plugins/Navigator.h b/lib/cpBaseQtApplication/Plugins/Navigator.h
new file mode 100644 (file)
index 0000000..a4a745a
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __cpBaseQtApplication__Plugins__Navigator__h__
+#define __cpBaseQtApplication__Plugins__Navigator__h__
+
+#include <cpBaseQtApplication_Export.h>
+#include <QTreeWidget>
+
+namespace cpBaseQtApplication
+{
+  namespace Plugins
+  {
+    /**
+     */
+    class cpBaseQtApplication_EXPORT Navigator
+      : public QTreeWidget
+    {
+      Q_OBJECT;
+
+    public:
+      typedef Navigator   Self;
+      typedef QTreeWidget Superclass;
+
+    public:
+      explicit Navigator( QWidget* parent = NULL );
+      virtual ~Navigator( );
+
+      void Update( );
+
+    protected:
+      void _Clear( );
+      void _Update( );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpBaseQtApplication__Plugins__Navigator__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/BezierCurveFunction.h b/lib/cpExtensions/Algorithms/BezierCurveFunction.h
new file mode 100644 (file)
index 0000000..65c3af8
--- /dev/null
@@ -0,0 +1,77 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__
+#define __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__
+
+#include <cpExtensions/Config.h>
+#include <vector>
+#include <itkFunctionBase.h>
+#include <itkMatrix.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     * Uses the De Casteljau's algorithm.
+     */
+    template< class V >
+    class BezierCurveFunction
+      : public itk::FunctionBase< typename V::ValueType, V >
+    {
+    public:
+      typedef BezierCurveFunction                           Self;
+      typedef itk::FunctionBase< typename V::ValueType, V > Superclass;
+      typedef itk::SmartPointer< Self >                     Pointer;
+      typedef itk::SmartPointer< const Self >               ConstPointer;
+
+      typedef V                     TVector;
+      typedef typename V::ValueType TScalar;
+
+      typedef
+      itk::Matrix< TScalar, TVector::Dimension, TVector::Dimension >
+      TFrame;
+      typedef std::vector< TVector > TVectorsContainer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( BezierCurveFunction, itkFunctionBase );
+
+    public:
+      virtual void AddPoint( const TVector& v );
+      virtual unsigned int GetNumberOfPoints( ) const;
+
+      virtual TVector Evaluate( const TScalar& u ) const cpExtensions_OVERRIDE;
+      virtual TFrame EvaluateFrenetFrame( const TScalar& u ) const;
+      virtual TScalar EvaluateLength( ) const;
+
+    protected:
+      BezierCurveFunction( );
+      virtual ~BezierCurveFunction( ) { }
+
+      void _UpdateDerivative( ) const;
+
+    private:
+      // Purposely not implemented
+      BezierCurveFunction( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TVectorsContainer m_Vectors;
+      mutable Pointer   m_Derivative;
+      mutable bool      m_DerivativeUpdated;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/BezierCurveFunction.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/BezierCurveFunction.hxx b/lib/cpExtensions/Algorithms/BezierCurveFunction.hxx
new file mode 100644 (file)
index 0000000..684360f
--- /dev/null
@@ -0,0 +1,155 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__HXX__
+
+// -------------------------------------------------------------------------
+template< class V >
+void cpExtensions::Algorithms::BezierCurveFunction< V >::
+AddPoint( const TVector& v )
+{
+  this->m_Vectors.push_back( v );
+  this->m_DerivativeUpdated = false;
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class V >
+unsigned int cpExtensions::Algorithms::BezierCurveFunction< V >::
+GetNumberOfPoints( ) const
+{
+  return( this->m_Vectors.size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class V >
+typename cpExtensions::Algorithms::BezierCurveFunction< V >::
+TVector cpExtensions::Algorithms::BezierCurveFunction< V >::
+Evaluate( const TScalar& u ) const
+{
+  TVectorsContainer Q = this->m_Vectors;
+  unsigned int n = Q.size( );
+  TScalar _1u = TScalar( 1 ) - u;
+
+  for( unsigned int k = 1; k < n; k++ )
+  {
+    // CM Fixed a bug appearing under Windows : changed the stopping
+    // condition from <= to <. Otherwise, on the last step, an element out
+    // of the range of vector Q is accessed (Q[ i + 1 ])...
+    for( unsigned int i = 0; i < n - k; i++ )
+      Q[ i ] = ( Q[ i ] * _1u ) + ( Q[ i + 1 ] * u );
+
+  } // rof
+  return( Q[ 0 ] );
+}
+
+// -------------------------------------------------------------------------
+template< class V >
+typename cpExtensions::Algorithms::BezierCurveFunction< V >::
+TFrame cpExtensions::Algorithms::BezierCurveFunction< V >::
+EvaluateFrenetFrame( const TScalar& u ) const
+{
+  TFrame fr;
+  fr.Fill( TScalar( 0 ) );
+  if( TVector::Dimension == 2 )
+  {
+    this->_UpdateDerivative( );
+    this->m_Derivative->_UpdateDerivative( );
+
+    TVector vT = this->m_Derivative->Evaluate( u );
+    TScalar nvT = vT.GetNorm( );
+    if( TScalar( 0 ) < nvT )
+      vT /= nvT;
+
+    fr[ 0 ][ 0 ] = vT[ 0 ];
+    fr[ 1 ][ 0 ] = vT[ 1 ];
+
+    fr[ 0 ][ 1 ] = -vT[ 1 ];
+    fr[ 1 ][ 1 ] =  vT[ 0 ];
+  }
+  else if( TVector::Dimension == 3 )
+  {
+    this->_UpdateDerivative( );
+    this->m_Derivative->_UpdateDerivative( );
+    TVector vT = this->m_Derivative->Evaluate( u );
+    TScalar nvT = vT.GetNorm( );
+    if( nvT > TScalar( 0 ) )
+    {
+      vT /= nvT;
+      TVector vN = this->m_Derivative->m_Derivative->Evaluate( u );
+      TScalar nvN = vN.GetNorm( );
+      if( nvT > TScalar( 0 ) )
+      {
+        vN /= nvN;
+        TVector vB;
+        vB[ 0 ] = ( vT[ 1 ] * vN[ 2 ] ) - ( vT[ 2 ] * vN[ 1 ] );
+        vB[ 1 ] = ( vT[ 2 ] * vN[ 0 ] ) - ( vT[ 0 ] * vN[ 2 ] );
+        vB[ 2 ] = ( vT[ 0 ] * vN[ 1 ] ) - ( vT[ 1 ] * vN[ 0 ] );
+
+        for( unsigned int d = 0; d < 3; d++ )
+        {
+          fr[ d ][ 0 ] = vT[ d ];
+          fr[ d ][ 1 ] = vN[ d ];
+          fr[ d ][ 2 ] = vB[ d ];
+
+        } // rof
+      }
+      else
+        std::cerr << "ERROR normal" << std::endl;
+    }
+    else
+      std::cerr << "ERROR tangent" << std::endl;
+
+  } // fi
+  return( fr );
+}
+
+// -------------------------------------------------------------------------
+template< class V >
+typename cpExtensions::Algorithms::BezierCurveFunction< V >::
+TScalar cpExtensions::Algorithms::BezierCurveFunction< V >::
+EvaluateLength( ) const
+{
+  unsigned int n = this->GetNumberOfPoints( ) << 1;
+  TScalar d = TScalar( 0 );
+  TVector v0 = this->Evaluate( 0 );
+  for( unsigned int i = 1; i < n; i++ )
+  {
+    TVector v1 = this->Evaluate( TScalar( i ) / TScalar( n - 1 ) );
+    d += ( v1 - v0 ).GetNorm( );
+    v0 = v1;
+
+  } // rof
+  return( d );
+}
+
+// -------------------------------------------------------------------------
+template< class V >
+cpExtensions::Algorithms::BezierCurveFunction< V >::
+BezierCurveFunction( )
+  : Superclass( ),
+    m_DerivativeUpdated( false )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class V >
+void cpExtensions::Algorithms::BezierCurveFunction< V >::
+_UpdateDerivative( ) const
+{
+  if( this->m_DerivativeUpdated )
+    return;
+
+  this->m_Derivative = Self::New( );
+  unsigned int n = this->m_Vectors.size( ) - 1;
+  for( unsigned int i = 0; i < n; i++ )
+    this->m_Derivative->AddPoint(
+      TScalar( n ) * ( this->m_Vectors[ i + 1 ] - this->m_Vectors[ i ] )
+      );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/CPRImageFilter.h b/lib/cpExtensions/Algorithms/CPRImageFilter.h
new file mode 100644 (file)
index 0000000..ed13da3
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __cpExtensions__Algorithms__CPRImageFilter__h__
+#define __cpExtensions__Algorithms__CPRImageFilter__h__
+
+#include <vector>
+#include <itkImageToImageFilter.h>
+#include <itkJoinSeriesImageFilter.h>
+#include <cpExtensions/Algorithms/IsoImageSlicer.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TImage, class _TCurve >
+    class CPRImageFilter
+      : public itk::ImageToImageFilter< _TImage, _TImage >
+    {
+    public:
+      typedef CPRImageFilter                              Self;
+      typedef itk::ImageToImageFilter< _TImage, _TImage > Superclass;
+      typedef itk::SmartPointer< Self >                   Pointer;
+      typedef itk::SmartPointer< const Self >             ConstPointer;
+
+      typedef _TImage TImage;
+      typedef _TCurve TCurve;
+      typedef typename TCurve::TScalar TScalar;
+
+      typedef IsoImageSlicer< TImage, TScalar >      TSlicer;
+      typedef typename TSlicer::TInterpolateFunction TInterpolateFunction;
+      typedef typename TSlicer::TSliceImage          TSliceImage;
+
+      typedef itk::JoinSeriesImageFilter< TSliceImage, TImage > TJoinFilter;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( CPRImageFilter, itk::ImageToImageFilter );
+
+      itkGetConstMacro( SliceRadius, double );
+      itkGetObjectMacro( Interpolator, TInterpolateFunction );
+
+      itkSetMacro( SliceRadius, double );
+      itkSetObjectMacro( Interpolator, TInterpolateFunction );
+
+    public:
+      _TCurve* GetCurve( );
+      const _TCurve* GetCurve( ) const;
+      void SetCurve( _TCurve* curve );
+
+    protected:
+      CPRImageFilter( );
+      virtual ~CPRImageFilter( );
+
+      virtual void GenerateOutputInformation( ) cpExtensions_OVERRIDE;
+      virtual void GenerateInputRequestedRegion( ) cpExtensions_OVERRIDE;
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+    protected:
+      double m_SliceRadius;
+      typename TInterpolateFunction::Pointer m_Interpolator;
+
+      std::vector< typename TSlicer::Pointer > m_Slicers;
+      typename TJoinFilter::Pointer            m_Join;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/CPRImageFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__CPRImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/CPRImageFilter.hxx b/lib/cpExtensions/Algorithms/CPRImageFilter.hxx
new file mode 100644 (file)
index 0000000..de76e7f
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __cpExtensions__Algorithms__CPRImageFilter__hxx__
+#define __cpExtensions__Algorithms__CPRImageFilter__hxx__
+
+#include <itkMinimumMaximumImageCalculator.h>
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+_TCurve* cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+GetCurve( )
+{
+  return(
+    dynamic_cast< _TCurve* >( this->itk::ProcessObject::GetInput( 1 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+const _TCurve* cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+GetCurve( ) const
+{
+  return(
+    dynamic_cast< const _TCurve* >( this->itk::ProcessObject::GetInput( 1 ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+SetCurve( _TCurve* curve )
+{
+  this->itk::ProcessObject::SetNthInput( 1, curve );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+CPRImageFilter( )
+  : Superclass( ),
+    m_SliceRadius( 0 )
+{
+  this->Superclass::SetNumberOfRequiredInputs( 2 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+~CPRImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+GenerateOutputInformation( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+GenerateInputRequestedRegion( )
+{
+  TImage* input = const_cast< TImage* >( this->GetInput( ) );
+  if( input != NULL )
+    input->SetRequestedRegionToLargestPossibleRegion( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TCurve >
+void cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve >::
+GenerateData( )
+{
+  typedef itk::MinimumMaximumImageCalculator< _TImage > _TMinMax;
+
+  auto input = this->GetInput( );
+  auto curve = this->GetCurve( );
+  auto output = this->GetOutput( );
+
+  // Compute image intensity range
+  typename _TMinMax::Pointer minmax = _TMinMax::New( );
+  minmax->SetImage( input );
+  minmax->Compute( );
+
+  // Main loop
+  this->m_Join = TJoinFilter::New( );
+  this->m_Slicers.clear( );
+  unsigned long N = curve->GetNumberOfPoints( );
+  double len = 0;
+  typename _TCurve::TPoint p, q;
+  for( unsigned long n = 0; n < N; ++n )
+  {
+    p = curve->GetPoint( n );
+    if( n > 0 )
+      len += p.EuclideanDistanceTo( q );
+    q = p;
+
+    // Prepare slicer
+    typename TSlicer::Pointer slicer = TSlicer::New( );
+    slicer->SetInput( input );
+    slicer->SetDefaultValue( minmax->GetMinimum( ) );
+    slicer->SpacingFromMinimumOn( );
+    if( this->m_Interpolator.IsNotNull( ) )
+      slicer->SetInterpolator( this->m_Interpolator );
+    slicer->SizeFromMaximumOff( );
+    if( this->m_SliceRadius > double( 0 ) )
+    {
+      slicer->SizeFromMinimumOff( );
+      slicer->SetSize( this->m_SliceRadius );
+    }
+    else
+      slicer->SizeFromMinimumOn( );
+    slicer->SetTranslation( p );
+    slicer->SetRotation( curve->GetFrame( n ) );
+    slicer->Update( );
+
+    this->m_Join->SetInput( n, slicer->GetOutput( ) );
+    this->m_Slicers.push_back( slicer );
+
+  } // rof
+  this->m_Join->SetSpacing( len / double( N ) );
+  this->m_Join->Update( );
+  this->GetOutput( )->Graft( this->m_Join->GetOutput( ) );
+}
+
+#endif // __cpExtensions__Algorithms__CPRImageFilter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/FluxMedialness.h b/lib/cpExtensions/Algorithms/FluxMedialness.h
new file mode 100644 (file)
index 0000000..c25f5f4
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__
+#define __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__
+
+#include <cpExtensions/Algorithms/GradientImageFunctionBase.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > >
+    class FluxMedialness
+      : public GradientImageFunctionBase< _TGradient, _TMask >
+    {
+    public:
+      typedef FluxMedialness                                  Self;
+      typedef GradientImageFunctionBase< _TGradient, _TMask > Superclass;
+      typedef itk::SmartPointer< Self >                       Pointer;
+      typedef itk::SmartPointer< const Self >                 ConstPointer;
+
+      itkStaticConstMacro( Dimension, unsigned int, Superclass::Dimension );
+
+      typedef typename Superclass::TOutput TOutput;
+      typedef typename Superclass::TScalar TScalar;
+      typedef typename Superclass::TIndex  TIndex;
+      typedef typename Superclass::TVector TVector;
+      typedef typename Superclass::TPoint  TPoint;
+
+      typedef std::vector< double > TRCandidates;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( FluxMedialness, GradientImageFunctionBase );
+
+      itkGetConstMacro( RadiusStep, double );
+      itkGetConstMacro( MinRadius, double );
+      itkGetConstMacro( MaxRadius, double );
+      itkGetConstMacro( RadialSampling, unsigned int );
+
+      itkSetMacro( RadiusStep, double );
+      itkSetMacro( MinRadius, double );
+      itkSetMacro( MaxRadius, double );
+      itkSetMacro( RadialSampling, unsigned int );
+
+    protected:
+      FluxMedialness( );
+      virtual ~FluxMedialness( );
+
+      virtual TOutput _Evaluate( const TIndex& i ) const cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented.
+      FluxMedialness( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      double       m_MinRadius;
+      double       m_MaxRadius;
+      unsigned int m_RadialSampling;
+      double       m_RadiusStep;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/FluxMedialness.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/FluxMedialness.hxx b/lib/cpExtensions/Algorithms/FluxMedialness.hxx
new file mode 100644 (file)
index 0000000..4412292
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__
+
+#include <cmath>
+#include <vnl/vnl_math.h>
+#include <itkLineConstIterator.h>
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >::
+FluxMedialness( )
+  : Superclass( ),
+    m_MinRadius( double( 0 ) ),
+    m_MaxRadius( double( 1 ) ),
+    m_RadialSampling( 4 ),
+    m_RadiusStep( double( 1 ) )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >::
+~FluxMedialness( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+typename cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >::
+TOutput cpExtensions::Algorithms::FluxMedialness< _TGradient, _TMask >::
+_Evaluate( const TIndex& i ) const
+{
+  itk::Object::GlobalWarningDisplayOff( );
+
+  double pi2n = double( 2 ) * double( vnl_math::pi );
+  pi2n /= int( this->m_RadialSampling );
+  const _TGradient* img = this->GetInputImage( );
+  // Gradient in central pixel
+  //TVector grad_idx = img->GetPixel( i );
+
+  double Flux1 = 0;
+  double Flux = 0;
+
+  TRCandidates FluxFinal;
+  TRCandidates radiusGenerated;
+  double dR = double( 0 );
+  double optR = double( 0 );
+  TPoint center;
+  img->TransformIndexToPhysicalPoint( i, center );
+  double radius = double(0);
+
+  for( unsigned int cx = 0; cx < Self::Dimension - 1; cx++ )
+  {
+    for( unsigned int cy = cx + 1; cy < Self::Dimension; cy++ )
+    {
+      dR = double( 0 );
+      FluxFinal.clear();
+      radiusGenerated.clear();
+      radius = this->m_MinRadius;
+      while( radius <= this->m_MaxRadius )
+      {
+        Flux = 0;
+        for( unsigned int I_radial = 0; I_radial < this->m_RadialSampling ; I_radial++ )
+        {
+          Flux1 = 0;
+
+          // Direction of first profile
+          typename TPoint::VectorType dir1;
+          dir1.Fill( double( 0 ) );
+          dir1[ cx ] = std::cos( pi2n * double( I_radial ) );
+          dir1[ cy ] = std::sin( pi2n * double( I_radial ) );
+          dir1 *= (radius);
+          TIndex rIdx;
+          if (img->TransformPhysicalPointToIndex( center + dir1, rIdx ))
+          {
+            TVector grad_rIdx = img->GetPixel( rIdx );
+            TVector u_i1;
+            u_i1.SetVnlVector( ( center - ( center + dir1 ) ).GetVnlVector( ) );
+            u_i1.Normalize( );
+            // dot product
+            Flux1 = grad_rIdx * u_i1;
+          }
+
+          Flux += Flux1;
+
+        } // rof
+        //std::cout<<" radius:"<<radius<<std::endl;
+        //std::cout<<"Center:"<<center[0]<<" "<<center[1]<<std::endl;
+        //std::cout<<"edge:"<<center[0]+radius*std::cos( pi2n * double( 0 ) )<<std::endl;
+        Flux /= this->m_RadialSampling;
+        FluxFinal.push_back(Flux);
+        radiusGenerated.push_back(radius);
+        radius += this->m_RadiusStep;
+
+      }     //elihw
+
+      dR= *( std::max_element( FluxFinal.begin(), FluxFinal.end() ) );
+      optR= (dR>optR)? dR:optR;
+
+    } // rof
+
+  } // rof
+  return( TScalar(optR) );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h b/lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h
new file mode 100644 (file)
index 0000000..308b3c5
--- /dev/null
@@ -0,0 +1,103 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__
+
+#include <itkImageToImageFilter.h>
+#include <itkImageScanlineConstIterator.h>
+#include <itkImageScanlineIterator.h>
+#include <itkProgressReporter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TInputImage, class _TEstimator >
+    class GaussianDensityImageFilter
+      : public itk::ImageToImageFilter< _TInputImage, itk::Image< typename _TEstimator::TScalar, _TInputImage::ImageDimension > >
+    {
+    public:
+      typedef typename _TEstimator::TScalar                         TScalar;
+      typedef itk::Image< TScalar, _TInputImage::ImageDimension >   TOutputImage;
+      typedef GaussianDensityImageFilter                            Self;
+      typedef itk::ImageToImageFilter< _TInputImage, TOutputImage > Superclass;
+      typedef itk::SmartPointer< Self >                             Pointer;
+      typedef itk::SmartPointer< const Self >                       ConstPointer;
+
+      typedef _TInputImage TInputImage;
+      typedef _TEstimator  TEstimator;
+      typedef typename TOutputImage::RegionType TRegion;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( GaussianDensityImageFilter, itkImageToImageFilter );
+
+      itkGetConstObjectMacro( Estimator, TEstimator );
+      itkSetConstObjectMacro( Estimator, TEstimator );
+
+    protected:
+      GaussianDensityImageFilter( )
+        : Superclass( )
+        {
+        }
+      virtual ~GaussianDensityImageFilter( )
+        {
+        }
+
+      virtual void ThreadedGenerateData(
+        const TRegion& region,
+        itk::ThreadIdType threadId
+        )
+        {
+          const typename TRegion::SizeType& regionSize = region.GetSize( );
+          if( regionSize[ 0 ] == 0 )
+            return;
+          const TInputImage* in = this->GetInput( );
+          TOutputImage* out = this->GetOutput( 0 );
+
+          const size_t nLines = region.GetNumberOfPixels( ) / regionSize[ 0 ];
+          itk::ProgressReporter progress( this, threadId, nLines );
+
+          // Define the iterators
+          itk::ImageScanlineConstIterator< TInputImage > inIt( in, region );
+          itk::ImageScanlineIterator< TOutputImage > outIt( out, region );
+
+          inIt.GoToBegin( );
+          outIt.GoToBegin( );
+          while( !inIt.IsAtEnd( ) )
+          {
+            while( !inIt.IsAtEndOfLine( ) )
+            {
+              if( this->m_Estimator.IsNotNull( ) )
+                outIt.Set( this->m_Estimator->Density( inIt.Get( ) ) );
+              ++inIt;
+              ++outIt;
+
+            } // elihw
+            inIt.NextLine( );
+            outIt.NextLine( );
+            progress.CompletedPixel( );
+
+          } // elihw
+        }
+
+    private:
+      // Purposely not implemented.
+      GaussianDensityImageFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      typename TEstimator::ConstPointer m_Estimator;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/GradientImageFunctionBase.h b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.h
new file mode 100644 (file)
index 0000000..7350495
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__
+#define __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__
+
+#include <cpExtensions/Config.h>
+#include <itkImage.h>
+#include <itkImageFunction.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     * Base class to compute values based on image gradients (vector).
+     */
+    template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > >
+    class GradientImageFunctionBase
+      : public itk::ImageFunction< _TGradient, typename _TGradient::PixelType::ValueType, typename _TGradient::PixelType::ValueType >
+    {
+    public:
+      // Types from input arguments
+      typedef _TGradient                     TGradient;
+      typedef _TMask                         TMask;
+      typedef typename _TGradient::PixelType TVector;
+      typedef typename TVector::ValueType    TScalar;
+      itkStaticConstMacro(
+        Dimension, unsigned int, _TGradient::ImageDimension
+        );
+
+      // Standard itk types
+      typedef GradientImageFunctionBase                          Self;
+      typedef itk::ImageFunction< _TGradient, TScalar, TScalar > Superclass;
+      typedef itk::SmartPointer< Self >                          Pointer;
+      typedef itk::SmartPointer< const Self >                    ConstPointer;
+
+      // Types from base itk::ImageFunction
+      typedef typename Superclass::InputType           TInput;
+      typedef typename Superclass::OutputType          TOutput;
+      typedef typename Superclass::PointType           TPoint;
+      typedef typename Superclass::ContinuousIndexType TContIndex;
+      typedef typename Superclass::IndexType           TIndex;
+
+    public:
+      itkTypeMacro( GradientImageFunctionBase, itkImageFunction );
+
+      itkGetConstObjectMacro( Mask, TMask );
+      itkSetConstObjectMacro( Mask, TMask );
+
+    public:
+      virtual void Prepare( ) const;
+      virtual TOutput Evaluate( const TPoint& p ) const cpExtensions_OVERRIDE;
+      virtual TOutput EvaluateAtIndex( const TIndex& i ) const cpExtensions_OVERRIDE;
+      virtual TOutput EvaluateAtContinuousIndex( const TContIndex& i ) const cpExtensions_OVERRIDE;
+
+    protected:
+      GradientImageFunctionBase( );
+      virtual ~GradientImageFunctionBase( );
+
+      virtual TOutput _Evaluate( const TIndex& i ) const = 0;
+
+    private:
+      // Purposely not implemented.
+      GradientImageFunctionBase( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      typename _TMask::ConstPointer m_Mask;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/GradientImageFunctionBase.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx
new file mode 100644 (file)
index 0000000..a858650
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+void
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+Prepare( ) const
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+typename
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+TOutput
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+Evaluate( const TPoint& p ) const
+{
+  TIndex i;
+  this->GetInputImage( )->TransformPhysicalPointToIndex( p, i );
+  return( this->EvaluateAtIndex( i ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+typename
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+TOutput
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+EvaluateAtIndex( const TIndex& i ) const
+{
+  bool eval = true;
+  if( this->m_Mask.IsNotNull( ) )
+    eval = ( ( unsigned long )( this->m_Mask->GetPixel( i ) ) > 0 );
+  if( eval )
+    return( this->_Evaluate( i ) );
+  else
+    return( TOutput( -1 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+typename
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+TOutput
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+EvaluateAtContinuousIndex( const TContIndex& i ) const
+{
+  TPoint p;
+  this->GetInputImage( )->TransformContinuousIndexToPhysicalPoint( i, p );
+  return( this->Evaluate( p ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+GradientImageFunctionBase( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient, _TMask >::
+~GradientImageFunctionBase( )
+{
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/GulsunTekMedialness.h b/lib/cpExtensions/Algorithms/GulsunTekMedialness.h
new file mode 100644 (file)
index 0000000..15add9e
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__
+#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__
+
+#include <cpExtensions/Algorithms/GradientImageFunctionBase.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > >
+    class GulsunTekMedialness
+      : public GradientImageFunctionBase< _TGradient, _TMask >
+    {
+    public:
+      typedef GulsunTekMedialness                             Self;
+      typedef GradientImageFunctionBase< _TGradient, _TMask > Superclass;
+      typedef itk::SmartPointer< Self >                       Pointer;
+      typedef itk::SmartPointer< const Self >                 ConstPointer;
+
+      itkStaticConstMacro( Dimension, unsigned int, Superclass::Dimension );
+
+      typedef typename Superclass::TOutput TOutput;
+      typedef typename Superclass::TScalar TScalar;
+      typedef typename Superclass::TIndex  TIndex;
+      typedef typename Superclass::TVector TVector;
+      typedef typename Superclass::TPoint  TPoint;
+      typedef typename TIndex::OffsetType  TOffset;
+
+      typedef std::vector< double >  TProfile;
+      typedef std::vector< TOffset > TOffsets;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( GulsunTekMedialness, GradientImageFunctionBase );
+
+      itkGetConstMacro( MinRadius, double );
+      itkGetConstMacro( MaxRadius, double );
+      itkGetConstMacro( ProfileSampling, unsigned int );
+      itkGetConstMacro( RadialSampling, unsigned int );
+
+      itkSetMacro( MinRadius, double );
+      itkSetMacro( MaxRadius, double );
+      itkSetMacro( ProfileSampling, unsigned int );
+      itkSetMacro( RadialSampling, unsigned int );
+
+    protected:
+      GulsunTekMedialness( );
+      virtual ~GulsunTekMedialness( );
+
+      virtual TOutput _Evaluate( const TIndex& i ) const cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented.
+      GulsunTekMedialness( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      double       m_MinRadius;
+      double       m_MaxRadius;
+      unsigned int m_ProfileSampling;
+      unsigned int m_RadialSampling;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/GulsunTekMedialness.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx b/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx
new file mode 100644 (file)
index 0000000..fc59929
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__
+
+#include <cmath>
+#include <vnl/vnl_math.h>
+#include <itkLineConstIterator.h>
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >::
+GulsunTekMedialness( )
+  : Superclass( ),
+    m_MinRadius( double( 0 ) ),
+    m_MaxRadius( double( 1 ) ),
+    m_ProfileSampling( 4 ),
+    m_RadialSampling( 10 )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >::
+~GulsunTekMedialness( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+typename cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >::
+TOutput cpExtensions::Algorithms::GulsunTekMedialness< _TGradient, _TMask >::
+_Evaluate( const TIndex& i ) const
+{
+  itk::Object::GlobalWarningDisplayOff( );
+
+  // Various values
+  const _TGradient* in = this->GetInputImage( );
+  double pi2n =
+    double( 2 ) * double( vnl_math::pi ) /
+    double( this->m_ProfileSampling );
+  double rOff = this->m_MaxRadius / double( this->m_RadialSampling - 1 );
+  double optR = double( 0 );
+  TPoint pnt;
+  in->TransformIndexToPhysicalPoint( i, pnt );
+
+  // Main loop
+  for( unsigned int cx = 0; cx < Self::Dimension - 1; cx++ )
+  {
+    for( unsigned int cy = cx + 1; cy < Self::Dimension; cy++ )
+    {
+      TProfile maxProfile( this->m_RadialSampling, double( 0 ) );
+      for( unsigned int p = 0; p < this->m_ProfileSampling; p++ )
+      {
+        double a = pi2n * double( p );
+
+        // Direction of this profile
+        TVector dir;
+        dir.Fill( TScalar( 0 ) );
+        dir[ cx ] = TScalar( std::cos( a ) );
+        dir[ cy ] = TScalar( std::sin( a ) );
+
+        double maxrise = double( 0 );
+        double maxfall = double( -1 );
+        TProfile profile;
+        for( unsigned int r = 0; r < this->m_RadialSampling; r++ )
+        {
+          double radius = double( r ) * rOff;
+          TIndex idx;
+          typename TPoint::VectorType aux;
+          aux.SetVnlVector( dir.GetVnlVector( ) );
+          if(
+            in->TransformPhysicalPointToIndex( pnt + ( aux * radius ), idx )
+            )
+          {
+            TVector g = in->GetPixel( idx );
+            double b = double( g.GetNorm( ) );
+            if( double( g * dir ) < double( 0 ) )
+              b *= double( -1 );
+            maxrise = ( b > maxrise )? b: maxrise;
+            if( radius >= this->m_MinRadius )
+              maxfall = ( b < maxfall )? b: maxfall;
+            profile.push_back( -b - maxrise );
+          }
+          else
+            profile.push_back( double( 0 ) );
+
+        } // rof
+
+        for( unsigned int r = 0; r < this->m_RadialSampling; r++ )
+        {
+          double E = profile[ r ] / -maxfall;
+          E = ( E < double( 0 ) )? double( 0 ): E;
+          E = ( E > double( 1 ) )? double( 1 ): E;
+          maxProfile[ r ] += E;
+
+        } // rof
+
+      } // rof
+
+      for( unsigned int r = 0; r < this->m_RadialSampling; r++ )
+      {
+        double E = maxProfile[ r ] / double( this->m_RadialSampling );
+        optR = ( E > optR )? E: optR;
+
+      } // rof
+
+    } // rof
+
+  } // rof
+  return( TScalar( optR ) );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageBlender.cxx b/lib/cpExtensions/Algorithms/ImageBlender.cxx
new file mode 100644 (file)
index 0000000..5a12cd0
--- /dev/null
@@ -0,0 +1,234 @@
+#include <cpExtensions/Algorithms/ImageBlender.h>
+
+#include <vtkDataObject.h>
+#include <vtkImageData.h>
+#include <vtkImageIterator.h>
+#include <vtkImageProgressIterator.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Algorithms::ImageBlender::
+Self* cpExtensions::Algorithms::ImageBlender::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpExtensions::Algorithms::ImageBlender::
+GetNumberOfInputs( )
+{
+  unsigned int np = this->GetNumberOfInputPorts( );
+  unsigned int ni = 0;
+  for( unsigned int p = 0; p < np; ++p )
+    ni += this->GetNumberOfInputConnections( p );
+  return( ni );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Algorithms::ImageBlender::
+ImageBlender( )
+  : Superclass( )
+{
+  this->SetNumberOfInputPorts( 1 );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Algorithms::ImageBlender::
+~ImageBlender( )
+{
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Algorithms::ImageBlender::
+RequestInformation(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  if( this->GetNumberOfInputConnections( 0 ) == 0 )
+    return( 0 );
+
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject( 0 ),
+    VTK_UNSIGNED_CHAR,
+    1
+    );
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Algorithms::ImageBlender::
+RequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  this->m_Ranges.clear( );
+  for( int i = 0; i < this->GetNumberOfInputPorts( ); ++i )
+  {
+    vtkInformationVector* portInfo = inputVector[ i ];
+    for( int j = 0; j < portInfo->GetNumberOfInformationObjects( ); ++j )
+    {
+      vtkInformation* info = portInfo->GetInformationObject( j );
+      vtkImageData* image = vtkImageData::SafeDownCast(
+        info->Get( vtkDataObject::DATA_OBJECT( ) )
+        );
+      if( image != NULL )
+      {
+        double r[ 2 ];
+        image->GetScalarRange( r );
+        this->m_Ranges.push_back( r[ 0 ] );
+        this->m_Ranges.push_back( r[ 1 ] );
+      }
+      else
+      {
+        this->m_Ranges.push_back( double( 0 ) );
+        this->m_Ranges.push_back( double( 0 ) );
+
+      } // fi
+
+    } // rof
+
+  } // rof
+  return(
+    this->Superclass::RequestData( request, inputVector, outputVector )
+    );
+}
+
+// -------------------------------------------------------------------------
+// Description:
+// This templated function executes the filter for any type of data.
+template< class T >
+void cpExtensions_Algorithms_ImageBlender_Execute(
+  cpExtensions::Algorithms::ImageBlender* self,
+  vtkImageData** inDatas, int numInputs,
+  const std::vector< double >& ranges, vtkImageData* outData,
+  int outExt[ 6 ], int id, T* really_not_used
+  )
+{
+  vtkImageIterator< T > inItsFast[ 256 ];
+  T* inSIFast[ 256 ];
+  vtkImageProgressIterator< T > outIt( outData, outExt, self, id );
+  vtkImageIterator< T >* inIts;
+  T** inSI;
+  if( numInputs < 256 )
+  {
+    inIts = inItsFast;
+    inSI = inSIFast;
+  }
+  else
+  {
+    inIts = new vtkImageIterator< T >[ numInputs ];
+    inSI = new T*[ numInputs ];
+
+  } // fi
+
+  // Loop through all input ImageData to initialize iterators
+  for( int i = 0; i < numInputs; ++i )
+    inIts[ i ].Initialize( inDatas[ i ], outExt );
+
+  // Loop through output pixels
+  while( !outIt.IsAtEnd( ) )
+  {
+    for( int j = 0; j < numInputs; ++j )
+      inSI[ j ] = inIts[ j ].BeginSpan( );
+
+    T* outSI = outIt.BeginSpan( );
+    T* outSIEnd = outIt.EndSpan( );
+
+    // Pixel operation
+    while( outSI != outSIEnd )
+    {
+      // Input 0 is ignored: it is just used to guarantee sizes all over
+      // the result
+      int vmax = 0;
+      for( int k = 0; k < numInputs; ++k )
+        if( double( *inSI[ k ] ) > ranges[ k << 1 ] && vmax <= k )
+          vmax = k + 1;
+      *outSI = static_cast< T >( vmax );
+      outSI++;
+      for( int l = 0; l < numInputs; ++l )
+        inSI[ l ]++;
+
+    } // elihw
+    for( int j = 0; j < numInputs; ++j )
+      inIts[ j ].NextSpan( );
+    outIt.NextSpan( );
+
+  } // elihw
+
+  if( numInputs >= 256)
+  {
+    delete [] inIts;
+    delete [] inSI;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Algorithms::ImageBlender::
+ThreadedRequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector,
+  vtkImageData*** inData, vtkImageData** outData,
+  int outExt[ 6 ], int id
+  )
+{
+  if( inData[ 0 ][ 0 ] == NULL )
+  {
+    vtkErrorMacro( << "Input " << 0 << " must be specified." );
+    return;
+
+  } // fi
+
+  int numInputs = this->GetNumberOfInputConnections( 0 );
+  int scalarType = inData[ 0 ][ 0 ]->GetScalarType( );
+  int numComp = inData[ 0 ][ 0 ]->GetNumberOfScalarComponents( );
+  for( int i = 0; i < numInputs; ++i )
+  {
+    int otherType = inData[ 0 ][ i ]->GetScalarType( );
+    int otherComp = inData[ 0 ][ i ]->GetNumberOfScalarComponents( );
+    if( otherType != scalarType || otherComp != numComp )
+    {
+      if( id == 0 )
+        vtkErrorMacro(
+          "ThreadedRequestData: Input " << i
+          << " has " << otherComp << " components of type "
+          << otherType << ", but input 0 has " << numComp
+          << " components of type " << scalarType
+          );
+      return;
+
+    } // fi
+
+  } // rof
+
+  switch( scalarType )
+  {
+    vtkTemplateMacro(
+      cpExtensions_Algorithms_ImageBlender_Execute(
+        this, inData[ 0 ], numInputs, this->m_Ranges,
+        outData[ 0 ], outExt, id, static_cast< VTK_TT* >( 0 )
+        )
+      );
+  default:
+    if( id == 0 )
+      vtkErrorMacro( << "Execute: Unknown ScalarType" );
+    return;
+  } // hctiws
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Algorithms::ImageBlender::
+FillInputPortInformation( int i, vtkInformation* info )
+{
+  info->Set( vtkAlgorithm::INPUT_IS_REPEATABLE( ), 1 );
+  return( this->Superclass::FillInputPortInformation( i,info ) );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageBlender.h b/lib/cpExtensions/Algorithms/ImageBlender.h
new file mode 100644 (file)
index 0000000..4d82bcf
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __cpExtensions__Algorithms__ImageBlender__h__
+#define __cpExtensions__Algorithms__ImageBlender__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkThreadedImageAlgorithm.h>
+#include <vector>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     * @note: Based on vtkImageWeightedSum
+     */
+    class cpExtensions_EXPORT ImageBlender
+      : public vtkThreadedImageAlgorithm
+    {
+    public:
+      typedef ImageBlender Self;
+      vtkTypeMacro( ImageBlender, vtkThreadedImageAlgorithm );
+
+    public:
+      static Self* New( );
+
+      unsigned int GetNumberOfInputs( );
+
+    protected:
+      ImageBlender( );
+      virtual ~ImageBlender( );
+
+      int RequestInformation(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        );
+      int RequestData(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        );
+      void ThreadedRequestData(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector,
+        vtkImageData*** inData, vtkImageData** outData,
+        int outExt[ 6 ], int id
+        );
+      int FillInputPortInformation( int i, vtkInformation* info );
+
+    private:
+      // Purposely not implemented.
+      ImageBlender( const Self& other );
+      void operator=( const Self& other );
+
+    protected:
+      std::vector< double > m_Ranges;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Algorithms__ImageBlender__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageFunctionFilter.h b/lib/cpExtensions/Algorithms/ImageFunctionFilter.h
new file mode 100644 (file)
index 0000000..503f791
--- /dev/null
@@ -0,0 +1,69 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__
+
+#include <cpExtensions/Config.h>
+#include <itkImageToImageFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TInput, class _TOutput, class _TFunction >
+    class ImageFunctionFilter
+      : public itk::ImageToImageFilter< _TInput, _TOutput >
+    {
+    public:
+      typedef ImageFunctionFilter                          Self;
+      typedef itk::ImageToImageFilter< _TInput, _TOutput > Superclass;
+      typedef itk::SmartPointer< Self >                    Pointer;
+      typedef itk::SmartPointer< const Self >              ConstPointer;
+
+      typedef _TInput    TInput;
+      typedef _TOutput   TOutput;
+      typedef _TFunction TFunction;
+
+      typedef typename TOutput::RegionType TRegion;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( ImageFunctionFilter, itkImageToImageFilter );
+
+      itkGetObjectMacro( Function, TFunction );
+      itkSetObjectMacro( Function, TFunction );
+
+    protected:
+      ImageFunctionFilter( );
+      virtual ~ImageFunctionFilter( );
+
+      virtual void BeforeThreadedGenerateData( ) cpExtensions_OVERRIDE;
+      virtual void ThreadedGenerateData(
+        const TRegion& region,
+        itk::ThreadIdType threadId
+        ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented.
+      ImageFunctionFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      typename TFunction::Pointer m_Function;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/ImageFunctionFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx b/lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx
new file mode 100644 (file)
index 0000000..c96c092
--- /dev/null
@@ -0,0 +1,67 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__
+
+#include <itkMacro.h>
+#include <itkImageRegionConstIteratorWithIndex.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkProgressReporter.h>
+
+// -------------------------------------------------------------------------
+template< class _TInput, class _TOutput, class _TFilter >
+cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >::
+ImageFunctionFilter( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInput, class _TOutput, class _TFilter >
+cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >::
+~ImageFunctionFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TInput, class _TOutput, class _TFilter >
+void cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >::
+BeforeThreadedGenerateData( )
+{
+  if( this->m_Function.IsNull( ) )
+    itkExceptionMacro( << "Please set a valid itk::ImageFunction" );
+  this->m_Function->SetInputImage( this->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInput, class _TOutput, class _TFilter >
+void cpExtensions::Algorithms::ImageFunctionFilter< _TInput, _TOutput, _TFilter >::
+ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId )
+{
+  const typename TRegion::SizeType& regionSize = region.GetSize( );
+  if( regionSize[ 0 ] == 0 )
+    return;
+  const _TInput* in = this->GetInput( );
+  _TOutput* out = this->GetOutput( 0 );
+
+  itk::ProgressReporter pr( this, threadId, region.GetNumberOfPixels( ) );
+
+  // Define the iterators
+  itk::ImageRegionConstIteratorWithIndex< TInput > iIt( in, region );
+  itk::ImageRegionIteratorWithIndex< TOutput > oIt( out, region );
+
+  iIt.GoToBegin( );
+  oIt.GoToBegin( );
+  for( ; !iIt.IsAtEnd( ) && !oIt.IsAtEnd( ); ++iIt, ++oIt )
+  {
+    oIt.Set( this->m_Function->EvaluateAtIndex( iIt.GetIndex( ) ) );
+    pr.CompletedPixel( );
+
+  } // rof
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageFunctorFilter.h b/lib/cpExtensions/Algorithms/ImageFunctorFilter.h
new file mode 100644 (file)
index 0000000..d8a7eca
--- /dev/null
@@ -0,0 +1,102 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__
+
+#include <itkImageToImageFilter.h>
+#include <itkImageScanlineConstIterator.h>
+#include <itkImageScanlineIterator.h>
+#include <itkProgressReporter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I, class O, class F >
+    class ImageFunctorFilter
+      : public itk::ImageToImageFilter< I, O >
+    {
+    public:
+      typedef ImageFunctorFilter             Self;
+      typedef itk::ImageToImageFilter< I, O > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef I TInputImage;
+      typedef O TOutputImage;
+      typedef F TFunctor;
+
+      typedef typename O::RegionType TRegion;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( ImageFunctorFilter, itkImageToImageFilter );
+
+      itkGetMacro( Functor, F );
+      itkGetConstMacro( Functor, F );
+
+    protected:
+      ImageFunctorFilter( )
+        : Superclass( )
+        {
+        }
+      virtual ~ImageFunctorFilter( )
+        {
+        }
+
+      virtual void ThreadedGenerateData(
+        const TRegion& region,
+        itk::ThreadIdType threadId
+        )
+        {
+          const typename TRegion::SizeType& regionSize = region.GetSize( );
+          if( regionSize[ 0 ] == 0 )
+            return;
+          const I* in = this->GetInput( );
+          O* out = this->GetOutput( 0 );
+
+          const size_t nLines = region.GetNumberOfPixels( ) / regionSize[ 0 ];
+          itk::ProgressReporter progress( this, threadId, nLines );
+
+          // Define the iterators
+          itk::ImageScanlineConstIterator< I > inIt( in, region );
+          itk::ImageScanlineIterator< O > outIt( out, region );
+
+          inIt.GoToBegin( );
+          outIt.GoToBegin( );
+          while( !inIt.IsAtEnd( ) )
+          {
+            while( !inIt.IsAtEndOfLine( ) )
+            {
+              outIt.Set( this->m_Functor( inIt.Get( ) ) );
+              ++inIt;
+              ++outIt;
+
+            } // elihw
+            inIt.NextLine( );
+            outIt.NextLine( );
+            progress.CompletedPixel( );
+
+          } // elihw
+        }
+
+    private:
+      // Purposely not implemented.
+      ImageFunctorFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      F m_Functor;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h b/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h
new file mode 100644 (file)
index 0000000..b970df4
--- /dev/null
@@ -0,0 +1,78 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__h__
+#define __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__h__
+
+#include <itkObject.h>
+#include <itkObjectFactory.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TImage >
+    class ImageToBoundingBoxFromThreshold
+      : public itk::Object
+    {
+    public:
+      typedef ImageToBoundingBoxFromThreshold Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TImage TImage;
+      typedef typename TImage::PixelType  TPixel;
+      typedef typename TImage::IndexType  TIndex;
+      typedef typename TImage::RegionType TRegion;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( ImageToBoundingBoxFromThreshold, itkObject );
+
+      itkGetConstObjectMacro( Image, TImage );
+      itkGetConstMacro( LowerThreshold, TPixel );
+      itkGetConstMacro( UpperThreshold, TPixel );
+      itkGetConstMacro( Region, TRegion );
+      itkGetConstMacro( PAD, unsigned int );
+
+      itkSetConstObjectMacro( Image, TImage );
+      itkSetMacro( LowerThreshold, TPixel );
+      itkSetMacro( UpperThreshold, TPixel );
+      itkSetMacro( Region, TRegion );
+      itkSetMacro( PAD, unsigned int );
+
+    public:
+      void Compute( );
+
+    protected:
+      ImageToBoundingBoxFromThreshold( );
+      virtual ~ImageToBoundingBoxFromThreshold( );
+
+    private:
+      // Purposely not implemented.
+      ImageToBoundingBoxFromThreshold( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      typename TImage::ConstPointer m_Image;
+      TPixel m_LowerThreshold;
+      TPixel m_UpperThreshold;
+      TRegion m_Region;
+      unsigned int m_PAD;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx b/lib/cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.hxx
new file mode 100644 (file)
index 0000000..55659eb
--- /dev/null
@@ -0,0 +1,89 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__hxx__
+#define __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__hxx__
+
+#include <limits>
+#include <itkImageRegionConstIteratorWithIndex.h>
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >::
+Compute( )
+{
+  typedef itk::ImageRegionConstIteratorWithIndex< _TImage > _TIt;
+
+  TIndex min_idx, max_idx;
+  min_idx.Fill( 0 );
+  max_idx.Fill( -1 );
+
+  if( this->m_Image.IsNotNull( ) )
+  {
+    auto region = this->m_Image->GetRequestedRegion( );
+    min_idx = max_idx = region.GetIndex( );
+    min_idx += region.GetSize( );
+
+    _TIt i( this->m_Image, region );
+    for( i.GoToBegin( ); !i.IsAtEnd( ); ++i )
+    {
+      auto v = i.Get( );
+      if( this->m_LowerThreshold <= v && v <= this->m_UpperThreshold )
+      {
+        auto idx = i.GetIndex( );
+        for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+        {
+          min_idx[ d ] = ( idx[ d ] < min_idx[ d ] )? idx[ d ]: min_idx[ d ]; 
+          max_idx[ d ] = ( idx[ d ] > max_idx[ d ] )? idx[ d ]: max_idx[ d ]; 
+        } // rof
+
+      } // fi
+
+    } // rof
+
+    // Fix indices
+    for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+    {
+      min_idx[ d ] -= long( this->m_PAD );
+      max_idx[ d ] += long( this->m_PAD );
+
+      if( min_idx[ d ] < region.GetIndex( )[ d ] )
+        min_idx[ d ] = region.GetIndex( )[ d ];
+      if( max_idx[ d ] > region.GetIndex( )[ d ] + region.GetSize( )[ d ] )
+        max_idx[ d ] = region.GetIndex( )[ d ] + region.GetSize( )[ d ];
+
+    } // rof
+
+  } // fi
+
+  typename _TImage::SizeType size;
+  for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+    size[ d ] = max_idx[ d ] - min_idx[ d ] + 1;
+  
+  this->m_Region.SetIndex( min_idx );
+  this->m_Region.SetSize( size );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >::
+ImageToBoundingBoxFromThreshold( )
+  : Superclass( ),
+    m_LowerThreshold( std::numeric_limits< TPixel >::min( ) ),
+    m_UpperThreshold( std::numeric_limits< TPixel >::max( ) ),
+    m_PAD( 0 )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >::
+~ImageToBoundingBoxFromThreshold( )
+{
+}
+
+#endif // __cpExtensions__Algorithms__ImageToBoundingBoxFromThreshold__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/InertiaMedialness.h b/lib/cpExtensions/Algorithms/InertiaMedialness.h
new file mode 100644 (file)
index 0000000..e385513
--- /dev/null
@@ -0,0 +1,215 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__
+#define __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__
+
+#include <map>
+#include <itkImageFunction.h>
+
+#include <cpExtensions/Algorithms/InertiaTensorFunction.h>
+#include <itkImageRegionConstIteratorWithIndex.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I, class S = float >
+    class InertiaMedialness
+      : public itk::ImageFunction< I, S, S >
+    {
+    public:
+      // Standard itk types
+      typedef InertiaMedialness               Self;
+      typedef itk::ImageFunction< I, S, S >   Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      // Types from base itk::ImageFunction
+      typedef typename Superclass::InputType           TInput;
+      typedef typename Superclass::OutputType          TOutput;
+      typedef typename Superclass::PointType           TPoint;
+      typedef typename Superclass::ContinuousIndexType TContIndex;
+      typedef typename Superclass::IndexType           TIndex;
+      typedef typename TIndex::OffsetType              TOffset;
+
+      // Sparse buffer
+      typedef std::map< TIndex, TOutput, typename TIndex::LexicographicCompare > TBuffer;
+
+      typedef InertiaTensorFunction< S, I::ImageDimension > TInertia;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( InertiaMedialness, itkImageFunction );
+
+      itkBooleanMacro( BufferResults );
+      itkGetConstMacro( BufferResults, bool );
+      itkGetConstMacro( MaxRadius, double );
+
+      itkSetMacro( BufferResults, bool );
+      itkSetMacro( MaxRadius, double );
+
+    public:
+      virtual void ResetBuffer( )
+        {
+          this->m_Buffer.clear( );
+        }
+
+      virtual TOutput Evaluate( const TPoint& p ) const
+        {
+          TIndex i;
+          this->GetInputImage( )->TransformPhysicalPointToIndex( p, i );
+          return( this->EvaluateAtIndex( i ) );
+        }
+
+      virtual TOutput EvaluateAtIndex( const TIndex& i ) const
+        {
+          TOutput res = TOutput( 0 );
+          bool computed = false;
+          if( this->m_BufferResults )
+          {
+            typename TBuffer::const_iterator bIt = this->m_Buffer.find( i );
+            computed = ( bIt != this->m_Buffer.end( ) );
+            res = ( computed )? bIt->second: res;
+
+          } // fi
+
+          if( !computed )
+            res = this->_Evaluate( i );
+
+          if( this->m_BufferResults )
+            this->m_Buffer[ i ] = res;
+          return( res );
+        }
+
+      virtual TOutput EvaluateAtContinuousIndex( const TContIndex& i ) const
+        {
+          TPoint p;
+          this->GetInputImage( )->TransformContinuousIndexToPhysicalPoint( i, p );
+          return( this->Evaluate( p ) );
+        }
+
+    protected:
+      InertiaMedialness( )
+        : Superclass( ),
+          m_BufferResults( false ),
+          m_MaxRadius( double( 1 ) )
+        {
+          this->m_Buffer.clear( );
+        }
+
+      virtual ~InertiaMedialness( )
+        {
+          this->m_Buffer.clear( );
+        }
+
+      virtual TOutput _Evaluate( const TIndex& idx ) const
+        {
+          const I* image = this->GetInputImage( );
+
+          typename I::PointType p_i;
+          image->TransformIndexToPhysicalPoint( idx, p_i );
+
+          typename I::PointType max_p, min_p;
+          for( unsigned int d = 0; d < I::ImageDimension; ++d )
+          {
+            max_p[ d ] = p_i[ d ] + this->m_MaxRadius;
+            min_p[ d ] = p_i[ d ] - this->m_MaxRadius;
+
+          } // rof
+          TIndex max_i, min_i;
+          image->TransformPhysicalPointToIndex( max_p, max_i );
+          image->TransformPhysicalPointToIndex( min_p, min_i );
+
+          typename I::RegionType in_region = image->GetRequestedRegion( );
+          TIndex in_index = in_region.GetIndex( );
+          TIndex in_last = in_index + in_region.GetSize( );
+          typename I::SizeType size;
+          for( unsigned int d = 0; d < I::ImageDimension; ++d )
+          {
+            if( min_i[ d ] < in_index[ d ] ) min_i[ d ] = in_index[ d ];
+            if( max_i[ d ] < in_index[ d ] ) max_i[ d ] = in_index[ d ];
+            if( min_i[ d ] >= in_last[ d ] ) min_i[ d ] = in_last[ d ];
+            if( max_i[ d ] >= in_last[ d ] ) max_i[ d ] = in_last[ d ];
+
+            size[ d ] = max_i[ d ] - min_i[ d ];
+
+          } // rof
+
+          typename I::RegionType region;
+          region.SetIndex( min_i );
+          region.SetSize( size );
+
+          std::vector< typename TInertia::Pointer > inertias;
+          itk::ImageRegionConstIteratorWithIndex< I > it( image, region );
+          for( it.GoToBegin( ); !it.IsAtEnd( ); ++it )
+          {
+            TOffset off = it.GetIndex( ) - idx;
+            unsigned long l1dist = std::abs( off[ 0 ] );
+            for( unsigned int d = 1; d < I::ImageDimension; ++d )
+              l1dist = ( std::abs( off[ d ] ) > l1dist )? std::abs( off[ d ] ): l1dist;
+
+            typename TInertia::TPoint i_pnt;
+            image->TransformIndexToPhysicalPoint( it.GetIndex( ), i_pnt );
+
+            for( unsigned long l = 0; l < l1dist; ++l )
+            {
+              if( inertias.size( ) <= l )
+                inertias.push_back( TInertia::New( ) );
+              inertias[ l ]->AddMass( i_pnt.GetVectorFromOrigin( ), S( it.Get( ) ) );
+
+              /* TODO
+                 typename TInertias::iterator inIt = inertias.find( l );
+                 if( inIt == inertias.end( ) )
+                 inIt = inertias.insert( std::pair< unsigned long, typename TInertia::Pointer >( l, TInertia::New( ) ) ).first;
+              */
+
+            } // rof
+
+          } // rof
+
+          if( inertias.size( ) > 0 )
+          {
+            S res = S( 0 );
+            for( unsigned int l = 0; l < inertias.size( ); ++l )
+            {
+              typename TInertia::TVector pv, r;
+              typename TInertia::TMatrix pm;
+              inertias[ l ]->GetEigenAnalysis( pm, pv, r );
+              S v = pv.GetNorm( );
+              if( l == 0 || v > res )
+                res = v;
+
+            } // rof
+            return( res );
+          }
+          else
+            return( TOutput( 0 ) );
+        }
+
+    private:
+      // Purposely not implemented.
+      InertiaMedialness( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      mutable TBuffer m_Buffer;
+      bool m_BufferResults;
+
+      double m_MaxRadius;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+// TODO: #include <cpExtensions/Algorithms/InertiaMedialness.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/InertiaTensorFunction.h b/lib/cpExtensions/Algorithms/InertiaTensorFunction.h
new file mode 100644 (file)
index 0000000..ecb341d
--- /dev/null
@@ -0,0 +1,180 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__
+#define __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__
+
+#include <itkObject.h>
+
+#include <itkObject.h>
+#include <itkObjectFactory.h>
+#include <itkMatrix.h>
+#include <itkPoint.h>
+
+
+#include <cmath>
+#include <itkSymmetricEigenAnalysis.h>
+
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class S, unsigned int D >
+    class InertiaTensorFunction
+      : public itk::Object
+    {
+    public:
+      // Standard itk types
+      typedef InertiaTensorFunction           Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef S                           TScalar;
+      typedef itk::Matrix< S, D, D >      TMatrix;
+      typedef itk::Point< S, D >          TPoint;
+      typedef typename TPoint::VectorType TVector;
+
+    protected:
+      typedef TMatrix _TInternalMatrix;
+      typedef itk::Matrix< S, D, 1 > _TInternalVector;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( InertiaTensorFunction, itkObject );
+
+    public:
+      inline void Reset( )
+        {
+          this->m_M = S( 0 );
+          this->m_MPP = S( 0 );
+          this->m_MP.Fill( S( 0 ) );
+          this->m_MPPT.Fill( S( 0 ) );
+          this->Modified( );
+        }
+      inline void AddMass( const TPoint& pnt, const S& mass = S( 1 ) )
+        {
+          this->AddMass( pnt.GetVectorFromOrigin( ), mass );
+        }
+      inline void AddMass( const S* data, const S& mass = S( 1 ) )
+        {
+          this->AddMass( TVector( data ), mass );
+        }
+      inline void AddMass( const TVector& vec, const S& mass = S( 1 ) )
+        {
+          this->m_M += mass;
+          this->m_MPP += mass * ( vec * vec );
+
+          _TInternalVector mp;
+          for( unsigned int d = 0; d < D; ++d )
+          {
+            this->m_MP[ d ][ 0 ] += mass * vec[ d ];
+            mp[ d ][ 0 ] = vec[ d ];
+
+          } // rof
+          this->m_MPPT +=
+            _TInternalMatrix( mp.GetVnlMatrix( ) * mp.GetTranspose( ) ) *
+            mass;
+        }
+
+      inline S GetMass( ) const
+        {
+          return( this->m_M );
+        }
+
+      inline TMatrix GetInertia( ) const
+        {
+          TMatrix I;
+          if( S( 0 ) < this->m_M )
+          {
+            I.SetIdentity( );
+            I *= this->m_MPP - ( ( this->m_MP.GetTranspose( ) * this->m_MP.GetVnlMatrix( ) )[ 0 ][ 0 ] / this->m_M );
+            I -= this->m_MPPT;
+            I += TMatrix( this->m_MP.GetVnlMatrix( ) * this->m_MP.GetTranspose( ) ) / this->m_M;
+          }
+          else
+            I.Fill( S( 0 ) );
+          return( I );
+        }
+
+      inline TVector GetCenterOfGravity( ) const
+        {
+          TVector cog;
+          if( S( 0 ) < this->m_M )
+          {
+            for( unsigned int d = 0; d < D; ++d )
+              cog[ d ] = this->m_MP[ d ][ 0 ] / this->m_M;
+          }
+          else
+            cog.Fill( S( 0 ) );
+          return( cog );
+        }
+
+      inline void GetEigenAnalysis( TMatrix& pm, TVector& pv, TVector& r ) const
+        {
+          TMatrix I = this->GetInertia( );
+
+          itk::SymmetricEigenAnalysis< TMatrix, TVector, TMatrix > eigen;
+          eigen.SetDimension( D );
+          eigen.SetOrderEigenMagnitudes( true );
+          eigen.SetOrderEigenValues( 1 );
+          eigen.ComputeEigenValuesAndVectors( I, pv, pm );
+          pm = TMatrix( pm.GetTranspose( ) );
+          S det = vnl_determinant( pm.GetVnlMatrix( ) );
+          for( unsigned int d = 0; d < D; ++d )
+            pm[ d ][ D - 1 ] *= det;
+
+          if( D == 2 )
+          {
+            S coeff = S( 4 ) / this->m_M;
+            r[ 0 ] = std::sqrt( std::fabs( coeff * pv[ 1 ] ) );
+            r[ 1 ] = std::sqrt( std::fabs( coeff * pv[ 0 ] ) );
+          }
+          else if( D == 3 )
+          {
+            S coeff = S( 2.5 ) / this->m_M;
+            r[ 0 ] = std::sqrt( std::fabs( coeff * ( pv[ 1 ] + pv[ 2 ] - pv[ 0 ] ) ) );
+            r[ 1 ] = std::sqrt( std::fabs( coeff * ( pv[ 0 ] + pv[ 2 ] - pv[ 1 ] ) ) );
+            r[ 2 ] = std::sqrt( std::fabs( coeff * ( pv[ 0 ] + pv[ 1 ] - pv[ 2 ] ) ) );
+          }
+          else
+            r.Fill( S( 0 ) );
+        }
+
+    protected:
+      InertiaTensorFunction( )
+        : Superclass( )
+        {
+          this->Reset( );
+        }
+      virtual ~InertiaTensorFunction( )
+        {
+        }
+
+    private:
+      // Purposely not implemented.
+      InertiaTensorFunction( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      S m_M;
+      S m_MPP;
+      _TInternalVector m_MP;
+      _TInternalMatrix m_MPPT;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+// #include <cpExtensions/Algorithms/InertiaTensorFunction.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/IsoImageSlicer.h b/lib/cpExtensions/Algorithms/IsoImageSlicer.h
new file mode 100644 (file)
index 0000000..9190430
--- /dev/null
@@ -0,0 +1,185 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__
+#define __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__
+
+#include <cpExtensions/Config.h>
+#include <itkAffineTransform.h>
+#include <itkExtractImageFilter.h>
+#include <itkImage.h>
+#include <itkImageToImageFilter.h>
+#include <itkInterpolateImageFunction.h>
+#include <itkResampleImageFilter.h>
+#include <itkVectorResampleImageFilter.h>
+#include <itkVectorInterpolateImageFunction.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class R, class I >
+    class BaseImageSlicer
+      : public itk::ImageToImageFilter< typename R::InputImageType, itk::Image< typename R::InputImageType::PixelType, R::ImageDimension - 1 > >
+    {
+    public:
+      // Basic types
+      typedef BaseImageSlicer            Self;
+      typedef R                          TSlicer;
+      typedef I                          TInterpolateFunction;
+      typedef typename R::InputImageType TImage;
+      typedef typename I::CoordRepType   TScalar;
+      typedef typename TImage::PixelType TPixel;
+      enum
+      {
+        Dim      = TImage::ImageDimension,
+        SliceDim = TImage::ImageDimension - 1
+      };
+      typedef itk::Image< TPixel, Self::SliceDim > TSliceImage;
+
+      // itk types
+      typedef itk::ImageToImageFilter< TImage, TSliceImage > Superclass;
+      typedef itk::SmartPointer< Self >                      Pointer;
+      typedef itk::SmartPointer< const Self >                ConstPointer;
+
+      // Internal filters
+      typedef itk::ExtractImageFilter< TImage, TSliceImage > TCollapsor;
+
+      // Various types
+      typedef typename TImage::IndexType   TIndex;
+      typedef typename TImage::RegionType  TRegion;
+      typedef typename TImage::SizeType    TSize;
+      typedef typename TImage::SpacingType TSpacing;
+      typedef typename TSpacing::ValueType TSpacingValue;
+
+      typedef itk::AffineTransform< TScalar, Self::Dim > TTransform;
+      typedef typename TTransform::MatrixType            TMatrix;
+      typedef typename TTransform::OffsetType            TVector;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( BaseImageSlicer, itkImageToImageFilter );
+
+      itkBooleanMacro( SizeFromMaximum );
+      itkBooleanMacro( SizeFromMinimum );
+      itkBooleanMacro( SpacingFromMaximum );
+      itkBooleanMacro( SpacingFromMinimum );
+
+      itkGetConstObjectMacro( Transform, TTransform );
+      itkGetConstMacro( DefaultValue, TPixel );
+      itkGetConstMacro( Size, TVector );
+      itkGetConstMacro( SizeFromMaximum, bool );
+      itkGetConstMacro( SizeFromMinimum, bool );
+      itkGetConstMacro( Spacing, TSpacingValue );
+      itkGetConstMacro( SpacingFromMaximum, bool );
+      itkGetConstMacro( SpacingFromMinimum, bool );
+
+      itkSetObjectMacro( Transform, TTransform );
+      itkSetMacro( Size, TVector );
+      itkSetMacro( DefaultValue, TPixel );
+      itkSetMacro( SizeFromMaximum, bool );
+      itkSetMacro( SizeFromMinimum, bool );
+      itkSetMacro( Spacing, TSpacingValue );
+      itkSetMacro( SpacingFromMaximum, bool );
+      itkSetMacro( SpacingFromMinimum, bool );
+
+    public:
+      virtual unsigned long GetMTime( ) const cpExtensions_OVERRIDE;
+
+      const TInterpolateFunction* GetInterpolator( ) const;
+      const TMatrix& GetRotation( ) const;
+      const TVector& GetTranslation( ) const;
+
+      void SetInterpolator( TInterpolateFunction* f );
+
+      template< class M >
+        void SetRotation( const M& r );
+
+      template< class V >
+        void SetTranslation( const V& t );
+      void SetSize( TScalar s );
+
+    protected:
+      BaseImageSlicer( );
+      virtual ~BaseImageSlicer( );
+
+      virtual void GenerateOutputInformation( ) cpExtensions_OVERRIDE; // TODO { }
+      virtual void GenerateInputRequestedRegion( ) cpExtensions_OVERRIDE;
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      BaseImageSlicer( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      typename TSlicer::Pointer    m_Slicer;
+      typename TCollapsor::Pointer m_Collapsor;
+      typename TTransform::Pointer m_Transform;
+
+      TPixel m_DefaultValue;
+
+      TVector m_Size;
+      bool    m_SizeFromMaximum;
+      bool    m_SizeFromMinimum;
+
+      TSpacingValue m_Spacing;
+      bool          m_SpacingFromMaximum;
+      bool          m_SpacingFromMinimum;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+// -------------------------------------------------------------------------
+#define CPPLUGINS_DEFINE_ISOIMAGESLICER( name, R, F )                   \
+  template< class I, class S = double >                                 \
+  class name                                                            \
+    : public BaseImageSlicer< R< I, I, S >, F< I, S > >                 \
+  {                                                                     \
+  public:                                                               \
+    typedef BaseImageSlicer< R< I, I, S >, F< I, S > > Superclass;      \
+    typedef name                                       Self;            \
+    typedef itk::SmartPointer< Self >                  Pointer;         \
+    typedef itk::SmartPointer< const Self >            ConstPointer;    \
+  public:                                                               \
+    itkNewMacro( Self );                                                \
+    itkTypeMacro( name, BaseSlicer );                                   \
+  protected:                                                            \
+    name( ) : Superclass( ) { }                                         \
+    virtual ~name( ) { }                                                \
+  private:                                                              \
+    name( const Self& );                                                \
+    void operator=( const Self& );                                      \
+  };
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    CPPLUGINS_DEFINE_ISOIMAGESLICER(
+      IsoImageSlicer,
+      itk::ResampleImageFilter,
+      itk::InterpolateImageFunction
+      );
+    CPPLUGINS_DEFINE_ISOIMAGESLICER(
+      VectorIsoImageSlicer,
+      itk::VectorResampleImageFilter,
+      itk::VectorInterpolateImageFunction
+      );
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/IsoImageSlicer.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/IsoImageSlicer.hxx b/lib/cpExtensions/Algorithms/IsoImageSlicer.hxx
new file mode 100644 (file)
index 0000000..041d874
--- /dev/null
@@ -0,0 +1,234 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__HXX__
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+unsigned long cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GetMTime( ) const
+{
+  unsigned long t = this->Superclass::GetMTime( );
+  unsigned long sT = this->m_Slicer->GetMTime( );
+  unsigned long cT = this->m_Collapsor->GetMTime( );
+  unsigned long tT = this->m_Transform->GetMTime( );
+  t = ( sT > t )? sT: t;
+  t = ( cT > t )? cT: t;
+  t = ( tT > t )? tT: t;
+  return( t );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+const typename cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+TInterpolateFunction*
+cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GetInterpolator( ) const
+{
+  return( this->m_Slicer->GetInterpolator( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+const typename cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+TMatrix& cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GetRotation( ) const
+{
+  return( this->m_Transform->GetMatrix( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+const typename cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+TVector& cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GetTranslation( ) const
+{
+  return( this->m_Transform->GetOffset( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+SetInterpolator( TInterpolateFunction* f )
+{
+  this->m_Slicer->SetInterpolator( f );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+template< class M >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+SetRotation( const M& r )
+{
+  TMatrix rotation;
+  for( unsigned int i = 0; i < Self::Dim; ++i )
+    for( unsigned int j = 0; j < Self::Dim; ++j )
+      rotation[ i ][ j ] = r[ i ][ j ];
+  this->m_Transform->SetMatrix( rotation );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+template< class V >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+SetTranslation( const V& t )
+{
+  TVector off;
+  for( unsigned int i = 0; i < Self::Dim; ++i )
+    off[ i ] = t[ i ];
+  this->m_Transform->SetOffset( off );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+SetSize( TScalar s )
+{
+  this->m_Size.Fill( s );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+BaseImageSlicer( )
+  : Superclass( ),
+    m_SizeFromMaximum( false ),
+    m_SizeFromMinimum( false ),
+    m_Spacing( TSpacingValue( 1 ) ),
+    m_SpacingFromMaximum( false ),
+    m_SpacingFromMinimum( false )
+{
+  this->m_Size.Fill( TScalar( 1 ) );
+
+  // Slicer
+  this->m_Slicer = TSlicer::New( );
+
+  TIndex idx;
+  idx.Fill( 0 );
+  this->m_Slicer->SetOutputStartIndex( idx );
+
+  // Dimension collapsor
+  this->m_Collapsor = TCollapsor::New( );
+  this->m_Collapsor->SetInput( this->m_Slicer->GetOutput( ) );
+  this->m_Collapsor->SetDirectionCollapseToIdentity( );
+
+  this->m_Transform = TTransform::New( );
+  this->m_Transform->SetIdentity( );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+~BaseImageSlicer( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GenerateOutputInformation( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GenerateInputRequestedRegion( )
+{
+  TImage* input = const_cast< TImage* >( this->GetInput( ) );
+  if( input != NULL )
+    input->SetRequestedRegionToLargestPossibleRegion( );
+}
+
+// -------------------------------------------------------------------------
+template< class R, class I >
+void cpExtensions::Algorithms::BaseImageSlicer< R, I >::
+GenerateData( )
+{
+  const TImage* input = this->GetInput( );
+
+  // Spacing
+  TSpacing spac;
+  if( this->m_SpacingFromMaximum || this->m_SpacingFromMinimum )
+  {
+    spac = input->GetSpacing( );
+    TSpacingValue minIso = spac[ 0 ];
+    TSpacingValue maxIso = spac[ 0 ];
+    for( unsigned int i = 1; i < Self::Dim; i++ )
+    {
+      minIso = ( spac[ i ] < minIso )? spac[ i ]: minIso;
+      maxIso = ( spac[ i ] > maxIso )? spac[ i ]: maxIso;
+
+    } // rof
+    this->m_Spacing = ( this->m_SpacingFromMinimum )? minIso: maxIso;
+
+  } // fi
+  spac.Fill( this->m_Spacing );
+
+  // Size and origin
+  if( this->m_SizeFromMaximum || this->m_SizeFromMinimum )
+  {
+    TSize iSize = input->GetRequestedRegion( ).GetSize( );
+    TSpacing iSpac = input->GetSpacing( );
+    TScalar minSize = TScalar( iSize[ 0 ] ) * TScalar( iSpac[ 0 ] );
+    TScalar maxSize = minSize;
+    for( unsigned int i = 1; i < Self::Dim; i++ )
+    {
+      TScalar v = TScalar( iSize[ i ] ) * TScalar( iSpac[ i ] );
+      minSize = ( v < minSize )? v: minSize;
+      maxSize = ( v > maxSize )? v: maxSize;
+
+    } // rof
+    if( this->m_SizeFromMaximum )
+      this->m_Size.Fill( maxSize );
+    else
+      this->m_Size.Fill( minSize );
+
+  } // fi
+
+  TSize size;
+  typename TSlicer::OriginPointType origin;
+  size[ 0 ] = 1;
+  origin[ 0 ] = 0;
+  for( unsigned int i = 1; i < Self::Dim; i++ )
+  {
+    double s = double( this->m_Size[ i ] ) / double( spac[ i ] );
+    size[ i ] = ( unsigned int )( s );
+    origin[ i ] = -( 0.5 * this->m_Size[ i ] );
+
+  } // rof
+
+  // Prepare slicer
+  this->m_Slicer->SetInput( input );
+  this->m_Slicer->SetTransform( this->m_Transform );
+  this->m_Slicer->SetOutputSpacing( spac );
+  this->m_Slicer->SetOutputOrigin( origin );
+  this->m_Slicer->SetSize( size );
+  this->m_Slicer->SetDefaultPixelValue( this->m_DefaultValue );
+
+  // Slice!
+  // Note: UpdateLargestPossibleRegion( ) is used since we need the
+  // output regions to be updated at each filter call.
+  this->m_Slicer->UpdateLargestPossibleRegion( );
+
+  // Collapse result
+  TRegion region = this->m_Slicer->GetOutput( )->GetRequestedRegion( );
+  TSize regionSize = region.GetSize( );
+  regionSize[ 0 ] = 0;
+  region.SetSize( regionSize );
+  this->m_Collapsor->SetExtractionRegion( region );
+
+  this->m_Collapsor->GraftOutput( this->GetOutput( ) );
+  this->m_Collapsor->UpdateLargestPossibleRegion( );
+  this->GraftOutput( this->m_Collapsor->GetOutput( ) );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h
new file mode 100644 (file)
index 0000000..b38e06e
--- /dev/null
@@ -0,0 +1,171 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__
+#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__
+
+#include <vector>
+#include <itkConceptChecking.h>
+#include <itkObject.h>
+#include <itkObjectFactory.h>
+
+#include <itkCovariantVector.h>
+#include <itkMatrix.h>
+#include <itkPoint.h>
+#include <itkVector.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     * Recursive formulation taken from:
+     * http://lmb.informatik.uni-freiburg.de/lectures/mustererkennung/Englische_Folien/07_c_ME_en.pdf
+     */
+    template< class _TScalar, unsigned int _VDimension >
+    class IterativeGaussianModelEstimator
+      : public itk::Object
+    {
+    public:
+      typedef IterativeGaussianModelEstimator Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TScalar TScalar;
+      itkStaticConstMacro( Dimension, unsigned int, _VDimension );
+
+      // Begin concept checking
+#ifdef ITK_USE_CONCEPT_CHECKING
+      itkConceptMacro(
+        ScalarTypeHasFloatResolution,
+        ( itk::Concept::IsFloatingPoint< _TScalar > )
+        );
+#endif
+      // End concept checking
+
+      typedef itk::Matrix< TScalar, Dimension, Dimension > TMatrix;
+      typedef itk::Vector< TScalar, Dimension > TVector;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( IterativeGaussianModelEstimator, itkObject );
+
+      itkGetConstMacro( Mean, TVector );
+      itkGetConstMacro( Covariance, TMatrix );
+      itkGetConstMacro( UnbiasedCovariance, TMatrix );
+      itkGetConstMacro( NumberOfSamples, unsigned long );
+
+      itkSetMacro( Mean, TVector );
+      itkSetMacro( Covariance, TMatrix );
+      itkSetMacro( NumberOfSamples, unsigned long );
+
+    public:
+      void Clear( );
+
+      template< class _TOtherScalar >
+      void AddSample( const _TOtherScalar& x1, ... );
+
+      template< class _TOtherScalar >
+      void AddSample( const _TOtherScalar* array );
+
+      template< class _TOtherScalar >
+      void AddSample( const vnl_vector< _TOtherScalar >& v );
+
+      template< class _TOtherScalar >
+      void AddSample(
+        const itk::CovariantVector< _TOtherScalar, _VDimension >& v
+        );
+
+      template< class _TOtherScalar >
+      void AddSample( const itk::Point< _TOtherScalar, _VDimension >& p );
+
+      template< class _TOtherScalar >
+      void AddSample( const itk::Vector< _TOtherScalar, _VDimension >& v );
+
+      template< class _TOtherScalar >
+      _TScalar SquaredMahalanobis( const _TOtherScalar& x1, ... ) const;
+
+      template< class _TOtherScalar >
+      _TScalar SquaredMahalanobis( const _TOtherScalar* array ) const;
+
+      template< class _TOtherScalar >
+      _TScalar SquaredMahalanobis(
+        const vnl_vector< _TOtherScalar >& v
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar SquaredMahalanobis(
+        const itk::CovariantVector< _TOtherScalar, _VDimension >& v
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar SquaredMahalanobis(
+        const itk::Point< _TOtherScalar, _VDimension >& p
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar SquaredMahalanobis(
+        const itk::Vector< _TOtherScalar, _VDimension >& v
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar Density( const _TOtherScalar& x1, ... ) const;
+
+      template< class _TOtherScalar >
+      _TScalar Density( const _TOtherScalar* array ) const;
+
+      template< class _TOtherScalar >
+      _TScalar Density(
+        const vnl_vector< _TOtherScalar >& v
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar Density(
+        const itk::CovariantVector< _TOtherScalar, _VDimension >& v
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar Density(
+        const itk::Point< _TOtherScalar, _VDimension >& p
+        ) const;
+
+      template< class _TOtherScalar >
+      _TScalar Density(
+        const itk::Vector< _TOtherScalar, _VDimension >& v
+        ) const;
+
+    protected:
+      IterativeGaussianModelEstimator( );
+      virtual ~IterativeGaussianModelEstimator( );
+
+    protected:
+      void _AddSample( const TVector& v ) const;
+      _TScalar _SquaredMahalanobis( const TVector& v ) const;
+      _TScalar _Density( const TVector& v ) const;
+
+    private:
+      // Purposely not implemented
+      IterativeGaussianModelEstimator( const Self& other );
+      void operator=( const Self& other );
+
+    protected:
+      // Recursive avg/cov values
+      mutable unsigned long m_NumberOfSamples;
+      mutable TVector m_Mean;
+      mutable TMatrix m_Covariance;
+      mutable TMatrix m_UnbiasedCovariance;
+      mutable bool m_InverseUpdated;
+      mutable TMatrix m_InverseUnbiasedCovariance;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#include <cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx>
+
+#endif // __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx
new file mode 100644 (file)
index 0000000..acd1da7
--- /dev/null
@@ -0,0 +1,365 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__
+
+#include <cstdarg>
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Clear( )
+{
+  this->m_NumberOfSamples = 0;
+  this->m_Mean.Fill( TScalar( 0 ) );
+  this->m_Covariance.Fill( TScalar( 0 ) );
+  this->m_InverseUpdated = false;
+  this->m_InverseUnbiasedCovariance.Fill( TScalar( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+AddSample( const _TOtherScalar& x1, ... )
+{
+  TVector s;
+  std::va_list lst;
+  va_start( lst, x1 );
+  s[ 0 ] = TScalar( x1 );
+  for( unsigned int d = 1; d < _VDimension; ++d )
+    s[ d ] = TScalar( va_arg( lst, double ) );
+  va_end( lst );
+  this->_AddSample( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+AddSample( const _TOtherScalar* array )
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( array[ d ] );
+  this->_AddSample( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+AddSample( const vnl_vector< _TOtherScalar >& v )
+{
+  unsigned int len = ( v.size( ) < _VDimension )? v.size: _VDimension;
+  TVector s;
+  for( unsigned d = 0; d < len; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  this->_AddSample( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+AddSample( const itk::CovariantVector< _TOtherScalar, _VDimension >& v )
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  this->_AddSample( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+AddSample( const itk::Point< _TOtherScalar, _VDimension >& p )
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( p[ d ] );
+  this->_AddSample( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+AddSample( const itk::Vector< _TOtherScalar, _VDimension >& v )
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  this->_AddSample( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+SquaredMahalanobis( const _TOtherScalar& x1, ... ) const
+{
+  TVector s;
+  std::va_list lst;
+  va_start( lst, x1 );
+  s[ 0 ] = TScalar( x1 );
+  for( unsigned int d = 1; d < _VDimension; ++d )
+    s[ d ] = TScalar( va_arg( lst, double ) );
+  va_end( lst );
+  return( this->_SquaredMahalanobis( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+SquaredMahalanobis( const _TOtherScalar* array ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( array[ d ] );
+  return( this->_SquaredMahalanobis( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+SquaredMahalanobis( const vnl_vector< _TOtherScalar >& v ) const
+{
+  unsigned int len = ( v.size( ) < _VDimension )? v.size: _VDimension;
+  TVector s;
+  for( unsigned d = 0; d < len; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  return( this->_SquaredMahalanobis( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+SquaredMahalanobis(
+  const itk::CovariantVector< _TOtherScalar, _VDimension >& v
+  ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  return( this->_SquaredMahalanobis( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+SquaredMahalanobis( const itk::Point< _TOtherScalar, _VDimension >& p ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( p[ d ] );
+  return( this->_SquaredMahalanobis( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+SquaredMahalanobis( const itk::Vector< _TOtherScalar, _VDimension >& v ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  return( this->_SquaredMahalanobis( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Density( const _TOtherScalar& x1, ... ) const
+{
+  TVector s;
+  std::va_list lst;
+  va_start( lst, x1 );
+  s[ 0 ] = TScalar( x1 );
+  for( unsigned int d = 1; d < _VDimension; ++d )
+    s[ d ] = TScalar( va_arg( lst, double ) );
+  va_end( lst );
+  return( this->_Density( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Density( const _TOtherScalar* array ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( array[ d ] );
+  return( this->_Density( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Density( const vnl_vector< _TOtherScalar >& v ) const
+{
+  unsigned int len = ( v.size( ) < _VDimension )? v.size: _VDimension;
+  TVector s;
+  for( unsigned d = 0; d < len; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  return( this->_Density( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Density(
+  const itk::CovariantVector< _TOtherScalar, _VDimension >& v
+  ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  return( this->_Density( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Density( const itk::Point< _TOtherScalar, _VDimension >& p ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( p[ d ] );
+  return( this->_Density( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+template< class _TOtherScalar >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+Density( const itk::Vector< _TOtherScalar, _VDimension >& v ) const
+{
+  TVector s;
+  for( unsigned d = 0; d < _VDimension; ++d )
+    s[ d ] = TScalar( v[ d ] );
+  return( this->_Density( s ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+IterativeGaussianModelEstimator( )
+  : Superclass( )
+{
+  this->Clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+~IterativeGaussianModelEstimator( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+void cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+_AddSample( const TVector& v ) const
+{
+  this->m_NumberOfSamples += 1;
+  TScalar a = TScalar( 1 ) / TScalar( this->m_NumberOfSamples );
+  TScalar b = TScalar( 1 ) - a;
+  TVector c = v - this->m_Mean;
+  TMatrix m;
+  for( unsigned int i = 0; i < _VDimension; ++i )
+  {
+    m[ i ][ i ] = c[ i ] * c[ i ];
+    for( unsigned int j = i + 1; j < _VDimension; ++j )
+      m[ i ][ j ] = m[ j ][ i ] = c[ i ] * c[ j ];
+
+  } // rof
+  this->m_Covariance = ( this->m_Covariance + ( m * a ) ) * b;
+  this->m_Mean = ( this->m_Mean * b ) + ( v * a );
+
+  TScalar u =
+    TScalar( this->m_NumberOfSamples ) /
+    TScalar( this->m_NumberOfSamples - 1 );
+  this->m_UnbiasedCovariance = this->m_Covariance * u;
+  this->m_InverseUpdated = false;
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+_SquaredMahalanobis( const TVector& v ) const
+{
+  if( !this->m_InverseUpdated )
+  {
+    double d =
+      double(
+        vnl_determinant( this->m_UnbiasedCovariance.GetVnlMatrix( ) )
+        );
+    if( std::fabs( d ) > double( 0 ) )
+      this->m_InverseUnbiasedCovariance =
+        this->m_UnbiasedCovariance.GetInverse( );
+    else
+      this->m_InverseUnbiasedCovariance.SetIdentity( );
+    this->m_InverseUpdated = true;
+
+  } // fi
+  TVector x = v - this->m_Mean;
+  return( x * ( this->m_InverseUnbiasedCovariance * x ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar, unsigned int _VDimension >
+_TScalar cpExtensions::Algorithms::
+IterativeGaussianModelEstimator< _TScalar, _VDimension >::
+_Density( const TVector& v ) const
+{
+  static const double _2pik =
+    std::pow( double( 2 ) * double( vnl_math::pi ), _VDimension );
+
+  double s = double( this->_SquaredMahalanobis( v ) ) / double( 2 );
+  double d =
+    double(
+      vnl_determinant( this->m_UnbiasedCovariance.GetVnlMatrix( ) )
+      );
+  return( _TScalar( std::exp( -s ) / std::sqrt( _2pik * d ) ) );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx b/lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx
new file mode 100644 (file)
index 0000000..0fd5d6c
--- /dev/null
@@ -0,0 +1,49 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#include <cpExtensions/Algorithms/KalmanConstantFilter.h>
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanConstantFilter< T >::
+Configure( unsigned int m )
+{
+  this->Superclass::Configure( m, 1, m );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanConstantFilter< T >::
+Initialize( )
+{
+  this->Superclass::Initialize( );
+
+  this->m_A.set_identity( );
+  this->m_B.fill( TScalar( 0 ) );
+  this->m_H.set_identity( );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+cpExtensions::Algorithms::KalmanConstantFilter< T >::
+KalmanConstantFilter( )
+  : Superclass( )
+{
+  this->Configure( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+cpExtensions::Algorithms::KalmanConstantFilter< T >::
+~KalmanConstantFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+// Explicit instantiations
+
+template class cpExtensions::Algorithms::KalmanConstantFilter< float >;
+template class cpExtensions::Algorithms::KalmanConstantFilter< double >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanConstantFilter.h b/lib/cpExtensions/Algorithms/KalmanConstantFilter.h
new file mode 100644 (file)
index 0000000..82cd263
--- /dev/null
@@ -0,0 +1,56 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__
+
+#include <cpExtensions/Algorithms/KalmanFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< typename T >
+    class cpExtensions_EXPORT KalmanConstantFilter
+      : public KalmanFilter< T >
+    {
+    public:
+      typedef KalmanConstantFilter            Self;
+      typedef KalmanFilter< T >               Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::TScalar TScalar;
+      typedef typename Superclass::TMatrix TMatrix;
+      typedef typename Superclass::TVector TVector;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( KalmanConstantFilter, KalmanFilter );
+
+    public:
+      void Configure( unsigned int m );
+
+      // Iteration methods
+      virtual void Initialize( ) cpExtensions_OVERRIDE;
+
+    protected:
+      KalmanConstantFilter( );
+      virtual ~KalmanConstantFilter( );
+
+    private:
+      // Purposely not implemented.
+      KalmanConstantFilter( const Self& );
+      void operator=( const Self& );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanFilter.cxx b/lib/cpExtensions/Algorithms/KalmanFilter.cxx
new file mode 100644 (file)
index 0000000..add2041
--- /dev/null
@@ -0,0 +1,137 @@
+#include <cpExtensions/Algorithms/KalmanFilter.h>
+
+#include <cstdlib>
+#include <vnl/algo/vnl_matrix_inverse.h>
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanFilter< T >::
+Configure( unsigned int s, unsigned int i, unsigned int m )
+{
+  this->m_StateSize   = s;
+  this->m_InputSize   = i;
+  this->m_MeasureSize = m;
+
+  // Matrices
+  this->m_A.set_size( s, s );
+  this->m_B.set_size( s, i );
+  this->m_H.set_size( m, s );
+  this->m_Id.set_size( s, s );
+  this->m_Q.set_size( s, s );
+  this->m_R.set_size( m, m );
+  this->m_P0.set_size( s, s );
+  this->m_K.set_size( s, m );
+  this->m_Pm.set_size( s, s );
+  this->m_Pp.set_size( s, s );
+
+  // Vectors
+  this->m_x0.set_size( s );
+  this->m_u.set_size( i );
+  this->m_m.set_size( m );
+  this->m_xm.set_size( s );
+  this->m_xp.set_size( s );
+
+  // Static values
+  this->m_Id.set_identity( );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanFilter< T >::
+Initialize( )
+{
+  // Set all to the first iteration
+  this->m_I = 0;
+  this->m_Step = Self::StFilt;
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanFilter< T >::
+Predict( )
+{
+  if( this->m_Step == Self::StFilt )
+  {
+    if( this->m_I == 0 )
+    {
+      this->m_xp = this->m_x0;
+      this->m_Pp = this->m_P0;
+
+    } // fi
+
+    // Project the state
+    this->m_xm = ( this->m_A * this->m_xp ) + ( this->m_B * this->m_u );
+
+    // Project the error
+    this->m_Pm  = this->m_A * this->m_Pp * this->m_A.transpose( );
+    this->m_Pm += this->m_Q;
+
+    this->m_Step = Self::StPred;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanFilter< T >::
+Innovate( )
+{
+  typedef vnl_matrix_inverse< T > _TInv;
+
+  if( this->m_Step == Self::StPred )
+  {
+    // Kalman gain
+    this->m_K  = this->m_Pm * this->m_H.transpose( );
+    this->m_K *=
+      _TInv(
+        ( this->m_H * this->m_Pm * this->m_H.transpose( ) ) + this->m_R
+        );
+
+    this->m_Step = Self::StInno;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanFilter< T >::
+Filtrate( )
+{
+  if( this->m_Step == Self::StInno )
+  {
+    // A posteriori state
+    this->m_xp  = this->m_xm;
+    this->m_xp += this->m_K * ( this->m_m - ( this->m_H * this->m_xm ) );
+
+    // A posteriori error
+    this->m_Pp = ( this->m_Id - ( this->m_K * this->m_H ) ) * this->m_Pm;
+
+    this->m_Step = Self::StFilt;
+    this->m_I++;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+cpExtensions::Algorithms::KalmanFilter< T >::
+KalmanFilter( )
+  : Superclass( )
+{
+  this->Configure( 1, 1, 1 );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+cpExtensions::Algorithms::KalmanFilter< T >::
+~KalmanFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+// Explicit instantiations
+
+template class cpExtensions::Algorithms::KalmanFilter< float >;
+template class cpExtensions::Algorithms::KalmanFilter< double >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanFilter.h b/lib/cpExtensions/Algorithms/KalmanFilter.h
new file mode 100644 (file)
index 0000000..0039620
--- /dev/null
@@ -0,0 +1,213 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__
+
+#include <cpExtensions/Config.h>
+
+#include <itkObject.h>
+#include <itkObjectFactory.h>
+#include <vnl/vnl_matrix.h>
+#include <vnl/vnl_vector.h>
+
+// -------------------------------------------------------------------------
+#define kalmanGetSetMacro( type, name )         \
+  itkGetConstMacro( name, type );               \
+  itkSetMacro( name, type );
+
+// -------------------------------------------------------------------------
+#define kalmanGetMatrixMacro( var, name )       \
+  virtual const TMatrix& Get##name( ) const     \
+  { return( this->m_##var ); }
+
+// -------------------------------------------------------------------------
+#define kalmanSetMatrixMacro( var, name )       \
+  virtual void Set##name( const TMatrix& m )    \
+  { this->Set##var( m ); }
+
+// -------------------------------------------------------------------------
+#define kalmanGetSetMatrixMacro( var, name )    \
+  kalmanGetMatrixMacro( var, name );            \
+  kalmanSetMatrixMacro( var, name );
+
+// -------------------------------------------------------------------------
+#define kalmanGetVectorMacro( var, name )       \
+  virtual const TVector& Get##name( ) const     \
+  { return( this->m_##var ); }
+
+// -------------------------------------------------------------------------
+#define kalmanSetVectorMacro( var, name )       \
+  virtual void Set##name( const TVector& v )    \
+  { this->Set##var( v ); }
+
+// -------------------------------------------------------------------------
+#define kalmanGetSetVectorMacro( var, name )    \
+  kalmanGetVectorMacro( var, name );            \
+  kalmanSetVectorMacro( var, name );
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     * Abstract class implementing the classical kalman filter. See
+     * http://www.cs.unc.edu/~welch/media/pdf/kalman_intro.pdf
+     * for a description of this algorithm.
+     */
+    template< typename T >
+    class cpExtensions_EXPORT KalmanFilter
+      : public itk::Object
+    {
+    public:
+      typedef KalmanFilter                    Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      // Template parameters types
+      typedef T TScalar;
+
+      // VNL types
+      typedef vnl_matrix< TScalar > TMatrix;
+      typedef vnl_vector< TScalar > TVector;
+
+      //  stage identificators
+      enum
+      {
+        StPred,
+        StInno,
+        StFilt
+      };
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( KalmanFilter, itkObject );
+
+      // Values
+      itkGetConstMacro( StateSize, unsigned int );
+      itkGetConstMacro( InputSize, unsigned int );
+      itkGetConstMacro( MeasureSize, unsigned int );
+
+      // Matrices
+      kalmanGetSetMacro( TMatrix, A );
+      kalmanGetSetMacro( TMatrix, B );
+      kalmanGetSetMacro( TMatrix, H );
+      kalmanGetSetMacro( TMatrix, Q );
+      kalmanGetSetMacro( TMatrix, R );
+      kalmanGetSetMacro( TMatrix, P0 );
+      kalmanGetSetMacro( TMatrix, K );
+      kalmanGetSetMacro( TMatrix, Pm );
+      kalmanGetSetMacro( TMatrix, Pp );
+
+      // Vectors
+      kalmanGetSetMacro( TVector, x0 );
+      kalmanGetSetMacro( TVector, u );
+      kalmanGetSetMacro( TVector, m );
+      kalmanGetSetMacro( TVector, xm );
+      kalmanGetSetMacro( TVector, xp );
+
+      // Human-readable matrices
+      kalmanGetSetMatrixMacro( A, TransitionMatrix );
+      kalmanGetSetMatrixMacro( B, InputControlMatrix );
+      kalmanGetSetMatrixMacro( H, MeasureMatrix );
+      kalmanGetSetMatrixMacro( Q, ProcessNoise );
+      kalmanGetSetMatrixMacro( R, MeasureNoise );
+      kalmanGetSetMatrixMacro( P0, InitialNoise );
+      kalmanGetSetMatrixMacro( K, Gain );
+      kalmanGetSetMatrixMacro( Pm, APrioriNoise );
+      kalmanGetSetMatrixMacro( Pp, APosterioriNoise );
+
+      // Human-readable vectors
+      kalmanGetSetVectorMacro( x0, InitialState );
+      kalmanGetSetVectorMacro( u, Input );
+      kalmanGetSetVectorMacro( m, Measure );
+      kalmanGetSetVectorMacro( xm, APrioriState );
+      kalmanGetSetVectorMacro( xp, APosterioriState );
+
+    public:
+
+      void Configure( unsigned int s, unsigned int i, unsigned int m );
+
+      // Iteration methods
+      virtual void Initialize( );
+      virtual void Predict( );
+      virtual void Innovate( );
+      virtual void Filtrate( );
+      virtual void OneStep( )
+        {
+          this->Predict( );
+          this->Innovate( );
+          this->Filtrate( );
+        }
+      virtual void NSteps( unsigned int n )
+        {
+          for( unsigned int i = 0; i < n; i++ )
+            this->OneStep( );
+        }
+      unsigned int CurrentIteration( ) const
+        { return( this->m_I ); }
+      unsigned char CurrentStep( ) const
+        { return( this->m_Step ); }
+
+    protected:
+      KalmanFilter( );
+      virtual ~KalmanFilter( );
+
+    private:
+      // Purposely not implemented
+      KalmanFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      // Filter dimensions
+      unsigned int m_StateSize;
+      unsigned int m_InputSize;
+      unsigned int m_MeasureSize;
+
+      // Transition matrices
+      TMatrix m_A;  // Transition
+      TMatrix m_B;  // Input control
+      TMatrix m_H;  // Measure
+      TMatrix m_Id; // Identity matrix
+
+      // Noise matrices
+      TMatrix m_Q; // Process noise covariance
+      TMatrix m_R; // Measure noise covariance
+
+      // Initial values
+      TVector m_x0; // Initial state
+      TMatrix m_P0; // Initial error covariance
+
+      // Loop vectors
+      TVector m_u;  // Last real input
+      TVector m_m;  // Last real measure
+      TVector m_xm; // A priori state
+      TVector m_xp; // A posteriori state
+
+      // Loop matrices
+      TMatrix m_K; // kalman gain
+      TMatrix m_Pm; // A priori error
+      TMatrix m_Pp; // A posteriori error
+
+      // Loop values
+      unsigned int  m_I;    // Current iteration
+      unsigned char m_Step; // Current step within current iteration
+
+      // -------------------------------------------------------------------
+      // Classic kronecker product operator
+      // -------------------------------------------------------------------
+      template< class M >
+      static void Kronecker( M& AkB, const M& A, const M& B );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#include <cpExtensions/Algorithms/KalmanFilter.hxx>
+
+#endif // __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanFilter.hxx b/lib/cpExtensions/Algorithms/KalmanFilter.hxx
new file mode 100644 (file)
index 0000000..e81cae2
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__HXX__
+
+// -------------------------------------------------------------------------
+template< typename T >
+template< class M >
+void cpExtensions::Algorithms::KalmanFilter< T >::
+Kronecker( M& AkB, const M& A, const M& B )
+{
+  unsigned int m = A.rows( ); unsigned int n = A.cols( );
+  unsigned int p = B.rows( ); unsigned int q = B.cols( );
+  AkB.set_size( m * p, n * q );
+
+  for( unsigned int i = 1; i <= m; ++i )
+  {
+    for( unsigned int j = 1; j <= n; ++j )
+    {
+      for( unsigned int k = 1; k <= p; ++k )
+      {
+        for( unsigned int l = 1; l <= q; ++l )
+        {
+          unsigned int al = ( ( p * ( i - 1 ) ) + k ) - 1;
+          unsigned int be = ( ( q * ( j - 1 ) ) + l ) - 1;
+          AkB[ al ][ be ] = A[ i - 1 ][ j - 1 ] * B[ k - 1 ][ l - 1 ];
+
+        } // rof
+
+      } // rof
+
+    } // rof
+
+  } // rof
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx
new file mode 100644 (file)
index 0000000..a725e16
--- /dev/null
@@ -0,0 +1,90 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#include <cpExtensions/Algorithms/KalmanVelocityFilter.h>
+#include <cmath>
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+Configure( unsigned int m )
+{
+  this->Superclass::Configure( m << 1, 1, m );
+
+  this->m_TimeOffset.set_size( 2, 2 );
+  this->SetTimeOffset( TScalar( 1 ) );
+
+  this->m_Sigma.set_size( this->m_MeasureSize, this->m_MeasureSize );
+  this->m_Sigma.set_identity( );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+typename cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+TScalar cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+GetTimeOffset( ) const
+{
+  return( TScalar( std::sqrt( double( this->m_TimeOffset[ 1 ][ 1 ] ) ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+SetTimeOffset( TScalar t )
+{
+  TScalar t2 = t * t;
+  TScalar t3 = t2 * t;
+  TScalar t4 = t3 * t;
+  this->m_TimeOffset[ 0 ][ 0 ] = t4 / TScalar( 4 );
+  this->m_TimeOffset[ 1 ][ 1 ] = t2;
+
+  this->m_TimeOffset[ 0 ][ 1 ] = t3 / TScalar( 2 );
+  this->m_TimeOffset[ 1 ][ 0 ] = this->m_TimeOffset[ 0 ][ 1 ];
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+void cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+Initialize( )
+{
+  this->Superclass::Initialize( );
+
+  Self::Kronecker( this->m_Q, this->m_Sigma, this->m_TimeOffset );
+
+  this->m_A.set_identity( );
+  this->m_B.fill( TScalar( 0 ) );
+  this->m_H.fill( TScalar( 0 ) );
+
+  TScalar tOff = this->GetTimeOffset( );
+  for( unsigned int i = 0; i < this->m_MeasureSize; i++ )
+  {
+    this->m_A[ i ][ this->m_MeasureSize + i ] = tOff;
+    this->m_H[ i ][ i ] = TScalar( 1 );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+KalmanVelocityFilter( )
+  : Superclass( )
+{
+  this->Configure( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< typename T >
+cpExtensions::Algorithms::KalmanVelocityFilter< T >::
+~KalmanVelocityFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+// Explicit instantiations
+
+template class cpExtensions::Algorithms::KalmanVelocityFilter< float >;
+template class cpExtensions::Algorithms::KalmanVelocityFilter< double >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/KalmanVelocityFilter.h b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.h
new file mode 100644 (file)
index 0000000..c32dde6
--- /dev/null
@@ -0,0 +1,66 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__
+
+#include <cpExtensions/Algorithms/KalmanFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< typename T >
+    class cpExtensions_EXPORT KalmanVelocityFilter
+      : public KalmanFilter< T >
+    {
+    public:
+      typedef KalmanVelocityFilter            Self;
+      typedef KalmanFilter< T >               Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::TScalar TScalar;
+      typedef typename Superclass::TMatrix TMatrix;
+      typedef typename Superclass::TVector TVector;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( KalmanVelocityFilter, KalmanFilter );
+
+      kalmanGetSetMacro( TMatrix, Sigma );
+      kalmanGetSetMatrixMacro( Sigma, AccelerationNoise );
+
+    public:
+      void Configure( unsigned int m );
+
+      TScalar GetTimeOffset( ) const;
+      void SetTimeOffset( TScalar t );
+
+      /// Iteration methods
+      virtual void Initialize( ) cpExtensions_OVERRIDE;
+
+    protected:
+        KalmanVelocityFilter( );
+        virtual ~KalmanVelocityFilter( );
+
+    private:
+        // Purposely not implemented.
+        KalmanVelocityFilter( const Self& );
+        void operator=( const Self& );
+
+    protected:
+        TMatrix m_TimeOffset;
+        TMatrix m_Sigma;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/LightCompensationFilter.h b/lib/cpExtensions/Algorithms/LightCompensationFilter.h
new file mode 100644 (file)
index 0000000..a3c28ff
--- /dev/null
@@ -0,0 +1,65 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__
+
+#include <itkInPlaceImageFilter.h>
+#include <cpExtensions/Algorithms/ParallelImageMean.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I >
+    class LightCompensationFilter
+      : public itk::InPlaceImageFilter< I, I >
+    {
+    public:
+      typedef LightCompensationFilter         Self;
+      typedef itk::InPlaceImageFilter< I, I > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef I TImage;
+      typedef typename I::RegionType TRegion;
+
+      typedef cpExtensions::Algorithms::ParallelImageMean< I > TMeanCalculator;
+      typedef typename TMeanCalculator::TMean TMean;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( LightCompensationFilter, itkInPlaceImageFilter );
+
+      itkGetConstMacro( Mean, TMean );
+
+    protected:
+      LightCompensationFilter( );
+      virtual ~LightCompensationFilter( );
+
+    private:
+      virtual void BeforeThreadedGenerateData( );
+      virtual void ThreadedGenerateData(
+        const TRegion& region, itk::ThreadIdType id
+        );
+      virtual void AfterThreadedGenerateData( );
+
+    protected:
+      TMean m_Mean;
+      TMean m_Coefficient;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include <cpExtensions/Algorithms/LightCompensationFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/LightCompensationFilter.hxx b/lib/cpExtensions/Algorithms/LightCompensationFilter.hxx
new file mode 100644 (file)
index 0000000..f75ffcd
--- /dev/null
@@ -0,0 +1,96 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__
+
+#include <itkImageRegionIterator.h>
+#include <itkImageRegionConstIterator.h>
+#include <itkNumericTraits.h>
+
+// -------------------------------------------------------------------------
+template< class I >
+cpExtensions::Algorithms::LightCompensationFilter< I >::
+LightCompensationFilter( )
+  : Superclass( )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+  this->InPlaceOff( );
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+cpExtensions::Algorithms::LightCompensationFilter< I >::
+~LightCompensationFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+void cpExtensions::Algorithms::LightCompensationFilter< I >::
+BeforeThreadedGenerateData( )
+{
+  this->Superclass::BeforeThreadedGenerateData( );
+
+  I* input = const_cast< I* >( this->GetInput( ) );
+
+  typename TMeanCalculator::Pointer mc = TMeanCalculator::New( );
+  mc->Execute( input, input->GetRequestedRegion( ) );
+  this->m_Mean = mc->GetMean( );
+
+  double gm = this->m_Mean[ 0 ] + this->m_Mean[ 1 ] + this->m_Mean[ 2 ];
+  gm /= double( 3 );
+  this->m_Coefficient = this->m_Mean;
+  this->m_Coefficient.Fill( gm );
+  this->m_Coefficient[ 0 ] /= this->m_Mean[ 0 ];
+  this->m_Coefficient[ 1 ] /= this->m_Mean[ 1 ];
+  this->m_Coefficient[ 2 ] /= this->m_Mean[ 2 ];
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+void cpExtensions::Algorithms::LightCompensationFilter< I >::
+ThreadedGenerateData( const TRegion& region, itk::ThreadIdType id )
+{
+  typedef itk::NumericTraits< typename I::PixelType > _TPixelTraits;
+  typedef typename _TPixelTraits::ValueType           _TPixelChannel;
+  typedef itk::NumericTraits< _TPixelChannel >        _TChannelTraits;
+  static const double max_value = double( _TChannelTraits::max( ) );
+
+  itk::ImageRegionConstIterator< I > iIt( this->GetInput( ), region );
+  itk::ImageRegionIterator< I > oIt( this->GetOutput( ), region );
+
+  iIt.GoToBegin( );
+  oIt.GoToBegin( );
+  for( ; !iIt.IsAtEnd( ); ++iIt, ++oIt )
+  {
+    double r = double( iIt.Get( )[ 0 ] ) * this->m_Coefficient[ 0 ];
+    double g = double( iIt.Get( )[ 1 ] ) * this->m_Coefficient[ 1 ];
+    double b = double( iIt.Get( )[ 2 ] ) * this->m_Coefficient[ 2 ];
+
+    if( r > max_value ) r = max_value;
+    if( g > max_value ) g = max_value;
+    if( b > max_value ) b = max_value;
+
+    typename I::PixelType pix;
+    pix.SetRed( _TPixelChannel( r ) );
+    pix.SetGreen( _TPixelChannel( g ) );
+    pix.SetBlue( _TPixelChannel( b ) );
+
+    oIt.Set( pix );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+void cpExtensions::Algorithms::LightCompensationFilter< I >::
+AfterThreadedGenerateData( )
+{
+  this->Superclass::AfterThreadedGenerateData( );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/MFluxMedialness.h b/lib/cpExtensions/Algorithms/MFluxMedialness.h
new file mode 100644 (file)
index 0000000..97bc44f
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__
+#define __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__
+
+#include <cpExtensions/Algorithms/GradientImageFunctionBase.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TGradient, class _TMask = itk::Image< unsigned char, _TGradient::ImageDimension > >
+    class MFluxMedialness
+      : public GradientImageFunctionBase< _TGradient, _TMask >
+    {
+    public:
+      typedef MFluxMedialness                                 Self;
+      typedef GradientImageFunctionBase< _TGradient, _TMask > Superclass;
+      typedef itk::SmartPointer< Self >                       Pointer;
+      typedef itk::SmartPointer< const Self >                 ConstPointer;
+
+      itkStaticConstMacro( Dimension, unsigned int, Superclass::Dimension );
+
+      typedef typename Superclass::TOutput TOutput;
+      typedef typename Superclass::TScalar TScalar;
+      typedef typename Superclass::TIndex  TIndex;
+      typedef typename Superclass::TVector TVector;
+      typedef typename Superclass::TPoint  TPoint;
+
+      typedef std::vector< double > TRCandidates;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( MFluxMedialness, GradientImageFunctionBase );
+
+      itkGetConstMacro( RadiusStep, double );
+      itkGetConstMacro( MinRadius, double );
+      itkGetConstMacro( MaxRadius, double );
+      itkGetConstMacro( RadialSampling, unsigned int );
+
+      itkSetMacro( RadiusStep, double );
+      itkSetMacro( MinRadius, double );
+      itkSetMacro( MaxRadius, double );
+      itkSetMacro( RadialSampling, unsigned int );
+
+    protected:
+      MFluxMedialness( );
+      virtual ~MFluxMedialness( );
+
+      virtual TOutput _Evaluate( const TIndex& i ) const cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented.
+      MFluxMedialness( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      double       m_MinRadius;
+      double       m_MaxRadius;
+      unsigned int m_RadialSampling;
+      double       m_RadiusStep;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/MFluxMedialness.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/MFluxMedialness.hxx b/lib/cpExtensions/Algorithms/MFluxMedialness.hxx
new file mode 100644 (file)
index 0000000..bc5db37
--- /dev/null
@@ -0,0 +1,159 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__
+
+#include <cmath>
+#include <vnl/vnl_math.h>
+#include <itkLineConstIterator.h>
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >::
+MFluxMedialness( )
+  : Superclass( ),
+    m_MinRadius( double( 0 ) ),
+    m_MaxRadius( double( 1 ) ),
+    m_RadialSampling( 4 ),
+    m_RadiusStep( double( 1 ) )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >::
+~MFluxMedialness( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TGradient, class _TMask >
+typename cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >::
+TOutput cpExtensions::Algorithms::MFluxMedialness< _TGradient, _TMask >::
+_Evaluate( const TIndex& i ) const
+{
+  itk::Object::GlobalWarningDisplayOff( );
+
+  double pi2n = double( 2 ) * double( vnl_math::pi );
+  pi2n /= int( this->m_RadialSampling );
+  const _TGradient* img = this->GetInputImage( );
+  //const itk::Image::SpacingType& input_spacing = img->GetSpacing( );
+
+  double Flux1 = 0;
+  double Flux2 = 0;
+  double MFlux = 0;
+
+  TRCandidates FluxFinal;
+  TRCandidates radiusGenerated;
+  double dR = double( 0 );
+  double optR = double( 0 );
+  TPoint center;
+  img->TransformIndexToPhysicalPoint( i, center );
+  double radius;
+
+  for( unsigned int cx = 0; cx < Self::Dimension - 1; cx++ )
+  {
+    for( unsigned int cy = cx + 1; cy < Self::Dimension; cy++ )
+    {
+      dR = double( 0 );
+      FluxFinal.clear();
+      radiusGenerated.clear();
+      radius = this->m_MinRadius;
+      while( radius <= this->m_MaxRadius )
+      {
+        MFlux = 0;
+        for( unsigned int I_radial = 0; I_radial < this->m_RadialSampling / 2; I_radial++ )
+        {
+          Flux1 = 0;
+          Flux2 = 0;
+
+          // Direction of first profile
+          typename TPoint::VectorType dir1;
+          dir1.Fill( double( 0 ) );
+          dir1[ cx ] = std::cos( pi2n * double( I_radial ) );
+          dir1[ cy ] = std::sin( pi2n * double( I_radial ) );
+          //dir1 *= (radius);
+
+          TIndex rIdx;
+
+          if ( img->TransformPhysicalPointToIndex( center + (dir1*radius), rIdx ) )
+          {
+            TVector grad_rIdx = img->GetPixel( rIdx );
+            TVector u_i1;
+            u_i1.SetVnlVector( ( center - ( center + dir1 ) ).GetVnlVector( ) );
+            u_i1.Normalize( );
+            // dot product
+            Flux1 = grad_rIdx * u_i1;
+          }
+          else
+          {
+            //if (Self::Dimension==3)
+            //{
+            //std::cout<<"Point Edge x:"<<center[0]+dir1[0] ;
+            //std::cout<<" y:"<<center[1]+dir1[1]<<" z:"<<center[2]+dir1[2]<<std::endl;
+            //}
+            //else if (Self::Dimension==2)
+            //{
+            //std::cout<<"Point Edge x:"<<center[0]+dir1[0] ;
+            //std::cout<<" y:"<<center[1]+dir1[1]<<std::endl;
+            //}
+          }
+
+          // Direction of second profile
+          // pi2n*Iradial + 180°
+          typename TPoint::VectorType dir2;
+          dir2.Fill( double( 0 ) );
+          dir2[ cx ] =  std::cos( (pi2n) * double( I_radial ) + double( vnl_math::pi ));
+          dir2[ cy ] =  std::sin( (pi2n) * double( I_radial ) + double( vnl_math::pi ));
+
+          TIndex rIdx2;
+
+          if ( img->TransformPhysicalPointToIndex( center + (dir2*radius), rIdx2 ) )
+          {
+            TVector grad_rIdx2 = img->GetPixel( rIdx2 );
+            TVector u_i2;
+            u_i2.SetVnlVector( ( center - ( center + dir2 ) ).GetVnlVector( ) );
+            u_i2.Normalize( );
+
+            Flux2 = grad_rIdx2 * u_i2;
+          }
+          else
+          {
+            //if (Self::Dimension==3)
+            //{
+            //std::cout<<"Point Edge x:"<<center[0]+dir2[0] ;
+            //std::cout<<" y:"<<center[1]+dir2[1]<<" z:"<<center[2]+dir2[2]<<std::endl;
+            //}
+            //else if (Self::Dimension==2)
+            //{
+            //std::cout<<"Point Edge x:"<<center[0]+dir2[0] ;
+            //std::cout<<" y:"<<center[1]+dir2[1]<<std::endl;
+            //}
+          }
+
+          MFlux += std::min( Flux1, Flux2 );
+        } // rof
+
+        //std::cout<<Self::Dimension<<" radius:"<<radius<<std::endl;
+        //std::cout<<"Center:"<<center[0]<<" "<<center[1]<<std::endl;
+        //std::cout<<"edge:"<<center[0]+radius*std::cos( pi2n * double( 0 ) )<<std::endl;
+
+        MFlux *= 2;
+        MFlux /= this->m_RadialSampling;
+        FluxFinal.push_back(MFlux);
+        radiusGenerated.push_back(radius);
+
+        radius += this->m_RadiusStep;
+
+      }     //elihw
+
+      dR= *( std::max_element( FluxFinal.begin(), FluxFinal.end() ) );
+      optR= (dR>optR)? dR:optR;
+
+    } // rof
+
+  } // rof
+  return( TScalar(optR) );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/MacheteImageFilter.h b/lib/cpExtensions/Algorithms/MacheteImageFilter.h
new file mode 100644 (file)
index 0000000..d9d3c32
--- /dev/null
@@ -0,0 +1,72 @@
+// -------------------------------------------------------------------------
+// @author Jose Luis Guzman (cycopepe@gmail.com)
+// -------------------------------------------------------------------------
+
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__
+
+#include <cpExtensions/cpExtensions_Export.h>
+
+#include <itkImageToImageFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    template< class I, class O>
+    class MacheteImageFilter :public itk::ImageToImageFilter < I, O >
+    {
+    public:
+      /** Standard class typedefs. */
+      typedef MacheteImageFilter             Self;
+
+      typedef itk::ImageToImageFilter< I, O > Superclass;
+      typedef itk::SmartPointer< Self >        Pointer;
+
+      /** Method for creation through the object factory. */
+      itkNewMacro(Self);
+
+      /** Run-time type information (and related methods). */
+      itkTypeMacro(MacheteImageFilter, ImageToImageFilter);
+      
+      typedef typename I::PixelType           RadiusType;
+      //typedef typename I::SizeValueType      RadiusValueType;
+      
+      itkGetConstReferenceMacro(Radius, RadiusType);
+
+      
+      void SetRadius(const RadiusType & rad);
+      //void SetRadius(const RadiusValueType & rad);
+
+      void SetPoint(itk::Point<double, 3> & point);
+      void SetPoint(const double & x, const double & y, const double & z);
+
+    protected:
+      MacheteImageFilter(){}
+      ~MacheteImageFilter(){}
+
+      /** Does the real work. */
+      virtual void GenerateData();
+
+      RadiusType m_Radius;
+      itk::Point<double, 3> point;
+
+    private:
+      MacheteImageFilter(const Self &); //purposely not implemented
+      void operator=(const Self &);  //purposely not implemented
+
+     
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include <cpExtensions/Algorithms/MacheteImageFilter.hxx>
+#endif
+
+
+#endif // __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__
\ No newline at end of file
diff --git a/lib/cpExtensions/Algorithms/MacheteImageFilter.hxx b/lib/cpExtensions/Algorithms/MacheteImageFilter.hxx
new file mode 100644 (file)
index 0000000..a984df1
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__HXX__
+
+#include <cpExtensions/Algorithms/MacheteImageFilter.h>
+
+//filter stuff
+#include "itkObjectFactory.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+
+//typedef itk::Image<unsigned char, 2>  ImageType;
+
+template< class I, class O>
+void cpExtensions::Algorithms::MacheteImageFilter<  I, O>
+::GenerateData()
+{
+  //const typename Superclass::OutputImageRegionType& region;
+
+  typename I::ConstPointer input = this->GetInput();
+
+  typename O::Pointer output = this->GetOutput();
+  output->SetRegions(input->GetLargestPossibleRegion());
+  output->Allocate();
+
+  itk::ImageRegionIterator<O> outputIterator(output, output->GetLargestPossibleRegion());
+  itk::ImageRegionConstIterator<I> inputIterator(input, input->GetLargestPossibleRegion());
+
+  while (!outputIterator.IsAtEnd())
+  {
+    auto p0 = inputIterator.GetIndex();
+    itk::Point<double, 3> otherPoint;
+    otherPoint[0] = p0[0];
+    otherPoint[1] = p0[1];
+    otherPoint[2] = p0[2];
+    //otherPoint[2] = this->point[2]; // TODO : Solve this hammer
+
+    double dist = this->point.EuclideanDistanceTo(otherPoint);
+    if (dist <= this->m_Radius)
+    {
+      outputIterator.Set(0);
+    }
+    else
+    {
+      outputIterator.Set(inputIterator.Get());
+    }
+
+    ++inputIterator;
+    ++outputIterator;
+  }
+
+  
+}
+
+template< class I, class O>
+void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetRadius(const RadiusType & rad)
+{
+  if (this->m_Radius != rad)
+  {
+    this->m_Radius = rad;
+    this->Modified();
+  }
+}
+
+//template< class I, class O>
+//void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetRadius(const RadiusValueType & rad)
+//{
+//  RadiusType r;
+//  r.Fill(rad);
+//  this->SetRadius(r);
+//}
+
+template< class I, class O>
+void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetPoint(itk::Point<double, 3> & p){
+  if (point != p)
+  {
+    this->point = p;
+    this->Modified();
+  }
+}
+
+template< class I, class O>
+void cpExtensions::Algorithms::MacheteImageFilter< I, O>::SetPoint(const double & x, const double & y, const double & z)
+{
+  this->point[0] = x;
+  this->point[1] = y;
+  this->point[2] = z;
+  this->Modified();
+}
+
+
+
+#endif
\ No newline at end of file
diff --git a/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h
new file mode 100644 (file)
index 0000000..63fb8a8
--- /dev/null
@@ -0,0 +1,86 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__h__
+#define __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__h__
+
+#include <cpExtensions/Config.h>
+#include <set>
+#include <itkImageToImageFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I, class O >
+    class MultiScaleGaussianImageFilter
+      : public itk::ImageToImageFilter< I, O >
+    {
+    public:
+      typedef MultiScaleGaussianImageFilter   Self;
+      typedef itk::ImageToImageFilter< I, O > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef I TInputImage;
+      typedef O TOutputImage;
+
+      typedef std::set< double > TScalesContainer;
+
+    protected:
+      /**
+       */
+      class _Greater
+      {
+      public:
+        typedef typename O::PixelType _T;
+
+      public:
+        _Greater( );
+        virtual ~_Greater( );
+        bool operator!=( const _Greater& b ) const;
+        bool operator==( const _Greater& b ) const;
+        inline _T operator()( const _T& a ) const;
+        inline _T operator()( const _T& a, const _T& b ) const;
+      };
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( MultiScaleGaussianImageFilter, itkImageToImageFilter );
+
+    public:
+      void AddScale( const double& s );
+      unsigned long GetNumberOfScales( ) const;
+
+    protected:
+      MultiScaleGaussianImageFilter( );
+      virtual ~MultiScaleGaussianImageFilter( );
+
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+      template< class F >
+      void _GenerateData( );
+
+    private:
+      // Purposely not implemented.
+      MultiScaleGaussianImageFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      TScalesContainer m_Scales;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx
new file mode 100644 (file)
index 0000000..985cbec
--- /dev/null
@@ -0,0 +1,226 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__hxx__
+#define __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__hxx__
+
+#include <vnl/vnl_vector.h>
+
+#include <itkImageRegionIterator.h>
+#include <itkImageRegionConstIterator.h>
+#include <itkNumericTraits.h>
+#include <itkProgressAccumulator.h>
+
+#include <itkBinaryFunctorImageFilter.h>
+#include <itkUnaryFunctorImageFilter.h>
+#include <itkGradientRecursiveGaussianImageFilter.h>
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+_Greater( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+~_Greater( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+bool cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+operator!=( const _Greater& b ) const
+{
+  return( false );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+bool cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+operator==( const _Greater& b ) const
+{
+  return !( *this != b );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+typename cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+_T cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+operator()( const _T& a ) const
+{
+  return( a );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+typename cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+_T cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::_Greater::
+operator()( const _T& a, const _T& b ) const
+{
+  typedef itk::NumericTraits< _T >     _TTraits;
+  typedef typename _TTraits::ValueType _TValue;
+  typedef vnl_vector< _TValue >        _TVector;
+
+  _TVector va( _TTraits::GetLength( ) );
+  _TVector vb( _TTraits::GetLength( ) );
+
+  _TTraits::AssignToArray( a, va );
+  _TTraits::AssignToArray( b, vb );
+  return( ( vb.magnitude( ) < va.magnitude( ) )? a: b );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+void
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::
+AddScale( const double& s )
+{
+  if( this->m_Scales.insert( s ).second )
+    this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+unsigned long
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::
+GetNumberOfScales( ) const
+{
+  return( this->m_Scales.size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::
+MultiScaleGaussianImageFilter( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::
+~MultiScaleGaussianImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+void
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::
+GenerateData( )
+{
+  typedef itk::GradientRecursiveGaussianImageFilter< I, O > _TGF;
+  this->_GenerateData< _TGF >( );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+template< class F >
+void
+cpExtensions::Algorithms::
+MultiScaleGaussianImageFilter< I, O >::
+_GenerateData( )
+{
+  // Some types
+  typedef itk::BinaryFunctorImageFilter< O, O, O, _Greater > _TMaxFilter;
+  typedef itk::UnaryFunctorImageFilter< O, O, _Greater >     _TCopyFilter;
+  typedef itk::ImageRegionConstIterator< O >                 _TConstIt;
+  typedef itk::ImageRegionIterator< O >                      _TIt;
+  typedef itk::ProgressAccumulator                           _TProgress;
+
+  // Some values
+  typename I::ConstPointer input = this->GetInput( );
+  typename O::Pointer output = this->GetOutput( );
+  unsigned int nThreads = this->GetNumberOfThreads( );
+  float fw = float( 1 ) / float( this->m_Scales.size( ) << 1 );
+
+  // Progress accumulator
+  _TProgress::Pointer pg = _TProgress::New( );
+  pg->SetMiniPipelineFilter( this );
+
+  // Copy image information
+  output->SetLargestPossibleRegion( input->GetLargestPossibleRegion( ) );
+  output->SetRequestedRegion( input->GetRequestedRegion( ) );
+  output->SetBufferedRegion( input->GetBufferedRegion( ) );
+  output->SetSpacing( input->GetSpacing( ) );
+  output->SetOrigin( input->GetOrigin( ) );
+  output->SetDirection( input->GetDirection( ) );
+  output->Allocate( );
+
+  // Intermediary buffer
+  typename O::Pointer buffer = O::New( );
+  buffer->SetLargestPossibleRegion( input->GetLargestPossibleRegion( ) );
+  buffer->SetRequestedRegion( input->GetRequestedRegion( ) );
+  buffer->SetBufferedRegion( input->GetBufferedRegion( ) );
+  buffer->SetSpacing( input->GetSpacing( ) );
+  buffer->SetOrigin( input->GetOrigin( ) );
+  buffer->SetDirection( input->GetDirection( ) );
+  buffer->Allocate( );
+
+  // Perform all scales
+  _TIt gIt( output, output->GetRequestedRegion( ) );
+  TScalesContainer::const_iterator sIt = this->m_Scales.begin( );
+  for( ; sIt != this->m_Scales.end( ); sIt++ )
+  {
+    // Single scale filter
+    typename F::Pointer filter = F::New( );
+    filter->SetInput( input );
+    filter->SetNormalizeAcrossScale( true );
+    filter->SetNumberOfThreads( nThreads );
+    filter->SetSigma( *sIt );
+    pg->RegisterInternalFilter( filter, fw );
+    filter->GraftOutput( buffer );
+    filter->Update( );
+    buffer->Graft( filter->GetOutput( ) );
+
+    // Get maximum response
+    if( sIt == this->m_Scales.begin( ) )
+    {
+      // Copy first result
+      typename _TCopyFilter::Pointer copy = _TCopyFilter::New( );
+      copy->SetInput( buffer );
+      copy->InPlaceOff( );
+      copy->SetNumberOfThreads( nThreads );
+      pg->RegisterInternalFilter( copy, fw );
+      copy->GraftOutput( output );
+      copy->Update( );
+      output->Graft( copy->GetOutput( ) );
+    }
+    else
+    {
+      // Maximize results
+      typename _TMaxFilter::Pointer max = _TMaxFilter::New( );
+      max->SetInput1( output );
+      max->SetInput2( buffer );
+      max->InPlaceOn( );
+      max->SetNumberOfThreads( nThreads );
+      pg->RegisterInternalFilter( max, fw );
+      max->GraftOutput( output );
+      max->Update( );
+      output->Graft( max->GetOutput( ) );
+
+    } // fi
+
+  } // rof
+}
+
+#endif // __cpExtensions__Algorithms__MultiScaleGaussianImageFilter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ParallelImageMean.h b/lib/cpExtensions/Algorithms/ParallelImageMean.h
new file mode 100644 (file)
index 0000000..6122ce3
--- /dev/null
@@ -0,0 +1,70 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__
+#define __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__
+
+#include <itkDomainThreader.h>
+#include <itkThreadedImageRegionPartitioner.h>
+#include <itkArray.h>
+#include <itkNumericTraits.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I >
+    class ParallelImageMean
+      : public itk::DomainThreader< itk::ThreadedImageRegionPartitioner< I::ImageDimension >, I >
+    {
+    public:
+      // Standard ITK typedefs.
+      typedef itk::DomainThreader< itk::ThreadedImageRegionPartitioner< I::ImageDimension >, I > Superclass;
+      typedef ParallelImageMean               Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef typename Superclass::DomainType DomainType;
+
+      typedef itk::Array< double > TMean;
+
+    protected:
+      typedef itk::NumericTraits< typename I::PixelType > _TPixelTraits;
+
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( ParallelImageMean, itkDomainThreader );
+
+      itkGetConstMacro( Mean, TMean );
+
+    protected:
+      ParallelImageMean( );
+      virtual ~ParallelImageMean( );
+
+    private:
+      virtual void BeforeThreadedExecution( );
+      virtual void ThreadedExecution(
+        const DomainType& region, const itk::ThreadIdType id
+        );
+      virtual void AfterThreadedExecution( );
+
+    protected:
+      itk::Array< double > m_Mean;
+      unsigned long m_N;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include <cpExtensions/Algorithms/ParallelImageMean.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/ParallelImageMean.hxx b/lib/cpExtensions/Algorithms/ParallelImageMean.hxx
new file mode 100644 (file)
index 0000000..b3e4716
--- /dev/null
@@ -0,0 +1,65 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__
+
+#include <itkImageRegionConstIterator.h>
+
+// -------------------------------------------------------------------------
+template< class I >
+cpExtensions::Algorithms::ParallelImageMean< I >::
+ParallelImageMean( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+cpExtensions::Algorithms::ParallelImageMean< I >::
+~ParallelImageMean( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+void cpExtensions::Algorithms::ParallelImageMean< I >::
+BeforeThreadedExecution( )
+{
+  this->m_Mean.SetSize( _TPixelTraits::GetLength( ) );
+  this->m_Mean.Fill( double( 0 ) );
+  this->m_N = 0;
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+void cpExtensions::Algorithms::ParallelImageMean< I >::
+ThreadedExecution( const DomainType& region, const itk::ThreadIdType id )
+{
+  itk::ImageRegionConstIterator< I > i( this->m_Associate, region );
+  for( i.GoToBegin( ); !i.IsAtEnd( ); ++i )
+  {
+    for( unsigned int d = 0; d < _TPixelTraits::GetLength( ); ++d )
+    {
+      this->m_Mean.SetElement(
+        d, this->m_Mean.GetElement( d ) + double( i.Get( )[ d ] )
+        );
+      this->m_N++;
+
+    } // rof
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+template< class I >
+void cpExtensions::Algorithms::ParallelImageMean< I >::
+AfterThreadedExecution( )
+{
+  this->m_Mean /= double( this->m_N );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.cxx b/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.cxx
new file mode 100644 (file)
index 0000000..9eecda1
--- /dev/null
@@ -0,0 +1,94 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#include <cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h>
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+_TPolyLine* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+GetInput( )
+{
+  return( dynamic_cast< _TPolyLine* >( this->Superclass::GetInput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+const _TPolyLine* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+GetInput( ) const
+{
+  return( dynamic_cast< const _TPolyLine* >( this->Superclass::GetInput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+void cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+SetInput( _TPolyLine* pl )
+{
+  this->Superclass::SetNthInput( 0, pl );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+_TCurve* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+GetOutput( )
+{
+  return( dynamic_cast< _TCurve* >( this->Superclass::GetOutput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+const _TCurve* cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+GetOutput( ) const
+{
+  return( dynamic_cast< const _TCurve* >( this->Superclass::GetOutput( 0 ) ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+PolyLineParametricPathToSimple3DCurve( )
+  : Superclass( ),
+    m_NumberOfSamples( 0 )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+  this->SetNumberOfRequiredOutputs( 1 );
+  typename _TCurve::Pointer curve = _TCurve::New( );
+  this->Superclass::SetNthOutput( 0, curve );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+~PolyLineParametricPathToSimple3DCurve( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine, class _TCurve >
+void cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPolyLine, _TCurve >::
+GenerateData( )
+{
+  const _TPolyLine* line = this->GetInput( );
+  _TCurve* curve = this->GetOutput( );
+  unsigned long N = this->m_NumberOfSamples;
+  if( N == 0 )
+    N = line->GetSize( );
+  curve->Clear( );
+
+  for( unsigned long n = 0; n < N; ++n )
+  {
+    double u = double( n ) / double( N - 1 );
+    curve->AddPoint( line->GetSmoothPoint( u ) );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+#include <cpExtensions/DataStructures/PolyLineParametricPath.h>
+#include <cpExtensions/DataStructures/Simple3DCurve.h>
+
+template class cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< cpExtensions::DataStructures::PolyLineParametricPath< 3 >, cpExtensions::DataStructures::Simple3DCurve< float > >; 
+template class cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< cpExtensions::DataStructures::PolyLineParametricPath< 3 >, cpExtensions::DataStructures::Simple3DCurve< double > >; 
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h b/lib/cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h
new file mode 100644 (file)
index 0000000..5282e88
--- /dev/null
@@ -0,0 +1,65 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__PolyLineParametricPathToSimple3DCurve__h__
+#define __cpExtensions__Algorithms__PolyLineParametricPathToSimple3DCurve__h__
+
+#include <cpExtensions/Config.h>
+#include <itkProcessObject.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TPolyLine, class _TCurve >
+    class cpExtensions_EXPORT PolyLineParametricPathToSimple3DCurve
+      : public itk::ProcessObject
+    {
+    public:
+      // Basic types
+      typedef PolyLineParametricPathToSimple3DCurve Self;
+      typedef itk::ProcessObject                    Superclass;
+      typedef itk::SmartPointer< Self >             Pointer;
+      typedef itk::SmartPointer< const Self >       ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( PolyLineParametricPathToSimple3DCurve, itk::ProcessObject );
+
+      itkGetConstMacro( NumberOfSamples, unsigned long );
+      itkSetMacro( NumberOfSamples, unsigned long );
+
+    public:
+      _TPolyLine* GetInput( );
+      const _TPolyLine* GetInput( ) const;
+      void SetInput( _TPolyLine* pl );
+
+      _TCurve* GetOutput( );
+      const _TCurve* GetOutput( ) const;
+
+    protected:
+      PolyLineParametricPathToSimple3DCurve( );
+      virtual ~PolyLineParametricPathToSimple3DCurve( );
+
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      PolyLineParametricPathToSimple3DCurve( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      unsigned long m_NumberOfSamples;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Algorithms__PolyLineParametricPathToSimple3DCurve__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.h b/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.h
new file mode 100644 (file)
index 0000000..f699602
--- /dev/null
@@ -0,0 +1,69 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__PolyLineParametricPathWriter__h__
+#define __cpExtensions__Algorithms__PolyLineParametricPathWriter__h__
+
+#include <itkProcessObject.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TPolyLine >
+    class PolyLineParametricPathWriter
+      : public itk::ProcessObject
+    {
+    public:
+      // Basic types
+      typedef PolyLineParametricPathWriter Self;
+      typedef itk::ProcessObject                    Superclass;
+      typedef itk::SmartPointer< Self >             Pointer;
+      typedef itk::SmartPointer< const Self >       ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( PolyLineParametricPathWriter, itk::ProcessObject );
+
+      itkGetConstMacro( FileName, std::string );
+      itkGetConstMacro( NumberOfPoints, long );
+
+      itkSetMacro( FileName, std::string );
+      itkSetMacro( NumberOfPoints, long );
+
+    public:
+      void SetInput( const _TPolyLine* input );
+      const _TPolyLine* GetInput( );
+      virtual void Update( );
+
+    protected:
+      PolyLineParametricPathWriter( );
+      virtual ~PolyLineParametricPathWriter( );
+
+      virtual void GenerateData( ) override;
+
+    private:
+      // Purposely not implemented
+      PolyLineParametricPathWriter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      std::string m_FileName;
+      long m_NumberOfPoints;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__PolyLineParametricPathWriter__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx b/lib/cpExtensions/Algorithms/PolyLineParametricPathWriter.hxx
new file mode 100644 (file)
index 0000000..8e9db8e
--- /dev/null
@@ -0,0 +1,128 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__PolyLineParametricPathWriter__hxx__
+#define __cpExtensions__Algorithms__PolyLineParametricPathWriter__hxx__
+
+#include <sstream>
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+void cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >::
+SetInput( const _TPolyLine* input )
+{
+  this->itk::ProcessObject::SetNthInput(
+    0, const_cast< _TPolyLine* >( input )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+const _TPolyLine*
+cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >::
+GetInput( )
+{
+  return(
+    dynamic_cast< const _TPolyLine* >(
+      this->itk::ProcessObject::GetInput( 0 )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+void cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >::
+Update( )
+{
+  _TPolyLine* input = const_cast< _TPolyLine* >( this->GetInput( ) );
+  if( input != NULL )
+  {
+    input->UpdateOutputInformation( );
+    input->UpdateOutputData( );
+    this->GenerateData( );
+    this->ReleaseInputs( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >::
+PolyLineParametricPathWriter( )
+  : Superclass( ),
+    m_FileName( "" ),
+    m_NumberOfPoints( 100 )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >::
+~PolyLineParametricPathWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+void cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLine >::
+GenerateData( )
+{
+  typedef typename _TPolyLine::TContinuousIndex _TContinuousIndex;
+
+  // "Serialize" data
+  const _TPolyLine* input = this->GetInput( );
+  unsigned int dim = _TPolyLine::PathDimension;
+  std::stringstream buffer;
+  long step = input->GetSize( ) / this->m_NumberOfPoints;
+
+  for( unsigned long i = 0; i < input->GetSize( ); i += step )
+  {
+    _TContinuousIndex idx;
+    idx.Fill( 0 );
+    int c = 0;
+    for( long j = -step; j <= step; ++j )
+    {
+      long k = i + j;
+      if( k >= 0 && k < input->GetSize( ) )
+      {
+        _TContinuousIndex kdx = input->GetContinuousVertex( k );
+        for( unsigned int d = 0; d < dim; ++d )
+          idx[ d ] += kdx[ d ];
+        c++;
+
+      } // fi
+
+    } // rof
+    if( c != 0 )
+      for( unsigned int d = 0; d < dim; ++d )
+        idx[ d ] /= c;
+
+    buffer << idx[ 0 ];
+    for( unsigned int d = 1; d < dim; ++d )
+      buffer << " " << idx[ d ];
+    buffer << std::endl;
+
+  } // rof
+
+  // Real write
+  std::ofstream file_stream(
+    this->m_FileName.c_str( ), std::ofstream::binary
+    );
+  if( !file_stream )
+  {
+    itkExceptionMacro(
+      << "Could not open file \"" << this->m_FileName << "\" to write a "
+      << "cpExtensions::DataStructures::PolyLineParametricPath< " << dim
+      << " > object."
+      );
+    return;
+
+  } // fi
+  file_stream.write( buffer.str( ).c_str( ), buffer.str( ).size( ) );
+}
+
+#endif // __cpExtensions__Algorithms__PolyLineParametricPathWriter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RGBExtractFunction.h b/lib/cpExtensions/Algorithms/RGBExtractFunction.h
new file mode 100644 (file)
index 0000000..ec7126b
--- /dev/null
@@ -0,0 +1,54 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__
+#define __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__
+
+#include <cmath>
+#include <limits>
+#include <vnl/vnl_math.h>
+
+#include <itkRGBPixel.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class P >
+    struct RGBExtractFunction
+    {
+      typedef RGBExtractFunction    Self;
+      typedef P                     TOutPixel;
+      typedef typename P::ValueType TValue;
+
+      template< class Tr, class Tg, class Tb >
+      P operator()( const Tr& r, const Tg& g, const Tb& b ) const
+        {
+          P out;
+          out[ 0 ] = TValue( r );
+          out[ 1 ] = TValue( g );
+          out[ 2 ] = TValue( b );
+          return( out );
+        }
+
+      template< class C >
+      TOutPixel operator()( const itk::RGBPixel< C >& rgb ) const
+        {
+          return(
+            this->operator()(
+              rgb.GetRed( ), rgb.GetGreen( ), rgb.GetBlue( )
+              )
+            );
+        }
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h
new file mode 100644 (file)
index 0000000..4ce6754
--- /dev/null
@@ -0,0 +1,67 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__
+
+#include <itkImageToImageFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I, class O, class C >
+    class RGBImageToOtherChannelsFilter
+      : public itk::ImageToImageFilter< I, O >
+    {
+    public:
+      typedef RGBImageToOtherChannelsFilter     Self;
+      typedef itk::ImageToImageFilter< I, O > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef I TInputImage;
+      typedef O TOutputImage;
+      typedef C TConverter;
+      typedef typename I::PixelType TInputPixel;
+      typedef typename O::PixelType TOutputPixel;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( RGBImageToOtherChannelsFilter, itkImageToImageFilter );
+
+    protected:
+      RGBImageToOtherChannelsFilter( );
+      virtual ~RGBImageToOtherChannelsFilter( );
+
+      virtual void BeforeThreadedGenerateData( );
+      virtual void AfterThreadedGenerateData( );
+
+      virtual void ThreadedGenerateData(
+        const typename Superclass::OutputImageRegionType& region,
+        itk::ThreadIdType threadId
+        );
+
+    private:
+      // Purposely not implemented
+      RGBImageToOtherChannelsFilter( const Self& other );
+      void operator=( const Self& other );
+
+    private:
+      TConverter Converter;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include <cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx
new file mode 100644 (file)
index 0000000..74578d4
--- /dev/null
@@ -0,0 +1,71 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__
+
+#include <cmath>
+#include <limits>
+#include <vnl/vnl_math.h>
+
+#include <itkImageRegionIterator.h>
+#include <itkImageRegionConstIterator.h>
+
+// -------------------------------------------------------------------------
+template< class I, class O, class C >
+cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >::
+RGBImageToOtherChannelsFilter( )
+  : Superclass( )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+  this->SetNumberOfRequiredOutputs( 1 );
+
+  typename O::Pointer o = O::New( );
+  this->SetNthOutput( 0, o );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O, class C >
+cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >::
+~RGBImageToOtherChannelsFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O, class C >
+void cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >::
+BeforeThreadedGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O, class C >
+void cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >::
+AfterThreadedGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O, class C >
+void cpExtensions::Algorithms::RGBImageToOtherChannelsFilter< I, O, C >::
+ThreadedGenerateData(
+  const typename Superclass::OutputImageRegionType& region,
+  itk::ThreadIdType threadId
+  )
+{
+  // typedef typename TInputPixel::ComponentType _TComponent;
+  typedef itk::ImageRegionConstIterator< I > _TInIt;
+  typedef itk::ImageRegionIterator< O >      _TOutIt;
+
+  _TInIt inIt( this->GetInput( ), region );
+  _TOutIt outIt( this->GetOutput( ), region );
+  inIt.GoToBegin( );
+  outIt.GoToBegin( );
+  for( ; !inIt.IsAtEnd( ); ++inIt, ++outIt )
+    outIt.Set( this->Converter( inIt.Get( ) ) );
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RGBToHSVFunction.h b/lib/cpExtensions/Algorithms/RGBToHSVFunction.h
new file mode 100644 (file)
index 0000000..b10f295
--- /dev/null
@@ -0,0 +1,87 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__
+#define __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__
+
+#include <cmath>
+#include <limits>
+#include <vnl/vnl_math.h>
+
+#include <itkRGBPixel.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class P >
+    struct RGBToHSVFunction
+    {
+      typedef RGBToHSVFunction      Self;
+      typedef P                     TOutPixel;
+      typedef typename P::ValueType TValue;
+
+      template< class Tr, class Tg, class Tb >
+      P operator()( const Tr& r, const Tg& g, const Tb& b ) const
+        {
+          static const double mVal =
+            double( std::numeric_limits< TValue >::max( ) );
+          static const double _0 = double( 0 );
+          static const double _1 = double( 1 );
+          static const double _2 = double( 2 );
+          static const double _3 = double( 3 );
+          static const double _2pi = _2 * double( vnl_math::pi );
+
+          P hsv;
+
+          double R = double( r );
+          double G = double( g );
+          double B = double( b );
+          double sRGB = R + G + B;
+          double RG = R - G;
+          double RB = R - B;
+          double GB = G - B;
+
+          // Hue
+          double A = std::sqrt( ( RG * RG ) + ( RB * GB ) );
+          if( A != _0 )
+            A = std::acos( ( RG + RB ) / ( _2 * A ) );
+          A /= _2pi;
+          hsv[ 0 ] = TValue( mVal * ( ( G >= B )? A: _1 - A ) );
+
+          // Saturation
+          if( sRGB != _0 )
+          {
+            double C = ( G < R )? G: R;
+            C        = ( B < C )? B: C;
+            hsv[ 1 ] = TValue( mVal * ( _1 - ( ( _3 * C ) / sRGB ) ) );
+          }
+          else
+            hsv[ 1 ] = TValue( 0 );
+
+          // Value
+          hsv[ 2 ] = TValue( sRGB / _3 );
+          return( hsv );
+        }
+
+      template< class C >
+      TOutPixel operator()( const itk::RGBPixel< C >& rgb ) const
+        {
+          return(
+            this->operator()(
+              rgb.GetRed( ), rgb.GetGreen( ), rgb.GetBlue( )
+              )
+            );
+        }
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h b/lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h
new file mode 100644 (file)
index 0000000..83085fe
--- /dev/null
@@ -0,0 +1,72 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__
+#define __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__
+
+#include <cmath>
+#include <limits>
+#include <vnl/vnl_math.h>
+#include <vnl/vnl_matrix.h>
+
+#include <itkRGBPixel.h>
+#include <itkMatrix.h>
+#include <itkVector.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class P >
+    struct RGBToYPbPrFunction
+    {
+      typedef RGBToYPbPrFunction    Self;
+      typedef P                     TOutPixel;
+      typedef typename P::ValueType TValue;
+
+      template< class Tr, class Tg, class Tb >
+      P operator()( const Tr& r, const Tg& g, const Tb& b ) const
+        {
+          static const double M[] =
+            {
+              double(  0.2990 ), double(  0.5870 ), double(  0.1140 ),
+              double( -0.1687 ), double( -0.3313 ), double(  0.5000 ),
+              double(  0.5000 ), double( -0.4187 ), double( -0.0813 )
+            };
+          static const vnl_matrix< double > vM( M, 3, 3 );
+          static const itk::Matrix< double, 3, 3 > iM( vM );
+
+          itk::Vector< double, 3 > rgb;
+          rgb[ 0 ] = double( r );
+          rgb[ 1 ] = double( b );
+          rgb[ 2 ] = double( g );
+          rgb = iM * rgb;
+
+          P out;
+          out[ 0 ] = TValue( rgb[ 0 ] );
+          out[ 1 ] = TValue( rgb[ 1 ] );
+          out[ 2 ] = TValue( rgb[ 2 ] );
+          return( out );
+        }
+
+      template< class C >
+      TOutPixel operator()( const itk::RGBPixel< C >& rgb ) const
+        {
+          return(
+            this->operator()(
+              rgb.GetRed( ), rgb.GetGreen( ), rgb.GetBlue( )
+              )
+            );
+        }
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RasterContourFilter.h b/lib/cpExtensions/Algorithms/RasterContourFilter.h
new file mode 100644 (file)
index 0000000..4797dec
--- /dev/null
@@ -0,0 +1,105 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__RasterContourFilter__h__
+#define __cpExtensions__Algorithms__RasterContourFilter__h__
+
+#include <cpExtensions/Config.h>
+#include <itkImageSource.h>
+#include <deque>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TImage >
+    class RasterContourFilter
+      : public itk::ImageSource< _TImage >
+    {
+    public:
+      // Basic types
+      typedef RasterContourFilter             Self;
+      typedef itk::ImageSource< _TImage >     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TImage TImage;
+      typedef typename _TImage::IndexType  TIndex;
+      typedef typename _TImage::PixelType  TPixel;
+      typedef typename _TImage::PointType  TPoint;
+      typedef typename _TImage::RegionType TRegion;
+      typedef itk::ImageBase< 2 > TImageBase;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( RasterContourFilter, itk::ImageSource );
+
+      itkGetConstObjectMacro( Template, TImageBase );
+      itkGetConstMacro( InsideValue, TPixel );
+      itkGetConstMacro( OutsideValue, TPixel );
+
+      itkSetConstObjectMacro( Template, TImageBase );
+      itkSetMacro( InsideValue, TPixel );
+      itkSetMacro( OutsideValue, TPixel );
+
+    public:
+      void AddPoint( double x, double y );
+      void AddPoint( double p[ 2 ] );
+      template< class _TPoint >
+        inline void AddPoint( const _TPoint& p );
+      void ClearPoints( );
+
+    protected:
+      RasterContourFilter( );
+      virtual ~RasterContourFilter( );
+
+      virtual void AllocateOutputs( ) cpExtensions_OVERRIDE;
+      virtual void BeforeThreadedGenerateData( ) cpExtensions_OVERRIDE;
+      virtual void AfterThreadedGenerateData( ) cpExtensions_OVERRIDE;
+      virtual void ThreadedGenerateData(
+        const TRegion& region, itk::ThreadIdType id
+        ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      RasterContourFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      std::deque< TPoint > m_Contour;
+      std::deque< TIndex > m_Polygon;
+      TRegion m_ROI;
+      typename TImageBase::ConstPointer m_Template;
+      TPixel m_InsideValue;
+      TPixel m_OutsideValue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+template< class _TPoint >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+AddPoint( const _TPoint& p )
+{
+  TPoint pnt;
+  pnt[ 0 ] = p[ 0 ];
+  pnt[ 1 ] = p[ 2 ];
+  this->m_Contour.push_back( pnt );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/RasterContourFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__RasterContourFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RasterContourFilter.hxx b/lib/cpExtensions/Algorithms/RasterContourFilter.hxx
new file mode 100644 (file)
index 0000000..4e7539a
--- /dev/null
@@ -0,0 +1,172 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// ------------------------------------------------------------------------
+
+// Inclusion test taken from:
+// https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
+
+#ifndef __cpExtensions__Algorithms__RasterContourFilter__hxx__
+#define __cpExtensions__Algorithms__RasterContourFilter__hxx__
+
+#include <itkImageRegionIteratorWithIndex.h>
+#include <vtkPolygon.h>
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+AddPoint( double x, double y )
+{
+  TPoint pnt;
+  pnt[ 0 ] = x;
+  pnt[ 1 ] = y;
+  this->m_Contour.push_back( pnt );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+AddPoint( double p[ 2 ] )
+{
+  TPoint pnt;
+  pnt[ 0 ] = p[ 0 ];
+  pnt[ 1 ] = p[ 2 ];
+  this->m_Contour.push_back( pnt );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+ClearPoints( )
+{
+  this->m_Contour.clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+RasterContourFilter( )
+  : Superclass( ),
+    m_InsideValue( TPixel( 1 ) ),
+    m_OutsideValue( TPixel( 0 ) )
+{
+  this->ClearPoints( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+~RasterContourFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+AllocateOutputs( )
+{
+  _TImage* out = this->GetOutput( 0 );
+  out->SetSpacing( this->m_Template->GetSpacing( ) );
+  out->SetRegions( this->m_Template->GetRequestedRegion( ) );
+  out->SetOrigin( this->m_Template->GetOrigin( ) );
+  out->SetDirection( this->m_Template->GetDirection( ) );
+  out->Allocate( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+BeforeThreadedGenerateData( )
+{
+  // Keep just indices, not points
+  this->m_Polygon.clear( );
+  _TImage* out = this->GetOutput( 0 );
+  TIndex minIdx, maxIdx;
+  for( auto c = this->m_Contour.begin( ); c != this->m_Contour.end( ); ++c )
+  {
+    TIndex idx;
+    out->TransformPhysicalPointToIndex( *c, idx );
+    bool added = true;
+    if( this->m_Polygon.size( ) > 0 )
+    {
+      if( this->m_Polygon.back( ) != idx )
+      {
+        this->m_Polygon.push_back( idx );
+        minIdx[ 0 ] = ( idx[ 0 ] < minIdx[ 0 ] )? idx[ 0 ]: minIdx[ 0 ];
+        minIdx[ 1 ] = ( idx[ 1 ] < minIdx[ 1 ] )? idx[ 1 ]: minIdx[ 1 ];
+        maxIdx[ 0 ] = ( idx[ 0 ] > maxIdx[ 0 ] )? idx[ 0 ]: maxIdx[ 0 ];
+        maxIdx[ 1 ] = ( idx[ 1 ] > maxIdx[ 1 ] )? idx[ 1 ]: maxIdx[ 1 ];
+
+      } // fi
+    }
+    else
+    {
+      this->m_Polygon.push_back( idx );
+      minIdx = maxIdx = idx;
+
+    } // fi
+
+  } // rof
+
+  // Set ROI
+  typename _TImage::SizeType size;
+  size[ 0 ] = maxIdx[ 0 ] - minIdx[ 0 ] + 1;
+  size[ 1 ] = maxIdx[ 1 ] - minIdx[ 1 ] + 1;
+  this->m_ROI.SetIndex( minIdx );
+  this->m_ROI.SetSize( size );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+AfterThreadedGenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RasterContourFilter< _TImage >::
+ThreadedGenerateData( const TRegion& region, itk::ThreadIdType id )
+{
+  long nVerts = this->m_Polygon.size( );
+  _TImage* out = this->GetOutput( );
+  itk::ImageRegionIteratorWithIndex< _TImage > iIt( out, region );
+  for( iIt.GoToBegin( ); !iIt.IsAtEnd( ); ++iIt )
+  {
+    TIndex p = iIt.GetIndex( );
+    bool inside = false;
+    if( this->m_ROI.IsInside( p ) )
+    {
+      long i, j;
+      for( i = 0, j = nVerts - 1; i < nVerts; j = i++ )
+      {
+        TIndex pi = this->m_Polygon[ i ];
+        TIndex pj = this->m_Polygon[ j ];
+        double pi0 = double( pi[ 0 ] );
+        double pi1 = double( pi[ 1 ] );
+        double pj0 = double( pj[ 0 ] );
+        double pj1 = double( pj[ 1 ] );
+        double p0 = double( p[ 0 ] );
+        double p1 = double( p[ 1 ] );
+        double ji0 = pj0 - pi0;
+        double ji1 = pj1 - pi1;
+        double i1 = p1 - pi1;
+        if(
+          ( ( pi1 > p1 ) != ( pj1 > p1 ) ) &&
+          ( p0 < ( ( ji0 * i1 ) / ji1 ) + pi0 )
+          )
+          inside = !inside;
+
+      } // rof
+
+    } // fi
+    iIt.Set( ( inside )? this->m_InsideValue: this->m_OutsideValue );
+
+  } // rof
+}
+
+#endif // __cpExtensions__Algorithms__RasterContourFilter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h
new file mode 100644 (file)
index 0000000..84102ad
--- /dev/null
@@ -0,0 +1,73 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__
+#define __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__
+
+#include <itkObject.h>
+#include <itkObjectFactory.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TImage >
+    class RegionOfInterestImageCalculator
+      : public itk::Object
+    {
+    public:
+      // Basic types
+      typedef RegionOfInterestImageCalculator Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TImage TImage;
+      typedef typename _TImage::IndexType TIndex;
+      typedef typename _TImage::PixelType TPixel;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( RegionOfInterestImageCalculator, itkObject );
+
+      itkGetConstObjectMacro( Image, _TImage );
+      itkGetConstMacro( BackgroundValue, TPixel );
+      itkGetConstMacro( Minimum, TIndex );
+      itkGetConstMacro( Maximum, TIndex );
+
+      itkSetConstObjectMacro( Image, _TImage );
+      itkSetMacro( BackgroundValue, TPixel );
+
+    public:
+      void Compute( );
+      
+    protected:
+      RegionOfInterestImageCalculator( );
+      virtual ~RegionOfInterestImageCalculator( );
+
+    private:
+      // Purposely not implemented
+      RegionOfInterestImageCalculator( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      typename _TImage::ConstPointer m_Image;
+      TPixel m_BackgroundValue;
+      TIndex m_Minimum;
+      TIndex m_Maximum;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx
new file mode 100644 (file)
index 0000000..fd7867f
--- /dev/null
@@ -0,0 +1,92 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__
+
+#include <itkImageRegionConstIteratorWithIndex.h>
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TImage >::
+Compute( )
+{
+  typedef itk::ImageRegionConstIteratorWithIndex< _TImage > _TIterator;
+  typedef typename _TImage::RegionType _TRegion;
+
+  if( this->m_Image.IsNotNull( ) )
+  {
+    _TRegion region = this->m_Image->GetRequestedRegion( );
+    TIndex minidx = region.GetIndex( );
+    TIndex maxidx = minidx + region.GetSize( );
+    for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+      maxidx[ d ] -= 1;
+
+    bool first = true;
+    _TIterator i( this->m_Image, region );
+    for( i.GoToBegin( ); !i.IsAtEnd( ); ++i )
+    {
+      if( i.Get( ) != this->m_BackgroundValue )
+      {
+        TIndex idx = i.GetIndex( );
+        if( !first )
+        {
+          for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+          {
+            minidx[ d ] = ( idx[ d ] < minidx[ d ] )? idx[ d ]: minidx[ d ];
+            maxidx[ d ] = ( idx[ d ] > maxidx[ d ] )? idx[ d ]: maxidx[ d ];
+
+          } // rof
+        }
+        else
+        {
+          minidx = maxidx = idx;
+          first = false;
+
+        } // fi
+
+      } // fi
+
+    } // rof
+    this->m_Minimum = minidx;
+    this->m_Maximum = maxidx;
+  }
+  else
+  {
+    this->m_Minimum.Fill( 0 );
+    this->m_Maximum.Fill( 0 );
+
+  } // fi
+}
+      
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TImage >::
+RegionOfInterestImageCalculator( )
+  : Superclass( ),
+    m_BackgroundValue( TPixel( 0 ) )
+{
+  this->m_Minimum.Fill( 0 );
+  this->m_Maximum.Fill( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TImage >::
+~RegionOfInterestImageCalculator( )
+{
+}
+
+
+/* TODO
+   typename _TImage::ConstPointer m_Image;
+   TPixel m_BackgroundValue;
+   TIndex m_Minimum;
+   TIndex m_Maximum;
+   };
+*/
+
+#endif // __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SkeletonReader.h b/lib/cpExtensions/Algorithms/SkeletonReader.h
new file mode 100644 (file)
index 0000000..e1a3064
--- /dev/null
@@ -0,0 +1,85 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__SkeletonReader__h__
+#define __cpExtensions__Algorithms__SkeletonReader__h__
+
+#include <cpExtensions/Config.h>
+#include <itkProcessObject.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TSkeleton >
+    class SkeletonReader
+      : public itk::ProcessObject
+    {
+    public:
+      // Basic types
+      typedef SkeletonReader                  Self;
+      typedef itk::ProcessObject              Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TSkeleton TSkeleton;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( SkeletonReader, itk::ImageSource );
+
+      itkGetConstMacro( FileName, std::string );
+      itkSetMacro( FileName, std::string );
+
+    public:
+      TSkeleton* GetOutput( );
+      TSkeleton* GetOutput( unsigned int i );
+
+      virtual void GraftOutput( itk::DataObject* out );
+      virtual void GraftOutput(
+        const typename Superclass::DataObjectIdentifierType& key,
+        itk::DataObject* out
+        );
+      virtual void GraftNthOutput( unsigned int i, itk::DataObject* out );
+      virtual itk::DataObject::Pointer MakeOutput(
+        itk::ProcessObject::DataObjectPointerArraySizeType i
+        ) cpExtensions_OVERRIDE;
+
+      virtual void Update( ) cpExtensions_OVERRIDE
+        { this->GenerateData( ); }
+
+    protected:
+      SkeletonReader( );
+      virtual ~SkeletonReader( );
+
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+      // Do nothing
+      virtual void GenerateOutputInformation( ) cpExtensions_OVERRIDE
+        { }
+
+    private:
+      // Purposely not implemented
+      SkeletonReader( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      std::string m_FileName;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+// -------------------------------------------------------------------------
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/SkeletonReader.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__SkeletonReader__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SkeletonReader.hxx b/lib/cpExtensions/Algorithms/SkeletonReader.hxx
new file mode 100644 (file)
index 0000000..4235539
--- /dev/null
@@ -0,0 +1,176 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__SkeletonReader__hxx__
+#define __cpExtensions__Algorithms__SkeletonReader__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+_TSkeleton* cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+GetOutput( )
+{
+  return(
+    itkDynamicCastInDebugMode< TSkeleton* >( this->GetPrimaryOutput( ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+_TSkeleton* cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+GetOutput( unsigned int i )
+{
+  return(
+    itkDynamicCastInDebugMode< TSkeleton* >(
+      this->itk::ProcessObject::GetOutput( i )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+GraftOutput( itk::DataObject* out )
+{
+  this->GraftNthOutput( 0, out );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+GraftOutput(
+  const typename Superclass::DataObjectIdentifierType& key,
+  itk::DataObject* out
+  )
+{
+  if( out == NULL )
+  {
+    itkExceptionMacro(
+      << "Requested to graft output that is a NULL pointer"
+      );
+
+  } // fi
+  itk::DataObject* output = this->itk::ProcessObject::GetOutput( key );
+  output->Graft( out );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+GraftNthOutput( unsigned int i, itk::DataObject* out )
+{
+  if( i >= this->GetNumberOfIndexedOutputs( ) )
+  {
+    itkExceptionMacro(
+      << "Requested to graft output " << i
+      << " but this filter only has "
+      << this->GetNumberOfIndexedOutputs( )
+      << " indexed Outputs."
+      );
+
+  } // fi
+  this->GraftOutput( this->MakeNameFromOutputIndex( i ), out );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+itk::DataObject::Pointer
+cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+MakeOutput( itk::ProcessObject::DataObjectPointerArraySizeType i )
+{
+  return( TSkeleton::New( ).GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+SkeletonReader( )
+  : Superclass( )
+{
+  typename TSkeleton::Pointer out =
+    static_cast< TSkeleton* >( this->MakeOutput( 0 ).GetPointer( ) );
+  this->itk::ProcessObject::SetNumberOfRequiredInputs( 0 );
+  this->itk::ProcessObject::SetNumberOfRequiredOutputs( 1 );
+  this->itk::ProcessObject::SetNthOutput( 0, out.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+~SkeletonReader( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonReader< _TSkeleton >::
+GenerateData( )
+{
+  typedef typename TSkeleton::TPath         _TPath;
+  typedef typename _TPath::TSpacing         _TSpacing;
+  typedef typename _TPath::TPoint           _TPoint;
+  typedef typename _TPath::TDirection       _TDirection;
+  typedef typename _TPath::TContinuousIndex _TContinuousIndex;
+
+  std::string buffer;
+  /* TODO
+     if( !( cpExtensions::Read( buffer, this->m_FileName ) ) )
+     {
+     itkExceptionMacro(
+     << "Error reading skeleton from \"" << this->m_FileName << "\""
+     );
+     return;
+
+     } // fi
+  */
+
+  std::istringstream in( buffer );
+  unsigned int dim;
+  in >> dim;
+  if( dim != TSkeleton::Dimension )
+  {
+    itkExceptionMacro(
+      << "Mismatched skeletons dimension: " << dim
+      << " != " << TSkeleton::Dimension
+      );
+    return;
+
+  } // fi
+
+  TSkeleton* out = this->GetOutput( );
+  unsigned long size;
+  in >> size;
+  while( size > 0 )
+  {
+    _TSpacing spa;
+    _TPoint ori;
+    _TDirection dir;
+    for( unsigned int d = 0; d < dim; ++d )
+      in >> spa[ d ];
+    for( unsigned int d = 0; d < dim; ++d )
+      in >> ori[ d ];
+    for( unsigned int d = 0; d < dim; ++d )
+      for( unsigned int e = 0; e < dim; ++e )
+        in >> dir[ d ][ e ];
+
+    typename _TPath::Pointer path = _TPath::New( );
+    path->SetSpacing( spa );
+    path->SetOrigin( ori );
+    path->SetDirection( dir );
+    for( unsigned long s = 0; s < size; ++s )
+    {
+      _TContinuousIndex idx;
+      for( unsigned int d = 0; d < dim; ++d )
+        in >> idx[ d ];
+      path->AddVertex( idx );
+
+    } // rof
+    out->AddBranch( path );
+    in >> size;
+
+  } // elihw
+}
+
+#endif // __cpExtensions__Algorithms__SkeletonReader__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SkeletonToImageFilter.h b/lib/cpExtensions/Algorithms/SkeletonToImageFilter.h
new file mode 100644 (file)
index 0000000..8c9d8fe
--- /dev/null
@@ -0,0 +1,81 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__SkeletonToImageFilter__h__
+#define __cpExtensions__Algorithms__SkeletonToImageFilter__h__
+
+#include <cpExtensions/Config.h>
+#include <itkImageSource.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TSkeleton, class _TImage >
+    class SkeletonToImageFilter
+      : public itk::ImageSource< _TImage >
+    {
+    public:
+      // Basic types
+      typedef SkeletonToImageFilter           Self;
+      typedef itk::ImageSource< _TImage >     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TSkeleton TSkeleton;
+      typedef _TImage    TImage;
+      typedef typename _TImage::IndexType  TIndex;
+      typedef typename _TImage::PixelType  TPixel;
+      typedef typename _TImage::PointType  TPoint;
+      typedef typename _TImage::RegionType TRegion;
+      typedef itk::ImageBase< _TImage::ImageDimension > TImageBase;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( SkeletonToImageFilter, itk::ImageSource );
+
+      itkGetConstMacro( InsideValue, TPixel );
+      itkGetConstMacro( OutsideValue, TPixel );
+
+      itkSetMacro( InsideValue, TPixel );
+      itkSetMacro( OutsideValue, TPixel );
+
+    public:
+      const TImageBase* GetTemplateImage( ) const;
+      void SetTemplateImage( const TImageBase* image );
+
+      const TSkeleton* GetSkeleton( ) const;
+      void SetSkeleton( const TSkeleton* skeleton );
+
+    protected:
+      SkeletonToImageFilter( );
+      virtual ~SkeletonToImageFilter( );
+
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      SkeletonToImageFilter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      TPixel m_InsideValue;
+      TPixel m_OutsideValue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+// -------------------------------------------------------------------------
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/SkeletonToImageFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__SkeletonToImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SkeletonToImageFilter.hxx b/lib/cpExtensions/Algorithms/SkeletonToImageFilter.hxx
new file mode 100644 (file)
index 0000000..1f428c9
--- /dev/null
@@ -0,0 +1,119 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__SkeletonToImageFilter__hxx__
+#define __cpExtensions__Algorithms__SkeletonToImageFilter__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+const typename
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+TImageBase*
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+GetTemplateImage( ) const
+{
+  return(
+    dynamic_cast< const TImageBase* >(
+      this->itk::ProcessObject::GetInput( 0 )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+void 
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+SetTemplateImage( const TImageBase* image )
+{
+  this->itk::ProcessObject::SetNthInput(
+    0, const_cast< TImageBase* >( image )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+const typename
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+TSkeleton*
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+GetSkeleton( ) const
+{
+  return(
+    dynamic_cast< const TSkeleton* >(
+      this->itk::ProcessObject::GetInput( 1 )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+void
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+SetSkeleton( const TSkeleton* skeleton )
+{
+  this->itk::ProcessObject::SetNthInput(
+    1, const_cast< TSkeleton* >( skeleton )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+SkeletonToImageFilter( )
+  : Superclass( ),
+    m_InsideValue( TPixel( 1 ) ),
+    m_OutsideValue( TPixel( 0 ) )
+{
+  this->SetNumberOfRequiredInputs( 2 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+~SkeletonToImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton, class _TImage >
+void cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage >::
+GenerateData( )
+{
+  const TSkeleton* sk = this->GetSkeleton( );
+  const TImageBase* im = this->GetTemplateImage( );
+  TImage* out = this->GetOutput( 0 );
+
+  out->SetLargestPossibleRegion( im->GetLargestPossibleRegion( ) );
+  out->SetRequestedRegion( im->GetRequestedRegion( ) );
+  out->SetBufferedRegion( im->GetBufferedRegion( ) );
+  out->SetSpacing( im->GetSpacing( ) );
+  out->SetOrigin( im->GetOrigin( ) );
+  out->SetDirection( im->GetDirection( ) );
+  out->Allocate( );
+  out->FillBuffer( this->m_OutsideValue );
+
+  // Fill skeleton
+  auto mIt = sk->BeginEdgesRows( );
+  for( ; mIt != sk->EndEdgesRows( ); ++mIt )
+  {
+    auto rIt = mIt->second.begin( );
+    for( ; rIt != mIt->second.end( ); ++rIt )
+    {
+      auto eIt = rIt->second.begin( );
+      for( ; eIt != rIt->second.end( ); ++eIt )
+      {
+        auto path = *eIt;
+        for( unsigned int i = 0; i < path->GetSize( ); ++i )
+          out->SetPixel( path->GetVertex( i ), this->m_InsideValue );
+
+      } // rof
+
+    } // rof
+
+  } // rof
+}
+
+#endif // __cpExtensions__Algorithms__SkeletonToImageFilter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SkeletonWriter.h b/lib/cpExtensions/Algorithms/SkeletonWriter.h
new file mode 100644 (file)
index 0000000..3112693
--- /dev/null
@@ -0,0 +1,69 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__SkeletonWriter__h__
+#define __cpExtensions__Algorithms__SkeletonWriter__h__
+
+#include <cpExtensions/Config.h>
+#include <itkProcessObject.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class _TSkeleton >
+    class SkeletonWriter
+      : public itk::ProcessObject
+    {
+    public:
+      // Basic types
+      typedef SkeletonWriter                  Self;
+      typedef itk::ProcessObject              Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TSkeleton TSkeleton;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( SkeletonWriter, itk::ImageSource );
+
+      itkGetConstMacro( FileName, std::string );
+      itkSetMacro( FileName, std::string );
+
+    public:
+      const TSkeleton* GetInput( ) const;
+      void SetInput( const TSkeleton* skeleton );
+      virtual void Update( ) cpExtensions_OVERRIDE;
+
+    protected:
+      SkeletonWriter( );
+      virtual ~SkeletonWriter( );
+
+      virtual void GenerateData( ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      SkeletonWriter( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      std::string m_FileName;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+// -------------------------------------------------------------------------
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/SkeletonWriter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__Algorithms__SkeletonWriter__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SkeletonWriter.hxx b/lib/cpExtensions/Algorithms/SkeletonWriter.hxx
new file mode 100644 (file)
index 0000000..76e05c1
--- /dev/null
@@ -0,0 +1,127 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __cpExtensions__Algorithms__SkeletonWriter__hxx__
+#define __cpExtensions__Algorithms__SkeletonWriter__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+const _TSkeleton* cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >::
+GetInput( ) const
+{
+  return(
+    dynamic_cast< const TSkeleton* >(
+      this->itk::ProcessObject::GetInput( 0 )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >::
+SetInput( const _TSkeleton* skeleton )
+{
+  this->itk::ProcessObject::SetNthInput(
+    0, const_cast< TSkeleton* >( skeleton )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >::
+Update( )
+{
+  TSkeleton* input = const_cast< TSkeleton* >( this->GetInput( ) );
+  if( input != NULL )
+  {
+    input->UpdateOutputInformation( );
+    input->UpdateOutputData( );
+    this->GenerateData( );
+    this->ReleaseInputs( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >::
+SkeletonWriter( )
+  : Superclass( ),
+    m_FileName( "" )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >::
+~SkeletonWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Algorithms::SkeletonWriter< _TSkeleton >::
+GenerateData( )
+{
+  const TSkeleton* sk = this->GetInput( );
+  std::stringstream out;
+  out << TSkeleton::Dimension << std::endl;
+
+  // Write
+  auto mIt = sk->BeginEdgesRows( );
+  for( ; mIt != sk->EndEdgesRows( ); ++mIt )
+  {
+    auto rIt = mIt->second.begin( );
+    for( ; rIt != mIt->second.end( ); ++rIt )
+    {
+      auto eIt = rIt->second.begin( );
+      for( ; eIt != rIt->second.end( ); ++eIt )
+      {
+        auto path = *eIt;
+        unsigned int size = path->GetSize( );
+        auto spa = path->GetSpacing( );
+        auto ori = path->GetOrigin( );
+        auto dir = path->GetDirection( );
+        out << size << std::endl;
+        for( unsigned int d = 0; d < TSkeleton::Dimension; ++d )
+          out << spa[ d ] << " ";
+        out << std::endl;
+        for( unsigned int d = 0; d < TSkeleton::Dimension; ++d )
+          out << ori[ d ] << " ";
+        out << std::endl;
+        for( unsigned int d = 0; d < TSkeleton::Dimension; ++d )
+          for( unsigned int e = 0; e < TSkeleton::Dimension; ++e )
+          out << dir[ d ][ e ] << " ";
+        out << std::endl;
+
+        for( unsigned int i = 0; i < path->GetSize( ); ++i )
+        {
+          auto v = path->GetVertex( i );
+          for( unsigned int d = 0; d < TSkeleton::Dimension; ++d )
+            out << v[ d ] << " ";
+
+        } // rof
+        out << std::endl;
+
+      } // rof
+
+    } // rof
+
+  } // rof
+  out << "0" << std::endl;
+
+  /* TODO
+     if( !( cpExtensions::Write( out.str( ), this->m_FileName ) ) )
+     itkExceptionMacro(
+     << "Unable to write skeleton to \""
+     << this->m_FileName
+     << "\""
+     );
+  */
+}
+
+#endif // __cpExtensions__Algorithms__SkeletonWriter__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h
new file mode 100644 (file)
index 0000000..2b81fb7
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__
+
+#include <itkConceptChecking.h>
+#include <itkImageToImageFilter.h>
+#include <itkSpatialObject.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    /**
+     */
+    template< class I, class O = I >
+    class SpatialObjectMaskImageFilter
+      : public itk::ImageToImageFilter< I, O >
+    {
+    public:
+      typedef SpatialObjectMaskImageFilter    Self;
+      typedef itk::ImageToImageFilter< I, O > Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef I TInputImage;
+      typedef O TOutputImage;
+
+      itkStaticConstMacro( InputDimension, unsigned int, I::ImageDimension );
+      itkStaticConstMacro( OutputDimension, unsigned int, O::ImageDimension );
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+      itkConceptMacro(
+        SameDimensionCheck1,
+        ( itk::Concept::SameDimension< InputDimension, OutputDimension > )
+        );
+#endif
+
+      typedef typename I::RegionType TRegion;
+      typedef typename O::PixelType  TOutPixel;
+      typedef itk::SpatialObject< InputDimension > TSpatialObject;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( SpatialObjectMaskImageFilter, itk::ImageToImageFilter );
+
+      itkGetObjectMacro( SpatialObject, TSpatialObject );
+      itkGetConstObjectMacro( SpatialObject, TSpatialObject );
+      itkGetConstMacro( OutsideValue, TOutPixel );
+
+      itkSetObjectMacro( SpatialObject, TSpatialObject );
+      itkSetMacro( OutsideValue, TOutPixel );
+
+    public:
+      O* GetPositiveOutput( );
+      const O* GetPositiveOutput( ) const;
+      O* GetNegativeOutput( );
+      const O* GetNegativeOutput( ) const;
+
+    protected:
+      SpatialObjectMaskImageFilter( );
+      virtual ~SpatialObjectMaskImageFilter( );
+
+      virtual void GenerateOutputInformation( );
+      virtual void ThreadedGenerateData(
+        const TRegion& region, itk::ThreadIdType threadId
+        );
+
+    private:
+      // Purposely not implemented.
+      SpatialObjectMaskImageFilter( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TSpatialObject::Pointer m_SpatialObject;
+      TOutPixel m_OutsideValue;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include <cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx
new file mode 100644 (file)
index 0000000..2c3cac7
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__
+
+#include <itkImageScanlineIterator.h>
+#include <itkProgressReporter.h>
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+GetPositiveOutput( )
+{
+  return( this->GetOutput( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+const O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+GetPositiveOutput( ) const
+{
+  return( this->GetOutput( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+GetNegativeOutput( )
+{
+  return( this->GetOutput( 1 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+const O* cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+GetNegativeOutput( ) const
+{
+  return( this->GetOutput( 1 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+SpatialObjectMaskImageFilter( )
+  : Superclass( )
+{
+  this->SetNumberOfRequiredInputs( 1 );
+  this->SetNumberOfRequiredOutputs( 2 );
+  this->SetNthOutput( 0, O::New( ) );
+  this->SetNthOutput( 1, O::New( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+~SpatialObjectMaskImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+void cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+GenerateOutputInformation( )
+{
+  const I* in =
+    dynamic_cast< const I* >( this->itk::ProcessObject::GetInput( 0 ) );
+  for( unsigned int idx = 0; idx < this->GetNumberOfOutputs( ); ++idx )
+  {
+    itk::DataObject* out = this->GetOutput( idx );
+    if( out )
+      out->CopyInformation( in );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+template< class I, class O >
+void cpExtensions::Algorithms::SpatialObjectMaskImageFilter< I, O >::
+ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId )
+{
+  if( this->m_SpatialObject.IsNull( ) )
+  {
+    itkGenericExceptionMacro( << "No itk::SpatialObject given." );
+    return;
+
+  } // fi
+
+  // Get inputs
+  const I* in =
+    dynamic_cast< const I* >( this->itk::ProcessObject::GetInput( 0 ) );
+  O* pos_out = this->GetPositiveOutput( );
+  O* neg_out = this->GetNegativeOutput( );
+  const auto size0 = region.GetSize( 0 );
+  if( size0 == 0 )
+    return;
+  const auto nLines = region.GetNumberOfPixels( ) / size0;
+
+  // Create iterators
+  itk::ImageScanlineConstIterator< I > iIt( in, region );
+  itk::ImageScanlineIterator< O > pos_oIt( pos_out, region );
+  itk::ImageScanlineIterator< O > neg_oIt( neg_out, region );
+  itk::ProgressReporter progress( this, threadId, nLines );
+
+  // Main loop
+  typename TSpatialObject::PointType pnt;
+  while( !iIt.IsAtEnd( ) )
+  {
+    while( !iIt.IsAtEndOfLine( ) )
+    {
+      auto idx = iIt.GetIndex( );
+      in->TransformIndexToPhysicalPoint( idx, pnt );
+      if( this->m_SpatialObject->IsInside( pnt ) )
+      {
+        pos_oIt.Set( TOutPixel( iIt.Get( ) ) );
+        neg_oIt.Set( this->m_OutsideValue );
+      }
+      else
+      {
+        neg_oIt.Set( TOutPixel( iIt.Get( ) ) );
+        pos_oIt.Set( this->m_OutsideValue );
+
+      } // fi
+      ++iIt;
+      ++pos_oIt;
+      ++neg_oIt;
+
+    } // elihw
+    iIt.NextLine( );
+    pos_oIt.NextLine( );
+    neg_oIt.NextLine( );
+    progress.CompletedPixel( );
+
+  } // elihw
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h
new file mode 100644 (file)
index 0000000..7de8b66
--- /dev/null
@@ -0,0 +1,102 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__
+#define __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__
+
+#include <itkUnaryFunctorImageFilter.h>
+
+namespace cpExtensions
+{
+  namespace Algorithms
+  {
+    namespace Functor
+    {
+      /**
+       */
+      template< typename _TInput >
+      class UnaryThreshold
+      {
+      public:
+        UnaryThreshold( );
+        virtual ~UnaryThreshold( );
+
+        const _TInput& GetThreshold( ) const;
+        const _TInput& GetInsideValue( ) const;
+        const _TInput& GetOutsideValue( ) const;
+        const bool& GetStrict( ) const;
+
+        void StrictOn( );
+        void StrictOff( );
+        void SetStrict( bool s );
+        void SetThreshold( const _TInput& thresh );
+        void SetInsideValue( const _TInput& value );
+        void SetOutsideValue( const _TInput& value );
+        bool operator!=( const UnaryThreshold& other ) const;
+        bool operator==( const UnaryThreshold& other ) const;
+        _TInput operator()( const _TInput& A ) const;
+
+      private:
+        _TInput m_Threshold;
+        _TInput m_InsideValue;
+        _TInput m_OutsideValue;
+        bool    m_Strict;
+      };
+    }
+
+    /**
+     */
+    template< class _TImage >
+    class UnaryThresholdImageFilter
+      : public itk::UnaryFunctorImageFilter< _TImage, _TImage, cpExtensions::Algorithms::Functor::UnaryThreshold< typename _TImage::PixelType > >
+    {
+    public:
+      // Basic types
+      typedef typename _TImage::PixelType TPixel;
+      typedef cpExtensions::Algorithms::Functor::UnaryThreshold< TPixel > TFunctor;
+      typedef itk::UnaryFunctorImageFilter< _TImage, _TImage, TFunctor > Superclass;
+      typedef UnaryThresholdImageFilter       Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TImage TImage;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( UnaryThresholdImageFilter, itkUnaryFunctorImageFilter );
+
+    public:
+      const TPixel& GetThreshold( ) const;
+      const TPixel& GetInsideValue( ) const;
+      const TPixel& GetOutsideValue( ) const;
+      const bool&    GetStrict( ) const;
+
+      void StrictOn( );
+      void StrictOff( );
+      void SetStrict( bool s );
+      void SetThreshold( const TPixel& thresh );
+      void SetInsideValue( const TPixel& value );
+      void SetOutsideValue( const TPixel& value );
+      
+    protected:
+      UnaryThresholdImageFilter( );
+      virtual ~UnaryThresholdImageFilter( );
+
+    private:
+      // Purposely not implemented
+      UnaryThresholdImageFilter( const Self& );
+      void operator=( const Self& );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx
new file mode 100644 (file)
index 0000000..ff85edd
--- /dev/null
@@ -0,0 +1,245 @@
+// -------------------------------------------------------------------------
+// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co)
+// -------------------------------------------------------------------------
+
+#ifndef __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__HXX__
+#define __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__HXX__
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+UnaryThreshold( )
+  : m_Strict( false )
+{
+  this->m_Threshold    = itk::NumericTraits< _TInput >::NonpositiveMin( );
+  this->m_OutsideValue = itk::NumericTraits< _TInput >::ZeroValue( );
+  this->m_InsideValue  = itk::NumericTraits< _TInput >::max( );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+~UnaryThreshold( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+const _TInput& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+GetThreshold( ) const
+{
+  return( this->m_Threshold );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+const _TInput& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+GetInsideValue( ) const
+{
+  return( this->m_InsideValue );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+const _TInput& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+GetOutsideValue( ) const
+{
+  return( this->m_OutsideValue );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+const bool& cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+GetStrict( ) const
+{
+  return( this->m_Strict );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+StrictOn( )
+{
+  this->SetStrict( true );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+StrictOff( )
+{
+  this->SetStrict( false );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+SetStrict( bool s )
+{
+  this->m_Strict = s;
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+SetThreshold( const _TInput& thresh )
+{
+  this->m_Threshold = thresh;
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+SetInsideValue( const _TInput& value )
+{
+  this->m_InsideValue = value;
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+void cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+SetOutsideValue( const _TInput& value )
+{
+  this->m_OutsideValue = value;
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+bool cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+operator!=( const UnaryThreshold& other ) const
+{
+  return(
+    this->m_Threshold != other.m_Threshold ||
+    itk::Math::NotExactlyEquals( this->m_InsideValue, other.m_InsideValue ) ||
+    itk::Math::NotExactlyEquals( this->m_OutsideValue, other.m_OutsideValue )
+    );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+bool cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+operator==( const UnaryThreshold& other ) const
+{
+  return( !( *this != other ) );
+}
+
+// -------------------------------------------------------------------------
+template< typename _TInput >
+_TInput cpExtensions::Algorithms::Functor::UnaryThreshold< _TInput >::
+operator()( const _TInput& A ) const
+{
+  if( this->m_Strict )
+  {
+    if( this->m_Threshold < A  )
+      return( this->m_InsideValue );
+    return( this->m_OutsideValue );
+  }
+  else
+  {
+    if( this->m_Threshold <= A  )
+      return( this->m_InsideValue );
+    return( this->m_OutsideValue );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+const typename cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+TPixel& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+GetThreshold( ) const
+{
+  return( this->GetFunctor( ).GetThreshold( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+const typename cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+TPixel& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+GetInsideValue( ) const
+{
+  return( this->GetFunctor( ).GetInsideValue( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+const typename cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+TPixel& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+GetOutsideValue( ) const
+{
+  return( this->GetFunctor( ).GetOutsideValue( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+const bool& cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+GetStrict( ) const
+{
+  return( this->GetFunctor( ).GetStrict( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+StrictOn( )
+{
+  this->GetFunctor( ).SetStrict( true );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+StrictOff( )
+{
+  this->GetFunctor( ).SetStrict( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+SetStrict( bool s )
+{
+  this->GetFunctor( ).SetStrict( s );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+SetThreshold( const TPixel& thresh )
+{
+  this->GetFunctor( ).SetThreshold( thresh );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+SetInsideValue( const TPixel& value )
+{
+  this->GetFunctor( ).SetInsideValue( value );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+SetOutsideValue( const TPixel& value )
+{
+  this->GetFunctor( ).SetOutsideValue( value );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+UnaryThresholdImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >::
+~UnaryThresholdImageFilter( )
+{
+}
+
+#endif // __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Config.h.in b/lib/cpExtensions/Config.h.in
new file mode 100644 (file)
index 0000000..4585244
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef __cpExtensions__Config__h__
+#define __cpExtensions__Config__h__
+
+#include <cpExtensions_Export.h>
+
+/*
+ * =========================================================================
+ * Identify OS
+ * =========================================================================
+ */
+#define cpExtensions_OS_@CMAKE_SYSTEM_NAME@
+
+/*
+ * =========================================================================
+ * Some global values
+ * =========================================================================
+ */
+#define cpExtensions_QT4_@QT4_FOUND@
+#ifdef cpExtensions_QT4_TRUE
+#  ifndef cpExtensions_QT4
+#    define cpExtensions_QT4
+#  endif // cpExtensions_QT4
+#  define cpExtensions_QVTKWidget @cpPlugins_Qt4_VTKWidget@
+#  include <@cpPlugins_Qt4_VTKWidget@.h>
+#else // cpExtensions_QT4_TRUE
+#  undef cpExtensions_QT4
+#endif // cpExtensions_QT4_TRUE
+
+/*
+ * =========================================================================
+ * Version numbers and strings
+ * =========================================================================
+ */
+
+#define cpExtensions_MAJOR_VERSION   @prj_MAJOR_VERSION@
+#define cpExtensions_MINOR_VERSION   @prj_MINOR_VERSION@
+#define cpExtensions_RELEASE_VERSION @prj_RELEASE_VERSION@
+#define cpExtensions_VERSION         "@prj_VERSION@"
+#define cpExtensions_SHORT_VERSION   "@prj_SHORT_VERSION@"
+
+/*
+ * =========================================================================
+ * Language related macros
+ * =========================================================================
+ */
+
+#if __cplusplus >= 201103L
+#  define cpExtensions_OVERRIDE override
+#  define cpExtensions_DELETE_FUNCTION =delete
+#  define cpExtensions_NULLPTR  nullptr
+#  define cpExtensions_NOEXCEPT noexcept
+#  define cpExtensions_HAS_CXX11_STATIC_ASSERT
+#  define cpExtensions_HAS_CXX11_RVREF
+#else
+#  define cpExtensions_OVERRIDE
+#  define cpExtensions_DELETE_FUNCTION
+#  define cpExtensions_NULLPTR  NULL
+#  define cpExtensions_NOEXCEPT throw()
+#endif
+
+// -------------------------------------------------------------------------
+#ifdef cpExtensions_OS_Windows
+#  define cpExtensions_SPRINTF( B, S, O ) sprintf_s( B, S, "%s", O );
+#else // cpExtensions_OS_Windows
+#  define cpExtensions_SPRINTF( B, S, O ) std::sprintf( B, "%s", O );
+#endif // cpExtensions_OS_Windows
+
+#endif // __cpExtensions__Config__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Graph.h b/lib/cpExtensions/DataStructures/Graph.h
new file mode 100644 (file)
index 0000000..d9e913d
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef __cpExtensions__DataStructures__Graph__h__
+#define __cpExtensions__DataStructures__Graph__h__
+
+#include <cpExtensions/Config.h>
+#include <map>
+#include <set>
+#include <vector>
+#include <itkDataObject.h>
+#include <itkObjectFactory.h>
+
+namespace cpExtensions
+{
+  namespace DataStructures
+  {
+    /** \brief A generic graph with templated index types.
+     *
+     *  @param _TVertex Vertex type.
+     *  @param _TCost   Cost type.
+     *  @param _TIndex  Index type (it should be a strict weak ordering type).
+     */
+    template< class _TVertex, class _TCost, class _TIndex = unsigned long, class _TIndexCompare = std::less< _TIndex > >
+    class Graph
+      : public itk::DataObject
+    {
+    public:
+      typedef Graph                           Self;
+      typedef itk::DataObject                 Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TVertex       TVertex;
+      typedef _TCost         TCost;
+      typedef _TIndex        TIndex;
+      typedef _TIndexCompare TIndexCompare;
+
+      // Base types
+      typedef std::map< TIndex, TVertex, TIndexCompare >    TVertices;
+      typedef std::vector< TCost >                          TEdges;
+      typedef std::map< TIndex, TEdges, TIndexCompare >     TMatrixRow;
+      typedef std::map< TIndex, TMatrixRow, TIndexCompare > TMatrix;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Graph, itk::DataObject );
+
+    public:
+      /*! \brief Iterators over vertices.
+       *         These allow you to iterate over all of graph's vertices.
+       *
+       * Typical iteration should be done as:
+       *
+       *  TGraph g;
+       *  ...
+       *  TGraph::TVertices::[const_]iterator vIt = g.BeginVertices( );
+       *  for( ; vIt != g.EndVertices( ); ++vIt )
+       *  {
+       *    vIt->first;  --> this is the vertex's index <--
+       *    vIt->second; --> this is the vertex's value <--
+       *  }
+       */
+      inline typename TVertices::iterator BeginVertices( )
+        { return( this->m_Vertices.begin( ) ); }
+      inline typename TVertices::iterator EndVertices( )
+        { return( this->m_Vertices.end( ) ); }
+      inline typename TVertices::const_iterator BeginVertices( ) const
+        { return( this->m_Vertices.begin( ) ); }
+      inline typename TVertices::const_iterator EndVertices( ) const
+        { return( this->m_Vertices.end( ) ); }
+
+      /*! \brief Iterators over edges.
+       *         These allow you to iterate over all of graph's edges.
+       *
+       * Typical iteration should be done as:
+       *
+       *  TGraph g;
+       *  ...
+       *  TGraph::TMatrix::[const_]iterator mIt = g.BeginEdgesRows( );
+       *  for( ; mIt != g.EndEdgesRows( ); ++mIt )
+       *  {
+       *    mIt->first; --> this is the row index. <--
+       *    TGraph::TMatrixRow::[const_]iterator rIt = mIt->second.begin( );
+       *    for( ; rIt != mIt->second.end( ); ++rIt )
+       *    {
+       *      rIt->first;  --> this is the column index.
+       *      TGraph::TEdges::[const_]iterator eIt = rIt->second.begin( );
+       *      for( ; eIt != rIt->second.end( ); ++eIt )
+       *        *eIt; --> this is the cost between mIt->first and rIt->first
+       *    }
+       *  }
+       */
+      inline typename TMatrix::iterator BeginEdgesRows( )
+        { return( this->m_Matrix.begin( ) ); }
+      inline typename TMatrix::iterator EndEdgetsRows( )
+        { return( this->m_Matrix.end( ) ); }
+      inline typename TMatrix::const_iterator BeginEdgesRows( ) const
+        { return( this->m_Matrix.begin( ) ); }
+      inline typename TMatrix::const_iterator EndEdgesRows( ) const
+        { return( this->m_Matrix.end( ) ); }
+
+      /*! \brief Clear all vertices and edges.
+       */
+      void Clear( );
+
+      /*! \brief Clear all edges.
+       */
+      inline void ClearEdges( )
+        { this->m_Matrix.clear( ); }
+
+      /*! \brief Vertex manipulation methods.
+       *         Names are self-explanatory.
+       */
+      inline bool HasVertexIndex( const TIndex& i ) const
+        { return( this->m_Vertices.find( i ) != this->m_Vertices.end( ) ); }
+      inline void SetVertex( const TIndex& index, TVertex& vertex )
+        { this->m_Vertices[ index ] = vertex; }
+      inline TVertex& GetVertex( const TIndex& index )
+        { return( this->m_Vertices[ index ] ); }
+      inline const TVertex& GetVertex( const TIndex& index ) const
+        { return( this->m_Vertices[ index ] ); }
+      bool RenameVertex( const TIndex& old_index, const TIndex& new_index );
+      void RemoveVertex( const TIndex& index );
+
+      /*! \brief Edge manipulation methods.
+       *         Names are self-explanatory.
+       */
+      inline void AddEdge( const TIndex& orig, const TIndex& dest, const TCost& cost )
+        { this->m_Matrix[ orig ][ dest ].push_back( cost ); }
+      TEdges& GetEdges( const TIndex& orig, const TIndex& dest );
+      const TEdges& GetEdges( const TIndex& orig, const TIndex& dest ) const;
+      bool HasEdge( const TIndex& orig, const TIndex& dest ) const;
+      void RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost );
+      void RemoveEdges( const TIndex& orig, const TIndex& dest );
+
+      /*! \brief Returns graph's sinks.
+       *
+       *  A sink is a special vertex which does not have any "exiting" edges.
+       *
+       *  @return Sinks ordered by their index.
+       */
+      std::set< TIndex, TIndexCompare > GetSinks( ) const;
+
+    protected:
+      Graph( );
+      virtual ~Graph( );
+
+    private:
+      // Purposely not implemented
+      Graph( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TVertices m_Vertices;
+      TMatrix   m_Matrix;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/DataStructures/Graph.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__DataStructures__Graph__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Graph.hxx b/lib/cpExtensions/DataStructures/Graph.hxx
new file mode 100644 (file)
index 0000000..62c6b75
--- /dev/null
@@ -0,0 +1,267 @@
+#ifndef __cpExtensions__DataStructures__Graph__hxx__
+#define __cpExtensions__DataStructures__Graph__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+Clear( )
+{
+  this->m_Vertices.clear( );
+  this->m_Matrix.clear( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+bool cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RenameVertex( const TIndex& old_index, const TIndex& new_index )
+{
+  auto old_v = this->m_Vertices.find( old_index );
+  auto new_v = this->m_Vertices.find( new_index );
+  if( old_v != this->m_Vertices.end( ) && new_v == this->m_Vertices.end( ) )
+  {
+    // Replace vertex
+    this->m_Vertices[ new_index ] = old_v->second;
+    this->m_Vertices.erase( old_index );
+
+    // Duplicate edges
+    auto mIt = this->m_Matrix.begin( );
+    auto found_row = this->m_Matrix.end( );
+    for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    {
+      if( mIt->first == old_index )
+        found_row = mIt;
+
+      auto rIt = mIt->second.begin( );
+      for( ; rIt != mIt->second.end( ); ++rIt )
+      {
+        if( mIt->first == old_index )
+          this->m_Matrix[ new_index ][ rIt->first ] = rIt->second;
+        else if( rIt->first == old_index )
+          this->m_Matrix[ mIt->first ][ new_index ] = rIt->second;
+
+      } // rof
+
+    } // rof
+
+    // Delete old edges
+    if( found_row != this->m_Matrix.end( ) )
+      this->m_Matrix.erase( found_row );
+
+    mIt = this->m_Matrix.begin( );
+    for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    {
+      auto rIt = mIt->second.begin( );
+      while( rIt != mIt->second.end( ) )
+      {
+        if( rIt->first == old_index )
+        {
+          mIt->second.erase( rIt );
+          rIt = mIt->second.begin( );
+        }
+        else
+          ++rIt;
+
+      } // elihw
+
+    } // rof
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RemoveVertex( const TIndex& index )
+{
+  auto i = this->m_Vertices.find( index );
+  if( i != this->m_Vertices.end( ) )
+  {
+    // Delete vertex
+    this->m_Vertices.erase( i );
+
+    // Delete edges starting from given vertex
+    auto mIt = this->m_Matrix.find( index );
+    if( mIt != this->m_Matrix.end( ) )
+      this->m_Matrix.erase( mIt );
+
+    // Delete edges arriving to given vertex
+    mIt = this->m_Matrix.begin( );
+    for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    {
+      auto rIt = mIt->second.begin( );
+      while( rIt != mIt->second.end( ) )
+      {
+        if( rIt->first == index )
+        {
+          mIt->second.erase( rIt );
+          rIt = mIt->second.begin( );
+        }
+        else
+          ++rIt;
+
+      } // elihw
+
+    } // rof
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+typename
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+TEdges&
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+GetEdges( const TIndex& orig, const TIndex& dest )
+{
+  static TEdges null_edges;
+  auto o = this->m_Matrix.find( orig );
+  if( o != this->m_Matrix.find( orig ) )
+  {
+    auto d = o->second.find( dest );
+    if( d == o->second.end( ) )
+    {
+      null_edges.clear( );
+      return( null_edges );
+    }
+    else
+      return( d->second );
+  }
+  else
+  {
+    null_edges.clear( );
+    return( null_edges );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+const typename 
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+TEdges&
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+GetEdges( const TIndex& orig, const TIndex& dest ) const
+{
+  static const TEdges null_edges;
+  auto o = this->m_Matrix.find( orig );
+  if( o != this->m_Matrix.find( orig ) )
+  {
+    auto d = o->second.find( dest );
+    if( d == o->second.end( ) )
+      return( null_edges );
+    else
+      return( d->second );
+  }
+  else
+    return( null_edges );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+bool cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+HasEdge( const TIndex& orig, const TIndex& dest ) const
+{
+  auto mIt = this->m_Matrix.find( orig );
+  if( mIt != this->m_Matrix.end( ) )
+    return( mIt->second.find( dest ) != mIt->second.end( ) );
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RemoveEdge( const TIndex& orig, const TIndex& dest, const TCost& cost )
+{
+  auto m = this->m_Matrix.find( orig );
+  if( m != this->m_Matrix.end( ) )
+  {
+    auto r = m->second.find( dest );
+    if( r != m->second.end( ) )
+    {
+      auto e = r->second.end( );
+      for(
+        auto i = r->second.begin( );
+        i != r->second.end( ) && e == r->second.end( );
+        ++i
+        )
+        if( *i == cost )
+          e = i;
+      if( e != r->second.end( ) )
+      {
+        r->second.erase( e );
+        if( r->second.size( ) == 0 )
+        {
+          m->second.erase( r );
+          if( m->second.size( ) == 0 )
+            this->m_Matrix.erase( m );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+void cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+RemoveEdges( const TIndex& orig, const TIndex& dest )
+{
+  auto m = this->m_Matrix.find( orig );
+  if( m != this->m_Matrix.end( ) )
+  {
+    auto r = m->second.find( dest );
+    if( r != m->second.end( ) )
+    {
+      m->second.erase( r );
+      if( m->second.size( ) == 0 )
+        this->m_Matrix.erase( m );
+
+    } // fi
+
+  } // fi
+
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+std::set< _TIndex, _TIndexCompare >
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+GetSinks( ) const
+{
+  std::set< _TIndex, _TIndexCompare > sinks;
+
+  auto vIt = this->m_Vertices.begin( );
+  for( ; vIt != this->m_Vertices.end( ); ++vIt )
+    sinks.insert( vIt->first );
+  auto mIt = this->m_Matrix.begin( );
+  for( ; mIt != this->m_Matrix.end( ); ++mIt )
+    sinks.erase( mIt->first );
+
+  return( sinks );
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+Graph( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TVertex, class _TCost, class _TIndex, class _TIndexCompare >
+cpExtensions::DataStructures::Graph< _TVertex, _TCost, _TIndex, _TIndexCompare >::
+~Graph( )
+{
+}
+
+#endif // __cpExtensions__DataStructures__Graph__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/PolyLineParametricPath.h b/lib/cpExtensions/DataStructures/PolyLineParametricPath.h
new file mode 100644 (file)
index 0000000..7f12200
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef __cpExtensions__DataStructures__PolyLineParametricPath__h__
+#define __cpExtensions__DataStructures__PolyLineParametricPath__h__
+
+#include <itkPolyLineParametricPath.h>
+#include <itkImageBase.h>
+#include <cpExtensions/Algorithms/BezierCurveFunction.h>
+
+namespace cpExtensions
+{
+  namespace DataStructures
+  {
+    /**
+     */
+    template< unsigned int _VDim >
+    class PolyLineParametricPath
+      : public itk::PolyLineParametricPath< _VDim >
+    {
+    public:
+      typedef PolyLineParametricPath               Self;
+      typedef itk::PolyLineParametricPath< _VDim > Superclass;
+      typedef itk::SmartPointer< Self >            Pointer;
+      typedef itk::SmartPointer< const Self >      ConstPointer;
+
+      typedef itk::ImageBase< _VDim >                  TImageBase;
+      typedef typename TImageBase::SpacingType         TSpacing;
+      typedef typename TImageBase::PointType           TPoint;
+      typedef typename TImageBase::DirectionType       TDirection;
+      typedef typename Superclass::ContinuousIndexType TContinuousIndex;
+      typedef typename TContinuousIndex::IndexType     TIndex;
+
+      typedef typename TPoint::VectorType TVector;
+      typedef cpExtensions::Algorithms::BezierCurveFunction< TVector > TBezier;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( PolyLineParametricPath, itk::PolyLineParametricPath );
+
+      itkGetConstReferenceMacro( Spacing, TSpacing );
+      itkGetConstReferenceMacro( Origin, TPoint );
+      itkGetConstReferenceMacro( Direction, TDirection );
+      itkGetConstReferenceMacro( InverseDirection, TDirection );
+
+      itkSetMacro( Origin, TPoint );
+
+    public:
+      void AddVertex( const TContinuousIndex& vertex );
+      unsigned long GetSize( ) const;
+      TContinuousIndex GetContinuousVertex( unsigned long i ) const;
+      TIndex GetVertex( unsigned long i ) const;
+      TPoint GetPoint( unsigned long i ) const;
+      TPoint GetSmoothPoint( double u ) const;
+
+      virtual void SetSpacing( const TSpacing& spac );
+      virtual void SetSpacing( const double spac[ _VDim ] );
+      virtual void SetSpacing( const float spac[ _VDim ] );
+      virtual void SetOrigin( const double ori[ _VDim ] );
+      virtual void SetOrigin( const float ori[ _VDim ] );
+      virtual void SetDirection( const TDirection& dir );
+
+      template< class _TRefImage >
+      inline void SetReferenceImage( const _TRefImage* image )
+        {
+          this->SetSpacing( image->GetSpacing( ) );
+          this->SetOrigin( image->GetOrigin( ) );
+          this->SetDirection( image->GetDirection( ) );
+        }
+
+    protected:
+      PolyLineParametricPath( );
+      virtual ~PolyLineParametricPath( );
+
+      virtual void _ComputeIndexToPhysicalPointMatrices( );
+
+    private:
+      // Purposely not implemented
+      PolyLineParametricPath( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      typename TBezier::Pointer m_Bezier;
+      TSpacing   m_Spacing;
+      TPoint     m_Origin;
+      TDirection m_Direction;
+      TDirection m_InverseDirection;
+      TDirection m_IndexToPhysicalPoint;
+      TDirection m_PhysicalPointToIndex;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/DataStructures/PolyLineParametricPath.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__DataStructures__PolyLineParametricPath__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/PolyLineParametricPath.hxx b/lib/cpExtensions/DataStructures/PolyLineParametricPath.hxx
new file mode 100644 (file)
index 0000000..635c8b7
--- /dev/null
@@ -0,0 +1,215 @@
+#ifndef __cpExtensions__DataStructures__PolyLineParametricPath__hxx__
+#define __cpExtensions__DataStructures__PolyLineParametricPath__hxx__
+
+#include <itkMath.h>
+#include <itkNumericTraits.h>
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+AddVertex( const TContinuousIndex& vertex )
+{
+  this->Superclass::AddVertex( vertex );
+  this->m_Bezier->AddPoint(
+    this->GetPoint( this->GetSize( ) - 1 ).GetVectorFromOrigin( )
+    );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+unsigned long cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+GetSize( ) const
+{
+  return( this->GetVertexList( )->Size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+TContinuousIndex
+cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+GetContinuousVertex( unsigned long i ) const
+{
+  return( this->GetVertexList( )->GetElement( i ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+TIndex cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+GetVertex( unsigned long i ) const
+{
+  TContinuousIndex cidx = this->GetContinuousVertex( i );
+  TIndex idx;
+  for( unsigned int d = 0; d < _VDim; ++d )
+    idx[ d ] = cidx[ d ];
+  return( idx );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+TPoint cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+GetPoint( unsigned long i ) const
+{
+  typedef typename TPoint::CoordRepType _TCoordRep;
+  TPoint pnt;
+  TContinuousIndex idx = this->GetVertex( i );
+  for( unsigned int r = 0; r < _VDim; ++r )
+  {
+    _TCoordRep sum = itk::NumericTraits< _TCoordRep >::ZeroValue( );
+    for( unsigned int c = 0; c < _VDim; ++c )
+      sum += this->m_IndexToPhysicalPoint( r, c ) * idx[ c ];
+    pnt[ r ] = sum + this->m_Origin[ r ];
+
+  } // rof
+  return( pnt );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+typename cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+TPoint cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+GetSmoothPoint( double u ) const
+{
+  TPoint p;
+  p.Fill( 0 );
+  p += this->m_Bezier->Evaluate( u );
+  return( p );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+SetSpacing( const TSpacing& spac )
+{
+  if( this->m_Spacing != spac )
+  {
+    this->m_Spacing = spac;
+    this->_ComputeIndexToPhysicalPointMatrices( );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+SetSpacing( const double spac[ _VDim ] )
+{
+  this->SetSpacing( TSpacing( spac ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+SetSpacing( const float spac[ _VDim ] )
+{
+  TSpacing s;
+  for( unsigned int d = 0; d < _VDim; ++d )
+    s[ d ] = spac[ d ];
+  this->SetSpacing( s );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+SetOrigin( const double ori[ _VDim ] )
+{
+  this->SetOrigin( TPoint( ori ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+SetOrigin( const float ori[ _VDim ] )
+{
+  this->SetOrigin( TPoint( ori ) );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+SetDirection( const TDirection& dir )
+{
+  bool modified = false;
+  for( unsigned int r = 0; r < _VDim; r++ )
+  {
+    for( unsigned int c = 0; c < _VDim; c++ )
+    {
+      if(
+        itk::Math::NotExactlyEquals(
+          this->m_Direction[ r ][ c ], dir[ r ][ c ]
+          )
+        )
+      {
+        this->m_Direction[ r ][ c ] = dir[ r ][ c ];
+        modified = true;
+      } // fi
+
+    } // rof
+
+  } // rof
+  if( modified )
+  {
+    this->_ComputeIndexToPhysicalPointMatrices( );
+    this->m_InverseDirection = this->m_Direction.GetInverse( );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+PolyLineParametricPath( )
+  : Superclass( )
+{
+  this->m_Bezier = TBezier::New( );
+
+  this->m_Spacing.Fill( 1.0 );
+  this->m_Origin.Fill( 0.0 );
+  this->m_Direction.SetIdentity( );
+  this->m_InverseDirection.SetIdentity( );
+  this->m_IndexToPhysicalPoint.SetIdentity( );
+  this->m_PhysicalPointToIndex.SetIdentity( );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+~PolyLineParametricPath( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::PolyLineParametricPath< _VDim >::
+_ComputeIndexToPhysicalPointMatrices( )
+{
+  TDirection scale;
+  scale.Fill( 0.0 );
+  for( unsigned int i = 0; i < _VDim; i++ )
+  {
+    if( this->m_Spacing[ i ] == 0.0 )
+      itkExceptionMacro(
+        "A spacing of 0 is not allowed: Spacing is " << this->m_Spacing
+        );
+    scale[ i ][ i ] = this->m_Spacing[ i ];
+
+  } // rof
+
+  if( vnl_determinant( this->m_Direction.GetVnlMatrix( ) ) == 0.0 )
+    itkExceptionMacro(
+      << "Bad direction, determinant is 0. Direction is "
+      << this->m_Direction
+      );
+  this->m_IndexToPhysicalPoint = this->m_Direction * scale;
+  this->m_PhysicalPointToIndex = this->m_IndexToPhysicalPoint.GetInverse( );
+  this->Modified( );
+}
+
+#endif // __cpExtensions__DataStructures__PolyLineParametricPath__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Simple3DCurve.cxx b/lib/cpExtensions/DataStructures/Simple3DCurve.cxx
new file mode 100644 (file)
index 0000000..1d1a92e
--- /dev/null
@@ -0,0 +1,137 @@
+#include <cpExtensions/DataStructures/Simple3DCurve.h>
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+void cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+Modified( ) const
+{
+  this->Superclass::Modified( );
+  this->m_FramesUpdated = false;
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+void cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+Clear( )
+{
+  this->m_Points.clear( );
+  this->m_Frames.clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+unsigned long cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+GetNumberOfPoints( ) const
+{
+  return( this->m_Points.size( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+const typename cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+TMatrix& cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+GetFrame( unsigned int id ) const
+{
+  if( !( this->m_FramesUpdated ) )
+  {
+    unsigned long N = this->m_Points.size( );
+
+    std::vector< TVector > tg( N );
+    tg[ 0 ] = this->m_Points[ 1 ] - this->m_Points[ 0 ];
+    tg[ N - 1 ] = this->m_Points[ N - 1 ] - this->m_Points[ N - 2 ];
+    for( unsigned int i = 1; i < N - 1; ++i )
+      tg[ i ] = this->m_Points[ i + 1 ] - this->m_Points[ i - 1 ];
+
+    std::vector< TVector > no( N );
+    std::vector< TVector > bn( N );
+    TVector prev_tg( _TScalar( 0 ) ), prev_no( _TScalar( 0 ) );
+    prev_tg[ 0 ] = _TScalar( 1 );
+    prev_no[ 1 ] = _TScalar( 1 );
+    for( unsigned int i = 0; i < N; ++i )
+    {
+      auto ntg = tg[ i ].GetNorm( );
+      if( double( ntg ) > double( 0 ) )
+        tg[ i ] /= ntg;
+
+      _TScalar ct = prev_tg * tg[ i ];
+      TVector a = itk::CrossProduct( prev_tg, tg[ i ] );
+      _TScalar st = a.GetNorm( );
+      if( st > _TScalar( 0 ) )
+        a /= st;
+
+      no[ i ] =
+        ( prev_no * ct ) +
+        ( itk::CrossProduct( a, prev_no ) * st ) +
+        ( a * ( ( a * prev_no ) * ( _TScalar( 1 ) - ct ) ) );
+      auto nno = no[ i ].GetNorm( );
+      if( double( nno ) > double( 0 ) )
+        no[ i ] /= nno;
+
+      bn[ i ] = itk::CrossProduct( tg[ i ], no[ i ] );
+
+      prev_tg = tg[ i ];
+      prev_no = no[ i ];
+
+    } // rof
+
+    this->m_Frames.clear( );
+    for( unsigned int i = 0; i < N; ++i )
+    {
+      TMatrix m;
+      for( unsigned int d = 0; d < 3; ++d )
+      {
+        m[ d ][ 0 ] = tg[ i ][ d ];
+        m[ d ][ 1 ] = no[ i ][ d ];
+        m[ d ][ 2 ] = bn[ i ][ d ];
+
+      } // rof
+      this->m_Frames.push_back( m );
+
+    } // rof
+
+    this->m_FramesUpdated = true;
+
+  } // fi
+  return( this->m_Frames[ id ] );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+const typename cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+TPoint& cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+GetPoint( unsigned int id ) const
+{
+  return( this->m_Points[ id ] );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+typename cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+TVector cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+GetVector( unsigned int id ) const
+{
+  return( this->m_Points[ id ].GetVectorFromOrigin( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+Simple3DCurve( )
+  : Superclass( ),
+    m_FramesUpdated( false )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TScalar >
+cpExtensions::DataStructures::Simple3DCurve< _TScalar >::
+~Simple3DCurve( )
+{
+}
+
+// -------------------------------------------------------------------------
+template class cpExtensions::DataStructures::Simple3DCurve< float >;
+template class cpExtensions::DataStructures::Simple3DCurve< double >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Simple3DCurve.h b/lib/cpExtensions/DataStructures/Simple3DCurve.h
new file mode 100644 (file)
index 0000000..0641d43
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __cpExtensions__DataStructures__Simple3DCurve__h__
+#define __cpExtensions__DataStructures__Simple3DCurve__h__
+
+#include <cpExtensions/Config.h>
+#include <itkDataObject.h>
+#include <itkObjectFactory.h>
+#include <itkMatrix.h>
+#include <itkPoint.h>
+
+namespace cpExtensions
+{
+  namespace DataStructures
+  {
+    /**
+     */
+    template< class _TScalar >
+    class cpExtensions_EXPORT Simple3DCurve
+      : public itk::DataObject
+    {
+    public:
+      typedef Simple3DCurve                   Self;
+      typedef itk::DataObject                 Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef _TScalar TScalar;
+      typedef itk::Matrix< TScalar, 3, 3 > TMatrix;
+      typedef itk::Point< TScalar, 3 >     TPoint;
+      typedef typename TPoint::VectorType  TVector;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Simple3DCurve, itk::DataObject );
+
+    public:
+      template< class _TVector >
+      inline void AddPoint( const _TVector& v )
+        {
+          TPoint p;
+          p[ 0 ] = v[ 0 ];
+          p[ 1 ] = v[ 1 ];
+          p[ 2 ] = v[ 2 ];
+          this->m_Points.push_back( p );
+          this->Modified( );
+        }
+
+      virtual void Modified( ) const cpExtensions_OVERRIDE;
+      void Clear( );
+      unsigned long GetNumberOfPoints( ) const;
+      const TMatrix& GetFrame( unsigned int id ) const;
+      const TPoint& GetPoint( unsigned int id ) const;
+      TVector GetVector( unsigned int id ) const;
+
+    protected:
+      Simple3DCurve( );
+      virtual ~Simple3DCurve( );
+
+    private:
+      // Purposely not implemented
+      Simple3DCurve( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      std::vector< TPoint > m_Points;
+      mutable std::vector< TMatrix > m_Frames;
+      mutable bool m_FramesUpdated;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__DataStructures__Simple3DCurve__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Skeleton.h b/lib/cpExtensions/DataStructures/Skeleton.h
new file mode 100644 (file)
index 0000000..9d0bd9b
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __cpExtensions__DataStructures__Skeleton__h__
+#define __cpExtensions__DataStructures__Skeleton__h__
+
+#include <cpExtensions/DataStructures/Graph.h>
+#include <cpExtensions/DataStructures/PolyLineParametricPath.h>
+
+namespace cpExtensions
+{
+  namespace DataStructures
+  {
+    /**
+     */
+    template< unsigned int _VDim >
+    class Skeleton
+      : public Graph< typename PolyLineParametricPath< _VDim >::TIndex, typename PolyLineParametricPath< _VDim >::Pointer, typename PolyLineParametricPath< _VDim >::TIndex, typename PolyLineParametricPath< _VDim >::TIndex::LexicographicCompare >
+    {
+    public:
+      typedef PolyLineParametricPath< _VDim >       TPath;
+      typedef typename TPath::TIndex                TIndex;
+      typedef typename TIndex::LexicographicCompare TIndexCompare;
+      typedef typename TPath::Pointer TPathPointer;
+
+      itkStaticConstMacro( Dimension, unsigned int, _VDim );
+
+      typedef Graph< TIndex, TPathPointer, TIndex, TIndexCompare > Superclass;
+      typedef Skeleton                        Self;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Skeleton, Graph );
+
+    public:
+      void AddBranch( TPath* path );
+      const TPath* GetBranch( const TIndex& a, const TIndex& b ) const;
+
+    protected:
+      Skeleton( );
+      virtual ~Skeleton( );
+
+    private:
+      // Purposely not implemented
+      Skeleton( const Self& other );
+      Self& operator=( const Self& other );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#  include <cpExtensions/DataStructures/Skeleton.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif // __cpExtensions__DataStructures__Skeleton__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Skeleton.hxx b/lib/cpExtensions/DataStructures/Skeleton.hxx
new file mode 100644 (file)
index 0000000..e6635ae
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __cpExtensions__DataStructures__Skeleton__hxx__
+#define __cpExtensions__DataStructures__Skeleton__hxx__
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+void cpExtensions::DataStructures::Skeleton< _VDim >::
+AddBranch( TPath* path )
+{
+  // Check inputs
+  if( path == NULL )
+    return;
+  unsigned long size = path->GetSize( );
+  if( size == 0 )
+    return;
+  TIndex a = path->GetVertex( 0 );
+  TIndex b = path->GetVertex( size - 1 );
+  if( this->HasEdge( a, b ) )
+    return;
+
+  // Add path
+  this->SetVertex( a, a );
+  this->SetVertex( b, b );
+  this->AddEdge( a, b, path );
+  this->AddEdge( b, a, path );
+  // TODO: this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+const typename cpExtensions::DataStructures::Skeleton< _VDim >::
+TPath* cpExtensions::DataStructures::Skeleton< _VDim >::
+GetBranch( const TIndex& a, const TIndex& b ) const
+{
+  static const TPath* null_path = NULL;
+  if( this->HasEdge( a, b ) )
+    return( this->GetEdges( a, b ).front( ) );
+  else
+    return( null_path );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+cpExtensions::DataStructures::Skeleton< _VDim >::
+Skeleton( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+cpExtensions::DataStructures::Skeleton< _VDim >::
+~Skeleton( )
+{
+}
+
+#endif // __cpExtensions__DataStructures__Skeleton__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/BaseStyle.cxx b/lib/cpExtensions/Interaction/BaseStyle.cxx
new file mode 100644 (file)
index 0000000..39bd24b
--- /dev/null
@@ -0,0 +1,437 @@
+#include <cpExtensions/Interaction/BaseStyle.h>
+
+#include <cmath>
+
+#include <vtkCallbackCommand.h>
+#include <vtkCamera.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindowInteractor.h>
+
+// -------------------------------------------------------------------------
+long cpExtensions::Interaction::BaseStyle::_TMouseButtonEvent::
+MaxDoubleClick = 350; // ms
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+SetSetDoubleClickDelay( long delay )
+{
+  Self::_TMouseButtonEvent::MaxDoubleClick = delay;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+DelegateTDxEvent( unsigned long event, void* calldata )
+{
+  // TODO
+  std::cerr << "No TDx support at this time!" << std::endl;
+  std::exit( 1 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnMouseMove( )
+{
+  if( this->Interactor == NULL )
+    return;
+
+  // Get modifiers
+  bool alt = ( this->Interactor->GetAltKey( ) == 1 );
+  bool ctr = ( this->Interactor->GetControlKey( ) == 1 );
+  bool sft = ( this->Interactor->GetShiftKey( ) == 1 );
+  ButtonID button = this->GetButtonID( );
+
+  // Invoke possible generic events
+  auto x = this->Interactor->GetEventPosition( )[ 0 ];
+  auto y = this->Interactor->GetEventPosition( )[ 1 ];
+  if( button == Self::ButtonID_Right )
+  {
+    if( !alt && !ctr && !sft )
+    {
+      this->FindPokedRenderer( x, y );
+      this->Dolly( );
+
+    } // fi
+  }
+  else if( button == Self::ButtonID_Middle )
+  {
+    if( !alt && !ctr && !sft )
+    {
+      this->FindPokedRenderer( x, y );
+      this->Pan( );
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnLeftButtonDown( )
+{
+  this->m_ActiveButton = Self::ButtonID_Left;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnLeftButtonUp( )
+{
+  this->m_ActiveButton = Self::ButtonID_None;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnMiddleButtonDown( )
+{
+  this->m_ActiveButton = Self::ButtonID_Middle;
+
+  // Get current position on the associated actors
+  if( this->Interactor == NULL )
+    return;
+
+  // Get modifiers
+  bool alt = ( this->Interactor->GetAltKey( ) == 1 );
+  bool ctr = ( this->Interactor->GetControlKey( ) == 1 );
+  bool sft = ( this->Interactor->GetShiftKey( ) == 1 );
+  if( !alt && !ctr && !sft )
+    this->StartPan( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnMiddleButtonUp( )
+{
+  this->m_ActiveButton = Self::ButtonID_None;
+
+  // Get current position on the associated actors
+  if( this->Interactor == NULL )
+    return;
+
+  switch( this->State )
+  {
+  case VTKIS_PAN:
+    this->EndPan( );
+    break;
+  default:
+    break;
+  } // hctiws
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnRightButtonDown( )
+{
+  this->m_ActiveButton = Self::ButtonID_Right;
+
+  // Get current position on the associated actors
+  if( this->Interactor == NULL )
+    return;
+
+  // Get modifiers
+  bool alt = ( this->Interactor->GetAltKey( ) == 1 );
+  bool ctr = ( this->Interactor->GetControlKey( ) == 1 );
+  bool sft = ( this->Interactor->GetShiftKey( ) == 1 );
+  if( !alt && !ctr && !sft )
+    this->StartDolly( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+OnRightButtonUp( )
+{
+  this->m_ActiveButton = Self::ButtonID_None;
+
+  // Get current position on the associated actors
+  if( this->Interactor == NULL )
+    return;
+
+  switch( this->State )
+  {
+  case VTKIS_DOLLY:
+    this->EndDolly( );
+    break;
+  default:
+    break;
+  } // hctiws
+}
+
+// -------------------------------------------------------------------------
+#define cpExtensions_BaseStyle_Click( S, T )          \
+  void cpExtensions::Interaction::BaseStyle::         \
+  On##S##T( )                                                   \
+  {                                                             \
+    if( this->Interactor == NULL )                              \
+      return;                                                   \
+    static int idx[ 2 ];                                        \
+    static double pos[ 3 ];                                     \
+    if( !( this->_PickPosition( idx, pos ) ) )                  \
+      return;                                                   \
+    auto i = this->m_Mouse##T##Commands.begin( );               \
+    for( ; i != this->m_Mouse##T##Commands.end( ); ++i )        \
+      i->first(                                                 \
+        i->second,                                              \
+        Self::ButtonID_##S,                                     \
+        idx, pos,                                               \
+        this->Interactor->GetAltKey( ) == 1,                    \
+        this->Interactor->GetControlKey( ) == 1,                \
+        this->Interactor->GetShiftKey( ) == 1                   \
+        );                                                      \
+  }
+
+cpExtensions_BaseStyle_Click( Left, Click );
+cpExtensions_BaseStyle_Click( Middle, Click );
+cpExtensions_BaseStyle_Click( Right, Click );
+cpExtensions_BaseStyle_Click( Left, DoubleClick );
+cpExtensions_BaseStyle_Click( Middle, DoubleClick );
+cpExtensions_BaseStyle_Click( Right, DoubleClick );
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+Dolly( )
+{
+  if( this->CurrentRenderer == NULL )
+    return;
+
+  vtkRenderWindowInteractor* rwi = this->GetInteractor( );
+  double *center = this->CurrentRenderer->GetCenter( );
+  int dy = rwi->GetEventPosition( )[ 1 ] - rwi->GetLastEventPosition( )[ 1 ];
+  double dyf = this->m_MotionFactor * dy / center[ 1 ];
+  this->_Dolly( std::pow( 1.1, dyf ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+Pan( )
+{
+  if( this->CurrentRenderer == NULL )
+    return;
+
+  vtkRenderWindowInteractor* rwi = this->Interactor;
+  double viewFocus[ 4 ], focalDepth, viewPoint[ 3 ];
+  double newPickPoint[ 4 ], oldPickPoint[ 4 ], motionVector[ 3 ];
+
+  // Calculate the focal depth since we'll be using it a lot
+  vtkCamera* camera = this->CurrentRenderer->GetActiveCamera( );
+  camera->GetFocalPoint( viewFocus );
+  this->ComputeWorldToDisplay(
+    viewFocus[ 0 ], viewFocus[ 1 ], viewFocus[ 2 ], viewFocus
+    );
+  focalDepth = viewFocus[ 2 ];
+  this->ComputeDisplayToWorld(
+    rwi->GetEventPosition( )[ 0 ],
+    rwi->GetEventPosition( )[ 1 ],
+    focalDepth,
+    newPickPoint
+    );
+
+  // Has to recalc old mouse point since the viewport has moved,
+  // so can't move it outside the loop
+  this->ComputeDisplayToWorld(
+    rwi->GetLastEventPosition( )[ 0 ],
+    rwi->GetLastEventPosition( )[ 1 ],
+    focalDepth,
+    oldPickPoint
+    );
+
+  // Camera motion is reversed
+  motionVector[ 0 ] = oldPickPoint[ 0 ] - newPickPoint[ 0 ];
+  motionVector[ 1 ] = oldPickPoint[ 1 ] - newPickPoint[ 1 ];
+  motionVector[ 2 ] = oldPickPoint[ 2 ] - newPickPoint[ 2 ];
+
+  camera->GetFocalPoint( viewFocus );
+  camera->GetPosition( viewPoint );
+  camera->SetFocalPoint(
+    motionVector[ 0 ] + viewFocus[ 0 ],
+    motionVector[ 1 ] + viewFocus[ 1 ],
+    motionVector[ 2 ] + viewFocus[ 2 ]
+    );
+  camera->SetPosition(
+    motionVector[ 0 ] + viewPoint[ 0 ],
+    motionVector[ 1 ] + viewPoint[ 1 ],
+    motionVector[ 2 ] + viewPoint[ 2 ]
+    );
+  if( rwi->GetLightFollowCamera( ) )
+    this->CurrentRenderer->UpdateLightsGeometryToFollowCamera( );
+  rwi->Render( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::BaseStyle::
+BaseStyle( )
+  : Superclass( ),
+    m_MotionFactor( double( 10 ) )
+{
+  this->m_LeftButtonEvent.Reset( );
+  this->m_MiddleButtonEvent.Reset( );
+  this->m_RightButtonEvent.Reset( );
+  this->m_ActiveButton = Self::ButtonID_None;
+
+  this->EventCallbackCommand->SetCallback( Self::_ProcessEvents );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::BaseStyle::
+~BaseStyle( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+_Dolly( double factor )
+{
+  if( this->CurrentRenderer == NULL )
+    return;
+
+  vtkCamera* camera = this->CurrentRenderer->GetActiveCamera( );
+  if( camera->GetParallelProjection( ) == 0 )
+  {
+    camera->Dolly( factor );
+    if( this->AutoAdjustCameraClippingRange )
+      this->CurrentRenderer->ResetCameraClippingRange( );
+  }
+  else
+    camera->SetParallelScale( camera->GetParallelScale( ) / factor );
+  if( this->Interactor->GetLightFollowCamera( ) )
+    this->CurrentRenderer->UpdateLightsGeometryToFollowCamera( );
+  this->Interactor->Render( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::BaseStyle::
+_ProcessEvents(
+  vtkObject* object,
+  unsigned long event,
+  void* clientdata,
+  void* calldata
+  )
+{
+  // Get active style and interactor
+  Self* s = reinterpret_cast< Self* >( clientdata );
+  if( s == NULL )
+    return;
+
+  // Process events
+  switch( event )
+  {
+  case vtkCommand::MouseMoveEvent:
+  {
+    s->OnMouseMove( );
+  }
+  break;
+  case vtkCommand::LeftButtonPressEvent:
+  {
+    unsigned char nc = s->m_LeftButtonEvent.Clicks( );
+    if( nc == 2 )
+      s->OnLeftDoubleClick( );
+    else if( nc == 1 )
+      s->OnLeftClick( );
+    s->OnLeftButtonDown( );
+  }
+  break;
+  case vtkCommand::LeftButtonReleaseEvent:
+  {
+    s->m_LeftButtonEvent.Release( );
+    s->OnLeftButtonUp( );
+  }
+  break;
+  case vtkCommand::MiddleButtonPressEvent:
+  {
+    unsigned char nc = s->m_MiddleButtonEvent.Clicks( );
+    if( nc == 2 )
+      s->OnMiddleDoubleClick( );
+    else if( nc == 1 )
+      s->OnMiddleClick( );
+    s->OnMiddleButtonDown( );
+  }
+  break;
+  case vtkCommand::MiddleButtonReleaseEvent:
+  {
+    s->m_MiddleButtonEvent.Release( );
+    s->OnMiddleButtonUp( );
+  }
+  break;
+  case vtkCommand::RightButtonPressEvent:
+  {
+    unsigned char nc = s->m_RightButtonEvent.Clicks( );
+    if( nc == 2 )
+      s->OnRightDoubleClick( );
+    else if( nc == 1 )
+      s->OnRightClick( );
+    s->OnRightButtonDown( );
+  }
+  break;
+  case vtkCommand::RightButtonReleaseEvent:
+  {
+    s->m_RightButtonEvent.Release( );
+    s->OnRightButtonUp( );
+  }
+  break;
+  case vtkCommand::MouseWheelForwardEvent:
+  {
+    s->OnMouseWheelForward( );
+  }
+  break;
+  case vtkCommand::MouseWheelBackwardEvent:
+  {
+    s->OnMouseWheelBackward( );
+  }
+  break;
+  case vtkCommand::KeyPressEvent:
+  {
+    s->OnKeyDown( );
+    s->OnKeyPress( );
+  }
+  break;
+  case vtkCommand::KeyReleaseEvent:
+  {
+    s->OnKeyUp( );
+    s->OnKeyRelease( );
+  }
+  break;
+  case vtkCommand::CharEvent:
+  {
+    s->OnChar( );
+  }
+  break;
+  case vtkCommand::ExposeEvent:
+  {
+    s->OnExpose( );
+  }
+  break;
+  case vtkCommand::ConfigureEvent:
+  {
+    s->OnConfigure( );
+  }
+  break;
+  case vtkCommand::EnterEvent:
+  {
+    s->OnEnter( );
+  }
+  break;
+  case vtkCommand::LeaveEvent:
+  {
+    s->OnLeave( );
+  }
+  break;
+  case vtkCommand::TimerEvent:
+  {
+    // Do nothing
+  }
+  break;
+  case vtkCommand::DeleteEvent:
+  {
+    s->SetInteractor( 0 );
+  }
+  break;
+  case vtkCommand::TDxMotionEvent:
+  case vtkCommand::TDxButtonPressEvent:
+  case vtkCommand::TDxButtonReleaseEvent:
+  {
+    s->DelegateTDxEvent( event, calldata );
+  }
+  break;
+  default:
+    break;
+  } // hctiws
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/BaseStyle.h b/lib/cpExtensions/Interaction/BaseStyle.h
new file mode 100644 (file)
index 0000000..cee7078
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef __cpExtensions__Interaction__BaseStyle__h__
+#define __cpExtensions__Interaction__BaseStyle__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkInteractorStyle.h>
+#include <map>
+
+// -------------------------------------------------------------------------
+#define cpExtensions_BaseStyle_Commands( C )                            \
+  protected:                                                            \
+  std::map< T##C##Command, void* > m_##C##Commands;                     \
+  public:                                                               \
+  inline void Add##C##Command( T##C##Command c, void* d )               \
+  {                                                                     \
+    if( c != NULL )                                                     \
+    {                                                                   \
+      this->m_##C##Commands[ c ] = d;                                   \
+      this->Modified( );                                                \
+    }                                                                   \
+  }                                                                     \
+  inline void Remove##C##Command( T##C##Command c )                     \
+  {                                                                     \
+    std::map< T##C##Command, void* >::iterator i =                      \
+      this->m_##C##Commands.find( c );                                  \
+    if( i != this->m_##C##Commands.end( ) )                             \
+    {                                                                   \
+      this->m_##C##Commands.erase( i );                                 \
+      this->Modified( );                                                \
+    }                                                                   \
+  }
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Interaction
+  {
+    /**
+     */
+    class cpExtensions_EXPORT BaseStyle
+      : public vtkInteractorStyle
+    {
+    public:
+      typedef BaseStyle Self;
+      vtkTypeMacro( BaseStyle, vtkInteractorStyle );
+
+      enum ButtonID
+      {
+        ButtonID_None = 0,
+        ButtonID_Left,
+        ButtonID_Middle,
+        ButtonID_Right
+      };
+
+      // Callbacks types
+      typedef void ( *TMouseCommand )(
+        void*, const ButtonID&, int*, double*, bool, bool, bool
+        );
+      typedef TMouseCommand TMouseClickCommand;
+      typedef TMouseCommand TMouseDoubleClickCommand;
+
+      // Associate callbacks for each event
+      cpExtensions_BaseStyle_Commands( MouseClick );
+      cpExtensions_BaseStyle_Commands( MouseDoubleClick );
+
+    public:
+      static void SetSetDoubleClickDelay( long delay );
+      void DelegateTDxEvent( unsigned long event, void* calldata );
+
+      // Possible mouse motion events
+      virtual void OnMouseMove( ) cpExtensions_OVERRIDE;
+      virtual void OnMouseWheelForward( )  cpExtensions_OVERRIDE { }
+      virtual void OnMouseWheelBackward( ) cpExtensions_OVERRIDE { }
+
+      // Possible mouse click-related events
+      inline ButtonID GetButtonID( ) const { return( this->m_ActiveButton ); }
+
+      virtual void OnLeftButtonDown( ) cpExtensions_OVERRIDE;
+      virtual void OnLeftButtonUp( ) cpExtensions_OVERRIDE;
+      virtual void OnMiddleButtonDown( ) cpExtensions_OVERRIDE;
+      virtual void OnMiddleButtonUp( ) cpExtensions_OVERRIDE;
+      virtual void OnRightButtonDown( ) cpExtensions_OVERRIDE;
+      virtual void OnRightButtonUp( ) cpExtensions_OVERRIDE;
+
+      virtual void OnLeftClick( );
+      virtual void OnLeftDoubleClick( );
+      virtual void OnMiddleClick( );
+      virtual void OnMiddleDoubleClick( );
+      virtual void OnRightClick( );
+      virtual void OnRightDoubleClick( );
+
+      // Keyboard-related events
+      virtual void OnChar( ) cpExtensions_OVERRIDE       { }
+      virtual void OnKeyDown( ) cpExtensions_OVERRIDE    { }
+      virtual void OnKeyUp( ) cpExtensions_OVERRIDE      { }
+      virtual void OnKeyPress( ) cpExtensions_OVERRIDE   { }
+      virtual void OnKeyRelease( ) cpExtensions_OVERRIDE { }
+
+      // Other events
+      virtual void OnExpose( ) cpExtensions_OVERRIDE    { }
+      virtual void OnConfigure( ) cpExtensions_OVERRIDE { }
+      virtual void OnEnter( ) cpExtensions_OVERRIDE     { }
+      virtual void OnLeave( ) cpExtensions_OVERRIDE     { }
+
+      virtual void Dolly( ) cpExtensions_OVERRIDE;
+      virtual void Pan( ) cpExtensions_OVERRIDE;
+
+    protected:
+      BaseStyle( );
+      virtual ~BaseStyle( );
+
+      virtual void _Dolly( double factor );
+
+      // Extension interface
+      virtual bool _PickPosition( int idx[ 2 ], double pos[ 3 ] ) = 0;
+
+      // Main event callback
+      static void _ProcessEvents(
+        vtkObject* object,
+        unsigned long event,
+        void* clientdata,
+        void* calldata
+        );
+
+    private:
+      // Purposely not implemented
+      BaseStyle( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      double m_MotionFactor;
+
+      /**
+       * Button events
+       */
+      struct _TMouseButtonEvent
+      {
+        static long MaxDoubleClick;
+        long m_LastButtonUp;
+        long m_LastButtonHeld;
+        long m_LastButtonDown;
+
+        inline _TMouseButtonEvent( )
+          { this->Reset( ); }
+        inline void Reset( )
+          {
+            this->m_LastButtonUp = 0;
+            this->m_LastButtonHeld = 0;
+            this->m_LastButtonDown = -1;
+          }
+        inline void Release( )
+          {
+            /* TODO
+               long c = cpExtensions_CHRONO;
+               this->m_LastButtonUp = c;
+               this->m_LastButtonHeld = c - this->m_LastButtonDown;
+               this->m_LastButtonDown = -1;
+            */
+          }
+        inline unsigned char Clicks( )
+          {
+            /* TODO
+               unsigned char n = 0;
+               long c = cpExtensions_CHRONO;
+               if(
+               this->m_LastButtonHeld < MaxDoubleClick &&
+               ( c - this->m_LastButtonUp ) < MaxDoubleClick
+               )
+               {
+               this->Reset( );
+               n = 2;
+               }
+               else
+               n = 1;
+               if( this->m_LastButtonDown < 0 )
+               this->m_LastButtonDown = c;
+               return( n );
+            */
+            return( 1 );
+          }
+      };
+      _TMouseButtonEvent m_LeftButtonEvent;
+      _TMouseButtonEvent m_MiddleButtonEvent;
+      _TMouseButtonEvent m_RightButtonEvent;
+      ButtonID           m_ActiveButton;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Interaction__BaseStyle__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/ImageSlicePointPlacer.cxx b/lib/cpExtensions/Interaction/ImageSlicePointPlacer.cxx
new file mode 100644 (file)
index 0000000..45c020b
--- /dev/null
@@ -0,0 +1,275 @@
+#include <cpExtensions/Interaction/ImageSlicePointPlacer.h>
+#include <cpExtensions/Visualization/ImageSliceMapper.h>
+#include <vtkBoundedPlanePointPlacer.h>
+#include <vtkImageData.h>
+#include <vtkImageMapper3D.h>
+#include <vtkImageSlice.h>
+#include <vtkPlane.h>
+
+// -------------------------------------------------------------------------
+vtkCxxSetObjectMacro(
+  cpExtensions::Interaction::ImageSlicePointPlacer, ImageSlice, vtkImageSlice
+  );
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::ImageSlicePointPlacer::
+Self* cpExtensions::Interaction::ImageSlicePointPlacer::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSlicePointPlacer::
+ComputeWorldPosition(
+  vtkRenderer* ren,
+  double displayPos[ 2 ],
+  double worldPos[ 3 ],
+  double worldOrient[ 9 ]
+  )
+{
+  if( !this->UpdateInternalState( ) )
+    return( 0 );
+  return(
+    this->Placer->ComputeWorldPosition(
+      ren, displayPos, worldPos, worldOrient
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSlicePointPlacer::
+ComputeWorldPosition(
+  vtkRenderer* ren,
+  double displayPos[ 2 ],
+  double refWorldPos[ 2 ],
+  double worldPos[ 3 ],
+  double worldOrient[ 9 ]
+  )
+{
+  if( !this->UpdateInternalState( ) )
+    return( 0 );
+  return(
+    this->Placer->ComputeWorldPosition(
+      ren, displayPos, refWorldPos, worldPos, worldOrient
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSlicePointPlacer::
+ValidateWorldPosition( double worldPos[ 3 ] )
+{
+  if( !this->UpdateInternalState( ) )
+    return( 0 );
+  return( this->Placer->ValidateWorldPosition( worldPos ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSlicePointPlacer::
+ValidateWorldPosition( double worldPos[ 3 ], double worldOrient[ 9 ] )
+{
+  if( !this->UpdateInternalState( ) )
+    return( 0 );
+  return( this->Placer->ValidateWorldPosition( worldPos, worldOrient ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSlicePointPlacer::
+UpdateWorldPosition(
+  vtkRenderer* ren, double worldPos[ 3 ], double worldOrient[ 9 ]
+  )
+{
+  if( !this->UpdateInternalState( ) )
+    return( 0 );
+  return( this->Placer->UpdateWorldPosition( ren, worldPos, worldOrient ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSlicePointPlacer::
+UpdateInternalState( )
+{
+  if( !this->ImageSlice )
+    return( 0 );
+
+  vtkImageData* input = this->ImageSlice->GetMapper( )->GetInput( );
+  if( !input )
+    return( 0 );
+
+  double spacing[ 3 ];
+  input->GetSpacing( spacing );
+
+  double origin[ 3 ];
+  input->GetOrigin( origin );
+
+  double b[ 6 ];
+  this->ImageSlice->GetBounds( b );
+  if( this->Bounds[ 0 ] != VTK_DOUBLE_MAX)
+  {
+    b[ 0 ] = ( b[ 0 ] < this->Bounds[ 0 ] )? this->Bounds[ 0 ] : b[ 0 ];
+    b[ 1 ] = ( b[ 1 ] > this->Bounds[ 1 ] )? this->Bounds[ 1 ] : b[ 1 ];
+    b[ 2 ] = ( b[ 2 ] < this->Bounds[ 2 ] )? this->Bounds[ 2 ] : b[ 2 ];
+    b[ 3 ] = ( b[ 3 ] > this->Bounds[ 3 ] )? this->Bounds[ 3 ] : b[ 3 ];
+    b[ 4 ] = ( b[ 4 ] < this->Bounds[ 4 ] )? this->Bounds[ 4 ] : b[ 4 ];
+    b[ 5 ] = ( b[ 5 ] > this->Bounds[ 5 ] )? this->Bounds[ 5 ] : b[ 5 ];
+
+  } // fi
+
+  int displayExtent[ 6 ] = { 0, 1, 0, 1, 0, 1 };
+  input->GetExtent( displayExtent );
+  auto mapper =
+    dynamic_cast< cpExtensions::Visualization::ImageSliceMapper* >(
+      this->ImageSlice->GetMapper( )
+      );
+  if( mapper != NULL )
+  {
+    auto ori = mapper->GetOrientation( );
+    displayExtent[ ( ori << 1 ) + 1 ] =
+      displayExtent[ ori << 1 ] =
+      mapper->GetSliceNumber( );
+
+  } // fi
+
+  int axis;
+  double position;
+  if( displayExtent[ 0 ] == displayExtent[ 1 ] )
+  {
+    axis = vtkBoundedPlanePointPlacer::XAxis;
+    position = origin[ 0 ] + displayExtent[ 0 ] * spacing[ 0 ];
+  }
+  else if( displayExtent[ 2 ] == displayExtent[ 3 ] )
+  {
+    axis = vtkBoundedPlanePointPlacer::YAxis;
+    position = origin[ 1 ] + displayExtent[ 2 ] * spacing[ 1 ];
+  }
+  else if( displayExtent[ 4 ] == displayExtent[ 5 ] )
+  {
+    axis = vtkBoundedPlanePointPlacer::ZAxis;
+    position = origin[ 2 ] + displayExtent[ 4 ] * spacing[ 2 ];
+  }
+  else
+  {
+    vtkErrorMacro( "Incorrect display extent in Image Slice" );
+    return( 0 );
+
+  } // fi
+
+  if(
+    axis != this->Placer->GetProjectionNormal( ) ||
+    position != this->Placer->GetProjectionPosition( ) ||
+    b[ 0 ] != this->SavedBounds[ 0 ] ||
+    b[ 1 ] != this->SavedBounds[ 1 ] ||
+    b[ 2 ] != this->SavedBounds[ 2 ] ||
+    b[ 3 ] != this->SavedBounds[ 3 ] ||
+    b[ 4 ] != this->SavedBounds[ 4 ] ||
+    b[ 5 ] != this->SavedBounds[ 5 ]
+    )
+  {
+    this->SavedBounds[ 0 ] = b[ 0 ];
+    this->SavedBounds[ 1 ] = b[ 1 ];
+    this->SavedBounds[ 2 ] = b[ 2 ];
+    this->SavedBounds[ 3 ] = b[ 3 ];
+    this->SavedBounds[ 4 ] = b[ 4 ];
+    this->SavedBounds[ 5 ] = b[ 5 ];
+
+    this->Placer->SetProjectionNormal( axis );
+    this->Placer->SetProjectionPosition( position );
+
+    this->Placer->RemoveAllBoundingPlanes( );
+
+    vtkPlane* plane;
+    if( axis != vtkBoundedPlanePointPlacer::XAxis )
+    {
+      plane = vtkPlane::New( );
+      plane->SetOrigin( b[ 0 ], b[ 2 ], b[ 4 ] );
+      plane->SetNormal( 1.0, 0.0, 0.0 );
+      this->Placer->AddBoundingPlane( plane );
+      plane->Delete( );
+
+      plane = vtkPlane::New();
+      plane->SetOrigin( b[ 1 ], b[ 3 ], b[ 5 ] );
+      plane->SetNormal( -1.0, 0.0, 0.0 );
+      this->Placer->AddBoundingPlane( plane );
+      plane->Delete( );
+
+    } // fi
+
+    if( axis != vtkBoundedPlanePointPlacer::YAxis )
+    {
+      plane = vtkPlane::New( );
+      plane->SetOrigin( b[ 0 ], b[ 2 ], b[ 4 ] );
+      plane->SetNormal( 0.0, 1.0, 0.0 );
+      this->Placer->AddBoundingPlane( plane );
+      plane->Delete( );
+
+      plane = vtkPlane::New( );
+      plane->SetOrigin( b[ 1 ], b[ 3 ], b[ 5 ] );
+      plane->SetNormal( 0.0, -1.0, 0.0 );
+      this->Placer->AddBoundingPlane( plane );
+      plane->Delete( );
+
+    } // fi
+
+    if( axis != vtkBoundedPlanePointPlacer::ZAxis )
+    {
+      plane = vtkPlane::New( );
+      plane->SetOrigin( b[ 0 ], b[ 2 ], b[ 4 ] );
+      plane->SetNormal( 0.0, 0.0, 1.0 );
+      this->Placer->AddBoundingPlane( plane );
+      plane->Delete( );
+
+      plane = vtkPlane::New( );
+      plane->SetOrigin( b[ 1 ], b[ 3 ], b[ 5 ] );
+      plane->SetNormal( 0.0, 0.0, -1.0 );
+      this->Placer->AddBoundingPlane( plane );
+      plane->Delete( );
+
+    } // fi
+
+    this->Modified( );
+
+  } // fi
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSlicePointPlacer::
+SetWorldTolerance( double tol )
+{
+  double t =
+    ( tol < 0.0 )? 0.0: ( ( tol > VTK_DOUBLE_MAX )? VTK_DOUBLE_MAX: tol );
+  if( this->WorldTolerance != t )
+  {
+    this->WorldTolerance = t;
+    this->Placer->SetWorldTolerance( tol );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::ImageSlicePointPlacer::
+ImageSlicePointPlacer( )
+  : Superclass( )
+{
+  this->Placer = vtkBoundedPlanePointPlacer::New( );
+  this->ImageSlice = NULL;
+  this->SavedBounds[ 0 ] = 0.0;
+  this->SavedBounds[ 1 ] = 0.0;
+  this->SavedBounds[ 2 ] = 0.0;
+  this->SavedBounds[ 3 ] = 0.0;
+  this->SavedBounds[ 4 ] = 0.0;
+  this->SavedBounds[ 5 ] = 0.0;
+  this->Bounds[ 0 ] = this->Bounds[ 2 ] = this->Bounds[ 4 ] = VTK_DOUBLE_MAX;
+  this->Bounds[ 1 ] = this->Bounds[ 3 ] = this->Bounds[ 5 ] = VTK_DOUBLE_MIN;
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::ImageSlicePointPlacer::
+~ImageSlicePointPlacer( )
+{
+  this->Placer->Delete( );
+  this->SetImageSlice( NULL );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/ImageSlicePointPlacer.h b/lib/cpExtensions/Interaction/ImageSlicePointPlacer.h
new file mode 100644 (file)
index 0000000..e0465d9
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef __cpExtensions__Interaction__ImageSlicePointPlacer__h__
+#define __cpExtensions__Interaction__ImageSlicePointPlacer__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPointPlacer.h>
+
+class vtkBoundedPlanePointPlacer;
+class vtkImageSlice;
+class vtkRenderer;
+
+namespace cpExtensions
+{
+  namespace Interaction
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ImageSlicePointPlacer
+      : public vtkPointPlacer
+    {
+    public:
+      typedef ImageSlicePointPlacer Self;
+      vtkTypeMacro( ImageSlicePointPlacer, vtkPointPlacer );
+
+      vtkGetObjectMacro( ImageSlice, vtkImageSlice );
+      vtkSetVector6Macro( Bounds, double );
+      vtkGetVector6Macro( Bounds, double );
+
+    public:
+      static Self* New( );
+
+      int ComputeWorldPosition(
+        vtkRenderer* ren,
+        double displayPos[ 2 ],
+        double worldPos[ 3 ],
+        double worldOrient[ 9 ]
+        );
+      int ComputeWorldPosition(
+        vtkRenderer* ren,
+        double displayPos[ 2 ],
+        double refWorldPos[ 2 ],
+        double worldPos[ 3 ],
+        double worldOrient[ 9 ]
+        );
+      int ValidateWorldPosition( double worldPos[ 3 ] );
+      int ValidateWorldPosition(
+        double worldPos[ 3 ], double worldOrient[ 9 ]
+        );
+      int UpdateWorldPosition(
+        vtkRenderer* ren, double worldPos[ 3 ], double worldOrient[ 9 ]
+        );
+      int UpdateInternalState( );
+
+      void SetImageSlice( vtkImageSlice* slice );
+      virtual void SetWorldTolerance( double tol );
+
+    protected:
+      ImageSlicePointPlacer( );
+      virtual ~ImageSlicePointPlacer( );
+
+    private:
+      // Purposely not implemented
+      ImageSlicePointPlacer( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkImageSlice* ImageSlice;
+      vtkBoundedPlanePointPlacer* Placer;
+      double SavedBounds[ 6 ];
+      double Bounds[ 6 ];
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Interaction__ImageSlicePointPlacer__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/ImageSliceStyle.cxx b/lib/cpExtensions/Interaction/ImageSliceStyle.cxx
new file mode 100644 (file)
index 0000000..7b9df5a
--- /dev/null
@@ -0,0 +1,414 @@
+#include <cpExtensions/Interaction/ImageSliceStyle.h>
+#include <cpExtensions/Visualization/CursorActors.h>
+#include <cpExtensions/Visualization/LUTImageActor.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+#include <vtkAssemblyPath.h>
+#include <vtkCommand.h>
+#include <vtkImageData.h>
+#include <vtkImageSlice.h>
+#include <vtkProperty.h>
+#include <vtkPropCollection.h>
+#include <vtkPropPicker.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkTextActor.h>
+#include <vtkTextProperty.h>
+#include <sstream>
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::ImageSliceStyle::
+Self* cpExtensions::Interaction::ImageSliceStyle::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSliceStyle::
+GetSliceNumber( ) const
+{
+  if( this->m_WLActor.GetPointer( ) != NULL )
+    return( this->m_WLActor->GetSliceNumber( ) );
+  else
+    return( -1 );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Interaction::ImageSliceStyle::
+GetOrientation( ) const
+{
+  if( this->m_WLActor.GetPointer( ) != NULL )
+    return( this->m_WLActor->GetOrientation( ) );
+  else
+    return( -1 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnMouseMove( )
+{
+  static bool cursor_visible = false;
+
+  int idx[ 2 ];
+  double pnt[ 3 ];
+  if( this->_PickPointOnImageActor( idx, pnt ) )
+  {
+    this->m_Cursor->SetCursor( pnt, false );
+    this->_ShowText( pnt );
+    if( !cursor_visible )
+    {
+      this->m_Cursor->VisibilityOn( );
+      this->m_Text->VisibilityOn( );
+      cursor_visible = true;
+
+    } // fi
+    this->Interactor->Render( );
+  }
+  else
+  {
+    if( cursor_visible )
+    {
+      this->m_Cursor->VisibilityOff( );
+      this->m_Text->VisibilityOff( );
+      cursor_visible = false;
+      this->Interactor->Render( );
+
+    } // fi
+
+  } // fi
+
+  this->Overclass::OnMouseMove( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnMouseWheelForward( )
+{
+  static int s = 0;
+  if( this->m_WLActor.GetPointer( ) == NULL )
+    return;
+  s = this->m_WLActor->GetSliceNumber( );
+  s += ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
+  this->m_WLActor->SetSliceNumber( s );
+  s = this->m_WLActor->GetSliceNumber( );
+  if( this->m_LUTActor.GetPointer( ) != NULL )
+    this->m_LUTActor->SetSliceNumber( s );
+  this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
+  this->Interactor->Render( );
+  this->OnMouseMove( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnMouseWheelBackward( )
+{
+  static int s = 0;
+  if( this->m_WLActor.GetPointer( ) == NULL )
+    return;
+  s = this->m_WLActor->GetSliceNumber( );
+  s -= ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
+  this->m_WLActor->SetSliceNumber( s );
+  s = this->m_WLActor->GetSliceNumber( );
+  if( this->m_LUTActor.GetPointer( ) != NULL )
+    this->m_LUTActor->SetSliceNumber( s );
+  this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
+  this->Interactor->Render( );
+  this->OnMouseMove( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnChar( )
+{
+  switch( this->Interactor->GetKeyCode( ) )
+  {
+  case 'r': case 'R':
+  {
+    this->FindPokedRenderer(
+      this->Interactor->GetEventPosition( )[ 0 ],
+      this->Interactor->GetEventPosition( )[ 1 ]
+      );
+    this->CurrentRenderer->ResetCamera( );
+    this->Interactor->Render( );
+  }
+  break;
+  default:
+    break;
+
+  } // hctiws
+}
+
+/* TODO
+cpExtensions::Visualization::ImageViewerActors*
+cpExtensions::Interaction::ImageSliceStyle::
+GetActors( )
+{
+  return( this->m_Actors );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::ImageViewerActors*
+cpExtensions::Interaction::ImageSliceStyle::
+GetActors( ) const
+{
+  return( this->m_Actors );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+SetActors( cpExtensions::Visualization::ImageViewerActors* actors )
+{
+  this->m_Actors = actors;
+  if( actors != NULL )
+  {
+    this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
+    this->m_PropPicker->PickFromListOn( );
+    this->m_PropPicker->GetPickList( )->RemoveAllItems( );
+    this->m_PropPicker->
+      AddPickList( this->m_Actors->GetWindowLevelImageActor( ) );
+  }
+  else
+    this->m_PropPicker = NULL;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnMouseMove( )
+{
+  this->Superclass::OnMouseMove( );
+  if( this->m_Actors.GetPointer( ) == NULL )
+    return;
+
+  // Slice synch
+  static int idx[ 2 ];
+  static double pos[ 3 ];
+  if( this->_PickPosition( idx, pos ) )
+  {
+    if(
+      this->Interactor->GetControlKey( ) == 1 &&
+      this->GetButtonID( ) == Self::ButtonID_Left
+      )
+    {
+      this->m_Actors->SetSuperCursor( pos, this->m_Actors->GetOrientation( ) == 2 );
+      this->InvokeEvent( vtkCommand::UserEvent + 1, pos );
+    }
+    else
+      this->m_Actors->SetCursor( pos, this->m_Actors->GetOrientation( ) == 2 );
+  }
+  else
+    this->m_Actors->HideViewerActors( );
+  this->Interactor->Render( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnMouseWheelForward( )
+{
+  static int s = 0;
+  if( this->m_Actors.GetPointer( ) == NULL )
+    return;
+  s = this->m_Actors->GetSliceNumber( );
+  s += ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
+  this->m_Actors->SetSliceNumber( s );
+  s = this->m_Actors->GetSliceNumber( );
+  this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
+  this->Interactor->Render( );
+  this->OnMouseMove( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnMouseWheelBackward( )
+{
+  static int s = 0;
+  if( this->m_Actors.GetPointer( ) == NULL )
+    return;
+  s = this->m_Actors->GetSliceNumber( );
+  s -= ( this->Interactor->GetShiftKey( ) == 1 )? 10: 1;
+  this->m_Actors->SetSliceNumber( s );
+  s = this->m_Actors->GetSliceNumber( );
+  this->InvokeEvent( vtkCommand::UserEvent + 2, &s );
+  this->Interactor->Render( );
+  this->OnMouseMove( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+OnChar( )
+{
+}
+*/
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::ImageSliceStyle::
+ImageSliceStyle( )
+  : Superclass( )
+{
+  this->SetInteractionModeToImage2D( );
+  this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( );
+  this->m_PropPicker->PickFromListOn( );
+
+  this->m_Cursor = vtkSmartPointer< TCursor >::New( );
+  this->m_Cursor->VisibilityOff( );
+  this->m_Cursor->GetProperty( 0 )->SetColor( 1, 1, 0 );
+  this->m_Cursor->GetProperty( 1 )->SetColor( 1, 1, 0 );
+
+  // Prepare text
+  this->m_TextBuffer[ 0 ] = '\0';
+  this->m_Text = vtkSmartPointer< vtkTextActor >::New( );
+  this->m_Text->SetTextScaleModeToNone( );
+  auto textprop = this->m_Text->GetTextProperty( );
+  textprop->SetColor( 1, 1, 0 );
+  textprop->SetFontFamilyToCourier( );
+  textprop->SetFontSize( 12 );
+  textprop->BoldOff( );
+  textprop->ItalicOff( );
+  textprop->ShadowOff( );
+  textprop->SetJustificationToLeft( );
+  textprop->SetVerticalJustificationToBottom( );
+  auto coord = this->m_Text->GetPositionCoordinate( );
+  coord->SetCoordinateSystemToNormalizedViewport( );
+  coord->SetValue( 0.01, 0.02 );
+  this->m_Text->VisibilityOff( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::ImageSliceStyle::
+~ImageSliceStyle( )
+{
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::Interaction::ImageSliceStyle::
+_PickPointOnImageActor( int idx[ 2 ], double pnt[ 3 ] )
+{
+  // Check if data is valid
+  if(
+    this->Interactor == NULL ||
+    this->CurrentRenderer == NULL ||
+    this->m_PropPicker.GetPointer( ) == NULL
+    )
+    return( false );
+
+  // Find the renderer where the event has been raised
+  idx[ 0 ] = this->Interactor->GetEventPosition( )[ 0 ];
+  idx[ 1 ] = this->Interactor->GetEventPosition( )[ 1 ];
+  this->FindPokedRenderer( double( idx[ 0 ] ), double( idx[ 1 ] ) );
+
+  // Check if the image has changed
+  this->Interactor->GetPicker( )->
+    Pick( idx[ 0 ], idx[ 1 ], 0.0, this->CurrentRenderer );
+  auto picker =
+    vtkAbstractPropPicker::SafeDownCast( this->Interactor->GetPicker( ) );
+  if( picker == NULL )
+    return( false );
+  TWLActor* curr_actor = dynamic_cast< TWLActor* >( picker->GetProp3D( ) );
+  if( curr_actor != this->m_WLActor.GetPointer( ) && curr_actor != NULL )
+  {
+    this->m_WLActor = curr_actor;
+    this->m_PropPicker->GetPickList( )->RemoveAllItems( );
+    this->m_PropPicker->AddPickList( curr_actor );
+
+    auto props = this->CurrentRenderer->GetViewProps( );
+    this->m_LUTActor = NULL;
+    props->InitTraversal( );
+    vtkProp* prop;
+    while( ( ( prop = props->GetNextProp( ) ) != NULL ) && ( this->m_LUTActor.GetPointer( ) == NULL ) )
+      this->m_LUTActor = dynamic_cast< TLUTActor* >( prop );
+
+    this->m_Cursor->SetImageBounds( curr_actor->GetImage( )->GetBounds( ) );
+    this->m_Cursor->SetImageOrientation( curr_actor->GetOrientation( ) );
+    this->m_Cursor->InitTraversal( );
+    while( vtkProp* prop = this->m_Cursor->GetNextProp( ) )
+      this->CurrentRenderer->AddViewProp( prop );
+    this->CurrentRenderer->AddViewProp( this->m_Text );
+
+  } // fi
+  if( this->m_WLActor.GetPointer( ) == NULL )
+  {
+    this->m_PropPicker->GetPickList( )->RemoveAllItems( );
+    return( false );
+
+  } // fi
+
+  // Pick a 3D position
+  int r = this->m_PropPicker->Pick(
+    double( idx[ 0 ] ), double( idx[ 1 ] ), double( 0 ),
+    this->CurrentRenderer
+    );
+  if( r == 0 )
+    return( false );
+  this->m_PropPicker->GetPickPosition( pnt );
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+_CorrectPosition( double pos[ 3 ], int ijk[ 3 ] )
+{
+  if( this->m_WLActor.GetPointer( ) == NULL )
+    return;
+  auto image = this->m_WLActor->GetImage( );
+  if( image == NULL )
+    return;
+
+  // Approximate image index
+  double pcoords[ 3 ];
+  image->ComputeStructuredCoordinates( pos, ijk, pcoords );
+
+  // Manually correct index
+  int ext[ 6 ];
+  image->GetExtent( ext );
+  for( int i = 0; i < 3; ++i )
+  {
+    if( ijk[ i ] < ext[ i << 1 ] )
+      ijk[ i ] = ext[ i << 1 ];
+    if( ext[ ( i << 1 ) + 1 ] < ijk[ i ] )
+      ijk[ i ] = ext[ ( i << 1 ) + 1 ];
+
+  } // rof
+
+  // Get real coordinates
+  int o = this->m_WLActor->GetOrientation( );
+  ijk[ o ] = this->m_WLActor->GetSliceNumber( );
+  image->GetPoint( image->ComputePointId( ijk ), pos );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::ImageSliceStyle::
+_ShowText( double pos[ 3 ] )
+{
+  if( this->m_WLActor.GetPointer( ) == NULL )
+    return;
+  auto image = this->m_WLActor->GetImage( );
+  if( image == NULL )
+    return;
+
+  int ijk[ 3 ];
+  this->_CorrectPosition( pos, ijk );
+  int o = this->m_WLActor->GetOrientation( );
+
+  std::stringstream buffer;
+  buffer << "Axis: " << char( 'X' + char( o ) ) << std::endl;
+  int nScl = image->GetNumberOfScalarComponents( );
+  buffer
+    << "Pixel: [" << ijk[ 0 ]
+    << "," << ijk[ 1 ]
+    << "," << ijk[ 2 ] << "] = < "
+    << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
+  for( int n = 1; n < nScl; ++n )
+    buffer
+      << " : "
+      << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n );
+  buffer << " >" << std::endl;
+  buffer
+    << "Point: ("
+    << pos[ 0 ] << ", " << pos[ 1 ] << ", " << pos[ 2 ]
+    << ")";
+  cpExtensions_SPRINTF( this->m_TextBuffer, 1024, buffer.str( ).c_str( ) );
+  this->m_Text->SetInput( this->m_TextBuffer );
+  this->m_Text->VisibilityOn( );
+  this->m_Text->Modified( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/ImageSliceStyle.h b/lib/cpExtensions/Interaction/ImageSliceStyle.h
new file mode 100644 (file)
index 0000000..6d2b114
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef __cpExtensions__Interaction__ImageSliceStyle__h__
+#define __cpExtensions__Interaction__ImageSliceStyle__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkInteractorStyleImage.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkPropPicker;
+class vtkTextActor;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class CursorActors;
+    class LUTImageActor;
+    class WindowLevelImageActor;
+  }
+  namespace Interaction
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ImageSliceStyle
+      : public vtkInteractorStyleImage
+    {
+    public:
+      typedef ImageSliceStyle Self;
+      typedef cpExtensions::Visualization::CursorActors          TCursor;
+      typedef cpExtensions::Visualization::LUTImageActor         TLUTActor;
+      typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor;
+
+    public:
+      vtkTypeMacro( ImageSliceStyle, vtkInteractorStyleImage );
+      typedef vtkInteractorStyleImage::Superclass Overclass;
+
+    public:
+      static Self* New( );
+
+      int GetSliceNumber( ) const;
+      int GetOrientation( ) const;
+
+      virtual void OnMouseMove( ) cpExtensions_OVERRIDE;
+      virtual void OnMouseWheelForward( ) cpExtensions_OVERRIDE;
+      virtual void OnMouseWheelBackward( ) cpExtensions_OVERRIDE;
+      virtual void OnChar( ) cpExtensions_OVERRIDE;
+
+
+      /* TODO
+         cpExtensions::Visualization::ImageViewerActors* GetActors( );
+         const cpExtensions::Visualization::ImageViewerActors* GetActors( ) const;
+         void SetActors( cpExtensions::Visualization::ImageViewerActors* actors );
+
+         // Events
+         virtual void OnMouseMove( ) cpExtensions_OVERRIDE;
+         virtual void OnChar( ) cpExtensions_OVERRIDE;
+      */
+
+    protected:
+      ImageSliceStyle( );
+      virtual ~ImageSliceStyle( );
+
+      bool _PickPointOnImageActor( int idx[ 2 ], double pnt[ 3 ] );
+      void _CorrectPosition( double pos[ 3 ], int ijk[ 3 ] );
+      void _ShowText( double pos[ 3 ] );
+
+    private:
+      // Purposely not implemented
+      ImageSliceStyle( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< vtkPropPicker > m_PropPicker;
+      vtkSmartPointer< TLUTActor >     m_LUTActor;
+      vtkSmartPointer< TWLActor >      m_WLActor;
+      vtkSmartPointer< TCursor >       m_Cursor;
+      vtkSmartPointer< vtkTextActor >  m_Text;
+      char m_TextBuffer[ 1024 ];
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Interaction__ImageSliceStyle__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/SeedWidget.cxx b/lib/cpExtensions/Interaction/SeedWidget.cxx
new file mode 100644 (file)
index 0000000..509d7c2
--- /dev/null
@@ -0,0 +1,165 @@
+#include <cpExtensions/Interaction/SeedWidget.h>
+
+#include <vtkCommand.h>
+#include <vtkEvent.h>
+#include <vtkRenderWindowInteractor.h>
+#include <vtkWidgetCallbackMapper.h>
+#include <vtkWidgetEvent.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::SeedWidget::
+Self* cpExtensions::Interaction::SeedWidget::
+New( )
+{
+  return( new Self );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::SeedWidget::
+SetInteractor( vtkRenderWindowInteractor* rwi )
+{
+  this->Superclass::SetInteractor( rwi );
+  /* TODO
+     if( rwi != NULL )
+     {
+     TBaseStyle* s =
+     dynamic_cast< TBaseStyle* >( rwi->GetInteractorStyle( ) );
+     if( s != NULL )
+     {
+     s->AddMouseClickCommand( Self::_Click, this );
+     s->AddMouseDoubleClickCommand( Self::_DoubleClick, this );
+
+     } // fi
+
+     } // fi
+  */
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::SeedWidget::
+SeedWidget( )
+  : Superclass( )
+{
+  // These are the event callbacks supported by this widget
+  this->CallbackMapper->SetCallbackMethod(
+    vtkCommand::LeftButtonPressEvent,
+    vtkWidgetEvent::AddPoint,
+    this, Self::_AddPointAction
+    );
+  this->CallbackMapper->SetCallbackMethod(
+    vtkCommand::RightButtonPressEvent,
+    vtkWidgetEvent::Completed,
+    this, Self::_CompletedAction
+    );
+  this->CallbackMapper->SetCallbackMethod(
+    vtkCommand::MouseMoveEvent,
+    vtkWidgetEvent::Move,
+    this, Self::_MoveAction
+    );
+  this->CallbackMapper->SetCallbackMethod(
+    vtkCommand::LeftButtonReleaseEvent,
+    vtkWidgetEvent::EndSelect,
+    this, Self::_EndSelectAction
+    );
+  this->CallbackMapper->SetCallbackMethod(
+    vtkCommand::KeyPressEvent,
+    vtkEvent::NoModifier, 127, 1, "Delete",
+    vtkWidgetEvent::Delete,
+    this, Self::_DeleteAction
+    );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Interaction::SeedWidget::
+~SeedWidget( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::SeedWidget::
+_AddPointAction( vtkAbstractWidget* wdg )
+{
+  Self* self = dynamic_cast< Self* >( wdg );
+  if( self == NULL )
+    return;
+  auto iren = self->GetInteractor( );
+  if( iren == NULL )
+    return;
+  int shift = iren->GetShiftKey( );
+  if( shift == 1 )
+    Self::AddPointAction( wdg );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::SeedWidget::
+_CompletedAction( vtkAbstractWidget* wdg )
+{
+  // Do nothing
+  Self::CompletedAction( wdg );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::SeedWidget::
+_MoveAction( vtkAbstractWidget* wdg )
+{
+  // Do nothing
+  Self::MoveAction( wdg );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::SeedWidget::
+_EndSelectAction( vtkAbstractWidget* wdg )
+{
+  // Do nothing
+  Self::EndSelectAction( wdg );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Interaction::SeedWidget::
+_DeleteAction( vtkAbstractWidget* wdg )
+{
+  // Do nothing
+  Self::DeleteAction( wdg );
+}
+
+// -------------------------------------------------------------------------
+/* TODO
+   void cpExtensions::Interaction::SeedWidget::
+   _Click(
+   void* data, const TBaseStyle::ButtonID& button,
+   int* idx, double* pos, bool alt, bool ctr, bool sft
+   )
+   {
+   SeedWidget* self = reinterpret_cast< SeedWidget* >( data );
+   if( self == NULL )
+   return;
+   if( self->WidgetState == vtkSeedWidget::MovingSeed )
+   return;
+
+   int st = self->WidgetRep->ComputeInteractionState( idx[ 0 ], idx[ 1 ] );
+   if( st == vtkSeedRepresentation::NearSeed )
+   {
+   self->WidgetState = vtkSeedWidget::MovingSeed;
+
+   // Invoke an event on ourself for the handles
+   self->InvokeEvent( vtkCommand::LeftButtonPressEvent, NULL );
+   self->Superclass::StartInteraction( );
+   self->InvokeEvent( vtkCommand::StartInteractionEvent, NULL );
+   self->EventCallbackCommand->SetAbortFlag( 1 );
+   self->Render( );
+
+   } // fi
+   }
+
+   // -------------------------------------------------------------------------
+   void cpExtensions::Interaction::SeedWidget::
+   _DoubleClick(
+   void* data, const TBaseStyle::ButtonID& button,
+   int* idx, double* pos, bool alt, bool ctr, bool sft
+   )
+   {
+   Self::AddPointAction( reinterpret_cast< vtkAbstractWidget* >( data ) );
+   }
+*/
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Interaction/SeedWidget.h b/lib/cpExtensions/Interaction/SeedWidget.h
new file mode 100644 (file)
index 0000000..858218b
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __cpExtensions__Interaction__SeedWidget__h__
+#define __cpExtensions__Interaction__SeedWidget__h__
+
+#include <cpExtensions/Config.h>
+#include <cpExtensions/Interaction/BaseStyle.h>
+#include <vtkSeedWidget.h>
+
+namespace cpExtensions
+{
+  namespace Interaction
+  {
+    /**
+     */
+    class cpExtensions_EXPORT SeedWidget
+      : public vtkSeedWidget
+    {
+    public:
+      typedef SeedWidget Self;
+      vtkTypeMacro( SeedWidget, vtkSeedWidget );
+
+      typedef cpExtensions::Interaction::BaseStyle TBaseStyle;
+
+    public:
+      static Self* New( );
+
+      virtual void SetInteractor(
+        vtkRenderWindowInteractor* rwi
+        ) cpExtensions_OVERRIDE;
+
+    protected:
+      SeedWidget( );
+      virtual ~SeedWidget( );
+
+      static void _AddPointAction( vtkAbstractWidget* wdg );
+      static void _CompletedAction( vtkAbstractWidget* wdg );
+      static void _MoveAction( vtkAbstractWidget* wdg );
+      static void _EndSelectAction( vtkAbstractWidget* wdg );
+      static void _DeleteAction( vtkAbstractWidget* wdg );
+
+      /* TODO
+         static void _Click(
+         void* data, const TBaseStyle::ButtonID& button,
+         int* idx, double* pos, bool alt, bool ctr, bool sft
+         );
+         static void _DoubleClick(
+         void* data, const TBaseStyle::ButtonID& button,
+         int* idx, double* pos, bool alt, bool ctr, bool sft
+         );
+      */
+
+    private:
+      // Purposely not implemented
+      SeedWidget( const Self& );
+      Self& operator=( const Self& );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Interaction__SeedWidget__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/ActorsWidgetInterface.h b/lib/cpExtensions/QT/ActorsWidgetInterface.h
new file mode 100644 (file)
index 0000000..6af66ea
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __cpExtensions__QT__ActorsWidgetInterface__h__
+#define __cpExtensions__QT__ActorsWidgetInterface__h__
+
+#include <cpExtensions/Config.h>
+
+#include <string>
+#include <set>
+
+class vtkRenderWindowInteractor;
+
+namespace cpExtensions
+{
+  namespace QT
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ActorsWidgetInterface
+    {
+    public:
+      typedef ActorsWidgetInterface Self;
+
+    public:
+      ActorsWidgetInterface( ) { }
+      virtual ~ActorsWidgetInterface( ) { }
+
+      virtual std::set< vtkRenderWindowInteractor* > GetInteractors( ) const = 0;
+
+      virtual std::set< std::string > GetActorsNames( ) const = 0;
+      virtual bool IsWindowLevelImageActor( const std::string& name ) const = 0;
+      virtual bool IsLUTImageActor( const std::string& name ) const = 0;
+      virtual bool Is3DActor( const std::string& name ) const = 0;
+
+      virtual void GetScalarRange( const std::string& name, double r[ 2 ] ) const = 0;
+      virtual void GetWindowLevel( const std::string& name, double wl[ 2 ] ) const = 0;
+      virtual double GetWindow( const std::string& name ) const = 0;
+      virtual double GetLevel( const std::string& name ) const = 0;
+      virtual char GetImageInterpolation( const std::string& name ) const = 0;
+
+      virtual void GetColor( const std::string& name, double& r, double& g, double& b ) const = 0;
+      virtual double GetOpacity( const std::string& name ) const = 0;
+      virtual double GetPointSize( const std::string& name ) const = 0;
+      virtual double GetLineWidth( const std::string& name ) const = 0;
+      virtual int GetRepresentation( const std::string& name ) const = 0;
+
+      virtual void SetScalarRange( const std::string& name, double r[ 2 ] ) = 0;
+      virtual void SetScalarRange( const std::string& name, double min, double max ) = 0;
+      virtual void SetWindowLevel( const std::string& name, double wl[ 2 ] ) = 0;
+      virtual void SetWindowLevel( const std::string& name, double w, double l ) = 0;
+      virtual void SetWindow( const std::string& name, double w ) = 0;
+      virtual void SetLevel( const std::string& name, double l ) = 0;
+      virtual void SetImageInterpolation( const std::string& name, char i ) = 0;
+
+      virtual void SetColor( const std::string& name, double r, double g, double b ) = 0;
+      virtual void SetOpacity( const std::string& name, double o ) = 0;
+      virtual void SetPointSize( const std::string& name, double s ) = 0;
+      virtual void SetLineWidth( const std::string& name, double w ) = 0;
+      virtual void SetRepresentationToPoints( const std::string& name ) = 0;
+      virtual void SetRepresentationToSurface( const std::string& name ) = 0;
+      virtual void SetRepresentationToWireframe( const std::string& name ) = 0;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__ActorsWidgetInterface__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/ConfigurationChooser.cxx b/lib/cpExtensions/QT/ConfigurationChooser.cxx
new file mode 100644 (file)
index 0000000..00c121b
--- /dev/null
@@ -0,0 +1,51 @@
+#include <cpExtensions/QT/ConfigurationChooser.h>
+#include <cpExtensions/QT/ui_ConfigurationChooser.h>
+#include <cpExtensions/QT/ActorsWidgetInterface.h>
+#include <cpExtensions/QT/WindowLevelImageConfiguration.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::ConfigurationChooser::
+ConfigurationChooser( QWidget* parent, Qt::WindowFlags f )
+  : Superclass( parent, f ),
+    m_UI( new Ui::ConfigurationChooser ),
+    m_Data( NULL )
+{
+  this->m_UI->setupUi( this );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::ConfigurationChooser::
+~ConfigurationChooser( )
+{
+  delete this->m_UI;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ConfigurationChooser::
+setData( ActorsWidgetInterface* data )
+{
+  this->m_Data = data;
+  if( this->m_Data != NULL )
+  {
+    auto actors = this->m_Data->GetActorsNames( );
+    for( auto n = actors.begin( ); n != actors.end( ); ++n )
+    {
+      if( this->m_Data->IsWindowLevelImageActor( *n ) )
+      {
+        auto wl_wdg = new WindowLevelImageConfiguration( this );
+        wl_wdg->setData( data, *n );
+        this->m_UI->Configurations->addTab( wl_wdg, n->c_str( ) );
+      }
+      else if( this->m_Data->IsLUTImageActor( *n ) )
+      {
+      }
+      else if( this->m_Data->Is3DActor( *n ) )
+      {
+      } // fi
+
+    } // rof
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/ConfigurationChooser.h b/lib/cpExtensions/QT/ConfigurationChooser.h
new file mode 100644 (file)
index 0000000..dc908ff
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __cpExtensions__QT__ConfigurationChooser__h__
+#define __cpExtensions__QT__ConfigurationChooser__h__
+
+#include <cpExtensions/Config.h>
+#include <QDialog>
+
+// -------------------------------------------------------------------------
+namespace Ui { class ConfigurationChooser; }
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace QT
+  {
+    class ActorsWidgetInterface;
+
+    /**
+     */
+    class cpExtensions_EXPORT ConfigurationChooser
+      : public QDialog
+    {
+      Q_OBJECT;
+
+    public:
+      typedef ConfigurationChooser Self;
+      typedef QDialog                       Superclass;
+
+    public:
+      explicit ConfigurationChooser( QWidget* parent = NULL, Qt::WindowFlags f = 0 );
+      virtual ~ConfigurationChooser( );
+
+      void setData( ActorsWidgetInterface* data );
+
+    protected:
+      Ui::ConfigurationChooser* m_UI;
+      ActorsWidgetInterface* m_Data;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__ConfigurationChooser__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/ConfigurationChooser.ui b/lib/cpExtensions/QT/ConfigurationChooser.ui
new file mode 100644 (file)
index 0000000..4c33dfa
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigurationChooser</class>
+ <widget class="QDialog" name="ConfigurationChooser">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>475</width>
+    <height>317</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTabWidget" name="Configurations"/>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="Buttons">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>Buttons</sender>
+   <signal>accepted()</signal>
+   <receiver>ConfigurationChooser</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/lib/cpExtensions/QT/ImageWidget.cxx b/lib/cpExtensions/QT/ImageWidget.cxx
new file mode 100644 (file)
index 0000000..bac5f17
--- /dev/null
@@ -0,0 +1,225 @@
+#include <cpExtensions/QT/ImageWidget.h>
+#include <cpExtensions/Interaction/ImageSliceStyle.h>
+#include <cpExtensions/Visualization/LUTImageActor.h>
+#include <cpExtensions/Visualization/MeshActor.h>
+#include <cpExtensions/Visualization/OutlineSource.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+#include <vtkActor.h>
+#include <vtkCamera.h>
+#include <vtkImageData.h>
+#include <vtkImageProperty.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::ImageWidget::
+ImageWidget( QWidget* parent, Qt::WindowFlags f )
+  : Superclass( parent, f ),
+    m_ImageName( "" ),
+    m_OutlineActor( NULL )
+{
+  this->m_Style = vtkSmartPointer< TStyle >::New( );
+  this->m_Style->SetCurrentRenderer( this->m_Renderer );
+  this->SetStyle( this->m_Style );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::ImageWidget::
+~ImageWidget( )
+{
+  this->Clear( );
+  if( this->m_OutlineActor != NULL )
+    delete this->m_OutlineActor;
+  for( auto a = this->m_Actors.begin( ); a != this->m_Actors.end( ); ++a )
+    delete *a;
+  this->m_Actors.clear( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ImageWidget::
+Clear( )
+{
+  this->RemoveViewProps( );
+  this->m_ImageName = "";
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ImageWidget::
+SetImage( vtkImageData* image, const std::string& name, int orientation )
+{
+  if( name == "" )
+    return;
+  if( this->m_ImageName != "" )
+    this->Clear( );
+  this->m_ImageName = name;
+
+  this->m_WLActor = vtkSmartPointer< TWLActor >::New( );
+  this->m_WLActor->SetImage( image );
+  this->m_WLActor->SetOrientation( orientation );
+
+  this->m_LUTActor = vtkSmartPointer< TLUTActor >::New( );
+  this->m_LUTActor->SetOrientation( orientation );
+
+  this->m_Outline = vtkSmartPointer< TOutline >::New( );
+  this->m_Outline->SetBounds( image->GetBounds( ) );
+  this->m_Outline->Update( );
+
+  if( this->m_OutlineActor != NULL )
+    delete this->m_OutlineActor;
+  this->m_OutlineActor = new TActor( );
+  this->m_OutlineActor->SetMesh( this->m_Outline->GetOutput( ) );
+
+  double cr = double( 0 );
+  double cg = double( 0 );
+  double cb = double( 0 );
+  switch( this->m_WLActor->GetOrientation( ) )
+  {
+  case 0:  cr = double( 1 ); break;
+  case 1:  cg = double( 1 ); break;
+  case 2:  cb = double( 1 ); break;
+  default: cr = double( 1 ); break;
+  } // hctiws
+  this->m_OutlineActor->GetActor( )->GetProperty( )->SetColor( cr, cg, cb );
+
+  this->AddViewProp( this->m_WLActor, this->m_ImageName );
+  this->AddAuxViewProp( this->m_OutlineActor->GetActor( ), this->m_ImageName );
+  this->ResetCamera( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ImageWidget::
+Add( vtkDataSet* data, const std::string& name )
+{
+  auto image = dynamic_cast< vtkImageData* >( data );
+  auto pdata = dynamic_cast< vtkPolyData* >( data );
+  if( image != NULL )
+  {
+    this->m_LUTActor->AddImage( image );
+    this->m_LUTActor->GetProperty( )->SetOpacity( 0.5 );
+    this->AddViewProp( this->m_LUTActor, "__LUT_IMAGE__" );
+    this->Render( );
+  }
+  else if( pdata != NULL )
+  {
+    TActor* actor = new TActor( );
+    actor->SetMesh( pdata );
+    this->m_Actors.push_back( actor );
+    this->AddViewProp( actor->GetActor( ), name );
+    this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ImageWidget::
+ResetCamera( )
+{
+  if( this->m_WLActor.GetPointer( ) != NULL )
+  {
+    auto image = this->m_WLActor->GetImage( );
+    if( image != NULL )
+    {
+      double bounds[ 6 ];
+      image->GetBounds( bounds );
+
+      // Compute camera properties
+      double center[ 3 ];
+      center[ 0 ] = ( bounds[ 1 ] + bounds[ 0 ] ) / double( 2 );
+      center[ 1 ] = ( bounds[ 3 ] + bounds[ 2 ] ) / double( 2 );
+      center[ 2 ] = ( bounds[ 5 ] + bounds[ 4 ] ) / double( 2 );
+
+      int ori = this->m_WLActor->GetOrientation( );
+      double pos[ 3 ] = { double( 0 ) };
+      pos[ ori ] = double( 1 );
+      pos[ 0 ] += center[ 0 ];
+      pos[ 1 ] += center[ 1 ];
+      pos[ 2 ] += center[ 2 ];
+
+      double up[ 3 ] = { double( 0 ) };
+      if( ori == 0 )
+      {
+        if     ( this->m_Quadrant == 0 ) up[ 2 ] = double( 1 );
+        else if( this->m_Quadrant == 1 ) up[ 2 ] = double( 1 );
+        else if( this->m_Quadrant == 2 ) up[ 2 ] = double( 1 );
+        else if( this->m_Quadrant == 3 ) up[ 2 ] = double( 1 );
+      }
+      else if( ori == 1 )
+      {
+        if     ( this->m_Quadrant == 0 ) up[ 2 ] = double( 1 );
+        else if( this->m_Quadrant == 1 ) up[ 2 ] = double( 1 );
+        else if( this->m_Quadrant == 2 ) up[ 2 ] = double( 1 );
+        else if( this->m_Quadrant == 3 ) up[ 2 ] = double( 1 );
+      }
+      else if( ori == 2 )
+      {
+        if     ( this->m_Quadrant == 0 ) up[ 1 ] = double( -1 );
+        else if( this->m_Quadrant == 1 ) up[ 1 ] = double( -1 );
+        else if( this->m_Quadrant == 2 ) up[ 1 ] = double( -1 );
+        else if( this->m_Quadrant == 3 ) up[ 1 ] = double( -1 );
+        pos[ 2 ] *= double( -1 );
+
+      } // fi
+
+      // Reconfigure camera and return
+      auto camera = this->m_Renderer->GetActiveCamera( );
+      camera->ParallelProjectionOn( );
+      camera->SetFocalPoint( center );
+      camera->SetPosition( pos );
+      camera->SetViewUp( up );
+      this->m_Renderer->ResetCamera( bounds );
+    }
+    else
+      this->Superclass::ResetCamera( );
+  }
+  else
+    this->Superclass::ResetCamera( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::ImageWidget::
+TWLActor* cpExtensions::QT::ImageWidget::
+GetImageActor( )
+{
+  return( this->m_WLActor );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::QT::ImageWidget::
+TWLActor* cpExtensions::QT::ImageWidget::
+GetImageActor( ) const
+{
+  return( this->m_WLActor );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ImageWidget::
+SetColor( const std::string& name, double r, double g, double b )
+{
+  auto props = this->GetViewProps( name );
+  for( auto p = props.begin( ); p != props.end( ); ++p )
+  {
+    auto actor = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+    if( actor != NULL )
+      actor->GetProperty( )->SetColor( r, g, b );
+
+  } // rof
+  this->Render( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::ImageWidget::
+SetLineWidth( const std::string& name, double w )
+{
+  auto props = this->GetViewProps( name );
+  for( auto p = props.begin( ); p != props.end( ); ++p )
+  {
+    auto actor = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+    if( actor != NULL )
+      actor->GetProperty( )->SetLineWidth( w );
+
+  } // rof
+  this->Render( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/ImageWidget.h b/lib/cpExtensions/QT/ImageWidget.h
new file mode 100644 (file)
index 0000000..9932bda
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __cpExtensions__QT__ImageWidget__h__
+#define __cpExtensions__QT__ImageWidget__h__
+
+#include <cpExtensions/QT/RendererWidget.h>
+
+// -------------------------------------------------------------------------
+class vtkDataSet;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class OutlineSource;
+    class LUTImageActor;
+    class WindowLevelImageActor;
+    class MeshActor;
+  }
+  namespace Interaction { class ImageSliceStyle; }
+
+  namespace QT
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ImageWidget
+      : public RendererWidget
+    {
+      Q_OBJECT;
+
+    public:
+      typedef ImageWidget    Self;
+      typedef RendererWidget Superclass;
+
+      typedef cpExtensions::Visualization::OutlineSource         TOutline;
+      typedef cpExtensions::Visualization::MeshActor             TActor;
+      typedef cpExtensions::Visualization::LUTImageActor         TLUTActor;
+      typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor;
+      typedef cpExtensions::Interaction::ImageSliceStyle         TStyle;
+
+    public:
+      explicit ImageWidget( QWidget* parent = NULL, Qt::WindowFlags f = 0 );
+      virtual ~ImageWidget( );
+
+      void Clear( );
+      void SetImage(
+        vtkImageData* image, const std::string& name, int orientation = 2
+        );
+      void Add( vtkDataSet* data, const std::string& name );
+      virtual void ResetCamera( ) cpExtensions_OVERRIDE;
+
+      TWLActor* GetImageActor( );
+      const TWLActor* GetImageActor( ) const;
+
+      void SetColor( const std::string& name, double r, double g, double b );
+      void SetLineWidth( const std::string& name, double w );
+
+    protected:
+      std::string m_ImageName;
+
+      vtkSmartPointer< TWLActor > m_WLActor;
+      vtkSmartPointer< TLUTActor > m_LUTActor;
+      vtkSmartPointer< TOutline > m_Outline;
+      TActor* m_OutlineActor;
+      std::vector< TActor* > m_Actors;
+
+      vtkSmartPointer< TStyle > m_Style;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__ImageWidget__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/MPR3DWidget.cxx b/lib/cpExtensions/QT/MPR3DWidget.cxx
new file mode 100644 (file)
index 0000000..f86992d
--- /dev/null
@@ -0,0 +1,140 @@
+#include <cpExtensions/QT/MPR3DWidget.h>
+#include <cpExtensions/Visualization/ImageOutlineActor.h>
+#include <cpExtensions/Visualization/MeshActor.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+#include <vtkImageData.h>
+#include <vtkPlane.h>
+#include <vtkPolyData.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::MPR3DWidget::
+MPR3DWidget( QWidget* parent, Qt::WindowFlags f )
+  : Superclass( parent, f ),
+    m_ImageName( "" )
+{
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::MPR3DWidget::
+~MPR3DWidget( )
+{
+  for( auto a = this->m_Actors.begin( ); a != this->m_Actors.end( ); ++a )
+    delete *a;
+  this->m_Actors.clear( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPR3DWidget::
+Clear( )
+{
+  this->RemoveViewProps( );
+  this->m_ImageName = "";
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPR3DWidget::
+SetImage( vtkImageData* image, const std::string& name )
+{
+  if( name == "" )
+    return;
+  if( this->m_ImageName != "" )
+    this->Clear( );
+  this->m_ImageName = name;
+
+  for( unsigned int o = 0; o < 3; ++o )
+  {
+    this->m_WLActors[ o ] = vtkSmartPointer< TWLActor >::New( );
+    this->m_WLActors[ o ]->SetImage( image );
+    this->m_WLActors[ o ]->SetOrientation( o );
+
+    this->m_OLActors[ o ] = vtkSmartPointer< TOLActor >::New( );
+    this->m_OLActors[ o ]->SetBounds(
+      o, image->GetBounds( )[ o << 1 ], image->GetBounds( )
+      );
+
+    this->AddViewProp( this->m_WLActors[ o ], this->m_ImageName );
+    this->AddAuxViewProp( this->m_OLActors[ o ], this->m_ImageName );
+    this->ResetCamera( );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPR3DWidget::
+Add( vtkDataSet* data, const std::string& name )
+{
+  auto image = dynamic_cast< vtkImageData* >( data );
+  auto pdata = dynamic_cast< vtkPolyData* >( data );
+  if( image != NULL )
+  {
+    /* TODO
+       if( this->m_ImageName != "" )
+       {
+       }
+       else
+       this->SetImage( image, name );
+    */
+  }
+  else if( pdata != NULL )
+  {
+    TActor* actor = new TActor( );
+    actor->SetMesh( pdata );
+    this->m_Actors.push_back( actor );
+    this->AddViewProp( actor->GetActor( ), name );
+    this->Render( );
+    if( this->m_ImageName == "" )
+      this->ResetCamera( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::MPR3DWidget::
+TWLActor* cpExtensions::QT::MPR3DWidget::
+GetImageActor( int o )
+{
+  return( this->m_WLActors[ o % 3 ] );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::QT::MPR3DWidget::
+TWLActor* cpExtensions::QT::MPR3DWidget::
+GetImageActor( int o ) const
+{
+  return( this->m_WLActors[ o % 3 ] );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPR3DWidget::
+SetSliceNumber( int orientation, int slice )
+{
+  int o = orientation % 3;
+  this->m_WLActors[ o ]->SetSliceNumber( slice );
+  this->m_OLActors[ o ]->SetBounds(
+    o,
+    this->m_WLActors[ o ]->GetSlicePlane( )->GetOrigin( )[ o ],
+    this->m_WLActors[ o ]->GetImage( )->GetBounds( )
+    );
+  this->Render( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPR3DWidget::
+SetSlicesNumbers( int x, int y, int z )
+{
+  int s[] = { x, y, z };
+  for( int o = 0; o < 3; ++o )
+  {
+    this->m_WLActors[ o ]->SetSliceNumber( s[ o ] );
+    this->m_OLActors[ o ]->SetBounds(
+      o,
+      this->m_WLActors[ o ]->GetSlicePlane( )->GetOrigin( )[ o ],
+      this->m_WLActors[ o ]->GetImage( )->GetBounds( )
+      );
+
+  } // rof
+  this->Render( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/MPR3DWidget.h b/lib/cpExtensions/QT/MPR3DWidget.h
new file mode 100644 (file)
index 0000000..6a0ef6e
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __cpExtensions__QT__MPR3DWidget__h__
+#define __cpExtensions__QT__MPR3DWidget__h__
+
+#include <cpExtensions/QT/RendererWidget.h>
+
+// -------------------------------------------------------------------------
+class vtkDataSet;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class ImageOutlineActor;
+    class MeshActor;
+    class WindowLevelImageActor;
+  }
+
+  namespace QT
+  {
+    /**
+     */
+    class cpExtensions_EXPORT MPR3DWidget
+      : public cpExtensions::QT::RendererWidget
+    {
+      Q_OBJECT;
+
+    public:
+      typedef MPR3DWidget                      Self;
+      typedef cpExtensions::QT::RendererWidget Superclass;
+
+      typedef cpExtensions::Visualization::MeshActor             TActor;
+      typedef cpExtensions::Visualization::ImageOutlineActor     TOLActor;
+      typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor;
+
+    public:
+      explicit MPR3DWidget( QWidget* parent = NULL, Qt::WindowFlags f = 0 );
+      virtual ~MPR3DWidget( );
+
+      void Clear( );
+      void SetImage( vtkImageData* image, const std::string& name );
+      void Add( vtkDataSet* data, const std::string& name );
+
+      TWLActor* GetImageActor( int o );
+      const TWLActor* GetImageActor( int o ) const;
+
+      void SetSliceNumber( int orientation, int slice );
+      void SetSlicesNumbers( int x, int y, int z );
+
+    protected:
+      std::string m_ImageName;
+
+      vtkSmartPointer< TWLActor > m_WLActors[ 3 ];
+      vtkSmartPointer< TOLActor > m_OLActors[ 3 ];
+      std::vector< TActor* > m_Actors;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__MPR3DWidget__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/MPRInteractionCommand.cxx b/lib/cpExtensions/QT/MPRInteractionCommand.cxx
new file mode 100644 (file)
index 0000000..39dc19d
--- /dev/null
@@ -0,0 +1,97 @@
+#include <cpExtensions/QT/MPRInteractionCommand.h>
+#include <cpExtensions/Interaction/ImageSliceStyle.h>
+#include <cpExtensions/Visualization/ImageViewerActors.h>
+#include <cpExtensions/QT/ImageWidget.h>
+#include <cpExtensions/QT/MPR3DWidget.h>
+#include <vtkImageData.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::MPRInteractionCommand::
+Self* cpExtensions::QT::MPRInteractionCommand::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPRInteractionCommand::
+AddWidget( QWidget* w )
+{
+  typedef cpExtensions::QT::ImageWidget _TImageWidget;
+  typedef cpExtensions::QT::MPR3DWidget _TMPR3DWidget;
+
+  auto img = dynamic_cast< _TImageWidget* >( w );
+  auto ren = dynamic_cast< _TMPR3DWidget* >( w );
+  if( img != NULL )
+    this->m_ImageWidgets.insert( img );
+  else if( ren != NULL )
+    this->m_MPR3DWidgets.insert( ren );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::MPRInteractionCommand::
+Execute( vtkObject* caller, unsigned long evId, void* data )
+{
+  typedef cpExtensions::Interaction::ImageSliceStyle _TStyle;
+
+  static const unsigned long _SuperCursor = vtkCommand::UserEvent + 1;
+  static const unsigned long _Slice = vtkCommand::UserEvent + 2;
+
+  // Prepare interaction data
+  auto* src = dynamic_cast< _TStyle* >( caller );
+  if( src == NULL || ( evId != _SuperCursor && evId != _Slice ) )
+    return;
+  if( evId == _SuperCursor )
+  {
+    /* TODO
+       auto ori = src->GetActors( )->GetOrientation( );
+       auto img = src->GetActors( )->GetImage( );
+       auto pos = reinterpret_cast< double* >( data );
+       int ijk[ 3 ];
+       double pcoords[ 3 ];
+       img->ComputeStructuredCoordinates( pos, ijk, pcoords );
+
+       for(
+       auto i = this->m_ImageWidgets.begin( );
+       i != this->m_ImageWidgets.end( );
+       ++i
+       )
+       if( ( *i )->GetInteractorStyle( ) != src )
+       ( *i )->SetSliceNumber( ijk[ ( *i )->GetOrientation( ) ] );
+    
+       for(
+       auto r = this->m_MPR3DWidgets.begin( );
+       r != this->m_MPR3DWidgets.end( );
+       ++r
+       )
+       ( *r )->SetSlicesNumbers( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ] );
+    */
+  }
+  else if( evId == _Slice )
+  {
+    int slc = src->GetSliceNumber( );
+    int ori = src->GetOrientation( );
+    for(
+      auto r = this->m_MPR3DWidgets.begin( );
+      r != this->m_MPR3DWidgets.end( );
+      ++r
+      )
+      ( *r )->SetSliceNumber( ori, slc );
+
+  } // fi
+}
+      
+// -------------------------------------------------------------------------
+cpExtensions::QT::MPRInteractionCommand::
+MPRInteractionCommand( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::MPRInteractionCommand::
+~MPRInteractionCommand( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/MPRInteractionCommand.h b/lib/cpExtensions/QT/MPRInteractionCommand.h
new file mode 100644 (file)
index 0000000..29aa5de
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __cpExtensions__QT__MPRInteractionCommand__h__
+#define __cpExtensions__QT__MPRInteractionCommand__h__
+
+#include <cpExtensions/Config.h>
+#include <cpExtensions/Interaction/BaseStyle.h>
+#include <vtkCommand.h>
+#include <vtkSmartPointer.h>
+#include <set>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace QT
+  {
+    class ImageWidget;
+    class MPR3DWidget;
+
+    /**
+     */
+    class cpExtensions_EXPORT MPRInteractionCommand
+      : public vtkCommand
+    {
+    public:
+      typedef MPRInteractionCommand Self;
+
+    public:
+      vtkTypeMacro( MPRInteractionCommand, vtkCommand );
+
+    public:
+      static Self* New( );
+
+      void AddWidget( QWidget* w );
+
+      virtual void Execute(
+        vtkObject* caller, unsigned long evId, void* data
+        ) cpExtensions_OVERRIDE;
+      
+    protected:
+      MPRInteractionCommand( );
+      virtual ~MPRInteractionCommand( );
+
+    private:
+      // Purposely not implemented
+      MPRInteractionCommand( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      std::set< cpExtensions::QT::ImageWidget* > m_ImageWidgets;
+      std::set< cpExtensions::QT::MPR3DWidget* > m_MPR3DWidgets;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__MPRInteractionCommand__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/RendererWidget.cxx b/lib/cpExtensions/QT/RendererWidget.cxx
new file mode 100644 (file)
index 0000000..0189ef6
--- /dev/null
@@ -0,0 +1,990 @@
+#include <cpExtensions/QT/RendererWidget.h>
+#include <vtkAxesActor.h>
+#include <vtkCamera.h>
+#include <vtkImageProperty.h>
+#include <vtkInteractorStyle.h>
+#include <vtkOrientationMarkerWidget.h>
+#include <vtkProperty.h>
+#include <vtkRenderer.h>
+#include <vtkRenderWindow.h>
+#include <cpExtensions/Visualization/LUTImageActor.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::RendererWidget::
+RendererWidget( QWidget* parent, Qt::WindowFlags f )
+  : Superclass( parent, f ),
+    Superclass2( )
+{
+  this->m_Renderer = vtkSmartPointer< vtkRenderer >::New( );
+  this->GetRenderWindow( )->AddRenderer( this->m_Renderer );
+
+  vtkAxesActor* axes = vtkAxesActor::New( );
+  axes->AxisLabelsOff( );
+  this->m_Marker = vtkSmartPointer< vtkOrientationMarkerWidget >::New( );
+  this->m_Marker->SetOutlineColor( 1, 1, 1 );
+  this->m_Marker->SetOrientationMarker( axes );
+  this->m_Marker->SetInteractor( this->GetRenderWindow( )->GetInteractor( ) );
+  this->m_Marker->EnabledOn( );
+  this->m_Marker->InteractiveOff( );
+  axes->Delete( );
+  this->SetQuadrant( 0 );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::RendererWidget::
+~RendererWidget( )
+{
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::QT::RendererWidget::
+GetQuadrant( ) const
+{
+  return( this->m_Quadrant );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetQuadrant( int q )
+{
+  this->m_Quadrant = ( q - 1 ) % 4;
+  if( this->m_Quadrant == 0 )
+    this->m_Marker->SetViewport( 0.85, 0.00, 1.00, 0.15 );
+  else if( this->m_Quadrant == 1 )
+    this->m_Marker->SetViewport( 0.00, 0.00, 0.15, 0.15 );
+  else if( this->m_Quadrant == 2 )
+    this->m_Marker->SetViewport( 0.00, 0.85, 0.15, 1.00 );
+  else if( this->m_Quadrant == 3 )
+    this->m_Marker->SetViewport( 0.85, 0.85, 1.00, 1.00 );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderer* cpExtensions::QT::RendererWidget::
+GetRenderer( )
+{
+  return( this->m_Renderer );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderer* cpExtensions::QT::RendererWidget::
+GetRenderer( ) const
+{
+  return( this->m_Renderer );
+}
+
+// -------------------------------------------------------------------------
+vtkInteractorStyle* cpExtensions::QT::RendererWidget::
+GetStyle( )
+{
+  auto iren = this->GetInteractor( );
+  if( iren != NULL )
+    return(
+      dynamic_cast< vtkInteractorStyle* >( iren->GetInteractorStyle( ) )
+      );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+const vtkInteractorStyle* cpExtensions::QT::RendererWidget::
+GetStyle( ) const
+{
+  // Ugly, but necessary :-(
+  Self* self = const_cast< Self* >( this );
+  if( self != NULL )
+  {
+    auto iren = self->GetInteractor( );
+    if( iren != NULL )
+      return(
+        dynamic_cast< const vtkInteractorStyle* >(
+          iren->GetInteractorStyle( )
+          )
+        );
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetStyle( vtkInteractorStyle* style )
+{
+  this->GetInteractor( )->SetInteractorStyle( style );
+}
+
+// -------------------------------------------------------------------------
+vtkCamera* cpExtensions::QT::RendererWidget::
+GetActiveCamera( )
+{
+  return( this->m_Renderer->GetActiveCamera( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkCamera* cpExtensions::QT::RendererWidget::
+GetActiveCamera( ) const
+{
+  return( this->m_Renderer->GetActiveCamera( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+AddViewProp( vtkProp* prop, const std::string& name )
+{
+  if( prop != NULL )
+  {
+    auto i = this->m_ViewProps.find( name );
+    if( i == this->m_ViewProps.end( ) )
+      i =
+        this->m_ViewProps.insert(
+          TPropCollection::value_type( name, TProps( ) )
+          ).first;
+    i->second.insert( prop );
+    this->m_Renderer->AddViewProp( prop );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+AddViewProps( vtkPropCollection* props, const std::string& name )
+{
+  if( props != NULL )
+  {
+    auto i = this->m_ViewProps.find( name );
+    if( i == this->m_ViewProps.end( ) )
+      i =
+        this->m_ViewProps.insert(
+          TPropCollection::value_type( name, TProps( ) )
+          ).first;
+    props->InitTraversal( );
+    while( vtkProp* prop = props->GetNextProp( ) )
+    {
+      i->second.insert( prop );
+      this->m_Renderer->AddViewProp( prop );
+
+    } // elihw
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+AddAuxViewProp( vtkProp* prop, const std::string& name )
+{
+  if( prop != NULL )
+  {
+    auto i = this->m_AuxViewProps.find( name );
+    if( i == this->m_AuxViewProps.end( ) )
+      i =
+        this->m_AuxViewProps.insert(
+          TPropCollection::value_type( name, TProps( ) )
+          ).first;
+    i->second.insert( prop );
+    this->m_Renderer->AddViewProp( prop );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+AddAuxViewProps( vtkPropCollection* props, const std::string& name )
+{
+  if( props != NULL )
+  {
+    auto i = this->m_AuxViewProps.find( name );
+    if( i == this->m_AuxViewProps.end( ) )
+      i =
+        this->m_AuxViewProps.insert(
+          TPropCollection::value_type( name, TProps( ) )
+          ).first;
+    props->InitTraversal( );
+    while( vtkProp* prop = props->GetNextProp( ) )
+    {
+      i->second.insert( prop );
+      this->m_Renderer->AddViewProp( prop );
+
+    } // elhiw
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::RendererWidget::
+TProps& cpExtensions::QT::RendererWidget::
+GetViewProps( const std::string& name )
+{
+  static TProps zero;
+  auto i = this->m_ViewProps.find( name );
+  if( i == this->m_ViewProps.end( ) )
+  {
+    zero.clear( );
+    return( zero );
+  }
+  else
+    return( i->second );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::QT::RendererWidget::
+TProps& cpExtensions::QT::RendererWidget::
+GetViewProps( const std::string& name ) const
+{
+  static const TProps zero;
+  auto i = this->m_ViewProps.find( name );
+  if( i == this->m_ViewProps.end( ) )
+    return( zero );
+  else
+    return( i->second );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::RendererWidget::
+TProps& cpExtensions::QT::RendererWidget::
+GetAuxViewProps( const std::string& name )
+{
+  static TProps zero;
+  auto i = this->m_AuxViewProps.find( name );
+  if( i == this->m_AuxViewProps.end( ) )
+  {
+    zero.clear( );
+    return( zero );
+  }
+  else
+    return( i->second );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::QT::RendererWidget::
+TProps& cpExtensions::QT::RendererWidget::
+GetAuxViewProps( const std::string& name ) const
+{
+  static const TProps zero;
+  auto i = this->m_AuxViewProps.find( name );
+  if( i == this->m_AuxViewProps.end( ) )
+    return( zero );
+  else
+    return( i->second );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+RemoveViewProps( const std::string& name )
+{
+  auto i = this->m_ViewProps.find( name );
+  if( i != this->m_ViewProps.end( ) )
+  {
+    for( auto p = i->second.begin( ); p != i->second.end( ); ++p )
+      this->m_Renderer->RemoveViewProp( *p );
+    this->m_ViewProps.erase( i );
+
+  } // fi
+
+  i = this->m_AuxViewProps.find( name );
+  if( i != this->m_AuxViewProps.end( ) )
+  {
+    for( auto p = i->second.begin( ); p != i->second.end( ); ++p )
+      this->m_Renderer->RemoveViewProp( *p );
+    this->m_AuxViewProps.erase( i );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+RemoveViewProps( )
+{
+  this->m_Renderer->RemoveAllViewProps( );
+  this->m_ViewProps.clear( );
+  this->m_AuxViewProps.clear( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+HideViewProps( const std::string& name )
+{
+  auto i = this->m_ViewProps.find( name );
+  if( i != this->m_ViewProps.end( ) )
+    for( auto p = i->second.begin( ); p != i->second.end( ); ++p )
+      ( *p )->VisibilityOff( );
+  i = this->m_AuxViewProps.find( name );
+  if( i != this->m_AuxViewProps.end( ) )
+    for( auto p = i->second.begin( ); p != i->second.end( ); ++p )
+      ( *p )->VisibilityOff( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+ShowViewProps( const std::string& name )
+{
+  auto i = this->m_ViewProps.find( name );
+  if( i != this->m_ViewProps.end( ) )
+    for( auto p = i->second.begin( ); p != i->second.end( ); ++p )
+      ( *p )->VisibilityOn( );
+  i = this->m_AuxViewProps.find( name );
+  if( i != this->m_AuxViewProps.end( ) )
+    for( auto p = i->second.begin( ); p != i->second.end( ); ++p )
+      ( *p )->VisibilityOn( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+ResetCamera( )
+{
+  this->m_Renderer->ResetCamera( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+Render( )
+{
+  this->GetRenderWindow( )->Render( );
+}
+
+// -------------------------------------------------------------------------
+std::set< vtkRenderWindowInteractor* > cpExtensions::QT::RendererWidget::
+GetInteractors( ) const
+{
+  Self* self = const_cast< Self* >( this );
+  std::set< vtkRenderWindowInteractor* > ret;
+  ret.insert( self->GetRenderWindow( )->GetInteractor( ) );
+  return( ret );
+}
+
+// -------------------------------------------------------------------------
+std::set< std::string > cpExtensions::QT::RendererWidget::
+GetActorsNames( ) const
+{
+  std::set< std::string > names;
+  for(
+    auto p = this->m_ViewProps.begin( );
+    p != this->m_ViewProps.end( );
+    ++p
+    )
+    names.insert( p->first );
+  return( names );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::RendererWidget::
+IsWindowLevelImageActor( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto a = it->second.begin( );
+    if( a != it->second.end( ) )
+      return( dynamic_cast< TWLActor* >( a->GetPointer( ) ) != NULL );
+    else
+      return( false );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::RendererWidget::
+IsLUTImageActor( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto a = it->second.begin( );
+    if( a != it->second.end( ) )
+      return( dynamic_cast< TLUTActor* >( a->GetPointer( ) ) != NULL );
+    else
+      return( false );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::RendererWidget::
+Is3DActor( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto a = it->second.begin( );
+    if( a != it->second.end( ) )
+      return( dynamic_cast< vtkActor* >( a->GetPointer( ) ) != NULL );
+    else
+      return( false );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+GetScalarRange( const std::string& name, double r[ 2 ] ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    TWLActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      a->GetRange( r );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+GetWindowLevel( const std::string& name, double wl[ 2 ] ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    TWLActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      a->GetWindowLevel( wl );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::RendererWidget::
+GetWindow( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    TWLActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetWindow( ) );
+    else
+      return( 0 );
+  }
+  else
+    return( 0 );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::RendererWidget::
+GetLevel( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    TWLActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetLevel( ) );
+    else
+      return( 0 );
+  }
+  else
+    return( 0 );
+}
+
+// -------------------------------------------------------------------------
+char cpExtensions::QT::RendererWidget::
+GetImageInterpolation( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    TWLActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+    {
+      int int_type = a->GetProperty( )->GetInterpolationType( );
+      char ret = 0;
+      switch( int_type )
+      {
+      case VTK_NEAREST_INTERPOLATION: ret = 'N'; break;
+      case VTK_LINEAR_INTERPOLATION: ret = 'L'; break;
+      case VTK_CUBIC_INTERPOLATION: ret = 'C'; break;
+      default: ret = 0; break;
+      } // hctiws
+      return( ret );
+    }
+    else
+      return( 0 );
+  }
+  else
+    return( 0 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+GetColor( const std::string& name, double& r, double& g, double& b ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    vtkActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetProperty( )->GetColor( r, g, b ) );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::RendererWidget::
+GetOpacity( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    vtkActor* a = NULL;
+    vtkImageSlice* s = NULL;
+    while( a == NULL && s == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      s = dynamic_cast< vtkImageSlice* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetProperty( )->GetOpacity( ) );
+    else if( s != NULL )
+      return( s->GetProperty( )->GetOpacity( ) );
+    else
+      return( 0 );
+  }
+  return( 0 );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::RendererWidget::
+GetPointSize( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    vtkActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetProperty( )->GetPointSize( ) );
+    else
+      return( 0 );
+  }
+  return( 0 );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::RendererWidget::
+GetLineWidth( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    vtkActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetProperty( )->GetLineWidth( ) );
+    else
+      return( 0 );
+  }
+  return( 0 );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::QT::RendererWidget::
+GetRepresentation( const std::string& name ) const
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    auto p = it->second.begin( );
+    vtkActor* a = NULL;
+    while( a == NULL && p != it->second.end( ) )
+    {
+      a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      p++;
+
+    } // elihw
+    if( a != NULL )
+      return( a->GetProperty( )->GetRepresentation( ) );
+    else
+      return( -1 );
+  }
+  return( -1 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetScalarRange( const std::string& name, double r[ 2 ] )
+{
+  this->SetScalarRange( name, r[ 0 ], r[ 1 ] );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetScalarRange( const std::string& name, double min, double max )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->SetRange( min, max );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetWindowLevel( const std::string& name, double wl[ 2 ] )
+{
+  this->SetWindowLevel( name, wl[ 0 ], wl[ 1 ] );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetWindowLevel( const std::string& name, double w, double l )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->SetWindowLevel( w, l );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetWindow( const std::string& name, double w )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->SetWindow( w );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetLevel( const std::string& name, double l )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->SetLevel( l );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetImageInterpolation( const std::string& name, char i )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      TWLActor* a = dynamic_cast< TWLActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        int int_type = VTK_NEAREST_INTERPOLATION;
+        switch( i )
+        {
+        case 'L': int_type = VTK_LINEAR_INTERPOLATION; break;
+        case 'C': int_type = VTK_CUBIC_INTERPOLATION; break;
+        default:  int_type = VTK_NEAREST_INTERPOLATION; break;
+        } // hctiws
+        a->GetProperty( )->SetInterpolationType( int_type );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetColor( const std::string& name, double r, double g, double b )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetColor( r, g, b );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetOpacity( const std::string& name, double o )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      vtkImageSlice* s = dynamic_cast< vtkImageSlice* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetOpacity( o );
+      }
+      else if( s != NULL )
+      {
+        render = true;
+        s->GetProperty( )->SetOpacity( o );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetPointSize( const std::string& name, double s )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetPointSize( s );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetLineWidth( const std::string& name, double w )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetLineWidth( w );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetRepresentationToPoints( const std::string& name )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetRepresentationToPoints( );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetRepresentationToSurface( const std::string& name )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetRepresentationToSurface( );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::RendererWidget::
+SetRepresentationToWireframe( const std::string& name )
+{
+  auto it = this->m_ViewProps.find( name );
+  if( it != this->m_ViewProps.end( ) )
+  {
+    bool render = false;
+    for( auto p = it->second.begin( ); p != it->second.end( ); ++p )
+    {
+      vtkActor* a = dynamic_cast< vtkActor* >( p->GetPointer( ) );
+      if( a != NULL )
+      {
+        render = true;
+        a->GetProperty( )->SetRepresentationToWireframe( );
+
+      } // fi
+
+    } // rof
+    if( render )
+      this->Render( );
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/RendererWidget.h b/lib/cpExtensions/QT/RendererWidget.h
new file mode 100644 (file)
index 0000000..2a5b145
--- /dev/null
@@ -0,0 +1,138 @@
+#ifndef __cpExtensions__QT__RendererWidget__h__
+#define __cpExtensions__QT__RendererWidget__h__
+
+#include <cpExtensions/Config.h>
+#include <cpExtensions/QT/ActorsWidgetInterface.h>
+#include <vtkSmartPointer.h>
+#include <map>
+#include <set>
+#include <string>
+
+// -------------------------------------------------------------------------
+class vtkCamera;
+class vtkInteractorStyle;
+class vtkOrientationMarkerWidget;
+class vtkProp;
+class vtkPropCollection;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class LUTImageActor;
+    class WindowLevelImageActor;
+  }
+
+  namespace QT
+  {
+    /**
+     */
+    class cpExtensions_EXPORT RendererWidget
+      : public cpExtensions_QVTKWidget,
+        public ActorsWidgetInterface
+    {
+      Q_OBJECT;
+    public:
+      typedef RendererWidget          Self;
+      typedef cpExtensions_QVTKWidget Superclass;
+      typedef ActorsWidgetInterface   Superclass2;
+
+      typedef std::set< vtkSmartPointer< vtkProp > > TProps;
+      typedef std::map< std::string, TProps >        TPropCollection;
+
+      typedef cpExtensions::Visualization::LUTImageActor         TLUTActor;
+      typedef cpExtensions::Visualization::WindowLevelImageActor TWLActor;
+
+    public:
+      explicit RendererWidget(
+        QWidget* parent = NULL, Qt::WindowFlags f = 0
+        );
+      virtual ~RendererWidget( );
+
+      int GetQuadrant( ) const;
+      void SetQuadrant( int q );
+
+      vtkRenderer* GetRenderer( );
+      const vtkRenderer* GetRenderer( ) const;
+
+      vtkInteractorStyle* GetStyle( );
+      const vtkInteractorStyle* GetStyle( ) const;
+      void SetStyle( vtkInteractorStyle* style );
+
+      vtkCamera* GetActiveCamera( );
+      const vtkCamera* GetActiveCamera( ) const;
+
+      void AddViewProp( vtkProp* prop, const std::string& name = "" );
+      void AddViewProps(
+        vtkPropCollection* props, const std::string& name = ""
+        );
+      void AddAuxViewProp( vtkProp* prop, const std::string& name = "" );
+      void AddAuxViewProps(
+        vtkPropCollection* props, const std::string& name = ""
+        );
+
+      TProps& GetViewProps( const std::string& name );
+      const TProps& GetViewProps( const std::string& name ) const;
+      TProps& GetAuxViewProps( const std::string& name );
+      const TProps& GetAuxViewProps( const std::string& name ) const;
+
+      void RemoveViewProps( const std::string& name );
+      void RemoveViewProps( );
+
+      virtual void HideViewProps( const std::string& name );
+      virtual void ShowViewProps( const std::string& name );
+
+      virtual void ResetCamera( );
+      virtual void Render( );
+
+      virtual std::set< vtkRenderWindowInteractor* > GetInteractors( ) const cpExtensions_OVERRIDE;
+      virtual std::set< std::string > GetActorsNames( ) const cpExtensions_OVERRIDE;
+      virtual bool IsWindowLevelImageActor( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual bool IsLUTImageActor( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual bool Is3DActor( const std::string& name ) const cpExtensions_OVERRIDE;
+
+      virtual void GetScalarRange( const std::string& name, double r[ 2 ] ) const cpExtensions_OVERRIDE;
+      virtual void GetWindowLevel( const std::string& name, double wl[ 2 ] ) const cpExtensions_OVERRIDE;
+      virtual double GetWindow( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual double GetLevel( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual char GetImageInterpolation( const std::string& name ) const cpExtensions_OVERRIDE;
+
+      virtual void GetColor( const std::string& name, double& r, double& g, double& b ) const cpExtensions_OVERRIDE;
+      virtual double GetOpacity( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual double GetPointSize( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual double GetLineWidth( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual int GetRepresentation( const std::string& name ) const cpExtensions_OVERRIDE;
+
+      virtual void SetScalarRange( const std::string& name, double r[ 2 ] ) cpExtensions_OVERRIDE;
+      virtual void SetScalarRange( const std::string& name, double min, double max ) cpExtensions_OVERRIDE;
+      virtual void SetWindowLevel( const std::string& name, double wl[ 2 ] ) cpExtensions_OVERRIDE;
+      virtual void SetWindowLevel( const std::string& name, double w, double l ) cpExtensions_OVERRIDE;
+      virtual void SetWindow( const std::string& name, double w ) cpExtensions_OVERRIDE;
+      virtual void SetLevel( const std::string& name, double l ) cpExtensions_OVERRIDE;
+      virtual void SetImageInterpolation( const std::string& name, char i ) cpExtensions_OVERRIDE;
+
+      virtual void SetColor( const std::string& name, double r, double g, double b ) cpExtensions_OVERRIDE;
+      virtual void SetOpacity( const std::string& name, double o ) cpExtensions_OVERRIDE;
+      virtual void SetPointSize( const std::string& name, double s ) cpExtensions_OVERRIDE;
+      virtual void SetLineWidth( const std::string& name, double w ) cpExtensions_OVERRIDE;
+      virtual void SetRepresentationToPoints( const std::string& name ) cpExtensions_OVERRIDE;
+      virtual void SetRepresentationToSurface( const std::string& name ) cpExtensions_OVERRIDE;
+      virtual void SetRepresentationToWireframe( const std::string& name ) cpExtensions_OVERRIDE;
+
+    protected:
+      vtkSmartPointer< vtkRenderer >                m_Renderer;
+      vtkSmartPointer< vtkOrientationMarkerWidget > m_Marker;
+      int m_Quadrant;
+
+      TPropCollection m_ViewProps;
+      TPropCollection m_AuxViewProps;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__RendererWidget__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.cxx b/lib/cpExtensions/QT/SimpleMPRWidget.cxx
new file mode 100644 (file)
index 0000000..9b47dfd
--- /dev/null
@@ -0,0 +1,635 @@
+#include <cpExtensions/QT/SimpleMPRWidget.h>
+#include <cpExtensions/QT/ui_SimpleMPRWidget.h>
+#include <cpExtensions/QT/ImageWidget.h>
+#include <cpExtensions/QT/MPR3DWidget.h>
+#include <cpExtensions/QT/MPRInteractionCommand.h>
+#include <cpExtensions/QT/ConfigurationChooser.h>
+
+#include <vtkImageData.h>
+#include <vtkPolyData.h>
+#include <vtkProp.h>
+#include <vtkPropCollection.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::SimpleMPRWidget::
+SimpleMPRWidget( QWidget* parent, Qt::WindowFlags f )
+  : Superclass( parent, f ),
+    Superclass2( ),
+    m_UI( new Ui::SimpleMPRWidget ),
+    m_MainImageName( "" )
+{
+  this->m_UI->setupUi( this );
+
+  // Prepare default configuration
+  this->m_UI->Q1->hide( );
+  this->m_UI->Q2->hide( );
+  this->m_UI->Q3->hide( );
+  this->m_UI->Q4->hide( );
+  this->m_UI->Q1->close( );
+  this->m_UI->Q2->close( );
+  this->m_UI->Q3->close( );
+  this->m_UI->Q4->close( );
+  delete this->m_UI->Q1;
+  delete this->m_UI->Q2;
+  delete this->m_UI->Q3;
+  delete this->m_UI->Q4;
+  this->m_XImage = new ImageWidget( this );
+  this->m_YImage = new ImageWidget( this );
+  this->m_ZImage = new ImageWidget( this );
+  this->m_3DView = new MPR3DWidget( this );
+  this->m_UI->Q1 = this->m_XImage;
+  this->m_UI->Q2 = this->m_YImage;
+  this->m_UI->Q3 = this->m_ZImage;
+  this->m_UI->Q4 = this->m_3DView;
+  this->Configure( 'y', 'x', 'w', 'z' );
+
+  // Interaction synchronizer
+  unsigned long ev1 = vtkCommand::UserEvent + 1;
+  unsigned long ev2 = vtkCommand::UserEvent + 2;
+  vtkSmartPointer< cpExtensions::QT::MPRInteractionCommand > cmd =
+    vtkSmartPointer< cpExtensions::QT::MPRInteractionCommand >::New( );
+  cmd->AddWidget( this->m_XImage );
+  cmd->AddWidget( this->m_YImage );
+  cmd->AddWidget( this->m_ZImage );
+  cmd->AddWidget( this->m_3DView );
+  this->m_XImage->GetStyle( )->AddObserver( ev1, cmd );
+  this->m_YImage->GetStyle( )->AddObserver( ev1, cmd );
+  this->m_ZImage->GetStyle( )->AddObserver( ev1, cmd );
+  this->m_XImage->GetStyle( )->AddObserver( ev2, cmd );
+  this->m_YImage->GetStyle( )->AddObserver( ev2, cmd );
+  this->m_ZImage->GetStyle( )->AddObserver( ev2, cmd );
+
+  // Connect slots
+  this->connect(
+    this->m_UI->Top, SIGNAL( splitterMoved( int, int ) ),
+    this, SLOT( _SyncBottom( int, int ) )
+    );
+  this->connect(
+    this->m_UI->Bottom, SIGNAL( splitterMoved( int, int ) ),
+    this, SLOT( _SyncTop( int, int ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::SimpleMPRWidget::
+~SimpleMPRWidget( )
+{
+  delete this->m_UI;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+Configure( char q1, char q2, char q3, char q4 )
+{
+  // Hide all widgets
+  this->m_UI->Q1->hide( );
+  this->m_UI->Q2->hide( );
+  this->m_UI->Q3->hide( );
+  this->m_UI->Q4->hide( );
+  this->m_UI->Q1->close( );
+  this->m_UI->Q2->close( );
+  this->m_UI->Q3->close( );
+  this->m_UI->Q4->close( );
+
+  // Reorder them
+  if     ( q1 == 'x' ) this->m_UI->Top->addWidget( this->m_XImage );
+  else if( q1 == 'y' ) this->m_UI->Top->addWidget( this->m_YImage );
+  else if( q1 == 'z' ) this->m_UI->Top->addWidget( this->m_ZImage );
+  else if( q1 == 'w' ) this->m_UI->Top->addWidget( this->m_3DView );
+  if     ( q2 == 'x' ) this->m_UI->Top->addWidget( this->m_XImage );
+  else if( q2 == 'y' ) this->m_UI->Top->addWidget( this->m_YImage );
+  else if( q2 == 'z' ) this->m_UI->Top->addWidget( this->m_ZImage );
+  else if( q2 == 'w' ) this->m_UI->Top->addWidget( this->m_3DView );
+  this->m_UI->Top->update( );
+  if     ( q4 == 'x' ) this->m_UI->Bottom->addWidget( this->m_XImage );
+  else if( q4 == 'y' ) this->m_UI->Bottom->addWidget( this->m_YImage );
+  else if( q4 == 'z' ) this->m_UI->Bottom->addWidget( this->m_ZImage );
+  else if( q4 == 'w' ) this->m_UI->Bottom->addWidget( this->m_3DView );
+  if     ( q3 == 'x' ) this->m_UI->Bottom->addWidget( this->m_XImage );
+  else if( q3 == 'y' ) this->m_UI->Bottom->addWidget( this->m_YImage );
+  else if( q3 == 'z' ) this->m_UI->Bottom->addWidget( this->m_ZImage );
+  else if( q3 == 'w' ) this->m_UI->Bottom->addWidget( this->m_3DView );
+  this->m_UI->Bottom->update( );
+
+  // Keep track
+  if     ( q1 == 'x' ) this->m_UI->Q1 = this->m_XImage;
+  else if( q1 == 'y' ) this->m_UI->Q1 = this->m_YImage;
+  else if( q1 == 'z' ) this->m_UI->Q1 = this->m_ZImage;
+  else if( q1 == 'w' ) this->m_UI->Q1 = this->m_3DView;
+  if     ( q2 == 'x' ) this->m_UI->Q2 = this->m_XImage;
+  else if( q2 == 'y' ) this->m_UI->Q2 = this->m_YImage;
+  else if( q2 == 'z' ) this->m_UI->Q2 = this->m_ZImage;
+  else if( q2 == 'w' ) this->m_UI->Q2 = this->m_3DView;
+  if     ( q3 == 'x' ) this->m_UI->Q3 = this->m_XImage;
+  else if( q3 == 'y' ) this->m_UI->Q3 = this->m_YImage;
+  else if( q3 == 'z' ) this->m_UI->Q3 = this->m_ZImage;
+  else if( q3 == 'w' ) this->m_UI->Q3 = this->m_3DView;
+  if     ( q4 == 'x' ) this->m_UI->Q4 = this->m_XImage;
+  else if( q4 == 'y' ) this->m_UI->Q4 = this->m_YImage;
+  else if( q4 == 'z' ) this->m_UI->Q4 = this->m_ZImage;
+  else if( q4 == 'w' ) this->m_UI->Q4 = this->m_3DView;
+
+  // Draw all
+  this->m_UI->Q1->show( );
+  this->m_UI->Q2->show( );
+  this->m_UI->Q3->show( );
+  this->m_UI->Q4->show( );
+  dynamic_cast< RendererWidget* >( this->m_UI->Q1 )->SetQuadrant( 1 );
+  dynamic_cast< RendererWidget* >( this->m_UI->Q2 )->SetQuadrant( 2 );
+  dynamic_cast< RendererWidget* >( this->m_UI->Q3 )->SetQuadrant( 3 );
+  dynamic_cast< RendererWidget* >( this->m_UI->Q4 )->SetQuadrant( 4 );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::SimpleMPRWidget::
+HasImage( ) const
+{
+  return( this->m_MainImage.GetPointer( ) != NULL );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetImage( vtkImageData* image, const std::string& name )
+{
+  if( this->m_MainImageName != "" || image == NULL )
+  {
+    // TODO: Clear visualization
+
+  } // fi
+  this->m_MainImageName = name;
+  this->m_MainImage = image;
+
+  if( this->m_MainImage != NULL && this->m_MainImageName != "" )
+  {
+    this->m_XImage->SetImage( this->m_MainImage, name, 0 );
+    this->m_YImage->SetImage( this->m_MainImage, name, 1 );
+    this->m_ZImage->SetImage( this->m_MainImage, name, 2 );
+    this->m_3DView->SetImage( this->m_MainImage, name );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::SimpleMPRWidget::
+Add( vtkDataSet* data, const std::string& name )
+{
+  bool success = true;
+  auto image = dynamic_cast< vtkImageData* >( data );
+  auto pdata = dynamic_cast< vtkPolyData* >( data );
+
+  if( image != NULL )
+  {
+    if( this->m_MainImageName != "" )
+    {
+      this->m_XImage->Add( image, name );
+      this->m_YImage->Add( image, name );
+      this->m_ZImage->Add( image, name );
+      // TODO: this->m_3DView->Add( image, name );
+    }
+    else
+      this->SetImage( image, name );
+  }
+  else if( pdata != NULL )
+    this->m_3DView->Add( pdata, name );
+  else
+    success = false;
+  return( success );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::SimpleMPRWidget::
+TProps cpExtensions::QT::SimpleMPRWidget::
+GetViewProps( const std::string& name ) const
+{
+/*
+  auto x = this->m_XImage->GetViewProps( name );
+  auto y = this->m_YImage->GetViewProps( name );
+  auto z = this->m_ZImage->GetViewProps( name );
+  auto w = this->m_3DView->GetViewProps( name );
+
+  TProps props;
+  if( x != NULL ) props.insert( x );
+  if( y != NULL ) props.insert( y );
+  if( z != NULL ) props.insert( z );
+  if( w != NULL ) props.insert( w );
+  return( props );
+*/
+  TProps props;
+  return( props );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::SimpleMPRWidget::
+TProps cpExtensions::QT::SimpleMPRWidget::
+GetImageProps( ) const
+{
+  return( this->GetViewProps( this->m_MainImageName ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetXInteractor( )
+{
+  return( this->m_XImage->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetXInteractor( ) const
+{
+  return( this->m_XImage->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetYInteractor( )
+{
+  return( this->m_YImage->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetYInteractor( ) const
+{
+  return( this->m_YImage->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetZInteractor( )
+{
+  return( this->m_ZImage->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetZInteractor( ) const
+{
+  return( this->m_ZImage->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetWInteractor( )
+{
+  return( this->m_3DView->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget::
+GetWInteractor( ) const
+{
+  return( this->m_3DView->GetInteractor( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetXRenderWindow( )
+{
+  return( this->m_XImage->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetXRenderWindow( ) const
+{
+  return( this->m_XImage->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetYRenderWindow( )
+{
+  return( this->m_YImage->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetYRenderWindow( ) const
+{
+  return( this->m_YImage->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetZRenderWindow( )
+{
+  return( this->m_ZImage->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetZRenderWindow( ) const
+{
+  return( this->m_ZImage->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetWRenderWindow( )
+{
+  return( this->m_3DView->GetRenderWindow( ) );
+}
+
+
+// -------------------------------------------------------------------------
+const vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget::
+GetWRenderWindow( ) const
+{
+  return( this->m_3DView->GetRenderWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+ResetCameras( )
+{
+  this->m_XImage->ResetCamera( );
+  this->m_YImage->ResetCamera( );
+  this->m_ZImage->ResetCamera( );
+  this->m_3DView->ResetCamera( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+Render( )
+{
+  this->m_XImage->Render( );
+  this->m_YImage->Render( );
+  this->m_ZImage->Render( );
+  this->m_3DView->Render( );
+}
+
+// -------------------------------------------------------------------------
+std::set< vtkRenderWindowInteractor* > cpExtensions::QT::SimpleMPRWidget::
+GetInteractors( ) const
+{
+  std::set< vtkRenderWindowInteractor* > ret;
+  ret.insert( this->m_XImage->GetInteractor( ) );
+  ret.insert( this->m_YImage->GetInteractor( ) );
+  ret.insert( this->m_ZImage->GetInteractor( ) );
+  ret.insert( this->m_3DView->GetInteractor( ) );
+  return( ret );
+}
+
+// -------------------------------------------------------------------------
+std::set< std::string > cpExtensions::QT::SimpleMPRWidget::
+GetActorsNames( ) const
+{
+  std::set< std::string > names = this->m_XImage->GetActorsNames( );
+  std::set< std::string > y = this->m_YImage->GetActorsNames( );
+  std::set< std::string > z = this->m_ZImage->GetActorsNames( );
+  std::set< std::string > w = this->m_3DView->GetActorsNames( );
+  names.insert( y.begin( ), y.end( ) );
+  names.insert( z.begin( ), z.end( ) );
+  names.insert( w.begin( ), w.end( ) );
+  return( names );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::SimpleMPRWidget::
+IsWindowLevelImageActor( const std::string& name ) const
+{
+  return( this->m_XImage->IsWindowLevelImageActor( name ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::SimpleMPRWidget::
+IsLUTImageActor( const std::string& name ) const
+{
+  return( this->m_XImage->IsLUTImageActor( name ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpExtensions::QT::SimpleMPRWidget::
+Is3DActor( const std::string& name ) const
+{
+  return(
+    this->m_XImage->Is3DActor( name ) || this->m_3DView->Is3DActor( name )
+    );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+GetScalarRange( const std::string& name, double r[ 2 ] ) const
+{
+  this->m_XImage->GetScalarRange( name, r );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+GetWindowLevel( const std::string& name, double wl[ 2 ] ) const
+{
+  this->m_XImage->GetWindowLevel( name, wl );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::SimpleMPRWidget::
+GetWindow( const std::string& name ) const
+{
+  return( this->m_XImage->GetWindow( name ) );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::SimpleMPRWidget::
+GetLevel( const std::string& name ) const
+{
+  return( this->m_XImage->GetLevel( name ) );
+}
+
+// -------------------------------------------------------------------------
+char cpExtensions::QT::SimpleMPRWidget::
+GetImageInterpolation( const std::string& name ) const
+{
+  return( this->m_XImage->GetImageInterpolation( name ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+GetColor( const std::string& name, double& r, double& g, double& b ) const
+{
+  this->m_XImage->GetColor( name, r, g, b );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::SimpleMPRWidget::
+GetOpacity( const std::string& name ) const
+{
+  return( this->m_XImage->GetOpacity( name ) );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::SimpleMPRWidget::
+GetPointSize( const std::string& name ) const
+{
+  return( this->m_XImage->GetPointSize( name ) );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::QT::SimpleMPRWidget::
+GetLineWidth( const std::string& name ) const
+{
+  return( this->m_XImage->GetLineWidth( name ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::QT::SimpleMPRWidget::
+GetRepresentation( const std::string& name ) const
+{
+  return( this->m_XImage->GetRepresentation( name ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetScalarRange( const std::string& name, double r[ 2 ] )
+{
+  this->m_XImage->SetScalarRange( name, r );
+  this->m_YImage->SetScalarRange( name, r );
+  this->m_ZImage->SetScalarRange( name, r );
+  this->m_3DView->SetScalarRange( name, r );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetScalarRange( const std::string& name, double min, double max )
+{
+  this->m_XImage->SetScalarRange( name, min, max );
+  this->m_YImage->SetScalarRange( name, min, max );
+  this->m_ZImage->SetScalarRange( name, min, max );
+  this->m_3DView->SetScalarRange( name, min, max );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetWindowLevel( const std::string& name, double wl[ 2 ] )
+{
+  this->m_XImage->SetWindowLevel( name, wl );
+  this->m_YImage->SetWindowLevel( name, wl );
+  this->m_ZImage->SetWindowLevel( name, wl );
+  this->m_3DView->SetWindowLevel( name, wl );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetWindowLevel( const std::string& name, double w, double l )
+{
+  this->m_XImage->SetWindowLevel( name, w, l );
+  this->m_YImage->SetWindowLevel( name, w, l );
+  this->m_ZImage->SetWindowLevel( name, w, l );
+  this->m_3DView->SetWindowLevel( name, w, l );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetWindow( const std::string& name, double w )
+{
+  this->m_XImage->SetWindow( name, w );
+  this->m_YImage->SetWindow( name, w );
+  this->m_ZImage->SetWindow( name, w );
+  this->m_3DView->SetWindow( name, w );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetLevel( const std::string& name, double l )
+{
+  this->m_XImage->SetLevel( name, l );
+  this->m_YImage->SetLevel( name, l );
+  this->m_ZImage->SetLevel( name, l );
+  this->m_3DView->SetLevel( name, l );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetImageInterpolation( const std::string& name, char i )
+{
+  this->m_XImage->SetImageInterpolation( name, i );
+  this->m_YImage->SetImageInterpolation( name, i );
+  this->m_ZImage->SetImageInterpolation( name, i );
+  this->m_3DView->SetImageInterpolation( name, i );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetColor( const std::string& name, double r, double g, double b )
+{
+  this->m_XImage->SetColor( name, r, g, b );
+  this->m_YImage->SetColor( name, r, g, b );
+  this->m_ZImage->SetColor( name, r, g, b );
+  this->m_3DView->SetColor( name, r, g, b );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetOpacity( const std::string& name, double o )
+{
+  this->m_XImage->SetOpacity( name, o );
+  this->m_YImage->SetOpacity( name, o );
+  this->m_ZImage->SetOpacity( name, o );
+  this->m_3DView->SetOpacity( name, o );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetPointSize( const std::string& name, double s )
+{
+  this->m_XImage->SetPointSize( name, s );
+  this->m_YImage->SetPointSize( name, s );
+  this->m_ZImage->SetPointSize( name, s );
+  this->m_3DView->SetPointSize( name, s );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetLineWidth( const std::string& name, double w )
+{
+  this->m_XImage->SetLineWidth( name, w );
+  this->m_YImage->SetLineWidth( name, w );
+  this->m_ZImage->SetLineWidth( name, w );
+  this->m_3DView->SetLineWidth( name, w );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetRepresentationToPoints( const std::string& name )
+{
+  this->m_XImage->SetRepresentationToPoints( name );
+  this->m_YImage->SetRepresentationToPoints( name );
+  this->m_ZImage->SetRepresentationToPoints( name );
+  this->m_3DView->SetRepresentationToPoints( name );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetRepresentationToSurface( const std::string& name )
+{
+  this->m_XImage->SetRepresentationToSurface( name );
+  this->m_YImage->SetRepresentationToSurface( name );
+  this->m_ZImage->SetRepresentationToSurface( name );
+  this->m_3DView->SetRepresentationToSurface( name );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+SetRepresentationToWireframe( const std::string& name )
+{
+  this->m_XImage->SetRepresentationToWireframe( name );
+  this->m_YImage->SetRepresentationToWireframe( name );
+  this->m_ZImage->SetRepresentationToWireframe( name );
+  this->m_3DView->SetRepresentationToWireframe( name );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+_SyncBottom( int a, int b )
+{
+  this->m_UI->Bottom->setSizes( this->m_UI->Top->sizes( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::SimpleMPRWidget::
+_SyncTop( int a, int b )
+{
+  this->m_UI->Top->setSizes( this->m_UI->Bottom->sizes( ) );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.h b/lib/cpExtensions/QT/SimpleMPRWidget.h
new file mode 100644 (file)
index 0000000..bc07ed3
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef __cpExtensions__QT__SimpleMPRWidget__h__
+#define __cpExtensions__QT__SimpleMPRWidget__h__
+
+#include <cpExtensions/Config.h>
+#include <cpExtensions/QT/ActorsWidgetInterface.h>
+#include <QWidget>
+#include <vtkSmartPointer.h>
+#include <map>
+#include <set>
+
+// -------------------------------------------------------------------------
+class vtkDataSet;
+class vtkProp;
+class vtkPropCollection;
+
+namespace Ui { class SimpleMPRWidget; }
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace QT
+  {
+    class MPR3DWidget;
+    class ImageWidget;
+
+    /**
+     */
+    class cpExtensions_EXPORT SimpleMPRWidget
+      : public QWidget,
+        public ActorsWidgetInterface
+    {
+      Q_OBJECT;
+
+    public:
+      typedef SimpleMPRWidget       Self;
+      typedef QWidget               Superclass;
+      typedef ActorsWidgetInterface Superclass2;
+
+      typedef vtkSmartPointer< vtkPropCollection > TProp;
+      typedef std::set< TProp >                    TProps;
+
+      // typedef cpExtensions::Visualization::MeshActor TMeshActor;
+
+    public:
+      explicit SimpleMPRWidget( QWidget* parent = NULL, Qt::WindowFlags f = 0 );
+      virtual ~SimpleMPRWidget( );
+
+      void Configure( char q1, char q2, char q3, char q4 );
+
+      bool HasImage( ) const;
+      void SetImage( vtkImageData* image, const std::string& name );
+
+      bool Add( vtkDataSet* data, const std::string& name );
+
+      TProps GetViewProps( const std::string& name ) const;
+      TProps GetImageProps( ) const;
+
+      vtkRenderWindowInteractor* GetXInteractor( );
+      const vtkRenderWindowInteractor* GetXInteractor( ) const;
+      vtkRenderWindowInteractor* GetYInteractor( );
+      const vtkRenderWindowInteractor* GetYInteractor( ) const;
+      vtkRenderWindowInteractor* GetZInteractor( );
+      const vtkRenderWindowInteractor* GetZInteractor( ) const;
+      vtkRenderWindowInteractor* GetWInteractor( );
+      const vtkRenderWindowInteractor* GetWInteractor( ) const;
+
+      vtkRenderWindow* GetXRenderWindow( );
+      const vtkRenderWindow* GetXRenderWindow( ) const;
+      vtkRenderWindow* GetYRenderWindow( );
+      const vtkRenderWindow* GetYRenderWindow( ) const;
+      vtkRenderWindow* GetZRenderWindow( );
+      const vtkRenderWindow* GetZRenderWindow( ) const;
+      vtkRenderWindow* GetWRenderWindow( );
+      const vtkRenderWindow* GetWRenderWindow( ) const;
+
+      void ResetCameras( );
+      void Render( );
+
+      virtual std::set< vtkRenderWindowInteractor* > GetInteractors( ) const cpExtensions_OVERRIDE;
+      virtual std::set< std::string > GetActorsNames( ) const cpExtensions_OVERRIDE;
+      virtual bool IsWindowLevelImageActor( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual bool IsLUTImageActor( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual bool Is3DActor( const std::string& name ) const cpExtensions_OVERRIDE;
+
+      virtual void GetScalarRange( const std::string& name, double r[ 2 ] ) const cpExtensions_OVERRIDE;
+      virtual void GetWindowLevel( const std::string& name, double wl[ 2 ] ) const cpExtensions_OVERRIDE;
+      virtual double GetWindow( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual double GetLevel( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual char GetImageInterpolation( const std::string& name ) const cpExtensions_OVERRIDE;
+
+      virtual void GetColor( const std::string& name, double& r, double& g, double& b ) const cpExtensions_OVERRIDE;
+      virtual double GetOpacity( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual double GetPointSize( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual double GetLineWidth( const std::string& name ) const cpExtensions_OVERRIDE;
+      virtual int GetRepresentation( const std::string& name ) const cpExtensions_OVERRIDE;
+
+      virtual void SetScalarRange( const std::string& name, double r[ 2 ] ) cpExtensions_OVERRIDE;
+      virtual void SetScalarRange( const std::string& name, double min, double max ) cpExtensions_OVERRIDE;
+      virtual void SetWindowLevel( const std::string& name, double wl[ 2 ] ) cpExtensions_OVERRIDE;
+      virtual void SetWindowLevel( const std::string& name, double w, double l ) cpExtensions_OVERRIDE;
+      virtual void SetWindow( const std::string& name, double w ) cpExtensions_OVERRIDE;
+      virtual void SetLevel( const std::string& name, double l ) cpExtensions_OVERRIDE;
+      virtual void SetImageInterpolation( const std::string& name, char i ) cpExtensions_OVERRIDE;
+
+      virtual void SetColor( const std::string& name, double r, double g, double b ) cpExtensions_OVERRIDE;
+      virtual void SetOpacity( const std::string& name, double o ) cpExtensions_OVERRIDE;
+      virtual void SetPointSize( const std::string& name, double s ) cpExtensions_OVERRIDE;
+      virtual void SetLineWidth( const std::string& name, double w ) cpExtensions_OVERRIDE;
+      virtual void SetRepresentationToPoints( const std::string& name ) cpExtensions_OVERRIDE;
+      virtual void SetRepresentationToSurface( const std::string& name ) cpExtensions_OVERRIDE;
+      virtual void SetRepresentationToWireframe( const std::string& name ) cpExtensions_OVERRIDE;
+
+    private slots:
+      void _SyncBottom( int a, int b );
+      void _SyncTop( int a, int b );
+
+    protected:
+      Ui::SimpleMPRWidget* m_UI;
+
+      ImageWidget* m_XImage;
+      ImageWidget* m_YImage;
+      ImageWidget* m_ZImage;
+      MPR3DWidget* m_3DView;
+
+      std::string m_MainImageName;
+      vtkSmartPointer< vtkImageData > m_MainImage;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__SimpleMPRWidget__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.ui b/lib/cpExtensions/QT/SimpleMPRWidget.ui
new file mode 100644 (file)
index 0000000..3f0750e
--- /dev/null
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SimpleMPRWidget</class>
+ <widget class="QWidget" name="SimpleMPRWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>495</width>
+    <height>394</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QSplitter" name="Quad">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <widget class="QSplitter" name="Top">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QWidget" name="Q1" native="true"/>
+      <widget class="QWidget" name="Q2" native="true"/>
+     </widget>
+     <widget class="QSplitter" name="Bottom">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="QWidget" name="Q4" native="true"/>
+      <widget class="QWidget" name="Q3" native="true"/>
+     </widget>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/lib/cpExtensions/QT/WindowLevelImageConfiguration.cxx b/lib/cpExtensions/QT/WindowLevelImageConfiguration.cxx
new file mode 100644 (file)
index 0000000..b2baa94
--- /dev/null
@@ -0,0 +1,231 @@
+#include <cpExtensions/QT/WindowLevelImageConfiguration.h>
+#include <cpExtensions/QT/ui_WindowLevelImageConfiguration.h>
+#include <cpExtensions/QT/SimpleMPRWidget.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::WindowLevelImageConfiguration::
+WindowLevelImageConfiguration( QWidget* parent, Qt::WindowFlags f )
+  : Superclass( parent, f ),
+    m_UI( new Ui::WindowLevelImageConfiguration ),
+    m_Data( NULL ),
+    m_Name( "" )
+{
+  this->m_UI->setupUi( this );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::QT::WindowLevelImageConfiguration::
+~WindowLevelImageConfiguration( )
+{
+  delete this->m_UI;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+setData( ActorsWidgetInterface* data, const std::string& name )
+{
+  if( this->m_Data != data )
+  {
+    this->m_Data = data;
+    this->m_Name = name;
+
+    // Get data
+    double range[ 2 ], win_lev[ 2 ];
+    this->m_Data->GetScalarRange( this->m_Name, range );
+    this->m_Data->GetWindowLevel( this->m_Name, win_lev );
+
+    // Intensity range
+    this->m_UI->MinimumBox->setMinimum( -1000000 );
+    this->m_UI->MinimumBox->setMaximum(  1000000 );
+    this->m_UI->MaximumBox->setMinimum( -1000000 );
+    this->m_UI->MaximumBox->setMaximum(  1000000 );
+    this->m_UI->MinimumBox->setValue( range[ 0 ] );
+    this->m_UI->MaximumBox->setValue( range[ 1 ] );
+
+    // Window/level
+    double off = range[ 1 ] - range[ 0 ];
+    this->m_UI->WindowBox->setMinimum( 0 );
+    this->m_UI->WindowBox->setMaximum( off );
+    this->m_UI->LevelBox->setMinimum( range[ 0 ] );
+    this->m_UI->LevelBox->setMaximum( range[ 1 ] );
+    this->m_UI->WindowBox->setValue( win_lev[ 0 ] );
+    this->m_UI->LevelBox->setValue( win_lev[ 1 ] );
+
+    double w = win_lev[ 0 ] / off;
+    w *=
+      double( this->m_UI->WindowSlider->maximum( ) ) -
+      double( this->m_UI->WindowSlider->minimum( ) );
+    w += double( this->m_UI->WindowSlider->minimum( ) );
+    this->m_UI->WindowSlider->setValue( w );
+
+    double l = ( win_lev[ 1 ] - range[ 0 ] ) / off;
+    l *=
+      double( this->m_UI->LevelSlider->maximum( ) ) -
+      double( this->m_UI->LevelSlider->minimum( ) );
+    l += double( this->m_UI->LevelSlider->minimum( ) );
+    this->m_UI->LevelSlider->setValue( l );
+
+    // Opacity
+    double o = this->m_Data->GetOpacity( this->m_Name );
+    o *=
+      double( this->m_UI->OpacitySlider->maximum( ) ) -
+      double( this->m_UI->OpacitySlider->minimum( ) );
+    o += double( this->m_UI->OpacitySlider->minimum( ) );
+    this->m_UI->OpacitySlider->setValue( o );
+
+    // Interpolation mode
+    switch( this->m_Data->GetImageInterpolation( this->m_Name ) )
+    {
+    case 'L': this->m_UI->InterpolatorBox->setCurrentIndex( 1 ); break;
+    case 'C': this->m_UI->InterpolatorBox->setCurrentIndex( 2 ); break;
+    default : this->m_UI->InterpolatorBox->setCurrentIndex( 0 ); break;
+    } // hctiws
+
+    // Slots <-> signals
+    this->connect(
+      this->m_UI->MaximumBox, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _maximumValue( int ) )
+      );
+    this->connect(
+      this->m_UI->MinimumBox, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _minimumValue( int ) )
+      );
+    this->connect(
+      this->m_UI->LevelBox, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _levelValue( int ) )
+      );
+    this->connect(
+      this->m_UI->LevelSlider, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _levelValue( int ) )
+      );
+    this->connect(
+      this->m_UI->WindowBox, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _windowValue( int ) )
+      );
+    this->connect(
+      this->m_UI->WindowSlider, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _windowValue( int ) )
+      );
+    this->connect(
+      this->m_UI->OpacitySlider, SIGNAL( valueChanged( int ) ),
+      this, SLOT( _opacityValue( int ) )
+      );
+    this->connect(
+      this->m_UI->InterpolatorBox, SIGNAL( currentIndexChanged( int ) ),
+      this, SLOT( _interpolatorValue( int ) )
+      );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+_maximumValue( int v )
+{
+  double range[ 2 ];
+  range[ 0 ] = double( this->m_UI->MinimumBox->value( ) );
+  range[ 1 ] = double( v );
+  this->m_Data->SetScalarRange( this->m_Name, range );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+_minimumValue( int v )
+{
+  double range[ 2 ];
+  range[ 0 ] = double( v );
+  range[ 1 ] = double( this->m_UI->MaximumBox->value( ) );
+  this->m_Data->SetScalarRange( this->m_Name, range );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+_levelValue( int v )
+{
+  double r[ 2 ];
+  double l, s;
+
+  this->m_Data->GetScalarRange( this->m_Name, r );
+  if( this->sender( ) == this->m_UI->LevelSlider )
+  {
+    s = double( v ) / double( this->m_UI->LevelSlider->maximum( ) );
+    l = ( ( r[ 1 ] - r[ 0 ] ) * s ) + r[ 0 ];
+  }
+  else
+  {
+    l = double( v );
+    s = ( l - r[ 0 ] ) / ( r[ 1 ] - r[ 0 ] );
+
+  } // fi
+  s *= this->m_UI->LevelSlider->maximum( );
+
+  bool b = this->m_UI->LevelSlider->blockSignals( true );
+  this->m_UI->LevelSlider->setValue( s );
+  this->m_UI->LevelSlider->blockSignals( b );
+  b = this->m_UI->LevelBox->blockSignals( true );
+  this->m_UI->LevelBox->setValue( l );
+  this->m_UI->LevelBox->blockSignals( b );
+
+  this->m_Data->SetLevel( this->m_Name, l );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+_windowValue( int v )
+{
+  double r[ 2 ];
+  double w, s;
+
+  this->m_Data->GetScalarRange( this->m_Name, r );
+  if( this->sender( ) == this->m_UI->WindowSlider )
+  {
+    s = double( v ) / double( this->m_UI->WindowSlider->maximum( ) );
+    w = ( ( r[ 1 ] - r[ 0 ] ) * s ) + r[ 0 ];
+  }
+  else
+  {
+    w = double( v );
+    s = ( w - r[ 0 ] ) / ( r[ 1 ] - r[ 0 ] );
+
+  } // fi
+  s *= this->m_UI->WindowSlider->maximum( );
+
+  bool b = this->m_UI->WindowSlider->blockSignals( true );
+  this->m_UI->WindowSlider->setValue( s );
+  this->m_UI->WindowSlider->blockSignals( b );
+  b = this->m_UI->WindowBox->blockSignals( true );
+  this->m_UI->WindowBox->setValue( w );
+  this->m_UI->WindowBox->blockSignals( b );
+
+  this->m_Data->SetWindow( this->m_Name, w );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+_opacityValue( int v )
+{
+  if( this->m_Data != NULL )
+  {
+    double o = double( v );
+    o -= double( this->m_UI->OpacitySlider->minimum( ) );
+    o /=
+      double( this->m_UI->OpacitySlider->maximum( ) ) -
+      double( this->m_UI->OpacitySlider->minimum( ) );
+    this->m_Data->SetOpacity( this->m_Name, o );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::QT::WindowLevelImageConfiguration::
+_interpolatorValue( int v )
+{
+  switch( v )
+  {
+  case 1  : this->m_Data->SetImageInterpolation( this->m_Name, 'L' ); break;
+  case 2  : this->m_Data->SetImageInterpolation( this->m_Name, 'C' ); break;
+  default : this->m_Data->SetImageInterpolation( this->m_Name, 'N' ); break;
+  } // hctiws
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/WindowLevelImageConfiguration.h b/lib/cpExtensions/QT/WindowLevelImageConfiguration.h
new file mode 100644 (file)
index 0000000..1725253
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __cpExtensions__QT__WindowLevelImageConfiguration__h__
+#define __cpExtensions__QT__WindowLevelImageConfiguration__h__
+
+#include <cpExtensions/Config.h>
+#include <QWidget>
+
+// -------------------------------------------------------------------------
+namespace Ui { class WindowLevelImageConfiguration; }
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace QT
+  {
+    class ActorsWidgetInterface;
+
+    /**
+     */
+    class cpExtensions_EXPORT WindowLevelImageConfiguration
+      : public QWidget
+    {
+      Q_OBJECT;
+
+    public:
+      typedef WindowLevelImageConfiguration Self;
+      typedef QWidget                       Superclass;
+
+    public:
+      explicit WindowLevelImageConfiguration(
+        QWidget* parent = NULL, Qt::WindowFlags f = 0
+        );
+      virtual ~WindowLevelImageConfiguration( );
+
+      void setData( ActorsWidgetInterface* data, const std::string& name );
+
+    protected slots:
+      void _maximumValue( int v );
+      void _minimumValue( int v );
+      void _levelValue( int v );
+      void _windowValue( int v );
+      void _opacityValue( int v );
+      void _interpolatorValue( int v );
+
+    protected:
+      Ui::WindowLevelImageConfiguration* m_UI;
+      ActorsWidgetInterface* m_Data;
+      std::string m_Name;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__QT__WindowLevelImageConfiguration__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/QT/WindowLevelImageConfiguration.ui b/lib/cpExtensions/QT/WindowLevelImageConfiguration.ui
new file mode 100644 (file)
index 0000000..65d066e
--- /dev/null
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WindowLevelImageConfiguration</class>
+ <widget class="QWidget" name="WindowLevelImageConfiguration">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>313</width>
+    <height>322</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>313</width>
+    <height>322</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_6">
+   <item>
+    <widget class="QFrame" name="frame">
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_5">
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout">
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout">
+          <item>
+           <widget class="QLabel" name="label">
+            <property name="text">
+             <string>Window:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSpinBox" name="WindowBox"/>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QSlider" name="WindowSlider">
+          <property name="maximum">
+           <number>1000</number>
+          </property>
+          <property name="pageStep">
+           <number>100</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QVBoxLayout" name="verticalLayout_4">
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <item>
+           <widget class="QLabel" name="label_2">
+            <property name="text">
+             <string>Level:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSpinBox" name="LevelBox"/>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <widget class="QSlider" name="LevelSlider">
+          <property name="maximum">
+           <number>1000</number>
+          </property>
+          <property name="pageStep">
+           <number>100</number>
+          </property>
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <item>
+         <widget class="QLabel" name="label_3">
+          <property name="text">
+           <string>Minimum:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="MinimumBox"/>
+        </item>
+        <item>
+         <widget class="QLabel" name="label_4">
+          <property name="text">
+           <string>Maximum:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QSpinBox" name="MaximumBox"/>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QFrame" name="frame_2">
+     <property name="frameShape">
+      <enum>QFrame::StyledPanel</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QGridLayout" name="gridLayout_2">
+      <item row="0" column="0">
+       <layout class="QVBoxLayout" name="verticalLayout_3">
+        <property name="spacing">
+         <number>0</number>
+        </property>
+        <item>
+         <layout class="QHBoxLayout" name="horizontalLayout_4">
+          <item>
+           <widget class="QLabel" name="label_6">
+            <property name="maximumSize">
+             <size>
+              <width>16777215</width>
+              <height>16777215</height>
+             </size>
+            </property>
+            <property name="text">
+             <string>Interpolation:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QComboBox" name="InterpolatorBox">
+            <item>
+             <property name="text">
+              <string>Nearest</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Linear</string>
+             </property>
+            </item>
+            <item>
+             <property name="text">
+              <string>Cubic</string>
+             </property>
+            </item>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item>
+         <layout class="QVBoxLayout" name="verticalLayout_2">
+          <item>
+           <widget class="QLabel" name="label_5">
+            <property name="text">
+             <string>Opacity:</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSlider" name="OpacitySlider">
+            <property name="maximum">
+             <number>100</number>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+  <zorder>label</zorder>
+  <zorder>label_2</zorder>
+  <zorder>label_3</zorder>
+  <zorder>label_4</zorder>
+  <zorder>label_5</zorder>
+  <zorder>label_6</zorder>
+  <zorder>InterpolatorBox</zorder>
+  <zorder>WindowSlider</zorder>
+  <zorder>LevelSlider</zorder>
+  <zorder>OpacitySlider</zorder>
+  <zorder>MinimumBox</zorder>
+  <zorder>MaximumBox</zorder>
+  <zorder>WindowSlider</zorder>
+  <zorder>frame</zorder>
+  <zorder>frame_2</zorder>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/lib/cpExtensions/Visualization/CursorActors.cxx b/lib/cpExtensions/Visualization/CursorActors.cxx
new file mode 100644 (file)
index 0000000..29dedc3
--- /dev/null
@@ -0,0 +1,176 @@
+#include <cpExtensions/Visualization/CursorActors.h>
+#include <cpExtensions/Visualization/LineSource.h>
+
+#include <vtkActor.h>
+#include <vtkPolyDataMapper.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::CursorActors::
+Self* cpExtensions::Visualization::CursorActors::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+Modified( )
+{
+  for( unsigned int i = 0; i < 2; ++i )
+  {
+    if( this->m_Lines[ i ].GetPointer( ) != NULL )
+    {
+      this->m_Lines[ i ]->Modified( );
+      this->m_Mappers[ i ]->Modified( );
+      this->m_Actors[ i ]->Modified( );
+
+    } // fi
+
+  } // rof
+  this->Superclass::Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+SetImageBounds( double* bounds )
+{
+  this->m_Bounds[ 0 ] = bounds[ 0 ];
+  this->m_Bounds[ 1 ] = bounds[ 1 ];
+  this->m_Bounds[ 2 ] = bounds[ 2 ];
+  this->m_Bounds[ 3 ] = bounds[ 3 ];
+  this->m_Bounds[ 4 ] = bounds[ 4 ];
+  this->m_Bounds[ 5 ] = bounds[ 5 ];
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+SetImageOrientation( int orientation )
+{
+  this->m_Orientation = orientation % 3;
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+SetCursor( double* pos, bool neg )
+{
+  static const double _eps = 1e-3;
+  double pnts[ 4 ][ 3 ];
+  if( this->m_Orientation == 0 )
+  {
+    pnts[ 0 ][ 1 ] = this->m_Bounds[ 2 ];
+    pnts[ 1 ][ 1 ] = this->m_Bounds[ 3 ];
+    pnts[ 0 ][ 2 ] = pnts[ 1 ][ 2 ] = pos[ 2 ];
+
+    pnts[ 2 ][ 1 ] = pnts[ 3 ][ 1 ] = pos[ 1 ];
+    pnts[ 2 ][ 2 ] = this->m_Bounds[ 4 ];
+    pnts[ 3 ][ 2 ] = this->m_Bounds[ 5 ];
+
+    pnts[ 0 ][ 0 ] = pnts[ 1 ][ 0 ] =
+      pnts[ 2 ][ 0 ] = pnts[ 3 ][ 0 ] =
+      pos[ 0 ] + ( double( neg? -1: 1 ) * _eps );
+  }
+  else if( this->m_Orientation == 1 )
+  {
+    pnts[ 0 ][ 0 ] = pnts[ 1 ][ 0 ] = pos[ 0 ];
+    pnts[ 0 ][ 2 ] = this->m_Bounds[ 4 ];
+    pnts[ 1 ][ 2 ] = this->m_Bounds[ 5 ];
+
+    pnts[ 2 ][ 0 ] = this->m_Bounds[ 0 ];
+    pnts[ 3 ][ 0 ] = this->m_Bounds[ 1 ];
+    pnts[ 2 ][ 2 ] = pnts[ 3 ][ 2 ] = pos[ 2 ];
+
+    pnts[ 0 ][ 1 ] = pnts[ 1 ][ 1 ] =
+      pnts[ 2 ][ 1 ] = pnts[ 3 ][ 1 ] =
+      pos[ 1 ] + ( double( neg? -1: 1 ) * _eps );
+  }
+  else if( this->m_Orientation == 2 )
+  {
+    pnts[ 0 ][ 0 ] = this->m_Bounds[ 0 ];
+    pnts[ 1 ][ 0 ] = this->m_Bounds[ 1 ];
+    pnts[ 0 ][ 1 ] = pnts[ 1 ][ 1 ] = pos[ 1 ];
+
+    pnts[ 2 ][ 0 ] = pnts[ 3 ][ 0 ] = pos[ 0 ];
+    pnts[ 2 ][ 1 ] = this->m_Bounds[ 2 ];
+    pnts[ 3 ][ 1 ] = this->m_Bounds[ 3 ];
+
+    pnts[ 0 ][ 2 ] = pnts[ 1 ][ 2 ] =
+      pnts[ 2 ][ 2 ] = pnts[ 3 ][ 2 ] =
+      pos[ 2 ] + ( double( neg? -1: 1 ) * _eps );
+
+  } // fi
+
+  this->m_Lines[ 0 ]->SetPoint1( pnts[ 0 ] );
+  this->m_Lines[ 0 ]->SetPoint2( pnts[ 1 ] );
+  this->m_Lines[ 1 ]->SetPoint1( pnts[ 2 ] );
+  this->m_Lines[ 1 ]->SetPoint2( pnts[ 3 ] );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+vtkProperty* cpExtensions::Visualization::CursorActors::
+GetProperty( unsigned int i )
+{
+  return( this->m_Actors[ i % 2 ]->GetProperty( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkProperty* cpExtensions::Visualization::CursorActors::
+GetProperty( unsigned int i ) const
+{
+  return( this->m_Actors[ i % 2 ]->GetProperty( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+SetVisibility( int v )
+{
+  this->m_Actors[ 0 ]->SetVisibility( v );
+  this->m_Actors[ 1 ]->SetVisibility( v );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+VisibilityOn( )
+{
+  this->m_Actors[ 0 ]->VisibilityOn( );
+  this->m_Actors[ 1 ]->VisibilityOn( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::CursorActors::
+VisibilityOff( )
+{
+  this->m_Actors[ 0 ]->VisibilityOff( );
+  this->m_Actors[ 1 ]->VisibilityOff( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::CursorActors::
+CursorActors( )
+  : Superclass( )
+{
+  this->m_Bounds[ 0 ] = this->m_Bounds[ 1 ] = this->m_Bounds[ 2 ] =
+    this->m_Bounds[ 3 ] = this->m_Bounds[ 4 ] = this->m_Bounds[ 5 ] =
+    double( 0 );
+
+  for( unsigned int i = 0; i < 2; ++i )
+  {
+    this->m_Lines[ i ] = vtkSmartPointer< LineSource >::New( );
+    this->m_Mappers[ i ] = vtkSmartPointer< vtkPolyDataMapper >::New( );
+    this->m_Actors[ i ] = vtkSmartPointer< vtkActor >::New( );
+    this->m_Mappers[ i ]->SetInputConnection(
+      this->m_Lines[ i ]->GetOutputPort( )
+      );
+    this->m_Actors[ i ]->SetMapper( this->m_Mappers[ i ] );
+    this->AddItem( this->m_Actors[ i ] );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::CursorActors::
+~CursorActors( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/CursorActors.h b/lib/cpExtensions/Visualization/CursorActors.h
new file mode 100644 (file)
index 0000000..77a6d8e
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef __cpExtensions__Visualization__CursorActors__h__
+#define __cpExtensions__Visualization__CursorActors__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPropCollection.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkActor;
+class vtkPolyDataMapper;
+class vtkProperty;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class LineSource;
+
+    /**
+     */
+    class cpExtensions_EXPORT CursorActors
+      : public vtkPropCollection
+    {
+    public:
+      typedef CursorActors Self;
+
+    public:
+      vtkTypeMacro( CursorActors, vtkPropCollection );
+
+    public:
+      static Self* New( );
+
+      virtual void Modified( ) cpExtensions_OVERRIDE;
+
+      void SetImageBounds( double* bounds );
+      void SetImageOrientation( int orientation );
+      void SetCursor( double* pos, bool neg );
+
+      vtkProperty* GetProperty( unsigned int i );
+      const vtkProperty* GetProperty( unsigned int i ) const;
+
+      void SetVisibility( int v );
+      void VisibilityOn( );
+      void VisibilityOff( );
+
+    protected:
+      CursorActors( );
+      virtual ~CursorActors( );
+
+    private:
+      // Purposely not implemented
+      CursorActors( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< LineSource >        m_Lines[ 2 ];
+      vtkSmartPointer< vtkPolyDataMapper > m_Mappers[ 2 ];
+      vtkSmartPointer< vtkActor >          m_Actors[ 2 ];
+      double m_Bounds[ 6 ];
+      int    m_Orientation;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__CursorActors__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageActor.cxx b/lib/cpExtensions/Visualization/ImageActor.cxx
new file mode 100644 (file)
index 0000000..d1f72ac
--- /dev/null
@@ -0,0 +1,94 @@
+#include <cpExtensions/Visualization/ImageActor.h>
+#include <cpExtensions/Visualization/ImageSliceMapper.h>
+
+#include <vtkCommand.h>
+#include <vtkImageData.h>
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageActor::
+Modified( )
+{
+  if( this->m_Mapper->GetNumberOfInputConnections( 0 ) > 0 )
+  {
+    this->m_Mapper->Modified( );
+    this->m_Mapper->Update( );
+    this->Superclass::Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageActor::
+GetOrientation( ) const
+{
+  return( this->m_Mapper->GetOrientation( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageActor::
+SetOrientation( int orientation )
+{
+  this->m_Mapper->SetOrientation( ( orientation < 3 )? orientation: 2 );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageActor::
+GetSliceNumber( ) const
+{
+  return( this->m_Mapper->GetSliceNumber( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageActor::
+SetSliceNumber( int slice )
+{
+  static int s = 0;
+  auto image = this->m_Mapper->GetInput( );
+  if( image != NULL )
+  {
+    // Update slice
+    s = slice;
+    if( s < this->m_Mapper->GetSliceNumberMinValue( ) )
+      s = this->m_Mapper->GetSliceNumberMinValue( );
+    if( s > this->m_Mapper->GetSliceNumberMaxValue( ) )
+      s = this->m_Mapper->GetSliceNumberMaxValue( );
+    this->m_Mapper->SetSliceNumber( s );
+    this->InvokeEvent( vtkCommand::InteractionEvent, &s );
+
+    // Propagate modifications
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+vtkPlane* cpExtensions::Visualization::ImageActor::
+GetSlicePlane( )
+{
+  return( this->m_Mapper->GetSlicePlane( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkPlane* cpExtensions::Visualization::ImageActor::
+GetSlicePlane( ) const
+{
+  return( this->m_Mapper->GetSlicePlane( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageActor::
+ImageActor( )
+  : Superclass( )
+{
+  this->m_Mapper = vtkSmartPointer< ImageSliceMapper >::New( );
+  this->SetMapper( this->m_Mapper );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageActor::
+~ImageActor( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageActor.h b/lib/cpExtensions/Visualization/ImageActor.h
new file mode 100644 (file)
index 0000000..c62c132
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __cpExtensions__Visualization__ImageActor__h__
+#define __cpExtensions__Visualization__ImageActor__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkImageSlice.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkImageAlgorithm;
+class vtkImageData;
+class vtkPlane;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class ImageSliceMapper;
+
+    /**
+     */
+    class cpExtensions_EXPORT ImageActor
+      : public vtkImageSlice
+    {
+    public:
+      typedef ImageActor Self;
+
+    public:
+      vtkTypeMacro( ImageActor, vtkImageSlice );
+
+    public:
+      virtual void Modified( ) cpExtensions_OVERRIDE;
+
+      int GetOrientation( ) const;
+      void SetOrientation( int orientation );
+
+      int GetSliceNumber( ) const;
+      void SetSliceNumber( int slice );
+
+      vtkPlane* GetSlicePlane( );
+      const vtkPlane* GetSlicePlane( ) const;
+
+    protected:
+      ImageActor( );
+      virtual ~ImageActor( );
+
+    private:
+      // Purposely not implemented
+      ImageActor( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< ImageSliceMapper > m_Mapper;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__ImageActor__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h
new file mode 100644 (file)
index 0000000..5129512
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__
+#define __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__
+
+#include <vtkPolyDataAlgorithm.h>
+#include <itkImageBase.h>
+
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    template< class _TIndexes >
+    class ImageIndexesContainerToPolyData
+      : public vtkPolyDataAlgorithm
+    {
+    public:
+      typedef ImageIndexesContainerToPolyData Self;
+
+      typedef _TIndexes TIndexes;
+      typedef typename TIndexes::ComponentType TContainer;
+      typedef typename TContainer::value_type  TIndex;
+      typedef itk::ImageBase< TIndex::Dimension > TImage;
+
+    public:
+      vtkTypeMacro( ImageIndexesContainerToPolyData, vtkPolyDataAlgorithm );
+
+    public:
+      static Self* New( );
+
+      const TIndexes* GetInput( ) const;
+      const TImage* GetReferenceImage( ) const;
+      void SetInput( const TIndexes* c );
+      void SetReferenceImage( const TImage* i );
+
+    protected:
+      ImageIndexesContainerToPolyData( );
+      virtual ~ImageIndexesContainerToPolyData( );
+
+      int RequestData(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+      int RequestInformation(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+
+    private:
+      // Purposely not implemented
+      ImageIndexesContainerToPolyData( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      const TIndexes* m_Indexes;
+      const TImage*   m_ReferenceImage;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include <cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx>
+#endif // ITK_MANUAL_INSTANTIATION
+
+#endif //  __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx
new file mode 100644 (file)
index 0000000..a1403ce
--- /dev/null
@@ -0,0 +1,188 @@
+#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__
+#define __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__
+
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+typename cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+Self* cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+const typename cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+TIndexes* cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+GetInput( ) const
+{
+  return( this->m_Indexes );
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+const typename cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+TImage* cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+GetReferenceImage( ) const
+{
+  return( this->m_ReferenceImage );
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+void cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+SetInput( const TIndexes* c )
+{
+  if( this->m_Indexes != c )
+  {
+    this->m_Indexes = c;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+void cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+SetReferenceImage( const TImage* i )
+{
+  if( this->m_ReferenceImage != i )
+  {
+    this->m_ReferenceImage = i;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+ImageIndexesContainerToPolyData( )
+  : vtkPolyDataAlgorithm( ),
+    m_Indexes( NULL ),
+    m_ReferenceImage( NULL )
+{
+  this->SetNumberOfInputPorts( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+~ImageIndexesContainerToPolyData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+int cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+RequestData(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  static const unsigned int dim = TIndex::Dimension;
+
+  if( this->m_Indexes == NULL )
+    return( 0 );
+
+  // Get output
+  vtkInformation* info = output->GetInformationObject( 0 );
+  vtkPolyData* out = vtkPolyData::SafeDownCast(
+    info->Get( vtkDataObject::DATA_OBJECT( ) )
+    );
+
+  // Get input data
+  auto& lst = this->m_Indexes->Get( );
+
+  // Prepare points
+  vtkPoints* points = out->GetPoints( );
+  if( points == NULL )
+  {
+    points = vtkPoints::New( );
+    out->SetPoints( points );
+    points->Delete( );
+
+  } // fi
+  points->SetNumberOfPoints( lst.size( ) );
+
+  // Prepare cells
+  vtkSmartPointer< vtkCellArray > verts =
+    vtkSmartPointer< vtkCellArray >::New( );
+
+  for( unsigned int i = 0; i < lst.size( ); ++i )
+  {
+    auto idx = lst[ i ];
+    if( this->m_ReferenceImage != NULL )
+    {
+      typename TImage::PointType pnt;
+      this->m_ReferenceImage->TransformIndexToPhysicalPoint( idx, pnt );
+      if( dim == 1 )
+        points->SetPoint( i, pnt[ 0 ], 0, 0 );
+      else if( dim == 2 )
+        points->SetPoint( i, pnt[ 0 ], pnt[ 1 ], 0 );
+      else
+        points->SetPoint( i, pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] );
+    }
+    else
+    {
+      if( dim == 1 )
+        points->SetPoint( i, idx[ 0 ], 0, 0 );
+      else if( dim == 2 )
+        points->SetPoint( i, idx[ 0 ], idx[ 1 ], 0 );
+      else
+        points->SetPoint( i, idx[ 0 ], idx[ 1 ], idx[ 2 ] );
+
+    } // fi
+    verts->InsertNextCell( 1 );
+    verts->InsertCellPoint( i );
+
+  } // rof
+  out->SetPoints( points );
+  out->SetVerts( verts );
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TIndexes >
+int
+cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TIndexes >::
+RequestInformation(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  vtkInformation* info = output->GetInformationObject( 0 );
+  /* TODO
+     info->Set(
+     vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES( ), -1
+     );
+  */
+
+  if( this->m_Indexes != NULL && this->m_ReferenceImage != NULL )
+  {
+    /* TODO
+       typename C::TScalar len = this->m_RGC->GetTotalLength( );
+       typename C::TScalar s0 = this->m_RGC->Gets0( );
+       typename C::TPoint p0 = this->m_RGC->Axis( s0 );
+       typename C::TPoint p1 = this->m_RGC->Axis( s0 + len );
+
+       info->Set(
+       vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX( ),
+       double( p0[ 0 ] ), double( p1[ 0 ] ),
+       double( p0[ 1 ] ), double( p1[ 1 ] ),
+       double( p0[ 2 ] ), double( p1[ 2 ] )
+       );
+    */
+
+  } // fi
+  return( 1 );
+}
+
+#endif //  __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageOutlineActor.cxx b/lib/cpExtensions/Visualization/ImageOutlineActor.cxx
new file mode 100644 (file)
index 0000000..9cef8d1
--- /dev/null
@@ -0,0 +1,68 @@
+#include <cpExtensions/Visualization/ImageOutlineActor.h>
+#include <cpExtensions/Visualization/ImageOutlineSource.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkProperty.h>
+
+// -------------------------------------------------------------------------
+double cpExtensions::Visualization::ImageOutlineActor::Colors[ 3 ][ 3 ] =
+{
+  { 1, 0, 0 },
+  { 0, 1, 0 },
+  { 0, 0, 1 }
+};
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageOutlineActor::
+Self* cpExtensions::Visualization::ImageOutlineActor::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageOutlineActor::
+Modified( )
+{
+  this->m_Outline->Modified( );
+  this->m_Mapper->Modified( );
+  this->Superclass::Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageOutlineActor::
+SetBounds( int orientation, double step, double* bounds )
+{
+  // Update geometry
+  this->m_Outline->SetBounds( orientation, step, bounds );
+
+  // Update visualization properties
+  int o = orientation % 3;
+  this->GetProperty( )->SetLineWidth( 1.5 );
+  this->GetProperty( )->SetColor(
+    Self::Colors[ o ][ 0 ],
+    Self::Colors[ o ][ 1 ],
+    Self::Colors[ o ][ 2 ]
+    );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageOutlineActor::
+ImageOutlineActor( )
+  : Superclass( )
+{
+  this->m_Outline = vtkSmartPointer< ImageOutlineSource >::New( );
+  this->m_Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
+  this->m_Mapper->SetInputConnection( this->m_Outline->GetOutputPort( ) );
+  this->SetMapper( this->m_Mapper );
+
+  this->UseBoundsOff( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageOutlineActor::
+~ImageOutlineActor( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageOutlineActor.h b/lib/cpExtensions/Visualization/ImageOutlineActor.h
new file mode 100644 (file)
index 0000000..5ba8c73
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __cpExtensions__Visualization__ImageOutlineActor__h__
+#define __cpExtensions__Visualization__ImageOutlineActor__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkOpenGLActor.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkPolyDataMapper;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class ImageOutlineSource;
+
+    /**
+     */
+    class cpExtensions_EXPORT ImageOutlineActor
+      : public vtkOpenGLActor
+    {
+    public:
+      typedef ImageOutlineActor Self;
+
+    public:
+      vtkTypeMacro( ImageOutlineActor, vtkOpenGLActor );
+
+    public:
+      static Self* New( );
+
+      virtual void Modified( ) cpExtensions_OVERRIDE;
+
+      void SetBounds( int orientation, double step, double* bounds );
+
+    protected:
+      ImageOutlineActor( );
+      virtual ~ImageOutlineActor( );
+
+    private:
+      // Purposely not implemented
+      ImageOutlineActor( const Self& );
+      Self& operator=( const Self& );
+
+    public:
+      static double Colors[ 3 ][ 3 ];
+
+    protected:
+      vtkSmartPointer< ImageOutlineSource > m_Outline;
+      vtkSmartPointer< vtkPolyDataMapper >  m_Mapper;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__ImageOutlineActor__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageOutlineSource.cxx b/lib/cpExtensions/Visualization/ImageOutlineSource.cxx
new file mode 100644 (file)
index 0000000..8fa8131
--- /dev/null
@@ -0,0 +1,156 @@
+#include <cpExtensions/Visualization/ImageOutlineSource.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageOutlineSource::
+Self* cpExtensions::Visualization::ImageOutlineSource::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageOutlineSource::
+SetBounds( int orientation, double step, double* bounds )
+{
+  // Update geometry
+  int o = orientation % 3;
+  if( o == 0 )
+  {
+    this->m_Bounds[ 0 ][ 0 ] = step;
+    this->m_Bounds[ 0 ][ 1 ] = bounds[ 2 ];
+    this->m_Bounds[ 0 ][ 2 ] = bounds[ 4 ];
+
+    this->m_Bounds[ 1 ][ 0 ] = step;
+    this->m_Bounds[ 1 ][ 1 ] = bounds[ 2 ];
+    this->m_Bounds[ 1 ][ 2 ] = bounds[ 5 ];
+
+    this->m_Bounds[ 2 ][ 0 ] = step;
+    this->m_Bounds[ 2 ][ 1 ] = bounds[ 3 ];
+    this->m_Bounds[ 2 ][ 2 ] = bounds[ 5 ];
+
+    this->m_Bounds[ 3 ][ 0 ] = step;
+    this->m_Bounds[ 3 ][ 1 ] = bounds[ 3 ];
+    this->m_Bounds[ 3 ][ 2 ] = bounds[ 4 ];
+  }
+  else if( o == 1 )
+  {
+    this->m_Bounds[ 0 ][ 0 ] = bounds[ 0 ];
+    this->m_Bounds[ 0 ][ 1 ] = step;
+    this->m_Bounds[ 0 ][ 2 ] = bounds[ 4 ];
+
+    this->m_Bounds[ 1 ][ 0 ] = bounds[ 1 ];
+    this->m_Bounds[ 1 ][ 1 ] = step;
+    this->m_Bounds[ 1 ][ 2 ] = bounds[ 4 ];
+
+    this->m_Bounds[ 2 ][ 0 ] = bounds[ 1 ];
+    this->m_Bounds[ 2 ][ 1 ] = step;
+    this->m_Bounds[ 2 ][ 2 ] = bounds[ 5 ];
+
+    this->m_Bounds[ 3 ][ 0 ] = bounds[ 0 ];
+    this->m_Bounds[ 3 ][ 1 ] = step;
+    this->m_Bounds[ 3 ][ 2 ] = bounds[ 5 ];
+  }
+  else if( o == 2 )
+  {
+    this->m_Bounds[ 0 ][ 0 ] = bounds[ 0 ];
+    this->m_Bounds[ 0 ][ 1 ] = bounds[ 2 ];
+    this->m_Bounds[ 0 ][ 2 ] = step;
+
+    this->m_Bounds[ 1 ][ 0 ] = bounds[ 1 ];
+    this->m_Bounds[ 1 ][ 1 ] = bounds[ 2 ];
+    this->m_Bounds[ 1 ][ 2 ] = step;
+
+    this->m_Bounds[ 2 ][ 0 ] = bounds[ 1 ];
+    this->m_Bounds[ 2 ][ 1 ] = bounds[ 3 ];
+    this->m_Bounds[ 2 ][ 2 ] = step;
+
+    this->m_Bounds[ 3 ][ 0 ] = bounds[ 0 ];
+    this->m_Bounds[ 3 ][ 1 ] = bounds[ 3 ];
+    this->m_Bounds[ 3 ][ 2 ] = step;
+
+  } // fi
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageOutlineSource::
+ImageOutlineSource( )
+  : Superclass( )
+{
+  this->SetNumberOfInputPorts( 0 );
+  for( unsigned int j = 0; j < 4; ++j )
+    for( unsigned int i = 0; i < 3; ++i )
+      this->m_Bounds[ j ][ i ] = double( 0 );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageOutlineSource::
+~ImageOutlineSource( )
+{
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageOutlineSource::
+RequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  // Get output object
+  vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
+  vtkPolyData* output =
+    vtkPolyData::SafeDownCast(
+      outInfo->Get( vtkDataObject::DATA_OBJECT( ) )
+      );
+
+  // Create points
+  vtkPoints* points = vtkPoints::New( );
+  points->SetDataType( VTK_FLOAT );
+  points->Allocate( 4 );
+
+  // Create lines
+  vtkCellArray* verts = vtkCellArray::New( );
+  vtkCellArray* lines = vtkCellArray::New( );
+  vtkCellArray* faces = vtkCellArray::New( );
+  vtkCellArray* strips = vtkCellArray::New( );
+  lines->Allocate( lines->EstimateSize( 4, 2 ) );
+
+  // Assign points
+  points->InsertPoint( 0, this->m_Bounds[ 0 ] );
+  points->InsertPoint( 1, this->m_Bounds[ 1 ] );
+  points->InsertPoint( 2, this->m_Bounds[ 2 ] );
+  points->InsertPoint( 3, this->m_Bounds[ 3 ] );
+
+  // Assign cells
+  vtkIdType cell_pts[ 4 ][ 2 ] =
+  {
+    { 0, 1 },
+    { 1, 2 },
+    { 2, 3 },
+    { 3, 0 }
+  };
+  lines->InsertNextCell( 2, cell_pts[ 0 ] );
+  lines->InsertNextCell( 2, cell_pts[ 1 ] );
+  lines->InsertNextCell( 2, cell_pts[ 2 ] );
+  lines->InsertNextCell( 2, cell_pts[ 3 ] );
+
+  // Assign to output
+  output->SetPoints( points );
+  output->SetVerts( verts );
+  output->SetLines( lines );
+  output->SetPolys( faces );
+  output->SetStrips( strips );
+
+  // Finish and return
+  points->Delete( );
+  verts->Delete( );
+  lines->Delete( );
+  faces->Delete( );
+  strips->Delete( );
+  return( 1 );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageOutlineSource.h b/lib/cpExtensions/Visualization/ImageOutlineSource.h
new file mode 100644 (file)
index 0000000..5f3f7d8
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __cpExtensions__Visualization__ImageOutlineSource__h__
+#define __cpExtensions__Visualization__ImageOutlineSource__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPolyDataAlgorithm.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ImageOutlineSource
+      : public vtkPolyDataAlgorithm
+    {
+    public:
+      typedef ImageOutlineSource Self;
+
+    public:
+      vtkTypeMacro( ImageOutlineSource, vtkPolyDataAlgorithm );
+
+    public:
+      static Self* New( );
+
+      void SetBounds( int orientation, double step, double* bounds );
+
+    protected:
+      ImageOutlineSource( );
+      virtual ~ImageOutlineSource( );
+
+      virtual int RequestData(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      ImageOutlineSource( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      double m_Bounds[ 4 ][ 3 ];
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__ImageOutlineSource__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.cxx b/lib/cpExtensions/Visualization/ImageSliceActors.cxx
new file mode 100644 (file)
index 0000000..6d67a66
--- /dev/null
@@ -0,0 +1,174 @@
+#include <cpExtensions/Visualization/ImageSliceActors.h>
+#include <cpExtensions/Visualization/ImageOutlineActor.h>
+#include <cpExtensions/Visualization/LUTImageActor.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+#include <vtkImageData.h>
+#include <vtkPlane.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageSliceActors::
+Self* cpExtensions::Visualization::ImageSliceActors::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkImageData* cpExtensions::Visualization::ImageSliceActors::
+GetImage( )
+{
+  if( this->m_WindowLevelImageActor.GetPointer( ) != NULL )
+    return( this->m_WindowLevelImageActor->GetImage( ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+const vtkImageData* cpExtensions::Visualization::ImageSliceActors::
+GetImage( ) const
+{
+  if( this->m_WindowLevelImageActor.GetPointer( ) != NULL )
+    return( this->m_WindowLevelImageActor->GetImage( ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+WindowLevelImageActor* cpExtensions::Visualization::ImageSliceActors::
+GetWindowLevelImageActor( )
+{
+  return( this->m_WindowLevelImageActor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+WindowLevelImageActor* cpExtensions::Visualization::ImageSliceActors::
+GetWindowLevelImageActor( ) const
+{
+  return( this->m_WindowLevelImageActor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+LUTImageActor* cpExtensions::Visualization::ImageSliceActors::
+GetLUTImageActor( )
+{
+  return( this->m_LUTImageActor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+LUTImageActor* cpExtensions::Visualization::ImageSliceActors::
+GetLUTImageActor( ) const
+{
+  return( this->m_LUTImageActor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+ImageOutlineActor* cpExtensions::Visualization::ImageSliceActors::
+GetImageOutlineActor( )
+{
+  return( this->m_ImageOutlineActor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+ImageOutlineActor* cpExtensions::Visualization::ImageSliceActors::
+GetImageOutlineActor( ) const
+{
+  return( this->m_ImageOutlineActor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageSliceActors::
+GetOrientation( ) const
+{
+  if( this->m_WindowLevelImageActor.GetPointer( ) != NULL )
+    return( this->m_WindowLevelImageActor->GetOrientation( ) );
+  else
+    return( 0 );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+SetImage( vtkImageData* image, int orientation )
+{
+  this->m_WindowLevelImageActor =
+    vtkSmartPointer< WindowLevelImageActor >::New( );
+  this->m_WindowLevelImageActor->SetImage( image );
+  this->m_WindowLevelImageActor->SetOrientation( orientation );
+  this->m_ImageOutlineActor = vtkSmartPointer< ImageOutlineActor >::New( );
+  this->m_LUTImageActor = NULL;
+
+  // Put an initial slice
+  int ext[ 6 ];
+  image->GetExtent( ext );
+  this->SetSliceNumber(
+    ext[ this->m_WindowLevelImageActor->GetOrientation( ) << 1 ]
+    );
+
+  // Update collection
+  this->RemoveAllItems( );
+  this->AddItem( this->m_ImageOutlineActor );
+  this->AddItem( this->m_WindowLevelImageActor );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpExtensions::Visualization::ImageSliceActors::
+AddLUTImage( vtkImageData* image )
+{
+  if( this->GetImage( ) != NULL )
+  {
+    if( this->m_LUTImageActor.GetPointer( ) == NULL )
+    {
+      this->m_LUTImageActor = vtkSmartPointer< LUTImageActor >::New( );
+      this->m_LUTImageActor->SetOrientation( this->GetOrientation( ) );
+      this->AddItem( this->m_LUTImageActor );
+
+    } // fi
+    this->m_LUTImageActor->AddImage( image );
+    return( this->m_LUTImageActor->GetNumberOfImages( ) );
+  }
+  else
+    return( 0 );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::ImageSliceActors::
+GetSliceNumber( ) const
+{
+  return( this->m_WindowLevelImageActor->GetSliceNumber( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageSliceActors::
+SetSliceNumber( int slice )
+{
+  this->m_WindowLevelImageActor->SetSliceNumber( slice );
+  if( this->m_LUTImageActor.GetPointer( ) != NULL )
+    this->m_LUTImageActor->SetSliceNumber( slice );
+
+  double bounds[ 6 ];
+  this->m_WindowLevelImageActor->GetImage( )->GetBounds( bounds );
+  int o = this->m_WindowLevelImageActor->GetOrientation( );
+  double p = this->m_WindowLevelImageActor->GetSlicePlane( )->GetOrigin( )[ o ];
+  this->m_ImageOutlineActor->SetBounds( o, p, bounds );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageSliceActors::
+ImageSliceActors( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageSliceActors::
+~ImageSliceActors( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.h b/lib/cpExtensions/Visualization/ImageSliceActors.h
new file mode 100644 (file)
index 0000000..25f81f6
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __cpExtensions__Visualization__ImageSliceActors__h__
+#define __cpExtensions__Visualization__ImageSliceActors__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPropCollection.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkImageData;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class ImageOutlineActor;
+    class LUTImageActor;
+    class WindowLevelImageActor;
+
+    /**
+     */
+    class cpExtensions_EXPORT ImageSliceActors
+      : public vtkPropCollection
+    {
+    public:
+      typedef ImageSliceActors Self;
+
+    public:
+      vtkTypeMacro( ImageSliceActors, vtkPropCollection );
+
+    public:
+      static Self* New( );
+
+      vtkImageData* GetImage( );
+      const vtkImageData* GetImage( ) const;
+
+      WindowLevelImageActor* GetWindowLevelImageActor( );
+      const WindowLevelImageActor* GetWindowLevelImageActor( ) const;
+
+      LUTImageActor* GetLUTImageActor( );
+      const LUTImageActor* GetLUTImageActor( ) const;
+
+      ImageOutlineActor* GetImageOutlineActor( );
+      const ImageOutlineActor* GetImageOutlineActor( ) const;
+
+      int GetOrientation( ) const;
+
+      int GetSliceNumber( ) const;
+      virtual void SetImage( vtkImageData* image, int orientation );
+      virtual unsigned int AddLUTImage( vtkImageData* image );
+      virtual void SetSliceNumber( int slice );
+
+    protected:
+      ImageSliceActors( );
+      virtual ~ImageSliceActors( );
+
+    private:
+      // Purposely not implemented
+      ImageSliceActors( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< ImageOutlineActor >     m_ImageOutlineActor;
+      vtkSmartPointer< LUTImageActor >         m_LUTImageActor;
+      vtkSmartPointer< WindowLevelImageActor > m_WindowLevelImageActor;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__ImageSliceActors__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageSliceMapper.cxx b/lib/cpExtensions/Visualization/ImageSliceMapper.cxx
new file mode 100644 (file)
index 0000000..5bf36fc
--- /dev/null
@@ -0,0 +1,64 @@
+#include <cpExtensions/Visualization/ImageSliceMapper.h>
+#include <vtkActor.h>
+#include <vtkCellArray.h>
+#include <vtkNew.h>
+#include <vtkOpenGLPolyDataMapper.h>
+#include <vtkPolyData.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageSliceMapper::
+Self* cpExtensions::Visualization::ImageSliceMapper::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageSliceMapper::
+ImageSliceMapper( )
+  : Superclass( )
+{
+#ifdef cpPlugins_OpenGL_BackEnd_OpenGL2
+  // Complete polydatas to avoid bizarre rendering errors (multi-thread)
+  vtkActor* a[ 3 ];
+  a[ 0 ] = this->PolyDataActor;
+  a[ 1 ] = this->BackingPolyDataActor;
+  a[ 2 ] = this->BackgroundPolyDataActor;
+  for( unsigned int i = 0; i < 3; ++i )
+  {
+    if( a[ i ] != NULL )
+    {
+      auto m =
+        dynamic_cast< vtkOpenGLPolyDataMapper* >( a[ i ]->GetMapper( ) );
+      if( m != NULL )
+      {
+        auto p = m->GetInput( );
+        if( p != NULL )
+        {
+          vtkNew< vtkCellArray > verts;
+          vtkNew< vtkCellArray > lines;
+          vtkNew< vtkCellArray > strips;
+          p->SetVerts( verts.Get( ) );
+          p->SetLines( lines.Get( ) );
+          p->SetStrips( strips.Get( ) );
+          p->Modified( );
+          m->Modified( );
+          a[ i ]->Modified( );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // rof
+#endif // cpPlugins_OpenGL_BackEnd_OpenGL2
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageSliceMapper::
+~ImageSliceMapper( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageSliceMapper.h b/lib/cpExtensions/Visualization/ImageSliceMapper.h
new file mode 100644 (file)
index 0000000..10e8404
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef __cpExtensions__Visualization__ImageSliceMapper__h__
+#define __cpExtensions__Visualization__ImageSliceMapper__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkOpenGLImageSliceMapper.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT ImageSliceMapper
+      : public vtkOpenGLImageSliceMapper
+    {
+    public:
+      typedef ImageSliceMapper Self;
+
+    public:
+      vtkTypeMacro( ImageSliceMapper, vtkOpenGLImageSliceMapper );
+
+    public:
+      static Self* New( );
+
+    protected:
+      ImageSliceMapper( );
+      virtual ~ImageSliceMapper( );
+
+    private:
+      // Purposely not implemented
+      ImageSliceMapper( const Self& );
+      Self& operator=( const Self& );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__ImageSliceMapper__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageViewerActors.cxx b/lib/cpExtensions/Visualization/ImageViewerActors.cxx
new file mode 100644 (file)
index 0000000..65114c8
--- /dev/null
@@ -0,0 +1,169 @@
+#include <cpExtensions/Visualization/ImageViewerActors.h>
+#include <cpExtensions/Visualization/CursorActors.h>
+#include <vtkImageData.h>
+#include <vtkProperty.h>
+#include <vtkRenderWindow.h>
+#include <vtkTextActor.h>
+#include <vtkTextProperty.h>
+#include <sstream>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageViewerActors::
+Self* cpExtensions::Visualization::ImageViewerActors::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageViewerActors::
+SetImage( vtkImageData* image, int orientation )
+{
+  this->Superclass::SetImage( image, orientation );
+
+  this->m_Cursor = vtkSmartPointer< CursorActors >::New( );
+  this->m_Cursor->SetImageBounds( image->GetBounds( ) );
+  this->m_Cursor->SetImageOrientation( orientation );
+  this->m_Cursor->GetProperty( 0 )->SetColor( 1, 1, 0 );
+  this->m_Cursor->GetProperty( 1 )->SetColor( 1, 1, 0 );
+  this->m_Cursor->GetProperty( 0 )->SetLineWidth( 1.5 );
+  this->m_Cursor->GetProperty( 1 )->SetLineWidth( 1.5 );
+  this->m_Cursor->VisibilityOff( );
+
+  this->m_SuperCursor = vtkSmartPointer< CursorActors >::New( );
+  this->m_SuperCursor->SetImageBounds( image->GetBounds( ) );
+  this->m_SuperCursor->SetImageOrientation( orientation );
+  this->m_SuperCursor->GetProperty( 0 )->SetColor( 0, 1, 1 );
+  this->m_SuperCursor->GetProperty( 1 )->SetColor( 0, 1, 1 );
+  this->m_SuperCursor->GetProperty( 0 )->SetLineWidth( 1.5 );
+  this->m_SuperCursor->GetProperty( 1 )->SetLineWidth( 1.5 );
+  this->m_SuperCursor->VisibilityOff( );
+
+  // Prepare text
+  this->m_TextBuffer[ 0 ] = '\0';
+  this->m_Text = vtkSmartPointer< vtkTextActor >::New( );
+  this->m_Text->SetTextScaleModeToNone( );
+  auto textprop = this->m_Text->GetTextProperty( );
+  textprop->SetColor( 1, 1, 0 );
+  textprop->SetFontFamilyToCourier( );
+  textprop->SetFontSize( 18 );
+  textprop->BoldOff( );
+  textprop->ItalicOff( );
+  textprop->ShadowOff( );
+  textprop->SetJustificationToLeft( );
+  textprop->SetVerticalJustificationToBottom( );
+  auto coord = this->m_Text->GetPositionCoordinate( );
+  coord->SetCoordinateSystemToNormalizedViewport( );
+  coord->SetValue( 0.01, 0.05 );
+  this->m_Text->VisibilityOff( );
+
+  // Update actor list
+  this->m_Cursor->InitTraversal( );
+  while( vtkProp* prop = this->m_Cursor->GetNextProp( ) )
+    this->AddItem( prop );
+  this->m_SuperCursor->InitTraversal( );
+  while( vtkProp* prop = this->m_SuperCursor->GetNextProp( ) )
+    this->AddItem( prop );
+  this->AddItem( this->m_Text );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageViewerActors::
+SetCursor( double* pos, bool neg )
+{
+  this->m_Cursor->SetCursor( pos, neg );
+  this->_ShowText( pos );
+  this->m_Cursor->VisibilityOn( );
+  this->m_Text->VisibilityOn( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageViewerActors::
+SetSuperCursor( double* pos, bool neg )
+{
+  this->SetCursor( pos, neg );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageViewerActors::
+HideViewerActors( )
+{
+  this->m_Cursor->VisibilityOff( );
+  this->m_Text->VisibilityOff( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageViewerActors::
+ImageViewerActors( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::ImageViewerActors::
+~ImageViewerActors( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageViewerActors::
+_CorrectPosition( double* pos, int* ijk )
+{
+  auto image = this->GetImage( );
+  if( image == NULL )
+    return;
+
+  // Approximate image index
+  double pcoords[ 3 ];
+  image->ComputeStructuredCoordinates( pos, ijk, pcoords );
+
+  // Manually correct index
+  int ext[ 6 ];
+  image->GetExtent( ext );
+  for( int i = 0; i < 3; ++i )
+  {
+    if( ijk[ i ] < ext[ i << 1 ] )
+      ijk[ i ] = ext[ i << 1 ];
+    if( ext[ ( i << 1 ) + 1 ] < ijk[ i ] )
+      ijk[ i ] = ext[ ( i << 1 ) + 1 ];
+
+  } // rof
+
+  // Get real coordinates
+  int o = this->GetOrientation( );
+  ijk[ o ] = this->GetSliceNumber( );
+  image->GetPoint( image->ComputePointId( ijk ), pos );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::ImageViewerActors::
+_ShowText( double* pos )
+{
+  auto image = this->GetImage( );
+  if( image == NULL )
+    return;
+
+  int ijk[ 3 ];
+  this->_CorrectPosition( pos, ijk );
+  int o = this->GetOrientation( );
+
+  std::stringstream buffer;
+  buffer << "Axis: " << char( 'X' + char( o ) ) << std::endl;
+  int nScl = image->GetNumberOfScalarComponents( );
+  buffer
+    << "Pixel: [" << ijk[ 0 ]
+    << "," << ijk[ 1 ]
+    << "," << ijk[ 2 ] << "]=("
+    << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 );
+  for( int n = 1; n < nScl; ++n )
+    buffer
+      << " : "
+      << image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n );
+  buffer << ")";
+  cpExtensions_SPRINTF( this->m_TextBuffer, 1024, buffer.str( ).c_str( ) );
+  this->m_Text->SetInput( this->m_TextBuffer );
+  this->m_Text->VisibilityOn( );
+  this->m_Text->Modified( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/ImageViewerActors.h b/lib/cpExtensions/Visualization/ImageViewerActors.h
new file mode 100644 (file)
index 0000000..b12e9c8
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __cpExtensions__Visualization__ImageViewerActors__h__
+#define __cpExtensions__Visualization__ImageViewerActors__h__
+
+#include <cpExtensions/Visualization/ImageSliceActors.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkTextActor;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class CursorActors;
+
+    /**
+     */
+    class cpExtensions_EXPORT ImageViewerActors
+      : public ImageSliceActors
+    {
+    public:
+      typedef ImageViewerActors Self;
+
+    public:
+      vtkTypeMacro( ImageViewerActors, ImageSliceActors );
+
+    public:
+      static Self* New( );
+
+      virtual void SetImage(
+        vtkImageData* image, int orientation
+        ) cpExtensions_OVERRIDE;
+
+      void SetCursor( double* pos, bool neg );
+      void SetSuperCursor( double* pos, bool neg );
+      void HideViewerActors( );
+
+    protected:
+      ImageViewerActors( );
+      virtual ~ImageViewerActors( );
+
+      void _CorrectPosition( double* pos, int* ijk );
+      void _ShowText( double* pos );
+
+    private:
+      // Purposely not implemented
+      ImageViewerActors( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< CursorActors > m_Cursor;
+      vtkSmartPointer< CursorActors > m_SuperCursor;
+      vtkSmartPointer< vtkTextActor > m_Text;
+      char m_TextBuffer[ 1024 ];
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__ImageViewerActors__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/LUTImageActor.cxx b/lib/cpExtensions/Visualization/LUTImageActor.cxx
new file mode 100644 (file)
index 0000000..d377215
--- /dev/null
@@ -0,0 +1,160 @@
+#include <cpExtensions/Visualization/LUTImageActor.h>
+#include <cpExtensions/Visualization/ImageSliceMapper.h>
+
+#include <vtkImageData.h>
+#include <vtkImageMapToColors.h>
+#include <vtkImageProperty.h>
+#include <vtkLookupTable.h>
+#include <cpExtensions/Algorithms/ImageBlender.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::LUTImageActor::
+Self* cpExtensions::Visualization::LUTImageActor::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpExtensions::Visualization::LUTImageActor::
+GetNumberOfImages( ) const
+{
+  return( this->m_Images.size( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkImageData* cpExtensions::Visualization::LUTImageActor::
+GetImage( unsigned int id )
+{
+  if( id < this->m_Images.size( ) )
+    return( this->m_Images[ id ] );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+const vtkImageData* cpExtensions::Visualization::LUTImageActor::
+GetImage( unsigned int id ) const
+{
+  if( id < this->m_Images.size( ) )
+    return( this->m_Images[ id ] );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpExtensions::Visualization::LUTImageActor::
+GetImageId( vtkImageData* image ) const
+{
+  unsigned int i = 0;
+  bool f = false;
+  while( i < this->m_Images.size( ) && !f )
+  {
+    if( this->m_Images[ i ].GetPointer( ) == image )
+      f = true;
+    else
+      i++;
+
+  } // elihw
+  return( i );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::LUTImageActor::
+GetLUTColor(
+  unsigned int id, double& r, double& g, double& b, double& a
+  ) const
+{
+  double rgba[ 4 ];
+  this->m_LUT->GetTableValue( id, rgba );
+  r = rgba[ 0 ];
+  g = rgba[ 1 ];
+  b = rgba[ 2 ];
+  a = rgba[ 3 ];
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::LUTImageActor::
+GetLUTColor(
+  vtkImageData* image, double& r, double& g, double& b, double& a
+  ) const
+{
+  this->GetLUTColor( this->GetImageId( image ), r, g, b, a );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::LUTImageActor::
+SetLUTColor( unsigned int id, double r, double g, double b, double a )
+{
+  if( id >= ( unsigned int )( this->m_LUT->GetNumberOfTableValues( ) ) )
+    this->m_LUT->SetNumberOfTableValues( id + 1 );
+  this->m_LUT->SetTableValue( id, r, g, b, a );
+  this->m_LUT->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::LUTImageActor::
+SetLUTColor( vtkImageData* image, double r, double g, double b, double a )
+{
+  this->SetLUTColor( this->GetImageId( image ), r, g, b, a );
+}
+
+// TODO: !!!!!
+#include <vtkImageCast.h>
+
+// -------------------------------------------------------------------------
+unsigned int cpExtensions::Visualization::LUTImageActor::
+AddImage( vtkImageData* image, double r, double g, double b, double a )
+{
+  static vtkSmartPointer< vtkImageCast > cast;
+  cast = vtkSmartPointer< vtkImageCast >::New( );
+
+  if( image != NULL )
+  {
+    cast->SetOutputScalarTypeToUnsignedChar( );
+    cast->SetInputData( image );
+    cast->Update( );
+
+    this->m_Images.push_back( image );
+    this->SetLUTColor( this->m_Images.size( ), r, g, b, a );
+    this->m_Blender->AddInputData( cast->GetOutput( ) );
+    this->m_Blender->Update( );
+
+    if( this->m_Images.size( ) == 1 )
+    {
+      this->m_ImageMap->
+        SetInputConnection( this->m_Blender->GetOutputPort( ) );
+      this->m_Mapper->
+        SetInputConnection( this->m_ImageMap->GetOutputPort( ) );
+
+    } // fi
+    this->Modified( );
+
+    this->GetProperty( )->SetInterpolationTypeToNearest( );
+
+  } // fi
+  return( this->m_Images.size( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::LUTImageActor::
+LUTImageActor( )
+  : Superclass( )
+{
+  this->m_LUT = vtkSmartPointer< vtkLookupTable >::New( );
+  this->m_LUT->SetNumberOfTableValues( 1 );
+  this->m_LUT->SetNanColor( 0, 0, 0, 0 );
+  this->m_LUT->SetTableValue( 0, 0, 0, 0, 0 );
+
+  this->m_Blender = vtkSmartPointer< _TImageBlender >::New( );
+  this->m_ImageMap = vtkSmartPointer< vtkImageMapToColors >::New( );
+  this->m_ImageMap->SetLookupTable( this->m_LUT );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::LUTImageActor::
+~LUTImageActor( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/LUTImageActor.h b/lib/cpExtensions/Visualization/LUTImageActor.h
new file mode 100644 (file)
index 0000000..851afa5
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef __cpExtensions__Visualization__LUTImageActor__h__
+#define __cpExtensions__Visualization__LUTImageActor__h__
+
+#include <cpExtensions/Visualization/ImageActor.h>
+#include <vector>
+
+// -------------------------------------------------------------------------
+class vtkImageMapToColors;
+class vtkLookupTable;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Algorithms { class ImageBlender; }
+
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT LUTImageActor
+      : public ImageActor
+    {
+    public:
+      typedef LUTImageActor Self;
+
+    protected:
+      typedef cpExtensions::Algorithms::ImageBlender _TImageBlender;
+
+    public:
+      vtkTypeMacro( LUTImageActor, ImageActor );
+
+    public:
+      static Self* New( );
+
+      unsigned int GetNumberOfImages( ) const;
+      vtkImageData* GetImage( unsigned int id );
+      const vtkImageData* GetImage( unsigned int id ) const;
+      unsigned int GetImageId( vtkImageData* image ) const;
+      void GetLUTColor(
+        unsigned int id, double& r, double& g, double& b, double& a
+        ) const;
+      void GetLUTColor(
+        vtkImageData* image, double& r, double& g, double& b, double& a
+        ) const;
+      void SetLUTColor(
+        unsigned int id, double r, double g, double b, double a
+        );
+      void SetLUTColor(
+        vtkImageData* image, double r, double g, double b, double a
+        );
+      unsigned int AddImage(
+        vtkImageData* image,
+        double r = 1, double g = 0, double b = 0, double a = 1
+        );
+
+    protected:
+      LUTImageActor( );
+      virtual ~LUTImageActor( );
+
+    private:
+      // Purposely not implemented
+      LUTImageActor( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< vtkLookupTable >              m_LUT;
+      vtkSmartPointer< _TImageBlender >              m_Blender;
+      vtkSmartPointer< vtkImageMapToColors >         m_ImageMap;
+      std::vector< vtkSmartPointer< vtkImageData > > m_Images;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__LUTImageActor__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/LineSource.cxx b/lib/cpExtensions/Visualization/LineSource.cxx
new file mode 100644 (file)
index 0000000..6280cba
--- /dev/null
@@ -0,0 +1,119 @@
+#include <cpExtensions/Visualization/LineSource.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::LineSource::
+Self* cpExtensions::Visualization::LineSource::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::LineSource::
+SetPoint1( float pnt[ 3 ] )
+{
+  double p[ 3 ];
+  p[ 0 ] = pnt[ 0 ];
+  p[ 1 ] = pnt[ 1 ];
+  p[ 2 ] = pnt[ 2 ];
+  this->SetPoint1( p );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::LineSource::
+SetPoint2( float pnt[ 3 ] )
+{
+  double p[ 3 ];
+  p[ 0 ] = pnt[ 0 ];
+  p[ 1 ] = pnt[ 1 ];
+  p[ 2 ] = pnt[ 2 ];
+  this->SetPoint2( p );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::LineSource::
+LineSource( )
+  : Superclass( )
+{
+  this->SetNumberOfInputPorts( 0 );
+  this->Point1[ 0 ] = -double( 0.5 );
+  this->Point1[ 1 ] =  double( 0.0 );
+  this->Point1[ 2 ] =  double( 0.0 );
+  this->Point2[ 0 ] =  double( 0.5 );
+  this->Point2[ 1 ] =  double( 0.0 );
+  this->Point2[ 2 ] =  double( 0.0 );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::LineSource::
+~LineSource( )
+{
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::LineSource::
+RequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  // Get output object
+  vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
+  vtkPolyData* output =
+    vtkPolyData::SafeDownCast(
+      outInfo->Get( vtkDataObject::DATA_OBJECT( ) )
+      );
+
+  // Create points
+  vtkPoints* points = vtkPoints::New( );
+  points->SetDataType( VTK_FLOAT );
+  points->Allocate( 2 );
+
+  // Create cells
+  vtkCellArray* verts = vtkCellArray::New( );
+  vtkCellArray* lines = vtkCellArray::New( );
+  vtkCellArray* faces = vtkCellArray::New( );
+  vtkCellArray* strips = vtkCellArray::New( );
+  lines->Allocate( lines->EstimateSize( 2, 2 ) );
+
+  // Assign points
+  points->InsertPoint( 0, this->Point1 );
+  points->InsertPoint( 1, this->Point2 );
+
+  // Assign cells
+  vtkIdType cell_pts[ 2 ] = { 0, 1 };
+  lines->InsertNextCell( 2, cell_pts );
+
+  // Assign to output
+  output->SetPoints( points );
+  output->SetVerts( verts );
+  output->SetLines( lines );
+  output->SetPolys( faces );
+  output->SetStrips( strips );
+
+  // Finish and return
+  points->Delete( );
+  verts->Delete( );
+  lines->Delete( );
+  faces->Delete( );
+  strips->Delete( );
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::LineSource::
+RequestInformation(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
+  outInfo->Set( CAN_HANDLE_PIECE_REQUEST(), 1 );
+  return( 1 );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/LineSource.h b/lib/cpExtensions/Visualization/LineSource.h
new file mode 100644 (file)
index 0000000..c675257
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __cpExtensions__Visualization__LineSource__h__
+#define __cpExtensions__Visualization__LineSource__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPolyDataAlgorithm.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT LineSource
+      : public vtkPolyDataAlgorithm
+    {
+    public:
+      typedef LineSource Self;
+
+    public:
+      vtkTypeMacro( LineSource, vtkPolyDataAlgorithm );
+
+      vtkSetVector3Macro( Point1, double );
+      vtkSetVector3Macro( Point2, double );
+      vtkGetVectorMacro( Point1, double, 3 );
+      vtkGetVectorMacro( Point2, double, 3 );
+
+    public:
+      static Self* New( );
+
+      void SetPoint1( float pnt[ 3 ] );
+      void SetPoint2( float pnt[ 3 ] );
+
+    protected:
+      LineSource( );
+      virtual ~LineSource( );
+
+      virtual int RequestData(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        ) cpExtensions_OVERRIDE;
+
+      virtual int RequestInformation(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      LineSource( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      double Point1[ 3 ];
+      double Point2[ 3 ];
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__LineSource__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/MPR3DActors.cxx b/lib/cpExtensions/Visualization/MPR3DActors.cxx
new file mode 100644 (file)
index 0000000..b3f4700
--- /dev/null
@@ -0,0 +1,186 @@
+#include <cpExtensions/Visualization/MPR3DActors.h>
+#include <cpExtensions/Visualization/ImageSliceActors.h>
+#include <cpExtensions/Visualization/LUTImageActor.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+#include <vtkActor.h>
+#include <vtkImageProperty.h>
+#include <vtkPolyData.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::MPR3DActors::
+Self* cpExtensions::Visualization::MPR3DActors::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkImageData* cpExtensions::Visualization::MPR3DActors::
+GetImage( )
+{
+  return( this->m_Slices[ 0 ]->GetImage( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkImageData* cpExtensions::Visualization::MPR3DActors::
+GetImage( ) const
+{
+  return( this->m_Slices[ 0 ]->GetImage( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+WindowLevelImageActor* cpExtensions::Visualization::MPR3DActors::
+GetWindowLevelImageActor( int o )
+{
+  return( this->m_Slices[ o % 3 ]->GetWindowLevelImageActor( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+WindowLevelImageActor* cpExtensions::Visualization::MPR3DActors::
+GetWindowLevelImageActor( int o ) const
+{
+  return( this->m_Slices[ o % 3 ]->GetWindowLevelImageActor( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+LUTImageActor* cpExtensions::Visualization::MPR3DActors::
+GetLUTImageActor( int o )
+{
+  return( this->m_Slices[ o % 3 ]->GetLUTImageActor( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+LUTImageActor* cpExtensions::Visualization::MPR3DActors::
+GetLUTImageActor( int o ) const
+{
+  return( this->m_Slices[ o % 3 ]->GetLUTImageActor( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::
+ImageOutlineActor* cpExtensions::Visualization::MPR3DActors::
+GetImageOutlineActor( int o )
+{
+  return( this->m_Slices[ o % 3 ]->GetImageOutlineActor( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpExtensions::Visualization::
+ImageOutlineActor* cpExtensions::Visualization::MPR3DActors::
+GetImageOutlineActor( int o ) const
+{
+  return( this->m_Slices[ o % 3 ]->GetImageOutlineActor( ) );
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::MPR3DActors::
+GetSliceNumber( int o ) const
+{
+  return( this->m_Slices[ o % 3 ]->GetSliceNumber( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPR3DActors::
+SetImage( vtkImageData* image )
+{
+  this->RemoveAllItems( );
+  for( int i = 0; i < 3; ++i )
+  {
+    this->m_Slices[ i ]->SetImage( image, i );
+    this->m_Slices[ i ]->InitTraversal( );
+    while( vtkProp* p = this->m_Slices[ i ]->GetNextProp( ) )
+      this->AddItem( p );
+    
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpExtensions::Visualization::MPR3DActors::
+AddLUTImage( vtkImageData* image )
+{
+  unsigned int res = 0;
+  for( int i = 0; i < 3; ++i )
+  {
+    res = this->m_Slices[ i ]->AddLUTImage( image );
+    this->AddItem( this->m_Slices[ i ]->GetLUTImageActor( ) );
+
+  } // rof
+  return( res );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPR3DActors::
+SetSliceNumber( int o, int s )
+{
+  this->m_Slices[ o % 3 ]->SetSliceNumber( s );
+}
+
+// -------------------------------------------------------------------------
+vtkActor* cpExtensions::Visualization::MPR3DActors::
+AddMesh( vtkPolyData* mesh )
+{
+  TMeshActor actor;
+  actor.SetMesh( mesh );
+  this->m_Meshes[ mesh ] = actor;
+  this->AddItem( actor.GetActor( ) );
+  return( actor.GetActor( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPR3DActors::
+SetScalarRange( double r[ 2 ] )
+{
+  this->m_Slices[ 0 ]->GetWindowLevelImageActor( )->SetRange( r );
+  this->m_Slices[ 1 ]->GetWindowLevelImageActor( )->SetRange( r );
+  this->m_Slices[ 2 ]->GetWindowLevelImageActor( )->SetRange( r );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPR3DActors::
+SetWindowLevel( double wl[ 2 ] )
+{
+  this->m_Slices[ 0 ]->GetWindowLevelImageActor( )->SetWindowLevel( wl );
+  this->m_Slices[ 1 ]->GetWindowLevelImageActor( )->SetWindowLevel( wl );
+  this->m_Slices[ 2 ]->GetWindowLevelImageActor( )->SetWindowLevel( wl );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPR3DActors::
+SetImageOpacity( double o )
+{
+  this->m_Slices[ 0 ]->GetWindowLevelImageActor( )->
+    GetProperty( )->SetOpacity( o );
+  this->m_Slices[ 1 ]->GetWindowLevelImageActor( )->
+    GetProperty( )->SetOpacity( o );
+  this->m_Slices[ 2 ]->GetWindowLevelImageActor( )->
+    GetProperty( )->SetOpacity( o );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MPR3DActors::
+SetImageInterpolation( unsigned char i )
+{
+  // TODO
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::MPR3DActors::
+MPR3DActors( )
+  : Superclass( )
+{
+  this->m_Slices[ 0 ] = vtkSmartPointer< ImageSliceActors >::New( );
+  this->m_Slices[ 1 ] = vtkSmartPointer< ImageSliceActors >::New( );
+  this->m_Slices[ 2 ] = vtkSmartPointer< ImageSliceActors >::New( );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::MPR3DActors::
+~MPR3DActors( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/MPR3DActors.h b/lib/cpExtensions/Visualization/MPR3DActors.h
new file mode 100644 (file)
index 0000000..07c41ba
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef __cpExtensions__Visualization__MPR3DActors__h__
+#define __cpExtensions__Visualization__MPR3DActors__h__
+
+#include <cpExtensions/Config.h>
+#include <cpExtensions/Visualization/MeshActor.h>
+#include <vtkPropCollection.h>
+#include <vtkSmartPointer.h>
+#include <map>
+
+// -------------------------------------------------------------------------
+class vtkActor;
+class vtkImageData;
+class vtkPolyData;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    class ImageOutlineActor;
+    class ImageSliceActors;
+    class LUTImageActor;
+    class WindowLevelImageActor;
+
+    /**
+     */
+    class cpExtensions_EXPORT MPR3DActors
+      : public vtkPropCollection
+    {
+    public:
+      typedef MPR3DActors Self;
+
+      typedef cpExtensions::Visualization::MeshActor TMeshActor;
+
+    public:
+      vtkTypeMacro( MPR3DActors, vtkPropCollection );
+
+    public:
+      static Self* New( );
+
+      vtkImageData* GetImage( );
+      const vtkImageData* GetImage( ) const;
+
+      WindowLevelImageActor* GetWindowLevelImageActor( int o );
+      const WindowLevelImageActor* GetWindowLevelImageActor( int o ) const;
+
+      LUTImageActor* GetLUTImageActor( int o );
+      const LUTImageActor* GetLUTImageActor( int o ) const;
+
+      ImageOutlineActor* GetImageOutlineActor( int o );
+      const ImageOutlineActor* GetImageOutlineActor( int o ) const;
+
+      int GetSliceNumber( int o ) const;
+      virtual void SetImage( vtkImageData* image );
+      virtual unsigned int AddLUTImage( vtkImageData* image );
+      virtual void SetSliceNumber( int o, int s );
+
+      virtual vtkActor* AddMesh( vtkPolyData* mesh );
+
+      void SetScalarRange( double r[ 2 ] );
+      void SetWindowLevel( double wl[ 2 ] );
+      void SetImageOpacity( double o );
+      void SetImageInterpolation( unsigned char i );
+
+    protected:
+      MPR3DActors( );
+      virtual ~MPR3DActors( );
+
+    private:
+      // Purposely not implemented
+      MPR3DActors( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      vtkSmartPointer< ImageSliceActors > m_Slices[ 3 ];
+      std::map< vtkSmartPointer< vtkPolyData >, TMeshActor > m_Meshes;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__MPR3DActors__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/MeshActor.cxx b/lib/cpExtensions/Visualization/MeshActor.cxx
new file mode 100644 (file)
index 0000000..ca6f1f9
--- /dev/null
@@ -0,0 +1,56 @@
+#include <cpExtensions/Visualization/MeshActor.h>
+
+#include <vtkActor.h>
+#include <vtkPolyData.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkQuadricLODActor.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::MeshActor::
+MeshActor( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::MeshActor::
+~MeshActor( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::MeshActor::
+SetMesh( vtkPolyData* mesh )
+{
+  static unsigned long MAX = std::numeric_limits< unsigned short >::max( );
+
+  this->m_Mesh = mesh;
+  this->m_Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( );
+  unsigned long c = mesh->GetNumberOfPolys( ) + mesh->GetNumberOfStrips( );
+  if( c >= MAX )
+  {
+    vtkSmartPointer< vtkQuadricLODActor > q =
+      vtkSmartPointer< vtkQuadricLODActor >::New( );
+    q->DeferLODConstructionOff( );
+    this->m_Actor = q.GetPointer( );
+  }
+  else
+    this->m_Actor = vtkSmartPointer< vtkActor >::New( );
+  this->m_Mapper->SetInputData( this->m_Mesh );
+  this->m_Actor->SetMapper( this->m_Mapper );
+}
+
+// -------------------------------------------------------------------------
+vtkActor* cpExtensions::Visualization::MeshActor::
+GetActor( )
+{
+  return( this->m_Actor.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkActor* cpExtensions::Visualization::MeshActor::
+GetActor( ) const
+{
+  return( this->m_Actor.GetPointer( ) );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/MeshActor.h b/lib/cpExtensions/Visualization/MeshActor.h
new file mode 100644 (file)
index 0000000..c26b8d7
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __cpExtensions__Visualization__MeshActor__h__
+#define __cpExtensions__Visualization__MeshActor__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkActor;
+class vtkPolyData;
+class vtkPolyDataMapper;
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT MeshActor
+    {
+    public:
+      typedef MeshActor Self;
+
+    public:
+      MeshActor( );
+      virtual ~MeshActor( );
+
+      void SetMesh( vtkPolyData* mesh );
+
+      vtkActor* GetActor( );
+      const vtkActor* GetActor( ) const;
+
+    protected:
+      vtkSmartPointer< vtkPolyData >       m_Mesh;
+      vtkSmartPointer< vtkPolyDataMapper > m_Mapper;
+      vtkSmartPointer< vtkActor >          m_Actor;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__MeshActor__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/OutlineSource.cxx b/lib/cpExtensions/Visualization/OutlineSource.cxx
new file mode 100644 (file)
index 0000000..a00a221
--- /dev/null
@@ -0,0 +1,50 @@
+#include <cpExtensions/Visualization/OutlineSource.h>
+#include <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::OutlineSource::
+Self* cpExtensions::Visualization::OutlineSource::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::OutlineSource::
+OutlineSource( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::OutlineSource::
+~OutlineSource( )
+{
+}
+
+// -------------------------------------------------------------------------
+int cpExtensions::Visualization::OutlineSource::
+RequestData(
+  vtkInformation* request,
+  vtkInformationVector** inputVector,
+  vtkInformationVector* outputVector
+  )
+{
+  int r = this->Superclass::RequestData( request, inputVector, outputVector );
+
+  // Complete polydatas to avoid bizarre rendering errors (multi-thread)
+  vtkInformation *outInfo = outputVector->GetInformationObject( 0 );
+  vtkPolyData *output = vtkPolyData::SafeDownCast(
+    outInfo->Get( vtkDataObject::DATA_OBJECT( ) )
+    );
+  output->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  output->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  if( this->GenerateFaces != 1 )
+    output->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  return( r );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/OutlineSource.h b/lib/cpExtensions/Visualization/OutlineSource.h
new file mode 100644 (file)
index 0000000..295a5b5
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __cpExtensions__Visualization__OutlineSource__h__
+#define __cpExtensions__Visualization__OutlineSource__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkOutlineSource.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT OutlineSource
+      : public vtkOutlineSource
+    {
+    public:
+      typedef OutlineSource Self;
+
+    public:
+      vtkTypeMacro( OutlineSource, vtkOutlineSource );
+
+    public:
+      static Self* New( );
+
+    protected:
+      OutlineSource( );
+      virtual ~OutlineSource( );
+
+      virtual int RequestData(
+        vtkInformation* request,
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector
+        ) cpExtensions_OVERRIDE;
+
+    private:
+      // Purposely not implemented
+      OutlineSource( const Self& );
+      Self& operator=( const Self& );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__OutlineSource__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.cxx b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.cxx
new file mode 100644 (file)
index 0000000..c97fac7
--- /dev/null
@@ -0,0 +1,131 @@
+#include <cpExtensions/Visualization/PolyLineParametricPathToPolyData.h>
+
+#include <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+typename
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+Self*
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+const typename
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+TPolyLine*
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+GetInput( ) const
+{
+  return( this->m_PolyLine );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+void
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+SetInput( const TPolyLine* pl )
+{
+  if( this->m_PolyLine != pl )
+  {
+    this->m_PolyLine = pl;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+PolyLineParametricPathToPolyData( )
+  : vtkPolyDataAlgorithm( ),
+    m_PolyLine( NULL )
+{
+  this->SetNumberOfInputPorts( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+~PolyLineParametricPathToPolyData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+int
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+RequestData(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  static const unsigned int dim = _TPolyLine::PathDimension;
+
+  if( this->m_PolyLine == NULL )
+    return( 0 );
+
+  // Get output
+  vtkInformation* info = output->GetInformationObject( 0 );
+  vtkPolyData* out = vtkPolyData::SafeDownCast(
+    info->Get( vtkDataObject::DATA_OBJECT( ) )
+    );
+
+  // Prepare data
+  out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+  out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  vtkPoints* points = out->GetPoints( );
+  vtkCellArray* lines = out->GetLines( );
+
+  // Get data
+  for( unsigned long i = 0; i < this->m_PolyLine->GetSize( ); ++i )
+  {
+    typename _TPolyLine::TPoint pnt = this->m_PolyLine->GetPoint( i );
+    if( dim == 1 )      points->InsertNextPoint( pnt[ 0 ], 0, 0 );
+    else if( dim == 2 ) points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], 0 );
+    else                points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] );
+    if( i > 0 )
+    {
+      lines->InsertNextCell( 2 );
+      lines->InsertCellPoint( i - 1 );
+      lines->InsertCellPoint( i );
+
+    } // fi
+
+  } // rof
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLine >
+int
+cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >::
+RequestInformation(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+#include <cpExtensions/DataStructures/PolyLineParametricPath.h>
+
+template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 1 > >;
+template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 2 > >;
+template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 3 > >;
+template class cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< 4 > >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h
new file mode 100644 (file)
index 0000000..8e73108
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __cpExtensions__Visualization__PolyLineParametricPathToPolyData__h__
+#define __cpExtensions__Visualization__PolyLineParametricPathToPolyData__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPolyDataAlgorithm.h>
+
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    template< class _TPolyLine >
+    class cpExtensions_EXPORT PolyLineParametricPathToPolyData
+      : public vtkPolyDataAlgorithm
+    {
+    public:
+      typedef PolyLineParametricPathToPolyData Self;
+      typedef _TPolyLine TPolyLine;
+
+    public:
+      vtkTypeMacro( PolyLineParametricPathToPolyData, vtkPolyDataAlgorithm );
+
+    public:
+      static Self* New( );
+
+      const TPolyLine* GetInput( ) const;
+      void SetInput( const TPolyLine* pl );
+
+    protected:
+      PolyLineParametricPathToPolyData( );
+      virtual ~PolyLineParametricPathToPolyData( );
+
+      int RequestData(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+      int RequestInformation(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+
+    private:
+      // Purposely not implemented
+      PolyLineParametricPathToPolyData( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      const TPolyLine* m_PolyLine;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif //  __cpExtensions__Visualization__PolyLineParametricPathToPolyData__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.cxx b/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.cxx
new file mode 100644 (file)
index 0000000..697807f
--- /dev/null
@@ -0,0 +1,119 @@
+#include <cpExtensions/Visualization/Simple3DCurveToPolyData.h>
+
+#include <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+typename cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+Self* cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+const typename cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+TCurve* cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+GetInput( ) const
+{
+  return( this->m_Curve );
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+void
+cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+SetInput( const TCurve* c )
+{
+  if( this->m_Curve != c )
+  {
+    this->m_Curve = c;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+Simple3DCurveToPolyData( )
+  : vtkPolyDataAlgorithm( ),
+    m_Curve( NULL )
+{
+  this->SetNumberOfInputPorts( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+~Simple3DCurveToPolyData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+int cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+RequestData(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  if( this->m_Curve == NULL )
+    return( 0 );
+
+  // Get output
+  vtkInformation* info = output->GetInformationObject( 0 );
+  vtkPolyData* out = vtkPolyData::SafeDownCast(
+    info->Get( vtkDataObject::DATA_OBJECT( ) )
+    );
+
+  // Prepare data
+  out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+  out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  vtkPoints* points = out->GetPoints( );
+  vtkCellArray* lines = out->GetLines( );
+
+  // Get data
+  for( unsigned long i = 0; i < this->m_Curve->GetNumberOfPoints( ); ++i )
+  {
+    typename _TCurve::TPoint pnt = this->m_Curve->GetPoint( i );
+    points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] );
+    if( i > 0 )
+    {
+      lines->InsertNextCell( 2 );
+      lines->InsertCellPoint( i - 1 );
+      lines->InsertCellPoint( i );
+
+    } // fi
+
+  } // rof
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+int cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >::
+RequestInformation(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+#include <cpExtensions/DataStructures/Simple3DCurve.h>
+
+template class cpExtensions::Visualization::Simple3DCurveToPolyData< cpExtensions::DataStructures::Simple3DCurve< float > >;
+template class cpExtensions::Visualization::Simple3DCurveToPolyData< cpExtensions::DataStructures::Simple3DCurve< double > >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.h b/lib/cpExtensions/Visualization/Simple3DCurveToPolyData.h
new file mode 100644 (file)
index 0000000..7407cea
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __cpExtensions__Visualization__Simple3DCurveToPolyData__h__
+#define __cpExtensions__Visualization__Simple3DCurveToPolyData__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPolyDataAlgorithm.h>
+
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    template< class _TCurve >
+    class cpExtensions_EXPORT Simple3DCurveToPolyData
+      : public vtkPolyDataAlgorithm
+    {
+    public:
+      typedef Simple3DCurveToPolyData Self;
+      typedef _TCurve TCurve;
+
+    public:
+      vtkTypeMacro( Simple3DCurveToPolyData, vtkPolyDataAlgorithm );
+
+    public:
+      static Self* New( );
+
+      const TCurve* GetInput( ) const;
+      void SetInput( const TCurve* c );
+
+    protected:
+      Simple3DCurveToPolyData( );
+      virtual ~Simple3DCurveToPolyData( );
+
+      int RequestData(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+      int RequestInformation(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+
+    private:
+      // Purposely not implemented
+      Simple3DCurveToPolyData( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      const TCurve* m_Curve;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif //  __cpExtensions__Visualization__Simple3DCurveToPolyData__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/SkeletonToPolyData.cxx b/lib/cpExtensions/Visualization/SkeletonToPolyData.cxx
new file mode 100644 (file)
index 0000000..5aa7d20
--- /dev/null
@@ -0,0 +1,147 @@
+#include <cpExtensions/Visualization/SkeletonToPolyData.h>
+
+#include <vtkCellArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+typename cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+Self* cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+const typename
+cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+TSkeleton* cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+GetInput( ) const
+{
+  return( this->m_Skeleton );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+SetInput( const TSkeleton* sk )
+{
+  if( this->m_Skeleton != sk )
+  {
+    this->m_Skeleton = sk;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+SkeletonToPolyData( )
+  : vtkPolyDataAlgorithm( ),
+    m_Skeleton( NULL )
+{
+  this->SetNumberOfInputPorts( 0 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+~SkeletonToPolyData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+int cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+RequestData(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  typedef typename _TSkeleton::TPath _TPath;
+  static const unsigned int dim = _TPath::PathDimension;
+
+  if( this->m_Skeleton == NULL )
+    return( 0 );
+
+  // Get output
+  vtkInformation* info = output->GetInformationObject( 0 );
+  vtkPolyData* out = vtkPolyData::SafeDownCast(
+    info->Get( vtkDataObject::DATA_OBJECT( ) )
+    );
+
+  // Prepare data
+  out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+  out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  vtkPoints* points = out->GetPoints( );
+  vtkCellArray* lines = out->GetLines( );
+
+  // Assign all data
+  auto mIt = this->m_Skeleton->BeginEdgesRows( );
+  for( ; mIt != this->m_Skeleton->EndEdgesRows( ); ++mIt )
+  {
+    // TODO: mIt->first; --> this is the row index. <--
+    auto rIt = mIt->second.begin( );
+    for( ; rIt != mIt->second.end( ); ++rIt )
+    {
+      // TODO: rIt->first;  --> this is the column index.
+      auto eIt = rIt->second.begin( );
+      for( ; eIt != rIt->second.end( ); ++eIt )
+      {
+        _TPath* path = *eIt;
+        for( unsigned long i = 0; i < path->GetSize( ); ++i )
+        {
+          auto pnt = path->GetPoint( i );
+          if( dim == 1 )
+            points->InsertNextPoint( pnt[ 0 ], 0, 0 );
+          else if( dim == 2 )
+            points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], 0 );
+          else
+            points->InsertNextPoint( pnt[ 0 ], pnt[ 1 ], pnt[ 2 ] );
+          if( i > 0 )
+          {
+            lines->InsertNextCell( 2 );
+            lines->InsertCellPoint( points->GetNumberOfPoints( ) - 2 );
+            lines->InsertCellPoint( points->GetNumberOfPoints( ) - 1 );
+
+          } // fi
+
+        } // rof
+
+      } // rof
+
+    } // rof
+
+  } // rof
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+int cpExtensions::Visualization::SkeletonToPolyData< _TSkeleton >::
+RequestInformation(
+  vtkInformation* information,
+  vtkInformationVector** input,
+  vtkInformationVector* output
+  )
+{
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+#include <cpExtensions/DataStructures/Skeleton.h>
+
+template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 1 > >;
+template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 2 > >;
+template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 3 > >;
+template class cpExtensions::Visualization::SkeletonToPolyData< cpExtensions::DataStructures::Skeleton< 4 > >;
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/SkeletonToPolyData.h b/lib/cpExtensions/Visualization/SkeletonToPolyData.h
new file mode 100644 (file)
index 0000000..1cef407
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __cpExtensions__Visualization__SkeletonToPolyData__h__
+#define __cpExtensions__Visualization__SkeletonToPolyData__h__
+
+#include <cpExtensions/Config.h>
+#include <vtkPolyDataAlgorithm.h>
+
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    template< class _TSkeleton >
+    class cpExtensions_EXPORT SkeletonToPolyData
+      : public vtkPolyDataAlgorithm
+    {
+    public:
+      typedef SkeletonToPolyData Self;
+      typedef _TSkeleton TSkeleton;
+
+    public:
+      vtkTypeMacro( SkeletonToPolyData, vtkPolyDataAlgorithm );
+
+    public:
+      static Self* New( );
+
+      const TSkeleton* GetInput( ) const;
+      void SetInput( const TSkeleton* sk );
+
+    protected:
+      SkeletonToPolyData( );
+      virtual ~SkeletonToPolyData( );
+
+      int RequestData(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+      int RequestInformation(
+        vtkInformation* information,
+        vtkInformationVector** input,
+        vtkInformationVector* output
+        );
+
+    private:
+      // Purposely not implemented
+      SkeletonToPolyData( const Self& );
+      void operator=( const Self& );
+
+    protected:
+      const TSkeleton* m_Skeleton;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif //  __cpExtensions__Visualization__SkeletonToPolyData__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/WindowLevelImageActor.cxx b/lib/cpExtensions/Visualization/WindowLevelImageActor.cxx
new file mode 100644 (file)
index 0000000..c7cbbd4
--- /dev/null
@@ -0,0 +1,200 @@
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+#include <cpExtensions/Visualization/ImageSliceMapper.h>
+
+#include <vtkImageData.h>
+#include <vtkImageProperty.h>
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::WindowLevelImageActor::
+Self* cpExtensions::Visualization::WindowLevelImageActor::
+New( )
+{
+  return( new Self( ) );
+}
+
+// -------------------------------------------------------------------------
+vtkImageData* cpExtensions::Visualization::WindowLevelImageActor::
+GetImage( )
+{
+  return( this->m_Mapper->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+const vtkImageData* cpExtensions::Visualization::WindowLevelImageActor::
+GetImage( ) const
+{
+  return( this->m_Mapper->GetInput( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetImage( vtkImageData* image )
+{
+  this->m_Mapper->SetInputData( image );
+  this->ResetRange( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::Visualization::WindowLevelImageActor::
+GetLevel( ) const
+{
+  Self* self = const_cast< Self* >( this );
+  return( self->GetProperty( )->GetColorLevel( ) );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::Visualization::WindowLevelImageActor::
+GetWindow( ) const
+{
+  Self* self = const_cast< Self* >( this );
+  return( self->GetProperty( )->GetColorWindow( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+GetWindowLevel( double wl[ 2 ] ) const
+{
+  Self* self = const_cast< Self* >( this );
+  wl[ 0 ] = self->GetProperty( )->GetColorWindow( );
+  wl[ 1 ] = self->GetProperty( )->GetColorLevel( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+ResetWindowLevel( )
+{
+  this->SetWindowLevel(
+    ( this->m_Range[ 1 ] - this->m_Range[ 0 ] ),
+    ( this->m_Range[ 1 ] + this->m_Range[ 0 ] ) / double( 2 )
+    );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetLevel( double l )
+{
+  double ol = this->GetProperty( )->GetColorLevel( );
+  if( l != ol && this->m_Range[ 0 ] <= l && l <= this->m_Range[ 1 ] )
+  {
+    this->GetProperty( )->SetColorLevel( l );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetWindow( double w )
+{
+  double mw = this->m_Range[ 1 ] - this->m_Range[ 0 ];
+  double ow = this->GetProperty( )->GetColorWindow( );
+  if( w != ow && double( 0 ) <= w && w <= mw )
+  {
+    this->GetProperty( )->SetColorWindow( w );
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetWindowLevel( double w, double l )
+{
+  this->SetWindow( w );
+  this->SetLevel( l );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetWindowLevel( double wl[ 2 ] )
+{
+  this->SetWindow( wl[ 0 ] );
+  this->SetLevel( wl[ 1 ] );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::Visualization::WindowLevelImageActor::
+GetMinimum( ) const
+{
+  return( this->m_Range[ 0 ] );
+}
+
+// -------------------------------------------------------------------------
+double cpExtensions::Visualization::WindowLevelImageActor::
+GetMaximum( ) const
+{
+  return( this->m_Range[ 0 ] );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+GetRange( double r[ 2 ] ) const
+{
+  r[ 0 ] = this->m_Range[ 0 ];
+  r[ 1 ] = this->m_Range[ 1 ];
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+ResetRange( )
+{
+  this->GetImage( )->GetScalarRange( this->m_Range );
+  this->ResetWindowLevel( );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetMinimum( double a )
+{
+  if( this->m_Range[ 0 ] != a )
+  {
+    this->m_Range[ 0 ] = a;
+    this->ResetWindowLevel( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetMaximum( double b )
+{
+  if( this->m_Range[ 1 ] != b )
+  {
+    this->m_Range[ 1 ] = b;
+    this->ResetWindowLevel( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetRange( double a, double b )
+{
+  this->SetMinimum( a );
+  this->SetMaximum( b );
+}
+
+// -------------------------------------------------------------------------
+void cpExtensions::Visualization::WindowLevelImageActor::
+SetRange( double r[ 2 ] )
+{
+  this->SetMinimum( r[ 0 ] );
+  this->SetMaximum( r[ 1 ] );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::WindowLevelImageActor::
+WindowLevelImageActor( )
+  : Superclass( )
+{
+  this->m_Range[ 0 ] = this->m_Range[ 1 ] = double( 0 );
+}
+
+// -------------------------------------------------------------------------
+cpExtensions::Visualization::WindowLevelImageActor::
+~WindowLevelImageActor( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpExtensions/Visualization/WindowLevelImageActor.h b/lib/cpExtensions/Visualization/WindowLevelImageActor.h
new file mode 100644 (file)
index 0000000..8af3943
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __cpExtensions__Visualization__WindowLevelImageActor__h__
+#define __cpExtensions__Visualization__WindowLevelImageActor__h__
+
+#include <cpExtensions/Visualization/ImageActor.h>
+
+// -------------------------------------------------------------------------
+namespace cpExtensions
+{
+  namespace Visualization
+  {
+    /**
+     */
+    class cpExtensions_EXPORT WindowLevelImageActor
+      : public ImageActor
+    {
+    public:
+      typedef WindowLevelImageActor Self;
+
+    public:
+      vtkTypeMacro( WindowLevelImageActor, ImageActor );
+
+    public:
+      static Self* New( );
+
+      vtkImageData* GetImage( );
+      const vtkImageData* GetImage( ) const;
+      void SetImage( vtkImageData* image );
+
+      double GetLevel( ) const;
+      double GetWindow( ) const;
+      void GetWindowLevel( double wl[ 2 ] ) const;
+      void ResetWindowLevel( );
+      void SetLevel( double l );
+      void SetWindow( double w );
+      void SetWindowLevel( double w, double l );
+      void SetWindowLevel( double wl[ 2 ] );
+
+      double GetMinimum( ) const;
+      double GetMaximum( ) const;
+      void GetRange( double r[ 2 ] ) const;
+      void ResetRange( );
+      void SetMinimum( double a );
+      void SetMaximum( double b );
+      void SetRange( double a, double b );
+      void SetRange( double r[ 2 ] );
+
+    protected:
+      WindowLevelImageActor( );
+      virtual ~WindowLevelImageActor( );
+
+    private:
+      // Purposely not implemented
+      WindowLevelImageActor( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      double m_Range[ 2 ];
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpExtensions__Visualization__WindowLevelImageActor__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/BaseObjects/ITKBaseObjects.i b/lib/cpInstances/BaseObjects/ITKBaseObjects.i
new file mode 100644 (file)
index 0000000..c74dfa2
--- /dev/null
@@ -0,0 +1,41 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define fadims=1;2;3;4;6
+tinclude itkFixedArray:h|hxx
+instances itk::FixedArray< #scalar_types#, #fadims# >
+
+define arrays=Array2D;Array;RGBPixel;RGBAPixel
+tinclude itk#arrays#:h|hxx
+instances itk::#arrays#< #scalar_types# >
+
+define vectors=CovariantVector;Point;Vector;SymmetricSecondRankTensor
+tinclude itk#vectors#:h|hxx
+tinclude itkVectorContainer:h|hxx
+instances itk::#vectors#< #real_types#, #pdims# >
+instances itk::VectorContainer< unsigned long, itk::#vectors#< #real_types#, #pdims# > >
+instances itk::VectorContainer< unsigned long, #scalar_types# >
+
+tinclude itkDiffusionTensor3D:h|hxx
+instances itk::DiffusionTensor3D< #real_types# >
+
+cinclude set
+instances itk::VectorContainer< unsigned long, std::set< #scalar_types# > >
+
+define cout_vectors=FixedArray;Point;Vector
+minstances #_export_# std::ostream& itk::operator<< < #real_types#, #pdims# >( std::ostream& a, itk::#cout_vectors#< #real_types#, #pdims# > const& b )
+
+define matrices=Matrix
+tinclude itk#matrices#:h|hxx
+instances itk::#matrices#< #real_types#, #pdims#, #pdims# >
+
+define decorated=std::string;#scalar_types#
+tinclude itkSimpleDataObjectDecorator:h|hxx
+instances itk::SimpleDataObjectDecorator< #decorated# >
+
+tinclude itkVariableLengthVector:h|hxx
+instances itk::VariableLengthVector< #scalar_types# >
+
+tinclude itkSymmetricEigenAnalysis:h|hxx
+instances itk::SymmetricEigenAnalysis< itk::Matrix< #real_types#, #pdims#, #pdims# >, itk::FixedArray< #real_types#, #pdims# >, itk::Matrix< #real_types#, #pdims#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/BaseObjects/ITKBoundingBoxes.i b/lib/cpInstances/BaseObjects/ITKBoundingBoxes.i
new file mode 100644 (file)
index 0000000..9bf736e
--- /dev/null
@@ -0,0 +1,6 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude itkBoundingBox:h|hxx
+instances itk::BoundingBox< unsigned long, #pdims#, #real_types#, itk::VectorContainer< unsigned long, itk::Point< #real_types#, #pdims# > > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/BaseObjects/ITKTransforms.i b/lib/cpInstances/BaseObjects/ITKTransforms.i
new file mode 100644 (file)
index 0000000..bc6b05d
--- /dev/null
@@ -0,0 +1,18 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define tr=AffineTransform
+
+tinclude itkOptimizerParameters:h|hxx
+tinclude itkTransform:h|hxx
+tinclude itkMatrixOffsetTransformBase:h|hxx
+tinclude itk#tr#:h|hxx
+tinclude itkDataObjectDecorator:h|hxx
+
+instances itk::OptimizerParameters< #real_types# >
+instances itk::MatrixOffsetTransformBase< #real_types#, #pdims#, #pdims# >
+instances itk::Transform< #real_types#, #pdims#, #pdims# >
+instances itk::#tr#< #real_types#, #pdims# >
+instances itk::DataObjectDecorator< itk::Transform< #real_types#, #pdims#, #pdims# > >
+instances itk::DataObjectDecorator< itk::#tr#< #real_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/CMakeLists.txt b/lib/cpInstances/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2c86239
--- /dev/null
@@ -0,0 +1,50 @@
+## ===========================================
+## == Directories containing instantiations ==
+## ===========================================
+
+SET(
+  _directories
+  BaseObjects
+  Images
+  Geometries
+  Extensions
+  )
+
+## =========================
+## == Real instantiations ==
+## =========================
+
+SET(_pfx cpInstances_)
+
+INCLUDE_DIRECTORIES(
+  ${CMAKE_CURRENT_SOURCE_DIR}/BaseObjects
+  ${CMAKE_CURRENT_BINARY_DIR}/BaseObjects
+  ${CMAKE_CURRENT_SOURCE_DIR}/Images
+  ${CMAKE_CURRENT_BINARY_DIR}/Images
+  )
+FOREACH(_dir ${_directories})
+  cpPlugins_BuildLibrary(${_pfx}${_dir} SHARED ${_dir})
+ENDFOREACH(_dir)
+
+## ===========
+## == Links ==
+## ===========
+
+TARGET_LINK_LIBRARIES(${_pfx}BaseObjects ${ITK_LIBRARIES})
+TARGET_LINK_LIBRARIES(${_pfx}Images ${_pfx}BaseObjects ${VTK_LIBRARIES})
+TARGET_LINK_LIBRARIES(${_pfx}Geometries ${_pfx}BaseObjects)
+TARGET_LINK_LIBRARIES(${_pfx}Extensions cpExtensions ${_pfx}Geometries)
+
+## ==========================
+## == Generic data objects ==
+## ==========================
+
+cpPlugins_BuildLibrary(cpPluginsDataObjects SHARED DataObjects)
+TARGET_LINK_LIBRARIES(
+  cpPluginsDataObjects
+  cpExtensions
+  cpPlugins
+  ${_pfx}Images ${_pfx}Geometries ${_pfx}Extensions
+  )
+
+## eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/BoundingBox.cxx b/lib/cpInstances/DataObjects/BoundingBox.cxx
new file mode 100644 (file)
index 0000000..ea05810
--- /dev/null
@@ -0,0 +1,93 @@
+#include <cpInstances/DataObjects/BoundingBox.h>
+#include <limits>
+#include <vtkDataSet.h>
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::BoundingBox::
+SetDataObject( DataObject* o )
+{
+  auto i = o->GetITK< itk::LightObject >( );
+  auto v = o->GetVTK< vtkObjectBase >( );
+  if( v != NULL )      this->SetVTK( v );
+  else if( i != NULL ) this->SetITK( i );
+  this->_UpdateVTK( );
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::BoundingBox::
+Copy( Self* other )
+{
+  this->m_Points[ 0 ] = other->m_Points[ 0 ];
+  this->m_Points[ 1 ] = other->m_Points[ 1 ];
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::BoundingBox::
+Blend( Self* other )
+{
+  if( this->m_Points[ 0 ].size( ) < other->m_Points[ 0 ].size( ) )
+    this->m_Points[ 0 ].resize(
+      other->m_Points[ 0 ].size( ),
+      std::numeric_limits< double >::max( )
+      );
+  if( this->m_Points[ 1 ].size( ) < other->m_Points[ 1 ].size( ) )
+    this->m_Points[ 1 ].resize(
+      other->m_Points[ 1 ].size( ),
+      -std::numeric_limits< double >::max( )
+      );
+  for( unsigned int d = 0; d < this->m_Points[ 0 ].size( ); ++d )
+    if( other->m_Points[ 0 ][ d ] < this->m_Points[ 0 ][ d ] )
+      this->m_Points[ 0 ][ d ] = other->m_Points[ 0 ][ d ];
+  for( unsigned int d = 0; d < this->m_Points[ 1 ].size( ); ++d )
+    if( other->m_Points[ 1 ][ d ] > this->m_Points[ 1 ][ d ] )
+      this->m_Points[ 1 ][ d ] = other->m_Points[ 1 ][ d ];
+  this->Modified( );
+  this->_UpdateVTK( );
+}
+
+// -------------------------------------------------------------------------
+cpInstances::DataObjects::BoundingBox::
+BoundingBox( )
+  : Superclass( )
+{
+  this->m_Points[ 0 ].push_back( double( 0 ) );
+  this->m_Points[ 1 ].push_back( double( 0 ) );
+  this->m_Outline = vtkSmartPointer< vtkOutlineSource >::New( );
+  this->_UpdateVTK( );
+}
+
+// -------------------------------------------------------------------------
+cpInstances::DataObjects::BoundingBox::
+~BoundingBox( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::BoundingBox::
+_UpdateVTK( )
+{
+  auto dobj = this->GetVTK< vtkDataSet >( );
+  if( dobj == NULL )
+    return;
+
+  // Get bounds
+  double bounds[ 6 ];
+  dobj->GetBounds( bounds );
+
+  this->m_Points[ 0 ].clear( );
+  this->m_Points[ 1 ].clear( );
+  this->m_Points[ 0 ].push_back( bounds[ 0 ] );
+  this->m_Points[ 0 ].push_back( bounds[ 2 ] );
+  this->m_Points[ 0 ].push_back( bounds[ 4 ] );
+  this->m_Points[ 1 ].push_back( bounds[ 1 ] );
+  this->m_Points[ 1 ].push_back( bounds[ 3 ] );
+  this->m_Points[ 1 ].push_back( bounds[ 5 ] );
+
+  // Update vtk objects
+  this->m_Outline->SetBounds( bounds );
+  this->m_Outline->Update( );
+  this->m_VTK = this->m_Outline->GetOutput( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/BoundingBox.h b/lib/cpInstances/DataObjects/BoundingBox.h
new file mode 100644 (file)
index 0000000..dfe1300
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __cpInstances__BoundingBox__h__
+#define __cpInstances__BoundingBox__h__
+
+#define ITK_MANUAL_INSTANTIATION
+#include <cpInstances/cpPluginsDataObjects_Export.h>
+#include <vector>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <vtkOutlineSource.h>
+#include <vtkSmartPointer.h>
+
+namespace cpInstances
+{
+  namespace DataObjects
+  {
+    /**
+     */
+    class cpPluginsDataObjects_EXPORT BoundingBox
+      : public cpPlugins::Pipeline::DataObject
+    {
+    public:
+      typedef BoundingBox                     Self;
+      typedef cpPlugins::Pipeline::DataObject Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( BoundingBox, DataObject );
+      cpPlugins_Id_Macro( BoundingBox, Object );
+      cpPlugins_Compatibility_Macro;
+
+    public:
+      void SetDataObject( DataObject* o );
+
+      void Copy( Self* other );
+      void Blend( Self* other );
+
+      template< class _TPoint >
+      inline void SetMinimum( const _TPoint& p )
+        {
+          this->_SetPoint( 0, p );
+        }
+
+      template< class _TPoint >
+      inline void SetMaximum( const _TPoint& p )
+        {
+          this->_SetPoint( 1, p );
+        }
+
+      template< class _TPoint >
+      inline _TPoint GetMinimum( ) const
+        {
+          return( this->_GetPoint< _TPoint >( 0 ) );
+        }
+
+      template< class _TPoint >
+      inline _TPoint GetMaximum( ) const
+        {
+          return( this->_GetPoint< _TPoint >( 1 ) );
+        }
+
+    protected:
+      BoundingBox( );
+      virtual ~BoundingBox( );
+
+      void _UpdateVTK( );
+
+      template< class _TPoint >
+      inline void _SetPoint( unsigned int m, const _TPoint& p )
+        {
+          this->m_Points[ m ].clear( );
+          for( unsigned int d = 0; d < _TPoint::PointDimension; ++d )
+            this->m_Points[ m ].push_back( double( p[ d ] ) );
+          this->_UpdateVTK( );
+          this->Modified( );
+        }
+
+      template< class _TPoint >
+      inline _TPoint _GetPoint( unsigned int m ) const
+        {
+          unsigned int dim = this->m_Points[ m ].size( );
+          dim =
+            ( _TPoint::PointDimension < dim )? _TPoint::PointDimension: dim;
+          _TPoint p;
+          p.Fill( 0 );
+          for( unsigned int d = 0; d < dim; ++d )
+            p[ d ] = this->m_Points[ m ][ d ];
+          return( p );
+        }
+
+    private:
+      // Purposely not implemented
+      BoundingBox( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      std::vector< double > m_Points[ 2 ];
+      vtkSmartPointer< vtkOutlineSource > m_Outline;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpInstances__BoundingBox__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Image.cxx b/lib/cpInstances/DataObjects/Image.cxx
new file mode 100644 (file)
index 0000000..09cf834
--- /dev/null
@@ -0,0 +1,196 @@
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkImageToVTKImageFilter.h>
+#include <itkVTKImageToImageFilter.h>
+#include <vtkImageData.h>
+#include <itkDiffusionTensor3D.h>
+#include <itkRGBPixel.h>
+#include <itkRGBAPixel.h>
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::Image::
+SetITK( itk::LightObject* o )
+{
+  this->Superclass::SetITK( o );
+  this->m_VTK = NULL;
+  this->m_ITKvVTK = NULL;
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::Image::
+SetVTK( vtkObjectBase* o )
+{
+  this->Superclass::SetVTK( o );
+  this->m_ITK = NULL;
+  this->m_ITKvVTK = NULL;
+  this->Modified( );
+
+  /* TODO
+     vtkImageData* img = dynamic_cast< vtkImageData* >( o );
+     this->Superclass::SetVTK( img );
+     if( img == NULL )
+     {
+     this->m_ITK = NULL;
+     this->m_ITKvVTK = NULL;
+     this->Modified( );
+     return;
+
+     } // fi
+
+     bool success = false;
+     auto stype = img->GetScalarType( );
+     #ifdef cpPlugins_CONFIG_INTEGER_TYPES_char
+     if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< char >( img );
+     if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned char >( img );
+     #endif // cpPlugins_CONFIG_INTEGER_TYPES_char
+     #ifdef cpPlugins_CONFIG_INTEGER_TYPES_short
+     if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< short >( img );
+     if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned short >( img );
+     #endif // cpPlugins_CONFIG_INTEGER_TYPES_short
+     #ifdef cpPlugins_CONFIG_INTEGER_TYPES_int
+     if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< int >( img );
+     if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned int >( img );
+     #endif // cpPlugins_CONFIG_INTEGER_TYPES_int
+     #ifdef cpPlugins_CONFIG_INTEGER_TYPES_long
+     if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< long >( img );
+     if( stype == VTK_UNSIGNED_CHAR ) success = this->_VTK_2_ITK_0< unsigned long >( img );
+     #endif // cpPlugins_CONFIG_INTEGER_TYPES_long
+     #ifdef cpPlugins_CONFIG_REAL_TYPES_float
+     if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< float >( img );
+     #endif // cpPlugins_CONFIG_REAL_TYPES_float
+     #ifdef cpPlugins_CONFIG_REAL_TYPES_double
+     if( stype == VTK_CHAR ) success = this->_VTK_2_ITK_0< double >( img );
+     #endif // cpPlugins_CONFIG_REAL_TYPES_double
+  */
+  /* TODO
+     #define cpPlugins_CONFIG_COLOR_PIXELS_RGBPixel
+     #define cpPlugins_CONFIG_COLOR_PIXELS_RGBAPixel
+     #define cpPlugins_CONFIG_VECTORS_CovariantVector
+     #define cpPlugins_CONFIG_VECTORS_Point
+     #define cpPlugins_CONFIG_VECTORS_SymmetricSecondRankTensor
+     #define cpPlugins_CONFIG_VECTORS_Vector
+     #define cpPlugins_CONFIG_DIFFUSIONTENSORS_DiffusionTensor3D
+     #define cpPlugins_CONFIG_MATRICES_Matrix
+  */
+  /* TODO
+     if( !success )
+     {
+     this->m_ITK = NULL;
+     this->m_ITKvVTK = NULL;
+
+     } // fi
+     this->Modified( );
+  */
+}
+
+// -------------------------------------------------------------------------
+cpInstances::DataObjects::Image::
+Image( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::DataObjects::Image::
+~Image( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::Image::
+_UpdateITK( ) const
+{
+  // TODO: std::cout << "Create ITK representation." << std::endl;
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::Image::
+_UpdateVTK( ) const
+{
+  auto i = const_cast< itk::LightObject* >( this->m_ITK.GetPointer( ) );
+  auto v = const_cast< vtkObjectBase* >( this->m_VTK.GetPointer( ) );
+  if( i != NULL && v == NULL )
+  {
+    cpPlugins_Demangle_Image_VisualDims_1( i, _ITK_2_VTK_0 )
+      cpPlugins_Demangle_Image_DiffTensors3D_1( i, _ITK_2_VTK_1 );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpInstances::DataObjects::Image::
+_ITK_2_VTK_0( _TImage* image ) const
+{
+  static const unsigned int d = _TImage::ImageDimension;
+  cpPlugins_Demangle_Image_ScalarPixels_1( image, _ITK_2_VTK_1, d )
+    cpPlugins_Demangle_Image_ColorPixels_1( image, _ITK_2_VTK_1, d )
+    cpPlugins_Demangle_Image_VectorPixels_1( image, _ITK_2_VTK_1, d );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpInstances::DataObjects::Image::
+_ITK_2_VTK_1( _TImage* image ) const
+{
+  typedef itk::ImageToVTKImageFilter< _TImage > _TFilter;
+
+  Self* self = const_cast< Self* >( this );
+  _TFilter* f = dynamic_cast< _TFilter* >( self->m_ITKvVTK.GetPointer( ) );
+  if( f == NULL )
+  {
+    typename _TFilter::Pointer nf = _TFilter::New( );
+    self->m_ITKvVTK = nf;
+    f = nf.GetPointer( );
+
+  } // fi
+  f->SetInput( image );
+  f->Update( );
+
+  // Keep object track
+  self->m_ITK = image;
+  self->m_VTK = f->GetOutput( );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPixel >
+bool cpInstances::DataObjects::Image::
+_VTK_2_ITK_0( vtkImageData* image )
+{
+  bool success = false;
+  unsigned int dim = image->GetDataDimension( );
+#ifdef cpPlugins_CONFIG_VISUAL_DIMENSIONS_2
+  if( dim == 2 ) success = this->_VTK_2_ITK_1< _TPixel, 2 >( image );
+#endif // cpPlugins_CONFIG_VISUAL_DIMENSIONS_2
+#ifdef cpPlugins_CONFIG_VISUAL_DIMENSIONS_3
+  if( dim == 3 ) success = this->_VTK_2_ITK_1< _TPixel, 3 >( image );
+#endif // cpPlugins_CONFIG_VISUAL_DIMENSIONS_2
+  return( success );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPixel, unsigned int _VDim >
+bool cpInstances::DataObjects::Image::
+_VTK_2_ITK_1( vtkImageData* image )
+{
+  typedef itk::Image< _TPixel, _VDim > _TImage;
+  typedef itk::VTKImageToImageFilter< _TImage > _TFilter;
+  _TFilter* f = dynamic_cast< _TFilter* >( this->m_ITKvVTK.GetPointer( ) );
+  if( f == NULL )
+  {
+    typename _TFilter::Pointer nf = _TFilter::New( );
+    this->m_ITKvVTK = nf;
+    f = nf.GetPointer( );
+
+  } // fi
+  f->SetInput( image );
+  f->Update( );
+
+  // Keep object track
+  this->m_VTK = image;
+  this->m_ITK = f->GetOutput( );
+  return( true );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Image.d b/lib/cpInstances/DataObjects/Image.d
new file mode 100644 (file)
index 0000000..b9a2444
--- /dev/null
@@ -0,0 +1,27 @@
+define all_ints=#int_types#;unsigned #int_types#
+define color_pixels=RGBPixel;RGBAPixel
+
+ProcessDims itk::ImageBase< #pdims# >
+VisualDims itk::ImageBase< #vdims# >
+
+IntPixels|d itk::Image< #all_ints#, d >
+RealPixels|d itk::Image< #real_types#, d >
+ScalarPixels|d itk::Image< #scalar_types#, d >
+ComplexPixels|d itk::Image< std::complex< #real_types# >, d >
+ColorPixels|d itk::Image< itk::#color_pixels#< #scalar_types# >, d >
+VectorPixels|d itk::Image< itk::#vectors#< #real_types#, d >, d >
+DiffTensors3D itk::Image< itk::#diff_tensors#< #real_types# >, 3 >
+
+IntPixels_AllDims itk::Image< #all_ints#, #pdims# >
+IntPixels_VisualDims itk::Image< #all_ints#, #pdims# >
+RealPixels_AllDims itk::Image< #real_types#, #pdims# >
+RealPixels_VisualDims itk::Image< #real_types#, #pdims# >
+ScalarPixels_AllDims itk::Image< #scalar_types#, #pdims# >
+ScalarPixels_VisualDims itk::Image< #scalar_types#, #vdims# >
+ColorPixels_AllDims itk::Image< itk::#color_pixels#< #scalar_types# >, #pdims# >
+ColorPixels_VisualDims itk::Image< itk::#color_pixels#< #scalar_types# >, #vdims# >
+VectorPixels_AllDims itk::Image< itk::#vectors#< #real_types#, #pdims# >, #pdims# >
+VectorPixels_VisualDims itk::Image< itk::#vectors#< #real_types#, #vdims# >, #vdims# >
+CovariantVectorPixels_AllDims itk::Image< itk::CovariantVector< #real_types#, #pdims# >, #pdims# >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Image.h b/lib/cpInstances/DataObjects/Image.h
new file mode 100644 (file)
index 0000000..a3ee5ef
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __cpInstances__Image__h__
+#define __cpInstances__Image__h__
+
+#define ITK_MANUAL_INSTANTIATION
+#include <cpInstances/cpPluginsDataObjects_Export.h>
+#include <cpInstances/DataObjects/Image_Demanglers.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <itkProcessObject.h>
+
+class vtkImageData;
+
+namespace cpInstances
+{
+  namespace DataObjects
+  {
+    /**
+     */
+    class cpPluginsDataObjects_EXPORT Image
+      : public cpPlugins::Pipeline::DataObject
+    {
+    public:
+      typedef Image                           Self;
+      typedef cpPlugins::Pipeline::DataObject Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Image, cpPlugins::Pipeline::DataObject );
+      cpPlugins_Id_Macro( Image, Object );
+      cpPlugins_Compatibility_Macro;
+
+    public:
+      virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE;
+      virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE;
+
+    protected:
+      Image( );
+      virtual ~Image( );
+
+      virtual void _UpdateITK( ) const cpPlugins_OVERRIDE;
+      virtual void _UpdateVTK( ) const cpPlugins_OVERRIDE;
+
+      template< class _TImage >
+      inline void _ITK_2_VTK_0( _TImage* image ) const;
+
+      template< class _TImage >
+      inline void _ITK_2_VTK_1( _TImage* image ) const;
+
+      template< class _TPixel >
+      inline bool _VTK_2_ITK_0( vtkImageData* image );
+
+      template< class _TPixel, unsigned int _VDim >
+      inline bool _VTK_2_ITK_1( vtkImageData* image );
+
+    private:
+      // Purposely not implemented
+      Image( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      itk::ProcessObject::Pointer m_ITKvVTK;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpInstances__Image__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Mesh.cxx b/lib/cpInstances/DataObjects/Mesh.cxx
new file mode 100644 (file)
index 0000000..2118301
--- /dev/null
@@ -0,0 +1,180 @@
+#include <cpInstances/DataObjects/Mesh.h>
+
+#include <itkMesh.h>
+#include <itkLineCell.h>
+#include <itkTriangleCell.h>
+#include <itkPolygonCell.h>
+#include <vtkPolyData.h>
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::Mesh::
+SetITK( itk::LightObject* o )
+{
+  this->Superclass::SetITK( o );
+  cpPlugins_Demangle_Mesh_AllMeshes_1( o, _ITK_2_VTK )
+  {
+    this->m_VTK = NULL;
+  }
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::DataObjects::Mesh::
+SetVTK( vtkObjectBase* o )
+{
+  vtkPolyData* mesh = dynamic_cast< vtkPolyData* >( o );
+  if( mesh == NULL )
+  {
+    this->m_ITK = NULL;
+    this->Modified( );
+    return;
+
+  } // fi
+
+  if( this->m_VTK.GetPointer( ) != mesh )
+  {
+    this->m_VTK = mesh;
+#ifdef cpPlugins_PROCESS_DIMS_3
+    typedef itk::Mesh< double, 3 >      _TMesh;
+    typedef _TMesh::CellType            _TCell;
+    typedef _TCell::CellAutoPointer     _TCellAutoPointer;
+    typedef itk::LineCell< _TCell >     _TLine;
+    typedef itk::TriangleCell< _TCell > _TTriangle;
+    typedef itk::PolygonCell< _TCell >  _TPolygon;
+
+    // Copy points
+    _TMesh::Pointer imesh = _TMesh::New( );
+    double point[ 3 ];
+    for( long i = 0; i < mesh->GetNumberOfPoints( ); ++i )
+    {
+      mesh->GetPoint( i, point );
+      _TMesh::PointType ipoint;
+      ipoint[ 0 ] = point[ 0 ];
+      ipoint[ 1 ] = point[ 1 ];
+      ipoint[ 2 ] = point[ 2 ];
+      imesh->SetPoint( i, ipoint );
+
+    } // rof
+
+    // Copy cells
+    vtkCellArray* arrays[ 4 ];
+    arrays[ 0 ] = mesh->GetLines( );
+    arrays[ 1 ] = mesh->GetPolys( );
+    arrays[ 2 ] = NULL; // TODO: mesh->GetStrips( );
+    arrays[ 3 ] = mesh->GetVerts( );
+
+    for( unsigned int c = 0; c < 4; c++ )
+    {
+      if( arrays[ c ] != NULL )
+      {
+        vtkSmartPointer< vtkIdList > ids =
+          vtkSmartPointer< vtkIdList >::New( );
+        arrays[ c ]->InitTraversal( );
+        while( arrays[ c ]->GetNextCell( ids ) == 1 )
+        {
+          long nPoints = ids->GetNumberOfIds( );
+          _TCellAutoPointer icell;
+          if( nPoints == 2 )
+          {
+            icell.TakeOwnership( new _TLine );
+            icell->SetPointId( 0, ids->GetId( 0 ) );
+            icell->SetPointId( 1, ids->GetId( 1 ) );
+          }
+          else if( nPoints == 3 )
+          {
+            icell.TakeOwnership( new _TTriangle );
+            icell->SetPointId( 0, ids->GetId( 0 ) );
+            icell->SetPointId( 1, ids->GetId( 1 ) );
+            icell->SetPointId( 2, ids->GetId( 2 ) );
+          }
+          else if( nPoints > 3 )
+          {
+            _TPolygon* polygon = new _TPolygon( );
+            for( long j = 0; j < nPoints; ++j )
+              polygon->AddPointId( ids->GetId( j ) );
+            icell.TakeOwnership( polygon );
+
+          } // fi
+          imesh->SetCell( imesh->GetNumberOfCells( ), icell );
+
+        } // elihw
+
+      } // fi
+
+    } // rof
+    this->m_ITK = imesh;
+#endif // cpPlugins_PROCESS_DIMS_3
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpInstances::DataObjects::Mesh::
+Mesh( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::DataObjects::Mesh::
+~Mesh( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TMesh >
+void cpInstances::DataObjects::Mesh::
+_ITK_2_VTK( _TMesh* mesh )
+{
+  long numPoints = mesh->GetNumberOfPoints( );
+  if( numPoints == 0 )
+    return;
+
+  vtkSmartPointer< vtkPoints > vpoints =
+    vtkSmartPointer< vtkPoints >::New( );
+  vpoints->SetNumberOfPoints( numPoints );
+  auto points = mesh->GetPoints( );
+
+  // Copy points
+  vtkIdType VTKId = 0;
+  std::map< vtkIdType, long > IndexMap;
+  for( auto i = points->Begin( ); i != points->End( ); ++i, VTKId++ )
+  {
+    IndexMap[ VTKId ] = i->Index( );
+    if( _TMesh::PointDimension == 2 )
+      vpoints->SetPoint(
+        VTKId,
+        i->Value( )[ 0 ], i->Value( )[ 1 ], 0
+        );
+    else if( _TMesh::PointDimension == 3 )
+      vpoints->SetPoint(
+        VTKId,
+        i->Value( )[ 0 ], i->Value( )[ 1 ], i->Value( )[ 2 ]
+        );
+
+  } // rof
+
+  // Copy cells
+  vtkSmartPointer< vtkCellArray > vcells =
+    vtkSmartPointer< vtkCellArray >::New( );
+  auto cells = mesh->GetCells( );
+  for( auto j = cells->Begin( ); j != cells->End( ); ++j )
+  {
+    auto cell = j->Value( );
+    vcells->InsertNextCell( cell->GetNumberOfPoints( ) );
+    for( auto k = cell->PointIdsBegin( ); k != cell->PointIdsEnd( ); ++k )
+      vcells->InsertCellPoint( IndexMap[ *k ] );
+
+  } // rof
+
+  // Final assignations
+  vtkSmartPointer< vtkPolyData > vmesh =
+    vtkSmartPointer< vtkPolyData >::New( );
+  vmesh->SetPoints( vpoints );
+  vmesh->SetPolys( vcells );
+  this->m_VTK = vmesh;
+  this->Modified( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Mesh.d b/lib/cpInstances/DataObjects/Mesh.d
new file mode 100644 (file)
index 0000000..8f98aca
--- /dev/null
@@ -0,0 +1,4 @@
+AllMeshes itk::Mesh< #real_types#, #vdims# >
+Meshes|d itk::Mesh< #real_types#, d >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Mesh.h b/lib/cpInstances/DataObjects/Mesh.h
new file mode 100644 (file)
index 0000000..fa658ed
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __cpInstances__Mesh__h__
+#define __cpInstances__Mesh__h__
+
+#define ITK_MANUAL_INSTANTIATION
+#include <cpInstances/cpPluginsDataObjects_Export.h>
+#include <cpInstances/DataObjects/Mesh_Demanglers.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+
+namespace cpInstances
+{
+  namespace DataObjects
+  {
+    /**
+     */
+    class cpPluginsDataObjects_EXPORT Mesh
+      : public cpPlugins::Pipeline::DataObject
+    {
+    public:
+      typedef Mesh                            Self;
+      typedef cpPlugins::Pipeline::DataObject Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Mesh, DataObject );
+      cpPlugins_Id_Macro( Mesh, Object );
+      cpPlugins_Compatibility_Macro;
+
+    public:
+      virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE;
+      virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE;
+
+    protected:
+      Mesh( );
+      virtual ~Mesh( );
+
+      template< class _TMesh >
+      inline void _ITK_2_VTK( _TMesh* mesh );
+
+    private:
+      // Purposely not implemented
+      Mesh( const Self& );
+      Self& operator=( const Self& );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpInstances__Mesh__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/PolyLineParametricPath.cxx b/lib/cpInstances/DataObjects/PolyLineParametricPath.cxx
new file mode 100644 (file)
index 0000000..488be38
--- /dev/null
@@ -0,0 +1,39 @@
+#include <cpInstances/DataObjects/PolyLineParametricPath.h>
+
+// -------------------------------------------------------------------------
+void cpInstances::PolyLineParametricPath::
+SetITK( itk::LightObject* o )
+{
+  this->Superclass::SetITK( o );
+  /* TODO
+     cpPlugins_Demangle_PolyLineParametricPath_VisualDims_1( o, _ITK_2_VTK_0 )
+     cpPlugins_Demangle_PolyLineParametricPath_DiffTensors3D_1( o, _ITK_2_VTK_1 )
+     {
+     this->m_VTK = NULL;
+     this->m_ITKvVTK = NULL;
+
+     } // fi
+  */
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::PolyLineParametricPath::
+SetVTK( vtkObjectBase* o )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::PolyLineParametricPath::
+PolyLineParametricPath( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::PolyLineParametricPath::
+~PolyLineParametricPath( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/PolyLineParametricPath.d b/lib/cpInstances/DataObjects/PolyLineParametricPath.d
new file mode 100644 (file)
index 0000000..e13c77f
--- /dev/null
@@ -0,0 +1,4 @@
+All cpExtensions::DataStructures::PolyLineParametricPath< #pdims# >
+Dim|d cpExtensions::DataStructures::PolyLineParametricPath< d >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/PolyLineParametricPath.h b/lib/cpInstances/DataObjects/PolyLineParametricPath.h
new file mode 100644 (file)
index 0000000..b563d41
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __cpInstances__PolyLineParametricPath__h__
+#define __cpInstances__PolyLineParametricPath__h__
+
+#include <cpInstances/cpPluginsDataObjects_Export.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <cpInstances/DataObjects/PolyLineParametricPath_Demanglers.h>
+#include <itkProcessObject.h>
+
+class vtkPolyLineParametricPathData;
+
+namespace cpInstances
+{
+  /**
+   */
+  class cpPluginsDataObjects_EXPORT PolyLineParametricPath
+    : public cpPlugins::Pipeline::DataObject
+  {
+  public:
+    typedef PolyLineParametricPath             Self;
+    typedef cpPlugins::Pipeline::DataObject Superclass;
+    typedef itk::SmartPointer< Self >          Pointer;
+    typedef itk::SmartPointer< const Self >    ConstPointer;
+
+  public:
+    itkNewMacro( Self );
+    itkTypeMacro( PolyLineParametricPath, cpPlugins::Pipeline::DataObject );
+    cpPlugins_Id_Macro( PolyLineParametricPath, Object );
+    cpPlugins_Compatibility_Macro;
+
+  public:
+    virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE;
+    virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE;
+
+  protected:
+    PolyLineParametricPath( );
+    virtual ~PolyLineParametricPath( );
+
+  private:
+    // Purposely not implemented
+    PolyLineParametricPath( const Self& );
+    Self& operator=( const Self& );
+  };
+
+} // ecapseman
+
+#endif // __cpInstances__PolyLineParametricPath__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Simple3DCurve.cxx b/lib/cpInstances/DataObjects/Simple3DCurve.cxx
new file mode 100644 (file)
index 0000000..10165f7
--- /dev/null
@@ -0,0 +1,64 @@
+#include <cpInstances/DataObjects/Simple3DCurve.h>
+#include <cpExtensions/DataStructures/Simple3DCurve.h>
+#include <cpExtensions/Visualization/Simple3DCurveToPolyData.h>
+
+// -------------------------------------------------------------------------
+void cpInstances::Simple3DCurve::
+SetVTK( vtkObjectBase* o )
+{
+  // Do nothing
+}
+
+// -------------------------------------------------------------------------
+cpInstances::Simple3DCurve::
+Simple3DCurve( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::Simple3DCurve::
+~Simple3DCurve( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::Simple3DCurve::
+_UpdateVTK( ) const
+{
+  auto i = const_cast< itk::LightObject* >( this->m_ITK.GetPointer( ) );
+  auto v = const_cast< vtkObjectBase* >( this->m_VTK.GetPointer( ) );
+  if( i != NULL && v == NULL )
+  {
+    cpPlugins_Demangle_Simple3DCurve_All_1( i, _ITK_2_VTK );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve >
+void cpInstances::Simple3DCurve::
+_ITK_2_VTK( _TCurve* curve ) const
+{
+  typedef
+    cpExtensions::Visualization::Simple3DCurveToPolyData< _TCurve >
+    _TFilter;
+
+  Self* self = const_cast< Self* >( this );
+  _TFilter* f = dynamic_cast< _TFilter* >( self->m_ITKvVTK.GetPointer( ) );
+  if( f == NULL )
+  {
+    _TFilter* nf = _TFilter::New( );
+    self->m_ITKvVTK = nf;
+    f = nf;
+
+  } // fi
+  f->SetInput( curve );
+  f->Update( );
+
+  // Keep object track
+  self->m_ITK = curve;
+  self->m_VTK = f->GetOutput( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Simple3DCurve.d b/lib/cpInstances/DataObjects/Simple3DCurve.d
new file mode 100644 (file)
index 0000000..2ba68a1
--- /dev/null
@@ -0,0 +1 @@
+All cpExtensions::DataStructures::Simple3DCurve< #real_types# >
diff --git a/lib/cpInstances/DataObjects/Simple3DCurve.h b/lib/cpInstances/DataObjects/Simple3DCurve.h
new file mode 100644 (file)
index 0000000..e53df26
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __cpInstances__Simple3DCurve__h__
+#define __cpInstances__Simple3DCurve__h__
+
+#include <cpInstances/cpPluginsDataObjects_Export.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <cpInstances/DataObjects/Simple3DCurve_Demanglers.h>
+#include <itkProcessObject.h>
+#include <vtkSmartPointer.h>
+
+// -------------------------------------------------------------------------
+class vtkPolyDataAlgorithm;
+
+// -------------------------------------------------------------------------
+namespace cpInstances
+{
+  /**
+   */
+  class cpPluginsDataObjects_EXPORT Simple3DCurve
+    : public cpPlugins::Pipeline::DataObject
+  {
+  public:
+    typedef Simple3DCurve                      Self;
+    typedef cpPlugins::Pipeline::DataObject Superclass;
+    typedef itk::SmartPointer< Self >          Pointer;
+    typedef itk::SmartPointer< const Self >    ConstPointer;
+
+  public:
+    itkNewMacro( Self );
+    itkTypeMacro( Simple3DCurve, cpPlugins::Pipeline::DataObject );
+    cpPlugins_Id_Macro( Simple3DCurve, Object );
+    cpPlugins_Compatibility_Macro;
+
+  public:
+    virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE;
+
+  protected:
+    Simple3DCurve( );
+    virtual ~Simple3DCurve( );
+
+    virtual void _UpdateVTK( ) const cpPlugins_OVERRIDE;
+
+    template< class _TCurve >
+    inline void _ITK_2_VTK( _TCurve* curve ) const;
+
+  private:
+    // Purposely not implemented
+    Simple3DCurve( const Self& );
+    Self& operator=( const Self& );
+
+  protected:
+    vtkSmartPointer< vtkPolyDataAlgorithm > m_ITKvVTK;
+  };
+
+} // ecapseman
+
+#endif // __cpInstances__Simple3DCurve__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Skeleton.cxx b/lib/cpInstances/DataObjects/Skeleton.cxx
new file mode 100644 (file)
index 0000000..fc4492b
--- /dev/null
@@ -0,0 +1,39 @@
+#include <cpInstances/DataObjects/Skeleton.h>
+
+// -------------------------------------------------------------------------
+void cpInstances::Skeleton::
+SetITK( itk::LightObject* o )
+{
+  this->Superclass::SetITK( o );
+  /* TODO
+     cpPlugins_Demangle_Skeleton_VisualDims_1( o, _ITK_2_VTK_0 )
+     cpPlugins_Demangle_Skeleton_DiffTensors3D_1( o, _ITK_2_VTK_1 )
+     {
+     this->m_VTK = NULL;
+     this->m_ITKvVTK = NULL;
+
+     } // fi
+  */
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpInstances::Skeleton::
+SetVTK( vtkObjectBase* o )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::Skeleton::
+Skeleton( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpInstances::Skeleton::
+~Skeleton( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/DataObjects/Skeleton.d b/lib/cpInstances/DataObjects/Skeleton.d
new file mode 100644 (file)
index 0000000..99e6261
--- /dev/null
@@ -0,0 +1 @@
+All cpExtensions::DataStructures::Skeleton< #pdims# >
diff --git a/lib/cpInstances/DataObjects/Skeleton.h b/lib/cpInstances/DataObjects/Skeleton.h
new file mode 100644 (file)
index 0000000..060a8e5
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __cpInstances__Skeleton__h__
+#define __cpInstances__Skeleton__h__
+
+#include <cpInstances/cpPluginsDataObjects_Export.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <cpInstances/DataObjects/Skeleton_Demanglers.h>
+#include <itkProcessObject.h>
+
+namespace cpInstances
+{
+  /**
+   */
+  class cpPluginsDataObjects_EXPORT Skeleton
+    : public cpPlugins::Pipeline::DataObject
+  {
+  public:
+    typedef Skeleton                      Self;
+    typedef cpPlugins::Pipeline::DataObject Superclass;
+    typedef itk::SmartPointer< Self >          Pointer;
+    typedef itk::SmartPointer< const Self >    ConstPointer;
+
+  public:
+    itkNewMacro( Self );
+    itkTypeMacro( Skeleton, cpPlugins::Pipeline::DataObject );
+    cpPlugins_Id_Macro( Skeleton, Object );
+    cpPlugins_Compatibility_Macro;
+
+  public:
+    virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE;
+    virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE;
+
+  protected:
+    Skeleton( );
+    virtual ~Skeleton( );
+
+  private:
+    // Purposely not implemented
+    Skeleton( const Self& );
+    Self& operator=( const Self& );
+  };
+
+} // ecapseman
+
+#endif // __cpInstances__Skeleton__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpInstances/Extensions/Paths.i b/lib/cpInstances/Extensions/Paths.i
new file mode 100644 (file)
index 0000000..cbf4450
--- /dev/null
@@ -0,0 +1,9 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude cpExtensions/Algorithms/BezierCurveFunction:h|hxx
+tinclude cpExtensions/DataStructures/PolyLineParametricPath:h|hxx
+
+instances cpExtensions::Algorithms::BezierCurveFunction< itk::Vector< #real_types#, #pdims# > >
+instances cpExtensions::DataStructures::PolyLineParametricPath< #pdims# >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Extensions/Skeleton.i b/lib/cpInstances/Extensions/Skeleton.i
new file mode 100644 (file)
index 0000000..ed1ec99
--- /dev/null
@@ -0,0 +1,8 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude cpExtensions/DataStructures/Skeleton:h|hxx
+cinclude cpExtensions/DataStructures/Graph.hxx
+
+instances cpExtensions::DataStructures::Skeleton< #pdims# >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Geometries/ITKMeshes.i b/lib/cpInstances/Geometries/ITKMeshes.i
new file mode 100644 (file)
index 0000000..70b0c54
--- /dev/null
@@ -0,0 +1,16 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define meshes=PointSet;Mesh
+tinclude itk#meshes#:h|hxx
+cinclude itkMapContainer.hxx
+cinclude itkVectorContainer.hxx
+instances itk::#meshes#< #real_types#, #vdims# >
+
+define cells=Vertex;Line;Triangle;Polygon
+tinclude itk#cells#Cell:h|hxx
+tinclude itkCellInterface:h|hxx
+instances itk::CellInterface< #real_types#, itk::CellTraitsInfo< #vdims#, float, float, unsigned long, unsigned long, unsigned long, itk::Point< float, #vdims# >, itk::VectorContainer< unsigned long, itk::Point< float, #vdims# > >, std::set< unsigned long > > >
+instances itk::VectorContainer< unsigned long, itk::CellInterface< #real_types#, itk::CellTraitsInfo< #vdims#, float, float, unsigned long, unsigned long, unsigned long, itk::Point< float, #vdims# >, itk::VectorContainer< unsigned long, itk::Point< float, #vdims# > >, std::set< unsigned long > > >* >
+instances itk::#cells#Cell< itk::CellInterface< #real_types#, itk::CellTraitsInfo< #vdims#, float, float, unsigned long, unsigned long, unsigned long, itk::Point< float, #vdims# >, itk::VectorContainer< unsigned long, itk::Point< float, #vdims# > >, std::set< unsigned long > > > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Geometries/ITKPaths.i b/lib/cpInstances/Geometries/ITKPaths.i
new file mode 100644 (file)
index 0000000..d2b413f
--- /dev/null
@@ -0,0 +1,11 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude itkPath:h|hxx
+tinclude itkParametricPath:h|hxx
+tinclude itkPolyLineParametricPath:h|hxx
+cinclude itkVectorContainer.hxx
+instances itk::Path< double, itk::ContinuousIndex< double, #pdims# >, #pdims# >
+define paths=itk::ParametricPath;itk::PolyLineParametricPath
+instances #paths#< #pdims# >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/ITK2VTKImageFilters.i b/lib/cpInstances/Images/ITK2VTKImageFilters.i
new file mode 100644 (file)
index 0000000..4166981
--- /dev/null
@@ -0,0 +1,21 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define color_pixels=RGBPixel;RGBAPixel
+define vector_pixels=CovariantVector;Point;Vector
+define matrices=Matrix
+define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >
+
+cinclude itkImage.h
+cinclude itk#color_pixels#.h
+cinclude itkFixedArray.h
+cinclude itk#vector_pixels#.h
+cinclude itk#matrices#.h
+
+define filters=VTKImageImport;VTKImageExport;ImageToVTKImageFilter;VTKImageToImageFilter
+tinclude itk#filters#:h|hxx
+instances itk::#filters#< itk::Image< #pixels#, #vdims# > >
+instances itk::#filters#< itk::Image< itk::FixedArray< #scalar_types#, #vdims# >, #vdims# > >
+instances itk::#filters#< itk::Image< itk::#vector_pixels#< #real_types#, #vdims# >, #vdims# > >
+instances itk::#filters#< itk::Image< itk::#matrices#< #real_types#, #vdims#, #vdims# >, #vdims# > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/ITKImageFunctions.i b/lib/cpInstances/Images/ITKImageFunctions.i
new file mode 100644 (file)
index 0000000..8b4cbdb
--- /dev/null
@@ -0,0 +1,13 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define i_reals=#real_types#
+define o_reals=#real_types#
+define p_reals=#real_types#
+
+tinclude itkImageFunction:h|hxx
+cinclude itkImage.h
+
+instances itk::ImageFunction< itk::Image< #scalar_types#, #pdims# >, #i_reals#, #o_reals# >
+instances itk::ImageFunction< itk::Image< itk::FixedArray< #i_reals#, #pdims# >, #pdims# >, itk::FixedArray< #o_reals#, #pdims# >, #p_reals# >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/ITKImageInterpolators.i b/lib/cpInstances/Images/ITKImageInterpolators.i
new file mode 100644 (file)
index 0000000..cee831b
--- /dev/null
@@ -0,0 +1,23 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define v=FixedArray
+define i_real=#real_types#
+define o_real=#real_types#
+define interp=Linear
+
+tinclude itk#interp#InterpolateImageFunction:h|hxx
+tinclude itkVectorLinearInterpolateImageFunction:h|hxx
+
+cinclude itk#v#.h
+cinclude itkImage.h
+
+instances itk::#interp#InterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types# >
+
+instances itk::VectorLinearInterpolateImageFunction< itk::Image< itk::#v#< #i_real#, #pdims# >, #pdims# >, #o_real# >
+
+tinclude itkBSplineDecompositionImageFilter:h|hxx
+tinclude itkBSplineInterpolateImageFunction:h|hxx
+instances itk::BSplineInterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types#, #real_types# >
+instances itk::BSplineDecompositionImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/ITKImages.i b/lib/cpInstances/Images/ITKImages.i
new file mode 100644 (file)
index 0000000..33f5852
--- /dev/null
@@ -0,0 +1,41 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude itkImportImageContainer:h|hxx
+tinclude itkImage:h|hxx
+
+define base_objects=ImageRegion;ImageBase
+tinclude itk#base_objects#:h|hxx
+instances itk::#base_objects#< #pdims# >
+
+minstances #_export_# std::ostream& itk::operator<< < #pdims# >( std::ostream& a, itk::ImageRegion< #pdims# > const& b )
+
+define color_pixels=RGBPixel;RGBAPixel
+define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# >;#sint_types#
+cinclude itk#color_pixels#.h
+cinclude complex
+instances itk::ImportImageContainer< unsigned long, #pixels# >
+instances itk::Image< #pixels#, #pdims# >
+
+cinclude itkFixedArray.h
+instances itk::ImportImageContainer< unsigned long, itk::FixedArray< #scalar_types#, #pdims# > >
+instances itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# >
+
+define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor
+cinclude itk#vector_pixels#.h
+instances itk::ImportImageContainer< unsigned long, itk::#vector_pixels#< #real_types#, #pdims# > >
+instances itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# >
+
+define matrices=Matrix
+cinclude itk#matrices#.h
+instances itk::ImportImageContainer< unsigned long, itk::#matrices#< #real_types#, #pdims#, #pdims# > >
+instances itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >
+
+cinclude itkOffset.h
+instances itk::ImportImageContainer< unsigned long, itk::Offset< #pdims# > >
+instances itk::Image< itk::Offset< #pdims# >, #pdims# >
+
+cinclude itkDiffusionTensor3D.h
+instances itk::ImportImageContainer< unsigned long, itk::DiffusionTensor3D< #real_types# > >
+instances itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/ITKImagesBaseFilters.i b/lib/cpInstances/Images/ITKImagesBaseFilters.i
new file mode 100644 (file)
index 0000000..f29b580
--- /dev/null
@@ -0,0 +1,58 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define color_pixels=RGBPixel;RGBAPixel
+define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor
+define matrices=Matrix
+define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# >
+
+cinclude complex
+cinclude itkImage.h
+cinclude itk#color_pixels#.h
+cinclude itkFixedArray.h
+cinclude itk#vector_pixels#.h
+cinclude itk#matrices#.h
+cinclude itkDiffusionTensor3D.h
+
+tinclude itkImageSource:h|hxx
+instances itk::ImageSource< itk::Image< #pixels#, #pdims# > >
+instances itk::ImageSource< itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > >
+instances itk::ImageSource< itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > >
+instances itk::ImageSource< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > >
+instances itk::ImageSource< itk::Image< itk::Offset< #pdims# >, #pdims# > >
+instances itk::ImageSource< itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > >
+
+define i_pixels=#pixels#
+define o_pixels=#pixels#
+define i_scalar_types=#scalar_types#
+define o_scalar_types=#scalar_types#
+define i_real_types=#real_types#
+define o_real_types=#real_types#
+define filters=ImageToImageFilter;InPlaceImageFilter
+tinclude itk#filters#:h|hxx
+instances itk::#filters#< itk::Image< #i_pixels#, #pdims# >, itk::Image< #o_pixels#, #pdims# > >
+instances itk::#filters#< itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# >, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# > >
+instances itk::#filters#< itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# >, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# > >
+instances itk::#filters#< itk::Image< itk::#matrices#< #i_real_types#, #pdims#, #pdims# >, #pdims# >, itk::Image< itk::#matrices#< #o_real_types#, #pdims#, #pdims# >, #pdims# > >
+
+define i_dims=#pdims#
+define o_dims=#pdims#
+instances itk::#filters#< itk::Image< #pixels#, #i_dims# >, itk::Image< #pixels#, #o_dims# > >
+
+tinclude itkImageAlgorithm:h|hxx
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< #i_scalar_types#, #pdims# >, itk::Image< #o_scalar_types#, #pdims# > >( itk::Image< #i_scalar_types#, #pdims# > const*, itk::Image< #o_scalar_types#, #pdims# >*, itk::Image< #i_scalar_types#, #pdims# >::RegionType const&, itk::Image< #o_scalar_types#, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< std::complex< #i_real_types# >, #pdims# >, itk::Image< std::complex< #o_real_types# >, #pdims# > >( itk::Image< std::complex< #i_real_types# >, #pdims# > const*, itk::Image< std::complex< #o_real_types# >, #pdims# >*, itk::Image< std::complex< #i_real_types# >, #pdims# >::RegionType const&, itk::Image< std::complex< #o_real_types# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::#color_pixels#< #i_scalar_types# >, #pdims# >, itk::Image< itk::#color_pixels#< #o_scalar_types# >, #pdims# > >( itk::Image< itk::#color_pixels#< #i_scalar_types# >, #pdims# > const*, itk::Image< itk::#color_pixels#< #o_scalar_types# >, #pdims# >*, itk::Image< itk::#color_pixels#< #i_scalar_types# >, #pdims# >::RegionType const&, itk::Image< itk::#color_pixels#< #o_scalar_types# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# >, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# > >( itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# > const*, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# >*, itk::Image< itk::FixedArray< #i_scalar_types#, #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::FixedArray< #o_scalar_types#, #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# >, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# > >( itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# > const*, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# >*, itk::Image< itk::#vector_pixels#< #i_real_types#, #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::#vector_pixels#< #o_real_types#, #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > >( itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > const*, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >*, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::Offset< #pdims# >, #pdims# >, itk::Image< itk::Offset< #pdims# >, #pdims# > >( itk::Image< itk::Offset< #pdims# >, #pdims# > const*, itk::Image< itk::Offset< #pdims# >, #pdims# >*, itk::Image< itk::Offset< #pdims# >, #pdims# >::RegionType const&, itk::Image< itk::Offset< #pdims# >, #pdims# >::RegionType const&, std::integral_constant< bool, true > )
+
+minstances void #_export_# itk::ImageAlgorithm::DispatchedCopy< itk::Image< itk::DiffusionTensor3D< #i_real_types# >, 3 >, itk::Image< itk::DiffusionTensor3D< #o_real_types# >, 3 > >( itk::Image< itk::DiffusionTensor3D< #i_real_types# >, 3 > const*, itk::Image< itk::DiffusionTensor3D< #o_real_types# >, 3 >*, itk::Image< itk::DiffusionTensor3D< #i_real_types# >, 3 >::RegionType const&, itk::Image< itk::DiffusionTensor3D< #o_real_types# >, 3 >::RegionType const&, std::integral_constant< bool, true > )
+
+** eof - $RCSfile$
\ No newline at end of file
diff --git a/lib/cpInstances/Images/ITKImagesNeighborhoodIterators.i b/lib/cpInstances/Images/ITKImagesNeighborhoodIterators.i
new file mode 100644 (file)
index 0000000..466da61
--- /dev/null
@@ -0,0 +1,37 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define color_pixels=RGBPixel;RGBAPixel
+define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor
+define matrices=Matrix
+define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >
+
+cinclude itkImage.h
+cinclude itk#color_pixels#.h
+cinclude itkFixedArray.h
+cinclude itk#vector_pixels#.h
+cinclude itk#matrices#.h
+
+define it=ConstNeighborhoodIterator;NeighborhoodIterator;ConstShapedNeighborhoodIterator;ShapedNeighborhoodIterator
+define co=ZeroFluxNeumannBoundaryCondition
+define pi=#scalar_types#;#sint_types#
+define op=Neighborhood;NeighborhoodOperator;DerivativeOperator
+
+tinclude itk#co#:h|hxx
+tinclude itk#op#:h|hxx
+tinclude itk#it#:h|hxx
+
+instances itk::NeighborhoodAllocator< #scalar_types#* >
+instances itk::NeighborhoodAllocator< #pi# >
+instances itk::Neighborhood< #scalar_types#*, #pdims#, itk::NeighborhoodAllocator< #scalar_types#* > >
+
+instances itk::#op#< #pi#, #pdims#, itk::NeighborhoodAllocator< #pi# > >
+instances itk::#co#< itk::Image< #pi#, #pdims# >, itk::Image< #pi#, #pdims# > >
+instances itk::#it#< itk::Image< #pi#, #pdims# >, itk::#co#< itk::Image< #pi#, #pdims# >, itk::Image< #pi#, #pdims# > > >
+
+tinclude itkNeighborhoodAlgorithm:h|hxx
+instances itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator< itk::Image< #pi#, #pdims# > >
+
+tinclude itkNeighborhoodInnerProduct:h|hxx
+instances itk::NeighborhoodInnerProduct< itk::Image< #pi#, #pdims# >, #pi#, #pi# >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/ITKImagesSimpleIterators.i b/lib/cpInstances/Images/ITKImagesSimpleIterators.i
new file mode 100644 (file)
index 0000000..e787093
--- /dev/null
@@ -0,0 +1,27 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define color_pixels=RGBPixel;RGBAPixel
+define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor
+define matrices=Matrix
+define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# >;#sint_types#
+
+cinclude itkImage.h
+cinclude itk#color_pixels#.h
+cinclude itkFixedArray.h
+cinclude itk#vector_pixels#.h
+cinclude itk#matrices#.h
+cinclude itkDiffusionTensor3D.h
+
+define it=ImageRegionConstIterator;ImageRegionIterator;ImageScanlineConstIterator;ImageScanlineIterator;ImageConstIteratorWithIndex;ImageIteratorWithIndex;ImageRegionConstIteratorWithIndex;ImageRegionIteratorWithIndex;ImageLinearConstIteratorWithIndex;ImageLinearIteratorWithIndex
+
+tinclude itk#it#:h|hxx
+
+tinclude itk#it#:h|hxx
+instances itk::#it#< itk::Image< #pixels#, #pdims# > >
+instances itk::#it#< itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > >
+instances itk::#it#< itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > >
+instances itk::#it#< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > >
+instances itk::#it#< itk::Image< itk::Offset< #pdims# >, #pdims# > >
+instances itk::#it#< itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > >
+
+** eof - $RCSfile$
diff --git a/lib/cpInstances/Images/itkImageToVTKImageFilter.h b/lib/cpInstances/Images/itkImageToVTKImageFilter.h
new file mode 100644 (file)
index 0000000..9390eb8
--- /dev/null
@@ -0,0 +1,111 @@
+/*=========================================================================
+ *
+ *  Copyright Insight Software Consortium
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *=========================================================================*/
+#ifndef itkImageToVTKImageFilter_h
+#define itkImageToVTKImageFilter_h
+
+#include "itkVTKImageExport.h"
+#include "vtkImageImport.h"
+#include "vtkImageData.h"
+
+namespace itk
+{
+
+/** \class ImageToVTKImageFilter
+ * \brief Converts an ITK image into a VTK image and plugs a
+ *  itk data pipeline to a VTK datapipeline.
+ *
+ *  This class puts together an itkVTKImageExporter and a vtkImageImporter.
+ *  It takes care of the details related to the connection of ITK and VTK
+ *  pipelines. The User will perceive this filter as an adaptor to which
+ *  an itk::Image can be plugged as input and a vtkImage is produced as
+ *  output.
+ *
+ * \ingroup   ITKVtkGlue
+ *
+ * \wiki
+ * \wikiexample{IO/ImageToVTKImageFilter,Display an ITK image}
+ * \wikiexample{IO/itkVtkImageConvertDICOM,Uses a custom user matrix to align the image with DICOM physical space}
+ * \endwiki
+ */
+template <typename TInputImage >
+class ImageToVTKImageFilter : public ProcessObject
+{
+public:
+  /** Standard class typedefs. */
+  typedef ImageToVTKImageFilter     Self;
+  typedef ProcessObject             Superclass;
+  typedef SmartPointer<Self>        Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(ImageToVTKImageFilter, ProcessObject);
+
+  /** Some typedefs. */
+  typedef TInputImage                            InputImageType;
+  typedef typename InputImageType::ConstPointer  InputImagePointer;
+
+  typedef VTKImageExport< InputImageType>        ExporterFilterType;
+  typedef typename ExporterFilterType::Pointer   ExporterFilterPointer;
+
+  /** Get the output in the form of a vtkImage.
+      This call is delegated to the internal vtkImageImporter filter  */
+  vtkImageData *  GetOutput() const;
+
+  /** Set the input in the form of an itk::Image */
+  using Superclass::SetInput;
+  void SetInput( const InputImageType * );
+  InputImageType * GetInput();
+
+  /** Return the internal VTK image importer filter.
+      This is intended to facilitate users the access
+      to methods in the importer */
+  vtkImageImport * GetImporter() const;
+
+  /** Return the internal ITK image exporter filter.
+      This is intended to facilitate users the access
+      to methods in the exporter */
+  ExporterFilterType * GetExporter() const;
+
+  /** This call delegates the update to the importer */
+  virtual void Update() ITK_OVERRIDE;
+
+  /** This call delegates the update to the importer */
+  virtual void UpdateLargestPossibleRegion() ITK_OVERRIDE;
+
+protected:
+  ImageToVTKImageFilter();
+  virtual ~ImageToVTKImageFilter();
+
+private:
+  ImageToVTKImageFilter(const Self&) ITK_DELETE_FUNCTION;
+  void operator=(const Self&) ITK_DELETE_FUNCTION;
+
+  ExporterFilterPointer       m_Exporter;
+  vtkImageImport *            m_Importer;
+};
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkImageToVTKImageFilter.hxx"
+#endif
+
+#endif
diff --git a/lib/cpInstances/Images/itkImageToVTKImageFilter.hxx b/lib/cpInstances/Images/itkImageToVTKImageFilter.hxx
new file mode 100644 (file)
index 0000000..e134b3f
--- /dev/null
@@ -0,0 +1,141 @@
+/*=========================================================================
+ *
+ *  Copyright Insight Software Consortium
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *=========================================================================*/
+#ifndef itkImageToVTKImageFilter_hxx
+#define itkImageToVTKImageFilter_hxx
+
+#include "itkImageToVTKImageFilter.h"
+
+namespace itk
+{
+
+/**
+ * Constructor
+ */
+template <typename TInputImage>
+ImageToVTKImageFilter<TInputImage>
+::ImageToVTKImageFilter()
+{
+  m_Importer = vtkImageImport::New();
+  m_Exporter = ExporterFilterType::New();
+
+  m_Importer->SetUpdateInformationCallback(m_Exporter->GetUpdateInformationCallback());
+  m_Importer->SetPipelineModifiedCallback(m_Exporter->GetPipelineModifiedCallback());
+  m_Importer->SetWholeExtentCallback(m_Exporter->GetWholeExtentCallback());
+  m_Importer->SetSpacingCallback(m_Exporter->GetSpacingCallback());
+  m_Importer->SetOriginCallback(m_Exporter->GetOriginCallback());
+  m_Importer->SetScalarTypeCallback(m_Exporter->GetScalarTypeCallback());
+  m_Importer->SetNumberOfComponentsCallback(m_Exporter->GetNumberOfComponentsCallback());
+  m_Importer->SetPropagateUpdateExtentCallback(m_Exporter->GetPropagateUpdateExtentCallback());
+  m_Importer->SetUpdateDataCallback(m_Exporter->GetUpdateDataCallback());
+  m_Importer->SetDataExtentCallback(m_Exporter->GetDataExtentCallback());
+  m_Importer->SetBufferPointerCallback(m_Exporter->GetBufferPointerCallback());
+  m_Importer->SetCallbackUserData(m_Exporter->GetCallbackUserData());
+
+}
+
+/**
+ * Destructor
+ */
+template <typename TInputImage>
+ImageToVTKImageFilter<TInputImage>
+::~ImageToVTKImageFilter()
+{
+  if( m_Importer )
+    {
+    m_Importer->Delete();
+    m_Importer = 0;
+    }
+}
+
+/**
+ * Set an itk::Image as input
+ */
+template <typename TInputImage>
+void
+ImageToVTKImageFilter<TInputImage>
+::SetInput( const InputImageType * inputImage )
+{
+  m_Exporter->SetInput( inputImage );
+}
+
+template <typename TInputImage>
+typename ImageToVTKImageFilter<TInputImage>::InputImageType *
+ImageToVTKImageFilter<TInputImage>
+::GetInput()
+{
+  return m_Exporter->GetInput();
+}
+
+/**
+ * Get a vtkImage as output
+ */
+template <typename TInputImage>
+vtkImageData *
+ImageToVTKImageFilter<TInputImage>
+::GetOutput() const
+{
+  return m_Importer->GetOutput();
+}
+
+/**
+ * Get the importer filter
+ */
+template <typename TInputImage>
+vtkImageImport *
+ImageToVTKImageFilter<TInputImage>
+::GetImporter() const
+{
+  return m_Importer;
+}
+
+/**
+ * Get the exporter filter
+ */
+template <typename TInputImage>
+typename ImageToVTKImageFilter<TInputImage>::ExporterFilterType *
+ImageToVTKImageFilter<TInputImage>
+::GetExporter() const
+{
+  return m_Exporter.GetPointer();
+}
+
+/**
+ * Delegate the Update to the importer
+ */
+template <typename TInputImage>
+void
+ImageToVTKImageFilter<TInputImage>
+::Update()
+{
+  m_Importer->Update();
+}
+
+/**
+ * Delegate the UpdateLargestPossibleRegion to the importer
+ */
+template <typename TInputImage>
+void
+ImageToVTKImageFilter<TInputImage>
+::UpdateLargestPossibleRegion()
+{
+  m_Importer->UpdateWholeExtent();
+}
+
+} // end namespace itk
+
+#endif
diff --git a/lib/cpInstances/Images/itkVTKImageToImageFilter.h b/lib/cpInstances/Images/itkVTKImageToImageFilter.h
new file mode 100644 (file)
index 0000000..b4427c8
--- /dev/null
@@ -0,0 +1,100 @@
+/*=========================================================================
+ *
+ *  Copyright Insight Software Consortium
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *=========================================================================*/
+
+#ifndef itkVTKImageToImageFilter_h
+#define itkVTKImageToImageFilter_h
+
+#include "itkVTKImageImport.h"
+#include "vtkImageExport.h"
+#include "vtkImageData.h"
+#include "vtkSmartPointer.h"
+
+#ifndef vtkFloatingPointType
+#define vtkFloatingPointType float
+#endif
+
+namespace itk
+{
+
+/** \class VTKImageToImageFilter
+ * \brief Converts a VTK image into an ITK image and plugs a
+ *  VTK data pipeline to an ITK datapipeline.
+ *
+ *  This class puts together an itk::VTKImageImport and a vtk::ImageExport.
+ *  It takes care of the details related to the connection of ITK and VTK
+ *  pipelines. The User will perceive this filter as an adaptor to which
+ *  a vtkImageData can be plugged as input and an itk::Image is produced as
+ *  output.
+ *
+ * \ingroup ITKVtkGlue
+ */
+template <typename TOutputImage >
+class VTKImageToImageFilter : public VTKImageImport< TOutputImage >
+{
+public:
+  /** Standard class typedefs. */
+  typedef VTKImageToImageFilter             Self;
+  typedef VTKImageImport< TOutputImage >    Superclass;
+  typedef SmartPointer<Self>                Pointer;
+  typedef SmartPointer<const Self>          ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VTKImageToImageFilter, VTKImageImport);
+
+  /** Some typedefs. */
+  typedef TOutputImage                              OutputImageType;
+  typedef typename    OutputImageType::ConstPointer OutputImagePointer;
+
+  /** Set the input in the form of a vtkImageData */
+  void SetInput( vtkImageData * );
+  using Superclass::SetInput;
+
+  /** Return the internal VTK image exporter filter.
+      This is intended to facilitate users the access
+      to methods in the exporter */
+  vtkImageExport * GetExporter() const;
+
+  /** Return the internal ITK image importer filter.
+      This is intended to facilitate users the access
+      to methods in the importer.
+      */
+  const Superclass * GetImporter() const;
+
+protected:
+  VTKImageToImageFilter();
+  virtual ~VTKImageToImageFilter();
+
+private:
+  VTKImageToImageFilter(const Self&) ITK_DELETE_FUNCTION;
+  void operator=(const Self&) ITK_DELETE_FUNCTION;
+
+  typedef vtkSmartPointer<vtkImageExport> ImageExportPointer;
+  ImageExportPointer m_Exporter;
+
+};
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkVTKImageToImageFilter.hxx"
+#endif
+
+#endif
diff --git a/lib/cpInstances/Images/itkVTKImageToImageFilter.hxx b/lib/cpInstances/Images/itkVTKImageToImageFilter.hxx
new file mode 100644 (file)
index 0000000..334b02b
--- /dev/null
@@ -0,0 +1,107 @@
+/*=========================================================================
+ *
+ *  Copyright Insight Software Consortium
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0.txt
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *=========================================================================*/
+
+#ifndef itkVTKImageToImageFilter_hxx
+#define itkVTKImageToImageFilter_hxx
+
+#include "itkVTKImageToImageFilter.h"
+
+#include "vtkVersion.h"
+
+namespace itk
+{
+
+/**
+ * Constructor
+ */
+template <typename TOutputImage>
+VTKImageToImageFilter<TOutputImage>
+::VTKImageToImageFilter()
+{
+
+  m_Exporter = vtkImageExport::New();
+
+  this->SetUpdateInformationCallback( m_Exporter->GetUpdateInformationCallback());
+  this->SetPipelineModifiedCallback( m_Exporter->GetPipelineModifiedCallback());
+  this->SetWholeExtentCallback( m_Exporter->GetWholeExtentCallback());
+  this->SetSpacingCallback( m_Exporter->GetSpacingCallback());
+  this->SetOriginCallback( m_Exporter->GetOriginCallback());
+  this->SetScalarTypeCallback( m_Exporter->GetScalarTypeCallback());
+  this->SetNumberOfComponentsCallback( m_Exporter->GetNumberOfComponentsCallback());
+  this->SetPropagateUpdateExtentCallback( m_Exporter->GetPropagateUpdateExtentCallback());
+  this->SetUpdateDataCallback( m_Exporter->GetUpdateDataCallback());
+  this->SetDataExtentCallback( m_Exporter->GetDataExtentCallback());
+  this->SetBufferPointerCallback( m_Exporter->GetBufferPointerCallback());
+  this->SetCallbackUserData( m_Exporter->GetCallbackUserData());
+
+}
+
+/**
+ * Destructor
+ */
+template <typename TOutputImage>
+VTKImageToImageFilter<TOutputImage>
+::~VTKImageToImageFilter()
+{
+  if( m_Exporter )
+    {
+    m_Exporter->Delete();
+    m_Exporter = 0;
+    }
+}
+
+/**
+ * Set a vtkImageData as input
+ */
+template <typename TOutputImage>
+void
+VTKImageToImageFilter<TOutputImage>
+::SetInput( vtkImageData * inputImage )
+{
+#if VTK_MAJOR_VERSION <= 5
+  m_Exporter->SetInput( inputImage );
+#else
+  m_Exporter->SetInputData( inputImage );
+#endif
+}
+
+/**
+ * Get the exporter filter
+ */
+template <typename TOutputImage>
+vtkImageExport *
+VTKImageToImageFilter<TOutputImage>
+::GetExporter() const
+{
+  return m_Exporter;
+}
+
+/**
+ * Get the importer filter
+ */
+template <typename TOutputImage>
+const typename VTKImageToImageFilter<TOutputImage>::Superclass *
+VTKImageToImageFilter<TOutputImage>
+::GetImporter() const
+{
+  return this;
+}
+
+} // end namespace itk
+
+#endif
diff --git a/lib/cpPlugins/Config.h.in b/lib/cpPlugins/Config.h.in
new file mode 100644 (file)
index 0000000..c10ee8d
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef __cpPlugins__Config__h__
+#define __cpPlugins__Config__h__
+
+#include <cpPlugins_Export.h>
+#include <stdexcept>
+#include <cpPlugins/RealConfig.h>
+
+/*
+ * =========================================================================
+ * Identify OS
+ * =========================================================================
+ */
+#define cpPlugins_OS_@CMAKE_SYSTEM_NAME@
+#ifdef cpPlugins_OS_Windows
+#  define cpPlugins_LIB_PREFIX     ""
+#  define cpPlugins_ENV_SEPARATOR  ";"
+#  define cpPlugins_PATH_SEPARATOR '\\'
+#  define cpPlugins_LIB_EXT        ".dll"
+#else // cpPlugins_OS_Windows
+#  define cpPlugins_LIB_PREFIX     "lib"
+#  define cpPlugins_ENV_SEPARATOR  ":"
+#  define cpPlugins_PATH_SEPARATOR '/'
+#  ifdef cpPlugins_OS_Linux
+#    define cpPlugins_LIB_EXT ".so"
+#  else // cpPlugins_OS_Linux
+#    define cpPlugins_LIB_EXT ".dylib"
+#  endif // cpPlugins_OS_Linux
+#endif // cpPlugins_OS_Windows
+
+#ifdef cpPlugins_OS_Windows
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN
+#  endif // WIN32_LEAN_AND_MEAN
+#  define NOMINMAX
+#  include <windows.h>
+#  include <tchar.h>
+#endif // cpPlugins_OS_Windows
+
+/*
+ * =========================================================================
+ * Some global values
+ * =========================================================================
+ */
+#define cpPlugins_PATHS "cpPlugins_PATHS"
+#define cpPlugins_CONFIG "cpPlugins_Libraries.config"
+
+#define cpPlugins_QT4_@QT4_FOUND@
+#ifdef cpPlugins_QT4_TRUE
+#  ifndef cpPlugins_QT4
+#    define cpPlugins_QT4
+#  endif // cpPlugins_QT4
+#else // cpPlugins_QT4_TRUE
+#  undef cpPlugins_QT4
+#endif // cpPlugins_QT4_TRUE
+
+/*
+ * =========================================================================
+ * Version numbers and strings
+ * =========================================================================
+ */
+#define cpPlugins_MAJOR_VERSION   @prj_MAJ_VER@
+#define cpPlugins_MINOR_VERSION   @prj_MIN_VER@
+#define cpPlugins_RELEASE_VERSION @prj_REL_VER@
+#define cpPlugins_VERSION         "@prj_VERSION@"
+#define cpPlugins_SHORT_VERSION   "@prj_SHORT_VERSION@"
+#define cpPlugins_OpenGL_BackEnd_@VTK_RENDERING_BACKEND@
+
+/*
+ * =========================================================================
+ * Language related macros
+ * =========================================================================
+ */
+#if __cplusplus >= 201103L
+#  define cpPlugins_OVERRIDE override
+#  define cpPlugins_DELETE_FUNCTION =delete
+#  define cpPlugins_NULLPTR  nullptr
+#  define cpPlugins_NOEXCEPT noexcept
+#  define cpPlugins_HAS_CXX11_STATIC_ASSERT
+#  define cpPlugins_HAS_CXX11_RVREF
+#else // __cplusplus >= 201103L
+#  define cpPlugins_OVERRIDE
+#  define cpPlugins_DELETE_FUNCTION
+#  define cpPlugins_NULLPTR  NULL
+#  define cpPlugins_NOEXCEPT throw()
+#endif // __cplusplus >= 201103L
+
+/*
+ * =========================================================================
+ * Some macros
+ * =========================================================================
+ */
+
+#define cpPlugins_Id_Macro( _class, _category )                         \
+  public:                                                               \
+  virtual const char* GetClassName( ) const cpPlugins_OVERRIDE          \
+  { return( #_class ); }                                                \
+  virtual const char* GetClassCategory( ) const cpPlugins_OVERRIDE      \
+  { return( #_category ); }
+
+#define cpPluginsObject( _cls, _scls, _cat )                            \
+  public:                                                               \
+  typedef _cls                            Self;                         \
+  typedef _scls                           Superclass;                   \
+  typedef itk::SmartPointer< Self >       Pointer;                      \
+  typedef itk::SmartPointer< const Self > ConstPointer;                 \
+  public:                                                               \
+  itkNewMacro( Self );                                                  \
+  itkTypeMacro( _cls, _scls );                                          \
+  public:                                                               \
+  virtual const char* GetClassName( ) const cpPlugins_OVERRIDE          \
+  { return( #_cls ); }                                                  \
+  virtual const char* GetClassCategory( ) const cpPlugins_OVERRIDE      \
+  { return( #_cat ); }                                                  \
+  protected:                                                            \
+  _cls( );                                                              \
+  virtual ~_cls( );                                                     \
+  virtual void _GenerateData( ) cpPlugins_OVERRIDE;                     \
+  private:                                                              \
+  _cls( const Self& );                                                  \
+  Self& operator=( const Self& )
+
+#define cpPlugins_Compatibility_Macro                           \
+  virtual bool IsCompatible(                                    \
+    const DataObject* other                                     \
+    ) const cpPlugins_OVERRIDE                                  \
+  {                                                             \
+    return( dynamic_cast< const Self* >( other ) != NULL );     \
+  }
+
+#endif // __cpPlugins__Config__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Interface/Loader.cxx b/lib/cpPlugins/Interface/Loader.cxx
new file mode 100644 (file)
index 0000000..dfb9bfb
--- /dev/null
@@ -0,0 +1,278 @@
+#include <cpPlugins/Interface/Loader.h>
+#include <cpPlugins/OS/FileSystem.h>
+#include <cpPlugins/OS/DLLManager.h>
+#include <cpPlugins/OS/String.h>
+#include <set>
+
+// -------------------------------------------------------------------------
+// Static attributes initialization
+// -------------------------------------------------------------------------
+
+cpPlugins::Interface::Loader::TLibraries
+cpPlugins::Interface::Loader::m_Libraries;
+
+cpPlugins::Interface::Loader::TFiltersToLibrariesReferences
+cpPlugins::Interface::Loader::m_References;
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Loader::
+Loader( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Loader::
+~Loader( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Loader::
+Register( const std::string& filename )
+{
+  // Canonicalize path
+  std::string path = cpPlugins::OS::FileSystem::CanonicalPath( filename );
+  if( path == "" )
+  {
+    throw std::runtime_error( "Unknown library file \"" + filename + "\"." );
+    return;
+
+  } // fi
+
+  // Ignore if the library is already loaded
+  if( Self::m_Libraries.find( path ) != Self::m_Libraries.end( ) )
+    return;
+
+  // Try to open library
+  void* hnd = NULL;
+  try
+  {
+    hnd = cpPlugins::OS::DLLManager::Open( path );
+  }
+  catch( std::exception& err )
+  {
+    throw std::runtime_error( err.what( ) );
+
+  } // yrt
+  if( hnd == NULL )
+    throw std::runtime_error( "Unknown file type for \"" + filename + "\"." );
+
+  // Get interfacing functions
+  TContentsFunc contents_func = NULL;
+  try
+  {
+    contents_func = reinterpret_cast< TContentsFunc >(
+      cpPlugins::OS::DLLManager::Sym( hnd, "cpPlugins_Contents" )
+      );
+  }
+  catch( std::exception& err )
+  {
+    cpPlugins::OS::DLLManager::Close( hnd );
+    throw std::runtime_error( "Library \"" + filename + "\" is not recognized as a cpPlugins library (i.e. \"cpPlugins_Contents\" function not found)." );
+
+  } // yrt
+
+  TCreatorFunc creator_func = NULL;
+  try
+  {
+    creator_func = reinterpret_cast< TCreatorFunc >(
+      cpPlugins::OS::DLLManager::Sym( hnd, "cpPlugins_Creator" )
+      );
+  }
+  catch( std::exception& err )
+  {
+    cpPlugins::OS::DLLManager::Close( hnd );
+    throw std::runtime_error( "Library \"" + filename + "\" is not recognized as a cpPlugins library (i.e. \"cpPlugins_Creator\" function not found)." );
+
+  } // yrt
+
+  // Keep track of handlers
+  Self::m_Libraries[ path ] = THandlers( hnd, contents_func, creator_func );
+
+  // Get library contents
+  std::vector< std::string > contents;
+  contents_func( &contents );
+
+  // Register contents
+  for( auto c : contents )
+  {
+    std::vector< std::string > t = cpPlugins::OS::String::Tokenize( c, "@" );
+    if( t.size( ) == 2 )
+      Self::m_References[ t[ 1 ] ][ t[ 0 ] ] = path;
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Loader::
+RegisterFromDirectory( const std::string& dirname )
+{
+  std::string patt = "*";
+  patt += cpPlugins_LIB_EXT;
+  std::set< std::string > files =
+    cpPlugins::OS::FileSystem::LoadDirContents(
+      dirname, false, patt
+      );
+  for( auto f : files )
+  {
+    try
+    {
+      Register( f );
+    }
+    catch( ... )
+    {
+      // Do nothing
+
+    } // yrt
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Loader::
+GuessEnvironment( const std::string& dirname )
+{
+  std::stringstream fname;
+  fname << dirname << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS;
+  std::string buffer;
+  if( cpPlugins::OS::FileSystem::Read( buffer, fname.str( ) ) )
+  {
+    std::istringstream input( buffer );
+    for( std::string line; std::getline( input, line ); )
+      Self::RegisterFromDirectory( line );
+  }
+  else
+    Self::RegisterFromDirectory( dirname );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Loader::
+SaveEnvironment( const std::string& dirname )
+{
+  std::set< std::string > locations;
+  for( auto lIt : Self::m_Libraries )
+    locations.insert(
+      cpPlugins::OS::FileSystem::SplitPath( lIt.first ).first
+      );
+  std::stringstream buffer;
+  for( auto loc : locations )
+    buffer << loc << std::endl;
+  std::stringstream fname;
+  fname << dirname << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS;
+  cpPlugins::OS::FileSystem::Write( buffer.str( ), fname.str( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Loader::
+UnRegister( const std::string& filename )
+{
+  // Canonicalize path
+  std::string path = cpPlugins::OS::FileSystem::CanonicalPath( filename );
+  if( path == "" )
+    return;
+
+  auto lIt = Self::m_Libraries.find( path );
+  if( lIt != Self::m_Libraries.end( ) )
+  {
+    // Unload handlers
+    cpPlugins::OS::DLLManager::Close( std::get< 0 >( lIt->second ) );
+    Self::m_Libraries.erase( lIt );
+
+    // Erase references
+    auto cIt = Self::m_References.begin( );
+    while( cIt != Self::m_References.end( ) )
+    {
+      auto fIt = cIt->second.begin( );
+      while( fIt != cIt->second.end( ) )
+      {
+        if( fIt->second == path )
+        {
+          cIt->second.erase( fIt );
+          fIt = cIt->second.begin( );
+        }
+        else
+          ++fIt;
+
+      } // elihw
+      if( cIt->second.size( ) == 0 )
+      {
+        Self::m_References.erase( cIt );
+        cIt = Self::m_References.begin( );
+      }
+      else
+        ++cIt;
+
+    } // elihw
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Loader::
+UnRegisterAll( )
+{
+  for( auto lIt : Self::m_Libraries )
+    cpPlugins::OS::DLLManager::Close( std::get< 0 >( lIt.second ) );
+  Self::m_Libraries.clear( );
+  Self::m_References.clear( );
+}
+
+// -------------------------------------------------------------------------
+std::map< std::string, std::set< std::string > >
+cpPlugins::Interface::Loader::
+GetFilters( ) const
+{
+  std::map< std::string, std::set< std::string > > filters;
+  for( auto ref : Self::m_References )
+    for( auto fil : ref.second )
+      filters[ ref.first ].insert( fil.first );
+  return( filters );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::ProcessObject::Pointer cpPlugins::Interface::Loader::
+CreateFilter(
+  const std::string& category, const std::string& filter,
+  const std::string& name
+  )
+{
+  cpPlugins::Pipeline::ProcessObject::Pointer ptr = NULL;
+  auto cIt = Self::m_References.find( category );
+  if( cIt != Self::m_References.end( ) )
+  {
+    auto fIt = cIt->second.find( filter );
+    if( fIt != cIt->second.end( ) )
+    {
+      auto lIt = Self::m_Libraries.find( fIt->second );
+      if( lIt != Self::m_Libraries.end( ) )
+      {
+        auto creator_func = std::get< 2 >( lIt->second );
+        if( creator_func != NULL )
+        {
+          itk::LightObject::Pointer l_ptr;
+          creator_func( l_ptr, category, filter );
+          ptr =
+            dynamic_cast< cpPlugins::Pipeline::ProcessObject* >(
+              l_ptr.GetPointer( )
+              );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+
+  if( ptr.IsNotNull( ) )
+  {
+    if( name == "" )
+      ptr->SetName( filter + "@" + category );
+    else
+      ptr->SetName( name );
+
+  } // fi
+  return( ptr );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Interface/Loader.h b/lib/cpPlugins/Interface/Loader.h
new file mode 100644 (file)
index 0000000..115196c
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __cpPlugins__Interface__Loader__h__
+#define __cpPlugins__Interface__Loader__h__
+
+#include <cpPlugins/Config.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+#include <iostream>
+#include <map>
+#include <vector>
+
+namespace cpPlugins
+{
+  namespace Interface
+  {
+    /**
+     */
+    class cpPlugins_EXPORT Loader
+    {
+    public:
+      typedef Loader Self;
+
+    public:
+      typedef void ( *TContentsFunc )( std::vector< std::string >* );
+      typedef void ( *TCreatorFunc )( itk::LightObject::Pointer& ptr, const std::string& c, const std::string& f );
+      typedef std::tuple< void*, TContentsFunc, TCreatorFunc > THandlers;
+      typedef std::map< std::string, THandlers > TLibraries;
+      typedef std::map< std::string, std::map< std::string, std::string > >
+      TFiltersToLibrariesReferences;
+
+    public:
+      Loader( );
+      virtual ~Loader( );
+
+      void Register( const std::string& filename );
+      void RegisterFromDirectory( const std::string& dirname );
+      void GuessEnvironment( const std::string& dirname );
+      void SaveEnvironment( const std::string& dirname );
+      void UnRegister( const std::string& filename );
+      void UnRegisterAll( );
+
+      std::map< std::string, std::set< std::string > > GetFilters( ) const;
+
+      cpPlugins::Pipeline::ProcessObject::Pointer CreateFilter(
+        const std::string& category, const std::string& filter,
+        const std::string& name = ""
+        );
+
+    protected:
+      static TLibraries m_Libraries;
+      static TFiltersToLibrariesReferences m_References;
+
+    public:
+      friend std::ostream& operator<<( std::ostream& o, const Loader& l )
+        {
+          o << "cpPlugins:" << std::endl;
+          for( auto c : l.m_References )
+          {
+            o << "  + " << c.first << std::endl;
+            for( auto f : c.second )
+              o << "  |--> " << f.first << " (" << f.second << ")" << std::endl;
+
+          } // rof
+          return( o );
+        }
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Interface__Loader__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Interface/Workspace.cxx b/lib/cpPlugins/Interface/Workspace.cxx
new file mode 100644 (file)
index 0000000..3822969
--- /dev/null
@@ -0,0 +1,627 @@
+#include <cpPlugins/Interface/Workspace.h>
+#include <cpPlugins/Pipeline/Widget.h>
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Clear( )
+{
+  this->m_Filters.clear( );
+}
+
+// -------------------------------------------------------------------------
+std::vector< std::string > cpPlugins::Interface::Workspace::
+GetFiltersNames( ) const
+{
+  std::vector< std::string > n;
+  for( auto i : this->m_Filters )
+    n.push_back( i.first );
+  return( n );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Workspace::
+TFilter* cpPlugins::Interface::Workspace::
+GetFilter( const std::string& name )
+{
+  auto i = this->m_Filters.find( name );
+  if( i != this->m_Filters.end( ) )
+    return( i->second.GetPointer( ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Interface::Workspace::
+TFilter* cpPlugins::Interface::Workspace::
+GetFilter( const std::string& name ) const
+{
+  auto i = this->m_Filters.find( name );
+  if( i != this->m_Filters.end( ) )
+    return( i->second.GetPointer( ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Workspace::
+TWidget* cpPlugins::Interface::Workspace::
+GetWidget( const std::string& name )
+{
+  TFilter* process = this->GetFilter( name );
+  return( dynamic_cast< TWidget* >( process ) );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Interface::Workspace::
+TWidget* cpPlugins::Interface::Workspace::
+GetWidget( const std::string& name ) const
+{
+  const TFilter* process = this->GetFilter( name );
+  return( dynamic_cast< const TWidget* >( process ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+HasFilter( const std::string& name ) const
+{
+  return( this->m_Filters.find( name ) != this->m_Filters.end( ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+HasWidget( const std::string& name ) const
+{
+  const TWidget* wdg = this->GetWidget( name );
+  return( wdg != NULL );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Workspace::
+TFilter* cpPlugins::Interface::Workspace::
+CreateFilter( const std::string& category, const std::string& filter )
+{
+  typedef cpPlugins::Pipeline::Widget _TWidget;
+
+  TFilter::Pointer o = this->m_Loader.CreateFilter( category, filter );
+  if( o.IsNotNull( ) )
+  {
+    // Choose a name
+    std::string name = filter;
+    while( this->GetFilter( name ) != NULL )
+      name += std::string( "_" );
+    o->SetPrintExecution( this->m_PrintExecution );
+    o->SetName( name );
+
+    // Interactors
+    for(
+      auto i = this->m_Interactors.begin( );
+      i != this->m_Interactors.end( );
+      ++i
+      )
+      o->AddInteractor( *i );
+
+    // Finish association
+    this->m_Filters[ name ] = o;
+
+  } // fi
+  return( o.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+RenameFilter( const std::string& old_name, const std::string& new_name )
+{
+  auto o = this->m_Filters.find( old_name );
+  auto n = this->m_Filters.find( new_name );
+  if( o != this->m_Filters.end( ) && n == this->m_Filters.end( ) )
+  {
+    // Rename filter
+    o->second->SetName( new_name );
+    this->m_Filters[ new_name ] = o->second;
+    this->m_Filters.erase( o );
+
+    // Rename exposed ports
+    /* TODO
+       auto e = this->m_ExposedInputs.begin( );
+       for( ; e != this->m_ExposedInputs.end( ); ++e )
+       if( e->second.first == old_name )
+       e->second.first = new_name;
+       e = this->m_ExposedOutputs.begin( );
+       for( ; e != this->m_ExposedOutputs.end( ); ++e )
+       if( e->second.first == old_name )
+       e->second.first = new_name;
+    */
+
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+RemoveFilter( const std::string& name )
+{
+  auto i = this->m_Filters.find( name );
+  if( i != this->m_Filters.end( ) )
+  {
+    i->second->Disconnect( );
+    this->m_Filters.erase( i );
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+SetPrintExecution( bool b )
+{
+  this->m_PrintExecution = b;
+  for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
+    i->second->SetPrintExecution( b );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+PrintExecutionOn( )
+{
+  this->SetPrintExecution( true );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+PrintExecutionOff( )
+{
+  this->SetPrintExecution( true );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+AddInteractor( vtkRenderWindowInteractor* iren )
+{
+  if( iren != NULL )
+  {
+    this->m_Interactors.insert( iren );
+    for( auto f : this->m_Filters )
+      f.second->AddInteractor( iren );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+Connect(
+  const std::string& origin_filter,
+  const std::string& origin_output,
+  const std::string& destination_filter,
+  const std::string& destination_input
+  )
+{
+  // Get filters and check pertinence
+  TFilter* origin = this->GetFilter( origin_filter );
+  TFilter* destination = this->GetFilter( destination_filter );
+  if( origin == NULL || destination == NULL )
+    return( false );
+  if( !( destination->HasInput( destination_input ) ) )
+    return( false );
+  if( !( origin->HasOutput( origin_output ) ) )
+    return( false );
+
+  // Check if there is room for a new connection
+  bool ok = true;
+  if( destination->IsInputMultiple( destination_input ) )
+  {
+    for(
+      unsigned int i = 0;
+      i < destination->GetInputSize( destination_input );
+      ++i
+      )
+      if(
+        destination->GetInput( destination_input, i )->GetSource( ) == origin
+        )
+        ok = false;
+  }
+  else
+    ok = ( destination->GetInput( destination_input ) == NULL );
+  if( ok )
+    destination->AddInput(
+      destination_input,
+      origin->GetOutput( origin_output )
+      );
+  return( ok );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+Connect(
+  TDataObject* input,
+  const std::string& destination_filter,
+  const std::string& destination_input
+  )
+{
+  // Get filters and check pertinence
+  if( input == NULL )
+    return( false );
+  TFilter* destination = this->GetFilter( destination_filter );
+  if( destination == NULL )
+    return( false );
+  if( !( destination->HasInput( destination_input ) ) )
+    return( false );
+
+  // Check if there is room for a new connection
+  bool ok = true;
+  if( destination->IsInputMultiple( destination_input ) )
+  {
+    for(
+      unsigned int i = 0;
+      i < destination->GetInputSize( destination_input );
+      ++i
+      )
+      if(
+        destination->GetInput( destination_input, i )->GetSource( ) ==
+        input->GetSource( )
+        )
+        ok = false;
+  }
+  else
+    ok = ( destination->GetInput( destination_input ) == NULL );
+  if( ok )
+    destination->AddInput(
+      destination_input,
+      input
+      );
+  return( ok );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+Disconnect(
+  const std::string& origin_filter,
+  const std::string& origin_output,
+  const std::string& destination_filter,
+  const std::string& destination_input
+  )
+{
+  // Get filters and check pertinence
+  TFilter* origin = this->GetFilter( origin_filter );
+  TFilter* destination = this->GetFilter( destination_filter );
+  if( origin == NULL || destination == NULL )
+    return( false );
+  if( !( destination->HasInput( destination_input ) ) )
+    return( false );
+  if( !( origin->HasOutput( origin_output ) ) )
+    return( false );
+
+  // Check if there is room for a new connection
+  bool ok = false;
+  unsigned int del_id = 0;
+  for(
+    unsigned int i = 0;
+    i < destination->GetInputSize( destination_input );
+    ++i
+    )
+    if(
+      destination->GetInput( destination_input, i )->GetSource( ) == origin
+      )
+    {
+      ok = true;
+      del_id = i;
+
+    } // fi
+  if( ok )
+    destination->DisconnectInput( destination_input, del_id );
+  return( ok );
+}
+
+// -------------------------------------------------------------------------
+/*
+const cpPlugins::Interface::Workspace::
+TExposedPorts& cpPlugins::Interface::Workspace::
+GetExposedInputs( ) const
+{
+  return( this->m_ExposedInputs );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Interface::Workspace::
+TExposedPorts& cpPlugins::Interface::Workspace::
+GetExposedOutputs( ) const
+{
+  return( this->m_ExposedOutputs );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::DataObject* cpPlugins::Interface::Workspace::
+GetExposedOutput( const std::string& name )
+{
+  auto i = this->m_ExposedOutputs.find( name );
+  if( i != this->m_ExposedOutputs.end( ) )
+  {
+    auto f = this->GetFilter( i->second.first );
+    if( f != NULL )
+      return( f->GetOutput( i->second.second ) );
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Pipeline::DataObject* cpPlugins::Interface::Workspace::
+GetExposedOutput( const std::string& name ) const
+{
+  auto i = this->m_ExposedOutputs.find( name );
+  if( i != this->m_ExposedOutputs.end( ) )
+  {
+    auto f = this->GetFilter( i->second.first );
+    if( f != NULL )
+      return( f->GetOutput( i->second.second ) );
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+ExposeInput(
+  const std::string& name,
+  const std::string& filter, const std::string& filter_input
+  )
+{
+  auto i = this->m_ExposedInputs.find( name );
+  if( i == this->m_ExposedInputs.end( ) )
+  {
+    this->m_ExposedInputs[ name ] =
+      std::pair< std::string, std::string >( filter, filter_input );
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+ExposeOutput(
+  const std::string& name,
+  const std::string& filter, const std::string& filter_output
+  )
+{
+  auto i = this->m_ExposedOutputs.find( name );
+  if( i == this->m_ExposedOutputs.end( ) )
+  {
+    this->m_ExposedOutputs[ name ] =
+      std::pair< std::string, std::string >( filter, filter_output );
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+HideInput( const std::string& name )
+{
+  auto i = this->m_ExposedInputs.find( name );
+  if( i != this->m_ExposedInputs.end( ) )
+    this->m_ExposedInputs.erase( i );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+HideOutput( const std::string& name )
+{
+  auto i = this->m_ExposedOutputs.find( name );
+  if( i != this->m_ExposedOutputs.end( ) )
+    this->m_ExposedOutputs.erase( i );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+RenameExposedInput(
+  const std::string& old_name, const std::string& new_name
+  )
+{
+  auto o = this->m_ExposedInputs.find( old_name );
+  auto n = this->m_ExposedInputs.find( new_name );
+  if( o != this->m_ExposedInputs.end( ) && n == this->m_ExposedInputs.end( ) )
+  {
+    this->m_ExposedInputs[ new_name ] = o->second;
+    this->m_ExposedInputs.erase( o );
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+RenameExposedOutput(
+  const std::string& old_name, const std::string& new_name
+  )
+{
+  auto o = this->m_ExposedOutputs.find( old_name );
+  auto n = this->m_ExposedOutputs.find( new_name );
+  if(
+    o != this->m_ExposedOutputs.end( ) && n == this->m_ExposedOutputs.end( )
+    )
+  {
+    this->m_ExposedOutputs[ new_name ] = o->second;
+    this->m_ExposedOutputs.erase( o );
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+std::vector< std::pair< std::string, std::string > >
+cpPlugins::Interface::Workspace::
+GetConnections(
+  const std::string& origin, const std::string& destination
+  ) const
+{
+  std::vector< std::pair< std::string, std::string > > conns;
+  auto orig = this->GetFilter( origin );
+  auto dest = this->GetFilter( destination );
+  if( orig != NULL && dest != NULL )
+  {
+    auto outs = orig->GetOutputsNames( );
+    auto ins = dest->GetInputsNames( );
+    for( auto o = outs.begin( ); o != outs.end( ); ++o )
+    {
+      for( auto i = ins.begin( ); i != ins.end( ); ++i )
+      {
+        unsigned int nInputs = dest->GetInputSize( *i );
+        for( unsigned j = 0; j < nInputs; ++j )
+        {
+          auto od = orig->GetOutput( *o );
+          auto id = dest->GetInput( *i, j );
+          if( od != NULL && od == id )
+            conns.push_back(
+              std::pair< std::string, std::string >( *o, *i )
+              );
+
+        } // rof
+
+      } // rof
+
+    } // rof
+
+  } // fi
+  return( conns );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Connect(
+  const std::string& orig_filter, const std::string& dest_filter,
+  const std::string& output_name, const std::string& input_name
+  )
+{
+  auto o = this->GetFilter( orig_filter );
+  auto d = this->GetFilter( dest_filter );
+  if( o != NULL && d != NULL )
+  {
+    try
+    {
+      d->AddInput( input_name, o->GetOutput( output_name ) );
+    }
+    catch( std::exception& err )
+    {
+      throw std::logic_error(
+        std::string( "Error connecting \"" ) +
+        output_name + std::string( "@" ) + orig_filter +
+        std::string( "\" with \"" ) +
+        input_name + std::string( "@" ) + dest_filter +
+        std::string( "\": " ) +
+        err.what( )
+        );
+
+    } // yrt
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Connect(
+  cpPlugins::Pipeline::DataObject* output,
+  const std::string& dest_filter, const std::string& input_name
+  )
+{
+  auto d = this->GetFilter( dest_filter );
+  if( d != NULL )
+    d->AddInput( input_name, output );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Connect(
+  cpPlugins::Pipeline::DataObject* output,
+  const std::string& exposed_input_name
+  )
+{
+  auto i = this->m_ExposedInputs.find( exposed_input_name );
+  if( i != this->m_ExposedInputs.end( ) )
+    this->Connect( output, i->second.first, i->second.second );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Disconnect(
+  const std::string& orig_filter, const std::string& dest_filter,
+  const std::string& output_name, const std::string& input_name
+  )
+{
+  auto orig = this->GetFilter( orig_filter );
+  auto dest = this->GetFilter( dest_filter );
+  if( orig != NULL && dest != NULL )
+  {
+    auto out = orig->GetOutput( output_name );
+    auto in = dest->GetInput( input_name );
+    if( out != NULL && out == in )
+      dest->SetInput(
+        input_name, ( cpPlugins::Pipeline::DataObject* )( NULL )
+        );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Disconnect(
+  const std::string& dest_filter, const std::string& input_name
+  )
+{
+  throw std::logic_error( "Disconnect 1" );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Disconnect( const std::string& dest_filter )
+{
+  throw std::logic_error( "Disconnect 2" );
+}
+*/
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Update( )
+{
+  for( auto f = this->m_Filters.begin( ); f != this->m_Filters.end( ); ++f )
+    f->second->Update( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Update( const std::string& name )
+{
+  auto filter = this->GetFilter( name );
+  if( filter != NULL )
+    filter->Update( );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Workspace::
+Workspace( )
+  : Superclass( ),
+    m_PrintExecution( false )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Workspace::
+~Workspace( )
+{
+  /* TODO
+     this->m_ExposedOutputs.clear( );
+     this->m_ExposedInputs.clear( );
+  */
+  this->m_Filters.clear( );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Interface/Workspace.h b/lib/cpPlugins/Interface/Workspace.h
new file mode 100644 (file)
index 0000000..745bd98
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef __cpPlugins__Interface__Workspace__h__
+#define __cpPlugins__Interface__Workspace__h__
+
+#include <cpPlugins/Interface/Loader.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+#include <cpPlugins/Pipeline/Widget.h>
+#include <itkObject.h>
+
+class vtkRenderWindowInteractor;
+
+namespace cpPlugins
+{
+  namespace Interface
+  {
+    /** \brief A complex pipeline
+     */
+    class cpPlugins_EXPORT Workspace
+      : public itk::Object
+    {
+    public:
+      typedef Workspace                       Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+      typedef cpPlugins::Pipeline::DataObject    TDataObject;
+      typedef cpPlugins::Pipeline::ProcessObject TFilter;
+      typedef cpPlugins::Pipeline::Widget        TWidget;
+      typedef cpPlugins::Interface::Loader          TLoader;
+
+      typedef std::map< std::string, TFilter::Pointer > TFilters;
+
+      /* TODO
+         typedef
+         std::map< std::string, std::pair< std::string, std::string > >
+         TExposedPorts;
+      */
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( Workspace, itk::Object );
+
+    public:
+      // Workspace IO
+      void Load( const std::string& fname );
+      void Save( const std::string& fname ) const;
+
+      // Memory management
+      void Clear( );
+
+      // Filter management
+      std::vector< std::string > GetFiltersNames( ) const;
+      TFilter* GetFilter( const std::string& name );
+      const TFilter* GetFilter( const std::string& name ) const;
+      TWidget* GetWidget( const std::string& name );
+      const TWidget* GetWidget( const std::string& name ) const;
+      bool HasFilter( const std::string& name ) const;
+      bool HasWidget( const std::string& name ) const;
+      TFilter* CreateFilter(
+        const std::string& category, const std::string& filter
+        );
+      bool RenameFilter(
+        const std::string& old_name, const std::string& new_name
+        );
+      bool RemoveFilter( const std::string& name );
+
+      void SetPrintExecution( bool b );
+      void PrintExecutionOn( );
+      void PrintExecutionOff( );
+
+      // Interactors
+      void AddInteractor( vtkRenderWindowInteractor* iren );
+
+      // Connection management
+      bool Connect(
+        const std::string& origin_filter,
+        const std::string& origin_output,
+        const std::string& destination_filter,
+        const std::string& destination_input
+        );
+      bool Connect(
+        TDataObject* input,
+        const std::string& destination_filter,
+        const std::string& destination_input
+        );
+      bool Disconnect(
+        const std::string& origin_filter,
+        const std::string& origin_output,
+        const std::string& destination_filter,
+        const std::string& destination_input
+        );
+
+      /* TODO
+         std::vector< std::pair< std::string, std::string > > GetConnections(
+         const std::string& origin, const std::string& destination
+         ) const;
+         void Connect(
+         const std::string& orig_filter, const std::string& dest_filter,
+         const std::string& output_name, const std::string& input_name
+         );
+         void Connect(
+         cpPlugins::Pipeline::DataObject* output,
+         const std::string& dest_filter, const std::string& input_name
+         );
+         void Connect(
+         cpPlugins::Pipeline::DataObject* output,
+         const std::string& exposed_input_name
+         );
+         void Disconnect(
+         const std::string& orig_filter, const std::string& dest_filter,
+         const std::string& output_name, const std::string& input_name
+         );
+         void Disconnect(
+         const std::string& dest_filter, const std::string& input_name
+         );
+         void Disconnect( const std::string& dest_filter );
+      */
+
+      // Pipeline execution
+      void Update( );
+      void Update( const std::string& name );
+
+    protected:
+      Workspace( );
+      virtual ~Workspace( );
+
+    private:
+      // Purposely not implemented
+      Workspace( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      TLoader  m_Loader;
+      TFilters m_Filters;
+      bool     m_PrintExecution;
+
+      /* TODO
+         TExposedPorts m_ExposedInputs;
+         TExposedPorts m_ExposedOutputs;
+      */
+
+      std::set< vtkRenderWindowInteractor* > m_Interactors;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Interface__Workspace__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Interface/WorkspaceIO.cxx b/lib/cpPlugins/Interface/WorkspaceIO.cxx
new file mode 100644 (file)
index 0000000..7b73c43
--- /dev/null
@@ -0,0 +1,315 @@
+#include <cpPlugins/Interface/Workspace.h>
+#include <cpPlugins/tinyxml2/tinyxml2.h>
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Load( const std::string& fname )
+{
+  this->Clear( );
+
+  // Read from disk
+  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( );
+  doc->LoadFile( fname.c_str( ) );
+  tinyxml2::XMLElement* root = doc->RootElement( );
+  if( root == NULL )
+  {
+    delete doc;
+    throw std::runtime_error( "cpPlugins::Workspace: No valid file" );
+
+  } // fi
+  if( std::string( root->Value( ) ) != "cpPlugins_Workspace" )
+  {
+    delete doc;
+    throw std::runtime_error( "cpPlugins::Workspace: Not a valid workspace" );
+
+  } // fi
+
+  // Read filters
+  std::stringstream err;
+  tinyxml2::XMLElement* filter = root->FirstChildElement( "Filter" );
+  while( filter != NULL )
+  {
+    const char* category_value = filter->Attribute( "Category" );
+    const char* class_value = filter->Attribute( "Class" );
+    const char* name_value = filter->Attribute( "Name" );
+    float viewX = float( 0 ), viewY = float( 0 );
+    filter->QueryFloatAttribute( "ViewX", &viewX );
+    filter->QueryFloatAttribute( "ViewY", &viewY );
+    int explicit_execution = 0;
+    filter->QueryIntAttribute(
+      "ExplicitExecution", &explicit_execution
+      );
+    if( class_value != NULL && name_value != NULL )
+    {
+      auto new_filter = this->CreateFilter( category_value, class_value );
+      if( new_filter != NULL )
+      {
+        this->RenameFilter( new_filter->GetName( ), name_value );
+        new_filter->SetViewCoords( viewX, viewY );
+        new_filter->SetExplicitExecution( explicit_execution == 1 );
+        new_filter->GetParameters( )->FromXML( filter );
+      }
+      else
+        err
+          << "No valid class \"" << class_value << "\" with name \""
+          << name_value << "\"" << std::endl;
+    }
+    else
+      err << "Incomplete data." << std::endl;
+    filter = filter->NextSiblingElement( "Filter" );
+
+  } // elihw
+
+  // Read connections
+  tinyxml2::XMLElement* connection = root->FirstChildElement( "Connection" );
+  while( connection != NULL )
+  {
+    tinyxml2::XMLElement* orig = connection->FirstChildElement( "Origin" );
+    tinyxml2::XMLElement* dest = connection->FirstChildElement( "Destination" );
+    if( orig != NULL && dest != NULL )
+    {
+      const char* orig_filter = orig->Attribute( "Filter" );
+      const char* dest_filter = dest->Attribute( "Filter" );
+      const char* orig_name = orig->Attribute( "Name" );
+      const char* dest_name = dest->Attribute( "Name" );
+      if(
+        orig_filter != NULL && dest_filter != NULL &&
+        orig_name != NULL && dest_name != NULL
+        )
+      {
+        try
+        {
+          this->Connect( orig_filter, orig_name, dest_filter, dest_name );
+        }
+        catch( std::exception& exc )
+        {
+          err << exc.what( ) << std::endl;
+
+        } // yrt
+
+      } // fi
+
+    } // fi
+    connection = connection->NextSiblingElement( "Connection" );
+
+  } // elihw
+
+  // Read exposed inputs
+  /* TODO
+     tinyxml2::XMLElement* port = root->FirstChildElement( "ExposedInput" );
+     while( port != NULL )
+     {
+     this->ExposeInput(
+     port->Attribute( "Name" ),
+     port->Attribute( "Filter" ),
+     port->Attribute( "Input" )
+     );
+     port = port->NextSiblingElement( "ExposedInput" );
+
+     } // elihw
+
+     // Read exposed outputs
+     port = root->FirstChildElement( "ExposedOutput" );
+     while( port != NULL )
+     {
+     this->ExposeOutput(
+     port->Attribute( "Name" ),
+     port->Attribute( "Filter" ),
+     port->Attribute( "Output" )
+     );
+     port = port->NextSiblingElement( "ExposedOutput" );
+
+     } // elihw
+  */
+
+  // Throw errors
+  std::string err_str = err.str( );
+  if( err_str != "" )
+  {
+    delete doc;
+    throw std::runtime_error(
+      std::string( "cpPlugins::Workspace " ) + err_str
+      );
+
+  } // fi
+
+  // Finish
+  delete doc;
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Save( const std::string& fname ) const
+{
+  tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( );
+  tinyxml2::XMLElement* root = doc->NewElement( "cpPlugins_Workspace" );
+  std::set< std::string > used_plugins;
+
+  // Save filter data
+  for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
+  {
+    auto filter = i->second;
+    used_plugins.insert( filter->GetPluginName( ) );
+    tinyxml2::XMLElement* e = doc->NewElement( "Filter" );
+    e->SetAttribute( "Category", filter->GetClassCategory( ) );
+    e->SetAttribute( "Class", filter->GetClassName( ) );
+    e->SetAttribute( "Name", filter->GetName( ) );
+    e->SetAttribute( "ViewX", filter->GetViewX( ) );
+    e->SetAttribute( "ViewY", filter->GetViewY( ) );
+    e->SetAttribute(
+      "ExplicitExecution", ( filter->GetExplicitExecution( ) )? 1: 0
+      );
+
+    auto params = filter->GetParameters( );
+    params->ToXML( doc, e );
+    root->LinkEndChild( e );
+
+  } // rof
+
+  // Save used plugins
+  /* TODO
+     tinyxml2::XMLElement* plugins = doc->NewElement( "Plugins" );
+     for( auto pIt = used_plugins.begin( ); pIt != used_plugins.end( ); ++pIt )
+     {
+     tinyxml2::XMLElement* e = doc->NewElement( "Plugin" );
+     e->SetAttribute( "Name", pIt->c_str( ) );
+     plugins->LinkEndChild( e );
+
+     } // rof
+     root->LinkEndChild( plugins );
+  */
+
+  // Save connections
+  for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
+  {
+    auto orig = i->second;
+    auto outputs = orig->GetOutputsNames( );
+    if( outputs.size( ) == 0 )
+      continue;
+    for( auto j = this->m_Filters.begin( ); j != this->m_Filters.end( ); ++j )
+    {
+      if( i == j )
+        continue;
+      auto dest = j->second;
+      auto inputs = dest->GetInputsNames( );
+      if( inputs.size( ) == 0 )
+        continue;
+
+      for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )
+      {
+        auto od = orig->GetOutput( *oIt );
+        for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )
+        {
+          unsigned int nInputs = dest->GetInputSize( *iIt );
+          for( unsigned int k = 0; k < nInputs; ++k )
+          {
+            auto id = dest->GetInput( *iIt, k );
+            if( od != NULL && od == id )
+            {
+              tinyxml2::XMLElement* e_conn = doc->NewElement( "Connection" );
+              tinyxml2::XMLElement* e_orig = doc->NewElement( "Origin" );
+              tinyxml2::XMLElement* e_dest = doc->NewElement( "Destination" );
+              e_orig->SetAttribute( "Filter", orig->GetName( ) );
+              e_orig->SetAttribute( "Name", oIt->c_str( ) );
+              e_dest->SetAttribute( "Filter", dest->GetName( ) );
+              e_dest->SetAttribute( "Name", iIt->c_str( ) );
+              e_conn->LinkEndChild( e_orig );
+              e_conn->LinkEndChild( e_dest );
+              root->LinkEndChild( e_conn );
+
+            } // fi
+
+          } // rof
+
+        } // rof
+
+      } // rof
+      
+    } // rof
+
+  } // rof
+
+  // Save exposed ports
+  /* TODO
+     auto eipIt = this->m_ExposedInputs.begin( );
+     for( ; eipIt != this->m_ExposedInputs.end( ); ++eipIt )
+     {
+     tinyxml2::XMLElement* port = doc->NewElement( "ExposedInput" );
+     port->SetAttribute( "Name", eipIt->first.c_str( ) );
+     port->SetAttribute( "Filter", eipIt->second.first.c_str( ) );
+     port->SetAttribute( "Input", eipIt->second.second.c_str( ) );
+     root->LinkEndChild( port );
+
+     } // rof
+
+     auto eopIt = this->m_ExposedOutputs.begin( );
+     for( ; eopIt != this->m_ExposedOutputs.end( ); ++eopIt )
+     {
+     tinyxml2::XMLElement* port = doc->NewElement( "ExposedOutput" );
+     port->SetAttribute( "Name", eopIt->first.c_str( ) );
+     port->SetAttribute( "Filter", eopIt->second.first.c_str( ) );
+     port->SetAttribute( "Output", eopIt->second.second.c_str( ) );
+     root->LinkEndChild( port );
+
+     } // rof
+  */
+
+  // Physical write and return
+  doc->LinkEndChild( root );
+  auto error = doc->SaveFile( fname.c_str( ) );
+  delete doc;
+  if( error != tinyxml2::XML_SUCCESS )
+  {
+    std::string m;
+    switch( error )
+    {
+    case tinyxml2::XML_NO_ATTRIBUTE:
+      m = "No attribute."; break;
+    case tinyxml2::XML_WRONG_ATTRIBUTE_TYPE:
+      m = "Wrong attribute."; break;
+    case tinyxml2::XML_ERROR_FILE_NOT_FOUND:
+      m = "File not found."; break;
+    case tinyxml2::XML_ERROR_FILE_COULD_NOT_BE_OPENED:
+      m = "File not opened."; break;
+    case tinyxml2::XML_ERROR_FILE_READ_ERROR:
+      m = "File not read."; break;
+    case tinyxml2::XML_ERROR_ELEMENT_MISMATCH:
+      m = "Element mismatch."; break;
+    case tinyxml2::XML_ERROR_PARSING_ELEMENT:
+      m = "Parsing element."; break;
+    case tinyxml2::XML_ERROR_PARSING_ATTRIBUTE:
+      m = "Parsing attribute."; break;
+    case tinyxml2::XML_ERROR_IDENTIFYING_TAG:
+      m = "Tag Id."; break;
+    case tinyxml2::XML_ERROR_PARSING_TEXT:
+      m = "Parsing text."; break;
+    case tinyxml2::XML_ERROR_PARSING_CDATA:
+      m = "Parsing cdata."; break;
+    case tinyxml2::XML_ERROR_PARSING_COMMENT:
+      m = "Parsing comment."; break;
+    case tinyxml2::XML_ERROR_PARSING_DECLARATION:
+      m = "Parsing declaration."; break;
+    case tinyxml2::XML_ERROR_PARSING_UNKNOWN:
+      m = "Parsing unknown."; break;
+    case tinyxml2::XML_ERROR_EMPTY_DOCUMENT:
+      m = "Empty document."; break;
+    case tinyxml2::XML_ERROR_MISMATCHED_ELEMENT:
+      m = "Mismatched element."; break;
+    case tinyxml2::XML_ERROR_PARSING:
+      m = "Parsing."; break;
+    case tinyxml2::XML_CAN_NOT_CONVERT_TEXT:
+      m = "Cannot convert."; break;
+    case tinyxml2::XML_NO_TEXT_NODE:
+      m = "No text."; break;
+    default:
+      m = "Unknown error."; break;
+    } // hctiws
+    throw std::runtime_error(
+      std::string( "cpPlugins::Workspace: Error while saving \"" ) +
+      fname + std::string( "\": " ) + m
+      );
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/Chrono.h b/lib/cpPlugins/OS/Chrono.h
new file mode 100644 (file)
index 0000000..e012406
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __cpPlugins__OS__Chrono__h__
+#define __cpPlugins__OS__Chrono__h__
+
+#include <cpPlugins/Config.h>
+#include <chrono>
+
+// -------------------------------------------------------------------------
+#define cpPlugins_CHRONO                                        \
+  std::chrono::duration_cast< std::chrono::milliseconds >(      \
+    std::chrono::system_clock::now( ).time_since_epoch( )       \
+    ).count( )
+
+#endif // __cpPlugins__OS__Chrono__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/DLLManager.cxx b/lib/cpPlugins/OS/DLLManager.cxx
new file mode 100644 (file)
index 0000000..ba13b36
--- /dev/null
@@ -0,0 +1,50 @@
+#include <cpPlugins/OS/DLLManager.h>
+#ifdef cpExtensions_OS_Windows
+#else // cpExtensions_OS_Windows
+#  include <dlfcn.h>
+#endif // cpExtensions_OS_Windows
+
+// -------------------------------------------------------------------------
+void* cpPlugins::OS::DLLManager::
+Open( const std::string& filename )
+{
+  void* hnd = NULL;
+#ifdef cpExtensions_OS_Windows
+#else // cpExtensions_OS_Windows
+  hnd = dlopen( filename.c_str( ), RTLD_NOW | RTLD_GLOBAL );
+  char* error = dlerror( );
+  if( error != NULL )
+    throw std::runtime_error( error );
+#endif // cpExtensions_OS_Windows
+  return( hnd );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::OS::DLLManager::
+Close( void* hnd )
+{
+#ifdef cpExtensions_OS_Windows
+#else // cpExtensions_OS_Windows
+  /* TODO: why this clashes with VTK? -> Unregistering of factories.
+     dlclose( hnd );
+     dlerror( );
+  */
+#endif // cpExtensions_OS_Windows
+}
+
+// -------------------------------------------------------------------------
+void* cpPlugins::OS::DLLManager::
+Sym( void* hnd, const std::string& symbol )
+{
+  void* sym = NULL;
+#ifdef cpExtensions_OS_Windows
+#else // cpExtensions_OS_Windows
+  sym = dlsym( hnd, symbol.c_str( ) );
+  char* error = dlerror( );
+  if( error != NULL )
+    throw std::runtime_error( error );
+#endif // cpExtensions_OS_Windows
+  return( sym );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/DLLManager.h b/lib/cpPlugins/OS/DLLManager.h
new file mode 100644 (file)
index 0000000..9e6460b
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __cpPlugins__OS__DLLManager__h__
+#define __cpPlugins__OS__DLLManager__h__
+
+#include <cpPlugins/Config.h>
+#include <iostream>
+
+namespace cpPlugins
+{
+  namespace OS
+  {
+    /**
+     */
+    class cpPlugins_EXPORT DLLManager
+    {
+    public:
+      static void* Open( const std::string& filename );
+      static void Close( void* hnd );
+      static void* Sym( void* hnd, const std::string& symbol );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__OS__DLLManager__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/FileSystem.cxx b/lib/cpPlugins/OS/FileSystem.cxx
new file mode 100644 (file)
index 0000000..334bf2a
--- /dev/null
@@ -0,0 +1,202 @@
+#include <cpPlugins/OS/FileSystem.h>
+#include <cpPlugins/OS/tinydir.h>
+#include <fstream>
+#include <sstream>
+
+// -------------------------------------------------------------------------
+std::string cpPlugins::OS::FileSystem::
+CanonicalPath( const std::string& path )
+{
+  std::string ret = "";
+#ifdef cpExtensions_OS_Windows
+  TCHAR  buffer[ 4096 ] = TEXT( "" );
+  TCHAR** lppPart = { NULL };
+  GetFullPathName( path.c_str( ), 4096, buffer, lppPart );
+  ret = std::string( buffer );
+#else // cpExtensions_OS_Windows
+  char* canonical_path = realpath( path.c_str( ), NULL );
+  if( canonical_path != NULL )
+  {
+    ret = canonical_path;
+    free( canonical_path );
+
+  } // fi
+#endif // cpExtensions_OS_Windows
+  return( ret );
+}
+
+// -------------------------------------------------------------------------
+std::pair< std::string, std::string > cpPlugins::OS::FileSystem::
+SplitPath( const std::string& path )
+{
+  size_t found = path.find_last_of( "/\\" );
+  return(
+    std::pair< std::string, std::string >(
+      path.substr( 0, found + 1 ), path.substr( found + 1 )
+      )
+    );
+}
+
+// -------------------------------------------------------------------------
+std::set< std::string > cpPlugins::OS::FileSystem::
+LoadDirContents(
+  const std::string& path, bool recursive,
+  const std::string& pattern
+  )
+{
+  // Prepare inputs and outputs
+  std::stringstream path_stream;
+  path_stream << path << cpPlugins_PATH_SEPARATOR;
+  std::string path_str = path_stream.str( );
+  std::set< std::string > output;
+
+  // Process data
+  tinydir_dir dir;
+  if( tinydir_open_sorted( &dir, path.c_str( ) ) != -1 )
+  {
+    for( auto i = 0; i < dir.n_files; i++ )
+    {
+      tinydir_file file;
+      if( tinydir_readfile_n( &dir, &file , i ) != -1 )
+      {
+        std::string fname = path_str + file.name;
+        if( file.is_dir )
+        {
+          if( recursive )
+          {
+            if( fname != "." && fname != ".." )
+            {
+              auto tmp = Self::LoadDirContents( fname, true );
+              output.insert( tmp.begin( ), tmp.end( ) );
+
+            } // fi
+
+          } // fi
+        }
+        else
+        {
+          if( pattern != "" )
+          {
+            if( Self::Glob( fname, path_str + pattern ) )
+              output.insert( fname );
+          }
+          else
+            output.insert( fname );
+
+        } // fi
+
+      } // fi
+
+    } // rof
+
+  } // fi
+  tinydir_close( &dir );
+  return( output );
+}
+
+// -------------------------------------------------------------------------
+int cpPlugins::OS::FileSystem::
+GlobMatch( const char* target, const char* pattern )
+{
+  char* pat = const_cast< char* >( pattern );
+  char* end = strchr( pat, ']' );
+  char* ptr;
+  if( *pat == '[' && end != NULL )
+  {
+    if( end == pat + 1 )
+    {
+      end = strchr( pat + 2, ']' );
+      if( end == NULL )
+        return( 0 );
+
+    } // fi
+
+    if( end - pat == 4 && pat[ 2 ] == '-' && pat[ 1 ] <= pattern[ 3 ] )
+    {
+      if( *target >= pat[ 1 ] && *target <= pat[ 3 ] )
+        return( 5 );
+      else
+        return( 0 );
+
+    } // fi
+
+    ptr = strchr( pat + 1, *target );
+    if( ptr != NULL && ptr < end )
+      return( end - pat + 1 );
+    else
+      return( 0 );
+
+  } // fi
+
+  if( *pat == '?' && *target != 0 )
+    return( 1 );
+  if( *pat == '*' )
+    return( 0 );
+  if( *target == 0 || *pat == 0 )
+    return( 0 );
+  if( *target == *pat )
+    return( 1 );
+  return( 0 );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::OS::FileSystem::
+Glob( const std::string& line, const std::string& pattern )
+{
+  const char* target = line.c_str( );
+  const char* pat = pattern.c_str( );
+  int gobble;
+
+  while( ( gobble = GlobMatch( target, pat ) ) )
+  {
+    target++;
+    pat += gobble;
+
+  } // elihw
+  if( *target == 0 && *pat == 0 )
+    return( true );
+  else if( *pat == '*' )
+  {
+    while( pat[ 1 ] == '*' )
+      pat++;
+    if( pat[ 1 ] == 0 )
+      return( true );
+    while( *target )
+      if( Glob( target++, pat + 1 ) )
+        return( 1 );
+
+  } // fi
+  return( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::OS::FileSystem::
+Read( std::string& buffer, const std::string& fname )
+{
+  buffer = "";
+  std::ifstream file_stream( fname.c_str( ) );
+  if( !file_stream )
+    return( false );
+  file_stream.seekg( 0, std::ios::end );
+  buffer.reserve( ( unsigned int )( file_stream.tellg( ) ) );
+  file_stream.seekg( 0, std::ios::beg );
+  buffer.assign(
+    ( std::istreambuf_iterator< char >( file_stream ) ),
+    std::istreambuf_iterator< char >( )
+    );
+  file_stream.close( );
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::OS::FileSystem::
+Write( const std::string& buffer, const std::string& fname )
+{
+  std::ofstream file_stream( fname.c_str( ), std::ofstream::binary );
+  if( !file_stream )
+    return( false );
+  file_stream.write( buffer.c_str( ), buffer.size( ) );
+  return( true );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/FileSystem.h b/lib/cpPlugins/OS/FileSystem.h
new file mode 100644 (file)
index 0000000..26d5ad4
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __cpPlugins__OS__FileSystem__h__
+#define __cpPlugins__OS__FileSystem__h__
+
+#include <cpPlugins/Config.h>
+#include <set>
+
+namespace cpPlugins
+{
+  namespace OS
+  {
+    /**
+     */
+    class cpPlugins_EXPORT FileSystem
+    {
+    public:
+      typedef FileSystem Self;
+
+    public:
+      /**
+       */
+      static std::string CanonicalPath( const std::string& path );
+
+      /**
+       */
+      static std::pair< std::string, std::string > SplitPath(
+        const std::string& path
+        );
+
+      /**
+       */
+      static std::set< std::string > LoadDirContents(
+        const std::string& path, bool recursive = false,
+        const std::string& pattern = ""
+        );
+
+      /**
+       */
+      static int GlobMatch( const char* target, const char* pattern );
+
+      /**
+       */
+      static bool Glob( const std::string& line, const std::string& pattern );
+
+      /**
+       */
+      static bool Read( std::string& buffer, const std::string& fname );
+
+      /**
+       */
+      static bool Write( const std::string& buffer, const std::string& fname );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__OS__FileSystem__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/String.cxx b/lib/cpPlugins/OS/String.cxx
new file mode 100644 (file)
index 0000000..0bb9b59
--- /dev/null
@@ -0,0 +1,37 @@
+#include <cpPlugins/OS/String.h>
+#include <cstring>
+
+// -------------------------------------------------------------------------
+#ifdef cpPlugins_OS_Windows
+#  define cpPlugins_STRTOK( A, B, N ) strtok_s( A, B, N )
+#else // cpPlugins_OS_Windows
+#  define cpPlugins_STRTOK( A, B, N ) std::strtok( A, B )
+#endif // cpPlugins_OS_Windows
+
+// -------------------------------------------------------------------------
+std::vector< std::string > cpPlugins::OS::String::
+Tokenize( const std::string& str, const std::string& delims )
+{
+  std::vector< std::string > tokens;
+  if( str.size( ) > 0 )
+  {
+    auto ssize = str.size( );
+    char* buffer = new char[ ssize + 1 ];
+    for( unsigned long i = 0; i < ssize; ++i )
+      buffer[ i ] = str[ i ];
+    buffer[ ssize ] = '\0';
+    char* next;
+    char* it = cpPlugins_STRTOK( buffer, delims.c_str( ), &next );
+    while( it != NULL )
+    {
+      tokens.push_back( std::string( it ) );
+      it = cpPlugins_STRTOK( NULL, delims.c_str( ), &next );
+
+    } // elihw
+    delete [] buffer;
+
+  } // fi
+  return( tokens );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/String.h b/lib/cpPlugins/OS/String.h
new file mode 100644 (file)
index 0000000..d87db17
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __cpPlugins__OS__String__h__
+#define __cpPlugins__OS__String__h__
+
+#include <cpPlugins/Config.h>
+#include <string>
+#include <vector>
+
+namespace cpPlugins
+{
+  namespace OS
+  {
+    /**
+     */
+    class cpPlugins_EXPORT String
+    {
+    public:
+      static std::vector< std::string > Tokenize(
+        const std::string& str, const std::string& delims
+        );
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__OS__String__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/tinydir.h b/lib/cpPlugins/OS/tinydir.h
new file mode 100644 (file)
index 0000000..432bd95
--- /dev/null
@@ -0,0 +1,806 @@
+/*
+  Copyright (c) 2013-2016, tinydir authors:
+  - Cong Xu
+  - Lautis Sun
+  - Baudouin Feildel
+  - Andargor <andargor@yahoo.com>
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef cpPlugins__OS__TINYDIR_H
+#define cpPlugins__OS__TINYDIR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if ((defined _UNICODE) && !(defined UNICODE))
+#define UNICODE
+#endif
+
+#if ((defined UNICODE) && !(defined _UNICODE))
+#define _UNICODE
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef _MSC_VER
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <tchar.h>
+# pragma warning(push)
+# pragma warning (disable : 4996)
+#else
+# include <dirent.h>
+# include <libgen.h>
+# include <sys/stat.h>
+# include <stddef.h>
+#endif
+#ifdef __MINGW32__
+# include <tchar.h>
+#endif
+
+
+/* types */
+
+/* Windows UNICODE wide character support */
+#if defined _MSC_VER || defined __MINGW32__
+#define _tinydir_char_t TCHAR
+#define TINYDIR_STRING(s) _TEXT(s)
+#define _tinydir_strlen _tcslen
+#define _tinydir_strcpy _tcscpy
+#define _tinydir_strcat _tcscat
+#define _tinydir_strcmp _tcscmp
+#define _tinydir_strrchr _tcsrchr
+#define _tinydir_strncmp _tcsncmp
+#else
+#define _tinydir_char_t char
+#define TINYDIR_STRING(s) s
+#define _tinydir_strlen strlen
+#define _tinydir_strcpy strcpy
+#define _tinydir_strcat strcat
+#define _tinydir_strcmp strcmp
+#define _tinydir_strrchr strrchr
+#define _tinydir_strncmp strncmp
+#endif
+
+#if (defined _MSC_VER || defined __MINGW32__)
+#include <windows.h>
+#define _TINYDIR_PATH_MAX MAX_PATH
+#elif defined  __linux__
+#include <linux/limits.h>
+#define _TINYDIR_PATH_MAX PATH_MAX
+#else
+#define _TINYDIR_PATH_MAX 4096
+#endif
+
+#ifdef _MSC_VER
+/* extra chars for the "\\*" mask */
+# define _TINYDIR_PATH_EXTRA 2
+#else
+# define _TINYDIR_PATH_EXTRA 0
+#endif
+
+#define _TINYDIR_FILENAME_MAX 256
+
+#if (defined _MSC_VER || defined __MINGW32__)
+#define _TINYDIR_DRIVE_MAX 3
+#endif
+
+#ifdef _MSC_VER
+# define _TINYDIR_FUNC static __inline
+#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# define _TINYDIR_FUNC static __inline__
+#else
+# define _TINYDIR_FUNC static inline
+#endif
+
+/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */
+#ifdef TINYDIR_USE_READDIR_R
+
+/* readdir_r is a POSIX-only function, and may not be available under various
+ * environments/settings, e.g. MinGW. Use readdir fallback */
+#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || \
+  _POSIX_SOURCE
+# define _TINYDIR_HAS_READDIR_R
+#endif
+#if _POSIX_C_SOURCE >= 200112L
+# define _TINYDIR_HAS_FPATHCONF
+# include <unistd.h>
+#endif
+#if _BSD_SOURCE || _SVID_SOURCE ||                      \
+  (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
+# define _TINYDIR_HAS_DIRFD
+# include <sys/types.h>
+#endif
+#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&     \
+  defined _PC_NAME_MAX
+# define _TINYDIR_USE_FPATHCONF
+#endif
+#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||   \
+  !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
+# define _TINYDIR_USE_READDIR
+#endif
+
+/* Use readdir by default */
+#else
+# define _TINYDIR_USE_READDIR
+#endif
+
+/* MINGW32 has two versions of dirent, ASCII and UNICODE*/
+#ifndef _MSC_VER
+#if (defined __MINGW32__) && (defined _UNICODE)
+#define _TINYDIR_DIR _WDIR
+#define _tinydir_dirent _wdirent
+#define _tinydir_opendir _wopendir
+#define _tinydir_readdir _wreaddir
+#define _tinydir_closedir _wclosedir
+#else
+#define _TINYDIR_DIR DIR
+#define _tinydir_dirent dirent
+#define _tinydir_opendir opendir
+#define _tinydir_readdir readdir
+#define _tinydir_closedir closedir
+#endif
+#endif
+
+/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */
+#if    defined(_TINYDIR_MALLOC) &&  defined(_TINYDIR_FREE)
+#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE)
+#else
+#error "Either define both alloc and free or none of them!"
+#endif
+
+#if !defined(_TINYDIR_MALLOC)
+#define _TINYDIR_MALLOC(_size) malloc(_size)
+#define _TINYDIR_FREE(_ptr)    free(_ptr)
+#endif /* !defined(_TINYDIR_MALLOC) */
+
+  typedef struct tinydir_file
+  {
+    _tinydir_char_t path[_TINYDIR_PATH_MAX];
+    _tinydir_char_t name[_TINYDIR_FILENAME_MAX];
+    _tinydir_char_t *extension;
+    int is_dir;
+    int is_reg;
+
+#ifndef _MSC_VER
+#ifdef __MINGW32__
+    struct _stat _s;
+#else
+    struct stat _s;
+#endif
+#endif
+  } tinydir_file;
+
+  typedef struct tinydir_dir
+  {
+    _tinydir_char_t path[_TINYDIR_PATH_MAX];
+    int has_next;
+    size_t n_files;
+
+    tinydir_file *_files;
+#ifdef _MSC_VER
+    HANDLE _h;
+    WIN32_FIND_DATA _f;
+#else
+    _TINYDIR_DIR *_d;
+    struct _tinydir_dirent *_e;
+#ifndef _TINYDIR_USE_READDIR
+    struct _tinydir_dirent *_ep;
+#endif
+#endif
+  } tinydir_dir;
+
+
+/* declarations */
+
+  _TINYDIR_FUNC
+  int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path);
+  _TINYDIR_FUNC
+  int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path);
+  _TINYDIR_FUNC
+  void tinydir_close(tinydir_dir *dir);
+
+  _TINYDIR_FUNC
+  int tinydir_next(tinydir_dir *dir);
+  _TINYDIR_FUNC
+  int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file);
+  _TINYDIR_FUNC
+  int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i);
+  _TINYDIR_FUNC
+  int tinydir_open_subdir_n(tinydir_dir *dir, size_t i);
+
+  _TINYDIR_FUNC
+  int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path);
+  _TINYDIR_FUNC
+  void _tinydir_get_ext(tinydir_file *file);
+  _TINYDIR_FUNC
+  int _tinydir_file_cmp(const void *a, const void *b);
+#ifndef _MSC_VER
+#ifndef _TINYDIR_USE_READDIR
+  _TINYDIR_FUNC
+  size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
+#endif
+#endif
+
+
+/* definitions*/
+
+  _TINYDIR_FUNC
+  int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
+  {
+#ifndef _MSC_VER
+#ifndef _TINYDIR_USE_READDIR
+    int error;
+    int size;       /* using int size */
+#endif
+#else
+    _tinydir_char_t path_buf[_TINYDIR_PATH_MAX];
+#endif
+    _tinydir_char_t *pathp;
+
+    if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0)
+    {
+      errno = EINVAL;
+      return -1;
+    }
+    if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
+    {
+      errno = ENAMETOOLONG;
+      return -1;
+    }
+
+    /* initialise dir */
+    dir->_files = NULL;
+#ifdef _MSC_VER
+    dir->_h = INVALID_HANDLE_VALUE;
+#else
+    dir->_d = NULL;
+#ifndef _TINYDIR_USE_READDIR
+    dir->_ep = NULL;
+#endif
+#endif
+    tinydir_close(dir);
+
+    _tinydir_strcpy(dir->path, path);
+    /* Remove trailing slashes */
+    pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
+    while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/')))
+    {
+      *pathp = TINYDIR_STRING('\0');
+      pathp++;
+    }
+#ifdef _MSC_VER
+    _tinydir_strcpy(path_buf, dir->path);
+    _tinydir_strcat(path_buf, TINYDIR_STRING("\\*"));
+    dir->_h = FindFirstFile(path_buf, &dir->_f);
+    if (dir->_h == INVALID_HANDLE_VALUE)
+    {
+      errno = ENOENT;
+#else
+      dir->_d = _tinydir_opendir(path);
+      if (dir->_d == NULL)
+      {
+#endif
+        goto bail;
+      }
+
+      /* read first file */
+      dir->has_next = 1;
+#ifndef _MSC_VER
+#ifdef _TINYDIR_USE_READDIR
+      dir->_e = _tinydir_readdir(dir->_d);
+#else
+      /* allocate dirent buffer for readdir_r */
+      size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
+      if (size == -1) return -1;
+      dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
+      if (dir->_ep == NULL) return -1;
+
+      error = readdir_r(dir->_d, dir->_ep, &dir->_e);
+      if (error != 0) return -1;
+#endif
+      if (dir->_e == NULL)
+      {
+        dir->has_next = 0;
+      }
+#endif
+
+      return 0;
+
+    bail:
+      tinydir_close(dir);
+      return -1;
+    }
+
+    _TINYDIR_FUNC
+      int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
+    {
+      /* Count the number of files first, to pre-allocate the files array */
+      size_t n_files = 0;
+      if (tinydir_open(dir, path) == -1)
+      {
+        return -1;
+      }
+      while (dir->has_next)
+      {
+        n_files++;
+        if (tinydir_next(dir) == -1)
+        {
+          goto bail;
+        }
+      }
+      tinydir_close(dir);
+
+      if (tinydir_open(dir, path) == -1)
+      {
+        return -1;
+      }
+
+      dir->n_files = 0;
+      dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
+      if (dir->_files == NULL)
+      {
+        goto bail;
+      }
+      while (dir->has_next)
+      {
+        tinydir_file *p_file;
+        dir->n_files++;
+
+        p_file = &dir->_files[dir->n_files - 1];
+        if (tinydir_readfile(dir, p_file) == -1)
+        {
+          goto bail;
+        }
+
+        if (tinydir_next(dir) == -1)
+        {
+          goto bail;
+        }
+
+        /* Just in case the number of files has changed between the first and
+           second reads, terminate without writing into unallocated memory */
+        if (dir->n_files == n_files)
+        {
+          break;
+        }
+      }
+
+      qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp);
+
+      return 0;
+
+    bail:
+      tinydir_close(dir);
+      return -1;
+    }
+
+    _TINYDIR_FUNC
+      void tinydir_close(tinydir_dir *dir)
+    {
+      if (dir == NULL)
+      {
+        return;
+      }
+
+      memset(dir->path, 0, sizeof(dir->path));
+      dir->has_next = 0;
+      dir->n_files = 0;
+      _TINYDIR_FREE(dir->_files);
+      dir->_files = NULL;
+#ifdef _MSC_VER
+      if (dir->_h != INVALID_HANDLE_VALUE)
+      {
+        FindClose(dir->_h);
+      }
+      dir->_h = INVALID_HANDLE_VALUE;
+#else
+      if (dir->_d)
+      {
+        _tinydir_closedir(dir->_d);
+      }
+      dir->_d = NULL;
+      dir->_e = NULL;
+#ifndef _TINYDIR_USE_READDIR
+      _TINYDIR_FREE(dir->_ep);
+      dir->_ep = NULL;
+#endif
+#endif
+    }
+
+    _TINYDIR_FUNC
+      int tinydir_next(tinydir_dir *dir)
+    {
+      if (dir == NULL)
+      {
+        errno = EINVAL;
+        return -1;
+      }
+      if (!dir->has_next)
+      {
+        errno = ENOENT;
+        return -1;
+      }
+
+#ifdef _MSC_VER
+      if (FindNextFile(dir->_h, &dir->_f) == 0)
+#else
+#ifdef _TINYDIR_USE_READDIR
+        dir->_e = _tinydir_readdir(dir->_d);
+#else
+      if (dir->_ep == NULL)
+      {
+        return -1;
+      }
+      if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0)
+      {
+        return -1;
+      }
+#endif
+      if (dir->_e == NULL)
+#endif
+      {
+        dir->has_next = 0;
+#ifdef _MSC_VER
+        if (GetLastError() != ERROR_SUCCESS &&
+            GetLastError() != ERROR_NO_MORE_FILES)
+        {
+          tinydir_close(dir);
+          errno = EIO;
+          return -1;
+        }
+#endif
+      }
+
+      return 0;
+    }
+
+    _TINYDIR_FUNC
+      int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
+    {
+      if (dir == NULL || file == NULL)
+      {
+        errno = EINVAL;
+        return -1;
+      }
+#ifdef _MSC_VER
+      if (dir->_h == INVALID_HANDLE_VALUE)
+#else
+        if (dir->_e == NULL)
+#endif
+        {
+          errno = ENOENT;
+          return -1;
+        }
+      if (_tinydir_strlen(dir->path) +
+          _tinydir_strlen(
+#ifdef _MSC_VER
+            dir->_f.cFileName
+#else
+            dir->_e->d_name
+#endif
+            ) + 1 + _TINYDIR_PATH_EXTRA >=
+          _TINYDIR_PATH_MAX)
+      {
+        /* the path for the file will be too long */
+        errno = ENAMETOOLONG;
+        return -1;
+      }
+      if (_tinydir_strlen(
+#ifdef _MSC_VER
+            dir->_f.cFileName
+#else
+            dir->_e->d_name
+#endif
+            ) >= _TINYDIR_FILENAME_MAX)
+      {
+        errno = ENAMETOOLONG;
+        return -1;
+      }
+
+      _tinydir_strcpy(file->path, dir->path);
+      _tinydir_strcat(file->path, TINYDIR_STRING("/"));
+      _tinydir_strcpy(file->name,
+#ifdef _MSC_VER
+                      dir->_f.cFileName
+#else
+                      dir->_e->d_name
+#endif
+        );
+      _tinydir_strcat(file->path, file->name);
+#ifndef _MSC_VER
+#ifdef __MINGW32__
+      if (_tstat(
+#else
+            if (stat(
+#endif
+                  file->path, &file->_s) == -1)
+            {
+              return -1;
+            }
+#endif
+            _tinydir_get_ext(file);
+
+            file->is_dir =
+#ifdef _MSC_VER
+            !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+#else
+            S_ISDIR(file->_s.st_mode);
+#endif
+            file->is_reg =
+#ifdef _MSC_VER
+            !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
+            (
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) &&
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
+#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
+#endif
+#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
+#endif
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) &&
+              !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
+#else
+            S_ISREG(file->_s.st_mode);
+#endif
+
+            return 0;
+            }
+
+          _TINYDIR_FUNC
+          int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
+        {
+          if (dir == NULL || file == NULL)
+          {
+            errno = EINVAL;
+            return -1;
+          }
+          if (i >= dir->n_files)
+          {
+            errno = ENOENT;
+            return -1;
+          }
+
+          memcpy(file, &dir->_files[i], sizeof(tinydir_file));
+          _tinydir_get_ext(file);
+
+          return 0;
+        }
+
+          _TINYDIR_FUNC
+          int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
+        {
+          _tinydir_char_t path[_TINYDIR_PATH_MAX];
+          if (dir == NULL)
+          {
+            errno = EINVAL;
+            return -1;
+          }
+          if (i >= dir->n_files || !dir->_files[i].is_dir)
+          {
+            errno = ENOENT;
+            return -1;
+          }
+
+          _tinydir_strcpy(path, dir->_files[i].path);
+          tinydir_close(dir);
+          if (tinydir_open_sorted(dir, path) == -1)
+          {
+            return -1;
+          }
+
+          return 0;
+        }
+
+/* Open a single file given its path */
+          _TINYDIR_FUNC
+          int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
+        {
+          tinydir_dir dir;
+          int result = 0;
+          int found = 0;
+          _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX];
+          _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX];
+          _tinydir_char_t *dir_name;
+          _tinydir_char_t *base_name;
+#if (defined _MSC_VER || defined __MINGW32__)
+          _tinydir_char_t drive_buf[_TINYDIR_DRIVE_MAX];
+          _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
+#endif
+
+          if (file == NULL || path == NULL || _tinydir_strlen(path) == 0)
+          {
+            errno = EINVAL;
+            return -1;
+          }
+          if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX)
+          {
+            errno = ENAMETOOLONG;
+            return -1;
+          }
+
+          /* Get the parent path */
+#if (defined _MSC_VER || defined __MINGW32__)
+#if ((defined _MSC_VER) && (_MSC_VER >= 1400))
+          _tsplitpath_s(
+            path,
+            drive_buf, _TINYDIR_DRIVE_MAX,
+            dir_name_buf, _TINYDIR_FILENAME_MAX,
+            file_name_buf, _TINYDIR_FILENAME_MAX,
+            ext_buf, _TINYDIR_FILENAME_MAX);
+#else
+          _tsplitpath(
+            path,
+            drive_buf,
+            dir_name_buf,
+            file_name_buf,
+            ext_buf);
+#endif
+
+/* _splitpath_s not work fine with only filename and widechar support */
+#ifdef _UNICODE
+          if (drive_buf[0] == L'\xFEFE')
+            drive_buf[0] = '\0';
+          if (dir_name_buf[0] == L'\xFEFE')
+            dir_name_buf[0] = '\0';
+#endif
+
+          if (errno)
+          {
+            errno = EINVAL;
+            return -1;
+          }
+          /* Emulate the behavior of dirname by returning "." for dir name if it's
+             empty */
+          if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0')
+          {
+            _tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
+          }
+          /* Concatenate the drive letter and dir name to form full dir name */
+          _tinydir_strcat(drive_buf, dir_name_buf);
+          dir_name = drive_buf;
+          /* Concatenate the file name and extension to form base name */
+          _tinydir_strcat(file_name_buf, ext_buf);
+          base_name = file_name_buf;
+#else
+          _tinydir_strcpy(dir_name_buf, path);
+          dir_name = dirname(dir_name_buf);
+          _tinydir_strcpy(file_name_buf, path);
+          base_name =basename(file_name_buf);
+#endif
+
+          /* Open the parent directory */
+          if (tinydir_open(&dir, dir_name) == -1)
+          {
+            return -1;
+          }
+
+          /* Read through the parent directory and look for the file */
+          while (dir.has_next)
+          {
+            if (tinydir_readfile(&dir, file) == -1)
+            {
+              result = -1;
+              goto bail;
+            }
+            if (_tinydir_strcmp(file->name, base_name) == 0)
+            {
+              /* File found */
+              found = 1;
+              break;
+            }
+            tinydir_next(&dir);
+          }
+          if (!found)
+          {
+            result = -1;
+            errno = ENOENT;
+          }
+
+        bail:
+          tinydir_close(&dir);
+          return result;
+        }
+
+          _TINYDIR_FUNC
+          void _tinydir_get_ext(tinydir_file *file)
+        {
+          _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
+          if (period == NULL)
+          {
+            file->extension = &(file->name[_tinydir_strlen(file->name)]);
+          }
+          else
+          {
+            file->extension = period + 1;
+          }
+        }
+
+          _TINYDIR_FUNC
+          int _tinydir_file_cmp(const void *a, const void *b)
+        {
+          const tinydir_file *fa = (const tinydir_file *)a;
+          const tinydir_file *fb = (const tinydir_file *)b;
+          if (fa->is_dir != fb->is_dir)
+          {
+            return -(fa->is_dir - fb->is_dir);
+          }
+          return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
+        }
+
+#ifndef _MSC_VER
+#ifndef _TINYDIR_USE_READDIR
+/*
+  The following authored by Ben Hutchings <ben@decadent.org.uk>
+  from https://womble.decadent.org.uk/readdir_r-advisory.html
+*/
+/* Calculate the required buffer size (in bytes) for directory       *
+ * entries read from the given directory handle.  Return -1 if this  *
+ * this cannot be done.                                              *
+ *                                                                   *
+ * This code does not trust values of NAME_MAX that are less than    *
+ * 255, since some systems (including at least HP-UX) incorrectly    *
+ * define it to be a smaller value.                                  */
+          _TINYDIR_FUNC
+          size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
+        {
+          long name_max;
+          size_t name_end;
+          /* parameter may be unused */
+          (void)dirp;
+
+#if defined _TINYDIR_USE_FPATHCONF
+          name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX);
+          if (name_max == -1)
+#if defined(NAME_MAX)
+            name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
+#else
+          return (size_t)(-1);
+#endif
+#elif defined(NAME_MAX)
+          name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
+#else
+#error "buffer size for readdir_r cannot be determined"
+#endif
+          name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
+          return (name_end > sizeof(struct _tinydir_dirent) ?
+                  name_end : sizeof(struct _tinydir_dirent));
+        }
+#endif
+#endif
+
+#ifdef __cplusplus
+          }
+#endif
+
+# if defined (_MSC_VER)
+# pragma warning(pop)
+# endif
+
+#endif // cpPlugins__OS__TINYDIR_H
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/OS/tinydir_COPYING.txt b/lib/cpPlugins/OS/tinydir_COPYING.txt
new file mode 100644 (file)
index 0000000..0d31329
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2013-2016, tinydir authors:
+- Cong Xu
+- Lautis Sun
+- Baudouin Feildel
+- Andargor <andargor@yahoo.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer. 
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/cpPlugins/OS/tinydir_README.md.txt b/lib/cpPlugins/OS/tinydir_README.md.txt
new file mode 100644 (file)
index 0000000..3fab002
--- /dev/null
@@ -0,0 +1,78 @@
+TinyDir
+=======
+[![Build Status](https://travis-ci.org/cxong/tinydir.svg?branch=master)](https://travis-ci.org/cxong/tinydir)[![Project Stats](https://www.openhub.net/p/tinydir/widgets/project_thin_badge.gif)](https://www.openhub.net/p/tinydir)
+
+Lightweight, portable and easy to integrate C directory and file reader. TinyDir wraps dirent for POSIX and FindFirstFile for Windows.
+
+Windows unicode is supported by defining `UNICODE` and `_UNICODE` before including `tinydir.h`.
+
+Example
+=======
+
+There are two methods. Error checking omitted:
+
+```C
+tinydir_dir dir;
+tinydir_open(&dir, "/path/to/dir");
+
+while (dir.has_next)
+{
+       tinydir_file file;
+       tinydir_readfile(&dir, &file);
+
+       printf("%s", file.name);
+       if (file.is_dir)
+       {
+               printf("/");
+       }
+       printf("\n");
+
+       tinydir_next(&dir);
+}
+
+tinydir_close(&dir);
+```
+
+```C
+tinydir_dir dir;
+int i;
+tinydir_open_sorted(&dir, "/path/to/dir");
+
+for (i = 0; i < dir.n_files; i++)
+{
+       tinydir_file file;
+       tinydir_readfile_n(&dir, &file, i);
+
+       printf("%s", file.name);
+       if (file.is_dir)
+       {
+               printf("/");
+       }
+       printf("\n");
+}
+
+tinydir_close(&dir);
+```
+
+See the `/samples` folder for more examples, including an interactive command-line directory navigator.
+
+Language
+========
+
+ANSI C, or C90.
+
+Platforms
+=========
+
+POSIX and Windows supported. Open to the possibility of supporting other platforms.
+
+License
+=======
+
+Simplified BSD; if you use tinydir you can comply by including `tinydir.h` or `COPYING` somewhere in your package.
+
+Known Limitations
+=================
+
+- Limited path and filename sizes
+- [Possible race condition bug if folder being read has changing content](https://github.com/cxong/tinydir/issues/13)
diff --git a/lib/cpPlugins/Pipeline/DataObject.cxx b/lib/cpPlugins/Pipeline/DataObject.cxx
new file mode 100644 (file)
index 0000000..7afa1c7
--- /dev/null
@@ -0,0 +1,92 @@
+#include <cpPlugins/Pipeline/DataObject.h>
+
+#include <itkDataObject.h>
+#include <vtkImageData.h>
+#include <vtkPolyData.h>
+#include <vtkUnstructuredGrid.h>
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::DataObject::
+IsCompatible( const Self* other ) const
+{
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::ProcessObject*
+cpPlugins::Pipeline::DataObject::
+GetSource( )
+{
+  return( this->m_Source );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Pipeline::ProcessObject*
+cpPlugins::Pipeline::DataObject::
+GetSource( ) const
+{
+  return( this->m_Source );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::DataObject::
+SetSource( cpPlugins::Pipeline::ProcessObject* src )
+{
+  if( this->m_Source != src )
+  {
+    this->m_Source = src;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::DataObject::
+DisconnectFromPipeline( )
+{
+  // Disconnect input pipelines (ITK)
+  itk::DataObject::Pointer itk_obj = this->GetITK< itk::DataObject >( );
+  if( itk_obj.IsNotNull( ) )
+    itk_obj->DisconnectPipeline( );
+
+  // Disconnect input pipelines (VTK)
+  bool      ok = this->_DisconnectVTK< vtkImageData >( );
+  if( !ok ) ok = this->_DisconnectVTK< vtkPolyData >( );
+
+  // Unbind source
+  this->m_Source = NULL;
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::DataObject::
+DataObject( )
+  : Superclass( ),
+    m_Source( NULL )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::DataObject::
+~DataObject( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+bool cpPlugins::Pipeline::DataObject::
+_DisconnectVTK( )
+{
+  _TType* v = dynamic_cast< _TType* >( this->m_VTK.GetPointer( ) );
+  if( v != NULL )
+  {
+    vtkSmartPointer< _TType > d = vtkSmartPointer< _TType >::New( );
+    d->ShallowCopy( v );
+    this->m_VTK = d;
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/DataObject.h b/lib/cpPlugins/Pipeline/DataObject.h
new file mode 100644 (file)
index 0000000..04623cf
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __cpPlugins__Pipeline__DataObject__h__
+#define __cpPlugins__Pipeline__DataObject__h__
+
+#include <cpPlugins/Pipeline/Object.h>
+
+namespace cpPlugins
+{
+  namespace Pipeline
+  {
+    // Some forward declarations
+    class ProcessObject;
+
+    /**
+     */
+    class cpPlugins_EXPORT DataObject
+      : public Object
+    {
+      friend class ProcessObject;
+
+    public:
+      typedef DataObject                      Self;
+      typedef Object                          Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkNewMacro( Self );
+      itkTypeMacro( DataObject, Object );
+      cpPlugins_Id_Macro( DataObject, Object );
+
+    public:
+      virtual bool IsCompatible( const Self* other ) const;
+
+      ProcessObject* GetSource( );
+      const ProcessObject* GetSource( ) const;
+      void SetSource( ProcessObject* src );
+
+      void DisconnectFromPipeline( );
+
+    protected:
+      DataObject( );
+      virtual ~DataObject( );
+
+      template< class _TType >
+      inline bool _DisconnectVTK( );
+
+    private:
+      // Purposely not implemented
+      DataObject( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      ProcessObject* m_Source;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Pipeline__DataObject__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Events.h b/lib/cpPlugins/Pipeline/Events.h
new file mode 100644 (file)
index 0000000..a675d93
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __cpPlugins__Pipeline__Events__h__
+#define __cpPlugins__Pipeline__Events__h__
+
+#include <cpPlugins/Config.h>
+#include <itkEventObject.h>
+
+// -------------------------------------------------------------------------
+#define cpPluginsEventsOpenMacro( name )                                \
+  class name                                                            \
+    : public itk::AnyEvent                                              \
+  {                                                                     \
+  public:                                                               \
+    typedef name          Self;                                         \
+    typedef itk::AnyEvent Superclass;                                   \
+  public:                                                               \
+    name( ) : Superclass( ) { }                                         \
+      virtual ~name( )      { }                                         \
+      const char* GetEventName( ) const                                 \
+      { return( "cpPlugins::Pipeline::Events::#name" ); }               \
+      bool CheckEvent( const itk::EventObject* e ) const                \
+      { return( dynamic_cast< const Self* >( e ) != NULL ); }           \
+      itk::EventObject* MakeObject( ) const                             \
+      { return( new Self( ) ); }
+
+// -------------------------------------------------------------------------
+#define cpPluginsEventsCloseMacro( name )       \
+  }
+
+namespace cpPlugins
+{
+  namespace Pipeline
+  {
+    namespace Events
+    {
+      /**
+       */
+      cpPluginsEventsOpenMacro( Modified )
+        public:
+      itk::ModifiedTimeType Time;
+      long                  Span;
+      cpPluginsEventsCloseMacro( Modified );
+
+    } // ecapseman
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Pipeline__Events__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Object.cxx b/lib/cpPlugins/Pipeline/Object.cxx
new file mode 100644 (file)
index 0000000..abcac9c
--- /dev/null
@@ -0,0 +1,98 @@
+#include <cpPlugins/Pipeline/Object.h>
+
+#include <itkObject.h>
+#include <vtkObject.h>
+
+// -------------------------------------------------------------------------
+const float& cpPlugins::Pipeline::Object::
+GetViewX( ) const
+{
+  return( this->m_ViewX );
+}
+
+// -------------------------------------------------------------------------
+const float& cpPlugins::Pipeline::Object::
+GetViewY( ) const
+{
+  return( this->m_ViewY );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Object::
+SetViewCoords( float x, float y )
+{
+  this->m_ViewX = x;
+  this->m_ViewY = y;
+  // WARNING: do not call "this->Modified( )" -> It could lead to
+  //          re-execution of all pipeline
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Object::
+Modified( ) const
+{
+  const itk::Object* i =
+    dynamic_cast< const itk::Object* >( this->m_ITK.GetPointer( ) );
+  vtkObject* v = dynamic_cast< vtkObject* >( this->m_VTK.GetPointer( ) );
+  if( i != NULL ) i->Modified( );
+  if( v != NULL ) v->Modified( );
+  this->Superclass::Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Object::
+SetITK( itk::LightObject* o )
+{
+  if( this->m_ITK.GetPointer( ) != o )
+  {
+    this->m_ITK = o;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Object::
+SetVTK( vtkObjectBase* o )
+{
+  if( this->m_VTK.GetPointer( ) != o )
+  {
+    this->m_VTK = o;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Object::
+Object( )
+  : m_ITK( NULL ),
+    m_VTK( NULL ),
+    m_ViewX( float( 0 ) ),
+    m_ViewY( float( 0 ) )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Object::
+~Object( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Object::
+_UpdateITK( ) const
+{
+  // WARNING: do nothing since this is supposed to be defined by DataObjects
+  // with ITK-VTK conversion strategies.
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Object::
+_UpdateVTK( ) const
+{
+  // WARNING: do nothing since this is supposed to be defined by DataObjects
+  // with ITK-VTK conversion strategies.
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Object.h b/lib/cpPlugins/Pipeline/Object.h
new file mode 100644 (file)
index 0000000..c920abb
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef __cpPlugins__Pipeline__Object__h__
+#define __cpPlugins__Pipeline__Object__h__
+
+#include <cpPlugins/Config.h>
+
+#include <itkLightObject.h>
+#include <itkObject.h>
+#include <itkObjectFactory.h>
+#include <vtkSmartPointer.h>
+#include <vtkObjectBase.h>
+
+namespace cpPlugins
+{
+  namespace Pipeline
+  {
+    /**
+     */
+    class cpPlugins_EXPORT Object
+      : public itk::Object
+    {
+    public:
+      typedef Object                          Self;
+      typedef itk::Object                     Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkTypeMacro( Object, itk::Object );
+
+    public:
+      virtual const char* GetClassName( ) const = 0;
+      virtual const char* GetClassCategory( ) const = 0;
+
+      const float& GetViewX( ) const;
+      const float& GetViewY( ) const;
+      void SetViewCoords( float x, float y );
+
+      virtual void Modified( ) const cpPlugins_OVERRIDE;
+
+      virtual void SetITK( itk::LightObject* o );
+      virtual void SetVTK( vtkObjectBase* o );
+
+      template< class _TType = itk::LightObject >
+      inline _TType* GetITK( )
+        {
+          if( this->m_ITK.GetPointer( ) == NULL )
+            this->_UpdateITK( );
+          return( dynamic_cast< _TType* >( this->m_ITK.GetPointer( ) ) );
+        }
+
+      template< class _TType = itk::LightObject >
+      inline const _TType* GetITK( ) const
+        {
+          if( this->m_ITK.GetPointer( ) == NULL )
+            this->_UpdateITK( );
+          return(
+            dynamic_cast< const _TType* >( this->m_ITK.GetPointer( ) )
+            );
+        }
+
+      template< class _TType = vtkObjectBase >
+      inline _TType* GetVTK( )
+        {
+          if( this->m_VTK.GetPointer( ) == NULL )
+            this->_UpdateVTK( );
+          return( dynamic_cast< _TType* >( this->m_VTK.GetPointer( ) ) );
+        }
+
+      template< class _TType = vtkObjectBase >
+      inline const _TType* GetVTK( ) const
+        {
+          if( this->m_VTK.GetPointer( ) == NULL )
+            this->_UpdateVTK( );
+          return(
+            dynamic_cast< const _TType* >( this->m_VTK.GetPointer( ) )
+            );
+        }
+
+    protected:
+      Object( );
+      virtual ~Object( );
+
+      virtual void _UpdateITK( ) const;
+      virtual void _UpdateVTK( ) const;
+
+    private:
+      // Purposely not implemented
+      Object( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      itk::LightObject::Pointer        m_ITK;
+      vtkSmartPointer< vtkObjectBase > m_VTK;
+
+      float m_ViewX;
+      float m_ViewY;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Pipeline__Object__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Parameters.cxx b/lib/cpPlugins/Pipeline/Parameters.cxx
new file mode 100644 (file)
index 0000000..ada5e9c
--- /dev/null
@@ -0,0 +1,742 @@
+#include <cpPlugins/Pipeline/Parameters.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+#include <cpPlugins/OS/String.h>
+#include <cpPlugins/tinyxml2/tinyxml2.h>
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Parameters::
+Parameters( )
+  : m_ProcessObject( NULL )
+{
+  this->Clear( );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Parameters::
+~Parameters( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::ProcessObject* cpPlugins::Pipeline::Parameters::
+GetProcessObject( )
+{
+  return( this->m_ProcessObject );
+}
+
+// -------------------------------------------------------------------------
+const
+cpPlugins::Pipeline::ProcessObject* cpPlugins::Pipeline::Parameters::
+GetProcessObject( ) const
+{
+  return( this->m_ProcessObject );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+SetProcessObject( cpPlugins::Pipeline::ProcessObject* po )
+{
+  this->m_ProcessObject = po;
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+Modified( ) const
+{
+  if( this->m_ProcessObject != NULL )
+    this->m_ProcessObject->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+Clear( )
+{
+  this->m_Parameters.clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+GetNames( std::vector< std::string >& container ) const
+{
+  container.clear( );
+  TParameters::const_iterator i = this->m_Parameters.begin( );
+  for( ; i != this->m_Parameters.end( ); ++i )
+    container.push_back( i->first );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Parameters::
+Type cpPlugins::Pipeline::Parameters::
+GetType( const std::string& name ) const
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+    return( i->second.first );
+  else
+    return( Self::NoType );
+}
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_TypeAsString( Y )      \
+  if( i->second.first == Self::Y )                              \
+    return( #Y )
+
+std::string cpPlugins::Pipeline::Parameters::
+GetTypeAsString( const std::string& name ) const
+{
+  auto i = this->m_Parameters.find( name );
+  cpPlugins_Pipeline_Parameters_TypeAsString( String );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( Bool );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( Int );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( Uint );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( Real );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( OpenFileName );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( SaveFileName );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( PathName );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( StringList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( BoolList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( IntList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( UintList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( RealList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( OpenFileNameList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( SaveFileNameList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( PathNameList );
+  else cpPlugins_Pipeline_Parameters_TypeAsString( Choices );
+  else return( "NoType" );
+}
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_TypeFromString( Y, str )   \
+  if( str == std::string( #Y ) )                                    \
+    return( Self::Y )
+
+cpPlugins::Pipeline::Parameters::
+Type cpPlugins::Pipeline::Parameters::
+GetTypeFromString( const std::string& t )
+{
+  cpPlugins_Pipeline_Parameters_TypeFromString( String, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( Bool, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( Int, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( Uint, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( Real, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( OpenFileName, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( SaveFileName, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( PathName, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( StringList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( BoolList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( IntList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( UintList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( RealList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( OpenFileNameList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( SaveFileNameList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( PathNameList, t );
+  else cpPlugins_Pipeline_Parameters_TypeFromString( Choices, t );
+  else return( Self::NoType );
+}
+
+// -------------------------------------------------------------------------
+std::string cpPlugins::Pipeline::Parameters::
+GetString( const std::string& name, bool force ) const
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == Self::String || force )
+      return( i->second.second );
+    else
+      return( "" );
+  }
+  else
+    return( "" );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+SetString( const std::string& name, const std::string& v, bool force )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == Self::String || force )
+    {
+      if( i->second.second != v )
+      {
+        i->second.second = v;
+        this->Modified( );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+ConfigureAsChoices(
+  const std::string& name, const std::vector< std::string >& choices
+  )
+{
+  // It is invalid not to give choices when configuring
+  if( choices.size( ) == 0 )
+    return;
+
+  std::stringstream str_choices;
+  str_choices << choices[ 0 ];
+  for( unsigned int i = 1; i < choices.size( ); ++i )
+    str_choices << "#" << choices[ i ];
+  str_choices << "@";
+  this->m_Parameters[ name ] =
+    TParameter( Self::Choices, str_choices.str( ) );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+ConfigureAsRealTypesChoices( const std::string& name )
+{
+  std::vector< std::string > choices;
+  choices.push_back( "float" );
+  choices.push_back( "double" );
+  this->ConfigureAsChoices( name, choices );
+  this->SetSelectedChoice( name, "float" );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+ConfigureAsIntTypesChoices( const std::string& name )
+{
+  std::vector< std::string > choices;
+  choices.push_back( "char" );
+  choices.push_back( "uchar" );
+  choices.push_back( "short" );
+  choices.push_back( "ushort" );
+  choices.push_back( "int" );
+  choices.push_back( "uint" );
+  choices.push_back( "long" );
+  choices.push_back( "ulong" );
+  this->ConfigureAsChoices( name, choices );
+  this->SetSelectedChoice( name, "char" );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+ConfigureAsScalarTypesChoices( const std::string& name )
+{
+  std::vector< std::string > choices;
+  choices.push_back( "char" );
+  choices.push_back( "uchar" );
+  choices.push_back( "short" );
+  choices.push_back( "ushort" );
+  choices.push_back( "int" );
+  choices.push_back( "uint" );
+  choices.push_back( "long" );
+  choices.push_back( "ulong" );
+  choices.push_back( "float" );
+  choices.push_back( "double" );
+  this->ConfigureAsChoices( name, choices );
+  this->SetSelectedChoice( name, "char" );
+}
+
+// -------------------------------------------------------------------------
+std::vector< std::string > cpPlugins::Pipeline::Parameters::
+GetChoices( const std::string& name ) const
+{
+  std::vector< std::string > choices;
+
+  TParameters::const_iterator i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == Self::Choices )
+    {
+      std::istringstream str_choices( i->second.second );
+      std::string real_choices;
+      std::getline( str_choices, real_choices, '@' );
+      std::istringstream str( real_choices );
+      std::string token;
+      while( std::getline( str, token, '#' ) )
+        choices.push_back( token );
+
+    } // fi
+
+  } // fi
+  return( choices );
+}
+
+// -------------------------------------------------------------------------
+std::string cpPlugins::Pipeline::Parameters::
+GetSelectedChoice( const std::string& name ) const
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == Self::Choices )
+    {
+      std::istringstream str_choices( i->second.second );
+      std::string real_choice;
+      std::getline( str_choices, real_choice, '@' );
+      std::getline( str_choices, real_choice, '@' );
+      return( real_choice );
+    }
+    else
+      return( "" );
+  }
+  else
+    return( "" );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::Parameters::
+SetSelectedChoice( const std::string& name, const std::string& choice )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == Self::Choices )
+    {
+      std::istringstream str_choices( i->second.second );
+      std::string choices;
+      std::getline( str_choices, choices, '@' );
+      if( choices.find( choice ) != std::string::npos )
+      {
+        std::stringstream new_choices;
+        new_choices << choices << "@" << choice;
+        i->second.second = new_choices.str( );
+        this->Modified( );
+        return( true );
+      }
+      else
+        return( false );
+    }
+    else
+      return( false );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+std::string cpPlugins::Pipeline::Parameters::
+GetAcceptedFileExtensions( const std::string& name ) const
+{
+  auto i = this->m_AcceptedFileExtensions.find( name );
+  if( i != this->m_AcceptedFileExtensions.end( ) )
+    return( i->second );
+  else
+    return( "" );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+SetAcceptedFileExtensions(
+  const std::string& name, const std::string& extensions
+  )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    bool is_valid = ( i->second.first == Self::OpenFileName );
+    is_valid     |= ( i->second.first == Self::SaveFileName );
+    is_valid     |= ( i->second.first == Self::OpenFileNameList );
+    is_valid     |= ( i->second.first == Self::SaveFileNameList );
+    if( is_valid )
+      this->m_AcceptedFileExtensions[ name ] = extensions;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::Parameters::
+ToXML(
+  tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* parent_elem
+  ) const
+{
+  if( parent_elem == NULL )
+    return( false );
+
+  auto pIt = this->m_Parameters.begin( );
+  for( ; pIt != this->m_Parameters.end( ); ++pIt )
+  {
+    tinyxml2::XMLElement* p = doc->NewElement( "Parameter" );
+    p->SetAttribute( "Name", pIt->first.c_str( ) );
+    p->SetAttribute( "Value", pIt->second.second.c_str( ) );
+    p->SetAttribute( "Type", this->GetTypeAsString( pIt->first ).c_str( ) );
+    parent_elem->InsertEndChild( p );
+
+  } // rof
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::Parameters::
+FromXML( const tinyxml2::XMLElement* filter_elem )
+{
+  const tinyxml2::XMLElement* param =
+    filter_elem->FirstChildElement( "Parameter" );
+  bool ret = false;
+  while( param != NULL )
+  {
+    const char* param_name = param->Attribute( "Name" );
+    const char* param_type = param->Attribute( "Type" );
+    if( param_name != NULL && param_type != NULL )
+    {
+      TParameter value;
+      value.second = param->Attribute( "Value" );
+      value.first = Self::GetTypeFromString( param_type );
+      this->m_Parameters[ param_name ] = value;
+
+    } // fi
+    param = param->NextSiblingElement( "Parameter" );
+    ret = true;
+
+  } // elihw
+  this->Modified( );
+  return( ret );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Parameters::
+TParameters& cpPlugins::Pipeline::Parameters::
+GetRawParameters( )
+{
+  return( this->m_Parameters );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Pipeline::Parameters::
+TParameters& cpPlugins::Pipeline::Parameters::
+GetRawParameters( ) const
+{
+  return( this->m_Parameters );
+}
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_Configure_Code( Y )            \
+  void cpPlugins::Pipeline::Parameters::                             \
+  ConfigureAs##Y( const std::string& name, const T##Y& init )           \
+  {                                                                     \
+    this->_Configure< Y >( name );                                      \
+    this->Set##Y( name, init );                                         \
+  }                                                                     \
+  bool cpPlugins::Pipeline::Parameters::                             \
+  Has##Y( const std::string& name ) const                               \
+  { return( this->_Has< Y >( name ) ); }
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_ConfigureList_Code( Y )        \
+  void cpPlugins::Pipeline::Parameters::                             \
+  ConfigureAs##Y##List( const std::string& name )                       \
+  { this->_Configure< Y##List >( name ); }                              \
+  bool cpPlugins::Pipeline::Parameters::                             \
+  Has##Y##List( const std::string& name ) const                         \
+  { return( this->_Has< Y##List >( name ) ); }
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_GetSet_Code( Y )               \
+  cpPlugins::Pipeline::Parameters::T##Y                              \
+  cpPlugins::Pipeline::Parameters::                                  \
+  Get##Y( const std::string& name ) const                               \
+  { return( this->_Get< T##Y, Y >( name ) ); }                          \
+  void cpPlugins::Pipeline::Parameters::Set##Y(                      \
+    const std::string& name, const T##Y& v                              \
+    )                                                                   \
+  { this->_Set< T##Y, Y >( name, v ); }
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_GetSetList_Code( Y )           \
+  std::vector< cpPlugins::Pipeline::Parameters::T##Y >               \
+  cpPlugins::Pipeline::Parameters::                                  \
+  Get##Y##List( const std::string& name ) const                         \
+  { return( this->_GetList< T##Y, Y##List >( name ) ); }                \
+  void cpPlugins::Pipeline::Parameters::AddTo##Y##List(              \
+    const std::string& name,                                            \
+    const cpPlugins::Pipeline::Parameters::T##Y& v                   \
+    )                                                                   \
+  { this->_AddToList< T##Y, Y##List >( name, v ); }                     \
+  void cpPlugins::Pipeline::Parameters::                             \
+  Clear##Y##List( const std::string& name )                             \
+  { this->_ClearList< Y##List >( name ); }
+
+// -------------------------------------------------------------------------
+cpPlugins_Pipeline_Parameters_Configure_Code( String );
+cpPlugins_Pipeline_Parameters_Configure_Code( Bool );
+cpPlugins_Pipeline_Parameters_Configure_Code( Int );
+cpPlugins_Pipeline_Parameters_Configure_Code( Uint );
+cpPlugins_Pipeline_Parameters_Configure_Code( Real );
+cpPlugins_Pipeline_Parameters_Configure_Code( OpenFileName );
+cpPlugins_Pipeline_Parameters_Configure_Code( SaveFileName );
+cpPlugins_Pipeline_Parameters_Configure_Code( PathName );
+
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( String );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( Bool );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( Int );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( Uint );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( Real );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( OpenFileName );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( SaveFileName );
+cpPlugins_Pipeline_Parameters_ConfigureList_Code( PathName );
+
+cpPlugins_Pipeline_Parameters_GetSet_Code( Bool );
+cpPlugins_Pipeline_Parameters_GetSet_Code( Int );
+cpPlugins_Pipeline_Parameters_GetSet_Code( Uint );
+cpPlugins_Pipeline_Parameters_GetSet_Code( Real );
+cpPlugins_Pipeline_Parameters_GetSet_Code( OpenFileName );
+cpPlugins_Pipeline_Parameters_GetSet_Code( SaveFileName );
+cpPlugins_Pipeline_Parameters_GetSet_Code( PathName );
+
+cpPlugins_Pipeline_Parameters_GetSetList_Code( String );
+cpPlugins_Pipeline_Parameters_GetSetList_Code( Bool );
+cpPlugins_Pipeline_Parameters_GetSetList_Code( Int );
+cpPlugins_Pipeline_Parameters_GetSetList_Code( Uint );
+cpPlugins_Pipeline_Parameters_GetSetList_Code( Real );
+cpPlugins_Pipeline_Parameters_GetSetList_Code( PathName );
+
+// -------------------------------------------------------------------------
+std::vector< cpPlugins::Pipeline::Parameters::TOpenFileName >
+cpPlugins::Pipeline::Parameters::
+GetOpenFileNameList( const std::string& name ) const
+{
+  return( this->_GetList< TOpenFileName, OpenFileNameList >( name ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+AddToOpenFileNameList(
+  const std::string& name,
+  const cpPlugins::Pipeline::Parameters::TOpenFileName& v
+  )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == OpenFileNameList )
+    {
+      auto pos = v.find_last_of( "/\\" );
+      if( i->second.second == "" )
+        i->second.second = v.substr( 0, pos );
+      i->second.second += std::string( "#" );
+      i->second.second += v.substr( pos + 1 );
+      this->Modified( );
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+ClearOpenFileNameList( const std::string& name )
+{
+  this->_ClearList< OpenFileNameList >( name );
+}
+
+// -------------------------------------------------------------------------
+std::vector< cpPlugins::Pipeline::Parameters::TSaveFileName >
+cpPlugins::Pipeline::Parameters::
+GetSaveFileNameList( const std::string& name ) const
+{
+  return( this->_GetList< TSaveFileName, SaveFileNameList >( name ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+AddToSaveFileNameList(
+  const std::string& name,
+  const cpPlugins::Pipeline::Parameters::TSaveFileName& v
+  )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == SaveFileNameList )
+    {
+      auto pos = v.find_last_of( "/\\" );
+      if( i->second.second == "" )
+        i->second.second = v.substr( 0, pos );
+      i->second.second += std::string( "#" );
+      i->second.second += v.substr( pos + 1 );
+      this->Modified( );
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Parameters::
+ClearSaveFileNameList( const std::string& name )
+{
+  this->_ClearList< SaveFileNameList >( name );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _Enum >
+void cpPlugins::Pipeline::Parameters::
+_Configure( const std::string& name )
+{
+  this->m_Parameters[ name ] = TParameter( ( Self::Type )( _Enum ), "" );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _Enum >
+bool cpPlugins::Pipeline::Parameters::
+_Has( const std::string& name ) const
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+    return( i->second.first == ( Self::Type )( _Enum ) );
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+template< class _Type, unsigned int _Enum >
+_Type cpPlugins::Pipeline::Parameters::
+_Get( const std::string& name ) const
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == ( Self::Type )( _Enum ) )
+    {
+      if( typeid( _Type ) != typeid( std::string ) )
+      {
+        std::istringstream tok_str( i->second.second );
+        _Type v;
+        tok_str >> v;
+        return( v );
+      }
+      else
+      {
+        const _Type* ptr =
+          reinterpret_cast< const _Type* >( &( i->second.second ) );
+        return( *ptr );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+  return( _Type( 0 ) );
+}
+
+// -------------------------------------------------------------------------
+template< class _Type, unsigned int _Enum >
+void cpPlugins::Pipeline::Parameters::
+_Set( const std::string& name, const _Type& v )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == ( Self::Type )( _Enum ) )
+    {
+      if( typeid( _Type ) != typeid( std::string ) )
+      {
+        std::stringstream str;
+        str << v;
+        if( i->second.second != str.str( ) )
+        {
+          i->second.second = str.str( );
+          this->Modified( );
+
+        } // fi
+      }
+      else
+      {
+        const std::string* str = reinterpret_cast< const std::string* >( &v );
+        if( i->second.second != *str )
+        {
+          i->second.second = *str;
+          this->Modified( );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _Type, unsigned int _Enum >
+std::vector< _Type > cpPlugins::Pipeline::Parameters::
+_GetList( const std::string& name ) const
+{
+  std::vector< _Type > lst;
+  std::vector< std::string >* slst =
+    reinterpret_cast< std::vector< std::string >* >( &lst );
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == ( Self::Type )( _Enum ) )
+    {
+      std::vector< std::string > tokens =
+        cpPlugins::OS::String::Tokenize( i->second.second, "#" );
+      for( auto t = tokens.begin( ); t != tokens.end( ); ++t )
+      {
+        if( typeid( _Type ) != typeid( std::string ) )
+        {
+          std::istringstream tok_str( *t );
+          _Type v;
+          tok_str >> v;
+          lst.push_back( v );
+        }
+        else
+          slst->push_back( *t );
+
+      } // rof
+
+    } // fi
+
+  } // fi
+  return( lst );
+}
+
+// -------------------------------------------------------------------------
+template< class _Type, unsigned int _Enum >
+void cpPlugins::Pipeline::Parameters::
+_AddToList( const std::string& name, const _Type& v )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == ( Self::Type )( _Enum ) )
+    {
+      std::stringstream str;
+      if( i->second.second != "" )
+        str << i->second.second << "#";
+      str << v;
+      i->second.second = str.str( );
+      this->Modified( );
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _Enum >
+void cpPlugins::Pipeline::Parameters::
+_ClearList( const std::string& name )
+{
+  auto i = this->m_Parameters.find( name );
+  if( i != this->m_Parameters.end( ) )
+  {
+    if( i->second.first == ( Self::Type )( _Enum ) )
+    {
+      if( i->second.second != "" )
+      {
+        i->second.second = "";
+        this->Modified( );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Parameters.h b/lib/cpPlugins/Pipeline/Parameters.h
new file mode 100644 (file)
index 0000000..4dbd871
--- /dev/null
@@ -0,0 +1,223 @@
+#ifndef __cpPlugins__Pipeline__Parameters__h__
+#define __cpPlugins__Pipeline__Parameters__h__
+
+#include <cpPlugins/Config.h>
+
+#include <map>
+#include <ostream>
+#include <sstream>
+#include <typeinfo>
+#include <vector>
+#include <itkTimeStamp.h>
+
+// Some forward declarations
+namespace tinyxml2
+{
+  class XMLElement;
+  class XMLDocument;
+}
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_Configure( Y )                 \
+  void ConfigureAs##Y( const std::string& name, const T##Y& init );     \
+  bool Has##Y( const std::string& name ) const
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_ConfigureList( Y )             \
+  void ConfigureAs##Y##List( const std::string& name );                 \
+  bool Has##Y##List( const std::string& name ) const
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_GetSet( Y )    \
+  T##Y Get##Y( const std::string& name ) const;         \
+  void Set##Y( const std::string& name, const T##Y& v )
+
+// -------------------------------------------------------------------------
+#define cpPlugins_Pipeline_Parameters_GetSetList( Y )                \
+  std::vector< T##Y > Get##Y##List( const std::string& name ) const;    \
+  void AddTo##Y##List( const std::string& name, const T##Y& v );        \
+  void Clear##Y##List( const std::string& name )
+
+// -------------------------------------------------------------------------
+namespace cpPlugins
+{
+  namespace QT { class ParametersDialog; }
+
+  namespace Pipeline
+  {
+    class ProcessObject;
+
+    /**
+     */
+    class cpPlugins_EXPORT Parameters
+    {
+      // Frienship with forward declaration to improve Qt dialog execution
+      friend class cpPlugins::QT::ParametersDialog;
+      friend std::ostream& operator<<( std::ostream& o, const Parameters& p )
+        {
+          for(
+            auto i = p.m_Parameters.begin( );
+            i != p.m_Parameters.end( );
+            ++i
+            )
+            o << i->first << ": ("
+              << i->second.first << " | "
+              << i->second.second << ")"
+              << std::endl;
+          return( o );
+        }
+
+    public:
+      typedef Parameters Self;
+
+      enum Type
+      {
+        String       , Bool             , Int              ,
+        Uint         , Real             , OpenFileName     ,
+        SaveFileName , PathName         , StringList       ,
+        BoolList     , IntList          , UintList         ,
+        RealList     , OpenFileNameList , SaveFileNameList ,
+        PathNameList , Choices          , NoType
+      };
+
+      typedef bool          TBool;
+      typedef long          TInt;
+      typedef unsigned long TUint;
+      typedef double        TReal;
+      typedef std::string   TString;
+      typedef std::string   TOpenFileName;
+      typedef std::string   TSaveFileName;
+      typedef std::string   TPathName;
+
+      typedef std::pair< Self::Type, std::string > TParameter;
+      typedef std::map< std::string, TParameter >  TParameters;
+
+    public:
+      cpPlugins_Pipeline_Parameters_Configure( String );
+      cpPlugins_Pipeline_Parameters_Configure( Bool );
+      cpPlugins_Pipeline_Parameters_Configure( Int );
+      cpPlugins_Pipeline_Parameters_Configure( Uint );
+      cpPlugins_Pipeline_Parameters_Configure( Real );
+      cpPlugins_Pipeline_Parameters_Configure( OpenFileName );
+      cpPlugins_Pipeline_Parameters_Configure( SaveFileName );
+      cpPlugins_Pipeline_Parameters_Configure( PathName );
+
+      cpPlugins_Pipeline_Parameters_ConfigureList( String );
+      cpPlugins_Pipeline_Parameters_ConfigureList( Bool );
+      cpPlugins_Pipeline_Parameters_ConfigureList( Int );
+      cpPlugins_Pipeline_Parameters_ConfigureList( Uint );
+      cpPlugins_Pipeline_Parameters_ConfigureList( Real );
+      cpPlugins_Pipeline_Parameters_ConfigureList( OpenFileName );
+      cpPlugins_Pipeline_Parameters_ConfigureList( SaveFileName );
+      cpPlugins_Pipeline_Parameters_ConfigureList( PathName );
+
+      cpPlugins_Pipeline_Parameters_GetSet( Bool );
+      cpPlugins_Pipeline_Parameters_GetSet( Int );
+      cpPlugins_Pipeline_Parameters_GetSet( Uint );
+      cpPlugins_Pipeline_Parameters_GetSet( Real );
+      cpPlugins_Pipeline_Parameters_GetSet( OpenFileName );
+      cpPlugins_Pipeline_Parameters_GetSet( SaveFileName );
+      cpPlugins_Pipeline_Parameters_GetSet( PathName );
+
+      cpPlugins_Pipeline_Parameters_GetSetList( String );
+      cpPlugins_Pipeline_Parameters_GetSetList( Bool );
+      cpPlugins_Pipeline_Parameters_GetSetList( Int );
+      cpPlugins_Pipeline_Parameters_GetSetList( Uint );
+      cpPlugins_Pipeline_Parameters_GetSetList( Real );
+      cpPlugins_Pipeline_Parameters_GetSetList( OpenFileName );
+      cpPlugins_Pipeline_Parameters_GetSetList( SaveFileName );
+      cpPlugins_Pipeline_Parameters_GetSetList( PathName );
+
+    public:
+      Parameters( );
+      virtual ~Parameters( );
+
+      ProcessObject* GetProcessObject( );
+      const ProcessObject* GetProcessObject( ) const;
+      void SetProcessObject( ProcessObject* po );
+      virtual void Modified( ) const;
+
+      // Parameters container configuration
+      void Clear( );
+
+      // Get methods
+      void GetNames( std::vector< std::string >& container ) const;
+      Type GetType( const std::string& name ) const;
+      std::string GetTypeAsString( const std::string& name ) const;
+      static Type GetTypeFromString( const std::string& t );
+
+      // Base string methods
+      std::string GetString(
+        const std::string& name, bool force = true
+        ) const;
+      void SetString(
+        const std::string& name, const std::string& v, bool force = true
+        );
+
+      void ConfigureAsChoices(
+        const std::string& name, const std::vector< std::string >& choices
+        );
+      void ConfigureAsRealTypesChoices( const std::string& name );
+      void ConfigureAsIntTypesChoices( const std::string& name );
+      void ConfigureAsScalarTypesChoices( const std::string& name );
+      std::vector< std::string > GetChoices( const std::string& name ) const;
+      std::string GetSelectedChoice( const std::string& name ) const;
+      bool SetSelectedChoice(
+        const std::string& name, const std::string& choice
+        );
+
+      std::string GetAcceptedFileExtensions( const std::string& name ) const;
+      void SetAcceptedFileExtensions(
+        const std::string& name, const std::string& extensions
+        );
+
+      // XML "streaming"
+      bool ToXML(
+        tinyxml2::XMLDocument* doc,
+        tinyxml2::XMLElement* parent_elem
+        ) const;
+      bool FromXML( const tinyxml2::XMLElement* filter_elem );
+
+    protected:
+      TParameters& GetRawParameters( );
+      const TParameters& GetRawParameters( ) const;
+
+      template< unsigned int _Enum >
+      inline void _Configure( const std::string& name );
+
+      template< unsigned int _Enum >
+      inline bool _Has( const std::string& name ) const;
+
+      template< class _Type, unsigned int _Enum >
+      inline _Type _Get( const std::string& name ) const;
+
+      template< class _Type, unsigned int _Enum >
+      inline void _Set( const std::string& name, const _Type& v );
+
+      template< class _Type, unsigned int _Enum >
+      inline std::vector< _Type > _GetList( const std::string& name ) const;
+
+      template< class _Type, unsigned int _Enum >
+      inline void _AddToList( const std::string& name, const _Type& v );
+
+      template< unsigned int _Enum >
+      inline void _ClearList( const std::string& name );
+
+    private:
+      // Purposely not implemented
+      Parameters( const Self& other );
+      Self& operator=( const Self& other );
+
+    protected:
+      ProcessObject*                       m_ProcessObject;
+      TParameters                          m_Parameters;
+      std::map< std::string, std::string > m_AcceptedFileExtensions;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Pipeline__Parameters__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Port.cxx b/lib/cpPlugins/Pipeline/Port.cxx
new file mode 100644 (file)
index 0000000..4c980c0
--- /dev/null
@@ -0,0 +1,231 @@
+#include <cpPlugins/Pipeline/Port.h>
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Port::
+Port( bool required )
+  : m_Required( required )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Port::
+~Port( )
+{
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::Port::
+IsRequired( ) const
+{
+  return( this->m_Required );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Port::
+Clear( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::SingleDataPort::
+SingleDataPort( bool required )
+  : Superclass( required )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::SingleDataPort::
+~SingleDataPort( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::SingleDataPort::
+Add( cpPlugins::Pipeline::DataObject* o )
+{
+  if( this->m_Sample.IsNull( ) )
+    throw std::logic_error(
+      "cpPlugins::SingleDataPort: Port not yet configured"
+      );
+  if( o != NULL )
+  {
+    if( this->m_Sample->IsCompatible( o ) )
+      this->m_Data = o;
+    else
+      throw std::logic_error(
+        "cpPlugins::SingleDataPort: incompatible types \"" +
+        std::string( typeid( *o ).name( ) ) + std::string( "\" and \"" ) +
+        std::string( typeid( *( this->m_Sample.GetPointer( ) ) ).name( ) ) +
+        std::string( "\"" )
+        );
+  }
+  else
+    this->m_Data = NULL;
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::DataObject* cpPlugins::Pipeline::SingleDataPort::
+Get( unsigned int i )
+{
+  return( this->m_Data.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Pipeline::DataObject* cpPlugins::Pipeline::SingleDataPort::
+Get( unsigned int i ) const
+{
+  return( this->m_Data.GetPointer( ) );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpPlugins::Pipeline::SingleDataPort::
+Size( ) const
+{
+  return( 1 );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::SingleDataPort::
+IsValid( ) const
+{
+  return( this->m_Data.IsNotNull( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::SingleDataPort::
+Clear( )
+{
+  this->m_Data = NULL;
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::OutputPort::
+OutputPort( bool required )
+  : Superclass( required )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::OutputPort::
+~OutputPort( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::OutputPort::
+Set( DataObject* o )
+{
+  this->m_Sample = o;
+  this->m_Data = o;
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::InputPort::
+InputPort( bool required )
+  : Superclass( required )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::InputPort::
+~InputPort( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::MultipleInputsPort::
+MultipleInputsPort( bool required )
+  : Superclass( required )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::MultipleInputsPort::
+~MultipleInputsPort( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::MultipleInputsPort::
+Add( cpPlugins::Pipeline::DataObject* o )
+{
+  if( this->m_Sample.IsNull( ) )
+    throw std::logic_error(
+      "cpPlugins::SingleDataPort: Port not yet configured"
+      );
+  if( o != NULL )
+  {
+    if( this->m_Sample->IsCompatible( o ) )
+    {
+      this->m_Data.push_back( o );
+    }
+    else
+      throw std::logic_error(
+        "cpPlugins::SingleDataPort: incompatible types \"" +
+        std::string( typeid( *o ).name( ) ) + std::string( "\" and \"" ) +
+        std::string( typeid( *( this->m_Sample.GetPointer( ) ) ).name( ) ) +
+        std::string( "\"" )
+        );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::DataObject*
+cpPlugins::Pipeline::MultipleInputsPort::
+Get( unsigned int i )
+{
+  if( i < this->m_Data.size( ) )
+    return( this->m_Data[ i ].GetPointer( ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Pipeline::DataObject*
+cpPlugins::Pipeline::MultipleInputsPort::
+Get( unsigned int i ) const
+{
+  if( i < this->m_Data.size( ) )
+    return( this->m_Data[ i ].GetPointer( ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpPlugins::Pipeline::MultipleInputsPort::
+Size( ) const
+{
+  return( this->m_Data.size( ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::MultipleInputsPort::
+IsValid( ) const
+{
+  if( this->m_Data.size( ) > 0 )
+    return( this->m_Data[ 0 ].IsNotNull( ) );
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::MultipleInputsPort::
+Clear( )
+{
+  this->m_Data.clear( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::MultipleInputsPort::
+Delete( unsigned int id )
+{
+  if( id < this->m_Data.size( ) )
+  {
+    this->m_Data[ id ] = NULL;
+    this->m_Data.erase( this->m_Data.begin( ) + id );
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Port.h b/lib/cpPlugins/Pipeline/Port.h
new file mode 100644 (file)
index 0000000..db912ff
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __cpPlugins__Pipeline__Port__h__
+#define __cpPlugins__Pipeline__Port__h__
+
+#include <vector>
+#include <cpPlugins/Pipeline/DataObject.h>
+
+namespace cpPlugins
+{
+  namespace Pipeline
+  {
+    /**
+     */
+    class cpPlugins_EXPORT Port
+    {
+    public:
+      typedef Port Self;
+
+    public:
+      Port( bool required = true );
+      virtual ~Port( );
+
+      virtual void Add( DataObject* o ) = 0;
+      virtual DataObject* Get( unsigned int i = 0 ) = 0;
+      virtual const DataObject* Get( unsigned int i = 0 ) const = 0;
+      virtual unsigned int Size( ) const = 0;
+      virtual bool IsValid( ) const = 0;
+
+      virtual bool IsRequired( ) const;
+      virtual void Clear( );
+
+      template< class _TType >
+      inline void Configure( ) { this->m_Sample = _TType::New( ); }
+
+    protected:
+      bool                m_Required;
+      DataObject::Pointer m_Sample;
+    };
+
+    /**
+     */
+    class cpPlugins_EXPORT SingleDataPort
+      : public Port
+    {
+    public:
+      typedef SingleDataPort Self;
+      typedef Port           Superclass;
+
+    public:
+      SingleDataPort( bool required = true );
+      virtual ~SingleDataPort( );
+
+      virtual void Add( DataObject* o ) cpPlugins_OVERRIDE;
+      virtual DataObject* Get( unsigned int i = 0 ) cpPlugins_OVERRIDE;
+      virtual const DataObject* Get( unsigned int i = 0 ) const cpPlugins_OVERRIDE;
+      virtual unsigned int Size( ) const cpPlugins_OVERRIDE;
+      virtual bool IsValid( ) const cpPlugins_OVERRIDE;
+      virtual void Clear( ) cpPlugins_OVERRIDE;
+
+    protected:
+      DataObject::Pointer m_Data;
+    };
+
+    /**
+     */
+    class cpPlugins_EXPORT OutputPort
+      : public SingleDataPort
+    {
+    public:
+      typedef OutputPort     Self;
+      typedef SingleDataPort Superclass;
+      typedef Port           BaseClass;
+
+    public:
+      OutputPort( bool required = true );
+      virtual ~OutputPort( );
+
+      void Set( DataObject* o );
+    };
+
+    /**
+     */
+    class cpPlugins_EXPORT InputPort
+      : public SingleDataPort
+    {
+    public:
+      typedef InputPort      Self;
+      typedef SingleDataPort Superclass;
+      typedef Port           BaseClass;
+
+    public:
+      InputPort( bool required = true );
+      virtual ~InputPort( );
+    };
+
+    /**
+     */
+    class cpPlugins_EXPORT MultipleInputsPort
+      : public Port
+    {
+    public:
+      typedef MultipleInputsPort Self;
+      typedef Port               Superclass;
+
+    public:
+      MultipleInputsPort( bool required = true );
+      virtual ~MultipleInputsPort( );
+
+      virtual void Add( DataObject* o ) cpPlugins_OVERRIDE;
+      virtual DataObject* Get( unsigned int i = 0 ) cpPlugins_OVERRIDE;
+      virtual const DataObject* Get( unsigned int i = 0 ) const cpPlugins_OVERRIDE;
+      virtual unsigned int Size( ) const cpPlugins_OVERRIDE;
+      virtual bool IsValid( ) const cpPlugins_OVERRIDE;
+      virtual void Clear( ) cpPlugins_OVERRIDE;
+
+      void Delete( unsigned int id );
+
+    protected:
+      std::vector< DataObject::Pointer > m_Data;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Pipeline__Port__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/ProcessObject.cxx b/lib/cpPlugins/Pipeline/ProcessObject.cxx
new file mode 100644 (file)
index 0000000..c8edba2
--- /dev/null
@@ -0,0 +1,377 @@
+#include <cpPlugins/Pipeline/ProcessObject.h>
+#include <itkProcessObject.h>
+#include <itkExceptionObject.h>
+#include <cpPlugins/Pipeline/Events.h>
+#include <cpPlugins/OS/Chrono.h>
+
+#ifdef cpPlugins_QT4
+#  include <cpPlugins/QT/ParametersDialog.h>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+PrintExecutionOn( )
+{
+  this->SetPrintExecution( true );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+PrintExecutionOff( )
+{
+  this->SetPrintExecution( false );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::ProcessObject::
+GetPrintExecution( ) const
+{
+  return( this->m_PrintExecution );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::ProcessObject::
+SetPrintExecution( bool v )
+{
+  this->m_PrintExecution = v;
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+SetPrintExecutionStream( std::ofstream* s )
+{
+  this->m_PrintExecutionStream = s;
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Parameters*
+cpPlugins::Pipeline::ProcessObject::
+GetParameters( )
+{
+  return( &( this->m_Parameters ) );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Pipeline::Parameters*
+cpPlugins::Pipeline::ProcessObject::
+GetParameters( ) const
+{
+  return( &( this->m_Parameters ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+SetITK( itk::LightObject* o )
+{
+  // Polymorphism: do nothing -> this is a filter!!!
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+SetVTK( vtkObjectBase* o )
+{
+  // Polymorphism: do nothing -> this is a filter!!!
+}
+
+// -------------------------------------------------------------------------
+std::set< std::string > cpPlugins::Pipeline::ProcessObject::
+GetInputsNames( ) const
+{
+  std::set< std::string > names;
+  for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i )
+    names.insert( i->first );
+  return( names );
+}
+
+// -------------------------------------------------------------------------
+std::set< std::string > cpPlugins::Pipeline::ProcessObject::
+GetOutputsNames( ) const
+{
+  std::set< std::string > names;
+  for( auto i = this->m_Outputs.begin( ); i != this->m_Outputs.end( ); ++i )
+    names.insert( i->first );
+  return( names );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::ProcessObject::
+HasInput( const std::string& n ) const
+{
+  auto i = this->m_Inputs.find( n );
+  return( i != this->m_Inputs.end( ) );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::ProcessObject::
+HasOutput( const std::string& n ) const
+{
+  auto i = this->m_Outputs.find( n );
+  return( i != this->m_Outputs.end( ) );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpPlugins::Pipeline::ProcessObject::
+GetNumberOfInputs( ) const
+{
+  return( this->m_Inputs.size( ) );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpPlugins::Pipeline::ProcessObject::
+GetNumberOfOutputs( ) const
+{
+  return( this->m_Outputs.size( ) );
+}
+
+// -------------------------------------------------------------------------
+unsigned int cpPlugins::Pipeline::ProcessObject::
+GetInputSize( const std::string& n ) const
+{
+  auto it = this->m_Inputs.find( n );
+  if( it != this->m_Inputs.end( ) )
+    return( it->second->Size( ) );
+  else
+    return( 0 );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::ProcessObject::
+IsInputMultiple( const std::string& n ) const
+{
+  auto i = this->m_Inputs.find( n );
+  if( i != this->m_Inputs.end( ) )
+    return( dynamic_cast< MultipleInputsPort* >( i->second ) != NULL );
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+AddInput( const std::string& n, cpPlugins::Pipeline::DataObject* o )
+{
+  auto it = this->m_Inputs.find( n );
+  if( it != this->m_Inputs.end( ) )
+    it->second->Add( o );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+SetInput( const std::string& n, cpPlugins::Pipeline::DataObject* o )
+{
+  this->AddInput( n, o );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+DisconnectInput( const std::string& n, unsigned int id )
+{
+  auto inIt = this->m_Inputs.find( n );
+  if( inIt != this->m_Inputs.end( ) )
+  {
+    auto multi = dynamic_cast< MultipleInputsPort* >( inIt->second );
+    auto single = dynamic_cast< InputPort* >( inIt->second );
+    if( multi != NULL )
+      multi->Delete( id );
+    else if( single != NULL )
+      single->Add( NULL );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+DisconnectInputs( )
+{
+  for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i )
+    i->second->Clear( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+DisconnectOutputs( )
+{
+  for( auto i = this->m_Outputs.begin( ); i != this->m_Outputs.end( ); ++i )
+    if( i->second->IsValid( ) )
+      i->second->Get( )->DisconnectFromPipeline( );
+  this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+Disconnect( )
+{
+  this->DisconnectInputs( );
+  this->DisconnectOutputs( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+Modified( ) const
+{
+  this->Superclass::Modified( );
+
+  cpPlugins::Pipeline::Events::Modified evt;
+  evt.Time = this->m_LastExecutionTime;
+  evt.Span = this->m_LastExecutionSpan;
+  this->InvokeEvent( evt );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+Update( )
+{
+  // Force upstream updates
+  bool update = ( this->m_LastExecutionTime < this->GetMTime( ) );
+  try
+  {
+    for( auto input : this->m_Inputs )
+    {
+      for( unsigned int i = 0; i < input.second->Size( ); ++i )
+      {
+        auto obj = input.second->Get( i );
+        if( obj != NULL )
+        {
+          auto src = obj->GetSource( );
+          if( src != NULL )
+          {
+            src->Update( );
+            update |= ( this->m_LastExecutionTime < src->GetMTime( ) );
+
+          } // fi
+        }
+        else
+        {
+          if( input.second->IsRequired( ) )
+            this->_Error(
+              std::string( "Required input \"" ) + input.first +
+              std::string( "\" in filter \"" ) +
+              this->m_Name +
+              std::string( "\" is not valid." )
+              );
+
+        } // fi
+
+      } // rof
+
+    } // rof
+  }
+  catch( std::exception& err )
+  {
+    this->_Error( err.what( ) );
+
+  } // yrt
+
+  if( update || this->m_ExplicitExecution )
+  {
+    // Show a message, if needed...
+    if( this->m_PrintExecution && this->m_PrintExecutionStream != NULL )
+    {
+      *( this->m_PrintExecutionStream )
+        << "cpPlugins: Updating \""
+        << this->GetName( ) << " ("
+        << this->GetClassCategory( ) << ":" << this->GetClassName( )
+        << ")\"... ";
+      this->m_PrintExecutionStream->flush( );
+
+    } // fi
+
+    // Execute filter's algorithm and keep information about time
+    try
+    {
+      auto t_start = cpPlugins_CHRONO;
+      this->_GenerateData( );
+      auto t_end = cpPlugins_CHRONO;
+      this->Modified( );
+      this->m_LastExecutionSpan = long( t_end - t_start );
+      this->m_LastExecutionTime = this->GetMTime( );
+
+      // End the message, if needed...
+      if( this->m_PrintExecution && this->m_PrintExecutionStream != NULL )
+      {
+        *( this->m_PrintExecutionStream )
+          << "done in "
+          << double( this->m_LastExecutionSpan ) / double( 1000 )
+          << " s." << std::endl;
+
+      } // fi
+    }
+    catch( std::exception& err )
+    {
+      this->_Error( err.what( ) );
+
+    } // yrt
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+QDialog* cpPlugins::Pipeline::ProcessObject::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::ParametersDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::ParametersDialog( );
+    dlg->setProcessObject( this );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+AddInteractor( vtkRenderWindowInteractor* i )
+{
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::ProcessObject::
+IsInteractive( )
+{
+  return( false );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::ProcessObject::
+ProcessObject( )
+  : Superclass( ),
+    m_Name( "" ),
+    m_PluginName( "" ),
+    m_ExplicitExecution( false ),
+    m_LastExecutionTime( 0 ),
+    m_LastExecutionSpan( -1 ),
+    m_PrintExecution( false ),
+    m_PrintExecutionStream( &( std::cout ) )
+{
+  this->m_Parameters.SetProcessObject( this );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::ProcessObject::
+~ProcessObject( )
+{
+  for( auto i = this->m_Inputs.begin( ); i != this->m_Inputs.end( ); ++i )
+    delete i->second;
+  for( auto o = this->m_Outputs.begin( ); o != this->m_Outputs.end( ); ++o )
+    delete o->second;
+
+  this->m_Inputs.clear( );
+  this->m_Outputs.clear( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::ProcessObject::
+_Error( const std::string& error )
+{
+  if( error != "" )
+    itkExceptionMacro(
+      "Error: \"" << this->m_Name << "\": " << error
+      );
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/ProcessObject.h b/lib/cpPlugins/Pipeline/ProcessObject.h
new file mode 100644 (file)
index 0000000..77b4a3d
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef __cpPlugins__Pipeline__ProcessObject__h__
+#define __cpPlugins__Pipeline__ProcessObject__h__
+
+#include <cpPlugins/Pipeline/Object.h>
+#include <cpPlugins/Pipeline/Parameters.h>
+#include <cpPlugins/Pipeline/Port.h>
+#include <set>
+
+// -------------------------------------------------------------------------
+class QDialog;
+class vtkRenderWindowInteractor;
+
+// -------------------------------------------------------------------------
+namespace cpPlugins
+{
+  namespace Pipeline
+  {
+    /**
+     */
+    class cpPlugins_EXPORT ProcessObject
+      : public Object
+    {
+    public:
+      typedef ProcessObject                   Self;
+      typedef Object                          Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkTypeMacro( ProcessObject, Object );
+      cpPlugins_Id_Macro( ProcessObject, Object );
+
+      itkBooleanMacro( ExplicitExecution );
+
+      itkGetStringMacro( Name );
+      itkGetStringMacro( PluginName );
+      itkGetConstMacro( ExplicitExecution, bool );
+      itkGetConstMacro( LastExecutionSpan, long );
+
+      itkSetStringMacro( Name );
+      itkSetStringMacro( PluginName );
+      itkSetMacro( ExplicitExecution, bool );
+
+    public:
+      void PrintExecutionOn( );
+      void PrintExecutionOff( );
+      bool GetPrintExecution( ) const;
+      bool SetPrintExecution( bool v );
+      void SetPrintExecutionStream( std::ofstream* s );
+
+      Parameters* GetParameters( );
+      const Parameters* GetParameters( ) const;
+
+      virtual void SetITK( itk::LightObject* o );
+      virtual void SetVTK( vtkObjectBase* o );
+
+      // "Getters"
+      std::set< std::string > GetInputsNames( ) const;
+      std::set< std::string > GetOutputsNames( ) const;
+      bool HasInput( const std::string& n ) const;
+      bool HasOutput( const std::string& n ) const;
+
+      unsigned int GetNumberOfInputs( ) const;
+      unsigned int GetNumberOfOutputs( ) const;
+      unsigned int GetInputSize( const std::string& n ) const;
+      bool IsInputMultiple( const std::string& n ) const;
+
+      template< class _TType = DataObject >
+      inline _TType* GetInput( const std::string& n, unsigned int i = 0 );
+
+      template< class _TType = DataObject >
+      inline const _TType* GetInput(
+        const std::string& n, unsigned int i = 0
+        ) const;
+
+      template< class _TType = itk::LightObject >
+      inline _TType* GetInputData( const std::string& n, unsigned int i = 0 );
+
+      template< class _TType = itk::LightObject >
+      inline const _TType* GetInputData(
+        const std::string& n, unsigned int i = 0
+        ) const;
+
+      template< class _TType = DataObject >
+      inline _TType* GetOutput( const std::string& n );
+
+      template< class _TType = DataObject >
+      inline const _TType* GetOutput( const std::string& n ) const;
+
+      template< class _TType = itk::LightObject >
+      inline _TType* GetOutputData( const std::string& n );
+
+      template< class _TType = itk::LightObject >
+      inline const _TType* GetOutputData( const std::string& n ) const;
+
+      // "Setters"
+      virtual void AddInput( const std::string& n, DataObject* o );
+      virtual void SetInput( const std::string& n, DataObject* o );
+
+      // Other interesting methods
+      void DisconnectInput( const std::string& n, unsigned int id );
+      void DisconnectInputs( );
+      void DisconnectOutputs( );
+      void Disconnect( );
+
+      // Pipeline execution
+      virtual void Modified( ) const cpPlugins_OVERRIDE;
+      virtual void Update( );
+
+      // Qt dialog creation
+      virtual QDialog* CreateQDialog( );
+      virtual void AddInteractor( vtkRenderWindowInteractor* i );
+      virtual bool IsInteractive( );
+
+    protected:
+      ProcessObject( );
+      virtual ~ProcessObject( );
+
+      // Error handling method
+      void _Error( const std::string& error );
+
+      // For configuration purposes
+      template< class _TType = DataObject >
+      inline void _ConfigureInput(
+        const std::string& name, bool required, bool multiple
+        );
+
+      template< class _TType = DataObject >
+      inline void _ConfigureOutput( const std::string& name );
+
+      template< class _TFilter >
+      inline _TFilter* _CreateITK( );
+
+      template< class _TFilter >
+      inline _TFilter* _CreateVTK( );
+
+      virtual void _GenerateData( ) = 0;
+
+    private:
+      // Purposely not implemented
+      ProcessObject( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      Parameters m_Parameters;
+      std::string m_Name;
+      std::string m_PluginName;
+      bool m_ExplicitExecution;
+
+      std::map< std::string, Port* > m_Inputs;
+      std::map< std::string, Port* > m_Outputs;
+
+      itk::ModifiedTimeType m_LastExecutionTime;
+      mutable long m_LastExecutionSpan;
+
+      bool m_PrintExecution;
+      std::ostream* m_PrintExecutionStream;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#include <cpPlugins/Pipeline/ProcessObject.hxx>
+
+#endif // __cpPlugins__Pipeline__ProcessObject__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/ProcessObject.hxx b/lib/cpPlugins/Pipeline/ProcessObject.hxx
new file mode 100644 (file)
index 0000000..47cd480
--- /dev/null
@@ -0,0 +1,293 @@
+#ifndef __cpPlugins__Pipeline__ProcessObject__hxx__
+#define __cpPlugins__Pipeline__ProcessObject__hxx__
+
+// -------------------------------------------------------------------------
+template< class _TType >
+_TType* cpPlugins::Pipeline::ProcessObject::
+GetInput( const std::string& n, unsigned int i )
+{
+  auto it = this->m_Inputs.find( n );
+  if( it != this->m_Inputs.end( ) )
+    return( dynamic_cast< _TType* >( it->second->Get( i ) ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+const _TType* cpPlugins::Pipeline::ProcessObject::
+GetInput( const std::string& n, unsigned int i ) const
+{
+  auto it = this->m_Inputs.find( n );
+  if( it != this->m_Inputs.end( ) )
+    return( dynamic_cast< const _TType* >( it->second->Get( i ) ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+_TType* cpPlugins::Pipeline::ProcessObject::
+GetInputData( const std::string& n, unsigned int i )
+{
+  auto d = this->GetInput( n, i );
+  if( d != NULL )
+  {
+    auto oi = d->m_ITK.GetPointer( );
+    auto ov = d->m_VTK.GetPointer( );
+    if( oi != NULL && ov != NULL )
+    {
+      auto di = dynamic_cast< _TType* >( oi );
+      auto dv = dynamic_cast< _TType* >( ov );
+      if     ( di != NULL ) return( di );
+      else if( dv != NULL ) return( dv );
+      else                  return( NULL );
+    }
+    else if( oi != NULL && ov == NULL )
+    {
+      auto di = dynamic_cast< _TType* >( oi );
+      if( di == NULL )
+        return( d->GetVTK< _TType >( ) );
+      else
+        return( di );
+    }
+    else if( oi == NULL && ov != NULL )
+    {
+      auto dv = dynamic_cast< _TType* >( ov );
+      if( dv == NULL )
+        return( d->GetITK< _TType >( ) );
+      else
+        return( dv );
+    }
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+const _TType* cpPlugins::Pipeline::ProcessObject::
+GetInputData( const std::string& n, unsigned int i ) const
+{
+  auto d = this->GetInput( n, i );
+  if( d != NULL )
+  {
+    auto oi = d->m_ITK.GetPointer( );
+    auto ov = d->m_VTK.GetPointer( );
+    if( oi != NULL && ov != NULL )
+    {
+      auto di = dynamic_cast< const _TType* >( oi );
+      auto dv = dynamic_cast< const _TType* >( ov );
+      if     ( di != NULL ) return( di );
+      else if( dv != NULL ) return( dv );
+      else                  return( NULL );
+    }
+    else if( oi != NULL && ov == NULL )
+    {
+      auto di = dynamic_cast< const _TType* >( oi );
+      if( di == NULL )
+        return( d->GetVTK< _TType >( ) );
+      else
+        return( di );
+    }
+    else if( oi == NULL && ov != NULL )
+    {
+      auto dv = dynamic_cast< const _TType* >( ov );
+      if( dv == NULL )
+        return( d->GetITK< _TType >( ) );
+      else
+        return( dv );
+    }
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+_TType* cpPlugins::Pipeline::ProcessObject::
+GetOutput( const std::string& n )
+{
+  auto it = this->m_Outputs.find( n );
+  if( it != this->m_Outputs.end( ) )
+    return( dynamic_cast< _TType* >( it->second->Get( ) ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+const _TType* cpPlugins::Pipeline::ProcessObject::
+GetOutput( const std::string& n ) const
+{
+  auto it = this->m_Outputs.find( n );
+  if( it != this->m_Outputs.end( ) )
+    return( dynamic_cast< const _TType* >( it->second->Get( ) ) );
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+_TType* cpPlugins::Pipeline::ProcessObject::
+GetOutputData( const std::string& n )
+{
+  auto d = this->GetOutput( n );
+  if( d != NULL )
+  {
+    auto oi = d->m_ITK.GetPointer( );
+    auto ov = d->m_VTK.GetPointer( );
+    if( oi != NULL && ov != NULL )
+    {
+      auto di = dynamic_cast< _TType* >( oi );
+      auto dv = dynamic_cast< _TType* >( ov );
+      if     ( di != NULL ) return( di );
+      else if( dv != NULL ) return( dv );
+      else                  return( NULL );
+    }
+    else if( oi != NULL && ov == NULL )
+    {
+      auto di = dynamic_cast< _TType* >( oi );
+      if( di == NULL )
+        return( d->GetVTK< _TType >( ) );
+      else
+        return( di );
+    }
+    else if( oi == NULL && ov != NULL )
+    {
+      auto dv = dynamic_cast< _TType* >( ov );
+      if( dv == NULL )
+        return( d->GetITK< _TType >( ) );
+      else
+        return( dv );
+    }
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+const _TType* cpPlugins::Pipeline::ProcessObject::
+GetOutputData( const std::string& n ) const
+{
+  auto d = this->GetOutput( n );
+  if( d != NULL )
+  {
+    auto oi = d->m_ITK.GetPointer( );
+    auto ov = d->m_VTK.GetPointer( );
+    if( oi != NULL && ov != NULL )
+    {
+      auto di = dynamic_cast< const _TType* >( oi );
+      auto dv = dynamic_cast< const _TType* >( ov );
+      if     ( di != NULL ) return( di );
+      else if( dv != NULL ) return( dv );
+      else                  return( NULL );
+    }
+    else if( oi != NULL && ov == NULL )
+    {
+      auto di = dynamic_cast< const _TType* >( oi );
+      if( di == NULL )
+        return( d->GetVTK< _TType >( ) );
+      else
+        return( di );
+    }
+    else if( oi == NULL && ov != NULL )
+    {
+      auto dv = dynamic_cast< const _TType* >( ov );
+      if( dv == NULL )
+        return( d->GetITK< _TType >( ) );
+      else
+        return( dv );
+    }
+    else
+      return( NULL );
+  }
+  else
+    return( NULL );
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+void cpPlugins::Pipeline::ProcessObject::
+_ConfigureInput( const std::string& name, bool required, bool multiple )
+{
+  auto it = this->m_Inputs.find( name );
+  if( it == this->m_Inputs.end( ) )
+  {
+    Port* port;
+    if( multiple ) port = new MultipleInputsPort( required );
+    else           port = new InputPort( required );
+    port->Configure< _TType >( );
+    this->m_Inputs[ name ] = port;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TType >
+void cpPlugins::Pipeline::ProcessObject::
+_ConfigureOutput( const std::string& name )
+{
+  auto it = this->m_Outputs.find( name );
+  if( it == this->m_Outputs.end( ) )
+  {
+    Port* port = new OutputPort( true );
+    port->Configure< _TType >( );
+    port->Add( _TType::New( ) );
+    port->Get( )->SetSource( this );
+    this->m_Outputs[ name ] = port;
+    this->Modified( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+_TFilter* cpPlugins::Pipeline::ProcessObject::
+_CreateITK( )
+{
+  // TODO: why this lead to synch issues???
+  _TFilter* filter = this->GetITK< _TFilter >( );
+  if( filter == NULL )
+  {
+    typename _TFilter::Pointer filter_ptr = _TFilter::New( );
+    this->m_ITK = filter_ptr;
+    this->m_VTK = NULL;
+    filter = filter_ptr.GetPointer( );
+    this->Modified( );
+
+  } // fi
+  return( filter );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter >
+_TFilter* cpPlugins::Pipeline::ProcessObject::
+_CreateVTK( )
+{
+  // TODO: why this lead to synch issues???
+  _TFilter* filter = this->GetVTK< _TFilter >( );
+  if( filter == NULL )
+  {
+    vtkSmartPointer< _TFilter > filter_ptr =
+      vtkSmartPointer< _TFilter >::New( );
+    this->m_ITK = NULL;
+    this->m_VTK = filter_ptr;
+    filter = filter_ptr.GetPointer( );
+    this->Modified( );
+
+  } // fi
+  return( filter );
+}
+
+#endif // __cpPlugins__Pipeline__ProcessObject__hxx__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Widget.cxx b/lib/cpPlugins/Pipeline/Widget.cxx
new file mode 100644 (file)
index 0000000..482bed9
--- /dev/null
@@ -0,0 +1,46 @@
+#include <cpPlugins/Pipeline/Widget.h>
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Widget::
+AddInteractor( vtkRenderWindowInteractor* i )
+{
+  if( this->m_Interactors.insert( i ).second )
+    this->Modified( );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Pipeline::Widget::
+IsInteractive( )
+{
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Widget::
+EnabledOn( )
+{
+  this->SetEnabled( true );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Pipeline::Widget::
+EnabledOff( )
+{
+  this->SetEnabled( false );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Widget::
+Widget( )
+  : Superclass( )
+{
+  this->m_Parameters.ConfigureAsString( "Text", "" );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::Widget::
+~Widget( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Pipeline/Widget.h b/lib/cpPlugins/Pipeline/Widget.h
new file mode 100644 (file)
index 0000000..91ef571
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __cpPlugins__Pipeline__Widget__h__
+#define __cpPlugins__Pipeline__Widget__h__
+
+#include <cpPlugins/Pipeline/ProcessObject.h>
+#include <vtkRenderWindowInteractor.h>
+
+// -------------------------------------------------------------------------
+namespace cpPlugins
+{
+  namespace Pipeline
+  {
+    /**
+     */
+    class cpPlugins_EXPORT Widget
+      : public ProcessObject
+    {
+    public:
+      typedef Widget                          Self;
+      typedef ProcessObject                   Superclass;
+      typedef itk::SmartPointer< Self >       Pointer;
+      typedef itk::SmartPointer< const Self > ConstPointer;
+
+    public:
+      itkTypeMacro( Widget, ProcessObject );
+      cpPlugins_Id_Macro( Widget, Object );
+
+    public:
+      virtual void AddInteractor( vtkRenderWindowInteractor* i ) cpPlugins_OVERRIDE;
+      virtual bool IsInteractive( ) cpPlugins_OVERRIDE;
+
+      virtual void EnabledOn( );
+      virtual void EnabledOff( );
+      virtual void Clear( ) = 0;
+      virtual void SetEnabled( bool v ) = 0;
+      virtual bool GetEnabled( ) const = 0;
+
+    protected:
+      Widget( );
+      virtual ~Widget( );
+
+    private:
+      // Purposely not implemented
+      Widget( const Self& );
+      Self& operator=( const Self& );
+
+    protected:
+      typedef vtkSmartPointer< vtkRenderWindowInteractor > _TInteractor;
+      struct _TInteractorCmp
+      {
+        bool operator()(
+          const _TInteractor& a, const _TInteractor& b
+          ) const
+          { return( a.GetPointer( ) < b.GetPointer( ) ); }
+      };
+      std::set< _TInteractor, _TInteractorCmp > m_Interactors;
+
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__Pipeline__Widget__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/QT/OpenFileDialog.cxx b/lib/cpPlugins/QT/OpenFileDialog.cxx
new file mode 100644 (file)
index 0000000..784d111
--- /dev/null
@@ -0,0 +1,107 @@
+#include <cpPlugins/QT/OpenFileDialog.h>
+#include <cpPlugins/Pipeline/Parameters.h>
+
+// -------------------------------------------------------------------------
+cpPlugins::QT::OpenFileDialog::
+OpenFileDialog( QWidget* parent )
+  : QFileDialog( parent ),
+    m_Parameters( NULL ),
+    m_Name( "" )
+{
+  this->connect(
+    this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) )
+    );
+  this->setWindowTitle( "Open an(some) file(s)" );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::QT::OpenFileDialog::
+~OpenFileDialog( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::OpenFileDialog::
+SetParameters(
+  cpPlugins::Pipeline::Parameters* params, const std::string& name
+  )
+{
+  if( params == NULL )
+  {
+    this->m_Parameters = NULL;
+    this->m_Name = "";
+    return;
+
+  } // fi
+  auto param_type = params->GetType( name );
+  if(
+    param_type != cpPlugins::Pipeline::Parameters::OpenFileName &&
+    param_type != cpPlugins::Pipeline::Parameters::OpenFileNameList
+    )
+  {
+    this->m_Parameters = NULL;
+    this->m_Name = "";
+    return;
+
+  } // fi
+  this->m_Parameters = params;
+  this->m_Name = name;
+
+  QStringList filters;
+  auto extensions = this->m_Parameters->GetAcceptedFileExtensions( name );
+  if( extensions != "" )
+    filters << extensions.c_str( );
+  filters << "Any file (*)";
+  if( param_type == cpPlugins::Pipeline::Parameters::OpenFileName )
+    this->setFileMode( QFileDialog::ExistingFile );
+  else
+    this->setFileMode( QFileDialog::ExistingFiles );
+  this->setNameFilters( filters );
+  this->setAcceptMode( QFileDialog::AcceptOpen );
+  if( param_type == cpPlugins::Pipeline::Parameters::OpenFileName )
+  {
+    auto file = this->m_Parameters->GetOpenFileName( this->m_Name );
+    if( file == "" )
+      file = ".";
+    QFileInfo info( file.c_str( ) );
+    this->setDirectory( info.canonicalPath( ) );
+  }
+  else
+  {
+    auto files = this->m_Parameters->GetOpenFileNameList( this->m_Name );
+    if( files.size( ) > 0 )
+    {
+      QFileInfo info( files[ 0 ].c_str( ) );
+      this->setDirectory( info.canonicalPath( ) );
+    }
+    else
+      this->setDirectory( "." );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::OpenFileDialog::
+_dlg_Accepted( )
+{
+  if( this->m_Parameters != NULL )
+  {
+    auto files = this->selectedFiles( );
+    auto param_type = this->m_Parameters->GetType( this->m_Name );
+    if( param_type == cpPlugins::Pipeline::Parameters::OpenFileNameList )
+    {
+      this->m_Parameters->ClearOpenFileNameList( this->m_Name );
+      for( auto fIt = files.begin( ); fIt != files.end( ); ++fIt )
+        this->m_Parameters->AddToOpenFileNameList(
+          this->m_Name, fIt->toStdString( )
+          );
+    }
+    else
+      this->m_Parameters->SetOpenFileName(
+        this->m_Name, files[ 0 ].toStdString( )
+        );
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/QT/OpenFileDialog.h b/lib/cpPlugins/QT/OpenFileDialog.h
new file mode 100644 (file)
index 0000000..2a69404
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __cpPlugins__QT__OpenFileDialog__h__
+#define __cpPlugins__QT__OpenFileDialog__h__
+
+#include <cpPlugins/Config.h>
+#include <QFileDialog>
+
+namespace cpPlugins{ namespace Pipeline { class Parameters; } }
+
+namespace cpPlugins
+{
+  namespace QT
+  {
+    /**
+     */
+    class OpenFileDialog
+      : public QFileDialog
+    {
+      Q_OBJECT;
+    public:
+      OpenFileDialog( QWidget* parent = 0 );
+      virtual ~OpenFileDialog( );
+
+      void SetParameters(
+        cpPlugins::Pipeline::Parameters* params, const std::string& name
+        );
+
+    protected slots:
+      void _dlg_Accepted( );
+
+    protected:
+      cpPlugins::Pipeline::Parameters* m_Parameters;
+      std::string m_Name;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__QT__OpenFileDialog__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/QT/ParametersDialog.cxx b/lib/cpPlugins/QT/ParametersDialog.cxx
new file mode 100644 (file)
index 0000000..39f1276
--- /dev/null
@@ -0,0 +1,888 @@
+#include <cpPlugins/QT/ParametersDialog.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+#include <limits>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QDoubleSpinBox>
+#include <QFileDialog>
+#include <QHBoxLayout>
+#include <QInputDialog>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QWidget>
+
+// -------------------------------------------------------------------------
+cpPlugins::QT::ParametersDialog::
+ParametersDialog( QWidget* parent, Qt::WindowFlags f, bool manual )
+  : QDialog( parent, f ),
+    m_ProcessObject( NULL ),
+    m_WidgetsUpdated( false ),
+    m_Manual( manual )
+{
+  if( !this->m_Manual )
+  {
+    this->m_Title = new QLabel( this );
+    this->m_Title->setText( "Parameters dialog title" );
+    this->m_MainLayout = new QGridLayout( this );
+    this->m_ToolsLayout = new QVBoxLayout( );
+    this->m_ToolsLayout->addWidget( this->m_Title );
+    this->m_MainLayout->addLayout( this->m_ToolsLayout, 0, 0, 1, 1 );
+
+  } // fi
+  this->connect(
+    this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::QT::ParametersDialog::
+~ParametersDialog( )
+{
+  if( !this->m_Manual )
+  {
+    delete this->m_Title;
+    delete this->m_ToolsLayout;
+    delete this->m_MainLayout;
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Pipeline::ProcessObject*
+cpPlugins::QT::ParametersDialog::
+getProcessObject( ) const
+{
+  return( this->m_ProcessObject );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::QT::ParametersDialog::
+setProcessObject( cpPlugins::Pipeline::ProcessObject* obj )
+{
+  if( this->m_ProcessObject != NULL || obj == NULL )
+    return( false );
+  this->m_ProcessObject = obj;
+  this->m_WidgetsUpdated = false;
+  this->_updateWidgets( );
+  this->updateView( );
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+updateParameters( )
+{
+  if( this->m_ProcessObject == NULL )
+    return;
+  if( this->m_Manual )
+    return;
+
+  // Check if an explicit re-execution button is needed
+  QCheckBox* v_bool =
+    this->findChild< QCheckBox* >( "___ExplicitExecution___" );
+  if( v_bool != NULL )
+    this->m_ProcessObject->SetExplicitExecution( v_bool->isChecked( ) );
+
+  // Put values
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  auto& raw_params = parameters->GetRawParameters( );
+  for( auto pIt = raw_params.begin( ); pIt != raw_params.end( ); ++pIt )
+  {
+    QString pName = pIt->first.c_str( );
+    switch( pIt->second.first )
+    {
+    case cpPlugins::Pipeline::Parameters::String:
+    case cpPlugins::Pipeline::Parameters::OpenFileName:
+    case cpPlugins::Pipeline::Parameters::SaveFileName:
+    case cpPlugins::Pipeline::Parameters::PathName:
+    case cpPlugins::Pipeline::Parameters::IntList:
+    case cpPlugins::Pipeline::Parameters::UintList:
+    case cpPlugins::Pipeline::Parameters::RealList:
+    case cpPlugins::Pipeline::Parameters::OpenFileNameList:
+    {
+      QLineEdit* v_string = this->findChild< QLineEdit* >( pName );
+      if( v_string != NULL )
+        pIt->second.second = v_string->text( ).toStdString( );
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Bool:
+    {
+      QCheckBox* v_bool = this->findChild< QCheckBox* >( pName );
+      if( v_bool != NULL )
+        pIt->second.second = ( v_bool->isChecked( ) )? "1": "0";
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Int:
+    case cpPlugins::Pipeline::Parameters::Uint:
+    {
+      QSpinBox* v_uint = this->findChild< QSpinBox* >( pName );
+      if( v_uint )
+      {
+        std::stringstream str;
+        str << v_uint->value( );
+        pIt->second.second = str.str( );
+
+      } // fi
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Real:
+    {
+      QDoubleSpinBox* v_double = this->findChild< QDoubleSpinBox* >( pName );
+      if( v_double )
+      {
+        std::stringstream str;
+        str << v_double->value( );
+        pIt->second.second = str.str( );
+
+      } // fi
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::StringList:
+      break;
+    case cpPlugins::Pipeline::Parameters::BoolList:
+      break;
+    case cpPlugins::Pipeline::Parameters::SaveFileNameList:
+      break;
+    case cpPlugins::Pipeline::Parameters::PathNameList:
+      break;
+    case cpPlugins::Pipeline::Parameters::Choices:
+    {
+      QComboBox* v_choices = this->findChild< QComboBox* >( pName );
+      if( v_choices != NULL )
+      {
+        std::istringstream str_choices( pIt->second.second );
+        std::string real_choices;
+        std::getline( str_choices, real_choices, '@' );
+        pIt->second.second =
+          real_choices + "@" +
+          v_choices->currentText( ).toStdString( );
+
+      } // fi
+    }
+    break;
+    default:
+      break;
+    } // hctiws
+
+  } // rof
+  this->m_ProcessObject->Modified( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+updateView( )
+{
+  if( this->m_ProcessObject == NULL )
+    return;
+  if( this->m_Manual )
+    return;
+
+  // Check if an explicit re-execution button is needed
+  QCheckBox* v_bool =
+    this->findChild< QCheckBox* >( "___ExplicitExecution___" );
+  if( v_bool != NULL )
+    v_bool->setChecked( this->m_ProcessObject->GetExplicitExecution( ) );
+
+  // Put values
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  auto& raw_params = parameters->GetRawParameters( );
+  for( auto pIt = raw_params.begin( ); pIt != raw_params.end( ); ++pIt )
+  {
+    QString pName = pIt->first.c_str( );
+    switch( pIt->second.first )
+    {
+    case cpPlugins::Pipeline::Parameters::String:
+    case cpPlugins::Pipeline::Parameters::OpenFileName:
+    case cpPlugins::Pipeline::Parameters::SaveFileName:
+    case cpPlugins::Pipeline::Parameters::PathName:
+    case cpPlugins::Pipeline::Parameters::IntList:
+    case cpPlugins::Pipeline::Parameters::UintList:
+    case cpPlugins::Pipeline::Parameters::RealList:
+    case cpPlugins::Pipeline::Parameters::OpenFileNameList:
+    {
+      QLineEdit* v_string = this->findChild< QLineEdit* >( pName );
+      if( v_string != NULL )
+        v_string->setText( pIt->second.second.c_str( ) );
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Bool:
+    {
+      QCheckBox* v_bool = this->findChild< QCheckBox* >( pName );
+      if( v_bool != NULL )
+        v_bool->setChecked( pIt->second.second == "1" );
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Int:
+    case cpPlugins::Pipeline::Parameters::Uint:
+    {
+      QSpinBox* v_uint = this->findChild< QSpinBox* >( pName );
+      if( v_uint )
+      {
+        std::istringstream tok_str( pIt->second.second );
+        int v;
+        tok_str >> v;
+        v_uint->setValue( v );
+
+      } // fi
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Real:
+    {
+      QDoubleSpinBox* v_double = this->findChild< QDoubleSpinBox* >( pName );
+      if( v_double )
+      {
+        std::istringstream tok_str( pIt->second.second );
+        double v;
+        tok_str >> v;
+        v_double->setValue( v );
+
+      } // fi
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::StringList:
+      break;
+    case cpPlugins::Pipeline::Parameters::BoolList:
+      break;
+    case cpPlugins::Pipeline::Parameters::SaveFileNameList:
+      break;
+    case cpPlugins::Pipeline::Parameters::PathNameList:
+      break;
+    case cpPlugins::Pipeline::Parameters::Choices:
+    {
+      QComboBox* v_choices = this->findChild< QComboBox* >( pName );
+      if( v_choices != NULL )
+      {
+        std::istringstream str_choices( pIt->second.second );
+        std::string choices, real_choice;
+        std::getline( str_choices, choices, '@' );
+        std::getline( str_choices, real_choice, '@' );
+        std::istringstream str( choices );
+        std::string token;
+        int id = -1, cont = 0;
+        while( std::getline( str, token, '#' ) )
+        {
+          if( token == real_choice )
+            id = cont;
+          cont++;
+
+        } // elihw
+
+        if( id > -1 )
+          v_choices->setCurrentIndex( id );
+
+      } // fi
+    }
+    break;
+    default:
+      break;
+    } // hctiws
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_addButtons( )
+{
+  if( this->m_Manual )
+    return;
+
+  // Add buttons
+  this->m_Buttons = new QDialogButtonBox(
+    QDialogButtonBox::Ok | QDialogButtonBox::Cancel
+    );
+  this->connect(
+    this->m_Buttons, SIGNAL( accepted( ) ), this, SLOT( accept( ) )
+    );
+  this->connect(
+    this->m_Buttons, SIGNAL( rejected( ) ), this, SLOT( reject( ) )
+    );
+  this->m_ToolsLayout->addWidget( this->m_Buttons );
+
+  this->updateView( );
+  this->m_WidgetsUpdated = true;
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_updateWidgets( )
+{
+  if( this->m_WidgetsUpdated || this->m_ProcessObject == NULL )
+    return;
+  if( this->m_Manual )
+    return;
+
+  // Set dialog title
+  std::stringstream title;
+  title
+    << "Parameters for an object of class \""
+    << this->m_ProcessObject->GetClassName( )
+    << "\"";
+  this->m_Title->setText( title.str( ).c_str( ) );
+
+  // Check if an explicit re-execution button is needed
+  QCheckBox* v_bool = new QCheckBox( this );
+  v_bool->setObjectName( "___ExplicitExecution___" );
+  v_bool->setText( "Explicit re-execution" );
+  v_bool->setChecked( this->m_ProcessObject->GetExplicitExecution( ) );
+
+  QHBoxLayout* new_layout = new QHBoxLayout( );
+  new_layout->addWidget( v_bool );
+  this->m_ToolsLayout->addLayout( new_layout );
+
+  // Put values
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  auto& raw_params = parameters->GetRawParameters( );
+  for( auto pIt = raw_params.begin( ); pIt != raw_params.end( ); ++pIt )
+  {
+    QWidget* w_input = NULL;
+    switch( pIt->second.first )
+    {
+    case cpPlugins::Pipeline::Parameters::String:
+    {
+      QLineEdit* v_string = new QLineEdit( this );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      w_input = v_string;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Bool:
+    {
+      QCheckBox* v_bool = new QCheckBox( this );
+      v_bool->setObjectName( pIt->first.c_str( ) );
+      v_bool->setText( "[ON/OFF]" );
+      v_bool->setChecked( pIt->second.second == "1" );
+      w_input = v_bool;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Int:
+    case cpPlugins::Pipeline::Parameters::Uint:
+    {
+      std::istringstream tok_str( pIt->second.second );
+      int v;
+      tok_str >> v;
+      QSpinBox* v_uint = new QSpinBox( this );
+      v_uint->setObjectName( pIt->first.c_str( ) );
+      if( pIt->second.first == cpPlugins::Pipeline::Parameters::Uint )
+        v_uint->setMinimum( 0 );
+      else
+        v_uint->setMinimum( -std::numeric_limits< int >::max( ) );
+      v_uint->setMaximum( std::numeric_limits< int >::max( ) );
+      v_uint->setValue( v );
+      w_input = v_uint;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::Real:
+    {
+      std::istringstream tok_str( pIt->second.second );
+      double v;
+      tok_str >> v;
+      QDoubleSpinBox* v_double = new QDoubleSpinBox( this );
+      v_double->setObjectName( pIt->first.c_str( ) );
+      v_double->setDecimals( 3 );
+      v_double->setMinimum( -std::numeric_limits< double >::max( ) );
+      v_double->setMaximum(  std::numeric_limits< double >::max( ) );
+      v_double->setValue( v );
+      w_input = v_double;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::OpenFileName:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "..." );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_OpenSingleFile( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    case cpPlugins::Pipeline::Parameters::SaveFileName:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "..." );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_SaveSingleFile( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::PathName:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "..." );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_OpenSinglePath( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::StringList:
+      break;
+    case cpPlugins::Pipeline::Parameters::BoolList:
+      break;
+    case cpPlugins::Pipeline::Parameters::IntList:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "+" );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_AddInt( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::UintList:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "+" );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_AddUint( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::RealList:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "+" );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_AddReal( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::OpenFileNameList:
+    {
+      QFrame* frame = new QFrame( this );
+      QHBoxLayout* layout = new QHBoxLayout( frame );
+      QLineEdit* v_string = new QLineEdit( frame );
+      v_string->setObjectName( pIt->first.c_str( ) );
+      v_string->setMaxLength( std::numeric_limits< int >::max( ) );
+      v_string->setText( pIt->second.second.c_str( ) );
+      QPushButton* v_button = new QPushButton( frame );
+      v_button->setObjectName( ( pIt->first + "_=?btn" ).c_str( ) );
+      v_button->setText( "..." );
+      v_button->connect(
+        v_button, SIGNAL( clicked( ) ),
+        this, SLOT( _dlg_OpenMultipleFiles( ) )
+        );
+      layout->addWidget( v_string );
+      layout->addWidget( v_button );
+      w_input = frame;
+    }
+    break;
+    case cpPlugins::Pipeline::Parameters::SaveFileNameList:
+      break;
+    case cpPlugins::Pipeline::Parameters::PathNameList:
+      break;
+    case cpPlugins::Pipeline::Parameters::Choices:
+    {
+      QComboBox* v_choices = new QComboBox( this );
+      v_choices->setObjectName( pIt->first.c_str( ) );
+
+      std::istringstream str0( pIt->second.second );
+      std::string choices;
+      std::getline( str0, choices, '@' );
+      std::istringstream str1( choices );
+      std::string token;
+      int id = 0;
+      while( std::getline( str1, token, '#' ) )
+        v_choices->insertItem( id++, token.c_str( ) );
+      w_input = v_choices;
+    }
+    break;
+    default:
+      w_input = NULL;
+      break;
+    } // hctiws
+
+    // Ok, a representation was created
+    if( w_input != NULL )
+    {
+      QHBoxLayout* new_layout = new QHBoxLayout( );
+      QLabel* label = new QLabel( this );
+      label->setText( QString( pIt->first.c_str( ) ) );
+      new_layout->addWidget( label );
+      new_layout->addWidget( w_input );
+      this->m_ToolsLayout->addLayout( new_layout );
+
+    } // fi
+
+  } // rof
+
+  // Update values
+  this->_addButtons( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_Accepted( )
+{
+  this->updateParameters( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_OpenSingleFile( )
+{
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        std::string param_value = parameters->GetOpenFileName( param_name );
+        if( param_value == "" )
+          param_value = ".";
+        QStringList dialog_filters;
+        std::string extensions = parameters->GetAcceptedFileExtensions( param_name );
+        if( extensions != "" )
+          dialog_filters << extensions.c_str( );
+        dialog_filters << "Any file (*)";
+
+        // Show dialog and check if it was accepted
+        QFileDialog dialog( this );
+        dialog.setFileMode( QFileDialog::ExistingFile );
+        dialog.setDirectory( QFileDialog::tr( param_value.c_str( ) ) );
+        dialog.setNameFilters( dialog_filters );
+        dialog.setAcceptMode( QFileDialog::AcceptOpen );
+        if( dialog.exec( ) )
+          line->setText( *( dialog.selectedFiles( ).begin( ) ) );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_SaveSingleFile( )
+{
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        std::string param_value = parameters->GetSaveFileName( param_name );
+        if( param_value == "" )
+          param_value = ".";
+        QStringList dialog_filters;
+        std::string extensions = parameters->GetAcceptedFileExtensions( param_name );
+        if( extensions != "" )
+          dialog_filters << extensions.c_str( );
+        dialog_filters << "Any file (*)";
+
+        // Show dialog and check if it was accepted
+        QFileDialog dialog( this );
+        dialog.setFileMode( QFileDialog::AnyFile );
+        dialog.setDirectory( QFileDialog::tr( param_value.c_str( ) ) );
+        dialog.setNameFilters( dialog_filters );
+        dialog.setAcceptMode( QFileDialog::AcceptSave );
+        if( dialog.exec( ) )
+          line->setText( *( dialog.selectedFiles( ).begin( ) ) );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_OpenSinglePath( )
+{
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        std::string param_value = parameters->GetPathName( param_name );
+        if( param_value == "" )
+          param_value = ".";
+
+        // Show dialog and check if it was accepted
+        QFileDialog dialog( this );
+        dialog.setFileMode( QFileDialog::Directory );
+        dialog.setDirectory( QFileDialog::tr( param_value.c_str( ) ) );
+        dialog.setAcceptMode( QFileDialog::AcceptOpen );
+        if( dialog.exec( ) )
+          line->setText( *( dialog.selectedFiles( ).begin( ) ) );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_OpenMultipleFiles( )
+{
+  auto parameters = this->m_ProcessObject->GetParameters( );
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        QStringList dialog_filters;
+        std::string extensions = parameters->GetAcceptedFileExtensions( param_name );
+        if( extensions != "" )
+          dialog_filters << extensions.c_str( );
+        dialog_filters << "Any file (*)";
+
+        // Show dialog and check if it was accepted
+        QFileDialog dialog( this );
+        dialog.setFileMode( QFileDialog::ExistingFiles );
+        dialog.setNameFilters( dialog_filters );
+        dialog.setAcceptMode( QFileDialog::AcceptOpen );
+        if( dialog.exec( ) )
+        {
+          if( dialog.selectedFiles( ).size( ) > 0 )
+          {
+            std::stringstream str;
+            auto files = dialog.selectedFiles( );
+            auto fIt = files.begin( );
+            str << fIt->toStdString( );
+            ++fIt;
+            for( ; fIt != files.end( ); ++fIt )
+              str << "#" << fIt->toStdString( );
+            line->setText( str.str( ).c_str( ) );
+
+          } // fi
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_AddInt( )
+{
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        bool ok;
+        int value =
+          QInputDialog::getInt(
+            this,
+            (
+              std::string( "Add new value to \"" ) +
+              param_name +
+              std::string( "\"" )
+              ).c_str( ),
+            "Value:",
+            0,
+            -std::numeric_limits< int >::max( ),
+            std::numeric_limits< int >::max( ),
+            1, &ok
+            );
+        if( ok )
+        {
+          std::string values = line->text( ).toStdString( );
+          if( values != "" )
+            values += "#";
+          std::stringstream str;
+          str << values << value;
+          line->setText( str.str( ).c_str( ) );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_AddUint( )
+{
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        bool ok;
+        int value =
+          QInputDialog::getInt(
+            this,
+            (
+              std::string( "Add new value to \"" ) +
+              param_name +
+              std::string( "\"" )
+              ).c_str( ),
+            "Value:",
+            0, 0, std::numeric_limits< int >::max( ), 1,
+            &ok
+            );
+        if( ok )
+        {
+          std::string values = line->text( ).toStdString( );
+          if( values != "" )
+            values += "#";
+          std::stringstream str;
+          str << values << value;
+          line->setText( str.str( ).c_str( ) );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::ParametersDialog::
+_dlg_AddReal( )
+{
+  QPushButton* btn = dynamic_cast< QPushButton* >( this->sender( ) );
+  if( btn != NULL )
+  {
+    std::string bName = btn->objectName( ).toStdString( );
+    std::string line_name = bName.substr( 0, bName.find( "_=?btn" ) );
+    QLineEdit* line = this->findChild< QLineEdit* >( line_name.c_str( ) );
+    if( line != NULL )
+    {
+      std::string param_name = line->objectName( ).toStdString( );
+      if( param_name != "" )
+      {
+        bool ok;
+        double value =
+          QInputDialog::getDouble(
+            this,
+            (
+              std::string( "Add new value to \"" ) +
+              param_name +
+              std::string( "\"" )
+              ).c_str( ),
+            "Value:",
+            0,
+            -std::numeric_limits< double >::max( ),
+            std::numeric_limits< double >::max( ),
+            1, &ok
+            );
+        if( ok )
+        {
+          std::string values = line->text( ).toStdString( );
+          if( values != "" )
+            values += "#";
+          std::stringstream str;
+          str << values << value;
+          line->setText( str.str( ).c_str( ) );
+
+        } // fi
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/QT/ParametersDialog.h b/lib/cpPlugins/QT/ParametersDialog.h
new file mode 100644 (file)
index 0000000..37a6863
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __cpPlugins__QT__ParametersDialog__h__
+#define __cpPlugins__QT__ParametersDialog__h__
+
+#include <cpPlugins/Config.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+#include <QApplication>
+#include <QDialog>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QLabel>
+#include <QVBoxLayout>
+
+namespace cpPlugins
+{
+  namespace QT
+  {
+    /**
+     */
+    class cpPlugins_EXPORT ParametersDialog
+      : public QDialog
+    {
+      Q_OBJECT;
+
+    public:
+      ParametersDialog(
+        QWidget* parent = 0, Qt::WindowFlags f = 0, bool manual = false
+        );
+      virtual ~ParametersDialog( );
+
+      cpPlugins::Pipeline::ProcessObject* getProcessObject( ) const;
+      virtual bool setProcessObject(
+        cpPlugins::Pipeline::ProcessObject* obj
+        );
+
+      virtual void updateParameters( );
+      virtual void updateView( );
+
+    protected:
+      virtual void _addButtons( );
+      virtual void _updateWidgets( );
+
+    protected slots:
+      virtual void _dlg_Accepted( );
+      virtual void _dlg_OpenSingleFile( );
+      virtual void _dlg_SaveSingleFile( );
+      virtual void _dlg_OpenSinglePath( );
+      virtual void _dlg_OpenMultipleFiles( );
+      virtual void _dlg_AddInt( );
+      virtual void _dlg_AddUint( );
+      virtual void _dlg_AddReal( );
+
+    protected:
+      cpPlugins::Pipeline::ProcessObject* m_ProcessObject;
+      bool m_WidgetsUpdated;
+      bool m_Manual;
+      QLabel* m_Title;
+      QGridLayout* m_MainLayout;
+      QVBoxLayout* m_ToolsLayout;
+      QDialogButtonBox* m_Buttons;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__QT__ParametersDialog__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/QT/SaveFileDialog.cxx b/lib/cpPlugins/QT/SaveFileDialog.cxx
new file mode 100644 (file)
index 0000000..d42af95
--- /dev/null
@@ -0,0 +1,76 @@
+#include <cpPlugins/QT/SaveFileDialog.h>
+#include <cpPlugins/Pipeline/Parameters.h>
+
+// -------------------------------------------------------------------------
+cpPlugins::QT::SaveFileDialog::
+SaveFileDialog( QWidget* parent )
+  : QFileDialog( parent ),
+    m_Parameters( NULL ),
+    m_Name( "" )
+{
+  this->connect(
+    this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) )
+    );
+  this->setWindowTitle( "Save a file" );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::QT::SaveFileDialog::
+~SaveFileDialog( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::SaveFileDialog::
+SetParameters(
+  cpPlugins::Pipeline::Parameters* params, const std::string& name
+  )
+{
+  if( params == NULL )
+  {
+    this->m_Parameters = NULL;
+    this->m_Name = "";
+    return;
+
+  } // fi
+  auto param_type = params->GetType( name );
+  if( param_type != cpPlugins::Pipeline::Parameters::SaveFileName )
+  {
+    this->m_Parameters = NULL;
+    this->m_Name = "";
+    return;
+
+  } // fi
+  this->m_Parameters = params;
+  this->m_Name = name;
+
+  QStringList filters;
+  auto extensions = this->m_Parameters->GetAcceptedFileExtensions( name );
+  if( extensions != "" )
+    filters << extensions.c_str( );
+  filters << "Any file (*)";
+  this->setFileMode( QFileDialog::AnyFile );
+  this->setNameFilters( filters );
+  this->setAcceptMode( QFileDialog::AcceptOpen );
+  auto file = this->m_Parameters->GetSaveFileName( this->m_Name );
+  if( file == "" )
+    file = ".";
+  QFileInfo info( file.c_str( ) );
+  this->setDirectory( info.canonicalPath( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::QT::SaveFileDialog::
+_dlg_Accepted( )
+{
+  if( this->m_Parameters != NULL )
+  {
+    auto files = this->selectedFiles( );
+    this->m_Parameters->SetSaveFileName(
+      this->m_Name, files[ 0 ].toStdString( )
+      );
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/QT/SaveFileDialog.h b/lib/cpPlugins/QT/SaveFileDialog.h
new file mode 100644 (file)
index 0000000..f290ead
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __cpPlugins__QT__SaveFileDialog__h__
+#define __cpPlugins__QT__SaveFileDialog__h__
+
+#include <cpPlugins/Config.h>
+#include <QFileDialog>
+
+namespace cpPlugins{ namespace Pipeline { class Parameters; } }
+
+namespace cpPlugins
+{
+  namespace QT
+  {
+    /**
+     */
+    class SaveFileDialog
+      : public QFileDialog
+    {
+      Q_OBJECT;
+    public:
+      SaveFileDialog( QWidget* parent = 0 );
+      virtual ~SaveFileDialog( );
+
+      void SetParameters(
+        cpPlugins::Pipeline::Parameters* params, const std::string& name
+        );
+
+    protected slots:
+      void _dlg_Accepted( );
+
+    protected:
+      cpPlugins::Pipeline::Parameters* m_Parameters;
+      std::string m_Name;
+    };
+
+  } // ecapseman
+
+} // ecapseman
+
+#endif // __cpPlugins__QT__SaveFileDialog__h__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/tinyxml2/OLD_CMakeLists.txt.old b/lib/cpPlugins/tinyxml2/OLD_CMakeLists.txt.old
new file mode 100644 (file)
index 0000000..6579b71
--- /dev/null
@@ -0,0 +1,32 @@
+SET(lib_NAME cpPlugins_tinyxml2)\r
+SET(lib_DIR  third_party/tinyxml)\r
+\r
+IF(MSVC)\r
+  ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)\r
+ENDIF(MSVC)\r
+\r
+ADD_LIBRARY(${lib_NAME} SHARED tinyxml2.cpp tinyxml2.h)\r
+SET_TARGET_PROPERTIES(\r
+  ${lib_NAME} PROPERTIES\r
+  VERSION "${prj_VER}"\r
+  SOVERSION "${prj_sVER}"\r
+  )\r
+GENERATE_EXPORT_HEADER(\r
+  ${lib_NAME}\r
+  BASE_NAME ${lib_NAME}\r
+  EXPORT_MACRO_NAME ${lib_NAME}_EXPORT\r
+  EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/${lib_DIR}/${lib_NAME}_Export.h\r
+  STATIC_DEFINE ${lib_NAME}_BUILT_AS_STATIC\r
+  )\r
+INSTALL(\r
+  TARGETS ${lib_NAME}\r
+  RUNTIME DESTINATION bin\r
+  LIBRARY DESTINATION lib\r
+  ARCHIVE DESTINATION lib/static\r
+  )\r
+INSTALL(\r
+  FILES tinyxml2.h\r
+  DESTINATION include\r
+  )\r
+\r
+## eof - $RCSfile$\r
diff --git a/lib/cpPlugins/tinyxml2/readme.md b/lib/cpPlugins/tinyxml2/readme.md
new file mode 100644 (file)
index 0000000..30424c3
--- /dev/null
@@ -0,0 +1,324 @@
+TinyXML-2 [![TravisCI Status](https://travis-ci.org/leethomason/tinyxml2.svg?branch=master)](https://travis-ci.org/leethomason/tinyxml2) [![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/leethomason/tinyxml2?branch=master&svg=true)](https://ci.appveyor.com/project/leethomason/tinyxml2)
+=========
+![TinyXML-2 Logo](http://www.grinninglizard.com/tinyxml2/TinyXML2_small.png)
+
+TinyXML-2 is a simple, small, efficient, C++ XML parser that can be 
+easily integrated into other programs.
+
+The master is hosted on github:
+https://github.com/leethomason/tinyxml2
+
+The online HTML version of these docs:
+http://grinninglizard.com/tinyxml2docs/index.html
+
+Examples are in the "related pages" tab of the HTML docs.
+
+What it does.
+-------------
+       
+In brief, TinyXML-2 parses an XML document, and builds from that a 
+Document Object Model (DOM) that can be read, modified, and saved.
+
+XML stands for "eXtensible Markup Language." It is a general purpose
+human and machine readable markup language to describe arbitrary data.
+All those random file formats created to store application data can 
+all be replaced with XML. One parser for everything.
+
+http://en.wikipedia.org/wiki/XML
+
+There are different ways to access and interact with XML data.
+TinyXML-2 uses a Document Object Model (DOM), meaning the XML data is parsed
+into a C++ objects that can be browsed and manipulated, and then 
+written to disk or another output stream. You can also construct an XML document 
+from scratch with C++ objects and write this to disk or another output
+stream. You can even use TinyXML-2 to stream XML programmatically from
+code without creating a document first.
+
+TinyXML-2 is designed to be easy and fast to learn. It is one header and
+one cpp file. Simply add these to your project and off you go. 
+There is an example file - xmltest.cpp - to get you started. 
+
+TinyXML-2 is released under the ZLib license, 
+so you can use it in open source or commercial code. The details
+of the license are at the top of every source file.
+
+TinyXML-2 attempts to be a flexible parser, but with truly correct and
+compliant XML output. TinyXML-2 should compile on any reasonably C++
+compliant system. It does not rely on exceptions, RTTI, or the STL.
+
+What it doesn't do.
+-------------------
+
+TinyXML-2 doesn't parse or use DTDs (Document Type Definitions) or XSLs
+(eXtensible Stylesheet Language.) There are other parsers out there 
+that are much more fully featured. But they are also much bigger, 
+take longer to set up in your project, have a higher learning curve, 
+and often have a more restrictive license. If you are working with 
+browsers or have more complete XML needs, TinyXML-2 is not the parser for you.
+
+TinyXML-1 vs. TinyXML-2
+-----------------------
+
+TinyXML-2 is now the focus of all development, well tested, and your
+best choice unless you have a requirement to maintain TinyXML-1 code.
+
+TinyXML-2 uses a similar API to TinyXML-1 and the same
+rich test cases. But the implementation of the parser is completely re-written
+to make it more appropriate for use in a game. It uses less memory, is faster,
+and uses far fewer memory allocations.
+
+TinyXML-2 has no requirement for STL, but has also dropped all STL support. All
+strings are query and set as 'const char*'. This allows the use of internal 
+allocators, and keeps the code much simpler.
+
+Both parsers:
+
+1.  Simple to use with similar APIs.
+2.  DOM based parser.
+3.  UTF-8 Unicode support. http://en.wikipedia.org/wiki/UTF-8
+
+Advantages of TinyXML-2
+
+1.  The focus of all future dev.
+2.  Many fewer memory allocation (1/10th to 1/100th), uses less memory
+    (about 40% of TinyXML-1), and faster.
+3.  No STL requirement.
+4.  More modern C++, including a proper namespace.
+5.  Proper and useful handling of whitespace
+
+Advantages of TinyXML-1
+
+1.  Can report the location of parsing errors.
+2.  Support for some C++ STL conventions: streams and strings
+3.  Very mature and well debugged code base.
+
+Features
+--------
+
+### Memory Model
+
+An XMLDocument is a C++ object like any other, that can be on the stack, or
+new'd and deleted on the heap.
+
+However, any sub-node of the Document, XMLElement, XMLText, etc, can only
+be created by calling the appropriate XMLDocument::NewElement, NewText, etc.
+method. Although you have pointers to these objects, they are still owned
+by the Document. When the Document is deleted, so are all the nodes it contains.
+
+### White Space
+
+#### Whitespace Preservation (default)
+
+Microsoft has an excellent article on white space: http://msdn.microsoft.com/en-us/library/ms256097.aspx
+
+By default, TinyXML-2 preserves white space in a (hopefully) sane way that is almost complient with the
+spec. (TinyXML-1 used a completely different model, much more similar to 'collapse', below.)
+
+As a first step, all newlines / carriage-returns / line-feeds are normalized to a
+line-feed character, as required by the XML spec.
+
+White space in text is preserved. For example:
+
+       <element> Hello,  World</element>
+
+The leading space before the "Hello" and the double space after the comma are 
+preserved. Line-feeds are preserved, as in this example:
+
+       <element> Hello again,  
+                 World</element>
+
+However, white space between elements is **not** preserved. Although not strictly 
+compliant, tracking and reporting inter-element space is awkward, and not normally
+valuable. TinyXML-2 sees these as the same XML:
+
+       <document>
+               <data>1</data>
+               <data>2</data>
+               <data>3</data>
+       </document>
+
+       <document><data>1</data><data>2</data><data>3</data></document>
+
+#### Whitespace Collapse
+
+For some applications, it is preferable to collapse whitespace. Collapsing
+whitespace gives you "HTML-like" behavior, which is sometimes more suitable
+for hand typed documents. 
+
+TinyXML-2 supports this with the 'whitespace' parameter to the XMLDocument constructor.
+(The default is to preserve whitespace, as described above.)
+
+However, you may also use COLLAPSE_WHITESPACE, which will:
+
+* Remove leading and trailing whitespace
+* Convert newlines and line-feeds into a space character
+* Collapse a run of any number of space characters into a single space character
+
+Note that (currently) there is a performance impact for using COLLAPSE_WHITESPACE.
+It essentially causes the XML to be parsed twice.
+
+### Entities
+
+TinyXML-2 recognizes the pre-defined "character entities", meaning special
+characters. Namely:
+
+       &amp;   &
+       &lt;    <
+       &gt;    >
+       &quot;  "
+       &apos;  '
+
+These are recognized when the XML document is read, and translated to their
+UTF-8 equivalents. For instance, text with the XML of:
+
+       Far &amp; Away
+
+will have the Value() of "Far & Away" when queried from the XMLText object,
+and will be written back to the XML stream/file as an ampersand. 
+
+Additionally, any character can be specified by its Unicode code point:
+The syntax `&#xA0;` or `&#160;` are both to the non-breaking space character. 
+This is called a 'numeric character reference'. Any numeric character reference
+that isn't one of the special entities above, will be read, but written as a
+regular code point. The output is correct, but the entity syntax isn't preserved.
+
+### Printing
+
+#### Print to file
+You can directly use the convenience function:
+
+       XMLDocument doc;
+       ...
+       doc.SaveFile( "foo.xml" );
+
+Or the XMLPrinter class:
+
+       XMLPrinter printer( fp );
+       doc.Print( &printer );
+
+#### Print to memory
+Printing to memory is supported by the XMLPrinter.
+
+       XMLPrinter printer;
+       doc.Print( &printer );
+       // printer.CStr() has a const char* to the XML
+
+#### Print without an XMLDocument
+
+When loading, an XML parser is very useful. However, sometimes
+when saving, it just gets in the way. The code is often set up
+for streaming, and constructing the DOM is just overhead.
+
+The Printer supports the streaming case. The following code
+prints out a trivially simple XML file without ever creating
+an XML document.
+
+       XMLPrinter printer( fp );
+       printer.OpenElement( "foo" );
+       printer.PushAttribute( "foo", "bar" );
+       printer.CloseElement();
+
+Examples
+--------
+
+#### Load and parse an XML file.
+
+       /* ------ Example 1: Load and parse an XML file. ---- */        
+       {
+               XMLDocument doc;
+               doc.LoadFile( "dream.xml" );
+       }
+
+#### Lookup information.
+
+       /* ------ Example 2: Lookup information. ---- */        
+       {
+               XMLDocument doc;
+               doc.LoadFile( "dream.xml" );
+
+               // Structure of the XML file:
+               // - Element "PLAY"      the root Element, which is the 
+               //                       FirstChildElement of the Document
+               // - - Element "TITLE"   child of the root PLAY Element
+               // - - - Text            child of the TITLE Element
+               
+               // Navigate to the title, using the convenience function,
+               // with a dangerous lack of error checking.
+               const char* title = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->GetText();
+               printf( "Name of play (1): %s\n", title );
+               
+               // Text is just another Node to TinyXML-2. The more
+               // general way to get to the XMLText:
+               XMLText* textNode = doc.FirstChildElement( "PLAY" )->FirstChildElement( "TITLE" )->FirstChild()->ToText();
+               title = textNode->Value();
+               printf( "Name of play (2): %s\n", title );
+       }
+
+Using and Installing
+--------------------
+
+There are 2 files in TinyXML-2:
+* tinyxml2.cpp
+* tinyxml2.h
+
+And additionally a test file:
+* xmltest.cpp
+
+Simply compile and run. There is a visual studio 2010 project included, a simple Makefile, 
+an XCode project, a Code::Blocks project, and a cmake CMakeLists.txt included to help you. 
+The top of tinyxml.h even has a simple g++ command line if you are are *nix and don't want 
+to use a build system.
+
+Versioning
+----------
+
+TinyXML-2 uses semantic versioning. http://semver.org/ Releases are now tagged in github.
+
+Note that the major version will (probably) change fairly rapidly. API changes are fairly
+common.
+
+Documentation
+-------------
+
+The documentation is build with Doxygen, using the 'dox' 
+configuration file.
+
+License
+-------
+
+TinyXML-2 is released under the zlib license:
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must 
+not claim that you wrote the original software. If you use this 
+software in a product, an acknowledgment in the product documentation 
+would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and 
+must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source 
+distribution.
+
+Contributors
+------------
+
+Thanks very much to everyone who sends suggestions, bugs, ideas, and 
+encouragement. It all helps, and makes this project fun.
+
+The original TinyXML-1 has many contributors, who all deserve thanks
+in shaping what is a very successful library. Extra thanks to Yves
+Berquin and Andrew Ellerton who were key contributors.
+
+TinyXML-2 grew from that effort. Lee Thomason is the original author
+of TinyXML-2 (and TinyXML-1) but TinyXML-2 has been and is being improved
+by many contributors.
+
+Thanks to John Mackay at http://john.mackay.rosalilastudio.com for the TinyXML-2 logo!
+
+
diff --git a/lib/cpPlugins/tinyxml2/tinyxml2.cpp b/lib/cpPlugins/tinyxml2/tinyxml2.cpp
new file mode 100644 (file)
index 0000000..df49d0d
--- /dev/null
@@ -0,0 +1,2467 @@
+/*\r
+Original code by Lee Thomason (www.grinninglizard.com)\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty. In no event will the authors be held liable for any\r
+damages arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any\r
+purpose, including commercial applications, and to alter it and\r
+redistribute it freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; you must\r
+not claim that you wrote the original software. If you use this\r
+software in a product, an acknowledgment in the product documentation\r
+would be appreciated but is not required.\r
+\r
+2. Altered source versions must be plainly marked as such, and\r
+must not be misrepresented as being the original software.\r
+\r
+3. This notice may not be removed or altered from any source\r
+distribution.\r
+*/\r
+\r
+#include "tinyxml2.h"\r
+\r
+#include <new>         // yes, this one new style header, is in the Android SDK.\r
+#if defined(ANDROID_NDK) || defined(__QNXNTO__)\r
+#   include <stddef.h>\r
+#   include <stdarg.h>\r
+#else\r
+#   include <cstddef>\r
+#   include <cstdarg>\r
+#endif\r
+\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)\r
+       // Microsoft Visual Studio, version 2005 and higher. Not WinCE.\r
+       /*int _snprintf_s(\r
+          char *buffer,\r
+          size_t sizeOfBuffer,\r
+          size_t count,\r
+          const char *format [,\r
+                 argument] ...\r
+       );*/\r
+       static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )\r
+       {\r
+               va_list va;\r
+               va_start( va, format );\r
+               int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );\r
+               va_end( va );\r
+               return result;\r
+       }\r
+\r
+       static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va )\r
+       {\r
+               int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );\r
+               return result;\r
+       }\r
+\r
+       #define TIXML_VSCPRINTF _vscprintf\r
+       #define TIXML_SSCANF    sscanf_s\r
+#elif defined _MSC_VER\r
+       // Microsoft Visual Studio 2003 and earlier or WinCE\r
+       #define TIXML_SNPRINTF  _snprintf\r
+       #define TIXML_VSNPRINTF _vsnprintf\r
+       #define TIXML_SSCANF    sscanf\r
+       #if (_MSC_VER < 1400 ) && (!defined WINCE)\r
+               // Microsoft Visual Studio 2003 and not WinCE.\r
+               #define TIXML_VSCPRINTF   _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have.\r
+       #else\r
+               // Microsoft Visual Studio 2003 and earlier or WinCE.\r
+               static inline int TIXML_VSCPRINTF( const char* format, va_list va )\r
+               {\r
+                       int len = 512;\r
+                       for (;;) {\r
+                               len = len*2;\r
+                               char* str = new char[len]();\r
+                               const int required = _vsnprintf(str, len, format, va);\r
+                               delete[] str;\r
+                               if ( required != -1 ) {\r
+                                       TIXMLASSERT( required >= 0 );\r
+                                       len = required;\r
+                                       break;\r
+                               }\r
+                       }\r
+                       TIXMLASSERT( len >= 0 );\r
+                       return len;\r
+               }\r
+       #endif\r
+#else\r
+       // GCC version 3 and higher\r
+       //#warning( "Using sn* functions." )\r
+       #define TIXML_SNPRINTF  snprintf\r
+       #define TIXML_VSNPRINTF vsnprintf\r
+       static inline int TIXML_VSCPRINTF( const char* format, va_list va )\r
+       {\r
+               int len = vsnprintf( 0, 0, format, va );\r
+               TIXMLASSERT( len >= 0 );\r
+               return len;\r
+       }\r
+       #define TIXML_SSCANF   sscanf\r
+#endif\r
+\r
+\r
+static const char LINE_FEED                            = (char)0x0a;                   // all line endings are normalized to LF\r
+static const char LF = LINE_FEED;\r
+static const char CARRIAGE_RETURN              = (char)0x0d;                   // CR gets filtered out\r
+static const char CR = CARRIAGE_RETURN;\r
+static const char SINGLE_QUOTE                 = '\'';\r
+static const char DOUBLE_QUOTE                 = '\"';\r
+\r
+// Bunch of unicode info at:\r
+//             http://www.unicode.org/faq/utf_bom.html\r
+//     ef bb bf (Microsoft "lead bytes") - designates UTF-8\r
+\r
+static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;\r
+static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;\r
+static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;\r
+\r
+namespace tinyxml2\r
+{\r
+\r
+struct Entity {\r
+    const char* pattern;\r
+    int length;\r
+    char value;\r
+};\r
+\r
+static const int NUM_ENTITIES = 5;\r
+static const Entity entities[NUM_ENTITIES] = {\r
+    { "quot", 4,       DOUBLE_QUOTE },\r
+    { "amp", 3,                '&'  },\r
+    { "apos", 4,       SINGLE_QUOTE },\r
+    { "lt",    2,              '<'      },\r
+    { "gt",    2,              '>'      }\r
+};\r
+\r
+\r
+StrPair::~StrPair()\r
+{\r
+    Reset();\r
+}\r
+\r
+\r
+void StrPair::TransferTo( StrPair* other )\r
+{\r
+    if ( this == other ) {\r
+        return;\r
+    }\r
+    // This in effect implements the assignment operator by "moving"\r
+    // ownership (as in auto_ptr).\r
+\r
+    TIXMLASSERT( other->_flags == 0 );\r
+    TIXMLASSERT( other->_start == 0 );\r
+    TIXMLASSERT( other->_end == 0 );\r
+\r
+    other->Reset();\r
+\r
+    other->_flags = _flags;\r
+    other->_start = _start;\r
+    other->_end = _end;\r
+\r
+    _flags = 0;\r
+    _start = 0;\r
+    _end = 0;\r
+}\r
+\r
+void StrPair::Reset()\r
+{\r
+    if ( _flags & NEEDS_DELETE ) {\r
+        delete [] _start;\r
+    }\r
+    _flags = 0;\r
+    _start = 0;\r
+    _end = 0;\r
+}\r
+\r
+\r
+void StrPair::SetStr( const char* str, int flags )\r
+{\r
+    TIXMLASSERT( str );\r
+    Reset();\r
+    size_t len = strlen( str );\r
+    TIXMLASSERT( _start == 0 );\r
+    _start = new char[ len+1 ];\r
+    memcpy( _start, str, len+1 );\r
+    _end = _start + len;\r
+    _flags = flags | NEEDS_DELETE;\r
+}\r
+\r
+\r
+char* StrPair::ParseText( char* p, const char* endTag, int strFlags )\r
+{\r
+    TIXMLASSERT( endTag && *endTag );\r
+\r
+    char* start = p;\r
+    char  endChar = *endTag;\r
+    size_t length = strlen( endTag );\r
+\r
+    // Inner loop of text parsing.\r
+    while ( *p ) {\r
+        if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {\r
+            Set( start, p, strFlags );\r
+            return p + length;\r
+        }\r
+        ++p;\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+char* StrPair::ParseName( char* p )\r
+{\r
+    if ( !p || !(*p) ) {\r
+        return 0;\r
+    }\r
+    if ( !XMLUtil::IsNameStartChar( *p ) ) {\r
+        return 0;\r
+    }\r
+\r
+    char* const start = p;\r
+    ++p;\r
+    while ( *p && XMLUtil::IsNameChar( *p ) ) {\r
+        ++p;\r
+    }\r
+\r
+    Set( start, p, 0 );\r
+    return p;\r
+}\r
+\r
+\r
+void StrPair::CollapseWhitespace()\r
+{\r
+    // Adjusting _start would cause undefined behavior on delete[]\r
+    TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );\r
+    // Trim leading space.\r
+    _start = XMLUtil::SkipWhiteSpace( _start );\r
+\r
+    if ( *_start ) {\r
+        char* p = _start;      // the read pointer\r
+        char* q = _start;      // the write pointer\r
+\r
+        while( *p ) {\r
+            if ( XMLUtil::IsWhiteSpace( *p )) {\r
+                p = XMLUtil::SkipWhiteSpace( p );\r
+                if ( *p == 0 ) {\r
+                    break;    // don't write to q; this trims the trailing space.\r
+                }\r
+                *q = ' ';\r
+                ++q;\r
+            }\r
+            *q = *p;\r
+            ++q;\r
+            ++p;\r
+        }\r
+        *q = 0;\r
+    }\r
+}\r
+\r
+\r
+const char* StrPair::GetStr()\r
+{\r
+    TIXMLASSERT( _start );\r
+    TIXMLASSERT( _end );\r
+    if ( _flags & NEEDS_FLUSH ) {\r
+        *_end = 0;\r
+        _flags ^= NEEDS_FLUSH;\r
+\r
+        if ( _flags ) {\r
+            char* p = _start;  // the read pointer\r
+            char* q = _start;  // the write pointer\r
+\r
+            while( p < _end ) {\r
+                if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {\r
+                    // CR-LF pair becomes LF\r
+                    // CR alone becomes LF\r
+                    // LF-CR becomes LF\r
+                    if ( *(p+1) == LF ) {\r
+                        p += 2;\r
+                    }\r
+                    else {\r
+                        ++p;\r
+                    }\r
+                    *q++ = LF;\r
+                }\r
+                else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {\r
+                    if ( *(p+1) == CR ) {\r
+                        p += 2;\r
+                    }\r
+                    else {\r
+                        ++p;\r
+                    }\r
+                    *q++ = LF;\r
+                }\r
+                else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {\r
+                    // Entities handled by tinyXML2:\r
+                    // - special entities in the entity table [in/out]\r
+                    // - numeric character reference [in]\r
+                    //   &#20013; or &#x4e2d;\r
+\r
+                    if ( *(p+1) == '#' ) {\r
+                        const int buflen = 10;\r
+                        char buf[buflen] = { 0 };\r
+                        int len = 0;\r
+                        char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );\r
+                        if ( adjusted == 0 ) {\r
+                            *q = *p;\r
+                            ++p;\r
+                            ++q;\r
+                        }\r
+                        else {\r
+                            TIXMLASSERT( 0 <= len && len <= buflen );\r
+                            TIXMLASSERT( q + len <= adjusted );\r
+                            p = adjusted;\r
+                            memcpy( q, buf, len );\r
+                            q += len;\r
+                        }\r
+                    }\r
+                    else {\r
+                        bool entityFound = false;\r
+                        for( int i = 0; i < NUM_ENTITIES; ++i ) {\r
+                            const Entity& entity = entities[i];\r
+                            if ( strncmp( p + 1, entity.pattern, entity.length ) == 0\r
+                                    && *( p + entity.length + 1 ) == ';' ) {\r
+                                // Found an entity - convert.\r
+                                *q = entity.value;\r
+                                ++q;\r
+                                p += entity.length + 2;\r
+                                entityFound = true;\r
+                                break;\r
+                            }\r
+                        }\r
+                        if ( !entityFound ) {\r
+                            // fixme: treat as error?\r
+                            ++p;\r
+                            ++q;\r
+                        }\r
+                    }\r
+                }\r
+                else {\r
+                    *q = *p;\r
+                    ++p;\r
+                    ++q;\r
+                }\r
+            }\r
+            *q = 0;\r
+        }\r
+        // The loop below has plenty going on, and this\r
+        // is a less useful mode. Break it out.\r
+        if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {\r
+            CollapseWhitespace();\r
+        }\r
+        _flags = (_flags & NEEDS_DELETE);\r
+    }\r
+    TIXMLASSERT( _start );\r
+    return _start;\r
+}\r
+\r
+\r
+\r
+\r
+// --------- XMLUtil ----------- //\r
+\r
+const char* XMLUtil::ReadBOM( const char* p, bool* bom )\r
+{\r
+    TIXMLASSERT( p );\r
+    TIXMLASSERT( bom );\r
+    *bom = false;\r
+    const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);\r
+    // Check for BOM:\r
+    if (    *(pu+0) == TIXML_UTF_LEAD_0\r
+            && *(pu+1) == TIXML_UTF_LEAD_1\r
+            && *(pu+2) == TIXML_UTF_LEAD_2 ) {\r
+        *bom = true;\r
+        p += 3;\r
+    }\r
+    TIXMLASSERT( p );\r
+    return p;\r
+}\r
+\r
+\r
+void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )\r
+{\r
+    const unsigned long BYTE_MASK = 0xBF;\r
+    const unsigned long BYTE_MARK = 0x80;\r
+    const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };\r
+\r
+    if (input < 0x80) {\r
+        *length = 1;\r
+    }\r
+    else if ( input < 0x800 ) {\r
+        *length = 2;\r
+    }\r
+    else if ( input < 0x10000 ) {\r
+        *length = 3;\r
+    }\r
+    else if ( input < 0x200000 ) {\r
+        *length = 4;\r
+    }\r
+    else {\r
+        *length = 0;    // This code won't convert this correctly anyway.\r
+        return;\r
+    }\r
+\r
+    output += *length;\r
+\r
+    // Scary scary fall throughs.\r
+    switch (*length) {\r
+        case 4:\r
+            --output;\r
+            *output = (char)((input | BYTE_MARK) & BYTE_MASK);\r
+            input >>= 6;\r
+        case 3:\r
+            --output;\r
+            *output = (char)((input | BYTE_MARK) & BYTE_MASK);\r
+            input >>= 6;\r
+        case 2:\r
+            --output;\r
+            *output = (char)((input | BYTE_MARK) & BYTE_MASK);\r
+            input >>= 6;\r
+        case 1:\r
+            --output;\r
+            *output = (char)(input | FIRST_BYTE_MARK[*length]);\r
+            break;\r
+        default:\r
+            TIXMLASSERT( false );\r
+    }\r
+}\r
+\r
+\r
+const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )\r
+{\r
+    // Presume an entity, and pull it out.\r
+    *length = 0;\r
+\r
+    if ( *(p+1) == '#' && *(p+2) ) {\r
+        unsigned long ucs = 0;\r
+        TIXMLASSERT( sizeof( ucs ) >= 4 );\r
+        ptrdiff_t delta = 0;\r
+        unsigned mult = 1;\r
+        static const char SEMICOLON = ';';\r
+\r
+        if ( *(p+2) == 'x' ) {\r
+            // Hexadecimal.\r
+            const char* q = p+3;\r
+            if ( !(*q) ) {\r
+                return 0;\r
+            }\r
+\r
+            q = strchr( q, SEMICOLON );\r
+\r
+            if ( !q ) {\r
+                return 0;\r
+            }\r
+            TIXMLASSERT( *q == SEMICOLON );\r
+\r
+            delta = q-p;\r
+            --q;\r
+\r
+            while ( *q != 'x' ) {\r
+                unsigned int digit = 0;\r
+\r
+                if ( *q >= '0' && *q <= '9' ) {\r
+                    digit = *q - '0';\r
+                }\r
+                else if ( *q >= 'a' && *q <= 'f' ) {\r
+                    digit = *q - 'a' + 10;\r
+                }\r
+                else if ( *q >= 'A' && *q <= 'F' ) {\r
+                    digit = *q - 'A' + 10;\r
+                }\r
+                else {\r
+                    return 0;\r
+                }\r
+                TIXMLASSERT( digit >= 0 && digit < 16);\r
+                TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );\r
+                const unsigned int digitScaled = mult * digit;\r
+                TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );\r
+                ucs += digitScaled;\r
+                TIXMLASSERT( mult <= UINT_MAX / 16 );\r
+                mult *= 16;\r
+                --q;\r
+            }\r
+        }\r
+        else {\r
+            // Decimal.\r
+            const char* q = p+2;\r
+            if ( !(*q) ) {\r
+                return 0;\r
+            }\r
+\r
+            q = strchr( q, SEMICOLON );\r
+\r
+            if ( !q ) {\r
+                return 0;\r
+            }\r
+            TIXMLASSERT( *q == SEMICOLON );\r
+\r
+            delta = q-p;\r
+            --q;\r
+\r
+            while ( *q != '#' ) {\r
+                if ( *q >= '0' && *q <= '9' ) {\r
+                    const unsigned int digit = *q - '0';\r
+                    TIXMLASSERT( digit >= 0 && digit < 10);\r
+                    TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );\r
+                    const unsigned int digitScaled = mult * digit;\r
+                    TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );\r
+                    ucs += digitScaled;\r
+                }\r
+                else {\r
+                    return 0;\r
+                }\r
+                TIXMLASSERT( mult <= UINT_MAX / 10 );\r
+                mult *= 10;\r
+                --q;\r
+            }\r
+        }\r
+        // convert the UCS to UTF-8\r
+        ConvertUTF32ToUTF8( ucs, value, length );\r
+        return p + delta + 1;\r
+    }\r
+    return p+1;\r
+}\r
+\r
+\r
+void XMLUtil::ToStr( int v, char* buffer, int bufferSize )\r
+{\r
+    TIXML_SNPRINTF( buffer, bufferSize, "%d", v );\r
+}\r
+\r
+\r
+void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )\r
+{\r
+    TIXML_SNPRINTF( buffer, bufferSize, "%u", v );\r
+}\r
+\r
+\r
+void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )\r
+{\r
+    TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );\r
+}\r
+\r
+/*\r
+       ToStr() of a number is a very tricky topic.\r
+       https://github.com/leethomason/tinyxml2/issues/106\r
+*/\r
+void XMLUtil::ToStr( float v, char* buffer, int bufferSize )\r
+{\r
+    TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v );\r
+}\r
+\r
+\r
+void XMLUtil::ToStr( double v, char* buffer, int bufferSize )\r
+{\r
+    TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v );\r
+}\r
+\r
+\r
+bool XMLUtil::ToInt( const char* str, int* value )\r
+{\r
+    if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+bool XMLUtil::ToUnsigned( const char* str, unsigned *value )\r
+{\r
+    if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+bool XMLUtil::ToBool( const char* str, bool* value )\r
+{\r
+    int ival = 0;\r
+    if ( ToInt( str, &ival )) {\r
+        *value = (ival==0) ? false : true;\r
+        return true;\r
+    }\r
+    if ( StringEqual( str, "true" ) ) {\r
+        *value = true;\r
+        return true;\r
+    }\r
+    else if ( StringEqual( str, "false" ) ) {\r
+        *value = false;\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+\r
+bool XMLUtil::ToFloat( const char* str, float* value )\r
+{\r
+    if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+bool XMLUtil::ToDouble( const char* str, double* value )\r
+{\r
+    if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+\r
+char* XMLDocument::Identify( char* p, XMLNode** node )\r
+{\r
+    TIXMLASSERT( node );\r
+    TIXMLASSERT( p );\r
+    char* const start = p;\r
+    p = XMLUtil::SkipWhiteSpace( p );\r
+    if( !*p ) {\r
+        *node = 0;\r
+        TIXMLASSERT( p );\r
+        return p;\r
+    }\r
+\r
+    // These strings define the matching patterns:\r
+    static const char* xmlHeader               = { "<?" };\r
+    static const char* commentHeader   = { "<!--" };\r
+    static const char* cdataHeader             = { "<![CDATA[" };\r
+    static const char* dtdHeader               = { "<!" };\r
+    static const char* elementHeader   = { "<" };      // and a header for everything else; check last.\r
+\r
+    static const int xmlHeaderLen              = 2;\r
+    static const int commentHeaderLen  = 4;\r
+    static const int cdataHeaderLen            = 9;\r
+    static const int dtdHeaderLen              = 2;\r
+    static const int elementHeaderLen  = 1;\r
+\r
+    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) );               // use same memory pool\r
+    TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) );   // use same memory pool\r
+    XMLNode* returnNode = 0;\r
+    if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {\r
+        TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );\r
+        returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );\r
+        returnNode->_memPool = &_commentPool;\r
+        p += xmlHeaderLen;\r
+    }\r
+    else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {\r
+        TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() );\r
+        returnNode = new (_commentPool.Alloc()) XMLComment( this );\r
+        returnNode->_memPool = &_commentPool;\r
+        p += commentHeaderLen;\r
+    }\r
+    else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {\r
+        TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );\r
+        XMLText* text = new (_textPool.Alloc()) XMLText( this );\r
+        returnNode = text;\r
+        returnNode->_memPool = &_textPool;\r
+        p += cdataHeaderLen;\r
+        text->SetCData( true );\r
+    }\r
+    else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {\r
+        TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() );\r
+        returnNode = new (_commentPool.Alloc()) XMLUnknown( this );\r
+        returnNode->_memPool = &_commentPool;\r
+        p += dtdHeaderLen;\r
+    }\r
+    else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {\r
+        TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() );\r
+        returnNode = new (_elementPool.Alloc()) XMLElement( this );\r
+        returnNode->_memPool = &_elementPool;\r
+        p += elementHeaderLen;\r
+    }\r
+    else {\r
+        TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );\r
+        returnNode = new (_textPool.Alloc()) XMLText( this );\r
+        returnNode->_memPool = &_textPool;\r
+        p = start;     // Back it up, all the text counts.\r
+    }\r
+\r
+    TIXMLASSERT( returnNode );\r
+    TIXMLASSERT( p );\r
+    *node = returnNode;\r
+    return p;\r
+}\r
+\r
+\r
+bool XMLDocument::Accept( XMLVisitor* visitor ) const\r
+{\r
+    TIXMLASSERT( visitor );\r
+    if ( visitor->VisitEnter( *this ) ) {\r
+        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {\r
+            if ( !node->Accept( visitor ) ) {\r
+                break;\r
+            }\r
+        }\r
+    }\r
+    return visitor->VisitExit( *this );\r
+}\r
+\r
+\r
+// --------- XMLNode ----------- //\r
+\r
+XMLNode::XMLNode( XMLDocument* doc ) :\r
+    _document( doc ),\r
+    _parent( 0 ),\r
+    _firstChild( 0 ), _lastChild( 0 ),\r
+    _prev( 0 ), _next( 0 ),\r
+    _memPool( 0 )\r
+{\r
+}\r
+\r
+\r
+XMLNode::~XMLNode()\r
+{\r
+    DeleteChildren();\r
+    if ( _parent ) {\r
+        _parent->Unlink( this );\r
+    }\r
+}\r
+\r
+const char* XMLNode::Value() const \r
+{\r
+    // Catch an edge case: XMLDocuments don't have a a Value. Carefully return nullptr.\r
+    if ( this->ToDocument() )\r
+        return 0;\r
+    return _value.GetStr();\r
+}\r
+\r
+void XMLNode::SetValue( const char* str, bool staticMem )\r
+{\r
+    if ( staticMem ) {\r
+        _value.SetInternedStr( str );\r
+    }\r
+    else {\r
+        _value.SetStr( str );\r
+    }\r
+}\r
+\r
+\r
+void XMLNode::DeleteChildren()\r
+{\r
+    while( _firstChild ) {\r
+        TIXMLASSERT( _lastChild );\r
+        TIXMLASSERT( _firstChild->_document == _document );\r
+        XMLNode* node = _firstChild;\r
+        Unlink( node );\r
+\r
+        DeleteNode( node );\r
+    }\r
+    _firstChild = _lastChild = 0;\r
+}\r
+\r
+\r
+void XMLNode::Unlink( XMLNode* child )\r
+{\r
+    TIXMLASSERT( child );\r
+    TIXMLASSERT( child->_document == _document );\r
+    TIXMLASSERT( child->_parent == this );\r
+    if ( child == _firstChild ) {\r
+        _firstChild = _firstChild->_next;\r
+    }\r
+    if ( child == _lastChild ) {\r
+        _lastChild = _lastChild->_prev;\r
+    }\r
+\r
+    if ( child->_prev ) {\r
+        child->_prev->_next = child->_next;\r
+    }\r
+    if ( child->_next ) {\r
+        child->_next->_prev = child->_prev;\r
+    }\r
+       child->_parent = 0;\r
+}\r
+\r
+\r
+void XMLNode::DeleteChild( XMLNode* node )\r
+{\r
+    TIXMLASSERT( node );\r
+    TIXMLASSERT( node->_document == _document );\r
+    TIXMLASSERT( node->_parent == this );\r
+    Unlink( node );\r
+    DeleteNode( node );\r
+}\r
+\r
+\r
+XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )\r
+{\r
+    TIXMLASSERT( addThis );\r
+    if ( addThis->_document != _document ) {\r
+        TIXMLASSERT( false );\r
+        return 0;\r
+    }\r
+    InsertChildPreamble( addThis );\r
+\r
+    if ( _lastChild ) {\r
+        TIXMLASSERT( _firstChild );\r
+        TIXMLASSERT( _lastChild->_next == 0 );\r
+        _lastChild->_next = addThis;\r
+        addThis->_prev = _lastChild;\r
+        _lastChild = addThis;\r
+\r
+        addThis->_next = 0;\r
+    }\r
+    else {\r
+        TIXMLASSERT( _firstChild == 0 );\r
+        _firstChild = _lastChild = addThis;\r
+\r
+        addThis->_prev = 0;\r
+        addThis->_next = 0;\r
+    }\r
+    addThis->_parent = this;\r
+    return addThis;\r
+}\r
+\r
+\r
+XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )\r
+{\r
+    TIXMLASSERT( addThis );\r
+    if ( addThis->_document != _document ) {\r
+        TIXMLASSERT( false );\r
+        return 0;\r
+    }\r
+    InsertChildPreamble( addThis );\r
+\r
+    if ( _firstChild ) {\r
+        TIXMLASSERT( _lastChild );\r
+        TIXMLASSERT( _firstChild->_prev == 0 );\r
+\r
+        _firstChild->_prev = addThis;\r
+        addThis->_next = _firstChild;\r
+        _firstChild = addThis;\r
+\r
+        addThis->_prev = 0;\r
+    }\r
+    else {\r
+        TIXMLASSERT( _lastChild == 0 );\r
+        _firstChild = _lastChild = addThis;\r
+\r
+        addThis->_prev = 0;\r
+        addThis->_next = 0;\r
+    }\r
+    addThis->_parent = this;\r
+    return addThis;\r
+}\r
+\r
+\r
+XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )\r
+{\r
+    TIXMLASSERT( addThis );\r
+    if ( addThis->_document != _document ) {\r
+        TIXMLASSERT( false );\r
+        return 0;\r
+    }\r
+\r
+    TIXMLASSERT( afterThis );\r
+\r
+    if ( afterThis->_parent != this ) {\r
+        TIXMLASSERT( false );\r
+        return 0;\r
+    }\r
+\r
+    if ( afterThis->_next == 0 ) {\r
+        // The last node or the only node.\r
+        return InsertEndChild( addThis );\r
+    }\r
+    InsertChildPreamble( addThis );\r
+    addThis->_prev = afterThis;\r
+    addThis->_next = afterThis->_next;\r
+    afterThis->_next->_prev = addThis;\r
+    afterThis->_next = addThis;\r
+    addThis->_parent = this;\r
+    return addThis;\r
+}\r
+\r
+\r
+\r
+\r
+const XMLElement* XMLNode::FirstChildElement( const char* name ) const\r
+{\r
+    for( const XMLNode* node = _firstChild; node; node = node->_next ) {\r
+        const XMLElement* element = node->ToElement();\r
+        if ( element ) {\r
+            if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {\r
+                return element;\r
+            }\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+const XMLElement* XMLNode::LastChildElement( const char* name ) const\r
+{\r
+    for( const XMLNode* node = _lastChild; node; node = node->_prev ) {\r
+        const XMLElement* element = node->ToElement();\r
+        if ( element ) {\r
+            if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {\r
+                return element;\r
+            }\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+const XMLElement* XMLNode::NextSiblingElement( const char* name ) const\r
+{\r
+    for( const XMLNode* node = _next; node; node = node->_next ) {\r
+        const XMLElement* element = node->ToElement();\r
+        if ( element\r
+                && (!name || XMLUtil::StringEqual( name, element->Name() ))) {\r
+            return element;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const\r
+{\r
+    for( const XMLNode* node = _prev; node; node = node->_prev ) {\r
+        const XMLElement* element = node->ToElement();\r
+        if ( element\r
+                && (!name || XMLUtil::StringEqual( name, element->Name() ))) {\r
+            return element;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )\r
+{\r
+    // This is a recursive method, but thinking about it "at the current level"\r
+    // it is a pretty simple flat list:\r
+    //         <foo/>\r
+    //         <!-- comment -->\r
+    //\r
+    // With a special case:\r
+    //         <foo>\r
+    //         </foo>\r
+    //         <!-- comment -->\r
+    //\r
+    // Where the closing element (/foo) *must* be the next thing after the opening\r
+    // element, and the names must match. BUT the tricky bit is that the closing\r
+    // element will be read by the child.\r
+    //\r
+    // 'endTag' is the end tag for this node, it is returned by a call to a child.\r
+    // 'parentEnd' is the end tag for the parent, which is filled in and returned.\r
+\r
+    while( p && *p ) {\r
+        XMLNode* node = 0;\r
+\r
+        p = _document->Identify( p, &node );\r
+        if ( node == 0 ) {\r
+            break;\r
+        }\r
+\r
+        StrPair endTag;\r
+        p = node->ParseDeep( p, &endTag );\r
+        if ( !p ) {\r
+            DeleteNode( node );\r
+            if ( !_document->Error() ) {\r
+                _document->SetError( XML_ERROR_PARSING, 0, 0 );\r
+            }\r
+            break;\r
+        }\r
+\r
+        XMLDeclaration* decl = node->ToDeclaration();\r
+        if ( decl ) {\r
+                // A declaration can only be the first child of a document.\r
+                // Set error, if document already has children.\r
+                if ( !_document->NoChildren() ) {\r
+                        _document->SetError( XML_ERROR_PARSING_DECLARATION, decl->Value(), 0);\r
+                        DeleteNode( decl );\r
+                        break;\r
+                }\r
+        }\r
+\r
+        XMLElement* ele = node->ToElement();\r
+        if ( ele ) {\r
+            // We read the end tag. Return it to the parent.\r
+            if ( ele->ClosingType() == XMLElement::CLOSING ) {\r
+                if ( parentEnd ) {\r
+                    ele->_value.TransferTo( parentEnd );\r
+                }\r
+                node->_memPool->SetTracked();   // created and then immediately deleted.\r
+                DeleteNode( node );\r
+                return p;\r
+            }\r
+\r
+            // Handle an end tag returned to this level.\r
+            // And handle a bunch of annoying errors.\r
+            bool mismatch = false;\r
+            if ( endTag.Empty() ) {\r
+                if ( ele->ClosingType() == XMLElement::OPEN ) {\r
+                    mismatch = true;\r
+                }\r
+            }\r
+            else {\r
+                if ( ele->ClosingType() != XMLElement::OPEN ) {\r
+                    mismatch = true;\r
+                }\r
+                else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {\r
+                    mismatch = true;\r
+                }\r
+            }\r
+            if ( mismatch ) {\r
+                _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, ele->Name(), 0 );\r
+                DeleteNode( node );\r
+                break;\r
+            }\r
+        }\r
+        InsertEndChild( node );\r
+    }\r
+    return 0;\r
+}\r
+\r
+void XMLNode::DeleteNode( XMLNode* node )\r
+{\r
+    if ( node == 0 ) {\r
+        return;\r
+    }\r
+    MemPool* pool = node->_memPool;\r
+    node->~XMLNode();\r
+    pool->Free( node );\r
+}\r
+\r
+void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const\r
+{\r
+    TIXMLASSERT( insertThis );\r
+    TIXMLASSERT( insertThis->_document == _document );\r
+\r
+    if ( insertThis->_parent )\r
+        insertThis->_parent->Unlink( insertThis );\r
+    else\r
+        insertThis->_memPool->SetTracked();\r
+}\r
+\r
+// --------- XMLText ---------- //\r
+char* XMLText::ParseDeep( char* p, StrPair* )\r
+{\r
+    const char* start = p;\r
+    if ( this->CData() ) {\r
+        p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION );\r
+        if ( !p ) {\r
+            _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 );\r
+        }\r
+        return p;\r
+    }\r
+    else {\r
+        int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES;\r
+        if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) {\r
+            flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING;\r
+        }\r
+\r
+        p = _value.ParseText( p, "<", flags );\r
+        if ( p && *p ) {\r
+            return p-1;\r
+        }\r
+        if ( !p ) {\r
+            _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 );\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const\r
+{\r
+    if ( !doc ) {\r
+        doc = _document;\r
+    }\r
+    XMLText* text = doc->NewText( Value() );   // fixme: this will always allocate memory. Intern?\r
+    text->SetCData( this->CData() );\r
+    return text;\r
+}\r
+\r
+\r
+bool XMLText::ShallowEqual( const XMLNode* compare ) const\r
+{\r
+    const XMLText* text = compare->ToText();\r
+    return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );\r
+}\r
+\r
+\r
+bool XMLText::Accept( XMLVisitor* visitor ) const\r
+{\r
+    TIXMLASSERT( visitor );\r
+    return visitor->Visit( *this );\r
+}\r
+\r
+\r
+// --------- XMLComment ---------- //\r
+\r
+XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )\r
+{\r
+}\r
+\r
+\r
+XMLComment::~XMLComment()\r
+{\r
+}\r
+\r
+\r
+char* XMLComment::ParseDeep( char* p, StrPair* )\r
+{\r
+    // Comment parses as text.\r
+    const char* start = p;\r
+    p = _value.ParseText( p, "-->", StrPair::COMMENT );\r
+    if ( p == 0 ) {\r
+        _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 );\r
+    }\r
+    return p;\r
+}\r
+\r
+\r
+XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const\r
+{\r
+    if ( !doc ) {\r
+        doc = _document;\r
+    }\r
+    XMLComment* comment = doc->NewComment( Value() );  // fixme: this will always allocate memory. Intern?\r
+    return comment;\r
+}\r
+\r
+\r
+bool XMLComment::ShallowEqual( const XMLNode* compare ) const\r
+{\r
+    TIXMLASSERT( compare );\r
+    const XMLComment* comment = compare->ToComment();\r
+    return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));\r
+}\r
+\r
+\r
+bool XMLComment::Accept( XMLVisitor* visitor ) const\r
+{\r
+    TIXMLASSERT( visitor );\r
+    return visitor->Visit( *this );\r
+}\r
+\r
+\r
+// --------- XMLDeclaration ---------- //\r
+\r
+XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )\r
+{\r
+}\r
+\r
+\r
+XMLDeclaration::~XMLDeclaration()\r
+{\r
+    //printf( "~XMLDeclaration\n" );\r
+}\r
+\r
+\r
+char* XMLDeclaration::ParseDeep( char* p, StrPair* )\r
+{\r
+    // Declaration parses as text.\r
+    const char* start = p;\r
+    p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION );\r
+    if ( p == 0 ) {\r
+        _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 );\r
+    }\r
+    return p;\r
+}\r
+\r
+\r
+XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const\r
+{\r
+    if ( !doc ) {\r
+        doc = _document;\r
+    }\r
+    XMLDeclaration* dec = doc->NewDeclaration( Value() );      // fixme: this will always allocate memory. Intern?\r
+    return dec;\r
+}\r
+\r
+\r
+bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const\r
+{\r
+    TIXMLASSERT( compare );\r
+    const XMLDeclaration* declaration = compare->ToDeclaration();\r
+    return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));\r
+}\r
+\r
+\r
+\r
+bool XMLDeclaration::Accept( XMLVisitor* visitor ) const\r
+{\r
+    TIXMLASSERT( visitor );\r
+    return visitor->Visit( *this );\r
+}\r
+\r
+// --------- XMLUnknown ---------- //\r
+\r
+XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )\r
+{\r
+}\r
+\r
+\r
+XMLUnknown::~XMLUnknown()\r
+{\r
+}\r
+\r
+\r
+char* XMLUnknown::ParseDeep( char* p, StrPair* )\r
+{\r
+    // Unknown parses as text.\r
+    const char* start = p;\r
+\r
+    p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION );\r
+    if ( !p ) {\r
+        _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 );\r
+    }\r
+    return p;\r
+}\r
+\r
+\r
+XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const\r
+{\r
+    if ( !doc ) {\r
+        doc = _document;\r
+    }\r
+    XMLUnknown* text = doc->NewUnknown( Value() );     // fixme: this will always allocate memory. Intern?\r
+    return text;\r
+}\r
+\r
+\r
+bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const\r
+{\r
+    TIXMLASSERT( compare );\r
+    const XMLUnknown* unknown = compare->ToUnknown();\r
+    return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));\r
+}\r
+\r
+\r
+bool XMLUnknown::Accept( XMLVisitor* visitor ) const\r
+{\r
+    TIXMLASSERT( visitor );\r
+    return visitor->Visit( *this );\r
+}\r
+\r
+// --------- XMLAttribute ---------- //\r
+\r
+const char* XMLAttribute::Name() const \r
+{\r
+    return _name.GetStr();\r
+}\r
+\r
+const char* XMLAttribute::Value() const \r
+{\r
+    return _value.GetStr();\r
+}\r
+\r
+char* XMLAttribute::ParseDeep( char* p, bool processEntities )\r
+{\r
+    // Parse using the name rules: bug fix, was using ParseText before\r
+    p = _name.ParseName( p );\r
+    if ( !p || !*p ) {\r
+        return 0;\r
+    }\r
+\r
+    // Skip white space before =\r
+    p = XMLUtil::SkipWhiteSpace( p );\r
+    if ( *p != '=' ) {\r
+        return 0;\r
+    }\r
+\r
+    ++p;       // move up to opening quote\r
+    p = XMLUtil::SkipWhiteSpace( p );\r
+    if ( *p != '\"' && *p != '\'' ) {\r
+        return 0;\r
+    }\r
+\r
+    char endTag[2] = { *p, 0 };\r
+    ++p;       // move past opening quote\r
+\r
+    p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES );\r
+    return p;\r
+}\r
+\r
+\r
+void XMLAttribute::SetName( const char* n )\r
+{\r
+    _name.SetStr( n );\r
+}\r
+\r
+\r
+XMLError XMLAttribute::QueryIntValue( int* value ) const\r
+{\r
+    if ( XMLUtil::ToInt( Value(), value )) {\r
+        return XML_NO_ERROR;\r
+    }\r
+    return XML_WRONG_ATTRIBUTE_TYPE;\r
+}\r
+\r
+\r
+XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const\r
+{\r
+    if ( XMLUtil::ToUnsigned( Value(), value )) {\r
+        return XML_NO_ERROR;\r
+    }\r
+    return XML_WRONG_ATTRIBUTE_TYPE;\r
+}\r
+\r
+\r
+XMLError XMLAttribute::QueryBoolValue( bool* value ) const\r
+{\r
+    if ( XMLUtil::ToBool( Value(), value )) {\r
+        return XML_NO_ERROR;\r
+    }\r
+    return XML_WRONG_ATTRIBUTE_TYPE;\r
+}\r
+\r
+\r
+XMLError XMLAttribute::QueryFloatValue( float* value ) const\r
+{\r
+    if ( XMLUtil::ToFloat( Value(), value )) {\r
+        return XML_NO_ERROR;\r
+    }\r
+    return XML_WRONG_ATTRIBUTE_TYPE;\r
+}\r
+\r
+\r
+XMLError XMLAttribute::QueryDoubleValue( double* value ) const\r
+{\r
+    if ( XMLUtil::ToDouble( Value(), value )) {\r
+        return XML_NO_ERROR;\r
+    }\r
+    return XML_WRONG_ATTRIBUTE_TYPE;\r
+}\r
+\r
+\r
+void XMLAttribute::SetAttribute( const char* v )\r
+{\r
+    _value.SetStr( v );\r
+}\r
+\r
+\r
+void XMLAttribute::SetAttribute( int v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    _value.SetStr( buf );\r
+}\r
+\r
+\r
+void XMLAttribute::SetAttribute( unsigned v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    _value.SetStr( buf );\r
+}\r
+\r
+\r
+void XMLAttribute::SetAttribute( bool v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    _value.SetStr( buf );\r
+}\r
+\r
+void XMLAttribute::SetAttribute( double v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    _value.SetStr( buf );\r
+}\r
+\r
+void XMLAttribute::SetAttribute( float v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    _value.SetStr( buf );\r
+}\r
+\r
+\r
+// --------- XMLElement ---------- //\r
+XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),\r
+    _closingType( 0 ),\r
+    _rootAttribute( 0 )\r
+{\r
+}\r
+\r
+\r
+XMLElement::~XMLElement()\r
+{\r
+    while( _rootAttribute ) {\r
+        XMLAttribute* next = _rootAttribute->_next;\r
+        DeleteAttribute( _rootAttribute );\r
+        _rootAttribute = next;\r
+    }\r
+}\r
+\r
+\r
+const XMLAttribute* XMLElement::FindAttribute( const char* name ) const\r
+{\r
+    for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {\r
+        if ( XMLUtil::StringEqual( a->Name(), name ) ) {\r
+            return a;\r
+        }\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+const char* XMLElement::Attribute( const char* name, const char* value ) const\r
+{\r
+    const XMLAttribute* a = FindAttribute( name );\r
+    if ( !a ) {\r
+        return 0;\r
+    }\r
+    if ( !value || XMLUtil::StringEqual( a->Value(), value )) {\r
+        return a->Value();\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+const char* XMLElement::GetText() const\r
+{\r
+    if ( FirstChild() && FirstChild()->ToText() ) {\r
+        return FirstChild()->Value();\r
+    }\r
+    return 0;\r
+}\r
+\r
+\r
+void   XMLElement::SetText( const char* inText )\r
+{\r
+       if ( FirstChild() && FirstChild()->ToText() )\r
+               FirstChild()->SetValue( inText );\r
+       else {\r
+               XMLText*        theText = GetDocument()->NewText( inText );\r
+               InsertFirstChild( theText );\r
+       }\r
+}\r
+\r
+\r
+void XMLElement::SetText( int v ) \r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    SetText( buf );\r
+}\r
+\r
+\r
+void XMLElement::SetText( unsigned v ) \r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    SetText( buf );\r
+}\r
+\r
+\r
+void XMLElement::SetText( bool v ) \r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    SetText( buf );\r
+}\r
+\r
+\r
+void XMLElement::SetText( float v ) \r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    SetText( buf );\r
+}\r
+\r
+\r
+void XMLElement::SetText( double v ) \r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    SetText( buf );\r
+}\r
+\r
+\r
+XMLError XMLElement::QueryIntText( int* ival ) const\r
+{\r
+    if ( FirstChild() && FirstChild()->ToText() ) {\r
+        const char* t = FirstChild()->Value();\r
+        if ( XMLUtil::ToInt( t, ival ) ) {\r
+            return XML_SUCCESS;\r
+        }\r
+        return XML_CAN_NOT_CONVERT_TEXT;\r
+    }\r
+    return XML_NO_TEXT_NODE;\r
+}\r
+\r
+\r
+XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const\r
+{\r
+    if ( FirstChild() && FirstChild()->ToText() ) {\r
+        const char* t = FirstChild()->Value();\r
+        if ( XMLUtil::ToUnsigned( t, uval ) ) {\r
+            return XML_SUCCESS;\r
+        }\r
+        return XML_CAN_NOT_CONVERT_TEXT;\r
+    }\r
+    return XML_NO_TEXT_NODE;\r
+}\r
+\r
+\r
+XMLError XMLElement::QueryBoolText( bool* bval ) const\r
+{\r
+    if ( FirstChild() && FirstChild()->ToText() ) {\r
+        const char* t = FirstChild()->Value();\r
+        if ( XMLUtil::ToBool( t, bval ) ) {\r
+            return XML_SUCCESS;\r
+        }\r
+        return XML_CAN_NOT_CONVERT_TEXT;\r
+    }\r
+    return XML_NO_TEXT_NODE;\r
+}\r
+\r
+\r
+XMLError XMLElement::QueryDoubleText( double* dval ) const\r
+{\r
+    if ( FirstChild() && FirstChild()->ToText() ) {\r
+        const char* t = FirstChild()->Value();\r
+        if ( XMLUtil::ToDouble( t, dval ) ) {\r
+            return XML_SUCCESS;\r
+        }\r
+        return XML_CAN_NOT_CONVERT_TEXT;\r
+    }\r
+    return XML_NO_TEXT_NODE;\r
+}\r
+\r
+\r
+XMLError XMLElement::QueryFloatText( float* fval ) const\r
+{\r
+    if ( FirstChild() && FirstChild()->ToText() ) {\r
+        const char* t = FirstChild()->Value();\r
+        if ( XMLUtil::ToFloat( t, fval ) ) {\r
+            return XML_SUCCESS;\r
+        }\r
+        return XML_CAN_NOT_CONVERT_TEXT;\r
+    }\r
+    return XML_NO_TEXT_NODE;\r
+}\r
+\r
+\r
+\r
+XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )\r
+{\r
+    XMLAttribute* last = 0;\r
+    XMLAttribute* attrib = 0;\r
+    for( attrib = _rootAttribute;\r
+            attrib;\r
+            last = attrib, attrib = attrib->_next ) {\r
+        if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {\r
+            break;\r
+        }\r
+    }\r
+    if ( !attrib ) {\r
+        TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );\r
+        attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();\r
+        attrib->_memPool = &_document->_attributePool;\r
+        if ( last ) {\r
+            last->_next = attrib;\r
+        }\r
+        else {\r
+            _rootAttribute = attrib;\r
+        }\r
+        attrib->SetName( name );\r
+        attrib->_memPool->SetTracked(); // always created and linked.\r
+    }\r
+    return attrib;\r
+}\r
+\r
+\r
+void XMLElement::DeleteAttribute( const char* name )\r
+{\r
+    XMLAttribute* prev = 0;\r
+    for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {\r
+        if ( XMLUtil::StringEqual( name, a->Name() ) ) {\r
+            if ( prev ) {\r
+                prev->_next = a->_next;\r
+            }\r
+            else {\r
+                _rootAttribute = a->_next;\r
+            }\r
+            DeleteAttribute( a );\r
+            break;\r
+        }\r
+        prev = a;\r
+    }\r
+}\r
+\r
+\r
+char* XMLElement::ParseAttributes( char* p )\r
+{\r
+    const char* start = p;\r
+    XMLAttribute* prevAttribute = 0;\r
+\r
+    // Read the attributes.\r
+    while( p ) {\r
+        p = XMLUtil::SkipWhiteSpace( p );\r
+        if ( !(*p) ) {\r
+            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() );\r
+            return 0;\r
+        }\r
+\r
+        // attribute.\r
+        if (XMLUtil::IsNameStartChar( *p ) ) {\r
+            TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );\r
+            XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();\r
+            attrib->_memPool = &_document->_attributePool;\r
+                       attrib->_memPool->SetTracked();\r
+\r
+            p = attrib->ParseDeep( p, _document->ProcessEntities() );\r
+            if ( !p || Attribute( attrib->Name() ) ) {\r
+                DeleteAttribute( attrib );\r
+                _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p );\r
+                return 0;\r
+            }\r
+            // There is a minor bug here: if the attribute in the source xml\r
+            // document is duplicated, it will not be detected and the\r
+            // attribute will be doubly added. However, tracking the 'prevAttribute'\r
+            // avoids re-scanning the attribute list. Preferring performance for\r
+            // now, may reconsider in the future.\r
+            if ( prevAttribute ) {\r
+                prevAttribute->_next = attrib;\r
+            }\r
+            else {\r
+                _rootAttribute = attrib;\r
+            }\r
+            prevAttribute = attrib;\r
+        }\r
+        // end of the tag\r
+        else if ( *p == '>' ) {\r
+            ++p;\r
+            break;\r
+        }\r
+        // end of the tag\r
+        else if ( *p == '/' && *(p+1) == '>' ) {\r
+            _closingType = CLOSED;\r
+            return p+2;        // done; sealed element.\r
+        }\r
+        else {\r
+            _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p );\r
+            return 0;\r
+        }\r
+    }\r
+    return p;\r
+}\r
+\r
+void XMLElement::DeleteAttribute( XMLAttribute* attribute )\r
+{\r
+    if ( attribute == 0 ) {\r
+        return;\r
+    }\r
+    MemPool* pool = attribute->_memPool;\r
+    attribute->~XMLAttribute();\r
+    pool->Free( attribute );\r
+}\r
+\r
+//\r
+//     <ele></ele>\r
+//     <ele>foo<b>bar</b></ele>\r
+//\r
+char* XMLElement::ParseDeep( char* p, StrPair* strPair )\r
+{\r
+    // Read the element name.\r
+    p = XMLUtil::SkipWhiteSpace( p );\r
+\r
+    // The closing element is the </element> form. It is\r
+    // parsed just like a regular element then deleted from\r
+    // the DOM.\r
+    if ( *p == '/' ) {\r
+        _closingType = CLOSING;\r
+        ++p;\r
+    }\r
+\r
+    p = _value.ParseName( p );\r
+    if ( _value.Empty() ) {\r
+        return 0;\r
+    }\r
+\r
+    p = ParseAttributes( p );\r
+    if ( !p || !*p || _closingType ) {\r
+        return p;\r
+    }\r
+\r
+    p = XMLNode::ParseDeep( p, strPair );\r
+    return p;\r
+}\r
+\r
+\r
+\r
+XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const\r
+{\r
+    if ( !doc ) {\r
+        doc = _document;\r
+    }\r
+    XMLElement* element = doc->NewElement( Value() );                                  // fixme: this will always allocate memory. Intern?\r
+    for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {\r
+        element->SetAttribute( a->Name(), a->Value() );                                        // fixme: this will always allocate memory. Intern?\r
+    }\r
+    return element;\r
+}\r
+\r
+\r
+bool XMLElement::ShallowEqual( const XMLNode* compare ) const\r
+{\r
+    TIXMLASSERT( compare );\r
+    const XMLElement* other = compare->ToElement();\r
+    if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {\r
+\r
+        const XMLAttribute* a=FirstAttribute();\r
+        const XMLAttribute* b=other->FirstAttribute();\r
+\r
+        while ( a && b ) {\r
+            if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {\r
+                return false;\r
+            }\r
+            a = a->Next();\r
+            b = b->Next();\r
+        }\r
+        if ( a || b ) {\r
+            // different count\r
+            return false;\r
+        }\r
+        return true;\r
+    }\r
+    return false;\r
+}\r
+\r
+\r
+bool XMLElement::Accept( XMLVisitor* visitor ) const\r
+{\r
+    TIXMLASSERT( visitor );\r
+    if ( visitor->VisitEnter( *this, _rootAttribute ) ) {\r
+        for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {\r
+            if ( !node->Accept( visitor ) ) {\r
+                break;\r
+            }\r
+        }\r
+    }\r
+    return visitor->VisitExit( *this );\r
+}\r
+\r
+\r
+// --------- XMLDocument ----------- //\r
+\r
+// Warning: List must match 'enum XMLError'\r
+const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = {\r
+    "XML_SUCCESS",\r
+    "XML_NO_ATTRIBUTE",\r
+    "XML_WRONG_ATTRIBUTE_TYPE",\r
+    "XML_ERROR_FILE_NOT_FOUND",\r
+    "XML_ERROR_FILE_COULD_NOT_BE_OPENED",\r
+    "XML_ERROR_FILE_READ_ERROR",\r
+    "XML_ERROR_ELEMENT_MISMATCH",\r
+    "XML_ERROR_PARSING_ELEMENT",\r
+    "XML_ERROR_PARSING_ATTRIBUTE",\r
+    "XML_ERROR_IDENTIFYING_TAG",\r
+    "XML_ERROR_PARSING_TEXT",\r
+    "XML_ERROR_PARSING_CDATA",\r
+    "XML_ERROR_PARSING_COMMENT",\r
+    "XML_ERROR_PARSING_DECLARATION",\r
+    "XML_ERROR_PARSING_UNKNOWN",\r
+    "XML_ERROR_EMPTY_DOCUMENT",\r
+    "XML_ERROR_MISMATCHED_ELEMENT",\r
+    "XML_ERROR_PARSING",\r
+    "XML_CAN_NOT_CONVERT_TEXT",\r
+    "XML_NO_TEXT_NODE"\r
+};\r
+\r
+\r
+XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :\r
+    XMLNode( 0 ),\r
+    _writeBOM( false ),\r
+    _processEntities( processEntities ),\r
+    _errorID( XML_NO_ERROR ),\r
+    _whitespace( whitespace ),\r
+    _errorStr1( 0 ),\r
+    _errorStr2( 0 ),\r
+    _charBuffer( 0 )\r
+{\r
+    // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)\r
+    _document = this;\r
+}\r
+\r
+\r
+XMLDocument::~XMLDocument()\r
+{\r
+    Clear();\r
+}\r
+\r
+\r
+void XMLDocument::Clear()\r
+{\r
+    DeleteChildren();\r
+\r
+#ifdef DEBUG\r
+    const bool hadError = Error();\r
+#endif\r
+    _errorID = XML_NO_ERROR;\r
+    _errorStr1 = 0;\r
+    _errorStr2 = 0;\r
+\r
+    delete [] _charBuffer;\r
+    _charBuffer = 0;\r
+\r
+#if 0\r
+    _textPool.Trace( "text" );\r
+    _elementPool.Trace( "element" );\r
+    _commentPool.Trace( "comment" );\r
+    _attributePool.Trace( "attribute" );\r
+#endif\r
+    \r
+#ifdef DEBUG\r
+    if ( !hadError ) {\r
+        TIXMLASSERT( _elementPool.CurrentAllocs()   == _elementPool.Untracked() );\r
+        TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );\r
+        TIXMLASSERT( _textPool.CurrentAllocs()      == _textPool.Untracked() );\r
+        TIXMLASSERT( _commentPool.CurrentAllocs()   == _commentPool.Untracked() );\r
+    }\r
+#endif\r
+}\r
+\r
+\r
+XMLElement* XMLDocument::NewElement( const char* name )\r
+{\r
+    TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() );\r
+    XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );\r
+    ele->_memPool = &_elementPool;\r
+    ele->SetName( name );\r
+    return ele;\r
+}\r
+\r
+\r
+XMLComment* XMLDocument::NewComment( const char* str )\r
+{\r
+    TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() );\r
+    XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );\r
+    comment->_memPool = &_commentPool;\r
+    comment->SetValue( str );\r
+    return comment;\r
+}\r
+\r
+\r
+XMLText* XMLDocument::NewText( const char* str )\r
+{\r
+    TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );\r
+    XMLText* text = new (_textPool.Alloc()) XMLText( this );\r
+    text->_memPool = &_textPool;\r
+    text->SetValue( str );\r
+    return text;\r
+}\r
+\r
+\r
+XMLDeclaration* XMLDocument::NewDeclaration( const char* str )\r
+{\r
+    TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );\r
+    XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );\r
+    dec->_memPool = &_commentPool;\r
+    dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );\r
+    return dec;\r
+}\r
+\r
+\r
+XMLUnknown* XMLDocument::NewUnknown( const char* str )\r
+{\r
+    TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() );\r
+    XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );\r
+    unk->_memPool = &_commentPool;\r
+    unk->SetValue( str );\r
+    return unk;\r
+}\r
+\r
+static FILE* callfopen( const char* filepath, const char* mode )\r
+{\r
+    TIXMLASSERT( filepath );\r
+    TIXMLASSERT( mode );\r
+#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)\r
+    FILE* fp = 0;\r
+    errno_t err = fopen_s( &fp, filepath, mode );\r
+    if ( err ) {\r
+        return 0;\r
+    }\r
+#else\r
+    FILE* fp = fopen( filepath, mode );\r
+#endif\r
+    return fp;\r
+}\r
+    \r
+void XMLDocument::DeleteNode( XMLNode* node )  {\r
+    TIXMLASSERT( node );\r
+    TIXMLASSERT(node->_document == this );\r
+    if (node->_parent) {\r
+        node->_parent->DeleteChild( node );\r
+    }\r
+    else {\r
+        // Isn't in the tree.\r
+        // Use the parent delete.\r
+        // Also, we need to mark it tracked: we 'know'\r
+        // it was never used.\r
+        node->_memPool->SetTracked();\r
+        // Call the static XMLNode version:\r
+        XMLNode::DeleteNode(node);\r
+    }\r
+}\r
+\r
+\r
+XMLError XMLDocument::LoadFile( const char* filename )\r
+{\r
+    Clear();\r
+    FILE* fp = callfopen( filename, "rb" );\r
+    if ( !fp ) {\r
+        SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );\r
+        return _errorID;\r
+    }\r
+    LoadFile( fp );\r
+    fclose( fp );\r
+    return _errorID;\r
+}\r
+\r
+// This is likely overengineered template art to have a check that unsigned long value incremented\r
+// by one still fits into size_t. If size_t type is larger than unsigned long type\r
+// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit\r
+// -Wtype-limits warning. This piece makes the compiler select code with a check when a check\r
+// is useful and code with no check when a check is redundant depending on how size_t and unsigned long\r
+// types sizes relate to each other.\r
+template\r
+<bool = (sizeof(unsigned long) >= sizeof(size_t))>\r
+struct LongFitsIntoSizeTMinusOne {\r
+    static bool Fits( unsigned long value )\r
+    {\r
+        return value < (size_t)-1;\r
+    }\r
+};\r
+\r
+template <>\r
+bool LongFitsIntoSizeTMinusOne<false>::Fits( unsigned long /*value*/ )\r
+{\r
+    return true;\r
+}\r
+\r
+XMLError XMLDocument::LoadFile( FILE* fp )\r
+{\r
+    Clear();\r
+\r
+    fseek( fp, 0, SEEK_SET );\r
+    if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {\r
+        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\r
+        return _errorID;\r
+    }\r
+\r
+    fseek( fp, 0, SEEK_END );\r
+    const long filelength = ftell( fp );\r
+    fseek( fp, 0, SEEK_SET );\r
+    if ( filelength == -1L ) {\r
+        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\r
+        return _errorID;\r
+    }\r
+    TIXMLASSERT( filelength >= 0 );\r
+\r
+    if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {\r
+        // Cannot handle files which won't fit in buffer together with null terminator\r
+        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\r
+        return _errorID;\r
+    }\r
+\r
+    if ( filelength == 0 ) {\r
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );\r
+        return _errorID;\r
+    }\r
+\r
+    const size_t size = filelength;\r
+    TIXMLASSERT( _charBuffer == 0 );\r
+    _charBuffer = new char[size+1];\r
+    size_t read = fread( _charBuffer, 1, size, fp );\r
+    if ( read != size ) {\r
+        SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );\r
+        return _errorID;\r
+    }\r
+\r
+    _charBuffer[size] = 0;\r
+\r
+    Parse();\r
+    return _errorID;\r
+}\r
+\r
+\r
+XMLError XMLDocument::SaveFile( const char* filename, bool compact )\r
+{\r
+    FILE* fp = callfopen( filename, "w" );\r
+    if ( !fp ) {\r
+        SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 );\r
+        return _errorID;\r
+    }\r
+    SaveFile(fp, compact);\r
+    fclose( fp );\r
+    return _errorID;\r
+}\r
+\r
+\r
+XMLError XMLDocument::SaveFile( FILE* fp, bool compact )\r
+{\r
+    // Clear any error from the last save, otherwise it will get reported\r
+    // for *this* call.\r
+    SetError( XML_NO_ERROR, 0, 0 );\r
+    XMLPrinter stream( fp, compact );\r
+    Print( &stream );\r
+    return _errorID;\r
+}\r
+\r
+\r
+XMLError XMLDocument::Parse( const char* p, size_t len )\r
+{\r
+    Clear();\r
+\r
+    if ( len == 0 || !p || !*p ) {\r
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );\r
+        return _errorID;\r
+    }\r
+    if ( len == (size_t)(-1) ) {\r
+        len = strlen( p );\r
+    }\r
+    TIXMLASSERT( _charBuffer == 0 );\r
+    _charBuffer = new char[ len+1 ];\r
+    memcpy( _charBuffer, p, len );\r
+    _charBuffer[len] = 0;\r
+\r
+    Parse();\r
+    if ( Error() ) {\r
+        // clean up now essentially dangling memory.\r
+        // and the parse fail can put objects in the\r
+        // pools that are dead and inaccessible.\r
+        DeleteChildren();\r
+        _elementPool.Clear();\r
+        _attributePool.Clear();\r
+        _textPool.Clear();\r
+        _commentPool.Clear();\r
+    }\r
+    return _errorID;\r
+}\r
+\r
+\r
+void XMLDocument::Print( XMLPrinter* streamer ) const\r
+{\r
+    if ( streamer ) {\r
+        Accept( streamer );\r
+    }\r
+    else {\r
+        XMLPrinter stdoutStreamer( stdout );\r
+        Accept( &stdoutStreamer );\r
+    }\r
+}\r
+\r
+\r
+void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )\r
+{\r
+    TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );\r
+    _errorID = error;\r
+    _errorStr1 = str1;\r
+    _errorStr2 = str2;\r
+}\r
+\r
+const char* XMLDocument::ErrorName() const\r
+{\r
+       TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT );\r
+    const char* errorName = _errorNames[_errorID];\r
+    TIXMLASSERT( errorName && errorName[0] );\r
+    return errorName;\r
+}\r
+\r
+void XMLDocument::PrintError() const\r
+{\r
+    if ( Error() ) {\r
+        static const int LEN = 20;\r
+        char buf1[LEN] = { 0 };\r
+        char buf2[LEN] = { 0 };\r
+\r
+        if ( _errorStr1 ) {\r
+            TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );\r
+        }\r
+        if ( _errorStr2 ) {\r
+            TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );\r
+        }\r
+\r
+        // Should check INT_MIN <= _errorID && _errorId <= INT_MAX, but that\r
+        // causes a clang "always true" -Wtautological-constant-out-of-range-compare warning\r
+        TIXMLASSERT( 0 <= _errorID && XML_ERROR_COUNT - 1 <= INT_MAX );\r
+        printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n",\r
+                static_cast<int>( _errorID ), ErrorName(), buf1, buf2 );\r
+    }\r
+}\r
+\r
+void XMLDocument::Parse()\r
+{\r
+    TIXMLASSERT( NoChildren() ); // Clear() must have been called previously\r
+    TIXMLASSERT( _charBuffer );\r
+    char* p = _charBuffer;\r
+    p = XMLUtil::SkipWhiteSpace( p );\r
+    p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );\r
+    if ( !*p ) {\r
+        SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );\r
+        return;\r
+    }\r
+    ParseDeep(p, 0 );\r
+}\r
+\r
+XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :\r
+    _elementJustOpened( false ),\r
+    _firstElement( true ),\r
+    _fp( file ),\r
+    _depth( depth ),\r
+    _textDepth( -1 ),\r
+    _processEntities( true ),\r
+    _compactMode( compact )\r
+{\r
+    for( int i=0; i<ENTITY_RANGE; ++i ) {\r
+        _entityFlag[i] = false;\r
+        _restrictedEntityFlag[i] = false;\r
+    }\r
+    for( int i=0; i<NUM_ENTITIES; ++i ) {\r
+        const char entityValue = entities[i].value;\r
+        TIXMLASSERT( 0 <= entityValue && entityValue < ENTITY_RANGE );\r
+        _entityFlag[ (unsigned char)entityValue ] = true;\r
+    }\r
+    _restrictedEntityFlag[(unsigned char)'&'] = true;\r
+    _restrictedEntityFlag[(unsigned char)'<'] = true;\r
+    _restrictedEntityFlag[(unsigned char)'>'] = true;  // not required, but consistency is nice\r
+    _buffer.Push( 0 );\r
+}\r
+\r
+\r
+void XMLPrinter::Print( const char* format, ... )\r
+{\r
+    va_list     va;\r
+    va_start( va, format );\r
+\r
+    if ( _fp ) {\r
+        vfprintf( _fp, format, va );\r
+    }\r
+    else {\r
+        const int len = TIXML_VSCPRINTF( format, va );\r
+        // Close out and re-start the va-args\r
+        va_end( va );\r
+        TIXMLASSERT( len >= 0 );\r
+        va_start( va, format );\r
+        TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );\r
+        char* p = _buffer.PushArr( len ) - 1;  // back up over the null terminator.\r
+               TIXML_VSNPRINTF( p, len+1, format, va );\r
+    }\r
+    va_end( va );\r
+}\r
+\r
+\r
+void XMLPrinter::PrintSpace( int depth )\r
+{\r
+    for( int i=0; i<depth; ++i ) {\r
+        Print( "    " );\r
+    }\r
+}\r
+\r
+\r
+void XMLPrinter::PrintString( const char* p, bool restricted )\r
+{\r
+    // Look for runs of bytes between entities to print.\r
+    const char* q = p;\r
+\r
+    if ( _processEntities ) {\r
+        const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;\r
+        while ( *q ) {\r
+            TIXMLASSERT( p <= q );\r
+            // Remember, char is sometimes signed. (How many times has that bitten me?)\r
+            if ( *q > 0 && *q < ENTITY_RANGE ) {\r
+                // Check for entities. If one is found, flush\r
+                // the stream up until the entity, write the\r
+                // entity, and keep looking.\r
+                if ( flag[(unsigned char)(*q)] ) {\r
+                    while ( p < q ) {\r
+                        const size_t delta = q - p;\r
+                        // %.*s accepts type int as "precision"\r
+                        const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;\r
+                        Print( "%.*s", toPrint, p );\r
+                        p += toPrint;\r
+                    }\r
+                    bool entityPatternPrinted = false;\r
+                    for( int i=0; i<NUM_ENTITIES; ++i ) {\r
+                        if ( entities[i].value == *q ) {\r
+                            Print( "&%s;", entities[i].pattern );\r
+                            entityPatternPrinted = true;\r
+                            break;\r
+                        }\r
+                    }\r
+                    if ( !entityPatternPrinted ) {\r
+                        // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release\r
+                        TIXMLASSERT( false );\r
+                    }\r
+                    ++p;\r
+                }\r
+            }\r
+            ++q;\r
+            TIXMLASSERT( p <= q );\r
+        }\r
+    }\r
+    // Flush the remaining string. This will be the entire\r
+    // string if an entity wasn't found.\r
+    TIXMLASSERT( p <= q );\r
+    if ( !_processEntities || ( p < q ) ) {\r
+        Print( "%s", p );\r
+    }\r
+}\r
+\r
+\r
+void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )\r
+{\r
+    if ( writeBOM ) {\r
+        static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };\r
+        Print( "%s", bom );\r
+    }\r
+    if ( writeDec ) {\r
+        PushDeclaration( "xml version=\"1.0\"" );\r
+    }\r
+}\r
+\r
+\r
+void XMLPrinter::OpenElement( const char* name, bool compactMode )\r
+{\r
+    SealElementIfJustOpened();\r
+    _stack.Push( name );\r
+\r
+    if ( _textDepth < 0 && !_firstElement && !compactMode ) {\r
+        Print( "\n" );\r
+    }\r
+    if ( !compactMode ) {\r
+        PrintSpace( _depth );\r
+    }\r
+\r
+    Print( "<%s", name );\r
+    _elementJustOpened = true;\r
+    _firstElement = false;\r
+    ++_depth;\r
+}\r
+\r
+\r
+void XMLPrinter::PushAttribute( const char* name, const char* value )\r
+{\r
+    TIXMLASSERT( _elementJustOpened );\r
+    Print( " %s=\"", name );\r
+    PrintString( value, false );\r
+    Print( "\"" );\r
+}\r
+\r
+\r
+void XMLPrinter::PushAttribute( const char* name, int v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    PushAttribute( name, buf );\r
+}\r
+\r
+\r
+void XMLPrinter::PushAttribute( const char* name, unsigned v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    PushAttribute( name, buf );\r
+}\r
+\r
+\r
+void XMLPrinter::PushAttribute( const char* name, bool v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    PushAttribute( name, buf );\r
+}\r
+\r
+\r
+void XMLPrinter::PushAttribute( const char* name, double v )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( v, buf, BUF_SIZE );\r
+    PushAttribute( name, buf );\r
+}\r
+\r
+\r
+void XMLPrinter::CloseElement( bool compactMode )\r
+{\r
+    --_depth;\r
+    const char* name = _stack.Pop();\r
+\r
+    if ( _elementJustOpened ) {\r
+        Print( "/>" );\r
+    }\r
+    else {\r
+        if ( _textDepth < 0 && !compactMode) {\r
+            Print( "\n" );\r
+            PrintSpace( _depth );\r
+        }\r
+        Print( "</%s>", name );\r
+    }\r
+\r
+    if ( _textDepth == _depth ) {\r
+        _textDepth = -1;\r
+    }\r
+    if ( _depth == 0 && !compactMode) {\r
+        Print( "\n" );\r
+    }\r
+    _elementJustOpened = false;\r
+}\r
+\r
+\r
+void XMLPrinter::SealElementIfJustOpened()\r
+{\r
+    if ( !_elementJustOpened ) {\r
+        return;\r
+    }\r
+    _elementJustOpened = false;\r
+    Print( ">" );\r
+}\r
+\r
+\r
+void XMLPrinter::PushText( const char* text, bool cdata )\r
+{\r
+    _textDepth = _depth-1;\r
+\r
+    SealElementIfJustOpened();\r
+    if ( cdata ) {\r
+        Print( "<![CDATA[%s]]>", text );\r
+    }\r
+    else {\r
+        PrintString( text, true );\r
+    }\r
+}\r
+\r
+void XMLPrinter::PushText( int value )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( value, buf, BUF_SIZE );\r
+    PushText( buf, false );\r
+}\r
+\r
+\r
+void XMLPrinter::PushText( unsigned value )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( value, buf, BUF_SIZE );\r
+    PushText( buf, false );\r
+}\r
+\r
+\r
+void XMLPrinter::PushText( bool value )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( value, buf, BUF_SIZE );\r
+    PushText( buf, false );\r
+}\r
+\r
+\r
+void XMLPrinter::PushText( float value )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( value, buf, BUF_SIZE );\r
+    PushText( buf, false );\r
+}\r
+\r
+\r
+void XMLPrinter::PushText( double value )\r
+{\r
+    char buf[BUF_SIZE];\r
+    XMLUtil::ToStr( value, buf, BUF_SIZE );\r
+    PushText( buf, false );\r
+}\r
+\r
+\r
+void XMLPrinter::PushComment( const char* comment )\r
+{\r
+    SealElementIfJustOpened();\r
+    if ( _textDepth < 0 && !_firstElement && !_compactMode) {\r
+        Print( "\n" );\r
+        PrintSpace( _depth );\r
+    }\r
+    _firstElement = false;\r
+    Print( "<!--%s-->", comment );\r
+}\r
+\r
+\r
+void XMLPrinter::PushDeclaration( const char* value )\r
+{\r
+    SealElementIfJustOpened();\r
+    if ( _textDepth < 0 && !_firstElement && !_compactMode) {\r
+        Print( "\n" );\r
+        PrintSpace( _depth );\r
+    }\r
+    _firstElement = false;\r
+    Print( "<?%s?>", value );\r
+}\r
+\r
+\r
+void XMLPrinter::PushUnknown( const char* value )\r
+{\r
+    SealElementIfJustOpened();\r
+    if ( _textDepth < 0 && !_firstElement && !_compactMode) {\r
+        Print( "\n" );\r
+        PrintSpace( _depth );\r
+    }\r
+    _firstElement = false;\r
+    Print( "<!%s>", value );\r
+}\r
+\r
+\r
+bool XMLPrinter::VisitEnter( const XMLDocument& doc )\r
+{\r
+    _processEntities = doc.ProcessEntities();\r
+    if ( doc.HasBOM() ) {\r
+        PushHeader( true, false );\r
+    }\r
+    return true;\r
+}\r
+\r
+\r
+bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )\r
+{\r
+    const XMLElement* parentElem = 0;\r
+    if ( element.Parent() ) {\r
+        parentElem = element.Parent()->ToElement();\r
+    }\r
+    const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;\r
+    OpenElement( element.Name(), compactMode );\r
+    while ( attribute ) {\r
+        PushAttribute( attribute->Name(), attribute->Value() );\r
+        attribute = attribute->Next();\r
+    }\r
+    return true;\r
+}\r
+\r
+\r
+bool XMLPrinter::VisitExit( const XMLElement& element )\r
+{\r
+    CloseElement( CompactMode(element) );\r
+    return true;\r
+}\r
+\r
+\r
+bool XMLPrinter::Visit( const XMLText& text )\r
+{\r
+    PushText( text.Value(), text.CData() );\r
+    return true;\r
+}\r
+\r
+\r
+bool XMLPrinter::Visit( const XMLComment& comment )\r
+{\r
+    PushComment( comment.Value() );\r
+    return true;\r
+}\r
+\r
+bool XMLPrinter::Visit( const XMLDeclaration& declaration )\r
+{\r
+    PushDeclaration( declaration.Value() );\r
+    return true;\r
+}\r
+\r
+\r
+bool XMLPrinter::Visit( const XMLUnknown& unknown )\r
+{\r
+    PushUnknown( unknown.Value() );\r
+    return true;\r
+}\r
+\r
+}   // namespace tinyxml2\r
+\r
diff --git a/lib/cpPlugins/tinyxml2/tinyxml2.h b/lib/cpPlugins/tinyxml2/tinyxml2.h
new file mode 100644 (file)
index 0000000..3598786
--- /dev/null
@@ -0,0 +1,2106 @@
+/*\r
+Original code by Lee Thomason (www.grinninglizard.com)\r
+\r
+This software is provided 'as-is', without any express or implied\r
+warranty. In no event will the authors be held liable for any\r
+damages arising from the use of this software.\r
+\r
+Permission is granted to anyone to use this software for any\r
+purpose, including commercial applications, and to alter it and\r
+redistribute it freely, subject to the following restrictions:\r
+\r
+1. The origin of this software must not be misrepresented; you must\r
+not claim that you wrote the original software. If you use this\r
+software in a product, an acknowledgment in the product documentation\r
+would be appreciated but is not required.\r
+\r
+2. Altered source versions must be plainly marked as such, and\r
+must not be misrepresented as being the original software.\r
+\r
+3. This notice may not be removed or altered from any source\r
+distribution.\r
+*/\r
+\r
+#ifndef TINYXML2_INCLUDED\r
+#define TINYXML2_INCLUDED\r
+\r
+#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)\r
+#   include <ctype.h>\r
+#   include <limits.h>\r
+#   include <stdio.h>\r
+#   include <stdlib.h>\r
+#   include <string.h>\r
+#else\r
+#   include <cctype>\r
+#   include <climits>\r
+#   include <cstdio>\r
+#   include <cstdlib>\r
+#   include <cstring>\r
+#endif\r
+\r
+/*\r
+   TODO: intern strings instead of allocation.\r
+*/\r
+/*\r
+       gcc:\r
+        g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe\r
+\r
+    Formatting, Artistic Style:\r
+        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h\r
+*/\r
+\r
+#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)\r
+#   ifndef DEBUG\r
+#       define DEBUG\r
+#   endif\r
+#endif\r
+\r
+#ifdef _MSC_VER\r
+#   pragma warning(push)\r
+#   pragma warning(disable: 4251)\r
+#endif\r
+\r
+#ifdef _WIN32\r
+#   ifdef TINYXML2_EXPORT\r
+#       define TINYXML2_LIB __declspec(dllexport)\r
+#   elif defined(TINYXML2_IMPORT)\r
+#       define TINYXML2_LIB __declspec(dllimport)\r
+#   else\r
+#       define TINYXML2_LIB\r
+#   endif\r
+#else\r
+#   define TINYXML2_LIB\r
+#endif\r
+\r
+\r
+#if defined(DEBUG)\r
+#   if defined(_MSC_VER)\r
+#       // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like\r
+#       define TIXMLASSERT( x )           if ( !((void)0,(x))) { __debugbreak(); }\r
+#   elif defined (ANDROID_NDK)\r
+#       include <android/log.h>\r
+#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }\r
+#   else\r
+#       include <assert.h>\r
+#       define TIXMLASSERT                assert\r
+#   endif\r
+#else\r
+#   define TIXMLASSERT( x )               {}\r
+#endif\r
+\r
+\r
+/* Versioning, past 1.0.14:\r
+       http://semver.org/\r
+*/\r
+static const int TIXML2_MAJOR_VERSION = 3;\r
+static const int TIXML2_MINOR_VERSION = 0;\r
+static const int TIXML2_PATCH_VERSION = 0;\r
+\r
+#include <cpPlugins_Export.h>\r
+#undef TINYXML2_LIB\r
+#define TINYXML2_LIB cpPlugins_EXPORT\r
+\r
+namespace tinyxml2\r
+{\r
+class XMLDocument;\r
+class XMLElement;\r
+class XMLAttribute;\r
+class XMLComment;\r
+class XMLText;\r
+class XMLDeclaration;\r
+class XMLUnknown;\r
+class XMLPrinter;\r
+\r
+/*\r
+       A class that wraps strings. Normally stores the start and end\r
+       pointers into the XML file itself, and will apply normalization\r
+       and entity translation if actually read. Can also store (and memory\r
+       manage) a traditional char[]\r
+*/\r
+class StrPair\r
+{\r
+public:\r
+    enum {\r
+        NEEDS_ENTITY_PROCESSING                        = 0x01,\r
+        NEEDS_NEWLINE_NORMALIZATION            = 0x02,\r
+        NEEDS_WHITESPACE_COLLAPSING     = 0x04,\r
+\r
+        TEXT_ELEMENT                           = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,\r
+        TEXT_ELEMENT_LEAVE_ENTITIES            = NEEDS_NEWLINE_NORMALIZATION,\r
+        ATTRIBUTE_NAME                         = 0,\r
+        ATTRIBUTE_VALUE                                = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,\r
+        ATTRIBUTE_VALUE_LEAVE_ENTITIES         = NEEDS_NEWLINE_NORMALIZATION,\r
+        COMMENT                                        = NEEDS_NEWLINE_NORMALIZATION\r
+    };\r
+\r
+    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}\r
+    ~StrPair();\r
+\r
+    void Set( char* start, char* end, int flags ) {\r
+        Reset();\r
+        _start  = start;\r
+        _end    = end;\r
+        _flags  = flags | NEEDS_FLUSH;\r
+    }\r
+\r
+    const char* GetStr();\r
+\r
+    bool Empty() const {\r
+        return _start == _end;\r
+    }\r
+\r
+    void SetInternedStr( const char* str ) {\r
+        Reset();\r
+        _start = const_cast<char*>(str);\r
+    }\r
+\r
+    void SetStr( const char* str, int flags=0 );\r
+\r
+    char* ParseText( char* in, const char* endTag, int strFlags );\r
+    char* ParseName( char* in );\r
+\r
+    void TransferTo( StrPair* other );\r
+\r
+private:\r
+    void Reset();\r
+    void CollapseWhitespace();\r
+\r
+    enum {\r
+        NEEDS_FLUSH = 0x100,\r
+        NEEDS_DELETE = 0x200\r
+    };\r
+\r
+    int     _flags;\r
+    char*   _start;\r
+    char*   _end;\r
+\r
+    StrPair( const StrPair& other );   // not supported\r
+    void operator=( StrPair& other );  // not supported, use TransferTo()\r
+};\r
+\r
+\r
+/*\r
+       A dynamic array of Plain Old Data. Doesn't support constructors, etc.\r
+       Has a small initial memory pool, so that low or no usage will not\r
+       cause a call to new/delete\r
+*/\r
+template <class T, int INITIAL_SIZE>\r
+class DynArray\r
+{\r
+public:\r
+    DynArray() {\r
+        _mem = _pool;\r
+        _allocated = INITIAL_SIZE;\r
+        _size = 0;\r
+    }\r
+\r
+    ~DynArray() {\r
+        if ( _mem != _pool ) {\r
+            delete [] _mem;\r
+        }\r
+    }\r
+\r
+    void Clear() {\r
+        _size = 0;\r
+    }\r
+\r
+    void Push( T t ) {\r
+        TIXMLASSERT( _size < INT_MAX );\r
+        EnsureCapacity( _size+1 );\r
+        _mem[_size++] = t;\r
+    }\r
+\r
+    T* PushArr( int count ) {\r
+        TIXMLASSERT( count >= 0 );\r
+        TIXMLASSERT( _size <= INT_MAX - count );\r
+        EnsureCapacity( _size+count );\r
+        T* ret = &_mem[_size];\r
+        _size += count;\r
+        return ret;\r
+    }\r
+\r
+    T Pop() {\r
+        TIXMLASSERT( _size > 0 );\r
+        return _mem[--_size];\r
+    }\r
+\r
+    void PopArr( int count ) {\r
+        TIXMLASSERT( _size >= count );\r
+        _size -= count;\r
+    }\r
+\r
+    bool Empty() const                                 {\r
+        return _size == 0;\r
+    }\r
+\r
+    T& operator[](int i)                               {\r
+        TIXMLASSERT( i>= 0 && i < _size );\r
+        return _mem[i];\r
+    }\r
+\r
+    const T& operator[](int i) const   {\r
+        TIXMLASSERT( i>= 0 && i < _size );\r
+        return _mem[i];\r
+    }\r
+\r
+    const T& PeekTop() const            {\r
+        TIXMLASSERT( _size > 0 );\r
+        return _mem[ _size - 1];\r
+    }\r
+\r
+    int Size() const                                   {\r
+        TIXMLASSERT( _size >= 0 );\r
+        return _size;\r
+    }\r
+\r
+    int Capacity() const                               {\r
+        TIXMLASSERT( _allocated >= INITIAL_SIZE );\r
+        return _allocated;\r
+    }\r
+\r
+    const T* Mem() const                               {\r
+        TIXMLASSERT( _mem );\r
+        return _mem;\r
+    }\r
+\r
+    T* Mem()                                                   {\r
+        TIXMLASSERT( _mem );\r
+        return _mem;\r
+    }\r
+\r
+private:\r
+    DynArray( const DynArray& ); // not supported\r
+    void operator=( const DynArray& ); // not supported\r
+\r
+    void EnsureCapacity( int cap ) {\r
+        TIXMLASSERT( cap > 0 );\r
+        if ( cap > _allocated ) {\r
+            TIXMLASSERT( cap <= INT_MAX / 2 );\r
+            int newAllocated = cap * 2;\r
+            T* newMem = new T[newAllocated];\r
+            memcpy( newMem, _mem, sizeof(T)*_size );   // warning: not using constructors, only works for PODs\r
+            if ( _mem != _pool ) {\r
+                delete [] _mem;\r
+            }\r
+            _mem = newMem;\r
+            _allocated = newAllocated;\r
+        }\r
+    }\r
+\r
+    T*  _mem;\r
+    T   _pool[INITIAL_SIZE];\r
+    int _allocated;            // objects allocated\r
+    int _size;                 // number objects in use\r
+};\r
+\r
+\r
+/*\r
+       Parent virtual class of a pool for fast allocation\r
+       and deallocation of objects.\r
+*/\r
+class MemPool\r
+{\r
+public:\r
+    MemPool() {}\r
+    virtual ~MemPool() {}\r
+\r
+    virtual int ItemSize() const = 0;\r
+    virtual void* Alloc() = 0;\r
+    virtual void Free( void* ) = 0;\r
+    virtual void SetTracked() = 0;\r
+    virtual void Clear() = 0;\r
+};\r
+\r
+\r
+/*\r
+       Template child class to create pools of the correct type.\r
+*/\r
+template< int SIZE >\r
+class MemPoolT : public MemPool\r
+{\r
+public:\r
+    MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)       {}\r
+    ~MemPoolT() {\r
+        Clear();\r
+    }\r
+    \r
+    void Clear() {\r
+        // Delete the blocks.\r
+        while( !_blockPtrs.Empty()) {\r
+            Block* b  = _blockPtrs.Pop();\r
+            delete b;\r
+        }\r
+        _root = 0;\r
+        _currentAllocs = 0;\r
+        _nAllocs = 0;\r
+        _maxAllocs = 0;\r
+        _nUntracked = 0;\r
+    }\r
+\r
+    virtual int ItemSize() const       {\r
+        return SIZE;\r
+    }\r
+    int CurrentAllocs() const          {\r
+        return _currentAllocs;\r
+    }\r
+\r
+    virtual void* Alloc() {\r
+        if ( !_root ) {\r
+            // Need a new block.\r
+            Block* block = new Block();\r
+            _blockPtrs.Push( block );\r
+\r
+            for( int i=0; i<COUNT-1; ++i ) {\r
+                block->chunk[i].next = &block->chunk[i+1];\r
+            }\r
+            block->chunk[COUNT-1].next = 0;\r
+            _root = block->chunk;\r
+        }\r
+        void* result = _root;\r
+        _root = _root->next;\r
+\r
+        ++_currentAllocs;\r
+        if ( _currentAllocs > _maxAllocs ) {\r
+            _maxAllocs = _currentAllocs;\r
+        }\r
+        _nAllocs++;\r
+        _nUntracked++;\r
+        return result;\r
+    }\r
+    \r
+    virtual void Free( void* mem ) {\r
+        if ( !mem ) {\r
+            return;\r
+        }\r
+        --_currentAllocs;\r
+        Chunk* chunk = static_cast<Chunk*>( mem );\r
+#ifdef DEBUG\r
+        memset( chunk, 0xfe, sizeof(Chunk) );\r
+#endif\r
+        chunk->next = _root;\r
+        _root = chunk;\r
+    }\r
+    void Trace( const char* name ) {\r
+        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",\r
+                name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );\r
+    }\r
+\r
+    void SetTracked() {\r
+        _nUntracked--;\r
+    }\r
+\r
+    int Untracked() const {\r
+        return _nUntracked;\r
+    }\r
+\r
+       // This number is perf sensitive. 4k seems like a good tradeoff on my machine.\r
+       // The test file is large, 170k.\r
+       // Release:             VS2010 gcc(no opt)\r
+       //              1k:             4000\r
+       //              2k:             4000\r
+       //              4k:             3900    21000\r
+       //              16k:    5200\r
+       //              32k:    4300\r
+       //              64k:    4000    21000\r
+    enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private\r
+\r
+private:\r
+    MemPoolT( const MemPoolT& ); // not supported\r
+    void operator=( const MemPoolT& ); // not supported\r
+\r
+    union Chunk {\r
+        Chunk*  next;\r
+        char    mem[SIZE];\r
+    };\r
+    struct Block {\r
+        Chunk chunk[COUNT];\r
+    };\r
+    DynArray< Block*, 10 > _blockPtrs;\r
+    Chunk* _root;\r
+\r
+    int _currentAllocs;\r
+    int _nAllocs;\r
+    int _maxAllocs;\r
+    int _nUntracked;\r
+};\r
+\r
+\r
+\r
+/**\r
+       Implements the interface to the "Visitor pattern" (see the Accept() method.)\r
+       If you call the Accept() method, it requires being passed a XMLVisitor\r
+       class to handle callbacks. For nodes that contain other nodes (Document, Element)\r
+       you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs\r
+       are simply called with Visit().\r
+\r
+       If you return 'true' from a Visit method, recursive parsing will continue. If you return\r
+       false, <b>no children of this node or its siblings</b> will be visited.\r
+\r
+       All flavors of Visit methods have a default implementation that returns 'true' (continue\r
+       visiting). You need to only override methods that are interesting to you.\r
+\r
+       Generally Accept() is called on the XMLDocument, although all nodes support visiting.\r
+\r
+       You should never change the document from a callback.\r
+\r
+       @sa XMLNode::Accept()\r
+*/\r
+class TINYXML2_LIB XMLVisitor\r
+{\r
+public:\r
+    virtual ~XMLVisitor() {}\r
+\r
+    /// Visit a document.\r
+    virtual bool VisitEnter( const XMLDocument& /*doc*/ )                      {\r
+        return true;\r
+    }\r
+    /// Visit a document.\r
+    virtual bool VisitExit( const XMLDocument& /*doc*/ )                       {\r
+        return true;\r
+    }\r
+\r
+    /// Visit an element.\r
+    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )   {\r
+        return true;\r
+    }\r
+    /// Visit an element.\r
+    virtual bool VisitExit( const XMLElement& /*element*/ )                    {\r
+        return true;\r
+    }\r
+\r
+    /// Visit a declaration.\r
+    virtual bool Visit( const XMLDeclaration& /*declaration*/ )                {\r
+        return true;\r
+    }\r
+    /// Visit a text node.\r
+    virtual bool Visit( const XMLText& /*text*/ )                                      {\r
+        return true;\r
+    }\r
+    /// Visit a comment node.\r
+    virtual bool Visit( const XMLComment& /*comment*/ )                                {\r
+        return true;\r
+    }\r
+    /// Visit an unknown node.\r
+    virtual bool Visit( const XMLUnknown& /*unknown*/ )                                {\r
+        return true;\r
+    }\r
+};\r
+\r
+// WARNING: must match XMLDocument::_errorNames[]\r
+enum XMLError {\r
+    XML_SUCCESS = 0,\r
+    XML_NO_ERROR = 0,\r
+    XML_NO_ATTRIBUTE,\r
+    XML_WRONG_ATTRIBUTE_TYPE,\r
+    XML_ERROR_FILE_NOT_FOUND,\r
+    XML_ERROR_FILE_COULD_NOT_BE_OPENED,\r
+    XML_ERROR_FILE_READ_ERROR,\r
+    XML_ERROR_ELEMENT_MISMATCH,\r
+    XML_ERROR_PARSING_ELEMENT,\r
+    XML_ERROR_PARSING_ATTRIBUTE,\r
+    XML_ERROR_IDENTIFYING_TAG,\r
+    XML_ERROR_PARSING_TEXT,\r
+    XML_ERROR_PARSING_CDATA,\r
+    XML_ERROR_PARSING_COMMENT,\r
+    XML_ERROR_PARSING_DECLARATION,\r
+    XML_ERROR_PARSING_UNKNOWN,\r
+    XML_ERROR_EMPTY_DOCUMENT,\r
+    XML_ERROR_MISMATCHED_ELEMENT,\r
+    XML_ERROR_PARSING,\r
+    XML_CAN_NOT_CONVERT_TEXT,\r
+    XML_NO_TEXT_NODE,\r
+\r
+       XML_ERROR_COUNT\r
+};\r
+\r
+\r
+/*\r
+       Utility functionality.\r
+*/\r
+class XMLUtil\r
+{\r
+public:\r
+    static const char* SkipWhiteSpace( const char* p ) {\r
+        TIXMLASSERT( p );\r
+        while( IsWhiteSpace(*p) ) {\r
+            ++p;\r
+        }\r
+        TIXMLASSERT( p );\r
+        return p;\r
+    }\r
+    static char* SkipWhiteSpace( char* p )                             {\r
+        return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );\r
+    }\r
+\r
+    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't\r
+    // correct, but simple, and usually works.\r
+    static bool IsWhiteSpace( char p )                                 {\r
+        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );\r
+    }\r
+    \r
+    inline static bool IsNameStartChar( unsigned char ch ) {\r
+        if ( ch >= 128 ) {\r
+            // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()\r
+            return true;\r
+        }\r
+        if ( isalpha( ch ) ) {\r
+            return true;\r
+        }\r
+        return ch == ':' || ch == '_';\r
+    }\r
+    \r
+    inline static bool IsNameChar( unsigned char ch ) {\r
+        return IsNameStartChar( ch )\r
+               || isdigit( ch )\r
+               || ch == '.'\r
+               || ch == '-';\r
+    }\r
+\r
+    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {\r
+        if ( p == q ) {\r
+            return true;\r
+        }\r
+        return strncmp( p, q, nChar ) == 0;\r
+    }\r
+    \r
+    inline static bool IsUTF8Continuation( char p ) {\r
+        return ( p & 0x80 ) != 0;\r
+    }\r
+\r
+    static const char* ReadBOM( const char* p, bool* hasBOM );\r
+    // p is the starting location,\r
+    // the UTF-8 value of the entity will be placed in value, and length filled in.\r
+    static const char* GetCharacterRef( const char* p, char* value, int* length );\r
+    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );\r
+\r
+    // converts primitive types to strings\r
+    static void ToStr( int v, char* buffer, int bufferSize );\r
+    static void ToStr( unsigned v, char* buffer, int bufferSize );\r
+    static void ToStr( bool v, char* buffer, int bufferSize );\r
+    static void ToStr( float v, char* buffer, int bufferSize );\r
+    static void ToStr( double v, char* buffer, int bufferSize );\r
+\r
+    // converts strings to primitive types\r
+    static bool        ToInt( const char* str, int* value );\r
+    static bool ToUnsigned( const char* str, unsigned* value );\r
+    static bool        ToBool( const char* str, bool* value );\r
+    static bool        ToFloat( const char* str, float* value );\r
+    static bool ToDouble( const char* str, double* value );\r
+};\r
+\r
+\r
+/** XMLNode is a base class for every object that is in the\r
+       XML Document Object Model (DOM), except XMLAttributes.\r
+       Nodes have siblings, a parent, and children which can\r
+       be navigated. A node is always in a XMLDocument.\r
+       The type of a XMLNode can be queried, and it can\r
+       be cast to its more defined type.\r
+\r
+       A XMLDocument allocates memory for all its Nodes.\r
+       When the XMLDocument gets deleted, all its Nodes\r
+       will also be deleted.\r
+\r
+       @verbatim\r
+       A Document can contain: Element (container or leaf)\r
+                                                       Comment (leaf)\r
+                                                       Unknown (leaf)\r
+                                                       Declaration( leaf )\r
+\r
+       An Element can contain: Element (container or leaf)\r
+                                                       Text    (leaf)\r
+                                                       Attributes (not on tree)\r
+                                                       Comment (leaf)\r
+                                                       Unknown (leaf)\r
+\r
+       @endverbatim\r
+*/\r
+class TINYXML2_LIB XMLNode\r
+{\r
+    friend class XMLDocument;\r
+    friend class XMLElement;\r
+public:\r
+\r
+    /// Get the XMLDocument that owns this XMLNode.\r
+    const XMLDocument* GetDocument() const     {\r
+        TIXMLASSERT( _document );\r
+        return _document;\r
+    }\r
+    /// Get the XMLDocument that owns this XMLNode.\r
+    XMLDocument* GetDocument()                         {\r
+        TIXMLASSERT( _document );\r
+        return _document;\r
+    }\r
+\r
+    /// Safely cast to an Element, or null.\r
+    virtual XMLElement*                ToElement()             {\r
+        return 0;\r
+    }\r
+    /// Safely cast to Text, or null.\r
+    virtual XMLText*           ToText()                {\r
+        return 0;\r
+    }\r
+    /// Safely cast to a Comment, or null.\r
+    virtual XMLComment*                ToComment()             {\r
+        return 0;\r
+    }\r
+    /// Safely cast to a Document, or null.\r
+    virtual XMLDocument*       ToDocument()    {\r
+        return 0;\r
+    }\r
+    /// Safely cast to a Declaration, or null.\r
+    virtual XMLDeclaration*    ToDeclaration() {\r
+        return 0;\r
+    }\r
+    /// Safely cast to an Unknown, or null.\r
+    virtual XMLUnknown*                ToUnknown()             {\r
+        return 0;\r
+    }\r
+\r
+    virtual const XMLElement*          ToElement() const               {\r
+        return 0;\r
+    }\r
+    virtual const XMLText*                     ToText() const                  {\r
+        return 0;\r
+    }\r
+    virtual const XMLComment*          ToComment() const               {\r
+        return 0;\r
+    }\r
+    virtual const XMLDocument*         ToDocument() const              {\r
+        return 0;\r
+    }\r
+    virtual const XMLDeclaration*      ToDeclaration() const   {\r
+        return 0;\r
+    }\r
+    virtual const XMLUnknown*          ToUnknown() const               {\r
+        return 0;\r
+    }\r
+\r
+    /** The meaning of 'value' changes for the specific type.\r
+       @verbatim\r
+       Document:       empty (NULL is returned, not an empty string)\r
+       Element:        name of the element\r
+       Comment:        the comment text\r
+       Unknown:        the tag contents\r
+       Text:           the text string\r
+       @endverbatim\r
+    */\r
+    const char* Value() const;\r
+\r
+    /** Set the Value of an XML node.\r
+       @sa Value()\r
+    */\r
+    void SetValue( const char* val, bool staticMem=false );\r
+\r
+    /// Get the parent of this node on the DOM.\r
+    const XMLNode*     Parent() const                  {\r
+        return _parent;\r
+    }\r
+\r
+    XMLNode* Parent()                                          {\r
+        return _parent;\r
+    }\r
+\r
+    /// Returns true if this node has no children.\r
+    bool NoChildren() const                                    {\r
+        return !_firstChild;\r
+    }\r
+\r
+    /// Get the first child node, or null if none exists.\r
+    const XMLNode*  FirstChild() const         {\r
+        return _firstChild;\r
+    }\r
+\r
+    XMLNode*           FirstChild()                    {\r
+        return _firstChild;\r
+    }\r
+\r
+    /** Get the first child element, or optionally the first child\r
+        element with the specified name.\r
+    */\r
+    const XMLElement* FirstChildElement( const char* name = 0 ) const;\r
+\r
+    XMLElement* FirstChildElement( const char* name = 0 )      {\r
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));\r
+    }\r
+\r
+    /// Get the last child node, or null if none exists.\r
+    const XMLNode*     LastChild() const                                               {\r
+        return _lastChild;\r
+    }\r
+\r
+    XMLNode*           LastChild()                                                             {\r
+        return _lastChild;\r
+    }\r
+\r
+    /** Get the last child element or optionally the last child\r
+        element with the specified name.\r
+    */\r
+    const XMLElement* LastChildElement( const char* name = 0 ) const;\r
+\r
+    XMLElement* LastChildElement( const char* name = 0 )       {\r
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );\r
+    }\r
+\r
+    /// Get the previous (left) sibling node of this node.\r
+    const XMLNode*     PreviousSibling() const                                 {\r
+        return _prev;\r
+    }\r
+\r
+    XMLNode*   PreviousSibling()                                                       {\r
+        return _prev;\r
+    }\r
+\r
+    /// Get the previous (left) sibling element of this node, with an optionally supplied name.\r
+    const XMLElement*  PreviousSiblingElement( const char* name = 0 ) const ;\r
+\r
+    XMLElement*        PreviousSiblingElement( const char* name = 0 ) {\r
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );\r
+    }\r
+\r
+    /// Get the next (right) sibling node of this node.\r
+    const XMLNode*     NextSibling() const                                             {\r
+        return _next;\r
+    }\r
+\r
+    XMLNode*   NextSibling()                                                           {\r
+        return _next;\r
+    }\r
+\r
+    /// Get the next (right) sibling element of this node, with an optionally supplied name.\r
+    const XMLElement*  NextSiblingElement( const char* name = 0 ) const;\r
+\r
+    XMLElement*        NextSiblingElement( const char* name = 0 )      {\r
+        return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );\r
+    }\r
+\r
+    /**\r
+       Add a child node as the last (right) child.\r
+               If the child node is already part of the document,\r
+               it is moved from its old location to the new location.\r
+               Returns the addThis argument or 0 if the node does not\r
+               belong to the same document.\r
+    */\r
+    XMLNode* InsertEndChild( XMLNode* addThis );\r
+\r
+    XMLNode* LinkEndChild( XMLNode* addThis )  {\r
+        return InsertEndChild( addThis );\r
+    }\r
+    /**\r
+       Add a child node as the first (left) child.\r
+               If the child node is already part of the document,\r
+               it is moved from its old location to the new location.\r
+               Returns the addThis argument or 0 if the node does not\r
+               belong to the same document.\r
+    */\r
+    XMLNode* InsertFirstChild( XMLNode* addThis );\r
+    /**\r
+       Add a node after the specified child node.\r
+               If the child node is already part of the document,\r
+               it is moved from its old location to the new location.\r
+               Returns the addThis argument or 0 if the afterThis node\r
+               is not a child of this node, or if the node does not\r
+               belong to the same document.\r
+    */\r
+    XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );\r
+\r
+    /**\r
+       Delete all the children of this node.\r
+    */\r
+    void DeleteChildren();\r
+\r
+    /**\r
+       Delete a child of this node.\r
+    */\r
+    void DeleteChild( XMLNode* node );\r
+\r
+    /**\r
+       Make a copy of this node, but not its children.\r
+       You may pass in a Document pointer that will be\r
+       the owner of the new Node. If the 'document' is\r
+       null, then the node returned will be allocated\r
+       from the current Document. (this->GetDocument())\r
+\r
+       Note: if called on a XMLDocument, this will return null.\r
+    */\r
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;\r
+\r
+    /**\r
+       Test if 2 nodes are the same, but don't test children.\r
+       The 2 nodes do not need to be in the same Document.\r
+\r
+       Note: if called on a XMLDocument, this will return false.\r
+    */\r
+    virtual bool ShallowEqual( const XMLNode* compare ) const = 0;\r
+\r
+    /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the\r
+       XML tree will be conditionally visited and the host will be called back\r
+       via the XMLVisitor interface.\r
+\r
+       This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse\r
+       the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this\r
+       interface versus any other.)\r
+\r
+       The interface has been based on ideas from:\r
+\r
+       - http://www.saxproject.org/\r
+       - http://c2.com/cgi/wiki?HierarchicalVisitorPattern\r
+\r
+       Which are both good references for "visiting".\r
+\r
+       An example of using Accept():\r
+       @verbatim\r
+       XMLPrinter printer;\r
+       tinyxmlDoc.Accept( &printer );\r
+       const char* xmlcstr = printer.CStr();\r
+       @endverbatim\r
+    */\r
+    virtual bool Accept( XMLVisitor* visitor ) const = 0;\r
+\r
+protected:\r
+    XMLNode( XMLDocument* );\r
+    virtual ~XMLNode();\r
+\r
+    virtual char* ParseDeep( char*, StrPair* );\r
+\r
+    XMLDocument*       _document;\r
+    XMLNode*           _parent;\r
+    mutable StrPair    _value;\r
+\r
+    XMLNode*           _firstChild;\r
+    XMLNode*           _lastChild;\r
+\r
+    XMLNode*           _prev;\r
+    XMLNode*           _next;\r
+\r
+private:\r
+    MemPool*           _memPool;\r
+    void Unlink( XMLNode* child );\r
+    static void DeleteNode( XMLNode* node );\r
+    void InsertChildPreamble( XMLNode* insertThis ) const;\r
+\r
+    XMLNode( const XMLNode& ); // not supported\r
+    XMLNode& operator=( const XMLNode& );      // not supported\r
+};\r
+\r
+\r
+/** XML text.\r
+\r
+       Note that a text node can have child element nodes, for example:\r
+       @verbatim\r
+       <root>This is <b>bold</b></root>\r
+       @endverbatim\r
+\r
+       A text node can have 2 ways to output the next. "normal" output\r
+       and CDATA. It will default to the mode it was parsed from the XML file and\r
+       you generally want to leave it alone, but you can change the output mode with\r
+       SetCData() and query it with CData().\r
+*/\r
+class TINYXML2_LIB XMLText : public XMLNode\r
+{\r
+    friend class XMLBase;\r
+    friend class XMLDocument;\r
+public:\r
+    virtual bool Accept( XMLVisitor* visitor ) const;\r
+\r
+    virtual XMLText* ToText()                  {\r
+        return this;\r
+    }\r
+    virtual const XMLText* ToText() const      {\r
+        return this;\r
+    }\r
+\r
+    /// Declare whether this should be CDATA or standard text.\r
+    void SetCData( bool isCData )                      {\r
+        _isCData = isCData;\r
+    }\r
+    /// Returns true if this is a CDATA text element.\r
+    bool CData() const                                         {\r
+        return _isCData;\r
+    }\r
+\r
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
+    virtual bool ShallowEqual( const XMLNode* compare ) const;\r
+\r
+protected:\r
+    XMLText( XMLDocument* doc )        : XMLNode( doc ), _isCData( false )     {}\r
+    virtual ~XMLText()                                                                                         {}\r
+\r
+    char* ParseDeep( char*, StrPair* endTag );\r
+\r
+private:\r
+    bool _isCData;\r
+\r
+    XMLText( const XMLText& ); // not supported\r
+    XMLText& operator=( const XMLText& );      // not supported\r
+};\r
+\r
+\r
+/** An XML Comment. */\r
+class TINYXML2_LIB XMLComment : public XMLNode\r
+{\r
+    friend class XMLDocument;\r
+public:\r
+    virtual XMLComment*        ToComment()                                     {\r
+        return this;\r
+    }\r
+    virtual const XMLComment* ToComment() const                {\r
+        return this;\r
+    }\r
+\r
+    virtual bool Accept( XMLVisitor* visitor ) const;\r
+\r
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
+    virtual bool ShallowEqual( const XMLNode* compare ) const;\r
+\r
+protected:\r
+    XMLComment( XMLDocument* doc );\r
+    virtual ~XMLComment();\r
+\r
+    char* ParseDeep( char*, StrPair* endTag );\r
+\r
+private:\r
+    XMLComment( const XMLComment& );   // not supported\r
+    XMLComment& operator=( const XMLComment& );        // not supported\r
+};\r
+\r
+\r
+/** In correct XML the declaration is the first entry in the file.\r
+       @verbatim\r
+               <?xml version="1.0" standalone="yes"?>\r
+       @endverbatim\r
+\r
+       TinyXML-2 will happily read or write files without a declaration,\r
+       however.\r
+\r
+       The text of the declaration isn't interpreted. It is parsed\r
+       and written as a string.\r
+*/\r
+class TINYXML2_LIB XMLDeclaration : public XMLNode\r
+{\r
+    friend class XMLDocument;\r
+public:\r
+    virtual XMLDeclaration*    ToDeclaration()                                 {\r
+        return this;\r
+    }\r
+    virtual const XMLDeclaration* ToDeclaration() const                {\r
+        return this;\r
+    }\r
+\r
+    virtual bool Accept( XMLVisitor* visitor ) const;\r
+\r
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
+    virtual bool ShallowEqual( const XMLNode* compare ) const;\r
+\r
+protected:\r
+    XMLDeclaration( XMLDocument* doc );\r
+    virtual ~XMLDeclaration();\r
+\r
+    char* ParseDeep( char*, StrPair* endTag );\r
+\r
+private:\r
+    XMLDeclaration( const XMLDeclaration& );   // not supported\r
+    XMLDeclaration& operator=( const XMLDeclaration& );        // not supported\r
+};\r
+\r
+\r
+/** Any tag that TinyXML-2 doesn't recognize is saved as an\r
+       unknown. It is a tag of text, but should not be modified.\r
+       It will be written back to the XML, unchanged, when the file\r
+       is saved.\r
+\r
+       DTD tags get thrown into XMLUnknowns.\r
+*/\r
+class TINYXML2_LIB XMLUnknown : public XMLNode\r
+{\r
+    friend class XMLDocument;\r
+public:\r
+    virtual XMLUnknown*        ToUnknown()                                     {\r
+        return this;\r
+    }\r
+    virtual const XMLUnknown* ToUnknown() const                {\r
+        return this;\r
+    }\r
+\r
+    virtual bool Accept( XMLVisitor* visitor ) const;\r
+\r
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
+    virtual bool ShallowEqual( const XMLNode* compare ) const;\r
+\r
+protected:\r
+    XMLUnknown( XMLDocument* doc );\r
+    virtual ~XMLUnknown();\r
+\r
+    char* ParseDeep( char*, StrPair* endTag );\r
+\r
+private:\r
+    XMLUnknown( const XMLUnknown& );   // not supported\r
+    XMLUnknown& operator=( const XMLUnknown& );        // not supported\r
+};\r
+\r
+\r
+\r
+/** An attribute is a name-value pair. Elements have an arbitrary\r
+       number of attributes, each with a unique name.\r
+\r
+       @note The attributes are not XMLNodes. You may only query the\r
+       Next() attribute in a list.\r
+*/\r
+class TINYXML2_LIB XMLAttribute\r
+{\r
+    friend class XMLElement;\r
+public:\r
+    /// The name of the attribute.\r
+    const char* Name() const;\r
+\r
+    /// The value of the attribute.\r
+    const char* Value() const;\r
+\r
+    /// The next attribute in the list.\r
+    const XMLAttribute* Next() const {\r
+        return _next;\r
+    }\r
+\r
+    /** IntValue interprets the attribute as an integer, and returns the value.\r
+        If the value isn't an integer, 0 will be returned. There is no error checking;\r
+       use QueryIntValue() if you need error checking.\r
+    */\r
+    int                 IntValue() const                               {\r
+        int i=0;\r
+        QueryIntValue( &i );\r
+        return i;\r
+    }\r
+    /// Query as an unsigned integer. See IntValue()\r
+    unsigned UnsignedValue() const                     {\r
+        unsigned i=0;\r
+        QueryUnsignedValue( &i );\r
+        return i;\r
+    }\r
+    /// Query as a boolean. See IntValue()\r
+    bool        BoolValue() const                              {\r
+        bool b=false;\r
+        QueryBoolValue( &b );\r
+        return b;\r
+    }\r
+    /// Query as a double. See IntValue()\r
+    double      DoubleValue() const                    {\r
+        double d=0;\r
+        QueryDoubleValue( &d );\r
+        return d;\r
+    }\r
+    /// Query as a float. See IntValue()\r
+    float       FloatValue() const                             {\r
+        float f=0;\r
+        QueryFloatValue( &f );\r
+        return f;\r
+    }\r
+\r
+    /** QueryIntValue interprets the attribute as an integer, and returns the value\r
+       in the provided parameter. The function will return XML_NO_ERROR on success,\r
+       and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.\r
+    */\r
+    XMLError QueryIntValue( int* value ) const;\r
+    /// See QueryIntValue\r
+    XMLError QueryUnsignedValue( unsigned int* value ) const;\r
+    /// See QueryIntValue\r
+    XMLError QueryBoolValue( bool* value ) const;\r
+    /// See QueryIntValue\r
+    XMLError QueryDoubleValue( double* value ) const;\r
+    /// See QueryIntValue\r
+    XMLError QueryFloatValue( float* value ) const;\r
+\r
+    /// Set the attribute to a string value.\r
+    void SetAttribute( const char* value );\r
+    /// Set the attribute to value.\r
+    void SetAttribute( int value );\r
+    /// Set the attribute to value.\r
+    void SetAttribute( unsigned value );\r
+    /// Set the attribute to value.\r
+    void SetAttribute( bool value );\r
+    /// Set the attribute to value.\r
+    void SetAttribute( double value );\r
+    /// Set the attribute to value.\r
+    void SetAttribute( float value );\r
+\r
+private:\r
+    enum { BUF_SIZE = 200 };\r
+\r
+    XMLAttribute() : _next( 0 ), _memPool( 0 ) {}\r
+    virtual ~XMLAttribute()    {}\r
+\r
+    XMLAttribute( const XMLAttribute& );       // not supported\r
+    void operator=( const XMLAttribute& );     // not supported\r
+    void SetName( const char* name );\r
+\r
+    char* ParseDeep( char* p, bool processEntities );\r
+\r
+    mutable StrPair _name;\r
+    mutable StrPair _value;\r
+    XMLAttribute*   _next;\r
+    MemPool*        _memPool;\r
+};\r
+\r
+\r
+/** The element is a container class. It has a value, the element name,\r
+       and can contain other elements, text, comments, and unknowns.\r
+       Elements also contain an arbitrary number of attributes.\r
+*/\r
+class TINYXML2_LIB XMLElement : public XMLNode\r
+{\r
+    friend class XMLBase;\r
+    friend class XMLDocument;\r
+public:\r
+    /// Get the name of an element (which is the Value() of the node.)\r
+    const char* Name() const           {\r
+        return Value();\r
+    }\r
+    /// Set the name of the element.\r
+    void SetName( const char* str, bool staticMem=false )      {\r
+        SetValue( str, staticMem );\r
+    }\r
+\r
+    virtual XMLElement* ToElement()                            {\r
+        return this;\r
+    }\r
+    virtual const XMLElement* ToElement() const {\r
+        return this;\r
+    }\r
+    virtual bool Accept( XMLVisitor* visitor ) const;\r
+\r
+    /** Given an attribute name, Attribute() returns the value\r
+       for the attribute of that name, or null if none\r
+       exists. For example:\r
+\r
+       @verbatim\r
+       const char* value = ele->Attribute( "foo" );\r
+       @endverbatim\r
+\r
+       The 'value' parameter is normally null. However, if specified,\r
+       the attribute will only be returned if the 'name' and 'value'\r
+       match. This allow you to write code:\r
+\r
+       @verbatim\r
+       if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();\r
+       @endverbatim\r
+\r
+       rather than:\r
+       @verbatim\r
+       if ( ele->Attribute( "foo" ) ) {\r
+               if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();\r
+       }\r
+       @endverbatim\r
+    */\r
+    const char* Attribute( const char* name, const char* value=0 ) const;\r
+\r
+    /** Given an attribute name, IntAttribute() returns the value\r
+       of the attribute interpreted as an integer. 0 will be\r
+       returned if there is an error. For a method with error\r
+       checking, see QueryIntAttribute()\r
+    */\r
+    int                 IntAttribute( const char* name ) const         {\r
+        int i=0;\r
+        QueryIntAttribute( name, &i );\r
+        return i;\r
+    }\r
+    /// See IntAttribute()\r
+    unsigned UnsignedAttribute( const char* name ) const {\r
+        unsigned i=0;\r
+        QueryUnsignedAttribute( name, &i );\r
+        return i;\r
+    }\r
+    /// See IntAttribute()\r
+    bool        BoolAttribute( const char* name ) const        {\r
+        bool b=false;\r
+        QueryBoolAttribute( name, &b );\r
+        return b;\r
+    }\r
+    /// See IntAttribute()\r
+    double      DoubleAttribute( const char* name ) const      {\r
+        double d=0;\r
+        QueryDoubleAttribute( name, &d );\r
+        return d;\r
+    }\r
+    /// See IntAttribute()\r
+    float       FloatAttribute( const char* name ) const       {\r
+        float f=0;\r
+        QueryFloatAttribute( name, &f );\r
+        return f;\r
+    }\r
+\r
+    /** Given an attribute name, QueryIntAttribute() returns\r
+       XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion\r
+       can't be performed, or XML_NO_ATTRIBUTE if the attribute\r
+       doesn't exist. If successful, the result of the conversion\r
+       will be written to 'value'. If not successful, nothing will\r
+       be written to 'value'. This allows you to provide default\r
+       value:\r
+\r
+       @verbatim\r
+       int value = 10;\r
+       QueryIntAttribute( "foo", &value );             // if "foo" isn't found, value will still be 10\r
+       @endverbatim\r
+    */\r
+    XMLError QueryIntAttribute( const char* name, int* value ) const                           {\r
+        const XMLAttribute* a = FindAttribute( name );\r
+        if ( !a ) {\r
+            return XML_NO_ATTRIBUTE;\r
+        }\r
+        return a->QueryIntValue( value );\r
+    }\r
+    /// See QueryIntAttribute()\r
+    XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const     {\r
+        const XMLAttribute* a = FindAttribute( name );\r
+        if ( !a ) {\r
+            return XML_NO_ATTRIBUTE;\r
+        }\r
+        return a->QueryUnsignedValue( value );\r
+    }\r
+    /// See QueryIntAttribute()\r
+    XMLError QueryBoolAttribute( const char* name, bool* value ) const                         {\r
+        const XMLAttribute* a = FindAttribute( name );\r
+        if ( !a ) {\r
+            return XML_NO_ATTRIBUTE;\r
+        }\r
+        return a->QueryBoolValue( value );\r
+    }\r
+    /// See QueryIntAttribute()\r
+    XMLError QueryDoubleAttribute( const char* name, double* value ) const                     {\r
+        const XMLAttribute* a = FindAttribute( name );\r
+        if ( !a ) {\r
+            return XML_NO_ATTRIBUTE;\r
+        }\r
+        return a->QueryDoubleValue( value );\r
+    }\r
+    /// See QueryIntAttribute()\r
+    XMLError QueryFloatAttribute( const char* name, float* value ) const                       {\r
+        const XMLAttribute* a = FindAttribute( name );\r
+        if ( !a ) {\r
+            return XML_NO_ATTRIBUTE;\r
+        }\r
+        return a->QueryFloatValue( value );\r
+    }\r
+\r
+       \r
+    /** Given an attribute name, QueryAttribute() returns\r
+       XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion\r
+       can't be performed, or XML_NO_ATTRIBUTE if the attribute\r
+       doesn't exist. It is overloaded for the primitive types,\r
+               and is a generally more convenient replacement of\r
+               QueryIntAttribute() and related functions.\r
+               \r
+               If successful, the result of the conversion\r
+       will be written to 'value'. If not successful, nothing will\r
+       be written to 'value'. This allows you to provide default\r
+       value:\r
+\r
+       @verbatim\r
+       int value = 10;\r
+       QueryAttribute( "foo", &value );                // if "foo" isn't found, value will still be 10\r
+       @endverbatim\r
+    */\r
+       int QueryAttribute( const char* name, int* value ) const {\r
+               return QueryIntAttribute( name, value );\r
+       }\r
+\r
+       int QueryAttribute( const char* name, unsigned int* value ) const {\r
+               return QueryUnsignedAttribute( name, value );\r
+       }\r
+\r
+       int QueryAttribute( const char* name, bool* value ) const {\r
+               return QueryBoolAttribute( name, value );\r
+       }\r
+\r
+       int QueryAttribute( const char* name, double* value ) const {\r
+               return QueryDoubleAttribute( name, value );\r
+       }\r
+\r
+       int QueryAttribute( const char* name, float* value ) const {\r
+               return QueryFloatAttribute( name, value );\r
+       }\r
+\r
+       /// Sets the named attribute to value.\r
+    void SetAttribute( const char* name, const char* value )   {\r
+        XMLAttribute* a = FindOrCreateAttribute( name );\r
+        a->SetAttribute( value );\r
+    }\r
+    /// Sets the named attribute to value.\r
+    void SetAttribute( const char* name, int value )                   {\r
+        XMLAttribute* a = FindOrCreateAttribute( name );\r
+        a->SetAttribute( value );\r
+    }\r
+    /// Sets the named attribute to value.\r
+    void SetAttribute( const char* name, unsigned value )              {\r
+        XMLAttribute* a = FindOrCreateAttribute( name );\r
+        a->SetAttribute( value );\r
+    }\r
+    /// Sets the named attribute to value.\r
+    void SetAttribute( const char* name, bool value )                  {\r
+        XMLAttribute* a = FindOrCreateAttribute( name );\r
+        a->SetAttribute( value );\r
+    }\r
+    /// Sets the named attribute to value.\r
+    void SetAttribute( const char* name, double value )                {\r
+        XMLAttribute* a = FindOrCreateAttribute( name );\r
+        a->SetAttribute( value );\r
+    }\r
+    /// Sets the named attribute to value.\r
+    void SetAttribute( const char* name, float value )         {\r
+        XMLAttribute* a = FindOrCreateAttribute( name );\r
+        a->SetAttribute( value );\r
+    }\r
+\r
+    /**\r
+       Delete an attribute.\r
+    */\r
+    void DeleteAttribute( const char* name );\r
+\r
+    /// Return the first attribute in the list.\r
+    const XMLAttribute* FirstAttribute() const {\r
+        return _rootAttribute;\r
+    }\r
+    /// Query a specific attribute in the list.\r
+    const XMLAttribute* FindAttribute( const char* name ) const;\r
+\r
+    /** Convenience function for easy access to the text inside an element. Although easy\r
+       and concise, GetText() is limited compared to getting the XMLText child\r
+       and accessing it directly.\r
+\r
+       If the first child of 'this' is a XMLText, the GetText()\r
+       returns the character string of the Text node, else null is returned.\r
+\r
+       This is a convenient method for getting the text of simple contained text:\r
+       @verbatim\r
+       <foo>This is text</foo>\r
+               const char* str = fooElement->GetText();\r
+       @endverbatim\r
+\r
+       'str' will be a pointer to "This is text".\r
+\r
+       Note that this function can be misleading. If the element foo was created from\r
+       this XML:\r
+       @verbatim\r
+               <foo><b>This is text</b></foo>\r
+       @endverbatim\r
+\r
+       then the value of str would be null. The first child node isn't a text node, it is\r
+       another element. From this XML:\r
+       @verbatim\r
+               <foo>This is <b>text</b></foo>\r
+       @endverbatim\r
+       GetText() will return "This is ".\r
+    */\r
+    const char* GetText() const;\r
+\r
+    /** Convenience function for easy access to the text inside an element. Although easy\r
+       and concise, SetText() is limited compared to creating an XMLText child\r
+       and mutating it directly.\r
+\r
+       If the first child of 'this' is a XMLText, SetText() sets its value to\r
+               the given string, otherwise it will create a first child that is an XMLText.\r
+\r
+       This is a convenient method for setting the text of simple contained text:\r
+       @verbatim\r
+       <foo>This is text</foo>\r
+               fooElement->SetText( "Hullaballoo!" );\r
+       <foo>Hullaballoo!</foo>\r
+               @endverbatim\r
+\r
+       Note that this function can be misleading. If the element foo was created from\r
+       this XML:\r
+       @verbatim\r
+               <foo><b>This is text</b></foo>\r
+       @endverbatim\r
+\r
+       then it will not change "This is text", but rather prefix it with a text element:\r
+       @verbatim\r
+               <foo>Hullaballoo!<b>This is text</b></foo>\r
+       @endverbatim\r
+               \r
+               For this XML:\r
+       @verbatim\r
+               <foo />\r
+       @endverbatim\r
+       SetText() will generate\r
+       @verbatim\r
+               <foo>Hullaballoo!</foo>\r
+       @endverbatim\r
+    */\r
+       void SetText( const char* inText );\r
+    /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
+    void SetText( int value );\r
+    /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
+    void SetText( unsigned value );  \r
+    /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
+    void SetText( bool value );  \r
+    /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
+    void SetText( double value );  \r
+    /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
+    void SetText( float value );  \r
+\r
+    /**\r
+       Convenience method to query the value of a child text node. This is probably best\r
+       shown by example. Given you have a document is this form:\r
+       @verbatim\r
+               <point>\r
+                       <x>1</x>\r
+                       <y>1.4</y>\r
+               </point>\r
+       @endverbatim\r
+\r
+       The QueryIntText() and similar functions provide a safe and easier way to get to the\r
+       "value" of x and y.\r
+\r
+       @verbatim\r
+               int x = 0;\r
+               float y = 0;    // types of x and y are contrived for example\r
+               const XMLElement* xElement = pointElement->FirstChildElement( "x" );\r
+               const XMLElement* yElement = pointElement->FirstChildElement( "y" );\r
+               xElement->QueryIntText( &x );\r
+               yElement->QueryFloatText( &y );\r
+       @endverbatim\r
+\r
+       @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted\r
+                        to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.\r
+\r
+    */\r
+    XMLError QueryIntText( int* ival ) const;\r
+    /// See QueryIntText()\r
+    XMLError QueryUnsignedText( unsigned* uval ) const;\r
+    /// See QueryIntText()\r
+    XMLError QueryBoolText( bool* bval ) const;\r
+    /// See QueryIntText()\r
+    XMLError QueryDoubleText( double* dval ) const;\r
+    /// See QueryIntText()\r
+    XMLError QueryFloatText( float* fval ) const;\r
+\r
+    // internal:\r
+    enum {\r
+        OPEN,          // <foo>\r
+        CLOSED,                // <foo/>\r
+        CLOSING                // </foo>\r
+    };\r
+    int ClosingType() const {\r
+        return _closingType;\r
+    }\r
+    virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
+    virtual bool ShallowEqual( const XMLNode* compare ) const;\r
+\r
+protected:\r
+    char* ParseDeep( char* p, StrPair* endTag );\r
+\r
+private:\r
+    XMLElement( XMLDocument* doc );\r
+    virtual ~XMLElement();\r
+    XMLElement( const XMLElement& );   // not supported\r
+    void operator=( const XMLElement& );       // not supported\r
+\r
+    XMLAttribute* FindAttribute( const char* name ) {\r
+        return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));\r
+    }\r
+    XMLAttribute* FindOrCreateAttribute( const char* name );\r
+    //void LinkAttribute( XMLAttribute* attrib );\r
+    char* ParseAttributes( char* p );\r
+    static void DeleteAttribute( XMLAttribute* attribute );\r
+\r
+    enum { BUF_SIZE = 200 };\r
+    int _closingType;\r
+    // The attribute list is ordered; there is no 'lastAttribute'\r
+    // because the list needs to be scanned for dupes before adding\r
+    // a new attribute.\r
+    XMLAttribute* _rootAttribute;\r
+};\r
+\r
+\r
+enum Whitespace {\r
+    PRESERVE_WHITESPACE,\r
+    COLLAPSE_WHITESPACE\r
+};\r
+\r
+\r
+/** A Document binds together all the functionality.\r
+       It can be saved, loaded, and printed to the screen.\r
+       All Nodes are connected and allocated to a Document.\r
+       If the Document is deleted, all its Nodes are also deleted.\r
+*/\r
+class TINYXML2_LIB XMLDocument : public XMLNode\r
+{\r
+    friend class XMLElement;\r
+public:\r
+    /// constructor\r
+    XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );\r
+    ~XMLDocument();\r
+\r
+    virtual XMLDocument* ToDocument()                          {\r
+        TIXMLASSERT( this == _document );\r
+        return this;\r
+    }\r
+    virtual const XMLDocument* ToDocument() const      {\r
+        TIXMLASSERT( this == _document );\r
+        return this;\r
+    }\r
+\r
+    /**\r
+       Parse an XML file from a character string.\r
+       Returns XML_NO_ERROR (0) on success, or\r
+       an errorID.\r
+\r
+       You may optionally pass in the 'nBytes', which is\r
+       the number of bytes which will be parsed. If not\r
+       specified, TinyXML-2 will assume 'xml' points to a\r
+       null terminated string.\r
+    */\r
+    XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );\r
+\r
+    /**\r
+       Load an XML file from disk.\r
+       Returns XML_NO_ERROR (0) on success, or\r
+       an errorID.\r
+    */\r
+    XMLError LoadFile( const char* filename );\r
+\r
+    /**\r
+       Load an XML file from disk. You are responsible\r
+       for providing and closing the FILE*. \r
+     \r
+        NOTE: The file should be opened as binary ("rb")\r
+        not text in order for TinyXML-2 to correctly\r
+        do newline normalization.\r
+\r
+       Returns XML_NO_ERROR (0) on success, or\r
+       an errorID.\r
+    */\r
+    XMLError LoadFile( FILE* );\r
+\r
+    /**\r
+       Save the XML file to disk.\r
+       Returns XML_NO_ERROR (0) on success, or\r
+       an errorID.\r
+    */\r
+    XMLError SaveFile( const char* filename, bool compact = false );\r
+\r
+    /**\r
+       Save the XML file to disk. You are responsible\r
+       for providing and closing the FILE*.\r
+\r
+       Returns XML_NO_ERROR (0) on success, or\r
+       an errorID.\r
+    */\r
+    XMLError SaveFile( FILE* fp, bool compact = false );\r
+\r
+    bool ProcessEntities() const               {\r
+        return _processEntities;\r
+    }\r
+    Whitespace WhitespaceMode() const  {\r
+        return _whitespace;\r
+    }\r
+\r
+    /**\r
+       Returns true if this document has a leading Byte Order Mark of UTF8.\r
+    */\r
+    bool HasBOM() const {\r
+        return _writeBOM;\r
+    }\r
+    /** Sets whether to write the BOM when writing the file.\r
+    */\r
+    void SetBOM( bool useBOM ) {\r
+        _writeBOM = useBOM;\r
+    }\r
+\r
+    /** Return the root element of DOM. Equivalent to FirstChildElement().\r
+        To get the first node, use FirstChild().\r
+    */\r
+    XMLElement* RootElement()                          {\r
+        return FirstChildElement();\r
+    }\r
+    const XMLElement* RootElement() const      {\r
+        return FirstChildElement();\r
+    }\r
+\r
+    /** Print the Document. If the Printer is not provided, it will\r
+        print to stdout. If you provide Printer, this can print to a file:\r
+       @verbatim\r
+       XMLPrinter printer( fp );\r
+       doc.Print( &printer );\r
+       @endverbatim\r
+\r
+       Or you can use a printer to print to memory:\r
+       @verbatim\r
+       XMLPrinter printer;\r
+       doc.Print( &printer );\r
+       // printer.CStr() has a const char* to the XML\r
+       @endverbatim\r
+    */\r
+    void Print( XMLPrinter* streamer=0 ) const;\r
+    virtual bool Accept( XMLVisitor* visitor ) const;\r
+\r
+    /**\r
+       Create a new Element associated with\r
+       this Document. The memory for the Element\r
+       is managed by the Document.\r
+    */\r
+    XMLElement* NewElement( const char* name );\r
+    /**\r
+       Create a new Comment associated with\r
+       this Document. The memory for the Comment\r
+       is managed by the Document.\r
+    */\r
+    XMLComment* NewComment( const char* comment );\r
+    /**\r
+       Create a new Text associated with\r
+       this Document. The memory for the Text\r
+       is managed by the Document.\r
+    */\r
+    XMLText* NewText( const char* text );\r
+    /**\r
+       Create a new Declaration associated with\r
+       this Document. The memory for the object\r
+       is managed by the Document.\r
+\r
+       If the 'text' param is null, the standard\r
+       declaration is used.:\r
+       @verbatim\r
+               <?xml version="1.0" encoding="UTF-8"?>\r
+       @endverbatim\r
+    */\r
+    XMLDeclaration* NewDeclaration( const char* text=0 );\r
+    /**\r
+       Create a new Unknown associated with\r
+       this Document. The memory for the object\r
+       is managed by the Document.\r
+    */\r
+    XMLUnknown* NewUnknown( const char* text );\r
+\r
+    /**\r
+       Delete a node associated with this document.\r
+       It will be unlinked from the DOM.\r
+    */\r
+    void DeleteNode( XMLNode* node );\r
+\r
+    void SetError( XMLError error, const char* str1, const char* str2 );\r
+\r
+    /// Return true if there was an error parsing the document.\r
+    bool Error() const {\r
+        return _errorID != XML_NO_ERROR;\r
+    }\r
+    /// Return the errorID.\r
+    XMLError  ErrorID() const {\r
+        return _errorID;\r
+    }\r
+       const char* ErrorName() const;\r
+\r
+    /// Return a possibly helpful diagnostic location or string.\r
+    const char* GetErrorStr1() const {\r
+        return _errorStr1;\r
+    }\r
+    /// Return a possibly helpful secondary diagnostic location or string.\r
+    const char* GetErrorStr2() const {\r
+        return _errorStr2;\r
+    }\r
+    /// If there is an error, print it to stdout.\r
+    void PrintError() const;\r
+    \r
+    /// Clear the document, resetting it to the initial state.\r
+    void Clear();\r
+\r
+    // internal\r
+    char* Identify( char* p, XMLNode** node );\r
+\r
+    virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const   {\r
+        return 0;\r
+    }\r
+    virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const      {\r
+        return false;\r
+    }\r
+\r
+private:\r
+    XMLDocument( const XMLDocument& ); // not supported\r
+    void operator=( const XMLDocument& );      // not supported\r
+\r
+    bool        _writeBOM;\r
+    bool        _processEntities;\r
+    XMLError    _errorID;\r
+    Whitespace  _whitespace;\r
+    const char* _errorStr1;\r
+    const char* _errorStr2;\r
+    char*       _charBuffer;\r
+\r
+    MemPoolT< sizeof(XMLElement) >      _elementPool;\r
+    MemPoolT< sizeof(XMLAttribute) > _attributePool;\r
+    MemPoolT< sizeof(XMLText) >                 _textPool;\r
+    MemPoolT< sizeof(XMLComment) >      _commentPool;\r
+\r
+       static const char* _errorNames[XML_ERROR_COUNT];\r
+\r
+    void Parse();\r
+};\r
+\r
+\r
+/**\r
+       A XMLHandle is a class that wraps a node pointer with null checks; this is\r
+       an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2\r
+       DOM structure. It is a separate utility class.\r
+\r
+       Take an example:\r
+       @verbatim\r
+       <Document>\r
+               <Element attributeA = "valueA">\r
+                       <Child attributeB = "value1" />\r
+                       <Child attributeB = "value2" />\r
+               </Element>\r
+       </Document>\r
+       @endverbatim\r
+\r
+       Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very\r
+       easy to write a *lot* of code that looks like:\r
+\r
+       @verbatim\r
+       XMLElement* root = document.FirstChildElement( "Document" );\r
+       if ( root )\r
+       {\r
+               XMLElement* element = root->FirstChildElement( "Element" );\r
+               if ( element )\r
+               {\r
+                       XMLElement* child = element->FirstChildElement( "Child" );\r
+                       if ( child )\r
+                       {\r
+                               XMLElement* child2 = child->NextSiblingElement( "Child" );\r
+                               if ( child2 )\r
+                               {\r
+                                       // Finally do something useful.\r
+       @endverbatim\r
+\r
+       And that doesn't even cover "else" cases. XMLHandle addresses the verbosity\r
+       of such code. A XMLHandle checks for null pointers so it is perfectly safe\r
+       and correct to use:\r
+\r
+       @verbatim\r
+       XMLHandle docHandle( &document );\r
+       XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();\r
+       if ( child2 )\r
+       {\r
+               // do something useful\r
+       @endverbatim\r
+\r
+       Which is MUCH more concise and useful.\r
+\r
+       It is also safe to copy handles - internally they are nothing more than node pointers.\r
+       @verbatim\r
+       XMLHandle handleCopy = handle;\r
+       @endverbatim\r
+\r
+       See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.\r
+*/\r
+class TINYXML2_LIB XMLHandle\r
+{\r
+public:\r
+    /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.\r
+    XMLHandle( XMLNode* node )                                                                                         {\r
+        _node = node;\r
+    }\r
+    /// Create a handle from a node.\r
+    XMLHandle( XMLNode& node )                                                                                         {\r
+        _node = &node;\r
+    }\r
+    /// Copy constructor\r
+    XMLHandle( const XMLHandle& ref )                                                                          {\r
+        _node = ref._node;\r
+    }\r
+    /// Assignment\r
+    XMLHandle& operator=( const XMLHandle& ref )                                                       {\r
+        _node = ref._node;\r
+        return *this;\r
+    }\r
+\r
+    /// Get the first child of this handle.\r
+    XMLHandle FirstChild()                                                                                                     {\r
+        return XMLHandle( _node ? _node->FirstChild() : 0 );\r
+    }\r
+    /// Get the first child element of this handle.\r
+    XMLHandle FirstChildElement( const char* name = 0 )                                                {\r
+        return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );\r
+    }\r
+    /// Get the last child of this handle.\r
+    XMLHandle LastChild()                                                                                                      {\r
+        return XMLHandle( _node ? _node->LastChild() : 0 );\r
+    }\r
+    /// Get the last child element of this handle.\r
+    XMLHandle LastChildElement( const char* name = 0 )                                         {\r
+        return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );\r
+    }\r
+    /// Get the previous sibling of this handle.\r
+    XMLHandle PreviousSibling()                                                                                                {\r
+        return XMLHandle( _node ? _node->PreviousSibling() : 0 );\r
+    }\r
+    /// Get the previous sibling element of this handle.\r
+    XMLHandle PreviousSiblingElement( const char* name = 0 )                           {\r
+        return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );\r
+    }\r
+    /// Get the next sibling of this handle.\r
+    XMLHandle NextSibling()                                                                                                    {\r
+        return XMLHandle( _node ? _node->NextSibling() : 0 );\r
+    }\r
+    /// Get the next sibling element of this handle.\r
+    XMLHandle NextSiblingElement( const char* name = 0 )                                       {\r
+        return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );\r
+    }\r
+\r
+    /// Safe cast to XMLNode. This can return null.\r
+    XMLNode* ToNode()                                                  {\r
+        return _node;\r
+    }\r
+    /// Safe cast to XMLElement. This can return null.\r
+    XMLElement* ToElement()                                    {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToElement() );\r
+    }\r
+    /// Safe cast to XMLText. This can return null.\r
+    XMLText* ToText()                                                  {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToText() );\r
+    }\r
+    /// Safe cast to XMLUnknown. This can return null.\r
+    XMLUnknown* ToUnknown()                                    {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );\r
+    }\r
+    /// Safe cast to XMLDeclaration. This can return null.\r
+    XMLDeclaration* ToDeclaration()                    {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );\r
+    }\r
+\r
+private:\r
+    XMLNode* _node;\r
+};\r
+\r
+\r
+/**\r
+       A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the\r
+       same in all regards, except for the 'const' qualifiers. See XMLHandle for API.\r
+*/\r
+class TINYXML2_LIB XMLConstHandle\r
+{\r
+public:\r
+    XMLConstHandle( const XMLNode* node )                                                                                      {\r
+        _node = node;\r
+    }\r
+    XMLConstHandle( const XMLNode& node )                                                                                      {\r
+        _node = &node;\r
+    }\r
+    XMLConstHandle( const XMLConstHandle& ref )                                                                                {\r
+        _node = ref._node;\r
+    }\r
+\r
+    XMLConstHandle& operator=( const XMLConstHandle& ref )                                                     {\r
+        _node = ref._node;\r
+        return *this;\r
+    }\r
+\r
+    const XMLConstHandle FirstChild() const                                                                                    {\r
+        return XMLConstHandle( _node ? _node->FirstChild() : 0 );\r
+    }\r
+    const XMLConstHandle FirstChildElement( const char* name = 0 ) const                               {\r
+        return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );\r
+    }\r
+    const XMLConstHandle LastChild()   const                                                                           {\r
+        return XMLConstHandle( _node ? _node->LastChild() : 0 );\r
+    }\r
+    const XMLConstHandle LastChildElement( const char* name = 0 ) const                                {\r
+        return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );\r
+    }\r
+    const XMLConstHandle PreviousSibling() const                                                                       {\r
+        return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );\r
+    }\r
+    const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const          {\r
+        return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );\r
+    }\r
+    const XMLConstHandle NextSibling() const                                                                           {\r
+        return XMLConstHandle( _node ? _node->NextSibling() : 0 );\r
+    }\r
+    const XMLConstHandle NextSiblingElement( const char* name = 0 ) const                      {\r
+        return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );\r
+    }\r
+\r
+\r
+    const XMLNode* ToNode() const                              {\r
+        return _node;\r
+    }\r
+    const XMLElement* ToElement() const                        {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToElement() );\r
+    }\r
+    const XMLText* ToText() const                              {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToText() );\r
+    }\r
+    const XMLUnknown* ToUnknown() const                        {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );\r
+    }\r
+    const XMLDeclaration* ToDeclaration() const        {\r
+        return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );\r
+    }\r
+\r
+private:\r
+    const XMLNode* _node;\r
+};\r
+\r
+\r
+/**\r
+       Printing functionality. The XMLPrinter gives you more\r
+       options than the XMLDocument::Print() method.\r
+\r
+       It can:\r
+       -# Print to memory.\r
+       -# Print to a file you provide.\r
+       -# Print XML without a XMLDocument.\r
+\r
+       Print to Memory\r
+\r
+       @verbatim\r
+       XMLPrinter printer;\r
+       doc.Print( &printer );\r
+       SomeFunction( printer.CStr() );\r
+       @endverbatim\r
+\r
+       Print to a File\r
+\r
+       You provide the file pointer.\r
+       @verbatim\r
+       XMLPrinter printer( fp );\r
+       doc.Print( &printer );\r
+       @endverbatim\r
+\r
+       Print without a XMLDocument\r
+\r
+       When loading, an XML parser is very useful. However, sometimes\r
+       when saving, it just gets in the way. The code is often set up\r
+       for streaming, and constructing the DOM is just overhead.\r
+\r
+       The Printer supports the streaming case. The following code\r
+       prints out a trivially simple XML file without ever creating\r
+       an XML document.\r
+\r
+       @verbatim\r
+       XMLPrinter printer( fp );\r
+       printer.OpenElement( "foo" );\r
+       printer.PushAttribute( "foo", "bar" );\r
+       printer.CloseElement();\r
+       @endverbatim\r
+*/\r
+class TINYXML2_LIB XMLPrinter : public XMLVisitor\r
+{\r
+public:\r
+    /** Construct the printer. If the FILE* is specified,\r
+       this will print to the FILE. Else it will print\r
+       to memory, and the result is available in CStr().\r
+       If 'compact' is set to true, then output is created\r
+       with only required whitespace and newlines.\r
+    */\r
+    XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );\r
+    virtual ~XMLPrinter()      {}\r
+\r
+    /** If streaming, write the BOM and declaration. */\r
+    void PushHeader( bool writeBOM, bool writeDeclaration );\r
+    /** If streaming, start writing an element.\r
+        The element must be closed with CloseElement()\r
+    */\r
+    void OpenElement( const char* name, bool compactMode=false );\r
+    /// If streaming, add an attribute to an open element.\r
+    void PushAttribute( const char* name, const char* value );\r
+    void PushAttribute( const char* name, int value );\r
+    void PushAttribute( const char* name, unsigned value );\r
+    void PushAttribute( const char* name, bool value );\r
+    void PushAttribute( const char* name, double value );\r
+    /// If streaming, close the Element.\r
+    virtual void CloseElement( bool compactMode=false );\r
+\r
+    /// Add a text node.\r
+    void PushText( const char* text, bool cdata=false );\r
+    /// Add a text node from an integer.\r
+    void PushText( int value );\r
+    /// Add a text node from an unsigned.\r
+    void PushText( unsigned value );\r
+    /// Add a text node from a bool.\r
+    void PushText( bool value );\r
+    /// Add a text node from a float.\r
+    void PushText( float value );\r
+    /// Add a text node from a double.\r
+    void PushText( double value );\r
+\r
+    /// Add a comment\r
+    void PushComment( const char* comment );\r
+\r
+    void PushDeclaration( const char* value );\r
+    void PushUnknown( const char* value );\r
+\r
+    virtual bool VisitEnter( const XMLDocument& /*doc*/ );\r
+    virtual bool VisitExit( const XMLDocument& /*doc*/ )                       {\r
+        return true;\r
+    }\r
+\r
+    virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );\r
+    virtual bool VisitExit( const XMLElement& element );\r
+\r
+    virtual bool Visit( const XMLText& text );\r
+    virtual bool Visit( const XMLComment& comment );\r
+    virtual bool Visit( const XMLDeclaration& declaration );\r
+    virtual bool Visit( const XMLUnknown& unknown );\r
+\r
+    /**\r
+       If in print to memory mode, return a pointer to\r
+       the XML file in memory.\r
+    */\r
+    const char* CStr() const {\r
+        return _buffer.Mem();\r
+    }\r
+    /**\r
+       If in print to memory mode, return the size\r
+       of the XML file in memory. (Note the size returned\r
+       includes the terminating null.)\r
+    */\r
+    int CStrSize() const {\r
+        return _buffer.Size();\r
+    }\r
+    /**\r
+       If in print to memory mode, reset the buffer to the\r
+       beginning.\r
+    */\r
+    void ClearBuffer() {\r
+        _buffer.Clear();\r
+        _buffer.Push(0);\r
+    }\r
+\r
+protected:\r
+       virtual bool CompactMode( const XMLElement& )   { return _compactMode; }\r
+\r
+       /** Prints out the space before an element. You may override to change\r
+           the space and tabs used. A PrintSpace() override should call Print().\r
+       */\r
+    virtual void PrintSpace( int depth );\r
+    void Print( const char* format, ... );\r
+\r
+    void SealElementIfJustOpened();\r
+    bool _elementJustOpened;\r
+    DynArray< const char*, 10 > _stack;\r
+\r
+private:\r
+    void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.\r
+\r
+    bool _firstElement;\r
+    FILE* _fp;\r
+    int _depth;\r
+    int _textDepth;\r
+    bool _processEntities;\r
+       bool _compactMode;\r
+\r
+    enum {\r
+        ENTITY_RANGE = 64,\r
+        BUF_SIZE = 200\r
+    };\r
+    bool _entityFlag[ENTITY_RANGE];\r
+    bool _restrictedEntityFlag[ENTITY_RANGE];\r
+\r
+    DynArray< char, 20 > _buffer;\r
+};\r
+\r
+\r
+}      // tinyxml2\r
+\r
+#if defined(_MSC_VER)\r
+#   pragma warning(pop)\r
+#endif\r
+\r
+#endif // TINYXML2_INCLUDED\r
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ba1a41a
--- /dev/null
@@ -0,0 +1,58 @@
+
+## =====================
+## == List of plugins ==
+## =====================
+
+SET(
+  _directories
+  GenericPlugins
+  VTKFilters
+  VTKIO
+  VTKWidgets
+  ITKAnisotropicSmoothing
+  ITKBinaryFunctorFilters
+  ITKDistanceMapFilters
+  ITKFiniteDifference
+  ITKImageGenericFilters_1
+  ITKImageInterpolators
+  ITKIO
+  ITKLevelSetFilters
+  ITKMorphology
+  ITKNeighborhoodOperatorFilters
+  ITKParaMorphology
+  ITKSeparableFilters
+  ITKSliceFilters
+  ITKUnaryFunctorFilters
+  cpExtensions
+  )
+
+## =========================
+## == Compile each plugin ==
+## =========================
+
+INCLUDE_DIRECTORIES(
+  ${PROJECT_SOURCE_DIR}/lib
+  ${PROJECT_BINARY_DIR}/lib
+  )
+FOREACH(_dir ${_directories})
+  cpPlugins_BuildPluginsLibrary(cpPlugins_${_dir} ${_dir})
+  TARGET_LINK_LIBRARIES(cpPlugins_${_dir} cpPluginsDataObjects)
+ENDFOREACH(_dir)
+
+TARGET_LINK_LIBRARIES(cpPlugins_ITKDistanceMapFilters cpPlugins_ITKUnaryFunctorFilters)
+TARGET_LINK_LIBRARIES(cpPlugins_ITKAnisotropicSmoothing cpPlugins_ITKFiniteDifference)
+TARGET_LINK_LIBRARIES(
+  cpPlugins_ITKLevelSetFilters
+  cpPlugins_ITKAnisotropicSmoothing
+  cpPlugins_ITKNeighborhoodOperatorFilters
+  cpPlugins_ITKImageGenericFilters_1
+  )
+TARGET_LINK_LIBRARIES(cpPlugins_ITKParaMorphology cpPlugins_ITKUnaryFunctorFilters)
+TARGET_LINK_LIBRARIES(cpPlugins_ITKSeparableFilters cpPlugins_ITKImageGenericFilters_1)
+TARGET_LINK_LIBRARIES(
+  cpPlugins_ITKSliceFilters
+  cpPlugins_ITKImageInterpolators
+  cpPlugins_ITKImageGenericFilters_1
+  )
+
+## eof - $RCSfile$
diff --git a/plugins/GenericPlugins/DataReproducer.cxx b/plugins/GenericPlugins/DataReproducer.cxx
new file mode 100644 (file)
index 0000000..586e37b
--- /dev/null
@@ -0,0 +1,49 @@
+#include "DataReproducer.h"
+#include <cpPlugins/Pipeline/DataObject.h>
+
+// -------------------------------------------------------------------------
+void cpPlugins_GenericPlugins::DataReproducer::
+AddInput( const std::string& n, cpPlugins::Pipeline::DataObject* o )
+{
+  this->Superclass::AddInput( n, o );
+  auto out =
+    dynamic_cast< cpPlugins::Pipeline::OutputPort* >(
+      this->m_Outputs.find( "Output" )->second
+      );
+  out->Set( o );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins_GenericPlugins::DataReproducer::
+SetInput( const std::string& n, cpPlugins::Pipeline::DataObject* o )
+{
+  this->Superclass::SetInput( n, o );
+  auto out =
+    dynamic_cast< cpPlugins::Pipeline::OutputPort* >(
+      this->m_Outputs.find( "Output" )->second
+      );
+  out->Set( o );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins_GenericPlugins::DataReproducer::
+DataReproducer( )
+  : Superclass( )
+{
+  this->_ConfigureInput( "Input", true, false );
+  this->_ConfigureOutput( "Output" );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins_GenericPlugins::DataReproducer::
+~DataReproducer( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins_GenericPlugins::DataReproducer::
+_GenerateData( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/plugins/GenericPlugins/DataReproducer.h b/plugins/GenericPlugins/DataReproducer.h
new file mode 100644 (file)
index 0000000..9bfcbc1
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __cpPlugins_GenericPlugins__DataReproducer__h__
+#define __cpPlugins_GenericPlugins__DataReproducer__h__
+
+#include <cpPlugins_GenericPlugins_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPlugins_GenericPlugins
+{
+  /**
+   */
+  class cpPlugins_GenericPlugins_EXPORT DataReproducer
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      DataReproducer,
+      cpPlugins::Pipeline::ProcessObject,
+      GenericPlugins
+      );
+
+  public:
+    virtual void AddInput(
+      const std::string& n, cpPlugins::Pipeline::DataObject* o
+      ) cpPlugins_OVERRIDE;
+    virtual void SetInput(
+      const std::string& n, cpPlugins::Pipeline::DataObject* o
+      ) cpPlugins_OVERRIDE;
+  };
+
+} // ecapseman
+
+#endif // __cpPlugins_GenericPlugins__DataReproducer__h__
+
+// eof - $RCSfile$
diff --git a/plugins/GenericPlugins/JoinBoundingBoxes.cxx b/plugins/GenericPlugins/JoinBoundingBoxes.cxx
new file mode 100644 (file)
index 0000000..d3bdfb5
--- /dev/null
@@ -0,0 +1,44 @@
+#include <GenericPlugins/JoinBoundingBoxes.h>
+#include <cpPlugins/Pipeline/DataObject.h>
+#include <cpInstances/DataObjects/BoundingBox.h>
+
+// -------------------------------------------------------------------------
+cpPlugins_GenericPlugins::JoinBoundingBoxes::
+JoinBoundingBoxes( )
+  : Superclass( )
+{
+  this->_ConfigureInput( "Inputs", true, true );
+  this->_ConfigureOutput< cpInstances::DataObjects::BoundingBox >( "Output" );
+}
+
+// -------------------------------------------------------------------------
+cpPlugins_GenericPlugins::JoinBoundingBoxes::
+~JoinBoundingBoxes( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins_GenericPlugins::JoinBoundingBoxes::
+_GenerateData( )
+{
+  typedef cpPlugins::Pipeline::DataObject _TDO;
+  typedef cpInstances::DataObjects::BoundingBox _TBB;
+
+  auto out = dynamic_cast< _TBB* >( this->GetOutput( "Output" ) );
+  unsigned int nInputs = this->GetInputSize( "Inputs" );
+  for( unsigned int i = 0; i < nInputs; ++i )
+  {
+    auto in = dynamic_cast< _TDO* >( this->GetInput( "Inputs", i ) );
+    if( i > 0 )
+    {
+      _TBB::Pointer bb = _TBB::New( );
+      bb->SetDataObject( in );
+      out->Blend( bb );
+    }
+    else
+      out->SetDataObject( in );
+
+  } // rof
+}
+
+// eof - $RCSfile$
diff --git a/plugins/GenericPlugins/JoinBoundingBoxes.h b/plugins/GenericPlugins/JoinBoundingBoxes.h
new file mode 100644 (file)
index 0000000..6751dad
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__
+#define __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__
+
+#include <cpPlugins_GenericPlugins_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPlugins_GenericPlugins
+{
+  /**
+   */
+  class cpPlugins_GenericPlugins_EXPORT JoinBoundingBoxes
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      JoinBoundingBoxes,
+      cpPlugins::Pipeline::ProcessObject,
+      GenericPlugins
+      );
+  };
+
+} // ecapseman
+
+#endif // __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.cxx b/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.cxx
new file mode 100644 (file)
index 0000000..26b76b0
--- /dev/null
@@ -0,0 +1,71 @@
+#include <ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkCurvatureAnisotropicDiffusionImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter::
+CurvatureAnisotropicDiffusionImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  this->m_Parameters.ConfigureAsUint( "NumberOfIterations", 5 );
+  this->m_Parameters.ConfigureAsBool( "UseImageSpacing", false );
+  this->m_Parameters.ConfigureAsReal( "ConductanceParameter", 3 );
+  this->m_Parameters.ConfigureAsReal( "TimeStep", 0.0625 );
+  this->m_Parameters.ConfigureAsRealTypesChoices( "OutputResolution" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter::
+~CurvatureAnisotropicDiffusionImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "No valid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter::
+_GD0( _TImage* image )
+{
+  std::string out_res =
+    this->m_Parameters.GetSelectedChoice( "OutputResolution" );
+  if( out_res == "float" ) this->_GD1< _TImage, float >( image );
+  if( out_res == "double" ) this->_GD1< _TImage, double >( image );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TScalar >
+void cpPluginsITKAnisotropicSmoothing::CurvatureAnisotropicDiffusionImageFilter::
+_GD1( _TImage* image )
+{
+  typedef itk::Image< _TScalar, _TImage::ImageDimension > _TOutImage;
+  typedef
+    itk::CurvatureAnisotropicDiffusionImageFilter< _TImage, _TOutImage >
+    _TFilter;
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetNumberOfIterations( this->m_Parameters.GetUint( "NumberOfIterations" ) );
+  filter->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) );
+  filter->SetConductanceParameter( this->m_Parameters.GetReal( "ConductanceParameter" ) );
+  filter->SetTimeStep( this->m_Parameters.GetReal( "TimeStep" ) );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h b/plugins/ITKAnisotropicSmoothing/CurvatureAnisotropicDiffusionImageFilter.h
new file mode 100644 (file)
index 0000000..dc91e06
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKAnisotropicSmoothing__CurvatureAnisotropicDiffusionImageFilter__h__
+#define __cpPluginsITKAnisotropicSmoothing__CurvatureAnisotropicDiffusionImageFilter__h__
+
+#include <cpPlugins_ITKAnisotropicSmoothing_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKAnisotropicSmoothing
+{
+  /**
+   */
+  class cpPlugins_ITKAnisotropicSmoothing_EXPORT CurvatureAnisotropicDiffusionImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      CurvatureAnisotropicDiffusionImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageSmoothing
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage, class _TScalar >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKAnisotropicSmoothing__CurvatureAnisotropicDiffusionImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKAnisotropicSmoothing/ITKAnisotropicSmoothing.i b/plugins/ITKAnisotropicSmoothing/ITKAnisotropicSmoothing.i
new file mode 100644 (file)
index 0000000..d87073b
--- /dev/null
@@ -0,0 +1,12 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define functions=ScalarAnisotropicDiffusionFunction;GradientNDAnisotropicDiffusionFunction;CurvatureNDAnisotropicDiffusionFunction
+tinclude itk#functions#:h|hxx
+instances itk::#functions#< itk::Image< #scalar_types#, #pdims# > >
+
+define filters=AnisotropicDiffusionImageFilter
+
+tinclude itk#filters#:h|hxx
+instances itk::#filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.cxx b/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.cxx
new file mode 100644 (file)
index 0000000..b297489
--- /dev/null
@@ -0,0 +1,92 @@
+#include <ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkAddImageFilter.h>
+#include <itkSubtractImageFilter.h>
+#include <itkMultiplyImageFilter.h>
+#include <itkDivideImageFilter.h>
+#include <itkDivideOrZeroOutImageFilter.h>
+#include <itkPowImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter::
+BinaryArithmeticImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input1", true, false );
+  this->_ConfigureInput< _TImage >( "Input2", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  std::vector< std::string > choices;
+  choices.push_back( "Add" );
+  choices.push_back( "Subtract" );
+  choices.push_back( "Multiply" );
+  choices.push_back( "Divide" );
+  choices.push_back( "DivideOrZero" );
+  choices.push_back( "Pow" );
+  this->m_Parameters.ConfigureAsChoices( "Operator", choices );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter::
+~BinaryArithmeticImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input1" );
+  cpPlugins_Demangle_Image_IntPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter::
+_GD0( _TImage* image1 )
+{
+  typedef itk::AddImageFilter< _TImage, _TImage > _TAdd;
+  typedef itk::SubtractImageFilter< _TImage, _TImage > _TSubtract;
+  typedef itk::MultiplyImageFilter< _TImage, _TImage > _TMultiply;
+  typedef itk::DivideImageFilter< _TImage, _TImage, _TImage > _TDivide;
+  typedef itk::DivideOrZeroOutImageFilter< _TImage, _TImage > _TDivideOrZero;
+  typedef itk::PowImageFilter< _TImage, _TImage > _TPow;
+
+  auto image2 = this->GetInputData< _TImage >( "Input2" );
+  if( image2 == NULL )
+    this->_Error( "Incompatible second input image." );
+  std::string op = this->m_Parameters.GetSelectedChoice( "Operator" );
+  if( op == "Add" )
+    this->_GD1< _TAdd, _TImage >( image1, image2 );
+  else if( op == "Subtract" )
+    this->_GD1< _TSubtract, _TImage >( image1, image2 );
+  else if( op == "Multiply" )
+    this->_GD1< _TMultiply, _TImage >( image1, image2 );
+  else if( op == "Divide" )
+    this->_GD1< _TDivide, _TImage >( image1, image2 );
+  else if( op == "DivideOrZero" )
+    this->_GD1< _TDivideOrZero, _TImage >( image1, image2 );
+  else if( op == "Pow" )
+    this->_GD1< _TPow, _TImage >( image1, image2 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TImage >
+void cpPluginsITKBinaryFunctorFilters::BinaryArithmeticImageFilter::
+_GD1( _TImage* image1, _TImage* image2 )
+{
+  // Configure filter
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput1( image1 );
+  filter->SetInput2( image2 );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h b/plugins/ITKBinaryFunctorFilters/BinaryArithmeticImageFilter.h
new file mode 100644 (file)
index 0000000..0b3b9f6
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKBinaryFunctorFilters__BinaryArithmeticImageFilter__h__
+#define __cpPluginsITKBinaryFunctorFilters__BinaryArithmeticImageFilter__h__
+
+#include <cpPlugins_ITKBinaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKBinaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKBinaryFunctorFilters_EXPORT BinaryArithmeticImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      BinaryArithmeticImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageArithmeticFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image1 );
+
+    template< class _TFilter, class _TImage >
+    inline void _GD1( _TImage* image1, _TImage* image2 );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKBinaryFunctorFilters__BinaryArithmeticImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.cxx b/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.cxx
new file mode 100644 (file)
index 0000000..3202b74
--- /dev/null
@@ -0,0 +1,74 @@
+#include <ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkAndImageFilter.h>
+#include <itkOrImageFilter.h>
+#include <itkXorImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter::
+BinaryBooleanImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input1", true, false );
+  this->_ConfigureInput< _TImage >( "Input2", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  std::vector< std::string > choices;
+  choices.push_back( "And" );
+  choices.push_back( "Or" );
+  choices.push_back( "Xor" );
+  this->m_Parameters.ConfigureAsChoices( "Operator", choices );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter::
+~BinaryBooleanImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input1" );
+  cpPlugins_Demangle_Image_IntPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter::
+_GD0( _TImage* image1 )
+{
+  typedef itk::AndImageFilter< _TImage, _TImage > _TAnd;
+  typedef itk::OrImageFilter< _TImage, _TImage > _TOr;
+  typedef itk::XorImageFilter< _TImage, _TImage > _TXor;
+
+  auto image2 = this->GetInputData< _TImage >( "Input2" );
+  if( image2 == NULL )
+    this->_Error( "Incompatible second input image." );
+  std::string op = this->m_Parameters.GetSelectedChoice( "Operator" );
+  if     ( op == "And" ) this->_GD1< _TAnd, _TImage >( image1, image2 );
+  else if( op == "Or" ) this->_GD1< _TOr, _TImage >( image1, image2 );
+  else if( op == "Xor" ) this->_GD1< _TXor, _TImage >( image1, image2 );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFilter, class _TImage >
+void cpPluginsITKBinaryFunctorFilters::BinaryBooleanImageFilter::
+_GD1( _TImage* image1, _TImage* image2 )
+{
+  // Configure filter
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput1( image1 );
+  filter->SetInput2( image2 );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h b/plugins/ITKBinaryFunctorFilters/BinaryBooleanImageFilter.h
new file mode 100644 (file)
index 0000000..439e178
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKBinaryFunctorFilters__BinaryBooleanImageFilter__h__
+#define __cpPluginsITKBinaryFunctorFilters__BinaryBooleanImageFilter__h__
+
+#include <cpPlugins_ITKBinaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKBinaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKBinaryFunctorFilters_EXPORT BinaryBooleanImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      BinaryBooleanImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageBooleanFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image1 );
+
+    template< class _TFilter, class _TImage >
+    inline void _GD1( _TImage* image1, _TImage* image2 );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKBinaryFunctorFilters__BinaryBooleanImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKBinaryFunctorFilters/ITKBinaryFunctorFilters.i b/plugins/ITKBinaryFunctorFilters/ITKBinaryFunctorFilters.i
new file mode 100644 (file)
index 0000000..d9d98bb
--- /dev/null
@@ -0,0 +1,17 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define all_ints=#int_types#;#uint_types#
+define a_filters=Add;Subtract;Multiply;Divide;DivideOrZeroOut;Pow
+define a_functor=Add2;Sub2;Mult;Div;DivideOrZeroOut;Pow
+define b_filters=And;Or;Xor
+define b_functor=AND;OR;XOR
+
+tinclude itkBinaryFunctorImageFilter:h|hxx
+cinclude itk#a_filters#ImageFilter.h
+cinclude itk#b_filters#ImageFilter.h
+
+instances itk::BinaryFunctorImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Functor::#a_functor#< #scalar_types#, #scalar_types#, #scalar_types# > >
+
+instances itk::BinaryFunctorImageFilter< itk::Image< #all_ints#, #pdims# >, itk::Image< #all_ints#, #pdims# >, itk::Image< #all_ints#, #pdims# >, itk::Functor::#b_functor#< #all_ints#, #all_ints#, #all_ints# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.cxx b/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.cxx
new file mode 100644 (file)
index 0000000..0cb9711
--- /dev/null
@@ -0,0 +1,71 @@
+#include <ITKDistanceMapFilters/BinaryContourImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkBinaryContourImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKDistanceMapFilters::BinaryContourImageFilter::
+BinaryContourImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "BackgroundValue", 0 );
+  this->m_Parameters.ConfigureAsReal( "ForegroundValue", 1 );
+  this->m_Parameters.ConfigureAsBool( "FullyConnected", false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKDistanceMapFilters::BinaryContourImageFilter::
+~BinaryContourImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKDistanceMapFilters::BinaryContourImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_VisualDims_1( o, _GD0 )
+    this->_Error( "Invalid input image dimension." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKDistanceMapFilters::BinaryContourImageFilter::
+_GD0( _TImage* image )
+{
+  cpPlugins_Demangle_Image_ScalarPixels_1( image, _GD1, _TImage::ImageDimension )
+    this->_Error( "Invalid input image pixel type." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKDistanceMapFilters::BinaryContourImageFilter::
+_GD1( _TImage* image )
+{
+  typedef
+    itk::BinaryContourImageFilter< _TImage, _TImage >
+    _TFilter;
+
+  // Get parameters
+  double b = this->m_Parameters.GetReal( "BackgroundValue" );
+  double f = this->m_Parameters.GetReal( "ForegroundValue" );
+  double c = this->m_Parameters.GetBool( "FullyConnected" );
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetBackgroundValue( ( typename _TImage::PixelType )( b ) );
+  filter->SetForegroundValue( ( typename _TImage::PixelType )( f ) );
+  filter->SetFullyConnected( c );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.h b/plugins/ITKDistanceMapFilters/BinaryContourImageFilter.h
new file mode 100644 (file)
index 0000000..8e16c99
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKDistanceMapFilters__BinaryContourImageFilter__h__
+#define __cpPluginsITKDistanceMapFilters__BinaryContourImageFilter__h__
+
+#include <cpPlugins_ITKDistanceMapFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKDistanceMapFilters
+{
+  /**
+   */
+  class cpPlugins_ITKDistanceMapFilters_EXPORT BinaryContourImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      BinaryContourImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageDistanceMaps
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKDistanceMapFilters__BinaryContourImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKDistanceMapFilters/ITKDistanceMapFilters.i b/plugins/ITKDistanceMapFilters/ITKDistanceMapFilters.i
new file mode 100644 (file)
index 0000000..6a703ad
--- /dev/null
@@ -0,0 +1,15 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude itkImageRegionConstIterator:h|h
+tinclude itkImageRegionIterator:h|h
+tinclude itkProgressReporter:h|h
+
+tinclude itkBinaryContourImageFilter:h|hxx
+instances itk::BinaryContourImageFilter< itk::Image< #scalar_types#, #vdims# >, itk::Image< #scalar_types#, #vdims# > >
+
+define filters=SignedMaurerDistanceMapImageFilter
+** ;DanielssonDistanceMapImageFilter;SignedDanielssonDistanceMapImageFilter
+tinclude itk#filters#:h|hxx
+instances itk::#filters#< itk::Image< #scalar_types#, #vdims# >, itk::Image< #real_types#, #vdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.cxx b/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.cxx
new file mode 100644 (file)
index 0000000..b92b881
--- /dev/null
@@ -0,0 +1,82 @@
+#include <ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkSignedMaurerDistanceMapImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter::
+SignedMaurerDistanceMapImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "BackgroundValue", 0 );
+  this->m_Parameters.ConfigureAsBool( "InsideIsPositive", true );
+  this->m_Parameters.ConfigureAsBool( "SquaredDistance", false );
+  this->m_Parameters.ConfigureAsBool( "UseImageSpacing", true );
+
+  std::vector< std::string > choices;
+  choices.push_back( "float" );
+  choices.push_back( "double" );
+  this->m_Parameters.ConfigureAsChoices( "OutputResolution", choices );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter::
+~SignedMaurerDistanceMapImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_VisualDims_1( o, _GD0 )
+    this->_Error( "Invalid input image dimension." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter::
+_GD0( _TImage* image )
+{
+  std::string out_res =
+    this->m_Parameters.GetSelectedChoice( "OutputResolution" );
+  if( out_res == "float" ) this->_GD1< _TImage, float >( image );
+  if( out_res == "double" ) this->_GD1< _TImage, double >( image );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TScalar >
+void cpPluginsITKDistanceMapFilters::SignedMaurerDistanceMapImageFilter::
+_GD1( _TImage* image )
+{
+  typedef itk::Image< _TScalar, _TImage::ImageDimension >  _TDMap;
+  typedef
+    itk::SignedMaurerDistanceMapImageFilter< _TImage, _TDMap >
+    _TFilter;
+
+  // Get parameters
+  double bv = this->m_Parameters.GetReal( "BackgroundValue" );
+  bool pi = this->m_Parameters.GetBool( "InsideIsPositive" );
+  bool sd = this->m_Parameters.GetBool( "SquaredDistance" );
+  bool us = this->m_Parameters.GetBool( "UseImageSpacing" );
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetBackgroundValue( ( typename _TImage::PixelType )( bv ) );
+  filter->SetInsideIsPositive( pi );
+  filter->SetSquaredDistance( sd );
+  filter->SetUseImageSpacing( us );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h b/plugins/ITKDistanceMapFilters/SignedMaurerDistanceMapImageFilter.h
new file mode 100644 (file)
index 0000000..825c09b
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKDistanceMapFilters__SignedMaurerDistanceMapImageFilter__h__
+#define __cpPluginsITKDistanceMapFilters__SignedMaurerDistanceMapImageFilter__h__
+
+#include <cpPlugins_ITKDistanceMapFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKDistanceMapFilters
+{
+  /**
+   */
+  class cpPlugins_ITKDistanceMapFilters_EXPORT SignedMaurerDistanceMapImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      SignedMaurerDistanceMapImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageDistanceMaps
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage, class _TScalar >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKDistanceMapFilters__SignedMaurerDistanceMapImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKFiniteDifference/ITKFiniteDifference.i b/plugins/ITKFiniteDifference/ITKFiniteDifference.i
new file mode 100644 (file)
index 0000000..1db9b6a
--- /dev/null
@@ -0,0 +1,15 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define base=FiniteDifferenceImageFilter;DenseFiniteDifferenceImageFilter
+define functions=FiniteDifferenceFunction
+
+define i_reals=#real_types#
+define o_reals=#real_types#
+
+tinclude itk#functions#:h|hxx
+tinclude itk#base#:h|hxx
+
+instances itk::#functions#< itk::Image< #scalar_types#, #pdims# > >
+instances itk::#base#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #o_reals#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKIO/DicomSeriesReader.cxx b/plugins/ITKIO/DicomSeriesReader.cxx
new file mode 100644 (file)
index 0000000..18ec6f0
--- /dev/null
@@ -0,0 +1,102 @@
+#include <ITKIO/DicomSeriesReader.h>
+#include <ITKIO/DicomSeriesReaderQDialog.h>
+
+#ifdef cpPlugins_QT4
+
+#include <QApplication>
+#include <QFileInfo>
+#include <ITKIO/ui_DicomSeriesReaderQDialog.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::DicomSeriesReaderQDialog::
+DicomSeriesReaderQDialog( QWidget* parent )
+  : QDialog( parent ),
+    m_UI( new Ui::DicomSeriesReaderQDialog ),
+    m_ProcessObject( NULL )
+{
+  this->m_UI->setupUi( this );
+  this->connect(
+    this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) )
+    );
+  this->setWindowTitle( "Open DICOM series" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::DicomSeriesReaderQDialog::
+~DicomSeriesReaderQDialog( )
+{
+  delete this->m_UI;
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::DicomSeriesReaderQDialog::
+setProcessObject( cpPlugins::Pipeline::ProcessObject* obj )
+{
+  if( obj == NULL )
+    return;
+  this->m_ProcessObject = obj;
+  auto param = this->m_ProcessObject->GetParameters( );
+  auto files = param->GetOpenFileNameList( "FileNames" );
+  if( files.size( ) > 0 )
+  {
+    QFileInfo info( files[ 0 ].c_str( ) );
+    this->m_UI->Selector->setStartDir( info.canonicalPath( ) );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::DicomSeriesReaderQDialog::
+_dlg_Accepted( )
+{
+  if( this->m_ProcessObject != NULL )
+  {
+    auto param = this->m_ProcessObject->GetParameters( );
+    auto files = this->m_UI->Selector->selectedFilenames( );
+    param->ClearOpenFileNameList( "FileNames" );
+    for( auto fIt = files->begin( ); fIt != files->end( ); ++fIt )
+      param->AddToOpenFileNameList( "FileNames", *fIt );
+
+  } // fi
+}
+
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginsITKIO::DicomSeriesReader::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  DicomSeriesReaderQDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new DicomSeriesReaderQDialog( );
+    dlg->setProcessObject( this );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::DicomSeriesReader::
+DicomSeriesReader( )
+  : Superclass( )
+{
+}
+// -------------------------------------------------------------------------
+cpPluginsITKIO::DicomSeriesReader::
+~DicomSeriesReader( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::DicomSeriesReader::
+_GenerateData( )
+{
+  this->Superclass::_GenerateData( );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/DicomSeriesReader.h b/plugins/ITKIO/DicomSeriesReader.h
new file mode 100644 (file)
index 0000000..349fe7a
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef __cpPluginsITKIO__DicomSeriesReader__h__
+#define __cpPluginsITKIO__DicomSeriesReader__h__
+
+#include <ITKIO/ImageReader.h>
+
+namespace cpPluginsITKIO
+{
+  /**
+   */
+  class cpPlugins_ITKIO_EXPORT DicomSeriesReader
+    : public ImageReader
+  {
+    cpPluginsObject( DicomSeriesReader, ImageReader, IO );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKIO__DicomSeriesReader__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/DicomSeriesReaderQDialog.h b/plugins/ITKIO/DicomSeriesReaderQDialog.h
new file mode 100644 (file)
index 0000000..3c17e3a
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __cpPluginsITKIO__DicomSeriesreaderQDialog__h__
+#define __cpPluginsITKIO__DicomSeriesreaderQDialog__h__
+
+#include <cpPlugins/Config.h>
+
+#ifdef cpPlugins_QT4
+
+#include <QDialog>
+#include <ITKIO/DicomSeriesSelectorWidget.h>
+
+namespace cpPlugins { namespace Pipeline { class ProcessObject; } }
+namespace Ui { class DicomSeriesReaderQDialog; }
+
+namespace cpPluginsITKIO
+{
+  /**
+   */
+  class DicomSeriesReaderQDialog
+    : public QDialog
+  {
+    Q_OBJECT;
+  public:
+    DicomSeriesReaderQDialog( QWidget* parent = 0 );
+    virtual ~DicomSeriesReaderQDialog( );
+    void setProcessObject( cpPlugins::Pipeline::ProcessObject* obj );
+
+  protected slots:
+    void _dlg_Accepted( );
+
+  protected:
+    Ui::DicomSeriesReaderQDialog* m_UI;
+    cpPlugins::Pipeline::ProcessObject* m_ProcessObject;
+  };
+
+} // ecapseman
+
+#endif // cpPlugins_QT4
+
+#endif // __cpPluginsITKIO__DicomSeriesreaderQDialog__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/DicomSeriesReaderQDialog.ui b/plugins/ITKIO/DicomSeriesReaderQDialog.ui
new file mode 100644 (file)
index 0000000..0ab2c2e
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DicomSeriesReaderQDialog</class>
+ <widget class="QDialog" name="DicomSeriesReaderQDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>511</width>
+    <height>335</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>511</width>
+    <height>335</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="cpPluginsITKIO::DicomSeriesSelectorWidget" name="Selector" native="true"/>
+   </item>
+   <item row="1" column="0">
+    <widget class="QDialogButtonBox" name="ButtonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>cpPluginsITKIO::DicomSeriesSelectorWidget</class>
+   <extends>QWidget</extends>
+   <header location="global">ITKIO/DicomSeriesSelectorWidget.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>ButtonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>DicomSeriesReaderQDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>ButtonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>DicomSeriesReaderQDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/plugins/ITKIO/DicomSeriesSelectorWidget.cxx b/plugins/ITKIO/DicomSeriesSelectorWidget.cxx
new file mode 100644 (file)
index 0000000..98954d4
--- /dev/null
@@ -0,0 +1,182 @@
+#include <ITKIO/DicomSeriesSelectorWidget.h>
+
+#ifdef cpPlugins_QT4
+
+#include <ITKIO/ui_DicomSeriesSelectorWidget.h>
+#include <queue>
+#include <string>
+#include <QFileDialog>
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::DicomSeriesSelectorWidget::
+DicomSeriesSelectorWidget( QWidget* parent )
+  : QWidget( parent ),
+    m_UI( new Ui::DicomSeriesSelectorWidget )
+{
+  this->m_UI->setupUi( this );
+  this->setStartDir( ".", false );
+  this->connect(
+    this->m_UI->ChooseButton, SIGNAL( clicked( ) ),
+    this, SLOT( _Choose( ) )
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::DicomSeriesSelectorWidget::
+~DicomSeriesSelectorWidget( )
+{
+  delete this->m_UI;
+}
+
+// -------------------------------------------------------------------------
+QString cpPluginsITKIO::DicomSeriesSelectorWidget::
+startDir( ) const
+{
+  return( this->m_UI->Directory->text( ) );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::DicomSeriesSelectorWidget::
+setStartDir( const QString& dir, bool build )
+{
+  this->m_Series.clear( );
+
+  this->m_UI->Directory->setText( dir );
+  if( !build )
+    return;
+  
+  // Process subdirs
+  QApplication::setOverrideCursor( Qt::WaitCursor );
+
+  this->m_UI->Series->clear( );
+  this->m_UI->Series->setColumnCount( 3 );
+  QStringList labels;
+  labels << "Images count" << "Series UID" << "Series path";
+  this->m_UI->Series->setHorizontalHeaderLabels( labels );
+
+  std::string main_dir_name = dir.toStdString( );
+  std::queue< std::string > q;
+  q.push( main_dir_name );
+  while( !( q.empty( ) ) )
+  {
+    std::string dir_name = q.front( );
+    q.pop( );
+
+    // Update queue
+    QDir dir( dir_name.c_str( ) );
+    QFileInfoList contents = dir.entryInfoList( );
+    QFileInfoList::const_iterator i = contents.begin( );
+    std::set< std::string > files;
+    for( ; i != contents.end( ); ++i )
+    {
+      if( i->isDir( ) )
+      {
+        std::string new_dir_name = i->absoluteFilePath( ).toStdString( );
+        if( new_dir_name.size( ) > dir_name.size( ) )
+          q.push( new_dir_name );
+      }
+      else
+        files.insert( i->absoluteFilePath( ).toStdString( ) );
+
+    } // rof
+
+    if( files.size( ) > 0 )
+    {
+      this->m_GDCMHelper.Clear( );
+      this->m_GDCMHelper.SetUseSeriesDetails( true );
+      this->m_GDCMHelper.SetLoadMode( 0 );
+      this->m_GDCMHelper.AddRestriction( "0008|0021" );
+      this->m_GDCMHelper.SetFileNames( files.begin( ), files.end( ) );
+
+      gdcm::FileList* flist =
+        this->m_GDCMHelper.GetFirstSingleSerieUIDFileSet( );
+      while( flist != NULL )
+      {
+        if( flist->size( ) > 0 )
+        {
+          this->m_GDCMHelper.OrderFileList( flist );
+          gdcm::File* file = ( *flist )[ 0 ];
+          std::string id =
+            this->m_GDCMHelper.CreateUniqueSeriesIdentifier( file ).c_str( );
+
+          gdcm::FileList::iterator it;
+          for( it = flist->begin( ); it != flist->end( ); ++it )
+            if( *it != NULL )
+              this->m_Series[ id ].push_back( ( *it )->filename );
+
+        } // fi
+        flist = this->m_GDCMHelper.GetNextSingleSerieUIDFileSet( );
+
+      } // elihw
+
+    } // fi
+
+  } // elihw
+
+  // Show series
+  for( auto sIt = this->m_Series.begin( ); sIt != this->m_Series.end( ); ++sIt )
+  {
+    if( sIt->second.size( ) > 0 )
+    {
+      QFileInfo fdir( sIt->second[ 0 ].c_str( ) );
+
+      unsigned long rows = this->m_UI->Series->rowCount( );
+      this->m_UI->Series->insertRow( rows );
+      std::stringstream str_count;
+      str_count << sIt->second.size( );
+      QTableWidgetItem* count_item =
+        new QTableWidgetItem( str_count.str( ).c_str( ) );
+      QTableWidgetItem* uid_item =
+        new QTableWidgetItem( sIt->first.c_str( ) );
+      QTableWidgetItem* dir_item =
+        new QTableWidgetItem( fdir.dir( ).canonicalPath( ) );
+      count_item->setFlags( count_item->flags( ) & ~Qt::ItemIsEditable );
+      uid_item->setFlags( uid_item->flags( ) & ~Qt::ItemIsEditable );
+      dir_item->setFlags( dir_item->flags( ) & ~Qt::ItemIsEditable );
+      this->m_UI->Series->setItem( rows, 0, count_item );
+      this->m_UI->Series->setItem( rows, 1, uid_item );
+      this->m_UI->Series->setItem( rows, 2, dir_item );
+
+    } // fi
+
+  } // rof
+
+  // Restore cursor
+  QApplication::restoreOverrideCursor( );
+}
+
+// -------------------------------------------------------------------------
+std::vector< std::string >* cpPluginsITKIO::DicomSeriesSelectorWidget::
+selectedFilenames( )
+{
+  auto items = this->m_UI->Series->selectedItems( );
+  if( items.size( ) > 0 )
+  {
+    std::string uid =
+      this->m_UI->Series->
+      item( items[ 0 ]->row( ), 1 )->text( ).toStdString( );
+    auto sIt = this->m_Series.find( uid );
+    if( sIt != this->m_Series.end( ) )
+      return( &( sIt->second ) );
+
+  } // fi
+  return( NULL );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::DicomSeriesSelectorWidget::
+_Choose( )
+{
+  QString qdir =
+    QFileDialog::getExistingDirectory(
+      this, tr( "Open Directory" ),
+      this->startDir( ),
+      QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
+      );
+  if( qdir.toStdString( ) != "" )
+    this->setStartDir( qdir );
+}
+
+#endif // cpPlugins_QT4
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/DicomSeriesSelectorWidget.h b/plugins/ITKIO/DicomSeriesSelectorWidget.h
new file mode 100644 (file)
index 0000000..3ac2fbb
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __cpPluginsITKIO__DicomSeriesSelectorWidget__H__
+#define __cpPluginsITKIO__DicomSeriesSelectorWidget__H__
+
+#include <cpPlugins_ITKIO_Export.h>
+#include <cpPlugins/Config.h>
+
+#ifdef cpPlugins_QT4
+
+#include <QWidget>
+#include <gdcmSerieHelper.h>
+
+// -------------------------------------------------------------------------
+namespace Ui
+{
+  class DicomSeriesSelectorWidget;
+}
+
+// -------------------------------------------------------------------------
+namespace cpPluginsITKIO
+{
+  /**
+   */
+  class cpPlugins_ITKIO_EXPORT DicomSeriesSelectorWidget
+    : public QWidget
+  {
+    Q_OBJECT;
+
+  public:
+    typedef DicomSeriesSelectorWidget Self;
+
+  protected:
+    /**
+     */
+    class _GDCMSerieHelper
+      : public gdcm::SerieHelper
+    {
+    public:
+      _GDCMSerieHelper( )
+        {
+        }
+      virtual ~_GDCMSerieHelper( )
+        {
+        }
+      template< class _TIt >
+      void SetFileNames( _TIt b, _TIt e )
+        {
+          for( _TIt i = b; i != e; ++i )
+            this->AddFileName( *i );
+        }
+    };
+
+  public:
+    explicit DicomSeriesSelectorWidget( QWidget* parent = 0 );
+    virtual ~DicomSeriesSelectorWidget( );
+
+    QString startDir( ) const;
+    void setStartDir( const QString& dir, bool build = true );
+
+    std::vector< std::string >* selectedFilenames( );
+
+  protected slots:
+    void _Choose( );
+
+  protected:
+    Ui::DicomSeriesSelectorWidget* m_UI;
+    _GDCMSerieHelper m_GDCMHelper;
+    std::map< std::string, std::vector< std::string > > m_Series;
+  };
+
+} // ecapseman
+
+#endif // cpPlugins_QT4
+
+#endif // __cpPluginsITKIO__DicomSeriesSelectorWidget__H__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/DicomSeriesSelectorWidget.ui b/plugins/ITKIO/DicomSeriesSelectorWidget.ui
new file mode 100644 (file)
index 0000000..d3b648f
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DicomSeriesSelectorWidget</class>
+ <widget class="QWidget" name="DicomSeriesSelectorWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>358</width>
+    <height>299</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <property name="margin">
+    <number>1</number>
+   </property>
+   <property name="spacing">
+    <number>1</number>
+   </property>
+   <item row="0" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="minimumSize">
+        <size>
+         <width>101</width>
+         <height>14</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>101</width>
+         <height>14</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>DICOM directory:</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QLineEdit" name="Directory">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="readOnly">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="ChooseButton">
+       <property name="minimumSize">
+        <size>
+         <width>25</width>
+         <height>25</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>25</width>
+         <height>25</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>...</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="0">
+    <widget class="QTableWidget" name="Series">
+     <property name="selectionMode">
+      <enum>QAbstractItemView::SingleSelection</enum>
+     </property>
+     <property name="selectionBehavior">
+      <enum>QAbstractItemView::SelectRows</enum>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
\ No newline at end of file
diff --git a/plugins/ITKIO/ITKIO.i b/plugins/ITKIO/ITKIO.i
new file mode 100644 (file)
index 0000000..372512e
--- /dev/null
@@ -0,0 +1,28 @@
+header #define ITK_MANUAL_INSTANTIATION
+header #define ITKIOImageBase_HIDDEN
+
+define color_pixels=RGBPixel;RGBAPixel
+define vector_pixels=CovariantVector;Point;Vector;SymmetricSecondRankTensor
+define matrices=Matrix
+define pixels=#scalar_types#;itk::#color_pixels#< #scalar_types# >;std::complex< #real_types# >
+
+cinclude complex
+cinclude itkImage.h
+cinclude itk#color_pixels#.h
+cinclude itkFixedArray.h
+cinclude itk#vector_pixels#.h
+cinclude itk#matrices#.h
+cinclude itkDiffusionTensor3D.h
+cinclude itkConvertPixelBuffer.hxx
+
+define io=ImageFileReader;ImageSeriesReader;ImageFileWriter
+
+tinclude itk#io#:h|hxx
+instances itk::#io#< itk::Image< #pixels#, #pdims# > >
+instances itk::#io#< itk::Image< itk::FixedArray< #scalar_types#, #pdims# >, #pdims# > >
+instances itk::#io#< itk::Image< itk::#vector_pixels#< #real_types#, #pdims# >, #pdims# > >
+instances itk::#io#< itk::Image< itk::#matrices#< #real_types#, #pdims#, #pdims# >, #pdims# > >
+instances itk::#io#< itk::Image< itk::Offset< #pdims# >, #pdims# > >
+instances itk::#io#< itk::Image< itk::DiffusionTensor3D< #real_types# >, 3 > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKIO/ImageReader.cxx b/plugins/ITKIO/ImageReader.cxx
new file mode 100644 (file)
index 0000000..90b032f
--- /dev/null
@@ -0,0 +1,269 @@
+#include <ITKIO/ImageReader.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpPlugins/QT/OpenFileDialog.h>
+
+#define ITKIOImageBase_HIDDEN
+#include <itkImageFileReader.h>
+#include <itkImageSeriesReader.h>
+#include <itkImageIOFactory.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginsITKIO::ImageReader::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::OpenFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::OpenFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileNames" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::ImageReader::
+ImageReader( )
+  : Superclass( )
+{
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+  this->m_Parameters.Clear( );
+  this->m_Parameters.ConfigureAsOpenFileNameList( "FileNames" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileNames",
+    "Image files (*.bmp *.png *.jpg *.jpeg *.dcm *.mhd *.nhdr *.nrrd *.tiff)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::ImageReader::
+~ImageReader( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::ImageReader::
+_GenerateData( )
+{
+  // Get filenames
+  auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" );
+  std::string fname = "";
+  if( fnames.size( ) > 1 )
+  {
+    std::stringstream fname_str;
+    fname_str << fnames[ 0 ] << cpPlugins_PATH_SEPARATOR << fnames[ 1 ];
+    fname = fname_str.str( );
+  }
+  else if( fnames.size( ) == 1 )
+    fname = fnames[ 0 ];
+
+  if( fname != "" )
+  {
+    // Guess image properties
+    itk::ImageIOBase::Pointer io =
+      itk::ImageIOFactory::CreateImageIO(
+        fname.c_str( ), itk::ImageIOFactory::ReadMode
+        );
+    if( io.IsNotNull( ) )
+    {
+      io->SetFileName( fname );
+      io->ReadImageInformation( );
+      bool success = false;
+      unsigned int dim = io->GetNumberOfDimensions( );
+#ifdef cpPlugins_PROCESS_DIMS_1
+      if( dim == 1 ) success = this->_GD0< 1 >( io );
+#endif // cpPlugins_PROCESS_DIMS_1
+#ifdef cpPlugins_PROCESS_DIMS_2
+      if( dim == 2 ) success = this->_GD0< 2 >( io );
+#endif // cpPlugins_PROCESS_DIMS_2
+#ifdef cpPlugins_PROCESS_DIMS_3
+      if( dim == 3 ) success = this->_GD0< 3 >( io );
+#endif // cpPlugins_PROCESS_DIMS_3
+#ifdef cpPlugins_PROCESS_DIMS_4
+      if( dim == 4 ) success = this->_GD0< 4 >( io );
+#endif // cpPlugins_PROCESS_DIMS_4
+      if( !success )
+        this->_Error( "Image dimension not supported." );
+    }
+    else
+      this->_Error(
+        std::string( "Could not create an ImageIO for \"" ) +
+        fnames[ 0 ] +
+        std::string( "\"" )
+        );
+  }
+  else
+    this->_Error( "No image(s) given" );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _Dim >
+bool cpPluginsITKIO::ImageReader::
+_GD0( itk::ImageIOBase* io )
+{
+  typedef unsigned char  uchar;
+  typedef unsigned short ushort;
+  typedef unsigned int   uint;
+  typedef unsigned long  ulong;
+
+  itk::ImageIOBase::IOComponentType ct = io->GetComponentType( );
+  itk::ImageIOBase::IOPixelType pt = io->GetPixelType( );
+
+  bool success = false;
+  if( pt == itk::ImageIOBase::SCALAR )
+  {
+    if( ct == itk::ImageIOBase::CHAR ) success = this->_GD1< char, _Dim >( io );
+    if( ct == itk::ImageIOBase::UCHAR ) success = this->_GD1< uchar, _Dim >( io );
+    if( ct == itk::ImageIOBase::SHORT ) success = this->_GD1< short, _Dim >( io );
+    if( ct == itk::ImageIOBase::USHORT ) success = this->_GD1< ushort, _Dim >( io );
+    if( ct == itk::ImageIOBase::INT ) success = this->_GD1< int, _Dim >( io );
+    if( ct == itk::ImageIOBase::UINT ) success = this->_GD1< uint, _Dim >( io );
+    if( ct == itk::ImageIOBase::LONG ) success = this->_GD1< long, _Dim >( io );
+    if( ct == itk::ImageIOBase::ULONG ) success = this->_GD1< ulong, _Dim >( io );
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< float, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< double, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::RGB )
+  {
+    if( ct == itk::ImageIOBase::CHAR ) success = this->_GD1< itk::RGBPixel< char >, _Dim >( io );
+    if( ct == itk::ImageIOBase::UCHAR ) success = this->_GD1< itk::RGBPixel< uchar >, _Dim >( io );
+    if( ct == itk::ImageIOBase::SHORT ) success = this->_GD1< itk::RGBPixel< short >, _Dim >( io );
+    if( ct == itk::ImageIOBase::USHORT ) success = this->_GD1< itk::RGBPixel< ushort >, _Dim >( io );
+    if( ct == itk::ImageIOBase::INT ) success = this->_GD1< itk::RGBPixel< int >, _Dim >( io );
+    if( ct == itk::ImageIOBase::UINT ) success = this->_GD1< itk::RGBPixel< uint >, _Dim >( io );
+    if( ct == itk::ImageIOBase::LONG ) success = this->_GD1< itk::RGBPixel< long >, _Dim >( io );
+    if( ct == itk::ImageIOBase::ULONG ) success = this->_GD1< itk::RGBPixel< ulong >, _Dim >( io );
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::RGBPixel< float >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::RGBPixel< double >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::RGBA )
+  {
+    if( ct == itk::ImageIOBase::CHAR ) success = this->_GD1< itk::RGBAPixel< char >, _Dim >( io );
+    if( ct == itk::ImageIOBase::UCHAR ) success = this->_GD1< itk::RGBAPixel< uchar >, _Dim >( io );
+    if( ct == itk::ImageIOBase::SHORT ) success = this->_GD1< itk::RGBAPixel< short >, _Dim >( io );
+    if( ct == itk::ImageIOBase::USHORT ) success = this->_GD1< itk::RGBAPixel< ushort >, _Dim >( io );
+    if( ct == itk::ImageIOBase::INT ) success = this->_GD1< itk::RGBAPixel< int >, _Dim >( io );
+    if( ct == itk::ImageIOBase::UINT ) success = this->_GD1< itk::RGBAPixel< uint >, _Dim >( io );
+    if( ct == itk::ImageIOBase::LONG ) success = this->_GD1< itk::RGBAPixel< long >, _Dim >( io );
+    if( ct == itk::ImageIOBase::ULONG ) success = this->_GD1< itk::RGBAPixel< ulong >, _Dim >( io );
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::RGBAPixel< float >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::RGBAPixel< double >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::COMPLEX )
+  {
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< std::complex< float >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< std::complex< double >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::COVARIANTVECTOR )
+  {
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::CovariantVector< float, _Dim >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::CovariantVector< double, _Dim >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::POINT )
+  {
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::Point< float, _Dim >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::Point< double, _Dim >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::VECTOR )
+  {
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::Vector< float, _Dim >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::Vector< double, _Dim >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR )
+  {
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::SymmetricSecondRankTensor< float, _Dim >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::SymmetricSecondRankTensor< double, _Dim >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::DIFFUSIONTENSOR3D )
+  {
+    if( _Dim == 3 )
+    {
+      if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::DiffusionTensor3D< float >, _Dim >( io );
+      if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::DiffusionTensor3D< double >, _Dim >( io );
+    }
+    else
+      this->_Error( "DiffusionTensor3D dimension not supported." );
+  }
+  else if( pt == itk::ImageIOBase::MATRIX )
+  {
+    if( ct == itk::ImageIOBase::FLOAT ) success = this->_GD1< itk::Matrix< float, _Dim, _Dim >, _Dim >( io );
+    if( ct == itk::ImageIOBase::DOUBLE ) success = this->_GD1< itk::Matrix< double, _Dim, _Dim >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::OFFSET )
+  {
+    this->_GD1< itk::Offset< _Dim >, _Dim >( io );
+  }
+  else if( pt == itk::ImageIOBase::FIXEDARRAY )
+  {
+  } // fi
+  return( success );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPixel, unsigned int _Dim >
+bool cpPluginsITKIO::ImageReader::
+_GD1( itk::ImageIOBase* io )
+{
+  typedef itk::Image< _TPixel, _Dim > _TImage;
+
+  // Get filenames
+  auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" );
+  if( fnames.size( ) == 1 || fnames.size( ) == 2 )
+  {
+    std::stringstream fname_str;
+    if( fnames.size( ) == 1 )
+      fname_str << fnames[ 0 ];
+    else
+      fname_str << fnames[ 0 ] << cpPlugins_PATH_SEPARATOR << fnames[ 1 ];
+
+    auto f = this->_CreateITK< itk::ImageFileReader< _TImage > >( );
+    f->SetFileName( fname_str.str( ) );
+    f->SetImageIO( io );
+    try
+    {
+      f->Update( );
+      this->GetOutput( "Output" )->SetITK( f->GetOutput( ) );
+      return( true );
+    }
+    catch( itk::ExceptionObject& err )
+    {
+      this->_Error( err.GetDescription( ) );
+      return( false );
+
+    } // yrt
+  }
+  else // if( fnames.size( ) > 1 )
+  {
+    auto f = this->_CreateITK< itk::ImageSeriesReader< _TImage > >( );
+    auto i = fnames.begin( );
+    std::stringstream dir;
+    dir << *i << cpPlugins_PATH_SEPARATOR;
+    i++;
+    for( ; i != fnames.end( ); ++i )
+      f->AddFileName( dir.str( ) + *i );
+    f->SetImageIO( io );
+    try
+    {
+      f->Update( );
+      this->GetOutput( "Output" )->SetITK( f->GetOutput( ) );
+      return( true );
+    }
+    catch( itk::ExceptionObject& err )
+    {
+      this->_Error( err.GetDescription( ) );
+      return( false );
+
+    } // yrt
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/ImageReader.h b/plugins/ITKIO/ImageReader.h
new file mode 100644 (file)
index 0000000..0e566d6
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __cpPluginsITKIO__ImageReader__h__
+#define __cpPluginsITKIO__ImageReader__h__
+
+#include <cpPlugins_ITKIO_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace itk { class ImageIOBase; }
+
+namespace cpPluginsITKIO
+{
+  /**
+   */
+  class cpPlugins_ITKIO_EXPORT ImageReader
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject( ImageReader, cpPlugins::Pipeline::ProcessObject, IO );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< unsigned int _Dim >
+    inline bool _GD0( itk::ImageIOBase* io );
+
+    template< class _TPixel, unsigned int _Dim >
+    inline bool _GD1( itk::ImageIOBase* io );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKIO__ImageReader__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/ImageWriter.cxx b/plugins/ITKIO/ImageWriter.cxx
new file mode 100644 (file)
index 0000000..a40aad6
--- /dev/null
@@ -0,0 +1,93 @@
+#include <ITKIO/ImageWriter.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpPlugins/QT/SaveFileDialog.h>
+
+#define ITKIOImageBase_HIDDEN
+#include <itkImageFileWriter.h>
+#include <itkImage.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginsITKIO::ImageWriter::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::SaveFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::SaveFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileName" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::ImageWriter::
+ImageWriter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileName",
+    "Image files (*.bmp *.png *.jpg *.jpeg *.dcm *.mhd *.nhdr *.nrrd *.tiff)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKIO::ImageWriter::
+~ImageWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKIO::ImageWriter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ProcessDims_1( o, _GD0 )
+    cpPlugins_Demangle_Image_DiffTensors3D_1( o, _GD1 )
+    this->_Error( "Invalid input image dimension." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKIO::ImageWriter::
+_GD0( _TImage* image )
+{
+  cpPlugins_Demangle_Image_ScalarPixels_1( image, _GD1, _TImage::ImageDimension )
+    cpPlugins_Demangle_Image_ComplexPixels_1( image, _GD1, _TImage::ImageDimension )
+    cpPlugins_Demangle_Image_ColorPixels_1( image, _GD1, _TImage::ImageDimension )
+    cpPlugins_Demangle_Image_VectorPixels_1( image, _GD1, _TImage::ImageDimension )
+    this->_Error( "Invalid input image pixel type." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKIO::ImageWriter::
+_GD1( _TImage* image )
+{
+  typedef itk::ImageFileWriter< _TImage > _TFilter;
+
+  auto f = this->_CreateITK< _TFilter >( );
+  f->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) );
+  f->SetInput( image );
+  try
+  {
+    f->Update( );
+  }
+  catch( itk::ExceptionObject& err )
+  {
+    this->_Error( err.GetDescription( ) );
+
+  } // yrt
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKIO/ImageWriter.h b/plugins/ITKIO/ImageWriter.h
new file mode 100644 (file)
index 0000000..1c0a131
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __cpPluginsITKIO__ImageWriter__h__
+#define __cpPluginsITKIO__ImageWriter__h__
+
+#include <cpPlugins_ITKIO_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKIO
+{
+  /**
+   */
+  class cpPlugins_ITKIO_EXPORT ImageWriter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject( ImageWriter, cpPlugins::Pipeline::ProcessObject, IO );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKIO__ImageWriter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/CastImageFilter.cxx b/plugins/ITKImageGenericFilters_1/CastImageFilter.cxx
new file mode 100644 (file)
index 0000000..a7cf31b
--- /dev/null
@@ -0,0 +1,64 @@
+#include <ITKImageGenericFilters_1/CastImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkCastImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::CastImageFilter::
+CastImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+  this->m_Parameters.ConfigureAsScalarTypesChoices( "OutputPixelType" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::CastImageFilter::
+~CastImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageGenericFilters_1::CastImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInput >
+void cpPluginsITKImageGenericFilters_1::CastImageFilter::
+_GD0( _TInput* input )
+{
+  std::string o_type =
+    this->m_Parameters.GetSelectedChoice( "OutputPixelType" );
+  if( o_type == "char" )        this->_GD1< _TInput, char >( input );
+  else if( o_type == "short" )  this->_GD1< _TInput, short >( input );
+  else if( o_type == "int" )    this->_GD1< _TInput, int >( input );
+  else if( o_type == "long" )   this->_GD1< _TInput, long >( input );
+  else if( o_type == "uchar" )  this->_GD1< _TInput, unsigned char >( input );
+  else if( o_type == "ushort" ) this->_GD1< _TInput, unsigned short >( input );
+  else if( o_type == "uint" )   this->_GD1< _TInput, unsigned int >( input );
+  else if( o_type == "ulong" )  this->_GD1< _TInput, unsigned long >( input );
+  else if( o_type == "float" )  this->_GD1< _TInput, float >( input );
+  else if( o_type == "double" ) this->_GD1< _TInput, double >( input );
+}
+
+// -------------------------------------------------------------------------
+template< class _TInput, class _TOutputPixel >
+void cpPluginsITKImageGenericFilters_1::CastImageFilter::
+_GD1( _TInput* input )
+{
+  typedef itk::Image< _TOutputPixel, _TInput::ImageDimension > _TOutput;
+  typedef itk::CastImageFilter< _TInput, _TOutput > _TFilter;
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( input );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/CastImageFilter.h b/plugins/ITKImageGenericFilters_1/CastImageFilter.h
new file mode 100644 (file)
index 0000000..973e0d9
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKImageGenericFilters_1__CastImageFilter__h__
+#define __cpPluginsITKImageGenericFilters_1__CastImageFilter__h__
+
+#include <cpPlugins_ITKImageGenericFilters_1_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKImageGenericFilters_1
+{
+  /**
+   */
+  class cpPlugins_ITKImageGenericFilters_1_EXPORT CastImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      CastImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageFilters
+      );
+
+  protected:
+    template< class _TInput >
+    inline void _GD0( _TInput* input );
+
+    template< class _TInput, class _TOutputPixel >
+    inline void _GD1( _TInput* input );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKImageGenericFilters_1__CastImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/ITKImageGenericFilters_1.i b/plugins/ITKImageGenericFilters_1/ITKImageGenericFilters_1.i
new file mode 100644 (file)
index 0000000..8c62830
--- /dev/null
@@ -0,0 +1,21 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude itkUnaryFunctorImageFilter:h|hxx
+
+define filters_1=CastImageFilter;ShiftScaleImageFilter
+define i_scalars=#scalar_types#
+define o_scalars=#scalar_types#
+
+tinclude itk#filters_1#:h|hxx
+instances itk::#filters_1#< itk::Image< #i_scalars#, #pdims# >, itk::Image< #o_scalars#, #pdims# > >
+
+tinclude itkRegionOfInterestImageFilter:h|hxx
+instances itk::RegionOfInterestImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# > >
+
+tinclude itkMinimumMaximumImageCalculator:h|hxx
+instances itk::MinimumMaximumImageCalculator< itk::Image< #scalar_types#, #pdims# > >
+
+tinclude cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold:h|hxx
+instances cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< itk::Image< #scalar_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.cxx b/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.cxx
new file mode 100644 (file)
index 0000000..a4e815b
--- /dev/null
@@ -0,0 +1,63 @@
+#include <ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/BoundingBox.h>
+
+#include <itkImage.h>
+#include <cpExtensions/Algorithms/ImageToBoundingBoxFromThreshold.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold::
+ImageToBoundingBoxFromThreshold( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::BoundingBox >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "LowerThreshold", 0 );
+  this->m_Parameters.ConfigureAsReal( "UpperThreshold", 1 );
+  this->m_Parameters.ConfigureAsUint( "PAD", 0 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold::
+~ImageToBoundingBoxFromThreshold( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKImageGenericFilters_1::ImageToBoundingBoxFromThreshold::
+_GD0( _TImage* image )
+{
+  typedef
+    cpExtensions::Algorithms::ImageToBoundingBoxFromThreshold< _TImage >
+    _TFilter;
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetImage( image );
+  filter->SetLowerThreshold( this->m_Parameters.GetReal( "LowerThreshold" ) );
+  filter->SetUpperThreshold( this->m_Parameters.GetReal( "UpperThreshold" ) );
+  filter->SetPAD( this->m_Parameters.GetUint( "PAD" ) );
+  filter->Compute( );
+
+  // Create output
+  auto reg = filter->GetRegion( );
+  auto bb = this->GetOutput< cpInstances::DataObjects::BoundingBox >( "Output" );
+  typename _TImage::PointType p0, p1;
+  image->TransformIndexToPhysicalPoint( reg.GetIndex( ), p0 );
+  image->TransformIndexToPhysicalPoint( reg.GetIndex( ) + reg.GetSize( ), p1 );
+  bb->SetMinimum( p0 );
+  bb->SetMaximum( p1 );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h b/plugins/ITKImageGenericFilters_1/ImageToBoundingBoxFromThreshold.h
new file mode 100644 (file)
index 0000000..92c8613
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKImageGenericFilters_1__ImageToBoundingBoxFromThreshold__h__
+#define __cpPluginsITKImageGenericFilters_1__ImageToBoundingBoxFromThreshold__h__
+
+#include <cpPlugins_ITKImageGenericFilters_1_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKImageGenericFilters_1
+{
+  /**
+   */
+  class cpPlugins_ITKImageGenericFilters_1_EXPORT ImageToBoundingBoxFromThreshold
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      ImageToBoundingBoxFromThreshold,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageFeatures
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKImageGenericFilters_1__ImageToBoundingBoxFromThreshold__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.cxx b/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.cxx
new file mode 100644 (file)
index 0000000..c30cad3
--- /dev/null
@@ -0,0 +1,120 @@
+#include <ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Mesh.h>
+
+#include <itkImage.h>
+#include <itkMinimumMaximumImageCalculator.h>
+#include <vtkPolyData.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator::
+MinimumMaximumImageCalculator( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+  typedef cpInstances::DataObjects::Mesh _TMesh;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TMesh >( "Maximum" );
+  this->_ConfigureOutput< _TMesh >( "Minimum" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator::
+~MinimumMaximumImageCalculator( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKImageGenericFilters_1::MinimumMaximumImageCalculator::
+_GD0( _TImage* input )
+{
+  typedef itk::MinimumMaximumImageCalculator< _TImage > _TFilter;
+  typedef typename _TImage::IndexType _TIndex;
+  typedef typename _TImage::PointType _TPoint;
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetImage( input );
+  filter->Compute( );
+
+  _TIndex min_idx = filter->GetIndexOfMinimum( );
+  _TIndex max_idx = filter->GetIndexOfMaximum( );
+
+  _TPoint min_pnt, max_pnt;
+  input->TransformIndexToPhysicalPoint( min_idx, min_pnt );
+  input->TransformIndexToPhysicalPoint( max_idx, max_pnt );
+
+  auto min_pd = this->GetOutputData< vtkPolyData >( "Minimum" );
+  if( min_pd == NULL )
+  {
+    auto points = vtkSmartPointer< vtkPoints >::New( );
+    auto verts = vtkSmartPointer< vtkCellArray >::New( );
+    auto lines = vtkSmartPointer< vtkCellArray >::New( );
+    auto polys = vtkSmartPointer< vtkCellArray >::New( );
+    auto strips = vtkSmartPointer< vtkCellArray >::New( );
+    auto pd = vtkSmartPointer< vtkPolyData >::New( );
+    pd->SetPoints( points );
+    pd->SetVerts( verts );
+    pd->SetLines( lines );
+    pd->SetPolys( polys );
+    pd->SetStrips( strips );
+
+    points->InsertNextPoint( 0, 0, 0 );
+    verts->InsertNextCell( 1 );
+    verts->InsertCellPoint( 0 );
+
+    this->GetOutput( "Minimum" )->SetVTK( pd );
+    min_pd = this->GetOutputData< vtkPolyData >( "Minimum" );
+
+  } // fi
+
+  if( _TImage::ImageDimension == 1 )
+    min_pd->GetPoints( )->SetPoint( 0, min_pnt[ 0 ], 0, 0 );
+  else if( _TImage::ImageDimension == 2 )
+    min_pd->GetPoints( )->SetPoint( 0, min_pnt[ 0 ], min_pnt[ 1 ], 0 );
+  else if( _TImage::ImageDimension > 2 )
+    min_pd->GetPoints( )->SetPoint( 0, min_pnt[ 0 ], min_pnt[ 1 ], min_pnt[ 2 ] );
+
+  auto max_pd = this->GetOutputData< vtkPolyData >( "Maximum" );
+  if( max_pd == NULL )
+  {
+    auto points = vtkSmartPointer< vtkPoints >::New( );
+    auto verts = vtkSmartPointer< vtkCellArray >::New( );
+    auto lines = vtkSmartPointer< vtkCellArray >::New( );
+    auto polys = vtkSmartPointer< vtkCellArray >::New( );
+    auto strips = vtkSmartPointer< vtkCellArray >::New( );
+    auto pd = vtkSmartPointer< vtkPolyData >::New( );
+    pd->SetPoints( points );
+    pd->SetVerts( verts );
+    pd->SetLines( lines );
+    pd->SetPolys( polys );
+    pd->SetStrips( strips );
+
+    points->InsertNextPoint( 0, 0, 0 );
+    verts->InsertNextCell( 1 );
+    verts->InsertCellPoint( 0 );
+
+    this->GetOutput( "Maximum" )->SetVTK( pd );
+    max_pd = this->GetOutputData< vtkPolyData >( "Maximum" );
+
+  } // fi
+
+  if( _TImage::ImageDimension == 1 )
+    max_pd->GetPoints( )->SetPoint( 0, max_pnt[ 0 ], 0, 0 );
+  else if( _TImage::ImageDimension == 2 )
+    max_pd->GetPoints( )->SetPoint( 0, max_pnt[ 0 ], max_pnt[ 1 ], 0 );
+  else if( _TImage::ImageDimension > 2 )
+    max_pd->GetPoints( )->SetPoint( 0, max_pnt[ 0 ], max_pnt[ 1 ], max_pnt[ 2 ] );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h b/plugins/ITKImageGenericFilters_1/MinimumMaximumImageCalculator.h
new file mode 100644 (file)
index 0000000..a52c685
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKImageGenericFilters_1__MinimumMaximumImageCalculator__h__
+#define __cpPluginsITKImageGenericFilters_1__MinimumMaximumImageCalculator__h__
+
+#include <cpPlugins_ITKImageGenericFilters_1_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKImageGenericFilters_1
+{
+  /**
+   */
+  class cpPlugins_ITKImageGenericFilters_1_EXPORT MinimumMaximumImageCalculator
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      MinimumMaximumImageCalculator,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageFeatures
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* input );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsImageGenericFilters__MinimumMaximumImageCalculator__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.cxx b/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.cxx
new file mode 100644 (file)
index 0000000..52ec23b
--- /dev/null
@@ -0,0 +1,79 @@
+#include <ITKImageGenericFilters_1/RegionOfInterestImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/BoundingBox.h>
+#include <cpInstances/DataObjects/Image_Demanglers.h>
+
+#include <itkRGBPixel.h>
+#include <itkRGBAPixel.h>
+#include <itkRegionOfInterestImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter::
+RegionOfInterestImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+  typedef cpInstances::DataObjects::BoundingBox _TBBox;
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureInput< _TBBox >( "BoundingBox", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter::
+~RegionOfInterestImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKImageGenericFilters_1::RegionOfInterestImageFilter::
+_GD0( _TImage* input )
+{
+  typedef cpInstances::DataObjects::BoundingBox _TBBox;
+  typedef itk::RegionOfInterestImageFilter< _TImage, _TImage > _TFilter;
+  typedef typename _TImage::IndexType  _TIndex;
+  typedef typename _TImage::PointType  _TPoint;
+  typedef typename _TImage::RegionType _TRegion;
+  typedef typename _TImage::SizeType   _TSize;
+
+  auto bb = this->GetInput< _TBBox >( "BoundingBox" );
+
+  _TRegion in_region = input->GetRequestedRegion( );
+  _TIndex in_i0 = in_region.GetIndex( );
+  _TIndex in_i1 = in_i0 + in_region.GetSize( );
+  _TIndex i0, i1;
+  input->TransformPhysicalPointToIndex( bb->GetMinimum< _TPoint >( ), i0 );
+  input->TransformPhysicalPointToIndex( bb->GetMaximum< _TPoint >( ), i1 );
+  for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+  {
+    if( i0[ d ] < in_i0[ d ] ) i0[ d ] = in_i0[ d ];
+    if( i1[ d ] > in_i1[ d ] ) i1[ d ] = in_i1[ d ];
+
+  } // rof
+
+  _TSize size;
+  for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+    size[ d ] = i1[ d ] - i0[ d ];
+
+  _TRegion region;
+  region.SetIndex( i0 );
+  region.SetSize( size );
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( input );
+  filter->SetRegionOfInterest( region );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.h b/plugins/ITKImageGenericFilters_1/RegionOfInterestImageFilter.h
new file mode 100644 (file)
index 0000000..5d29887
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKImageGenericFilters_1__RegionOfInterestImageFilter__h__
+#define __cpPluginsITKImageGenericFilters_1__RegionOfInterestImageFilter__h__
+
+#include <cpPlugins_ITKImageGenericFilters_1_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKImageGenericFilters_1
+{
+  /**
+   */
+  class cpPlugins_ITKImageGenericFilters_1_EXPORT RegionOfInterestImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      RegionOfInterestImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* input );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKImageGenericFilters_1__RegionOfInterestImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.cxx b/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.cxx
new file mode 100644 (file)
index 0000000..16c64da
--- /dev/null
@@ -0,0 +1,62 @@
+#include <ITKImageInterpolators/BSplineInterpolateImageFunction.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <itkImage.h>
+#include <itkBSplineInterpolateImageFunction.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction::
+BSplineInterpolateImageFunction( )
+  : Superclass( )
+{
+  this->m_Parameters.ConfigureAsUint( "SplineOrder", 3 );
+  this->m_Parameters.ConfigureAsBool( "UseImageDirection", true );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction::
+~BSplineInterpolateImageFunction( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction::
+CreateInterpolator(
+  itk::LightObject* image, const std::string& precision_type
+  )
+{
+  this->m_PrecisionType = precision_type;
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( image, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction::
+_GenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction::
+_GD0( _TImage* image )
+{
+  if( this->m_PrecisionType == "float" )
+    this->_GD1< _TImage, float >( image );
+  else if( this->m_PrecisionType == "double" )
+    this->_GD1< _TImage, double >( image );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TScalar >
+void cpPluginsITKImageInterpolators::BSplineInterpolateImageFunction::
+_GD1( _TImage* image )
+{
+  typedef itk::BSplineInterpolateImageFunction< _TImage, _TScalar, _TScalar > _TFunction;
+
+  auto function = this->_CreateITK< _TFunction >( );
+  function->SetSplineOrder( this->m_Parameters.GetUint( "SplineOrder" ) );
+  function->SetUseImageDirection( this->m_Parameters.GetBool( "UseImageDirection" ) );
+  this->GetOutput( "Output" )->SetITK( function );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.h b/plugins/ITKImageInterpolators/BSplineInterpolateImageFunction.h
new file mode 100644 (file)
index 0000000..bb0ee9f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __cpPluginsITKImageInterpolators__BSplineInterpolateImageFunction__h__
+#define __cpPluginsITKImageInterpolators__BSplineInterpolateImageFunction__h__
+
+#include <cpPlugins_ITKImageInterpolators_Export.h>
+#include <ITKImageInterpolators/InterpolateImageFunction.h>
+
+namespace cpPluginsITKImageInterpolators
+{
+  /**
+   */
+  class cpPlugins_ITKImageInterpolators_EXPORT BSplineInterpolateImageFunction
+    : public InterpolateImageFunction
+  {
+    cpPluginsObject(
+      BSplineInterpolateImageFunction,
+      InterpolateImageFunction,
+      ITKImageInterpolators
+      );
+
+  public:
+    virtual void CreateInterpolator(
+      itk::LightObject* image,
+      const std::string& precision_type
+      ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage, class _TScalar >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKImageInterpolators__BSplineInterpolateImageFunction__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/ITKImageInterpolators.i b/plugins/ITKImageInterpolators/ITKImageInterpolators.i
new file mode 100644 (file)
index 0000000..c6c5f9c
--- /dev/null
@@ -0,0 +1,25 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define v=FixedArray
+define i_real=#real_types#
+define o_real=#real_types#
+define interp=Linear
+
+tinclude itkImageFunction:h|hxx
+tinclude itk#interp#InterpolateImageFunction:h|hxx
+tinclude itkVectorLinearInterpolateImageFunction:h|hxx
+
+cinclude itk#v#.h
+cinclude itkImage.h
+
+instances itk::ImageFunction< itk::Image< #scalar_types#, #pdims# >, #i_real#, #o_real# >
+instances itk::#interp#InterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types# >
+
+instances itk::VectorLinearInterpolateImageFunction< itk::Image< itk::#v#< #i_real#, #pdims# >, #pdims# >, #o_real# >
+
+tinclude itkBSplineDecompositionImageFilter:h|hxx
+tinclude itkBSplineInterpolateImageFunction:h|hxx
+instances itk::BSplineInterpolateImageFunction< itk::Image< #scalar_types#, #pdims# >, #real_types#, #real_types# >
+instances itk::BSplineDecompositionImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/InterpolateImageFunction.cxx b/plugins/ITKImageInterpolators/InterpolateImageFunction.cxx
new file mode 100644 (file)
index 0000000..b58fba5
--- /dev/null
@@ -0,0 +1,39 @@
+#include <ITKImageInterpolators/InterpolateImageFunction.h>
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::InterpolateImageFunction::
+SetITK( itk::LightObject* o )
+{
+  if( this->m_ITK.GetPointer( ) != o )
+    this->m_ITK = o;
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::InterpolateImageFunction::
+SetVTK( vtkObjectBase* o )
+{
+  if( this->m_VTK.GetPointer( ) != o )
+    this->m_VTK = o;
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageInterpolators::InterpolateImageFunction::
+InterpolateImageFunction( )
+  : Superclass( )
+{
+  this->_ConfigureOutput< cpPlugins::Pipeline::DataObject >( "Output" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageInterpolators::InterpolateImageFunction::
+~InterpolateImageFunction( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::InterpolateImageFunction::
+_GenerateData( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/InterpolateImageFunction.h b/plugins/ITKImageInterpolators/InterpolateImageFunction.h
new file mode 100644 (file)
index 0000000..d3fd440
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __cpPluginsITKImageInterpolators__InterpolateImageFunction__h__
+#define __cpPluginsITKImageInterpolators__InterpolateImageFunction__h__
+
+#include <cpPlugins_ITKImageInterpolators_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKImageInterpolators
+{
+  /**
+   */
+  class cpPlugins_ITKImageInterpolators_EXPORT InterpolateImageFunction
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+  public:
+    typedef InterpolateImageFunction              Self;
+    typedef cpPlugins::Pipeline::ProcessObject Superclass;
+    typedef itk::SmartPointer< Self >             Pointer;
+    typedef itk::SmartPointer< const Self >       ConstPointer;
+
+  public:
+    itkTypeMacro( BaseFilter, cpPlugins::Pipeline::ProcessObject );
+    cpPlugins_Id_Macro( InterpolateImageFunction, ImageInterpolators );
+
+  public:
+    virtual void SetITK( itk::LightObject* o ) cpPlugins_OVERRIDE;
+    virtual void SetVTK( vtkObjectBase* o ) cpPlugins_OVERRIDE;
+
+  protected:
+    InterpolateImageFunction( );
+    virtual ~InterpolateImageFunction( );
+
+  public:
+    virtual void CreateInterpolator(
+      itk::LightObject* image,
+      const std::string& precision_type
+      ) = 0;
+
+  protected:
+    virtual void _GenerateData( ) cpPlugins_OVERRIDE;
+
+  private:
+    // Purposely not implemented.
+    InterpolateImageFunction( const Self& other );
+    Self& operator=( const Self& other );
+
+  protected:
+    std::string m_PrecisionType;
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKImageInterpolators__InterpolateImageFunction__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.cxx b/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.cxx
new file mode 100644 (file)
index 0000000..5317a29
--- /dev/null
@@ -0,0 +1,58 @@
+#include <ITKImageInterpolators/LinearInterpolateImageFunction.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <itkImage.h>
+#include <itkLinearInterpolateImageFunction.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageInterpolators::LinearInterpolateImageFunction::
+LinearInterpolateImageFunction( )
+  : Superclass( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKImageInterpolators::LinearInterpolateImageFunction::
+~LinearInterpolateImageFunction( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction::
+CreateInterpolator(
+  itk::LightObject* image, const std::string& precision_type
+  )
+{
+  this->m_PrecisionType = precision_type;
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( image, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction::
+_GenerateData( )
+{
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction::
+_GD0( _TImage* image )
+{
+  if( this->m_PrecisionType == "float" )
+    this->_GD1< _TImage, float >( image );
+  else if( this->m_PrecisionType == "double" )
+    this->_GD1< _TImage, double >( image );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TScalar >
+void cpPluginsITKImageInterpolators::LinearInterpolateImageFunction::
+_GD1( _TImage* image )
+{
+  typedef itk::LinearInterpolateImageFunction< _TImage, _TScalar > _TFunction;
+
+  auto function = this->_CreateITK< _TFunction >( );
+  this->GetOutput( "Output" )->SetITK( function );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.h b/plugins/ITKImageInterpolators/LinearInterpolateImageFunction.h
new file mode 100644 (file)
index 0000000..a6fa94c
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __cpPluginsITKImageInterpolators__LinearInterpolateImageFunction__h__
+#define __cpPluginsITKImageInterpolators__LinearInterpolateImageFunction__h__
+
+#include <cpPlugins_ITKImageInterpolators_Export.h>
+#include <ITKImageInterpolators/InterpolateImageFunction.h>
+
+namespace cpPluginsITKImageInterpolators
+{
+  /**
+   */
+  class cpPlugins_ITKImageInterpolators_EXPORT LinearInterpolateImageFunction
+    : public InterpolateImageFunction
+  {
+    cpPluginsObject(
+      LinearInterpolateImageFunction,
+      InterpolateImageFunction,
+      ITKImageInterpolators
+      );
+
+  public:
+    virtual void CreateInterpolator(
+      itk::LightObject* image,
+      const std::string& precision_type
+      ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage, class _TScalar >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKImageInterpolators__LinearInterpolateImageFunction__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKLevelSetFilters/ITKLevelSetFilters.i b/plugins/ITKLevelSetFilters/ITKLevelSetFilters.i
new file mode 100644 (file)
index 0000000..a1c4a75
--- /dev/null
@@ -0,0 +1,28 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define base=ZeroCrossingImageFilter;SparseFieldLevelSetImageFilter
+define filters=SegmentationLevelSetImageFilter;ThresholdSegmentationLevelSetImageFilter;LaplacianSegmentationLevelSetImageFilter
+define functions=LevelSetFunction
+define ls_functions=SegmentationLevelSetFunction;ThresholdSegmentationLevelSetFunction;LaplacianSegmentationLevelSetFunction
+
+define i_reals=#real_types#
+define o_reals=#real_types#
+
+tinclude itk#functions#:h|hxx
+tinclude itk#ls_functions#:h|hxx
+tinclude itk#base#:h|hxx
+tinclude itk#filters#:h|hxx
+tinclude itkSparseFieldLayer:h|hxx
+tinclude itkObjectStore:h|hxx
+
+cinclude itkLinearInterpolateImageFunction.hxx
+
+instances itk::SparseFieldLayer< itk::SparseFieldLevelSetNode< itk::Index< #pdims# > > >
+instances itk::ObjectStore< itk::SparseFieldLevelSetNode< itk::Index< #pdims# > > >
+
+instances itk::#functions#< itk::Image< #i_reals#, #pdims# > >
+instances itk::#ls_functions#< itk::Image< #i_reals#, #pdims# >, itk::Image< #o_reals#, #pdims# > >
+instances itk::#base#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #i_reals#, #pdims# > >
+instances itk::#filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #i_reals#, #pdims# >, #o_reals# >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.cxx b/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.cxx
new file mode 100644 (file)
index 0000000..c45c75a
--- /dev/null
@@ -0,0 +1,72 @@
+#include <ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkLaplacianSegmentationLevelSetImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter::
+LaplacianSegmentationLevelSetImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Feature", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "PropagationScaling", 1 );
+  this->m_Parameters.ConfigureAsReal( "CurvatureScaling", 1 );
+  this->m_Parameters.ConfigureAsReal( "MaximumRMSError", 0.02 );
+  this->m_Parameters.ConfigureAsReal( "IsoSurfaceValue", 0 );
+  this->m_Parameters.ConfigureAsUint( "NumberOfIterations", 100 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter::
+~LaplacianSegmentationLevelSetImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_RealPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter::
+_GD0( _TImage* image )
+{
+  auto f = this->GetInputData( "Feature" );
+  cpPlugins_Demangle_Image_RealPixels_2( f, _GD1, _TImage::ImageDimension, image )
+    this->_Error( "Invalid feature image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFeature, class _TImage >
+void cpPluginsITKLevelSetFilters::LaplacianSegmentationLevelSetImageFilter::
+_GD1( _TFeature* feature, _TImage* image )
+{
+  typedef typename _TFeature::PixelType _TScalar;
+  typedef
+    itk::LaplacianSegmentationLevelSetImageFilter< _TImage, _TFeature, _TScalar >
+    _TFilter;
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetFeatureImage( feature );
+  filter->SetPropagationScaling( this->m_Parameters.GetReal( "PropagationScaling" ) );
+  filter->SetCurvatureScaling( this->m_Parameters.GetReal( "CurvatureScaling" ) );
+  filter->SetMaximumRMSError( this->m_Parameters.GetReal( "MaximumRMSError" ) );
+  filter->SetIsoSurfaceValue( this->m_Parameters.GetReal( "IsoSurfaceValue" ) );
+  filter->SetNumberOfIterations( this->m_Parameters.GetUint( "NumberOfIterations" ) );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h b/plugins/ITKLevelSetFilters/LaplacianSegmentationLevelSetImageFilter.h
new file mode 100644 (file)
index 0000000..d82aa9b
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKLevelSetFilters__LaplacianSegmentationLevelSetImageFilter__h__
+#define __cpPluginsITKLevelSetFilters__LaplacianSegmentationLevelSetImageFilter__h__
+
+#include <cpPlugins_ITKLevelSetFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKLevelSetFilters
+{
+  /**
+   */
+  class cpPlugins_ITKLevelSetFilters_EXPORT LaplacianSegmentationLevelSetImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      LaplacianSegmentationLevelSetImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageLevelSetFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TFeature, class _TImage >
+    inline void _GD1( _TFeature* feature, _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKLevelSetFilters__LaplacianSegmentationLevelSetImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.cxx b/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.cxx
new file mode 100644 (file)
index 0000000..9847f54
--- /dev/null
@@ -0,0 +1,76 @@
+#include <ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkThresholdSegmentationLevelSetImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter::
+ThresholdSegmentationLevelSetImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Feature", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "PropagationScaling", 1 );
+  this->m_Parameters.ConfigureAsReal( "CurvatureScaling", 1 );
+  this->m_Parameters.ConfigureAsReal( "MaximumRMSError", 0.02 );
+  this->m_Parameters.ConfigureAsReal( "UpperThreshold", 1 );
+  this->m_Parameters.ConfigureAsReal( "LowerThreshold", 0 );
+  this->m_Parameters.ConfigureAsReal( "IsoSurfaceValue", 0 );
+  this->m_Parameters.ConfigureAsUint( "NumberOfIterations", 100 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter::
+~ThresholdSegmentationLevelSetImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_RealPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image dimension." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter::
+_GD0( _TImage* image )
+{
+  auto f = this->GetInputData( "Feature" );
+  cpPlugins_Demangle_Image_RealPixels_2( f, _GD1, _TImage::ImageDimension, image )
+    this->_Error( "Invalid feature image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TFeature, class _TImage >
+void cpPluginsITKLevelSetFilters::ThresholdSegmentationLevelSetImageFilter::
+_GD1( _TFeature* feature, _TImage* image )
+{
+  typedef typename _TFeature::PixelType _TScalar;
+  typedef
+    itk::ThresholdSegmentationLevelSetImageFilter< _TImage, _TFeature, _TScalar >
+    _TFilter;
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetFeatureImage( feature );
+  filter->SetPropagationScaling( this->m_Parameters.GetReal( "PropagationScaling" ) );
+  filter->SetCurvatureScaling( this->m_Parameters.GetReal( "CurvatureScaling" ) );
+  filter->SetMaximumRMSError( this->m_Parameters.GetReal( "MaximumRMSError" ) );
+  filter->SetUpperThreshold( this->m_Parameters.GetReal( "UpperThreshold" ) );
+  filter->SetLowerThreshold( this->m_Parameters.GetReal( "LowerThreshold" ) );
+  filter->SetIsoSurfaceValue( this->m_Parameters.GetReal( "IsoSurfaceValue" ) );
+  filter->SetNumberOfIterations( this->m_Parameters.GetUint( "NumberOfIterations" ) );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h b/plugins/ITKLevelSetFilters/ThresholdSegmentationLevelSetImageFilter.h
new file mode 100644 (file)
index 0000000..c8a071d
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKLevelSetFilters__ThresholdSegmentationLevelSetImageFilter__h__
+#define __cpPluginsITKLevelSetFilters__ThresholdSegmentationLevelSetImageFilter__h__
+
+#include <cpPlugins_ITKLevelSetFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKLevelSetFilters
+{
+  /**
+   */
+  class cpPlugins_ITKLevelSetFilters_EXPORT ThresholdSegmentationLevelSetImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      ThresholdSegmentationLevelSetImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageLevelSetFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TFeature, class _TImage >
+    inline void _GD1( _TFeature* feature, _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKLevelSetFilters__ThresholdSegmentationLevelSetImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKMorphology/ITKMorphology.i b/plugins/ITKMorphology/ITKMorphology.i
new file mode 100644 (file)
index 0000000..212fd21
--- /dev/null
@@ -0,0 +1,7 @@
+** TODO:
+header #undef ITK_MANUAL_INSTANTIATION
+
+tinclude itkBinaryFillholeImageFilter:h|hxx
+instances itk::BinaryFillholeImageFilter< itk::Image< #scalar_types#, #vdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKNeighborhoodOperatorFilters/ITKNeighborhoodOperatorFilters.i b/plugins/ITKNeighborhoodOperatorFilters/ITKNeighborhoodOperatorFilters.i
new file mode 100644 (file)
index 0000000..943b07f
--- /dev/null
@@ -0,0 +1,19 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define filters_1=LaplacianImageFilter
+define i_reals=#real_types#
+define o_reals=#real_types#
+
+tinclude itkNeighborhoodInnerProduct:h|hxx
+instances itk::NeighborhoodInnerProduct< itk::Image< float, #pdims# >, float, double >
+
+tinclude itkNeighborhoodOperatorImageFilter:h|hxx
+instances itk::NeighborhoodOperatorImageFilter< itk::Image< float, #pdims# >, itk::Image< float, #pdims# >, float >
+
+tinclude itkLaplacianOperator:h|hxx
+instances itk::LaplacianOperator< float, #pdims#, itk::NeighborhoodAllocator< float > >
+
+tinclude itk#filters_1#:h|hxx
+instances itk::#filters_1#< itk::Image< #i_reals#, #pdims# >, itk::Image< #o_reals#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.cxx b/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.cxx
new file mode 100644 (file)
index 0000000..7dcf749
--- /dev/null
@@ -0,0 +1,52 @@
+#include <ITKParaMorphology/BinaryDilateParaImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Image_Demanglers.h>
+
+#include <itkBinaryDilateParaImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKParaMorphology::BinaryDilateParaImageFilter::
+BinaryDilateParaImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+  this->m_Parameters.ConfigureAsReal( "Radius", 3 );
+  this->m_Parameters.ConfigureAsBool( "Circular", true );
+  this->m_Parameters.ConfigureAsBool( "UseImageSpacing", false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKParaMorphology::BinaryDilateParaImageFilter::
+~BinaryDilateParaImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKParaMorphology::BinaryDilateParaImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "No valid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKParaMorphology::BinaryDilateParaImageFilter::
+_GD0( _TImage* image )
+{
+  typedef itk::BinaryDilateParaImageFilter< _TImage > _TFilter;
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetRadius( this->m_Parameters.GetReal( "Radius" ) );
+  filter->SetCircular( this->m_Parameters.GetBool( "Circular" ) );
+  filter->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.h b/plugins/ITKParaMorphology/BinaryDilateParaImageFilter.h
new file mode 100644 (file)
index 0000000..1325985
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKParaMorphology__BinaryDilateParaImageFilter__h__
+#define __cpPluginsITKParaMorphology__BinaryDilateParaImageFilter__h__
+
+#include <cpPlugins_ITKParaMorphology_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKParaMorphology
+{
+  /**
+   */
+  class cpPlugins_ITKParaMorphology_EXPORT BinaryDilateParaImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      BinaryDilateParaImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageMorphology
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKParaMorphology__BinaryDilateParaImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.cxx b/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.cxx
new file mode 100644 (file)
index 0000000..30fb4b8
--- /dev/null
@@ -0,0 +1,52 @@
+#include <ITKParaMorphology/BinaryErodeParaImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Image_Demanglers.h>
+
+#include <itkBinaryErodeParaImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKParaMorphology::BinaryErodeParaImageFilter::
+BinaryErodeParaImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+  this->m_Parameters.ConfigureAsReal( "Radius", 3 );
+  this->m_Parameters.ConfigureAsBool( "Circular", true );
+  this->m_Parameters.ConfigureAsBool( "UseImageSpacing", false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKParaMorphology::BinaryErodeParaImageFilter::
+~BinaryErodeParaImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKParaMorphology::BinaryErodeParaImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "No valid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKParaMorphology::BinaryErodeParaImageFilter::
+_GD0( _TImage* image )
+{
+  typedef itk::BinaryErodeParaImageFilter< _TImage > _TFilter;
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetRadius( this->m_Parameters.GetReal( "Radius" ) );
+  filter->SetCircular( this->m_Parameters.GetBool( "Circular" ) );
+  filter->SetUseImageSpacing( this->m_Parameters.GetBool( "UseImageSpacing" ) );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.h b/plugins/ITKParaMorphology/BinaryErodeParaImageFilter.h
new file mode 100644 (file)
index 0000000..adae5e9
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKParaMorphology__BinaryErodeParaImageFilter__h__
+#define __cpPluginsITKParaMorphology__BinaryErodeParaImageFilter__h__
+
+#include <cpPlugins_ITKParaMorphology_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKParaMorphology
+{
+  /**
+   */
+  class cpPlugins_ITKParaMorphology_EXPORT BinaryErodeParaImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      BinaryErodeParaImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageMorphology
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKParaMorphology__BinaryErodeParaImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKParaMorphology/ITKParaMorphology.i b/plugins/ITKParaMorphology/ITKParaMorphology.i
new file mode 100644 (file)
index 0000000..fade5c4
--- /dev/null
@@ -0,0 +1,18 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define itk_filters=BinaryDilateParaImageFilter;BinaryErodeParaImageFilter
+define i_scalars=#scalar_types#
+define o_scalars=#scalar_types#
+define booleans=false;true
+
+tinclude itkParabolicErodeDilateImageFilter:h|hxx
+tinclude itk#itk_filters#:h|hxx
+
+cinclude itkUnaryFunctorImageFilter.hxx
+
+instances itk::ParabolicErodeDilateImageFilter< itk::Image< #i_scalars#, #pdims# >, #booleans#, itk::Image< #o_scalars#, #pdims# > >
+
+instances itk::#itk_filters#< itk::Image< #i_scalars#, #pdims# >, itk::Image< #o_scalars#, #pdims# > >
+
+
+** eof - $RCSfile$
diff --git a/plugins/ITKSeparableFilters/ITKSeparableFilters.i b/plugins/ITKSeparableFilters/ITKSeparableFilters.i
new file mode 100644 (file)
index 0000000..ad1c5f5
--- /dev/null
@@ -0,0 +1,7 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define filters=RecursiveSeparableImageFilter;RecursiveGaussianImageFilter;SmoothingRecursiveGaussianImageFilter
+tinclude itk#filters#:h|hxx
+instances itk::#filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #real_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.cxx b/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.cxx
new file mode 100644 (file)
index 0000000..5b79eaa
--- /dev/null
@@ -0,0 +1,74 @@
+#include <ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkSmoothingRecursiveGaussianImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter::
+SmoothingRecursiveGaussianImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+  this->m_Parameters.ConfigureAsRealList( "SigmaArray" );
+  this->m_Parameters.ConfigureAsRealTypesChoices( "OutputResolution" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter::
+~SmoothingRecursiveGaussianImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image dimension." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter::
+_GD0( _TImage* image )
+{
+  std::string out_res =
+    this->m_Parameters.GetSelectedChoice( "OutputResolution" );
+  if( out_res == "float" ) this->_GD1< _TImage, float >( image );
+  if( out_res == "double" ) this->_GD1< _TImage, double >( image );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TScalar >
+void cpPluginsITKSeparableFilters::SmoothingRecursiveGaussianImageFilter::
+_GD1( _TImage* image )
+{
+  typedef itk::Image< _TScalar, _TImage::ImageDimension > _TOutput;
+  typedef
+    itk::SmoothingRecursiveGaussianImageFilter< _TImage, _TOutput >
+    _TFilter;
+  typedef typename _TFilter::SigmaArrayType _TSigmas;
+
+  auto param_sigmas = this->m_Parameters.GetRealList( "SigmaArray" );
+  unsigned int dim =
+    ( param_sigmas.size( ) < _TImage::ImageDimension )? 
+    param_sigmas.size( ):
+    _TImage::ImageDimension;
+  _TSigmas sigmas;
+  sigmas.Fill( param_sigmas[ dim - 1 ] );
+  for( unsigned d = 0; d < dim; ++d )
+    sigmas[ d ] = param_sigmas[ d ];
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetSigmaArray( sigmas );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h b/plugins/ITKSeparableFilters/SmoothingRecursiveGaussianImageFilter.h
new file mode 100644 (file)
index 0000000..edac699
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKSeparableFilters__SmoothingRecursiveGaussianImageFilter__h__
+#define __cpPluginsITKSeparableFilters__SmoothingRecursiveGaussianImageFilter__h__
+
+#include <cpPlugins_ITKSeparableFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKSeparableFilters
+{
+  /**
+   */
+  class cpPlugins_ITKSeparableFilters_EXPORT SmoothingRecursiveGaussianImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      SmoothingRecursiveGaussianImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageSeparableFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage, class _TScalar >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKSeparableFilters__SmoothingRecursiveGaussianImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKSliceFilters/CPRImageFilter.cxx b/plugins/ITKSliceFilters/CPRImageFilter.cxx
new file mode 100644 (file)
index 0000000..60de5f5
--- /dev/null
@@ -0,0 +1,63 @@
+#include <ITKSliceFilters/CPRImageFilter.h>
+
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Simple3DCurve.h>
+
+#include <itkImage.h>
+#include <cpExtensions/DataStructures/Simple3DCurve.h>
+#include <cpExtensions/Algorithms/CPRImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKSliceFilters::CPRImageFilter::
+CPRImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image         _TImage;
+  typedef cpInstances::Simple3DCurve _TCurve;
+  this->_ConfigureInput< _TImage >( "Image", true, false );
+  this->_ConfigureInput< _TCurve >( "Curve", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+  this->m_Parameters.ConfigureAsReal( "SliceRadius", 1 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKSliceFilters::CPRImageFilter::
+~CPRImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKSliceFilters::CPRImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Image" );
+  cpPlugins_Demangle_Image_ScalarPixels_1( o, _GD0, 3 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKSliceFilters::CPRImageFilter::
+_GD0( _TImage* image )
+{
+  auto o = this->GetInputData( "Curve" );
+  cpPlugins_Demangle_Simple3DCurve_All_2( o, _GD1, image )
+    this->_Error( "Invalid input curve." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TCurve, class _TImage >
+void cpPluginsITKSliceFilters::CPRImageFilter::
+_GD1( _TCurve* curve, _TImage* image )
+{
+  typedef cpExtensions::Algorithms::CPRImageFilter< _TImage, _TCurve > _TFilter;
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetCurve( curve );
+  filter->SetSliceRadius( this->m_Parameters.GetReal( "SliceRadius" ) );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKSliceFilters/CPRImageFilter.h b/plugins/ITKSliceFilters/CPRImageFilter.h
new file mode 100644 (file)
index 0000000..a2d0802
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKSliceFilters__CPRImageFilter__h__
+#define __cpPluginsITKSliceFilters__CPRImageFilter__h__
+
+#include <cpPlugins_ITKSliceFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKSliceFilters
+{
+  /**
+   */
+  class cpPlugins_ITKSliceFilters_EXPORT CPRImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      CPRImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ITKSliceFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TCurve, class _TImage >
+    inline void _GD1( _TCurve* curve, _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKSliceFilters__CPRImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKSliceFilters/ITKSliceFilters.i b/plugins/ITKSliceFilters/ITKSliceFilters.i
new file mode 100644 (file)
index 0000000..ee71b1c
--- /dev/null
@@ -0,0 +1,20 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude itkImageToImageFilter:h|hxx
+tinclude itkInPlaceImageFilter:h|hxx
+instances itk::ImageToImageFilter< itk::Image< #scalar_types#, 3 >, itk::Image< #scalar_types#, 2 > >
+instances itk::InPlaceImageFilter< itk::Image< #scalar_types#, 3 >, itk::Image< #scalar_types#, 2 > >
+
+tinclude itkResampleImageFilter:h|hxx
+instances itk::ResampleImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, #real_types#, #real_types# >
+
+tinclude cpExtensions/Algorithms/IsoImageSlicer:h|hxx
+tinclude itkExtractImageFilter:h|hxx
+tinclude itkJoinSeriesImageFilter:h|hxx
+tinclude itkImageAlgorithm:h|hxx
+
+cinclude cpExtensions/DataStructures/Simple3DCurve.h
+tinclude cpExtensions/Algorithms/CPRImageFilter:h|hxx
+instances cpExtensions::Algorithms::CPRImageFilter< itk::Image< #scalar_types#, 3 >, cpExtensions::DataStructures::Simple3DCurve< #real_types# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKSliceFilters/IsoResampleImageFilter.cxx b/plugins/ITKSliceFilters/IsoResampleImageFilter.cxx
new file mode 100644 (file)
index 0000000..0e451db
--- /dev/null
@@ -0,0 +1,109 @@
+#include <ITKSliceFilters/IsoResampleImageFilter.h>
+#include <ITKImageInterpolators/InterpolateImageFunction.h>
+
+#include <cpInstances/DataObjects/Image.h>
+#include <itkImage.h>
+#include <itkResampleImageFilter.h>
+#include <itkIdentityTransform.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKSliceFilters::IsoResampleImageFilter::
+IsoResampleImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureInput< cpPlugins::Pipeline::DataObject >( "Interpolator", false, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "Scale", 1 );
+  this->m_Parameters.ConfigureAsBool( "ScaleFromMinimumSpacing", true );
+  this->m_Parameters.ConfigureAsRealTypesChoices( "PrecisionType" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKSliceFilters::IsoResampleImageFilter::
+~IsoResampleImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKSliceFilters::IsoResampleImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKSliceFilters::IsoResampleImageFilter::
+_GD0( _TImage* image )
+{
+  typedef cpPluginsITKImageInterpolators::InterpolateImageFunction _TInterpolator;
+
+  std::string p_type = this->m_Parameters.GetSelectedChoice( "PrecisionType" );
+  auto interpolator = dynamic_cast< _TInterpolator* >(
+    this->GetInput( "Interpolator" )->GetSource( )
+    );
+  if( interpolator != NULL )
+    interpolator->CreateInterpolator( image, p_type );
+  if     ( p_type == "float" )  this->_GD1< _TImage, float >( image );
+  else if( p_type == "double" ) this->_GD1< _TImage, double >( image );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage, class _TScalar >
+void cpPluginsITKSliceFilters::IsoResampleImageFilter::
+_GD1( _TImage* image )
+{
+  typedef itk::IdentityTransform< _TScalar, _TImage::ImageDimension > _TTransform;
+  typedef itk::ResampleImageFilter< _TImage, _TImage, _TScalar, _TScalar > _TFilter;
+  typedef typename _TFilter::InterpolatorType _TInterpolator;
+
+  // Initial configuration
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+
+  // Associate transform
+  typename _TTransform::Pointer transform = _TTransform::New( );
+  transform->SetIdentity( );
+  filter->SetTransform( transform );
+
+  // Compute new spacing
+  typename _TImage::SpacingType in_spac = image->GetSpacing( );
+  double val_spac = in_spac[ 0 ];
+  if( this->m_Parameters.GetBool( "ScaleFromMinimumSpacing" ) )
+    for( unsigned int d = 1; d < _TImage::ImageDimension; ++d )
+      val_spac = ( in_spac[ d ] < val_spac )? in_spac[ d ]: val_spac;
+  else
+    for( unsigned int d = 1; d < _TImage::ImageDimension; ++d )
+      val_spac = ( in_spac[ d ] > val_spac )? in_spac[ d ]: val_spac;
+  val_spac *= this->m_Parameters.GetReal( "Scale" );
+  typename _TImage::SpacingType out_spac;
+  out_spac.Fill( val_spac );
+  filter->SetOutputSpacing( out_spac );
+
+  // Compute new size
+  typename _TImage::SizeType in_size = image->GetRequestedRegion( ).GetSize( );
+  typename _TImage::SizeType out_size;
+  for( unsigned int d = 0; d < _TImage::ImageDimension; ++d )
+    out_size[ d ] = ( unsigned long )(
+      double( in_size[ d ] ) * double( in_spac[ d ] ) / val_spac
+      );
+  filter->SetSize( out_size );
+
+  // New origin
+  filter->SetOutputOrigin( image->GetOrigin( ) );
+
+  // Set interpolator
+  auto interpolator = this->GetInputData< _TInterpolator >( "Interpolator" );
+  if( interpolator != NULL )
+    filter->SetInterpolator( interpolator );
+
+  // Update
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKSliceFilters/IsoResampleImageFilter.h b/plugins/ITKSliceFilters/IsoResampleImageFilter.h
new file mode 100644 (file)
index 0000000..238e7f5
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __cpPluginsITKSliceFilters__IsoResampleImageFilter__h__
+#define __cpPluginsITKSliceFilters__IsoResampleImageFilter__h__
+
+#include <cpPlugins_ITKSliceFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKSliceFilters
+{
+  /**
+   */
+  class cpPlugins_ITKSliceFilters_EXPORT IsoResampleImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      IsoResampleImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ITKSliceFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+
+    template< class _TImage, class _TScalar >
+    inline void _GD1( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKSliceFilters__IsoResampleImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/AbsImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/AbsImageFilter.cxx
new file mode 100644 (file)
index 0000000..6e7c27c
--- /dev/null
@@ -0,0 +1,46 @@
+#include <ITKUnaryFunctorFilters/AbsImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkAbsImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::AbsImageFilter::
+AbsImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::AbsImageFilter::
+~AbsImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKUnaryFunctorFilters::AbsImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKUnaryFunctorFilters::AbsImageFilter::
+_GD0( _TImage* image )
+{
+  typedef itk::AbsImageFilter< _TImage, _TImage > _TFilter;
+
+  // Configure filter
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/AbsImageFilter.h b/plugins/ITKUnaryFunctorFilters/AbsImageFilter.h
new file mode 100644 (file)
index 0000000..2738512
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKUnaryFunctorFilters__AbsImageFilter__h__
+#define __cpPluginsITKUnaryFunctorFilters__AbsImageFilter__h__
+
+#include <cpPlugins_ITKUnaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKUnaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKUnaryFunctorFilters_EXPORT AbsImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      AbsImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKUnaryFunctorFilters__AbsImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.cxx
new file mode 100644 (file)
index 0000000..50c0338
--- /dev/null
@@ -0,0 +1,65 @@
+#include <ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkBinaryThresholdImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter::
+BinaryThresholdImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "LowerThresholdValue", 0 );
+  this->m_Parameters.ConfigureAsReal( "UpperThresholdValue", 1 );
+  this->m_Parameters.ConfigureAsUint( "InsideValue", 1 );
+  this->m_Parameters.ConfigureAsUint( "OutsideValue", 0 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter::
+~BinaryThresholdImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKUnaryFunctorFilters::BinaryThresholdImageFilter::
+_GD0( _TImage* image )
+{
+  typedef unsigned char _TBin;
+  typedef itk::Image< unsigned char, _TImage::ImageDimension > _TBinImage;
+  typedef itk::BinaryThresholdImageFilter< _TImage, _TBinImage > _TFilter;
+  typedef typename _TImage::PixelType _TPixel;
+
+  // Get parameters
+  _TPixel lt = _TPixel( this->m_Parameters.GetReal( "LowerThresholdValue" ) );
+  _TPixel ut = _TPixel( this->m_Parameters.GetReal( "UpperThresholdValue" ) );
+  _TBin iv  = _TBin( this->m_Parameters.GetUint( "InsideValue" ) );
+  _TBin ov = _TBin( this->m_Parameters.GetUint( "OutsideValue" ) );
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetLowerThreshold( lt );
+  filter->SetUpperThreshold( ut );
+  filter->SetInsideValue( iv );
+  filter->SetOutsideValue( ov );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h b/plugins/ITKUnaryFunctorFilters/BinaryThresholdImageFilter.h
new file mode 100644 (file)
index 0000000..a2a0773
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKUnaryFunctorFilters__BinaryThresholdImageFilter__h__
+#define __cpPluginsITKUnaryFunctorFilters__BinaryThresholdImageFilter__h__
+
+#include <cpPlugins_ITKUnaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKUnaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKUnaryFunctorFilters_EXPORT BinaryThresholdImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      BinaryThresholdImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageThresholdFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKUnaryFunctorFilters__BinaryThresholdImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/ITKUnaryFunctorFilters.i b/plugins/ITKUnaryFunctorFilters/ITKUnaryFunctorFilters.i
new file mode 100644 (file)
index 0000000..4bf7475
--- /dev/null
@@ -0,0 +1,33 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+define all_ints=#int_types#;#uint_types#
+define a_filters=Abs
+define a_functor=Abs
+define b_filters=Not
+define b_functor=NOT
+
+tinclude itkUnaryFunctorImageFilter:h|hxx
+cinclude itk#a_filters#ImageFilter.h
+cinclude itk#b_filters#ImageFilter.h
+
+instances itk::UnaryFunctorImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Functor::#a_functor#< #scalar_types#, #scalar_types# > >
+
+instances itk::UnaryFunctorImageFilter< itk::Image< #all_ints#, #pdims# >, itk::Image< #all_ints#, #pdims# >, itk::Functor::#b_functor#< #all_ints#, #all_ints# > >
+
+cinclude itkBinaryNotImageFilter.h
+instances itk::UnaryFunctorImageFilter< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# >, itk::Functor::BinaryNot< #scalar_types# > >
+
+define oa_filters=InvertIntensityImageFilter
+tinclude itk#oa_filters#:h|hxx
+instances itk::#oa_filters#< itk::Image< #scalar_types#, #pdims# >, itk::Image< #scalar_types#, #pdims# > >
+
+define oam_filters=BinaryThresholdImageFilter
+define i_scalars=#scalar_types#
+define o_scalars=#scalar_types#
+tinclude itk#oam_filters#:h|hxx
+instances itk::#oam_filters#< itk::Image< #i_scalars#, #pdims# >, itk::Image< #o_scalars#, #pdims# > >
+
+tinclude cpExtensions/Algorithms/UnaryThresholdImageFilter:h|hxx
+instances cpExtensions::Algorithms::UnaryThresholdImageFilter< itk::Image< #scalar_types#, #pdims# > >
+
+** eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.cxx
new file mode 100644 (file)
index 0000000..e9e61b9
--- /dev/null
@@ -0,0 +1,48 @@
+#include <ITKUnaryFunctorFilters/InvertIntensityImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkInvertIntensityImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter::
+InvertIntensityImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+  this->m_Parameters.ConfigureAsUint( "Maximum", 1 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter::
+~InvertIntensityImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKUnaryFunctorFilters::InvertIntensityImageFilter::
+_GD0( _TImage* image )
+{
+  typedef itk::InvertIntensityImageFilter< _TImage > _TFilter;
+
+  // Configure filter
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetMaximum( this->m_Parameters.GetUint( "Maximum" ) );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.h b/plugins/ITKUnaryFunctorFilters/InvertIntensityImageFilter.h
new file mode 100644 (file)
index 0000000..3158c0d
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKUnaryFunctorFilters__InvertIntensityImageFilter__h__
+#define __cpPluginsITKUnaryFunctorFilters__InvertIntensityImageFilter__h__
+
+#include <cpPlugins_ITKUnaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKUnaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKUnaryFunctorFilters_EXPORT InvertIntensityImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      InvertIntensityImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageBooleanFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKUnaryFunctorFilters__InvertIntensityImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.cxx
new file mode 100644 (file)
index 0000000..8c28321
--- /dev/null
@@ -0,0 +1,49 @@
+#include <ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <itkNotImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter::
+UnaryBooleanImageFilter( )
+  : Superclass( )
+{
+  typedef cpInstances::DataObjects::Image _TImage;
+
+  this->_ConfigureInput< _TImage >( "Input", true, false );
+  this->_ConfigureOutput< _TImage >( "Output" );
+
+  std::vector< std::string > choices;
+  choices.push_back( "Not" );
+  this->m_Parameters.ConfigureAsChoices( "Operator", choices );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter::
+~UnaryBooleanImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_IntPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKUnaryFunctorFilters::UnaryBooleanImageFilter::
+_GD0( _TImage* image )
+{
+  typedef itk::NotImageFilter< _TImage, _TImage > _TFilter;
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h b/plugins/ITKUnaryFunctorFilters/UnaryBooleanImageFilter.h
new file mode 100644 (file)
index 0000000..db3ccbc
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKUnaryFunctorFilters__UnaryBooleanImageFilter__h__
+#define __cpPluginsITKUnaryFunctorFilters__UnaryBooleanImageFilter__h__
+
+#include <cpPlugins_ITKUnaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKUnaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKUnaryFunctorFilters_EXPORT UnaryBooleanImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      UnaryBooleanImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageBooleanFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image1 );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKUnaryFunctorFilters__UnaryBooleanImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.cxx b/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.cxx
new file mode 100644 (file)
index 0000000..d119094
--- /dev/null
@@ -0,0 +1,57 @@
+#include <ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+
+#include <cpExtensions/Algorithms/UnaryThresholdImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter::
+UnaryThresholdImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+
+  this->m_Parameters.ConfigureAsReal( "Threshold", 0 );
+  this->m_Parameters.ConfigureAsReal( "InsideValue", 1 );
+  this->m_Parameters.ConfigureAsReal( "OutsideValue", 0 );
+  this->m_Parameters.ConfigureAsBool( "Strict", false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter::
+~UnaryThresholdImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 )
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TImage >
+void cpPluginsITKUnaryFunctorFilters::UnaryThresholdImageFilter::
+_GD0( _TImage* image )
+{
+  typedef
+    cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage >
+    _TFilter;
+
+  // Configure filter
+  _TFilter* filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( image );
+  filter->SetThreshold( this->m_Parameters.GetReal( "Threshold" ) );
+  filter->SetInsideValue( this->m_Parameters.GetReal( "InsideValue" ) );
+  filter->SetOutsideValue( this->m_Parameters.GetReal( "OutsideValue" ) );
+  filter->SetStrict( this->m_Parameters.GetBool( "Strict" ) );
+  filter->Update( );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h b/plugins/ITKUnaryFunctorFilters/UnaryThresholdImageFilter.h
new file mode 100644 (file)
index 0000000..f99e518
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __cpPluginsITKUnaryFunctorFilters__UnaryThresholdImageFilter__h__
+#define __cpPluginsITKUnaryFunctorFilters__UnaryThresholdImageFilter__h__
+
+#include <cpPlugins_ITKUnaryFunctorFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsITKUnaryFunctorFilters
+{
+  /**
+   */
+  class cpPlugins_ITKUnaryFunctorFilters_EXPORT UnaryThresholdImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      UnaryThresholdImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageThresholdFilters
+      );
+
+  protected:
+    template< class _TImage >
+    inline void _GD0( _TImage* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsITKUnaryFunctorFilters__UnaryThresholdImageFilter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKFilters/CylinderSource.cxx b/plugins/VTKFilters/CylinderSource.cxx
new file mode 100644 (file)
index 0000000..d8939cf
--- /dev/null
@@ -0,0 +1,35 @@
+#include <VTKFilters/CylinderSource.h>
+#include <cpInstances/DataObjects/Mesh.h>
+
+#include <vtkCylinderSource.h>
+
+// -------------------------------------------------------------------------
+cpPluginsVTKFilters::CylinderSource::
+CylinderSource( )
+  : Superclass( )
+{
+  this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" );
+  this->m_Parameters.ConfigureAsReal( "Height", 1 );
+  this->m_Parameters.ConfigureAsReal( "Radius", 1 );
+  this->m_Parameters.ConfigureAsUint( "Resolution", 8 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKFilters::CylinderSource::
+~CylinderSource( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKFilters::CylinderSource::
+_GenerateData( )
+{
+  auto src = this->_CreateVTK< vtkCylinderSource >( );
+  src->SetHeight( this->m_Parameters.GetReal( "Height" ) );
+  src->SetRadius( this->m_Parameters.GetReal( "Radius" ) );
+  src->SetResolution( this->m_Parameters.GetUint( "Resolution" ) );
+  src->Update( );
+  this->GetOutput( "Output" )->SetVTK( src->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKFilters/CylinderSource.h b/plugins/VTKFilters/CylinderSource.h
new file mode 100644 (file)
index 0000000..5c25ee5
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __cpPluginsVTKFilters__CylinderSource__h__
+#define __cpPluginsVTKFilters__CylinderSource__h__
+
+#include <cpPlugins_VTKFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsVTKFilters
+{
+  /**
+   */
+  class cpPlugins_VTKFilters_EXPORT CylinderSource
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      CylinderSource,
+      cpPlugins::Pipeline::ProcessObject,
+      MeshSources
+      );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKFilters__CylinderSource__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKFilters/MarchingCubes.cxx b/plugins/VTKFilters/MarchingCubes.cxx
new file mode 100644 (file)
index 0000000..b01a9dc
--- /dev/null
@@ -0,0 +1,64 @@
+#include <VTKFilters/MarchingCubes.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Mesh.h>
+
+#include <vtkImageData.h>
+#include <vtkMarchingCubes.h>
+#include <vtkMarchingSquares.h>
+
+// -------------------------------------------------------------------------
+cpPluginsVTKFilters::MarchingCubes::
+MarchingCubes( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "Input", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" );
+  this->m_Parameters.ConfigureAsRealList( "Thresholds" );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKFilters::MarchingCubes::
+~MarchingCubes( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKFilters::MarchingCubes::
+_GenerateData( )
+{
+  // Get input
+  auto image = this->GetInput( "Input" );
+  vtkImageData* vtk_image = image->GetVTK< vtkImageData >( );
+  if( vtk_image == NULL )
+    this->_Error( "Input does not have a valid VTK conversion." );
+
+  std::vector< double > values =
+    this->m_Parameters.GetRealList( "Thresholds" );
+  vtkPolyData* pd = NULL;
+  if( vtk_image->GetDataDimension( ) == 2 )
+  {
+    vtkMarchingSquares* ms = this->_CreateVTK< vtkMarchingSquares >( );
+    ms->SetInputData( vtk_image );
+    for( unsigned int i = 0; i < values.size( ); ++i )
+      ms->SetValue( i, values[ i ] );
+    ms->Update( );
+    pd = ms->GetOutput( );
+  }
+  else if( vtk_image->GetDataDimension( ) == 3 )
+  {
+    vtkMarchingCubes* mc = this->_CreateVTK< vtkMarchingCubes >( );
+    mc->ComputeNormalsOff( );
+    mc->SetInputData( vtk_image );
+    for( unsigned int i = 0; i < values.size( ); ++i )
+      mc->SetValue( i, values[ i ] );
+    mc->Update( );
+    pd = mc->GetOutput( );
+  }
+  else
+    this->_Error( "Input data does not have a valid dimension." );
+
+  // Connect output
+  this->GetOutput( "Output" )->SetVTK( pd );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKFilters/MarchingCubes.h b/plugins/VTKFilters/MarchingCubes.h
new file mode 100644 (file)
index 0000000..693909a
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __cpPluginsVTKFilters__MarchingCubes__h__
+#define __cpPluginsVTKFilters__MarchingCubes__h__
+
+#include <cpPlugins_VTKFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsVTKFilters
+{
+  /**
+   */
+  class cpPlugins_VTKFilters_EXPORT MarchingCubes
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      MarchingCubes,
+      cpPlugins::Pipeline::ProcessObject,
+      ImageToMeshFilters
+      );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKFilters__MarchingCubes__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKFilters/SphereSource.cxx b/plugins/VTKFilters/SphereSource.cxx
new file mode 100644 (file)
index 0000000..0eaac1b
--- /dev/null
@@ -0,0 +1,35 @@
+#include <VTKFilters/SphereSource.h>
+#include <cpInstances/DataObjects/Mesh.h>
+
+#include <vtkSphereSource.h>
+
+// -------------------------------------------------------------------------
+cpPluginsVTKFilters::SphereSource::
+SphereSource( )
+  : Superclass( )
+{
+  this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" );
+  this->m_Parameters.ConfigureAsReal( "Radius", 1 );
+  this->m_Parameters.ConfigureAsUint( "PhiResolution", 8 );
+  this->m_Parameters.ConfigureAsUint( "ThetaResolution", 8 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKFilters::SphereSource::
+~SphereSource( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKFilters::SphereSource::
+_GenerateData( )
+{
+  auto src = this->_CreateVTK< vtkSphereSource >( );
+  src->SetRadius( this->m_Parameters.GetReal( "Radius" ) );
+  src->SetPhiResolution( this->m_Parameters.GetUint( "PhiResolution" ) );
+  src->SetThetaResolution( this->m_Parameters.GetUint( "ThetaResolution" ) );
+  src->Update( );
+  this->GetOutput( "Output" )->SetVTK( src->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKFilters/SphereSource.h b/plugins/VTKFilters/SphereSource.h
new file mode 100644 (file)
index 0000000..b0c7ac4
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __cpPluginsVTKFilters__SphereSource__h__
+#define __cpPluginsVTKFilters__SphereSource__h__
+
+#include <cpPlugins_VTKFilters_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsVTKFilters
+{
+  /**
+   */
+  class cpPlugins_VTKFilters_EXPORT SphereSource
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      SphereSource,
+      cpPlugins::Pipeline::ProcessObject,
+      MeshSources
+      );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKFilters__SphereSource__h__
+
+
+// eof - $RCSfile$
diff --git a/plugins/VTKIO/MeshReader.cxx b/plugins/VTKIO/MeshReader.cxx
new file mode 100644 (file)
index 0000000..59d2a50
--- /dev/null
@@ -0,0 +1,60 @@
+#include <VTKIO/MeshReader.h>
+#include <cpInstances/DataObjects/Mesh.h>
+#include <cpPlugins/QT/OpenFileDialog.h>
+
+#include <vtkPolyData.h>
+#include <vtkPolyDataReader.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginsVTKIO::MeshReader::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::OpenFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::OpenFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileName" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKIO::MeshReader::
+MeshReader( )
+  : Superclass( )
+{
+  this->_ConfigureOutput< cpInstances::DataObjects::Mesh >( "Output" );
+  this->m_Parameters.Clear( );
+  this->m_Parameters.ConfigureAsOpenFileName( "FileName", "" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileName",
+    "Mesh files (*.vtk)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKIO::MeshReader::
+~MeshReader( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKIO::MeshReader::
+_GenerateData( )
+{
+  auto f = this->_CreateVTK< vtkPolyDataReader >( );
+  f->SetFileName( this->m_Parameters.GetOpenFileName( "FileName" ).c_str( ) );
+  f->Update( );
+  this->GetOutput( "Output" )->SetVTK( f->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKIO/MeshReader.h b/plugins/VTKIO/MeshReader.h
new file mode 100644 (file)
index 0000000..69f9b8d
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __cpPluginsVTKIO__MeshReader__h__
+#define __cpPluginsVTKIO__MeshReader__h__
+
+#include <cpPlugins_VTKIO_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsVTKIO
+{
+  /**
+   */
+  class cpPlugins_VTKIO_EXPORT MeshReader
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject( MeshReader, cpPlugins::Pipeline::ProcessObject, IO );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKIO__MeshReader__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKIO/MeshWriter.cxx b/plugins/VTKIO/MeshWriter.cxx
new file mode 100644 (file)
index 0000000..fa44b2d
--- /dev/null
@@ -0,0 +1,65 @@
+#include <VTKIO/MeshWriter.h>
+#include <cpInstances/DataObjects/Mesh.h>
+#include <cpPlugins/QT/SaveFileDialog.h>
+
+#include <vtkPolyData.h>
+#include <vtkPolyDataWriter.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginsVTKIO::MeshWriter::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::SaveFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::SaveFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileName" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKIO::MeshWriter::
+MeshWriter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::DataObjects::Mesh >( "Input", true, false );
+  this->m_Parameters.Clear( );
+  this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileName",
+    "Mesh files (*.vtk)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKIO::MeshWriter::
+~MeshWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKIO::MeshWriter::
+_GenerateData( )
+{
+  auto mesh = this->GetInputData< vtkPolyData >( "Input" );
+  if( mesh == NULL )
+    this->_Error( "Invalid input mesh." );
+
+  auto f = this->_CreateVTK< vtkPolyDataWriter >( );
+  f->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ).c_str( ) );
+  f->SetInputData( mesh );
+  f->SetFileTypeToBinary( );
+  f->Update( );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKIO/MeshWriter.h b/plugins/VTKIO/MeshWriter.h
new file mode 100644 (file)
index 0000000..2278b01
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __cpPluginsVTKIO__MeshWriter__h__
+#define __cpPluginsVTKIO__MeshWriter__h__
+
+#include <cpPlugins_VTKIO_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginsVTKIO
+{
+  /**
+   */
+  class cpPlugins_VTKIO_EXPORT MeshWriter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject( MeshWriter, cpPlugins::Pipeline::ProcessObject, IO );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKIO__MeshWriter__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKWidgets/LineWidget.cxx b/plugins/VTKWidgets/LineWidget.cxx
new file mode 100644 (file)
index 0000000..24928e6
--- /dev/null
@@ -0,0 +1,173 @@
+#include <VTKWidgets/LineWidget.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Mesh.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+#include <vtkLineWidget2.h>
+#include <vtkImageData.h>
+#include <vtkImageMapper3D.h>
+#include <vtkInteractorObserver.h>
+#include <vtkLineRepresentation.h>
+#include <vtkMapper.h>
+#include <vtkPolyData.h>
+#include <vtkRenderer.h>
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::LineWidget::
+Clear( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::LineWidget::
+SetEnabled( bool v )
+{
+  auto wdg = this->GetVTK< vtkLineWidget2 >( );
+  if( wdg != NULL )
+  {
+    wdg->SetEnabled( v );
+    wdg->GetInteractor( )->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+bool cpPluginsVTKWidgets::LineWidget::
+GetEnabled( ) const
+{
+  auto wdg = this->GetVTK< const vtkLineWidget2 >( );
+  if( wdg != NULL )
+  {
+    vtkLineWidget2* w = const_cast< vtkLineWidget2* >( wdg );
+    return( w->GetEnabled( ) != 0 );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::LineWidget::
+LineWidget( )
+  : Superclass( )
+{
+  typedef cpPlugins::Pipeline::DataObject _TData;
+  typedef cpInstances::DataObjects::Mesh       _TMesh;
+
+  this->_ConfigureInput< _TData >( "Input", false, false );
+  this->_ConfigureOutput< _TMesh >( "Output" );
+
+  // Create output data
+  auto line = this->_CreateVTK< vtkPolyData >( );
+  line->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+  line->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  line->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+  line->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  line->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  this->GetOutput( "Output" )->SetVTK( line );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::LineWidget::
+~LineWidget( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::LineWidget::
+_GenerateData( )
+{
+  if( this->m_Interactors.size( ) == 0 )
+    this->_Error( "Give at least one valid interactor." );
+
+  auto image = this->GetInputData< vtkImageData >( "Input" );
+  if( image != NULL ) this->_GD_Image( image );
+  else this->_Error( "Do not know how to create this widget." );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::LineWidget::
+TValidProps cpPluginsVTKWidgets::LineWidget::
+_GetValidActors( vtkObject* source )
+{
+  TValidProps valid_props;
+  auto iIt = this->m_Interactors.begin( );
+  for( ; iIt != this->m_Interactors.end( ); ++iIt )
+  {
+    auto r = ( *iIt )->GetInteractorStyle( )->GetCurrentRenderer( );
+    if( r != NULL )
+    {
+      auto props = r->GetViewProps( );
+      if( props != NULL )
+      {
+        props->InitTraversal( );
+        while( vtkProp* prop = props->GetNextProp( ) )
+        {
+          auto image_actor = dynamic_cast< vtkImageSlice* >( prop );
+          auto mesh_actor = dynamic_cast< vtkActor* >( prop );
+          vtkObject* input = NULL;
+          if( image_actor != NULL )
+          {
+            auto mapper = image_actor->GetMapper( );
+            if( mapper != NULL )
+              input = mapper->GetInput( );
+          }
+          else if( mesh_actor != NULL )
+          {
+            auto mapper = mesh_actor->GetMapper( );
+            if( mapper != NULL )
+              input = mapper->GetInput( );
+
+          } // fi
+          if( input != NULL )
+            valid_props[ *iIt ].insert( prop );
+
+        } // elihw
+
+      } // fi
+
+    } // fi
+
+  } // rof
+  return( valid_props );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::LineWidget::
+_GD_Image( vtkImageData* image )
+{
+  auto valid_props = this->_GetValidActors( image );
+  if( valid_props.size( ) == 0 )
+    this->_Error( "Given image does not have a valid associated actor." );
+
+  vtkSmartPointer< vtkLineWidget2 > wdg = this->GetVTK< vtkLineWidget2 >( );
+  if( wdg.GetPointer( ) == NULL )
+  {
+    auto vIt = valid_props.begin( );
+    auto actor = dynamic_cast< vtkImageSlice* >( *( vIt->second.begin( ) ) );
+
+    double bnds[ 6 ];
+    actor->GetBounds( bnds );
+    double p0[ 3 ], p1[ 3 ];
+    p0[ 0 ] = bnds[ 0 ];
+    p0[ 1 ] = bnds[ 2 ];
+    p0[ 2 ] = bnds[ 4 ];
+    p1[ 0 ] = bnds[ 1 ];
+    p1[ 1 ] = bnds[ 3 ];
+    p1[ 2 ] = bnds[ 5 ];
+
+    auto rep = vtkSmartPointer< vtkLineRepresentation >::New( );
+    rep->SetPoint1WorldPosition( p0 );
+    rep->SetPoint2WorldPosition( p1 );
+    rep->PlaceWidget( bnds );
+
+    wdg = this->_CreateVTK< vtkLineWidget2 >( );
+    wdg->SetInteractor( valid_props.begin( )->first );
+    wdg->SetRepresentation( rep );
+    wdg->EnabledOn( );
+  }
+  else
+    dynamic_cast< vtkLineRepresentation* >( wdg->GetRepresentation( ) )->
+      GetPolyData( this->GetOutputData< vtkPolyData >( "Output" ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKWidgets/LineWidget.h b/plugins/VTKWidgets/LineWidget.h
new file mode 100644 (file)
index 0000000..ed16240
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __cpPluginsVTKWidgets__LineWidget__h__
+#define __cpPluginsVTKWidgets__LineWidget__h__
+
+#include <cpPlugins_VTKWidgets_Export.h>
+#include <cpPlugins/Pipeline/Widget.h>
+#include <set>
+
+// -------------------------------------------------------------------------
+class vtkImageData;
+class vtkProp;
+
+// -------------------------------------------------------------------------
+namespace cpPluginsVTKWidgets
+{
+  /**
+   */
+  class cpPlugins_VTKWidgets_EXPORT LineWidget
+    : public cpPlugins::Pipeline::Widget
+  {
+    cpPluginsObject( LineWidget, cpPlugins::Pipeline::Widget, Widgets );
+
+  public:
+    virtual void Clear( ) cpPlugins_OVERRIDE;
+    virtual void SetEnabled( bool v ) cpPlugins_OVERRIDE;
+    virtual bool GetEnabled( ) const cpPlugins_OVERRIDE;
+
+  protected:
+    typedef std::set< vtkProp* > TProps;
+    typedef std::map< vtkRenderWindowInteractor*, TProps > TValidProps;
+
+  protected:
+    TValidProps _GetValidActors( vtkObject* source );
+    void _GD_Image( vtkImageData* image );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKWidgets__LineWidget__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKWidgets/SeedWidget.cxx b/plugins/VTKWidgets/SeedWidget.cxx
new file mode 100644 (file)
index 0000000..d0db73e
--- /dev/null
@@ -0,0 +1,380 @@
+#include <VTKWidgets/SeedWidget.h>
+
+#include <cpPlugins/OS/String.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Mesh.h>
+
+#include <cpExtensions/Interaction/SeedWidget.h>
+#include <cpExtensions/Interaction/ImageSlicePointPlacer.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+#include <vtkHandleWidget.h>
+#include <vtkImageData.h>
+#include <vtkPlane.h>
+#include <vtkPointHandleRepresentation3D.h>
+#include <vtkProperty.h>
+#include <vtkRendererCollection.h>
+#include <vtkRenderWindow.h>
+#include <vtkSeedRepresentation.h>
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SeedWidget::
+Clear( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SeedWidget::
+SetEnabled( bool v )
+{
+  for( auto w = this->m_Widgets.begin( ); w != this->m_Widgets.end( ); ++w )
+  {
+    if( v ) w->second->RestartInteraction( );
+    else    w->second->CompleteInteraction( );
+    w->second->SetEnabled( v );
+    w->second->Render( );
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+bool cpPluginsVTKWidgets::SeedWidget::
+GetEnabled( ) const
+{
+  if( this->m_Widgets.size( ) > 0 )
+  {
+    auto i = this->m_Widgets.begin( );
+    TWidget* w = const_cast< TWidget* >( i->second.GetPointer( ) );
+    return( w->GetEnabled( ) != 0 );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SeedWidget::
+SeedWidget( )
+  : Superclass( )
+{
+  typedef cpPlugins::Pipeline::DataObject _TData;
+  typedef cpInstances::DataObjects::Mesh       _TMesh;
+
+  // Create ports
+  this->_ConfigureInput< _TData >( "Input", false, false );
+  this->_ConfigureOutput< _TMesh >( "Output" );
+
+  // Create output data
+  auto out = this->_CreateVTK< vtkPolyData >( );
+  out->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+  out->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  out->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  this->GetOutput( "Output" )->SetVTK( out );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SeedWidget::
+~SeedWidget( )
+{
+  /* TODO
+     for( auto w = this->m_Widgets.begin( ); w != this->m_Widgets.end( ); ++w )
+     w->second->EnabledOff( );
+     this->m_Widgets.clear( );
+  */
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SeedWidget::
+_GenerateData( )
+{
+  auto image = this->GetInputData< vtkImageData >( "Input" );
+  if( image != NULL )
+    this->_GD0_Image( image );
+  else
+    this->_Error( "Invalid input image." );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SeedWidget::
+_GD0_Image( vtkImageData* image )
+{
+  auto seeds = this->GetOutputData< vtkPolyData >( "Output" );
+  if( this->m_Widgets.size( ) == 0 )
+  {
+    this->m_Command = vtkSmartPointer< TCallback >::New( );
+    this->m_Command->SetSeeds( seeds );
+    for(
+      auto inIt = this->m_Interactors.begin( );
+      inIt != this->m_Interactors.end( );
+      ++inIt
+      )
+    {
+      auto rends = ( *inIt )->GetRenderWindow( )->GetRenderers( );
+      std::set< TImageActor* > all_props;
+      if( rends != NULL )
+      {
+        rends->InitTraversal( );
+        while( vtkRenderer* ren = rends->GetNextItem( ) )
+        {
+          auto props = ren->GetViewProps( );
+          props->InitTraversal( );
+          while( vtkProp* p = props->GetNextProp( ) )
+          {
+            auto image_actor = dynamic_cast< TImageActor* >( p );
+            if( image_actor != NULL )
+            {
+              if( image_actor->GetImage( ) == image )
+                all_props.insert( image_actor );
+
+            } // fi
+
+          } // elihw
+
+        } // elihw
+
+      } // fi
+      if( all_props.size( ) == 1 )
+      {
+        if( this->m_Widgets.find( *inIt ) == this->m_Widgets.end( ) )
+        {
+          auto act = *( all_props.begin( ) );
+          auto pla = vtkSmartPointer< TPlacer >::New( );
+          auto hnd = vtkSmartPointer< THandleRep >::New( );
+          auto rep = vtkSmartPointer< TSeedRep >::New( );
+          auto wdg = vtkSmartPointer< TWidget >::New( );
+
+          pla->SetImageSlice( act );
+          hnd->GetProperty( )->SetColor( 1, 0, 0 );
+          hnd->SetPointPlacer( pla );
+          rep->SetHandleRepresentation( hnd );
+          wdg->SetRepresentation( rep );
+          wdg->SetInteractor( *inIt );
+          act->AddObserver( vtkCommand::InteractionEvent, this->m_Command );
+          wdg->AddObserver( vtkCommand::PlacePointEvent, this->m_Command );
+          wdg->AddObserver( vtkCommand::CursorChangedEvent, this->m_Command );
+          this->m_Widgets[ *inIt ] = wdg;
+
+        } // fi
+
+      } // fi
+
+    } // rof
+
+    // Associate input text
+    std::string text = this->m_Parameters.GetString( "Text" );
+    std::vector< std::string > tok1, tok2;
+    tok1 = cpPlugins::OS::String::Tokenize( text, "#" );
+    if( tok1.size( ) > seeds->GetPoints( )->GetNumberOfPoints( ) )
+    {
+      for( auto t1 = tok1.begin( ); t1 != tok1.end( ); ++t1 )
+      {
+        if( *t1 != "" )
+        {
+          tok2 = cpPlugins::OS::String::Tokenize( *t1, " " );
+          double x[ 3 ];
+          for( unsigned int d = 0; d < 3; ++d )
+          {
+            if( d < tok2.size( ) )
+            {
+              std::istringstream str( tok2[ d ] );
+              str >> x[ d ];
+            }
+            else
+              x[ d ] = double( 0 );
+
+          } // rof
+
+          seeds->GetPoints( )->InsertNextPoint( x );
+          seeds->GetVerts( )->InsertNextCell( 1 );
+          seeds->GetVerts( )->InsertCellPoint(
+            seeds->GetPoints( )->GetNumberOfPoints( ) - 1
+            );
+          seeds->Modified( );
+
+        } // fi
+
+      } // rof
+
+    } // fi
+  }
+  else
+  {
+    double x[ 3 ];
+    std::stringstream text;
+    for( long i = 0; i < seeds->GetNumberOfPoints( ); ++i )
+    {
+      seeds->GetPoint( i, x );
+      text << x[ 0 ] << " " << x[ 1 ] << " " << x[ 2 ] << "#";
+
+    } // rof
+    this->m_Parameters.SetString( "Text", text.str( ) );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SeedWidget::TCallback*
+cpPluginsVTKWidgets::SeedWidget::TCallback::
+New( )
+{
+  return( new TCallback );
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SeedWidget::TCallback::
+Execute( vtkObject* caller, unsigned long id, void* data )
+{
+  static const double EPS = 1e-5;
+  auto src_act = dynamic_cast< TImageActor* >( caller );
+  auto src_wdg = dynamic_cast< TWidget* >( caller );
+
+  if( id == vtkCommand::InteractionEvent && src_act != NULL )
+  {
+    TWidget* widget = NULL;
+    TSeedRep* seed_rep = NULL;
+
+    auto w = this->m_Widgets.begin( );
+    while( w != this->m_Widgets.end( ) && widget == NULL )
+    {
+      auto rep =
+        dynamic_cast< vtkSeedRepresentation* >(
+          ( *w )->GetRepresentation( )
+          );
+      if( rep != NULL )
+      {
+        auto hnd = rep->GetHandleRepresentation( );
+        if( hnd != NULL )
+        {
+          auto pla =
+            dynamic_cast< SeedWidget::TPlacer* >(
+              hnd->GetPointPlacer( )
+              );
+          if( pla != NULL )
+          {
+            auto act = pla->GetImageSlice( );
+            if( act == src_act )
+            {
+              widget = *w;
+              seed_rep = rep;
+
+            } // fi
+
+          } // fi
+
+        } // fi
+
+      } // fi
+      w++;
+
+    } // elihw
+
+    if( widget != NULL )
+    {
+      // Cut through given seeds
+      auto plane = src_act->GetSlicePlane( );
+      double x[ 3 ];
+      std::vector< long > ids;
+      for( long i = 0; i < this->m_Seeds->GetNumberOfPoints( ); ++i )
+      {
+        this->m_Seeds->GetPoint( i, x );
+        double d = plane->DistanceToPlane( x );
+        if( d <= EPS )
+          ids.push_back( i );
+
+      } // rof
+
+      // Erase seeds
+      widget->CompleteInteraction( );
+      widget->EnabledOff( );
+      int nSeeds = seed_rep->GetNumberOfSeeds ();
+      for( int i = 0; i < nSeeds; ++i )
+      {
+        seed_rep->RemoveLastHandle( );
+        widget->DeleteSeed( seed_rep->GetNumberOfSeeds( ) );
+
+      } // rof
+
+      if( ids.size( ) > 0 )
+      {
+        auto ren = widget->GetInteractor( )->FindPokedRenderer(
+          widget->GetInteractor( )->GetEventPosition( )[ 0 ],
+          widget->GetInteractor( )->GetEventPosition( )[ 1 ]
+          );
+
+        // Add seeds
+        seed_rep->BuildRepresentation( );
+        for( auto id = ids.begin( ); id != ids.end( ); ++id )
+        {
+          this->m_Seeds->GetPoint( *id, x );
+          widget->ComputeWorldToDisplay(
+            ren, x[ 0 ], x[ 1 ], x[ 2 ], x
+            );
+          x[ 2 ] = double( 0 );
+          int s = seed_rep->CreateHandle( x );
+          vtkHandleWidget* curr_hnd = widget->CreateNewHandle( );
+          seed_rep->SetSeedDisplayPosition( s, x );
+          curr_hnd->SetEnabled( 1 );
+
+        } // rof
+
+      } // fi
+
+      // Reactivate widget
+      widget->RestartInteraction( );
+      widget->EnabledOn( );
+      widget->Render( );
+
+    } // fi
+  }
+  else if( id == vtkCommand::PlacePointEvent && src_wdg != NULL )
+  {
+    this->m_Widgets.insert( src_wdg );
+    auto rep =
+      dynamic_cast< vtkSeedRepresentation* >(
+        src_wdg->GetRepresentation( )
+        );
+    if( rep != NULL )
+    {
+      unsigned long nSeeds = rep->GetNumberOfSeeds( );
+      if( nSeeds > 0 )
+      {
+        double pos[ 3 ];
+        rep->GetSeedWorldPosition( nSeeds - 1, pos );
+
+        this->m_Seeds->GetPoints( )->InsertNextPoint( pos );
+        this->m_Seeds->GetVerts( )->InsertNextCell( 1 );
+        this->m_Seeds->GetVerts( )->InsertCellPoint(
+          this->m_Seeds->GetPoints( )->GetNumberOfPoints( ) - 1
+          );
+        this->m_Seeds->Modified( );
+
+      } // fi
+
+    } // fi
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SeedWidget::TCallback::
+SetSeeds( vtkPolyData* seeds )
+{
+  this->m_Seeds = seeds;
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SeedWidget::TCallback::
+TCallback( )
+  : vtkCommand( ),
+    m_Seeds( NULL )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SeedWidget::TCallback::
+~TCallback( )
+{
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKWidgets/SeedWidget.h b/plugins/VTKWidgets/SeedWidget.h
new file mode 100644 (file)
index 0000000..0c70d35
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __cpPluginsVTKWidgets__SeedWidget__h__
+#define __cpPluginsVTKWidgets__SeedWidget__h__
+
+#include <cpPlugins_VTKWidgets_Export.h>
+#include <cpPlugins/Pipeline/Widget.h>
+#include <vtkCommand.h>
+
+// -------------------------------------------------------------------------
+class vtkImageData;
+class vtkPointHandleRepresentation3D;
+class vtkPolyData;
+class vtkSeedRepresentation;
+namespace cpExtensions
+{
+  namespace Interaction
+  {
+    class ImageSlicePointPlacer;
+    class SeedWidget;
+  }
+  namespace Visualization
+  {
+    class WindowLevelImageActor;
+  }
+}
+
+// -------------------------------------------------------------------------
+namespace cpPluginsVTKWidgets
+{
+  /**
+   */
+  class cpPlugins_VTKWidgets_EXPORT SeedWidget
+    : public cpPlugins::Pipeline::Widget
+  {
+    cpPluginsObject( SeedWidget, cpPlugins::Pipeline::Widget, Widgets );
+
+  public:
+    typedef vtkPointHandleRepresentation3D                     THandleRep;
+    typedef vtkSeedRepresentation                              TSeedRep;
+    typedef cpExtensions::Interaction::SeedWidget              TWidget;
+    typedef cpExtensions::Interaction::ImageSlicePointPlacer   TPlacer;
+    typedef cpExtensions::Visualization::WindowLevelImageActor TImageActor;
+
+  public:
+    virtual void Clear( ) cpPlugins_OVERRIDE;
+    virtual void SetEnabled( bool v ) cpPlugins_OVERRIDE;
+    virtual bool GetEnabled( ) const cpPlugins_OVERRIDE;
+
+  protected:
+    /**
+     */
+    class TCallback
+      : public vtkCommand
+    {
+    public:
+      static TCallback* New( );
+      virtual void Execute(
+        vtkObject* caller, unsigned long id, void* data
+        ) cpPlugins_OVERRIDE;
+      void SetSeeds( vtkPolyData* seeds );
+
+    protected:
+      TCallback( );
+      virtual ~TCallback( );
+
+    protected:
+      vtkPolyData*         m_Seeds;
+      std::set< TWidget* > m_Widgets;
+    };
+
+  protected:
+    inline void _GD0_Image( vtkImageData* image );
+
+  protected:
+    std::map< vtkRenderWindowInteractor*, vtkSmartPointer< TWidget > > m_Widgets;
+    vtkSmartPointer< TCallback > m_Command;
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKWidgets__SeedWidget__h__
+
+// eof - $RCSfile$
diff --git a/plugins/VTKWidgets/SplineWidget.cxx b/plugins/VTKWidgets/SplineWidget.cxx
new file mode 100644 (file)
index 0000000..5f82c7e
--- /dev/null
@@ -0,0 +1,253 @@
+#include <VTKWidgets/SplineWidget.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Mesh.h>
+#include <cpExtensions/Visualization/WindowLevelImageActor.h>
+
+#include <itkVector.h>
+
+#include <vtkImageData.h>
+#include <vtkPolyData.h>
+#include <vtkRenderer.h>
+#include <vtkSplineWidget.h>
+#include <vtkParametricSpline.h>
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SplineWidget::
+Clear( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SplineWidget::
+SetEnabled( bool v )
+{
+  auto wdg = this->GetVTK< vtkSplineWidget >( );
+  if( wdg != NULL )
+  {
+    wdg->SetEnabled( v );
+    wdg->GetInteractor( )->Render( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+bool cpPluginsVTKWidgets::SplineWidget::
+GetEnabled( ) const
+{
+  auto wdg = this->GetVTK< const vtkSplineWidget >( );
+  if( wdg != NULL )
+  {
+    vtkSplineWidget* w = const_cast< vtkSplineWidget* >( wdg );
+    return( w->GetEnabled( ) != 0 );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SplineWidget::
+SplineWidget( )
+  : Superclass( ),
+    m_Configured( false )
+{
+  typedef cpPlugins::Pipeline::DataObject _TData;
+  typedef cpInstances::DataObjects::Mesh       _TMesh;
+
+  this->_ConfigureInput< _TData >( "Input", false, false );
+  this->_ConfigureOutput< _TMesh >( "Output" );
+  this->m_Contour = vtkSmartPointer< vtkPolyData >::New( );
+  this->m_Contour->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+  this->m_Contour->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+  this->m_Contour->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+  this->m_Contour->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+  this->m_Contour->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+  this->GetOutput( "Output" )->SetVTK( this->m_Contour );
+
+  this->m_Parameters.ConfigureAsBool( "Extend", false );
+}
+
+// -------------------------------------------------------------------------
+cpPluginsVTKWidgets::SplineWidget::
+~SplineWidget( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginsVTKWidgets::SplineWidget::
+_GenerateData( )
+{
+  typedef cpExtensions::Visualization::WindowLevelImageActor _TActor;
+
+  auto image = this->GetInputData< vtkImageData >( "Input" );
+  if( image == NULL )
+    this->_Error( "Invalid input image." );
+  if( this->m_Interactors.size( ) == 0 )
+    this->_Error( "Give at least one interactor." );
+
+  auto wdg = this->_CreateVTK< vtkSplineWidget >( );
+  if( this->m_Configured )
+  {
+    if( this->m_Parameters.GetBool( "Extend" ) )
+    {
+      wdg->GetPolyData( this->m_Contour.GetPointer( ) );
+
+      typedef itk::Vector< double, 3 > _TVector;
+      typedef std::vector< _TVector > _TVectors;
+
+      unsigned long nPoints = this->m_Contour->GetNumberOfPoints( );
+      unsigned long support = nPoints / 10;
+      _TVectors pp, qp;
+      for( unsigned long i = 0; i < support; ++i )
+      {
+        double p[ 3 ], q[ 3 ];
+        this->m_Contour->GetPoint( i, p );
+        this->m_Contour->GetPoint( nPoints - 1 - i, q );
+
+        _TVector pv, qv;
+        pv[ 0 ] = p[ 0 ];
+        pv[ 1 ] = p[ 1 ];
+        pv[ 2 ] = p[ 2 ];
+        qv[ 0 ] = q[ 0 ];
+        qv[ 1 ] = q[ 1 ];
+        qv[ 2 ] = q[ 2 ];
+        pp.push_back( pv );
+        qp.push_back( qv );
+
+      } // rof
+
+      _TVectors pt, qt;
+      pt.push_back( pp[ 1 ] - pp[ 0 ] );
+      qt.push_back( qp[ 1 ] - qp[ 0 ] );
+      for( unsigned long i = 1; i < support - 1; ++i )
+      {
+        pt.push_back( pp[ i + 1 ] - pp[ i - 1 ] );
+        qt.push_back( qp[ i + 1 ] - qp[ i - 1 ] );
+
+      } // rof
+      pt.push_back( pp[ support - 1 ] - pp[ support - 2 ] );
+      qt.push_back( qp[ support - 1 ] - qp[ support - 2 ] );
+
+      _TVector t0( double( 0 ) ), t1( double( 0 ) );
+      long real0 = 0, real1 = 0;
+      for( unsigned long i = 0; i < support; ++i )
+      {
+        double n0 = pt[ i ].GetNorm( );
+        if( n0 > double( 0 ) )
+        {
+          t0 += pt[ i ] / n0;
+          real0++;
+
+        } // fi
+
+        double n1 = qt[ i ].GetNorm( );
+        if( n1 > double( 0 ) )
+        {
+          t1 += qt[ i ] / n1;
+          real1++;
+
+        } // fi
+
+      } // rof
+
+      if( real0 > 0 )
+        t0 /= double( -real0 );
+      if( real1 > 0 )
+        t1 /= double( -real1 );
+
+      t0 *= ( pp[ 0 ] - qp[ 0 ] ).GetNorm( );
+      t1 *= ( pp[ 0 ] - qp[ 0 ] ).GetNorm( );
+
+      _TVector p0 = pp[ 0 ] + t0;
+      _TVector p1 = qp[ 0 ] + t1;
+
+      vtkSmartPointer< vtkPolyData > cnt = this->m_Contour;
+      this->m_Contour = vtkSmartPointer< vtkPolyData >::New( );
+      this->m_Contour->SetPoints( vtkSmartPointer< vtkPoints >::New( ) );
+      this->m_Contour->SetVerts( vtkSmartPointer< vtkCellArray >::New( ) );
+      this->m_Contour->SetLines( vtkSmartPointer< vtkCellArray >::New( ) );
+      this->m_Contour->SetPolys( vtkSmartPointer< vtkCellArray >::New( ) );
+      this->m_Contour->SetStrips( vtkSmartPointer< vtkCellArray >::New( ) );
+      this->GetOutput( "Output" )->SetVTK( this->m_Contour );
+
+      this->m_Contour->GetPoints( )->
+        InsertNextPoint( p0[ 0 ], p0[ 1 ], p0[ 2 ] );
+      for( unsigned long i = 0; i < nPoints; ++i )
+      {
+        double p[ 3 ];
+        cnt->GetPoints( )->GetPoint( i, p );
+        this->m_Contour->GetPoints( )->InsertNextPoint( p );
+
+      } // rof
+      this->m_Contour->GetPoints( )->
+        InsertNextPoint( p1[ 0 ], p1[ 1 ], p1[ 2 ] );
+      this->m_Contour->Modified( );
+    }
+    else
+      wdg->GetPolyData( this->m_Contour.GetPointer( ) );
+  }
+  else
+  {
+    auto iIt = this->m_Interactors.begin( );
+    vtkRenderWindowInteractor* iren = NULL;
+    vtkRenderer* ren = NULL;
+    _TActor* actor = NULL;
+    for( ; iIt != this->m_Interactors.end( ); ++iIt )
+    {
+      auto r = ( *iIt )->GetInteractorStyle( )->GetCurrentRenderer( );
+      if( r != NULL )
+      {
+        auto props = r->GetViewProps( );
+        if( props != NULL )
+        {
+          props->InitTraversal( );
+          while( vtkProp* prop = props->GetNextProp( ) )
+          {
+            auto a = dynamic_cast< _TActor* >( prop );
+            if( a != NULL )
+              if( a->GetImage( ) == image )
+              {
+                iren = *iIt;
+                actor = a;
+                ren = r;
+
+              } // fi
+
+          } // elihw
+
+        } // fi
+
+      } // fi
+
+    } // rof
+    if( actor == NULL || ren == NULL || iren == NULL )
+      this->_Error( "Invalid actor and/or renderer." );
+
+    // Widget configuration
+    wdg->SetCurrentRenderer( ren );
+    wdg->SetDefaultRenderer( ren );
+    wdg->SetInputData( image );
+    wdg->SetProp3D( actor );
+    wdg->SetInteractor( iren );
+    double bnds[ 6 ];
+    image->GetBounds( bnds );
+    wdg->PlaceWidget(
+      bnds[ 0 ], bnds[ 1 ],
+      bnds[ 2 ], bnds[ 3 ],
+      bnds[ 4 ], bnds[ 5 ]
+      );
+    wdg->ProjectToPlaneOn( );
+    wdg->SetProjectionNormalToZAxes( );
+    wdg->SetProjectionPosition(
+      (
+        actor->GetBounds( )[ 4 ] +
+        actor->GetBounds( )[ 5 ]
+        ) / double( 2 )
+      );
+    wdg->SetHandleSize( 0.005 );
+    wdg->SetNumberOfHandles( 3 );
+    this->m_Configured = true;
+
+  } // fi
+}
+
+// eof - $RCSfile$
diff --git a/plugins/VTKWidgets/SplineWidget.h b/plugins/VTKWidgets/SplineWidget.h
new file mode 100644 (file)
index 0000000..6822323
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __cpPluginsVTKWidgets__SplineWidget__h__
+#define __cpPluginsVTKWidgets__SplineWidget__h__
+
+#include <cpPlugins_VTKWidgets_Export.h>
+#include <cpPlugins/Pipeline/Widget.h>
+
+#include <vtkSmartPointer.h>
+
+/* TODO
+   #include <cpExtensions/Interaction/SplineWidget.h>
+   #include <cpExtensions/Interaction/ImageSlicePointPlacer.h>
+   #include <cpExtensions/Visualization/WindowLevelImageActor.h>
+   #include <vtkImageSlice.h>
+   #include <vtkPointHandleRepresentation3D.h>
+   #include <vtkSeedRepresentation.h>
+   #include <map>
+*/
+
+// -------------------------------------------------------------------------
+class vtkPolyData;
+
+// -------------------------------------------------------------------------
+namespace cpPluginsVTKWidgets
+{
+  /**
+   */
+  class cpPlugins_VTKWidgets_EXPORT SplineWidget
+    : public cpPlugins::Pipeline::Widget
+  {
+    cpPluginsObject( SplineWidget, cpPlugins::Pipeline::Widget, Widgets );
+
+  public:
+    virtual void Clear( ) cpPlugins_OVERRIDE;
+    virtual void SetEnabled( bool v ) cpPlugins_OVERRIDE;
+    virtual bool GetEnabled( ) const cpPlugins_OVERRIDE;
+
+  protected:
+    bool m_Configured;
+    vtkSmartPointer< vtkPolyData > m_Contour;
+
+    /* TODO:
+       public:
+       typedef cpExtensions::Visualization::WindowLevelImageActor TImageActor;
+
+       public:
+       struct TWidgetData
+       {
+       typedef cpExtensions::Interaction::SplineWidget            _TWidget;
+       typedef cpExtensions::Interaction::ImageSlicePointPlacer _TPlacer;
+
+       std::vector< vtkSmartPointer< _TWidget > >                       Widgets;
+       std::vector< vtkSmartPointer< _TPlacer > >                       Placers;
+       std::vector< vtkSmartPointer< vtkPointHandleRepresentation3D > > Handles;
+       std::vector< vtkSmartPointer< vtkSeedRepresentation > >  Representations;
+       unsigned int ActualWidgetId;
+       vtkSmartPointer< vtkCommand > Command;
+
+       TWidgetData(
+       SplineWidget* seedWidget,
+       TImageActor* actor,
+       vtkRenderWindowInteractor* iren
+       );
+       virtual ~TWidgetData( );
+       };
+
+       protected:
+       void _Configure( );
+
+       template< class _TImage >
+       inline void _GD0_Image( _TImage* image );
+
+       protected:
+       std::map< vtkProp*, vtkRenderWindowInteractor* > m_Props;
+       std::vector< TWidgetData* > m_Widgets;
+       bool m_Configured;
+    */
+  };
+
+} // ecapseman
+
+#endif // __cpPluginsVTKWidgets__SplineWidget__h__
+
+// eof - $RCSfile$
diff --git a/plugins/change.csv b/plugins/change.csv
new file mode 100644 (file)
index 0000000..999df74
--- /dev/null
@@ -0,0 +1 @@
+grep -rl cpPlugins_GenericPlugins . | xargs sed -i 's/cpPlugins_GenericPlugins/cpPlugins_GenericPlugins/g'
diff --git a/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.cxx b/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.cxx
new file mode 100644 (file)
index 0000000..21760ce
--- /dev/null
@@ -0,0 +1,46 @@
+#include <cpExtensions/PolyLineParametricPathToSimple3DCurve.h>
+#include <cpInstances/DataObjects/PolyLineParametricPath.h>
+#include <cpInstances/DataObjects/Simple3DCurve.h>
+
+#include <cpExtensions/DataStructures/PolyLineParametricPath.h>
+#include <cpExtensions/DataStructures/Simple3DCurve.h>
+#include <cpExtensions/Algorithms/PolyLineParametricPathToSimple3DCurve.h>
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::PolyLineParametricPathToSimple3DCurve::
+PolyLineParametricPathToSimple3DCurve( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::PolyLineParametricPath >(
+    "Input", true, false
+    );
+  this->_ConfigureOutput< cpInstances::Simple3DCurve >( "Output" );
+  this->m_Parameters.ConfigureAsUint( "NumberOfSamples", 0 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::PolyLineParametricPathToSimple3DCurve::
+~PolyLineParametricPathToSimple3DCurve( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginscpExtensions::PolyLineParametricPathToSimple3DCurve::
+_GenerateData( )
+{
+  typedef cpExtensions::DataStructures::PolyLineParametricPath< 3 > _TPath;
+  typedef cpExtensions::DataStructures::Simple3DCurve< double > _TCurve;
+  typedef cpExtensions::Algorithms::PolyLineParametricPathToSimple3DCurve< _TPath, _TCurve > _TFilter;
+
+  auto in = this->GetInputData< _TPath >( "Input" );
+  if( in == NULL )
+    this->_Error( "Invalid input path." );
+
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetInput( in );
+  filter->SetNumberOfSamples( this->m_Parameters.GetUint( "NumberOfSamples" ) );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.h b/plugins/cpExtensions/PolyLineParametricPathToSimple3DCurve.h
new file mode 100644 (file)
index 0000000..864acf6
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __cpPluginscpExtensions__PolyLineParametricPathToSimple3DCurve__h__
+#define __cpPluginscpExtensions__PolyLineParametricPathToSimple3DCurve__h__
+
+#include <cpPlugins_cpExtensions_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginscpExtensions
+{
+  /**
+   */
+  class cpPlugins_cpExtensions_EXPORT PolyLineParametricPathToSimple3DCurve
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      PolyLineParametricPathToSimple3DCurve,
+      cpPlugins::Pipeline::ProcessObject,
+      cpExtensions
+      );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginscpExtensions__PolyLineParametricPathToSimple3DCurve__h__
+
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/PolyLineParametricPathWriter.cxx b/plugins/cpExtensions/PolyLineParametricPathWriter.cxx
new file mode 100644 (file)
index 0000000..7ee1be3
--- /dev/null
@@ -0,0 +1,79 @@
+#include <cpExtensions/PolyLineParametricPathWriter.h>
+#include <cpInstances/DataObjects/PolyLineParametricPath.h>
+
+#include <cpExtensions/DataStructures/PolyLineParametricPath.h>
+#include <cpExtensions/Algorithms/PolyLineParametricPathWriter.h>
+#include <cpPlugins/QT/SaveFileDialog.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginscpExtensions::PolyLineParametricPathWriter::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::SaveFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::SaveFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileName" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::PolyLineParametricPathWriter::
+PolyLineParametricPathWriter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::PolyLineParametricPath >( "Input", true, false );
+  this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileName",
+    "PolyLineParametricPath files (*.txt)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::PolyLineParametricPathWriter::
+~PolyLineParametricPathWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginscpExtensions::PolyLineParametricPathWriter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_PolyLineParametricPath_All_1( o, _GD0 )
+    this->_Error( "Invalid input skeleton." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TPolyLineParametricPath >
+void cpPluginscpExtensions::PolyLineParametricPathWriter::
+_GD0( _TPolyLineParametricPath* skeleton )
+{
+  typedef cpExtensions::Algorithms::PolyLineParametricPathWriter< _TPolyLineParametricPath > _TWriter;
+
+  auto filter = this->_CreateITK< _TWriter >( );
+  filter->SetInput( skeleton );
+  filter->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) );
+  try
+  {
+    filter->Update( );
+  }
+  catch( itk::ExceptionObject& err )
+  {
+    this->_Error( err.GetDescription( ) );
+
+  } // yrt
+}
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/PolyLineParametricPathWriter.h b/plugins/cpExtensions/PolyLineParametricPathWriter.h
new file mode 100644 (file)
index 0000000..2794132
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __cpPluginscpExtensions__PolyLineParametricPathWriter__h__
+#define __cpPluginscpExtensions__PolyLineParametricPathWriter__h__
+
+#include <cpPlugins_cpExtensions_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginscpExtensions
+{
+  /**
+   */
+  class cpPlugins_cpExtensions_EXPORT PolyLineParametricPathWriter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      PolyLineParametricPathWriter,
+      cpPlugins::Pipeline::ProcessObject,
+      IO
+      );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< class _TPolyLineParametricPath >
+    inline void _GD0( _TPolyLineParametricPath* skeleton );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginscpExtensions__PolyLineParametricPathWriter__h__
+
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/SkeletonReader.cxx b/plugins/cpExtensions/SkeletonReader.cxx
new file mode 100644 (file)
index 0000000..f62ff69
--- /dev/null
@@ -0,0 +1,93 @@
+#include <cpExtensions/SkeletonReader.h>
+#include <cpInstances/DataObjects/Skeleton.h>
+
+#include <cpExtensions/DataStructures/Skeleton.h>
+#include <cpExtensions/Algorithms/SkeletonReader.h>
+#include <cpPlugins/QT/OpenFileDialog.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginscpExtensions::SkeletonReader::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::OpenFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::OpenFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileName" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::SkeletonReader::
+SkeletonReader( )
+  : Superclass( )
+{
+  this->_ConfigureOutput< cpInstances::Skeleton >( "Output" );
+  this->m_Parameters.ConfigureAsOpenFileName( "FileName", "" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileName",
+    "Skeleton files (*.txt)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::SkeletonReader::
+~SkeletonReader( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginscpExtensions::SkeletonReader::
+_GenerateData( )
+{
+  std::string success = "";
+#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_1
+  success = this->_GD0< 1 >( );
+#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_1
+#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_2
+  if( success != "" ) success = this->_GD0< 2 >( );
+#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_2
+#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_3
+  if( success != "" ) success = this->_GD0< 3 >( );
+#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_3
+#ifdef cpPlugins_CONFIG_PROCESS_DIMENSIONS_4
+  if( success != "" ) success = this->_GD0< 4 >( );
+#endif // cpPlugins_CONFIG_PROCESS_DIMENSIONS_4
+  if( success != "" )
+    this->_Error( success );
+}
+
+// -------------------------------------------------------------------------
+template< unsigned int _VDim >
+std::string cpPluginscpExtensions::SkeletonReader::
+_GD0( )
+{
+  typedef cpExtensions::DataStructures::Skeleton< _VDim > _TSkeleton;
+  typedef cpExtensions::Algorithms::SkeletonReader< _TSkeleton > _TReader;
+
+  auto filter = this->_CreateITK< _TReader >( );
+  filter->SetFileName( this->m_Parameters.GetOpenFileName( "FileName" ) );
+  try
+  {
+    filter->Update( );
+  }
+  catch( std::exception& err )
+  {
+    return( err.what( ) );
+
+  } // yrt
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+  return( "" );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/SkeletonReader.h b/plugins/cpExtensions/SkeletonReader.h
new file mode 100644 (file)
index 0000000..3490682
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __cpPluginscpExtensions__SkeletonReader__h__
+#define __cpPluginscpExtensions__SkeletonReader__h__
+
+#include <cpPlugins_cpExtensions_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginscpExtensions
+{
+  /**
+   */
+  class cpPlugins_cpExtensions_EXPORT SkeletonReader
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      SkeletonReader,
+      cpPlugins::Pipeline::ProcessObject,
+      IO
+      );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< unsigned int _VDim >
+    inline std::string _GD0( );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginscpExtensions__SkeletonReader__h__
+
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/SkeletonToImageFilter.cxx b/plugins/cpExtensions/SkeletonToImageFilter.cxx
new file mode 100644 (file)
index 0000000..30bdddc
--- /dev/null
@@ -0,0 +1,54 @@
+#include <cpExtensions/SkeletonToImageFilter.h>
+#include <cpInstances/DataObjects/Image.h>
+#include <cpInstances/DataObjects/Skeleton.h>
+
+#include <cpExtensions/DataStructures/Skeleton.h>
+#include <cpExtensions/Algorithms/SkeletonToImageFilter.h>
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::SkeletonToImageFilter::
+SkeletonToImageFilter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::Skeleton >( "Skeleton", true, false );
+  this->_ConfigureInput< cpInstances::DataObjects::Image >( "TemplateImage", true, false );
+  this->_ConfigureOutput< cpInstances::DataObjects::Image >( "Output" );
+  this->m_Parameters.ConfigureAsUint( "InsideValue", 1 );
+  this->m_Parameters.ConfigureAsUint( "OutsideValue", 0 );
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::SkeletonToImageFilter::
+~SkeletonToImageFilter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginscpExtensions::SkeletonToImageFilter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Skeleton" );
+  cpPlugins_Demangle_Skeleton_All_1( o, _GD0 )
+    this->_Error( "Invalid input skeleton." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpPluginscpExtensions::SkeletonToImageFilter::
+_GD0( _TSkeleton* skeleton )
+{
+  typedef itk::ImageBase< _TSkeleton::Dimension > _TImageBase;
+  typedef itk::Image< unsigned char, _TSkeleton::Dimension > _TImage;
+  typedef cpExtensions::Algorithms::SkeletonToImageFilter< _TSkeleton, _TImage > _TFilter;
+
+  auto image = this->GetInputData< _TImageBase >( "TemplateImage" );
+  auto filter = this->_CreateITK< _TFilter >( );
+  filter->SetTemplateImage( image );
+  filter->SetSkeleton( skeleton );
+  filter->SetInsideValue( this->m_Parameters.GetUint( "InsideValue" ) );
+  filter->SetOutsideValue( this->m_Parameters.GetUint( "OutsideValue" ) );
+  filter->Update( );
+  this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) );
+}
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/SkeletonToImageFilter.h b/plugins/cpExtensions/SkeletonToImageFilter.h
new file mode 100644 (file)
index 0000000..99aa824
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef __cpPluginscpExtensions__SkeletonToImageFilter__h__
+#define __cpPluginscpExtensions__SkeletonToImageFilter__h__
+
+#include <cpPlugins_cpExtensions_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginscpExtensions
+{
+  /**
+   */
+  class cpPlugins_cpExtensions_EXPORT SkeletonToImageFilter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      SkeletonToImageFilter,
+      cpPlugins::Pipeline::ProcessObject,
+      cpExtensions
+      );
+
+  protected:
+    template< class _TSkeleton >
+    inline void _GD0( _TSkeleton* skeleton );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginscpExtensions__SkeletonToImageFilter__h__
+
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/SkeletonWriter.cxx b/plugins/cpExtensions/SkeletonWriter.cxx
new file mode 100644 (file)
index 0000000..f23f600
--- /dev/null
@@ -0,0 +1,79 @@
+#include <cpExtensions/SkeletonWriter.h>
+#include <cpInstances/DataObjects/Skeleton.h>
+
+#include <cpExtensions/DataStructures/Skeleton.h>
+#include <cpExtensions/Algorithms/SkeletonWriter.h>
+#include <cpPlugins/QT/SaveFileDialog.h>
+
+#ifdef cpPlugins_QT4
+#  include <QApplication>
+#endif // cpPlugins_QT4
+
+// -------------------------------------------------------------------------
+QDialog* cpPluginscpExtensions::SkeletonWriter::
+CreateQDialog( )
+{
+#ifdef cpPlugins_QT4
+  cpPlugins::QT::SaveFileDialog* dlg = NULL;
+  if( QApplication::instance( ) != NULL )
+  {
+    dlg = new cpPlugins::QT::SaveFileDialog( );
+    dlg->SetParameters( &( this->m_Parameters ), "FileName" );
+
+  } // fi
+  return( dlg );
+#else // cpPlugins_QT4
+  return( NULL );
+#endif // cpPlugins_QT4
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::SkeletonWriter::
+SkeletonWriter( )
+  : Superclass( )
+{
+  this->_ConfigureInput< cpInstances::Skeleton >( "Input", true, false );
+  this->m_Parameters.ConfigureAsSaveFileName( "FileName", "" );
+  this->m_Parameters.SetAcceptedFileExtensions(
+    "FileName",
+    "Skeleton files (*.txt)"
+    );
+}
+
+// -------------------------------------------------------------------------
+cpPluginscpExtensions::SkeletonWriter::
+~SkeletonWriter( )
+{
+}
+
+// -------------------------------------------------------------------------
+void cpPluginscpExtensions::SkeletonWriter::
+_GenerateData( )
+{
+  auto o = this->GetInputData( "Input" );
+  cpPlugins_Demangle_Skeleton_All_1( o, _GD0 )
+    this->_Error( "Invalid input skeleton." );
+}
+
+// -------------------------------------------------------------------------
+template< class _TSkeleton >
+void cpPluginscpExtensions::SkeletonWriter::
+_GD0( _TSkeleton* skeleton )
+{
+  typedef cpExtensions::Algorithms::SkeletonWriter< _TSkeleton > _TWriter;
+
+  auto filter = this->_CreateITK< _TWriter >( );
+  filter->SetInput( skeleton );
+  filter->SetFileName( this->m_Parameters.GetSaveFileName( "FileName" ) );
+  try
+  {
+    filter->Update( );
+  }
+  catch( itk::ExceptionObject& err )
+  {
+    this->_Error( err.GetDescription( ) );
+
+  } // yrt
+}
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/SkeletonWriter.h b/plugins/cpExtensions/SkeletonWriter.h
new file mode 100644 (file)
index 0000000..920ae01
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __cpPluginscpExtensions__SkeletonWriter__h__
+#define __cpPluginscpExtensions__SkeletonWriter__h__
+
+#include <cpPlugins_cpExtensions_Export.h>
+#include <cpPlugins/Pipeline/ProcessObject.h>
+
+namespace cpPluginscpExtensions
+{
+  /**
+   */
+  class cpPlugins_cpExtensions_EXPORT SkeletonWriter
+    : public cpPlugins::Pipeline::ProcessObject
+  {
+    cpPluginsObject(
+      SkeletonWriter,
+      cpPlugins::Pipeline::ProcessObject,
+      IO
+      );
+
+  public:
+    virtual QDialog* CreateQDialog( ) cpPlugins_OVERRIDE;
+
+  protected:
+    template< class _TSkeleton >
+    inline void _GD0( _TSkeleton* skeleton );
+  };
+
+} // ecapseman
+
+#endif // __cpPluginscpExtensions__SkeletonWriter__h__
+
+
+// eof - $RCSfile$
diff --git a/plugins/cpExtensions/cpExtensions.i b/plugins/cpExtensions/cpExtensions.i
new file mode 100644 (file)
index 0000000..4d3e1ea
--- /dev/null
@@ -0,0 +1,13 @@
+header #define ITK_MANUAL_INSTANTIATION
+
+tinclude cpExtensions/Algorithms/SkeletonToImageFilter:h|hxx
+tinclude cpExtensions/Algorithms/SkeletonReader:h|hxx
+tinclude cpExtensions/Algorithms/SkeletonWriter:h|hxx
+cinclude cpExtensions/DataStructures/Skeleton.h
+
+instances cpExtensions::Algorithms::SkeletonToImageFilter< cpExtensions::DataStructures::Skeleton< #pdims# >, itk::Image< unsigned char, #pdims# > >
+
+instances cpExtensions::Algorithms::SkeletonReader< cpExtensions::DataStructures::Skeleton< #pdims# > >
+instances cpExtensions::Algorithms::SkeletonWriter< cpExtensions::DataStructures::Skeleton< #pdims# > >
+
+** eof - $RCSfile$
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
new file mode 100644 (file)
index 0000000..988fc31
--- /dev/null
@@ -0,0 +1,29 @@
+
+## ===================
+## == List of tools ==
+## ===================
+
+SET(_pfx cpPlugins_tool_)
+SET(
+  _tools
+  ExecutePipeline
+  PrintFileInfo
+  PrintDirInfo
+  PrintGuessInfo
+  RenameImageFile
+  )
+
+## =======================
+## == Compilation rules ==
+## =======================
+
+INCLUDE_DIRECTORIES(
+  ${PROJECT_SOURCE_DIR}/lib
+  ${PROJECT_BINARY_DIR}/lib
+  )
+FOREACH(_t ${_tools})
+  ADD_EXECUTABLE(${_pfx}${_t} ${_t}.cxx)
+  TARGET_LINK_LIBRARIES(${_pfx}${_t} cpPlugins)
+ENDFOREACH(_t)
+
+## eof - $RCSfile$
diff --git a/tools/ExecutePipeline.cxx b/tools/ExecutePipeline.cxx
new file mode 100644 (file)
index 0000000..2c59a03
--- /dev/null
@@ -0,0 +1,7 @@
+
+int main( int argc, char* argv[] )
+{
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tools/PrintDirInfo.cxx b/tools/PrintDirInfo.cxx
new file mode 100644 (file)
index 0000000..0c00f79
--- /dev/null
@@ -0,0 +1,56 @@
+#include <iostream>
+#include <cpPlugins/Interface/Loader.h>
+
+int main( int argc, char* argv[] )
+{
+  if( argc < 2 )
+  {
+    std::cerr << "Usage: " << argv[ 0 ] << " library" << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Get plugins loader
+  std::string error_message = "";
+  cpPlugins::Interface::Loader loader;
+  for( int i = 1; i < argc; ++i )
+  {
+    try
+    {
+      loader.RegisterFromDirectory( argv[ i ] );
+    }
+    catch( std::exception& err )
+    {
+      error_message += err.what( ) + std::string( "\n" );
+
+    } // yrt
+
+  } // rof
+
+  if( error_message != "" )
+  {
+    std::cerr
+      << "***************************************" << std::endl
+      << "Errors during load: " << std::endl
+      << error_message << std::endl
+      << "***************************************" << std::endl;
+
+  } // fi
+
+  // Show loader information
+  std::cout << "---------------------------" << std::endl;
+  std::cout << loader << std::endl;
+  std::cout << "---------------------------" << std::endl;
+
+  // Close connection to loaded plugins file
+  loader.UnRegisterAll( );
+
+  // Just a last check
+  std::cout << "---------------------------" << std::endl;
+  std::cout << loader << std::endl;
+  std::cout << "---------------------------" << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tools/PrintFileInfo.cxx b/tools/PrintFileInfo.cxx
new file mode 100644 (file)
index 0000000..0eb1109
--- /dev/null
@@ -0,0 +1,56 @@
+#include <iostream>
+#include <cpPlugins/Interface/Loader.h>
+
+int main( int argc, char* argv[] )
+{
+  if( argc < 2 )
+  {
+    std::cerr << "Usage: " << argv[ 0 ] << " library" << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Get plugins loader
+  std::string error_message = "";
+  cpPlugins::Interface::Loader loader;
+  for( int i = 1; i < argc; ++i )
+  {
+    try
+    {
+      loader.Register( argv[ i ] );
+    }
+    catch( std::exception& err )
+    {
+      error_message += err.what( ) + std::string( "\n" );
+
+    } // yrt
+
+  } // rof
+
+  if( error_message != "" )
+  {
+    std::cerr
+      << "***************************************" << std::endl
+      << "Errors during load: " << std::endl
+      << error_message << std::endl
+      << "***************************************" << std::endl;
+
+  } // fi
+
+  // Show loader information
+  std::cout << "---------------------------" << std::endl;
+  std::cout << loader << std::endl;
+  std::cout << "---------------------------" << std::endl;
+
+  // Close connection to loaded plugins file
+  loader.UnRegisterAll( );
+
+  // Just a last check
+  std::cout << "---------------------------" << std::endl;
+  std::cout << loader << std::endl;
+  std::cout << "---------------------------" << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tools/PrintGuessInfo.cxx b/tools/PrintGuessInfo.cxx
new file mode 100644 (file)
index 0000000..7b50afd
--- /dev/null
@@ -0,0 +1,28 @@
+#include <iostream>
+#include <cpPlugins/Interface/Loader.h>
+#include <cpPlugins/OS/FileSystem.h>
+
+int main( int argc, char* argv[] )
+{
+  // Get plugins loader
+  std::string error_message = "";
+  cpPlugins::Interface::Loader loader;
+  loader.GuessEnvironment( cpPlugins::OS::FileSystem::CanonicalPath( "." ) );
+
+  // Show loader information
+  std::cout << "---------------------------" << std::endl;
+  std::cout << loader << std::endl;
+  std::cout << "---------------------------" << std::endl;
+
+  // Close connection to loaded plugins file
+  loader.UnRegisterAll( );
+
+  // Just a last check
+  std::cout << "---------------------------" << std::endl;
+  std::cout << loader << std::endl;
+  std::cout << "---------------------------" << std::endl;
+
+  return( 0 );
+}
+
+// eof - $RCSfile$
diff --git a/tools/RenameImageFile.cxx b/tools/RenameImageFile.cxx
new file mode 100644 (file)
index 0000000..60297c4
--- /dev/null
@@ -0,0 +1,62 @@
+#include <iostream>
+#include <cpPlugins/Interface/Loader.h>
+
+int main( int argc, char* argv[] )
+{
+  if( argc < 2 )
+  {
+    std::cerr
+      << "Usage: " << argv[ 0 ]
+      << " input_file(s) output_file" << std::endl;
+    return( 1 );
+
+  } // fi
+
+  // Get plugins loader
+  cpPlugins::Interface::Loader loader;
+  try
+  {
+    loader.RegisterFromDirectory( "." );
+  }
+  catch( std::exception& err )
+  {
+    std::cerr << "Error caught: " << err.what( ) << std::endl;
+    return( 1 );
+
+  } // yrt
+
+  // Try to get any errors
+  try
+  {
+    // Create filters
+    auto reader = loader.CreateFilter( "IO", "ImageReader", "reader" );
+    auto writer = loader.CreateFilter( "IO", "ImageWriter", "writer" );
+
+    // Configure parameters
+    auto reader_params = reader->GetParameters( );
+    auto writer_params = writer->GetParameters( );
+    for( int i = 1; i < argc - 1; ++i )
+      reader_params->AddToOpenFileNameList( "FileNames", argv[ i ] );
+    writer_params->SetSaveFileName( "FileName", argv[ argc - 1 ] );
+
+    // Connect filters
+    writer->SetInput( "Input", reader->GetOutput( "Output" ) );
+
+    // Execute
+    reader->PrintExecutionOn( );
+    writer->PrintExecutionOn( );
+    writer->Update( );
+  }
+  catch( std::exception& err )
+  {
+    std::cerr << "Error caught: " << err.what( ) << std::endl;
+    return( 1 );
+
+  } // yrt
+
+  // Close connection to loaded plugins file
+  loader.UnRegisterAll( );
+  return( 0 );
+}
+
+// eof - $RCSfile$