From 201c5026430f9bcc33f9db6a39f5d03db096c860 Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Sun, 26 Jun 2016 23:13:31 -0500 Subject: [PATCH] Code cleaning --- CMakeLists.txt | 51 + COMPILATION | 132 + README | 49 + appli/CMakeLists.txt | 8 + appli/PipelineEditor/CMakeLists.txt | 9 + .../PipelineEditorMainWindow.cxx | 85 + .../PipelineEditor/PipelineEditorMainWindow.h | 58 + .../PipelineEditorMainWindow.ui | 189 + appli/PipelineEditor/main.cxx | 7 + appli/bash/CMakeLists.txt | 27 + appli/bash/cpPlugins_CreateInstances.cxx | 286 + appli/bash/cpPlugins_HostCreator.cxx | 172 + appli/examples/CMakeLists.txt | 10 + appli/examples/extensions/CMakeLists.txt | 21 + .../example_extensions_ImageSlice.cxx | 52 + ...nsions_IterativeGaussianModelEstimator.cxx | 81 + .../example_extensions_KalmanVelocity.cxx | 59 + appli/examples/plugins/CMakeLists.txt | 21 + .../plugins/example_plugins_GuessPlugins.cxx | 44 + .../plugins/example_plugins_LoadDirectory.cxx | 53 + .../plugins/example_plugins_LoadFile.cxx | 53 + .../plugins/example_plugins_LoadPlugin.cxx | 53 + .../plugins/example_plugins_ReadImage.cxx | 64 + appli/plugins/CMakeLists.txt | 21 + appli/plugins/cpPlugins_ExecuteWorkspace.cxx | 76 + cmake/CMakeLists.txt | 11 + cmake/cpPluginsConfig.cmake.in | 118 + cmake/cpPlugins_Functions.cmake | 342 + cmake/cpPlugins_KitwareTools.cmake | 19 + cmake/cpPlugins_Options.cmake | 51 + cmake/cpPlugins_Policies.cmake | 23 + cmake/cpPlugins_Qt4Tools.cmake | 44 + data/ReadWriteImage.wxml | 15 + data/circles.png | Bin 0 -> 4877 bytes data/inertia.lyx | 454 + data/line_rad_25.png | Bin 0 -> 6540 bytes data/mesh_00.vtk | 96 + data/mesh_01.obj | 12446 ++++++++++++++++ data/mesh_02.obj | 7214 +++++++++ data/mesh_03.vtk | 28 + data/mesh_04.vtk | 5461 +++++++ data/mesh_05.obj | 8863 +++++++++++ data/mesh_06.vtk | 12 + .../save_dicomseries_as_singlefile_image.wxml | 12 + data/test.png | Bin 0 -> 4705 bytes data/test2.png | Bin 0 -> 3812 bytes data/test3.png | Bin 0 -> 5600 bytes data/workspace_00.xml | 16 + doc/uml/cpPlugins_classes.dia | Bin 0 -> 5924 bytes lib/CMakeLists.txt | 75 + lib/Instances/BaseImageFilters.i | 35 + lib/Instances/BaseImages.i | 24 + lib/Instances/BaseImages_extra.cxx | 18 + lib/Instances/BaseObjects.i | 46 + lib/Instances/BaseObjects_extra.cxx | 99 + lib/Instances/BitwiseImageFilters.i | 14 + lib/Instances/CMakeLists.txt | 60 + lib/Instances/CastImageFilters.i | 33 + lib/Instances/ColorImages.i | 48 + lib/Instances/DistanceMapFilters.i | 15 + lib/Instances/ExtractImageFilters.i | 19 + lib/Instances/GaussianImageFilters.i | 26 + lib/Instances/ImageMeshFilters.i | 14 + lib/Instances/ImageReaders.i | 41 + lib/Instances/ImageWriters.i | 41 + lib/Instances/MedialnessFilters.i | 22 + lib/Instances/Mesh.i | 36 + lib/Instances/MorphologicalImageFilters.i | 34 + lib/Instances/NeighborhoodIterators.i | 22 + lib/Instances/Paths.i | 26 + lib/Instances/ResamplingFilters.i | 14 + lib/Instances/ScalarImages.i | 51 + lib/Instances/ScalarImagesFilters.i | 33 + lib/Instances/ThresholdFilters.i | 34 + lib/Instances/Transforms.i | 14 + lib/Instances/VectorImages.i | 49 + lib/Itk2Vtk/itkImageToVTKImageFilter.h | 111 + lib/Itk2Vtk/itkImageToVTKImageFilter.hxx | 141 + lib/Itk2Vtk/itkVTKImageToImageFilter.h | 100 + lib/Itk2Vtk/itkVTKImageToImageFilter.hxx | 107 + .../ActorAxesProperties.cxx | 205 + lib/cpBaseQtApplication/ActorAxesProperties.h | 45 + .../ActorAxesProperties.ui | 157 + .../ActorImageProperties.cxx | 241 + .../ActorImageProperties.h | 48 + .../ActorImageProperties.ui | 215 + .../ActorPolyDataProperties.cxx | 250 + .../ActorPolyDataProperties.h | 49 + .../ActorPolyDataProperties.ui | 233 + lib/cpBaseQtApplication/ActorProperties.cxx | 34 + lib/cpBaseQtApplication/ActorProperties.h | 57 + .../ActorPropertiesQDialog.cxx | 685 + .../ActorPropertiesQDialog.h | 99 + lib/cpBaseQtApplication/Block.cxx | 317 + lib/cpBaseQtApplication/Block.h | 88 + lib/cpBaseQtApplication/Canvas.cxx | 160 + lib/cpBaseQtApplication/Canvas.h | 50 + lib/cpBaseQtApplication/Connection.cxx | 139 + lib/cpBaseQtApplication/Connection.h | 56 + lib/cpBaseQtApplication/Editor.cxx | 623 + lib/cpBaseQtApplication/Editor.h | 148 + lib/cpBaseQtApplication/MainHelper.h | 90 + lib/cpBaseQtApplication/MainWindow.cxx | 551 + lib/cpBaseQtApplication/MainWindow.h | 105 + lib/cpBaseQtApplication/Port.cxx | 305 + lib/cpBaseQtApplication/Port.h | 169 + .../Algorithms/BezierCurveFunction.h | 76 + .../Algorithms/BezierCurveFunction.hxx | 155 + lib/cpExtensions/Algorithms/FluxMedialness.h | 74 + .../Algorithms/FluxMedialness.hxx | 108 + .../Algorithms/GaussianDensityImageFilter.h | 103 + .../Algorithms/GradientImageFunctionBase.h | 68 + .../Algorithms/GradientImageFunctionBase.hxx | 59 + .../Algorithms/GulsunTekMedialness.h | 76 + .../Algorithms/GulsunTekMedialness.hxx | 114 + .../Algorithms/ImageFunctionFilter.h | 68 + .../Algorithms/ImageFunctionFilter.hxx | 67 + .../Algorithms/ImageFunctorFilter.h | 102 + .../Algorithms/InertiaMedialness.h | 215 + .../Algorithms/InertiaTensorFunction.h | 180 + lib/cpExtensions/Algorithms/IsoImageSlicer.h | 184 + .../Algorithms/IsoImageSlicer.hxx | 234 + .../IterativeGaussianModelEstimator.h | 171 + .../IterativeGaussianModelEstimator.hxx | 365 + .../Algorithms/KalmanConstantFilter.cxx | 49 + .../Algorithms/KalmanConstantFilter.h | 56 + lib/cpExtensions/Algorithms/KalmanFilter.cxx | 137 + lib/cpExtensions/Algorithms/KalmanFilter.h | 215 + lib/cpExtensions/Algorithms/KalmanFilter.hxx | 37 + .../Algorithms/KalmanVelocityFilter.cxx | 90 + .../Algorithms/KalmanVelocityFilter.h | 66 + .../Algorithms/LightCompensationFilter.h | 65 + .../Algorithms/LightCompensationFilter.hxx | 96 + lib/cpExtensions/Algorithms/MFluxMedialness.h | 74 + .../Algorithms/MFluxMedialness.hxx | 159 + .../Algorithms/MacheteImageFilter.h | 72 + .../Algorithms/MacheteImageFilter.hxx | 92 + .../MultiScaleGaussianImageFilter.h | 85 + .../MultiScaleGaussianImageFilter.hxx | 226 + .../Algorithms/ParallelImageMean.h | 70 + .../Algorithms/ParallelImageMean.hxx | 65 + .../Algorithms/RGBExtractFunction.h | 54 + .../RGBImageToOtherChannelsFilter.h | 67 + .../RGBImageToOtherChannelsFilter.hxx | 71 + .../Algorithms/RGBToHSVFunction.h | 87 + .../Algorithms/RGBToYPbPrFunction.h | 72 + .../RegionOfInterestImageCalculator.h | 73 + .../RegionOfInterestImageCalculator.hxx | 92 + .../Algorithms/SpatialObjectMaskImageFilter.h | 87 + .../SpatialObjectMaskImageFilter.hxx | 136 + .../Algorithms/UnaryThresholdImageFilter.h | 102 + .../Algorithms/UnaryThresholdImageFilter.hxx | 245 + lib/cpExtensions/CMakeLists.txt | 72 + lib/cpExtensions/Config.h.in | 87 + lib/cpExtensions/DataStructures/Graph.h | 166 + lib/cpExtensions/DataStructures/Graph.hxx | 208 + .../DataStructures/ImageIndexesContainer.h | 66 + .../DataStructures/PolyLineParametricPath.h | 62 + .../Interaction/BaseInteractorStyle.cxx | 568 + .../Interaction/BaseInteractorStyle.h | 226 + .../Interaction/ImageInteractorStyle.cxx | 259 + .../Interaction/ImageInteractorStyle.h | 108 + lib/cpExtensions/Interaction/SeedWidget.cxx | 93 + lib/cpExtensions/Interaction/SeedWidget.h | 54 + .../QT/DicomSeriesSelectorWidget.cxx | 162 + .../QT/DicomSeriesSelectorWidget.h | 55 + .../QT/DicomSeriesSelectorWidget.ui | 89 + lib/cpExtensions/QT/SimpleMPRWidget.cxx | 408 + lib/cpExtensions/QT/SimpleMPRWidget.h | 121 + lib/cpExtensions/QT/SimpleMPRWidget.ui | 94 + lib/cpExtensions/Utility.h | 127 + .../Visualization/ImageBlender.cxx | 239 + lib/cpExtensions/Visualization/ImageBlender.h | 65 + .../ImageIndexesContainerToPolyData.h | 71 + .../ImageIndexesContainerToPolyData.hxx | 188 + .../Visualization/ImageSliceActors.cxx | 658 + .../Visualization/ImageSliceActors.h | 190 + .../PolyLineParametricPathToPolyData.h | 69 + .../PolyLineParametricPathToPolyData.hxx | 213 + .../Visualization/SeedWidgetCorrector.cxx | 79 + .../Visualization/SeedWidgetCorrector.h | 44 + lib/cpPlugins/BaseWidget.cxx | 95 + lib/cpPlugins/BaseWidget.h | 69 + lib/cpPlugins/BoundingBox.cxx | 97 + lib/cpPlugins/BoundingBox.h | 76 + lib/cpPlugins/BoundingBox.hxx | 131 + lib/cpPlugins/CMakeLists.txt | 239 + lib/cpPlugins/Config.h.in | 103 + lib/cpPlugins/DataObject.cxx | 103 + lib/cpPlugins/DataObject.h | 60 + lib/cpPlugins/Image.cxx | 66 + lib/cpPlugins/Image.h | 63 + lib/cpPlugins/Image.hxx | 165 + lib/cpPlugins/ImageIndexesContainer.cxx | 39 + lib/cpPlugins/ImageIndexesContainer.h | 53 + lib/cpPlugins/ImageIndexesContainer.hxx | 44 + lib/cpPlugins/Interface.cxx | 374 + lib/cpPlugins/Interface.h | 112 + .../LoadDynamicLibrariesFunctions.cxx | 53 + lib/cpPlugins/LoadDynamicLibrariesFunctions.h | 22 + lib/cpPlugins/Mesh.cxx | 220 + lib/cpPlugins/Mesh.h | 72 + lib/cpPlugins/Mesh.hxx | 72 + lib/cpPlugins/Object.cxx | 101 + lib/cpPlugins/Object.h | 78 + lib/cpPlugins/Object.hxx | 38 + lib/cpPlugins/OrthoNormalBase.cxx | 73 + lib/cpPlugins/OrthoNormalBase.h | 58 + lib/cpPlugins/OrthoNormalBase.hxx | 43 + lib/cpPlugins/Parameters.cxx | 581 + lib/cpPlugins/Parameters.h | 208 + lib/cpPlugins/ParametersQDialog.cxx | 906 ++ lib/cpPlugins/ParametersQDialog.h | 70 + lib/cpPlugins/Path.cxx | 39 + lib/cpPlugins/Path.h | 53 + lib/cpPlugins/Path.hxx | 44 + lib/cpPlugins/Port.cxx | 135 + lib/cpPlugins/Port.h | 82 + lib/cpPlugins/ProcessObject.cxx | 305 + lib/cpPlugins/ProcessObject.h | 142 + lib/cpPlugins/ProcessObject.hxx | 142 + lib/cpPlugins/Utilities.h | 135 + lib/cpPlugins/Workspace.cxx | 480 + lib/cpPlugins/Workspace.h | 164 + lib/cpPlugins/WorkspaceIO.cxx | 251 + lib/cpPlugins/dirent.h | 848 ++ lib/tinyxml2/OLD_CMakeLists.txt.old | 32 + lib/tinyxml2/readme.md | 324 + lib/tinyxml2/tinyxml2.cpp | 2467 +++ lib/tinyxml2/tinyxml2.h | 2106 +++ plugins/CMakeLists.txt | 27 + plugins/GenericFilters/JoinBoundingBoxes.cxx | 55 + plugins/GenericFilters/JoinBoundingBoxes.h | 42 + plugins/IO/DataReproducer.cxx | 31 + plugins/IO/DataReproducer.h | 42 + plugins/IO/DicomSeriesReader.cxx | 95 + plugins/IO/DicomSeriesReader.h | 43 + plugins/IO/DicomSeriesReaderQDialog.h | 47 + plugins/IO/DicomSeriesReaderQDialog.ui | 81 + plugins/IO/ImageReader.cxx | 336 + plugins/IO/ImageReader.h | 57 + plugins/IO/ImageReaderQDialog.h | 41 + plugins/IO/ImageWriter.cxx | 159 + plugins/IO/ImageWriter.h | 57 + plugins/IO/ImageWriterQDialog.h | 41 + plugins/ImageFilters/AndImageFilter.cxx | 64 + plugins/ImageFilters/AndImageFilter.h | 45 + .../ImageFilters/BinaryContourImageFilter.cxx | 86 + .../ImageFilters/BinaryContourImageFilter.h | 48 + .../BinaryDilateParaImageFilter.cxx | 53 + .../BinaryDilateParaImageFilter.h | 45 + .../BinaryErodeParaImageFilter.cxx | 53 + .../ImageFilters/BinaryErodeParaImageFilter.h | 45 + .../BinaryThresholdImageFilter.cxx | 80 + .../ImageFilters/BinaryThresholdImageFilter.h | 48 + plugins/ImageFilters/CastImageFilter.cxx | 93 + plugins/ImageFilters/CastImageFilter.h | 48 + .../GaussianDensityImageFilter.cxx | 80 + .../ImageFilters/GaussianDensityImageFilter.h | 48 + .../MultiScaleGaussianImageFilter.cxx | 80 + .../MultiScaleGaussianImageFilter.h | 48 + plugins/ImageFilters/OrImageFilter.cxx | 64 + plugins/ImageFilters/OrImageFilter.h | 45 + .../RegionOfInterestImageFilter.cxx | 72 + .../RegionOfInterestImageFilter.h | 45 + plugins/ImageFilters/ResampleImageFilter.cxx | 73 + plugins/ImageFilters/ResampleImageFilter.h | 48 + .../SignedMaurerDistanceMapImageFilter.cxx | 93 + .../SignedMaurerDistanceMapImageFilter.h | 53 + .../UnaryThresholdImageFilter.cxx | 59 + .../ImageFilters/UnaryThresholdImageFilter.h | 45 + plugins/ImageMeshFilters/MarchingCubes.cxx | 64 + plugins/ImageMeshFilters/MarchingCubes.h | 42 + .../TriangleMeshToBinaryImageFilter.cxx | 133 + .../TriangleMeshToBinaryImageFilter.h | 48 + .../MedialnessFilters/GulsunTekMedialness.cxx | 30 + .../MedialnessFilters/GulsunTekMedialness.h | 45 + plugins/MeshFilters/AppendMeshesFilter.cxx | 52 + plugins/MeshFilters/AppendMeshesFilter.h | 42 + plugins/MeshSources/CylinderSource.cxx | 37 + plugins/MeshSources/CylinderSource.h | 42 + plugins/MeshSources/SphereSource.cxx | 38 + plugins/MeshSources/SphereSource.h | 42 + plugins/Widgets/SeedWidget.cxx | 202 + plugins/Widgets/SeedWidget.h | 68 + .../cpPlugins_Install_CMAKE.sh | 194 + .../cpPlugins_Install_ITK.sh | 212 + .../cpPlugins_Install_QT4.sh | 219 + .../cpPlugins_Install_VTK.sh | 252 + third_party_installers/qt-4.8.6.patch | 18 + 290 files changed, 70155 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 COMPILATION create mode 100644 README create mode 100644 appli/CMakeLists.txt create mode 100644 appli/PipelineEditor/CMakeLists.txt create mode 100644 appli/PipelineEditor/PipelineEditorMainWindow.cxx create mode 100644 appli/PipelineEditor/PipelineEditorMainWindow.h create mode 100644 appli/PipelineEditor/PipelineEditorMainWindow.ui create mode 100644 appli/PipelineEditor/main.cxx create mode 100644 appli/bash/CMakeLists.txt create mode 100644 appli/bash/cpPlugins_CreateInstances.cxx create mode 100644 appli/bash/cpPlugins_HostCreator.cxx create mode 100644 appli/examples/CMakeLists.txt create mode 100644 appli/examples/extensions/CMakeLists.txt create mode 100644 appli/examples/extensions/example_extensions_ImageSlice.cxx create mode 100644 appli/examples/extensions/example_extensions_IterativeGaussianModelEstimator.cxx create mode 100644 appli/examples/extensions/example_extensions_KalmanVelocity.cxx create mode 100644 appli/examples/plugins/CMakeLists.txt create mode 100644 appli/examples/plugins/example_plugins_GuessPlugins.cxx create mode 100644 appli/examples/plugins/example_plugins_LoadDirectory.cxx create mode 100644 appli/examples/plugins/example_plugins_LoadFile.cxx create mode 100644 appli/examples/plugins/example_plugins_LoadPlugin.cxx create mode 100644 appli/examples/plugins/example_plugins_ReadImage.cxx create mode 100644 appli/plugins/CMakeLists.txt create mode 100644 appli/plugins/cpPlugins_ExecuteWorkspace.cxx create mode 100644 cmake/CMakeLists.txt create mode 100644 cmake/cpPluginsConfig.cmake.in create mode 100644 cmake/cpPlugins_Functions.cmake create mode 100644 cmake/cpPlugins_KitwareTools.cmake create mode 100644 cmake/cpPlugins_Options.cmake create mode 100644 cmake/cpPlugins_Policies.cmake create mode 100644 cmake/cpPlugins_Qt4Tools.cmake create mode 100644 data/ReadWriteImage.wxml create mode 100644 data/circles.png create mode 100644 data/inertia.lyx create mode 100644 data/line_rad_25.png create mode 100644 data/mesh_00.vtk create mode 100644 data/mesh_01.obj create mode 100644 data/mesh_02.obj create mode 100644 data/mesh_03.vtk create mode 100644 data/mesh_04.vtk create mode 100644 data/mesh_05.obj create mode 100644 data/mesh_06.vtk create mode 100644 data/save_dicomseries_as_singlefile_image.wxml create mode 100644 data/test.png create mode 100644 data/test2.png create mode 100644 data/test3.png create mode 100644 data/workspace_00.xml create mode 100644 doc/uml/cpPlugins_classes.dia create mode 100644 lib/CMakeLists.txt create mode 100644 lib/Instances/BaseImageFilters.i create mode 100644 lib/Instances/BaseImages.i create mode 100644 lib/Instances/BaseImages_extra.cxx create mode 100644 lib/Instances/BaseObjects.i create mode 100644 lib/Instances/BaseObjects_extra.cxx create mode 100644 lib/Instances/BitwiseImageFilters.i create mode 100644 lib/Instances/CMakeLists.txt create mode 100644 lib/Instances/CastImageFilters.i create mode 100644 lib/Instances/ColorImages.i create mode 100644 lib/Instances/DistanceMapFilters.i create mode 100644 lib/Instances/ExtractImageFilters.i create mode 100644 lib/Instances/GaussianImageFilters.i create mode 100644 lib/Instances/ImageMeshFilters.i create mode 100644 lib/Instances/ImageReaders.i create mode 100644 lib/Instances/ImageWriters.i create mode 100644 lib/Instances/MedialnessFilters.i create mode 100644 lib/Instances/Mesh.i create mode 100644 lib/Instances/MorphologicalImageFilters.i create mode 100644 lib/Instances/NeighborhoodIterators.i create mode 100644 lib/Instances/Paths.i create mode 100644 lib/Instances/ResamplingFilters.i create mode 100644 lib/Instances/ScalarImages.i create mode 100644 lib/Instances/ScalarImagesFilters.i create mode 100644 lib/Instances/ThresholdFilters.i create mode 100644 lib/Instances/Transforms.i create mode 100644 lib/Instances/VectorImages.i create mode 100644 lib/Itk2Vtk/itkImageToVTKImageFilter.h create mode 100644 lib/Itk2Vtk/itkImageToVTKImageFilter.hxx create mode 100644 lib/Itk2Vtk/itkVTKImageToImageFilter.h create mode 100644 lib/Itk2Vtk/itkVTKImageToImageFilter.hxx create mode 100644 lib/cpBaseQtApplication/ActorAxesProperties.cxx create mode 100644 lib/cpBaseQtApplication/ActorAxesProperties.h create mode 100644 lib/cpBaseQtApplication/ActorAxesProperties.ui create mode 100644 lib/cpBaseQtApplication/ActorImageProperties.cxx create mode 100644 lib/cpBaseQtApplication/ActorImageProperties.h create mode 100644 lib/cpBaseQtApplication/ActorImageProperties.ui create mode 100644 lib/cpBaseQtApplication/ActorPolyDataProperties.cxx create mode 100644 lib/cpBaseQtApplication/ActorPolyDataProperties.h create mode 100644 lib/cpBaseQtApplication/ActorPolyDataProperties.ui create mode 100644 lib/cpBaseQtApplication/ActorProperties.cxx create mode 100644 lib/cpBaseQtApplication/ActorProperties.h create mode 100644 lib/cpBaseQtApplication/ActorPropertiesQDialog.cxx create mode 100644 lib/cpBaseQtApplication/ActorPropertiesQDialog.h create mode 100644 lib/cpBaseQtApplication/Block.cxx create mode 100644 lib/cpBaseQtApplication/Block.h create mode 100644 lib/cpBaseQtApplication/Canvas.cxx create mode 100644 lib/cpBaseQtApplication/Canvas.h create mode 100644 lib/cpBaseQtApplication/Connection.cxx create mode 100644 lib/cpBaseQtApplication/Connection.h create mode 100644 lib/cpBaseQtApplication/Editor.cxx create mode 100644 lib/cpBaseQtApplication/Editor.h create mode 100644 lib/cpBaseQtApplication/MainHelper.h create mode 100644 lib/cpBaseQtApplication/MainWindow.cxx create mode 100644 lib/cpBaseQtApplication/MainWindow.h create mode 100644 lib/cpBaseQtApplication/Port.cxx create mode 100644 lib/cpBaseQtApplication/Port.h create mode 100644 lib/cpExtensions/Algorithms/BezierCurveFunction.h create mode 100644 lib/cpExtensions/Algorithms/BezierCurveFunction.hxx create mode 100644 lib/cpExtensions/Algorithms/FluxMedialness.h create mode 100644 lib/cpExtensions/Algorithms/FluxMedialness.hxx create mode 100644 lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h create mode 100644 lib/cpExtensions/Algorithms/GradientImageFunctionBase.h create mode 100644 lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx create mode 100644 lib/cpExtensions/Algorithms/GulsunTekMedialness.h create mode 100644 lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx create mode 100644 lib/cpExtensions/Algorithms/ImageFunctionFilter.h create mode 100644 lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/ImageFunctorFilter.h create mode 100644 lib/cpExtensions/Algorithms/InertiaMedialness.h create mode 100644 lib/cpExtensions/Algorithms/InertiaTensorFunction.h create mode 100644 lib/cpExtensions/Algorithms/IsoImageSlicer.h create mode 100644 lib/cpExtensions/Algorithms/IsoImageSlicer.hxx create mode 100644 lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h create mode 100644 lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx create mode 100644 lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx create mode 100644 lib/cpExtensions/Algorithms/KalmanConstantFilter.h create mode 100644 lib/cpExtensions/Algorithms/KalmanFilter.cxx create mode 100644 lib/cpExtensions/Algorithms/KalmanFilter.h create mode 100644 lib/cpExtensions/Algorithms/KalmanFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx create mode 100644 lib/cpExtensions/Algorithms/KalmanVelocityFilter.h create mode 100644 lib/cpExtensions/Algorithms/LightCompensationFilter.h create mode 100644 lib/cpExtensions/Algorithms/LightCompensationFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/MFluxMedialness.h create mode 100644 lib/cpExtensions/Algorithms/MFluxMedialness.hxx create mode 100644 lib/cpExtensions/Algorithms/MacheteImageFilter.h create mode 100644 lib/cpExtensions/Algorithms/MacheteImageFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h create mode 100644 lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/ParallelImageMean.h create mode 100644 lib/cpExtensions/Algorithms/ParallelImageMean.hxx create mode 100644 lib/cpExtensions/Algorithms/RGBExtractFunction.h create mode 100644 lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h create mode 100644 lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/RGBToHSVFunction.h create mode 100644 lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h create mode 100644 lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h create mode 100644 lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx create mode 100644 lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h create mode 100644 lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h create mode 100644 lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx create mode 100644 lib/cpExtensions/CMakeLists.txt create mode 100644 lib/cpExtensions/Config.h.in create mode 100644 lib/cpExtensions/DataStructures/Graph.h create mode 100644 lib/cpExtensions/DataStructures/Graph.hxx create mode 100644 lib/cpExtensions/DataStructures/ImageIndexesContainer.h create mode 100644 lib/cpExtensions/DataStructures/PolyLineParametricPath.h create mode 100644 lib/cpExtensions/Interaction/BaseInteractorStyle.cxx create mode 100644 lib/cpExtensions/Interaction/BaseInteractorStyle.h create mode 100644 lib/cpExtensions/Interaction/ImageInteractorStyle.cxx create mode 100644 lib/cpExtensions/Interaction/ImageInteractorStyle.h create mode 100644 lib/cpExtensions/Interaction/SeedWidget.cxx create mode 100644 lib/cpExtensions/Interaction/SeedWidget.h create mode 100644 lib/cpExtensions/QT/DicomSeriesSelectorWidget.cxx create mode 100644 lib/cpExtensions/QT/DicomSeriesSelectorWidget.h create mode 100644 lib/cpExtensions/QT/DicomSeriesSelectorWidget.ui create mode 100644 lib/cpExtensions/QT/SimpleMPRWidget.cxx create mode 100644 lib/cpExtensions/QT/SimpleMPRWidget.h create mode 100644 lib/cpExtensions/QT/SimpleMPRWidget.ui create mode 100644 lib/cpExtensions/Utility.h create mode 100644 lib/cpExtensions/Visualization/ImageBlender.cxx create mode 100644 lib/cpExtensions/Visualization/ImageBlender.h create mode 100644 lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h create mode 100644 lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx create mode 100644 lib/cpExtensions/Visualization/ImageSliceActors.cxx create mode 100644 lib/cpExtensions/Visualization/ImageSliceActors.h create mode 100644 lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h create mode 100644 lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.hxx create mode 100644 lib/cpExtensions/Visualization/SeedWidgetCorrector.cxx create mode 100644 lib/cpExtensions/Visualization/SeedWidgetCorrector.h create mode 100644 lib/cpPlugins/BaseWidget.cxx create mode 100644 lib/cpPlugins/BaseWidget.h create mode 100644 lib/cpPlugins/BoundingBox.cxx create mode 100644 lib/cpPlugins/BoundingBox.h create mode 100644 lib/cpPlugins/BoundingBox.hxx create mode 100644 lib/cpPlugins/CMakeLists.txt create mode 100644 lib/cpPlugins/Config.h.in create mode 100644 lib/cpPlugins/DataObject.cxx create mode 100644 lib/cpPlugins/DataObject.h create mode 100644 lib/cpPlugins/Image.cxx create mode 100644 lib/cpPlugins/Image.h create mode 100644 lib/cpPlugins/Image.hxx create mode 100644 lib/cpPlugins/ImageIndexesContainer.cxx create mode 100644 lib/cpPlugins/ImageIndexesContainer.h create mode 100644 lib/cpPlugins/ImageIndexesContainer.hxx create mode 100644 lib/cpPlugins/Interface.cxx create mode 100644 lib/cpPlugins/Interface.h create mode 100644 lib/cpPlugins/LoadDynamicLibrariesFunctions.cxx create mode 100644 lib/cpPlugins/LoadDynamicLibrariesFunctions.h create mode 100644 lib/cpPlugins/Mesh.cxx create mode 100644 lib/cpPlugins/Mesh.h create mode 100644 lib/cpPlugins/Mesh.hxx create mode 100644 lib/cpPlugins/Object.cxx create mode 100644 lib/cpPlugins/Object.h create mode 100644 lib/cpPlugins/Object.hxx create mode 100644 lib/cpPlugins/OrthoNormalBase.cxx create mode 100644 lib/cpPlugins/OrthoNormalBase.h create mode 100644 lib/cpPlugins/OrthoNormalBase.hxx create mode 100644 lib/cpPlugins/Parameters.cxx create mode 100644 lib/cpPlugins/Parameters.h create mode 100644 lib/cpPlugins/ParametersQDialog.cxx create mode 100644 lib/cpPlugins/ParametersQDialog.h create mode 100644 lib/cpPlugins/Path.cxx create mode 100644 lib/cpPlugins/Path.h create mode 100644 lib/cpPlugins/Path.hxx create mode 100644 lib/cpPlugins/Port.cxx create mode 100644 lib/cpPlugins/Port.h create mode 100644 lib/cpPlugins/ProcessObject.cxx create mode 100644 lib/cpPlugins/ProcessObject.h create mode 100644 lib/cpPlugins/ProcessObject.hxx create mode 100644 lib/cpPlugins/Utilities.h create mode 100644 lib/cpPlugins/Workspace.cxx create mode 100644 lib/cpPlugins/Workspace.h create mode 100644 lib/cpPlugins/WorkspaceIO.cxx create mode 100644 lib/cpPlugins/dirent.h create mode 100644 lib/tinyxml2/OLD_CMakeLists.txt.old create mode 100644 lib/tinyxml2/readme.md create mode 100644 lib/tinyxml2/tinyxml2.cpp create mode 100644 lib/tinyxml2/tinyxml2.h create mode 100644 plugins/CMakeLists.txt create mode 100644 plugins/GenericFilters/JoinBoundingBoxes.cxx create mode 100644 plugins/GenericFilters/JoinBoundingBoxes.h create mode 100644 plugins/IO/DataReproducer.cxx create mode 100644 plugins/IO/DataReproducer.h create mode 100644 plugins/IO/DicomSeriesReader.cxx create mode 100644 plugins/IO/DicomSeriesReader.h create mode 100644 plugins/IO/DicomSeriesReaderQDialog.h create mode 100644 plugins/IO/DicomSeriesReaderQDialog.ui create mode 100644 plugins/IO/ImageReader.cxx create mode 100644 plugins/IO/ImageReader.h create mode 100644 plugins/IO/ImageReaderQDialog.h create mode 100644 plugins/IO/ImageWriter.cxx create mode 100644 plugins/IO/ImageWriter.h create mode 100644 plugins/IO/ImageWriterQDialog.h create mode 100644 plugins/ImageFilters/AndImageFilter.cxx create mode 100644 plugins/ImageFilters/AndImageFilter.h create mode 100644 plugins/ImageFilters/BinaryContourImageFilter.cxx create mode 100644 plugins/ImageFilters/BinaryContourImageFilter.h create mode 100644 plugins/ImageFilters/BinaryDilateParaImageFilter.cxx create mode 100644 plugins/ImageFilters/BinaryDilateParaImageFilter.h create mode 100644 plugins/ImageFilters/BinaryErodeParaImageFilter.cxx create mode 100644 plugins/ImageFilters/BinaryErodeParaImageFilter.h create mode 100644 plugins/ImageFilters/BinaryThresholdImageFilter.cxx create mode 100644 plugins/ImageFilters/BinaryThresholdImageFilter.h create mode 100644 plugins/ImageFilters/CastImageFilter.cxx create mode 100644 plugins/ImageFilters/CastImageFilter.h create mode 100644 plugins/ImageFilters/GaussianDensityImageFilter.cxx create mode 100644 plugins/ImageFilters/GaussianDensityImageFilter.h create mode 100644 plugins/ImageFilters/MultiScaleGaussianImageFilter.cxx create mode 100644 plugins/ImageFilters/MultiScaleGaussianImageFilter.h create mode 100644 plugins/ImageFilters/OrImageFilter.cxx create mode 100644 plugins/ImageFilters/OrImageFilter.h create mode 100644 plugins/ImageFilters/RegionOfInterestImageFilter.cxx create mode 100644 plugins/ImageFilters/RegionOfInterestImageFilter.h create mode 100644 plugins/ImageFilters/ResampleImageFilter.cxx create mode 100644 plugins/ImageFilters/ResampleImageFilter.h create mode 100644 plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.cxx create mode 100644 plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.h create mode 100644 plugins/ImageFilters/UnaryThresholdImageFilter.cxx create mode 100644 plugins/ImageFilters/UnaryThresholdImageFilter.h create mode 100644 plugins/ImageMeshFilters/MarchingCubes.cxx create mode 100644 plugins/ImageMeshFilters/MarchingCubes.h create mode 100644 plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.cxx create mode 100644 plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.h create mode 100644 plugins/MedialnessFilters/GulsunTekMedialness.cxx create mode 100644 plugins/MedialnessFilters/GulsunTekMedialness.h create mode 100644 plugins/MeshFilters/AppendMeshesFilter.cxx create mode 100644 plugins/MeshFilters/AppendMeshesFilter.h create mode 100644 plugins/MeshSources/CylinderSource.cxx create mode 100644 plugins/MeshSources/CylinderSource.h create mode 100644 plugins/MeshSources/SphereSource.cxx create mode 100644 plugins/MeshSources/SphereSource.h create mode 100644 plugins/Widgets/SeedWidget.cxx create mode 100644 plugins/Widgets/SeedWidget.h create mode 100755 third_party_installers/cpPlugins_Install_CMAKE.sh create mode 100755 third_party_installers/cpPlugins_Install_ITK.sh create mode 100755 third_party_installers/cpPlugins_Install_QT4.sh create mode 100755 third_party_installers/cpPlugins_Install_VTK.sh create mode 100644 third_party_installers/qt-4.8.6.patch diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..72a0e6c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,51 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +INCLUDE(cmake/cpPlugins_Policies.cmake) +INCLUDE(cmake/cpPlugins_Functions.cmake) + +## ================== +## == Project name == +## ================== + +PROJECT(cpPlugins) +SET(prj_MAJ_VER "0") +SET(prj_MIN_VER "1") +SET(prj_REL_VER "0") +SET(prj_VERSION "${prj_MAJ_VER}.${prj_MIN_VER}.${prj_REL_VER}") +SET(prj_SHORT_VERSION "${prj_MAJ_VER}") + +## ========================== +## == Packages and options == +## ========================== + +INCLUDE(cmake/cpPlugins_Options.cmake) +INCLUDE(cmake/cpPlugins_KitwareTools.cmake) + +## ===================== +## == Qt4 is optional == +## ===================== + +OPTION(USE_QT4 "Build Qt4-based code" OFF) +INCLUDE(cmake/cpPlugins_Qt4Tools.cmake) + +## ========================= +## == Include directories == +## ========================= + +INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} + ${PROJECT_SOURCE_DIR}/lib + ${PROJECT_BINARY_DIR}/lib + ${PROJECT_SOURCE_DIR}/lib/Itk2Vtk + ${PROJECT_BINARY_DIR}/lib/Itk2Vtk + ${PROJECT_SOURCE_DIR}/lib/Instances + ${PROJECT_BINARY_DIR}/lib/Instances + ) + +## ============================= +## == Subdirs containing code == +## ============================= + +SUBDIRS(cmake lib appli plugins) + +## eof - $RCSfile$ diff --git a/COMPILATION b/COMPILATION new file mode 100644 index 0000000..f85b498 --- /dev/null +++ b/COMPILATION @@ -0,0 +1,132 @@ +@description + The project uses CMake as compilation helper. It should compile on the three + major box flavors (linux, windows, mac). However, as of december 2014, it + has only been tested on linux Fedora 20 and Ubuntu 14.04. + +@prerequisites + + 0. A decent compiler for your system: + Linux: g++ with c++11 support + Mac: Xcode + Windows: any Visual Studio >= 2010 + + 1. CMake (>=2.8.12.2) + Just use your favorite repository or get the installer from http://www.cmake.org. + + 2. [Optional] Qt (=4.8) + On linux just install the corresponding package. On Mac and Windows, download + the source code and compile it with your favorite compiler. Please be aware that: + - Both release and debug configs are needed. + - Compile Qt with only SHARED support. + - Compile Qt without Webkit support. + + 3. Visualization Toolkit -VTK- (>=6.1.0) + 1. Download VTK source code from http://www.vtk.org, copy the downloaded + zip/tar.gz file to your work directory (say ~/sources), uncompress the + source file and create an empty folder (say ~/sources/vtk-build) + 2. Execute cmake taking care to put two directories: the source dir (where + the VTK source code is after decompression) and the build dir (the new + empty folder you just created). + 3. On linux/mac, it is easier to execute from a command line console: + $ cd ~/sources/vtk-build + *** WARNING: IF YOU INSTALLED QT *** + $ cmake -DCMAKE_CXX_FLAGS:STRING=-std=c++11 \ + -DBUILD_DOCUMENTATION:BOOL=OFF \ + -DBUILD_EXAMPLES:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ + -DBUILD_TESTING:BOOL=OFF \ + -DCMAKE_BUILD_TYPE:STRING=MinSizeRel \ + -DModule_vtkGUISupportQt:BOOL=ON \ + -DModule_vtkGUISupportQtOpenGL:BOOL=ON \ + -DModule_vtkGUISupportQtSQL:BOOL=OFF \ + -DModule_vtkGUISupportQtWebkit:BOOL=OFF \ + -DCMAKE_INSTALL_PREFIX:PATH=~/local \ + ~/source/the_folder_where_vtk_was_decompressed + *** WARNING: IF YOU DIDN'T INSTALLED QT *** + $ cmake -DCMAKE_CXX_FLAGS:STRING=-std=c++11 \ + -DBUILD_DOCUMENTATION:BOOL=OFF \ + -DBUILD_EXAMPLES:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ + -DBUILD_TESTING:BOOL=OFF \ + -DCMAKE_BUILD_TYPE:STRING=MinSizeRel \ + -DModule_vtkGUISupportQt:BOOL=OFF \ + -DModule_vtkGUISupportQtOpenGL:BOOL=OFF \ + -DModule_vtkGUISupportQtSQL:BOOL=OFF \ + -DModule_vtkGUISupportQtWebkit:BOOL=OFF \ + -DCMAKE_INSTALL_PREFIX:PATH=~/local \ + ~/source/the_folder_where_vtk_was_decompressed + $ make + ... WAIT A FEW MINUTES ... + $ make install + 4. On windows, make sure that the following cmake variables are configured as: + BUILD_DOCUMENTATION:BOOL=OFF + BUILD_EXAMPLES:BOOL=OFF + BUILD_SHARED_LIBS:BOOL=ON + BUILD_TESTING:BOOL=OFF + CMAKE_BUILD_TYPE:STRING=MinSizeRel + Module_vtkGUISupportQt:BOOL=[OFF/ON] ** "ON", IF YOU INSTALLED Qt + Module_vtkGUISupportQtOpenGL:BOOL=[OFF/ON] ** "ON", IF YOU INSTALLED Qt + Module_vtkGUISupportQtSQL:BOOL=OFF \ + Module_vtkGUISupportQtWebkit:BOOL=OFF \ + NOTE: Normally, windows compilers already support c++11. + + 4. Insight Toolkit -ITK- (>=4.6.0) + 1. Download ITK source code from http://www.itk.org, copy the downloaded + zip/tar.gz file to your work directory (say ~/sources), uncompress the + source file and create an empty folder (say ~/sources/itk-build) + 2. Execute cmake taking care to put two directories: the source dir (where + the ITK source code is after decompression) and the build dir (the new + empty folder you just created). + 3. On linux/mac, it is easier to execute from a command line console: + $ cd ~/sources/itk-build + $ cmake -DCMAKE_CXX_FLAGS:STRING=-std=c++11 \ + -DBUILD_DOCUMENTATION:BOOL=OFF \ + -DBUILD_EXAMPLES:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ + -DBUILD_TESTING:BOOL=OFF \ + -DCMAKE_BUILD_TYPE:STRING=MinSizeRel \ + -DModule_ITKReview:BOOL=ON \ + -DModule_ITKVtkGlue:BOOL=OFF \ + -DCMAKE_INSTALL_PREFIX:PATH=~/local \ + ~/source/the_folder_where_itk_was_decompressed + $ make + ... WAIT A FEW MINUTES ... + $ make install + 4. On windows, make sure that the following cmake variables are configured as: + BUILD_DOCUMENTATION:BOOL=OFF + BUILD_EXAMPLES:BOOL=OFF + BUILD_SHARED_LIBS:BOOL=ON + BUILD_TESTING:BOOL=OFF + CMAKE_BUILD_TYPE:STRING=MinSizeRel + Module_ITKReview:BOOL=ON + Module_ITKVtkGlue:BOOL=OFF + NOTE: Normally, windows compilers already support c++11. + + 4. WARNING: Notes on compilation on MS-Windows + As the time being (circa dec 2014), I've been using MSVC-2013 (compiler + version 12). As expected, weird behavior is related to this config. Please + take into account the following in order to have a successful compilation: + 4.1 If you want to build the Qt-based code, please be sure that + it was compiled with EXACTLY the same compiler you are using. + 4.2 Since the dll load-unload procedure in MSWin is kind of magic, + VTK and ITK should be compiled as shared libraries. This allows a + correct execution of the SmartPointer's thus preventing anoying crashes. + 4.3 If you found more problems in any MSWin config, please let us know at + florez-l@javeriana.edu.co + +@compilation + The project uses CMake as project manager. You can use the CMake GUI to configure + it on your box. Please take into account the following variables: + USE_QT4:BOOL -> It allows you to compile the Qt support + BUILD_EXAMPLES:BOOL -> Do you want to compile the examples? + BUILD_SHARED_LIBRARIES -> Put this allways "ON". "OFF" is still experimental + CMAKE_BUILD_TYPE -> Compilation type. Possible values: Debug, Release, + MinSizeRel, RelWithDebInfo, None + ITK_DIR -> Where ITK was intalled. If you followed this list, + it should be on: ~/local/lib/cmake/ITK-X.Y (X and Y are + the version numbers) + VTK_DIR -> Where VTK was intalled. If you followed this list, + it should be on: ~/local/lib/cmake/vtk-X.Y (X and Y are + the version numbers) + +## eof - $RCSfile$ diff --git a/README b/README new file mode 100644 index 0000000..46efa01 --- /dev/null +++ b/README @@ -0,0 +1,49 @@ + +@project + cpPlugins: Plugin system to encapsulate pipeline objects (data, filters, + sources and sinks) + +@version + 0.0.1 (2014-12-31) + +@authors + Leonardo FLÓREZ-VALENCIA (florez-l@javeriana.edu.co) + Maciej ORKISZ (maciej.orkisz@creatis.insa-lyon.fr) + José Luis GUZMÁN-RODRÍGUEZ (cycopepe@gmail.com) + + +@description + + +@third_party Pluma + Pluma - Plug-in Management Framework + 1. About + Pluma stands for PLUg-in MAnagement framework, and also for PLUg-in + Minimal Architecture. It's small, cross-platform and simple to use. + Support and more information at http://pluma-framework.sourceforge.net + 2. Licence + Source code is provided under the terms of the zlib/libpng License + (http://www.opensource.org/licenses/zlib-license.php): + Pluma - Plug-in Management Framework + Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com) + + 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. + +@license + + + +## eof - $RCSfile$ diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt new file mode 100644 index 0000000..5600125 --- /dev/null +++ b/appli/CMakeLists.txt @@ -0,0 +1,8 @@ + +## =================== +## == Other subdirs == +## =================== + +SUBDIRS(bash examples plugins PipelineEditor) + +## eof - $RCSfile$ diff --git a/appli/PipelineEditor/CMakeLists.txt b/appli/PipelineEditor/CMakeLists.txt new file mode 100644 index 0000000..2266e04 --- /dev/null +++ b/appli/PipelineEditor/CMakeLists.txt @@ -0,0 +1,9 @@ +IF(Qt4_FOUND) + cpPlugins_BuildAppFromDirectory( + ${CMAKE_CURRENT_SOURCE_DIR} + ${cpBaseQtApplication_LIB} + ) +ENDIF(Qt4_FOUND) + + +## eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditorMainWindow.cxx b/appli/PipelineEditor/PipelineEditorMainWindow.cxx new file mode 100644 index 0000000..20ddc16 --- /dev/null +++ b/appli/PipelineEditor/PipelineEditorMainWindow.cxx @@ -0,0 +1,85 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +#define _QT_CONNECT_ACTION( ACTION ) \ + this->connect( \ + this->m_UI->Action##ACTION, SIGNAL( triggered( ) ), \ + this, SLOT( _Action##ACTION( ) ) \ + ) + +// ------------------------------------------------------------------------- +PipelineEditorMainWindow:: +PipelineEditorMainWindow( + int argc, char* argv[], QApplication* app, QWidget* parent + ) + : Superclass( argc, argv, app, parent ), + m_UI( new Ui::PipelineEditorMainWindow ) +{ + // Basic UI configuration + this->m_UI->setupUi( this ); + this->UpdateEnvironment( ); + this->_Configure( + this->m_UI->Plugins, this->m_UI->MPR, this->m_UI->Canvas->editor( ) + ); + + // Slots <-> signals + _QT_CONNECT_ACTION( Open ); + _QT_CONNECT_ACTION( Save ); + _QT_CONNECT_ACTION( Close ); + _QT_CONNECT_ACTION( LoadPluginFile ); + _QT_CONNECT_ACTION( LoadPluginDirectory ); + _QT_CONNECT_ACTION( ShowPlugins ); +} + +// ------------------------------------------------------------------------- +PipelineEditorMainWindow:: +~PipelineEditorMainWindow( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void PipelineEditorMainWindow:: +_ActionOpen( ) +{ + this->_InteractiveLoadWorkspace( ); +} + +// ------------------------------------------------------------------------- +void PipelineEditorMainWindow:: +_ActionSave( ) +{ + this->_InteractiveSaveWorkspace( ); +} + +// ------------------------------------------------------------------------- +void PipelineEditorMainWindow:: +_ActionClose( ) +{ +} + +// ------------------------------------------------------------------------- +void PipelineEditorMainWindow:: +_ActionLoadPluginFile( ) +{ + this->_InteractiveLoadPlugins( ); +} + +// ------------------------------------------------------------------------- +void PipelineEditorMainWindow:: +_ActionLoadPluginDirectory( ) +{ + this->_InteractiveLoadPluginsFromPath( ); +} + +// ------------------------------------------------------------------------- +void PipelineEditorMainWindow:: +_ActionShowPlugins( ) +{ + this->_ShowPlugins( ); +} + +// eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditorMainWindow.h b/appli/PipelineEditor/PipelineEditorMainWindow.h new file mode 100644 index 0000000..aa88f1e --- /dev/null +++ b/appli/PipelineEditor/PipelineEditorMainWindow.h @@ -0,0 +1,58 @@ +#ifndef __PIPELINEEDITORMAINWINDOW__H__ +#define __PIPELINEEDITORMAINWINDOW__H__ + +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class PipelineEditorMainWindow; +} + +/** + */ +class PipelineEditorMainWindow + : public cpBaseQtApplication::MainWindow +{ + Q_OBJECT; +public: + typedef PipelineEditorMainWindow Self; + typedef cpBaseQtApplication::MainWindow Superclass; + +public: + explicit PipelineEditorMainWindow( + int argc, char* argv[], + QApplication* app, + QWidget* parent = NULL + ); + virtual ~PipelineEditorMainWindow( ); + +protected slots: + void _ActionOpen( ); + void _ActionSave( ); + void _ActionClose( ); + void _ActionLoadPluginFile( ); + void _ActionLoadPluginDirectory( ); + void _ActionShowPlugins( ); + + /* + void _ActionBackgroundMPR( ); + void _ActionBackground3D( ); + void _ShowFilterOutput( + const std::string& filter_name, const std::string& output_name + ); + void _HideFilterOutput( + const std::string& filter_name, const std::string& output_name + ); + void _PropertiesFilterOutput( + const std::string& filter_name, const std::string& output_name + ); + */ + +private: + Ui::PipelineEditorMainWindow* m_UI; +}; + +#endif // __PIPELINEEDITORMAINWINDOW__H__ + +// eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditorMainWindow.ui b/appli/PipelineEditor/PipelineEditorMainWindow.ui new file mode 100644 index 0000000..0da8432 --- /dev/null +++ b/appli/PipelineEditor/PipelineEditorMainWindow.ui @@ -0,0 +1,189 @@ + + + PipelineEditorMainWindow + + + + 0 + 0 + 640 + 480 + + + + MainWindow + + + + + + + Qt::Vertical + + + + + 60 + 60 + + + + + + Qt::Horizontal + + + + + 60 + 60 + + + + true + + + QAbstractItemView::DragOnly + + + true + + + + Loaded plugins + + + + + + + 60 + 60 + + + + + + + + + + + + 0 + 0 + 640 + 22 + + + + + &File + + + + + + + + + + &Plugins + + + + + + + + + + + + + &Open + + + Ctrl+O + + + + + &Save + + + Ctrl+S + + + + + E&xit + + + + + &Close + + + Ctrl+Shift+C + + + + + Load &file + + + Ctrl+Shift+P + + + + + Load &directory + + + Ctrl+Shift+D + + + + + &Show + + + Ctrl+Shift+S + + + + + + cpExtensions::QT::SimpleMPRWidget + QWidget +
cpExtensions/QT/SimpleMPRWidget.h
+ 1 +
+ + cpBaseQtApplication::Canvas + QWidget +
cpBaseQtApplication/Canvas.h
+ 1 +
+
+ + + + ActionExit + triggered() + PipelineEditorMainWindow + close() + + + -1 + -1 + + + 212 + 190 + + + + +
diff --git a/appli/PipelineEditor/main.cxx b/appli/PipelineEditor/main.cxx new file mode 100644 index 0000000..a675420 --- /dev/null +++ b/appli/PipelineEditor/main.cxx @@ -0,0 +1,7 @@ +#include +#include + +cpBaseQtApplication_Main( PipelineEditorMainWindow ); +cpBaseQtApplication_MainComplement; + +// eof - $RCSfile$ diff --git a/appli/bash/CMakeLists.txt b/appli/bash/CMakeLists.txt new file mode 100644 index 0000000..6d2c288 --- /dev/null +++ b/appli/bash/CMakeLists.txt @@ -0,0 +1,27 @@ +## ============================ +## == Configure source files == +## ============================ + +FILE( + GLOB all_SOURCE_CXX_FILES RELATIVE + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx" + ) + +## ========================== +## == Compile source files == +## ========================== + +FOREACH(source ${all_SOURCE_CXX_FILES}) + GET_FILENAME_COMPONENT(name ${source} NAME_WE) + ADD_EXECUTABLE(${name} ${source}) + INSTALL( + TARGETS ${name} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + ) + SET(${name}_APP ${name} CACHE INTERNAL "bash program ${name}") +ENDFOREACH(source) + +## eof - $RCSfile$ diff --git a/appli/bash/cpPlugins_CreateInstances.cxx b/appli/bash/cpPlugins_CreateInstances.cxx new file mode 100644 index 0000000..eb218a3 --- /dev/null +++ b/appli/bash/cpPlugins_CreateInstances.cxx @@ -0,0 +1,286 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +typedef std::vector< std::string > TLines; +typedef std::map< char, TLines > TParsedLines; +typedef std::map< std::string, TLines > TVariables; + +// ------------------------------------------------------------------------- +bool ReadFile( TParsedLines& lines, const std::string& fname ); +void ExpandGroups( TLines& res, const TLines& lines ); +void ExpandDefinitions( + TLines& res, const TLines& lines, const TVariables& vars + ); +void PrintLines( + const std::string& prefix, const std::string& suffix, + const TLines& lines, std::ostream& out + ); + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " input_definitions library_name output_dir" + << std::endl; + return( 1 ); + + } // fi + std::string input_definitions_fname = cpExtensions::CanonicalPath( argv[ 1 ] ); + std::string library_name = argv[ 2 ]; + std::string output_dir = cpExtensions::CanonicalPath( argv[ 3 ] ); + + // Build source files names + std::stringstream str_dir; + str_dir << output_dir; + if( !cpExtensions::IsPathSeparator( output_dir.back( ) ) ) + str_dir << cpExtensions_PATH_SEPARATOR; + std::string header_file_fname = str_dir.str( ); + std::string source_file_fname = header_file_fname; + header_file_fname += library_name + std::string( ".h" ); + source_file_fname += library_name + std::string( ".cxx" ); + + // Read file and simple parse it + TParsedLines lines; + if( !ReadFile( lines, input_definitions_fname ) ) + { + std::cerr + << "Error opening file: \"" + << input_definitions_fname << "\"" + << std::endl; + return( 1 ); + + } // fi + + // Expand definitions + TVariables vars; + for( auto dIt = lines[ 'd' ].begin( ); dIt != lines[ 'd' ].end( ); ++dIt ) + { + TLines tokens; + cpExtensions::TokenizeString( tokens, *dIt, "=;" ); + auto tIt = tokens.begin( ); + auto vName = *tIt; + tIt++; + for( ; tIt != tokens.end( ); ++tIt ) + vars[ vName ].push_back( *tIt ); + + TLines res; + ExpandDefinitions( res, vars[ vName ], vars ); + vars[ vName ] = res; + + } // rof + + // Expand groups + TLines f_includes_groups, includes_groups, templates_groups, classes_groups; + ExpandGroups( f_includes_groups, lines[ 'f' ] ); + ExpandGroups( includes_groups, lines[ 'i' ] ); + ExpandGroups( templates_groups, lines[ 't' ] ); + ExpandGroups( classes_groups, lines[ 'c' ] ); + + // Expand definitions + TLines f_includes_list, includes_list, templates_list, classes_list; + ExpandDefinitions( f_includes_list, f_includes_groups, vars ); + ExpandDefinitions( includes_list, includes_groups, vars ); + ExpandDefinitions( templates_list, templates_groups, vars ); + ExpandDefinitions( classes_list, classes_groups, vars ); + + // Write header file + std::ofstream header_file( header_file_fname.c_str( ) ); + if( !header_file ) + { + std::cerr + << "Error opening \"" << header_file_fname + << "\" for writing." << std::endl; + return( 1 ); + + } // fi + + // Print header + header_file + << "#ifndef __" << library_name << "__H__" << std::endl + << "#define __" << library_name << "__H__" << std::endl<< std::endl + << "#include " << std::endl + << "#include <" << library_name << "_Export.h>" << std::endl << std::endl; + PrintLines( "", "", lines[ 'b' ], header_file ); + header_file << std::endl; + PrintLines( "#include <", ">", f_includes_list, header_file ); + header_file + << "#ifdef " << library_name << "_EXPORTS" << std::endl + << "# define " << library_name << "_PREFIX template class " + << library_name << "_EXPORT" << std::endl + << "#else // " << library_name << "_EXPORTS" << std::endl + << "# define " << library_name + << "_PREFIX extern template class" << std::endl + << "#endif // " + << library_name << "_EXPORTS" << std::endl << std::endl; + PrintLines( "#include <", ">", includes_list, header_file ); + PrintLines( "#include <", ">", templates_list, header_file ); + header_file + << std::endl << "#ifdef " << library_name << "_EXPORTS" << std::endl; + PrintLines( "#include <", "xx>", templates_list, header_file ); + header_file + << "#endif // " << library_name << "_EXPORTS" << std::endl << std::endl; + PrintLines( + library_name + std::string( "_PREFIX " ), ";", classes_list, header_file + ); + header_file + << std::endl << "#endif // __" << library_name << "__H__" << std::endl; + header_file.close( ); + + // Write source file + std::ofstream source_file( source_file_fname ); + if( !source_file ) + { + std::cerr + << "Error opening \"" << header_file_fname << "\" for writing." << std::endl; + return( 1 ); + + } // fi + source_file + << "#include \"" << header_file_fname << "\"" << std::endl; + source_file.close( ); + + return( 0 ); +} + +// ------------------------------------------------------------------------- +bool ReadFile( TParsedLines& lines, const std::string& fname ) +{ + std::string buffer; + if( cpExtensions::ReadFileIntoBuffer( buffer, fname ) ) + { + std::istringstream input_stream( buffer ); + + // Read line by line + std::string line; + while( std::getline( input_stream, line ) ) + { + auto cmd_pos = line.end( ); + auto arg_pos = line.end( ); + auto lIt = line.begin( ); + while( lIt != line.end( ) ) + { + if( !cpExtensions::IsBlank( *lIt ) ) + { + if( cmd_pos == line.end( ) ) + { + cmd_pos = lIt; + ++lIt; + } + else if( arg_pos == line.end( ) ) + { + arg_pos = lIt; + lIt = line.end( ); + + } // fi + } + else + ++lIt; + + } // elihw + char cmd = *cmd_pos; + std::string arg; + arg.resize( line.end( ) - arg_pos ); + std::copy( arg_pos, line.end( ), arg.begin( ) ); + lines[ cmd ].push_back( arg ); + + } // elihw + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void ExpandGroups( TLines& res, const TLines& lines ) +{ + for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt ) + { + auto b_pos = lIt->find( "@{" ); + if( b_pos != std::string::npos ) + { + unsigned int braces_count = 1; + auto e_pos = b_pos; + e_pos += 2; + while( braces_count != 0 && e_pos < lIt->size( ) ) + { + auto v = ( *lIt )[ e_pos ]; + braces_count += ( v == '{' )? 1: ( ( v == '}' )? -1: 0 ); + e_pos++; + + } // elihw + if( braces_count == 0 ) + { + auto replace = lIt->substr( b_pos, e_pos - b_pos ); + auto expansion = replace.substr( 2, replace.size( ) - 3 ); + TLines tokens; + cpExtensions::TokenizeString( tokens, expansion, ";" ); + for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt ) + *tIt = cpExtensions::ReplaceString( *lIt, replace, *tIt ); + ExpandGroups( res, tokens ); + + } // fi + } + else + res.push_back( *lIt ); + + } // rof +} + +// ------------------------------------------------------------------------- +void ExpandDefinitions( + TLines& res, const TLines& lines, const TVariables& vars + ) +{ + std::string seps = " ,;:{}[]()\"$&<>*."; + + for( auto lIt = lines.begin( ); lIt != lines.end( ); ++lIt ) + { + auto b_pos = lIt->find( "#" ); + if( b_pos != std::string::npos ) + { + TLines tokens; + cpExtensions::TokenizeString( tokens, lIt->substr( b_pos ), seps ); + std::string cmd = tokens[ 0 ]; + auto vIt = vars.find( cmd ); + if( vIt != vars.end( ) ) + { + if( vIt->second.size( ) > 0 ) + { + TLines new_res; + for( + auto wIt = vIt->second.begin( ); wIt != vIt->second.end( ); ++wIt + ) + new_res.push_back( cpExtensions::ReplaceString( *lIt, cmd, *wIt ) ); + ExpandDefinitions( res, new_res, vars ); + + } // fi + + } // fi + } + else + res.push_back( + cpExtensions::ReplaceString( + cpExtensions::ReplaceString( *lIt, "{", "" ), "}", "" + ) + ); + + } // rof +} + +// ------------------------------------------------------------------------- +void PrintLines( + const std::string& prefix, const std::string& suffix, + const TLines& lines, std::ostream& out + ) +{ + for( auto i = lines.begin( ); i != lines.end( ); ++i ) + out << prefix << *i << suffix << std::endl; +} + +// eof - $RCSfile$ diff --git a/appli/bash/cpPlugins_HostCreator.cxx b/appli/bash/cpPlugins_HostCreator.cxx new file mode 100644 index 0000000..feee786 --- /dev/null +++ b/appli/bash/cpPlugins_HostCreator.cxx @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +typedef std::map< std::string, std::string > TPair; +typedef std::map< std::string, TPair > TInfo; + +// ------------------------------------------------------------------------- +bool is_valid_class( const std::string& str ) +{ + return( str.find( "cpPlugins_Id_Macro" ) != std::string::npos ); +} + +// ------------------------------------------------------------------------- +void process_header( TInfo& info, const std::string& file_name ) +{ + // Load file into a buffer + std::ifstream file_stream( file_name.c_str( ) ); + if( !file_stream ) + return; + std::string buf; + file_stream.seekg( 0, std::ios::end ); + buf.reserve( ( unsigned int )( file_stream.tellg( ) ) ); + file_stream.seekg( 0, std::ios::beg ); + buf.assign( + ( std::istreambuf_iterator< char >( file_stream ) ), + std::istreambuf_iterator< char >( ) + ); + file_stream.close( ); + + // Replace separators with spaces + std::replace( buf.begin( ), buf.end( ), ',', ' ' ); + std::replace( buf.begin( ), buf.end( ), ';', ' ' ); + std::replace( buf.begin( ), buf.end( ), ':', ' ' ); + std::replace( buf.begin( ), buf.end( ), '(', ' ' ); + std::replace( buf.begin( ), buf.end( ), ')', ' ' ); + std::replace( buf.begin( ), buf.end( ), '{', ' ' ); + std::replace( buf.begin( ), buf.end( ), '}', ' ' ); + + // Tokenize buffer + std::istringstream tokenizer( buf ); + std::vector< std::string > tokens; + std::copy( + std::istream_iterator< std::string >( tokenizer ), + std::istream_iterator< std::string >( ), + std::back_inserter( tokens ) + ); + + // Find pivot + auto p = std::find_if( tokens.begin( ), tokens.end( ), is_valid_class ); + if( p != tokens.end( ) ) + { + // Find class name and category + auto cls_it = p; cls_it++; + auto cat_it = cls_it; cat_it++; + + // Find namespace + typedef std::reverse_iterator< std::vector< std::string >::iterator > _RIt; + _RIt r_end( tokens.begin( ) ); + _RIt r_begin( cls_it ); + auto ns_it = std::find( r_begin, r_end, "namespace" ); ns_it--; + + // Update info + info[ *cat_it ][ *cls_it ] = *ns_it; + + } // fi +} + +// ------------------------------------------------------------------------- +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 ]; + + // 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 + + // Write data + std::ofstream out_stream( argv[ 2 ] ); + + // Write include section + for( int i = 3; i < argc; ++i ) + out_stream << "#include \"" << argv[ i ] << "\"" <second.begin( ); jIt != iIt->second.end( ); ++jIt ) + out_stream + << " classes += std::string( \"" << iIt->first + << ":" << jIt->first << ";\" );" << std::endl; + out_stream + << " return( classes.c_str( ) );" << std::endl + << "}" << std::endl << std::endl; + + // Write creators + for( auto iIt = info.begin( ); iIt != info.end( ); ++iIt ) + { + for( auto jIt = iIt->second.begin( ); jIt != iIt->second.end( ); ++jIt ) + { + out_stream + << "extern \"C\" " << export_prefix << " void* " + << iIt->first << "_" << jIt->first + << "( )" << std::endl << "{" << std::endl + << " static " << jIt->second << "::" << jIt->first << "::Pointer f;" << std::endl + << " f = " << jIt->second << "::" << jIt->first << "::New( );" << std::endl + << " return( &f );" + << std::endl; + out_stream + << "}" << std::endl << std::endl; + + } // rof + + } // rof + out_stream.close( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/CMakeLists.txt b/appli/examples/CMakeLists.txt new file mode 100644 index 0000000..4c13ea5 --- /dev/null +++ b/appli/examples/CMakeLists.txt @@ -0,0 +1,10 @@ +## ============= +## == Options == +## ============= + +OPTION(BUILD_EXAMPLES "Build examples" OFF) +IF(BUILD_EXAMPLES) + SUBDIRS(extensions plugins) +ENDIF(BUILD_EXAMPLES) + +## eof - $RCSfile$ diff --git a/appli/examples/extensions/CMakeLists.txt b/appli/examples/extensions/CMakeLists.txt new file mode 100644 index 0000000..0edb012 --- /dev/null +++ b/appli/examples/extensions/CMakeLists.txt @@ -0,0 +1,21 @@ +## ============================ +## == Configure source files == +## ============================ + +FILE( + GLOB all_SOURCE_CXX_FILES RELATIVE + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx" + ) + +## ========================== +## == Compile source files == +## ========================== + +FOREACH(source ${all_SOURCE_CXX_FILES}) + GET_FILENAME_COMPONENT(name ${source} NAME_WE) + ADD_EXECUTABLE(${name} ${source}) + TARGET_LINK_LIBRARIES(${name} ${cpExtensions_LIB}) +ENDFOREACH(source) + +## eof - $RCSfile$ diff --git a/appli/examples/extensions/example_extensions_ImageSlice.cxx b/appli/examples/extensions/example_extensions_ImageSlice.cxx new file mode 100644 index 0000000..b45588a --- /dev/null +++ b/appli/examples/extensions/example_extensions_ImageSlice.cxx @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include + +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " input_image.png" << std::endl; + return( 1 ); + + } // fi + + // Read a test image + vtkSmartPointer< vtkPNGReader > reader = + vtkSmartPointer< vtkPNGReader >::New( ); + reader->SetFileName( argv[ 1 ] ); + reader->Update( ); + + // Prepate slice objects + vtkSmartPointer< cpExtensions::Visualization::ImageSliceActors > actors = + vtkSmartPointer< cpExtensions::Visualization::ImageSliceActors >::New( ); + actors->SetInputConnection( reader->GetOutputPort( ), 2 ); + + // Prepare scene + vtkSmartPointer< vtkRenderer > ren = + vtkSmartPointer< vtkRenderer >::New( ); + ren->SetBackground( 0, 0, 0 ); + actors->PushInto( ren ); + + vtkSmartPointer< vtkRenderWindow > win = + vtkSmartPointer< vtkRenderWindow >::New( ); + win->AddRenderer( ren ); + win->SetSize( 300, 300 ); + + vtkSmartPointer< vtkRenderWindowInteractor > iren = + vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + iren->SetRenderWindow( win ); + iren->SetInteractorStyle( actors->GetStyle( ) ); + + iren->Initialize( ); + ren->ResetCamera( ); + iren->Start( ); + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/extensions/example_extensions_IterativeGaussianModelEstimator.cxx b/appli/examples/extensions/example_extensions_IterativeGaussianModelEstimator.cxx new file mode 100644 index 0000000..b168dcb --- /dev/null +++ b/appli/examples/extensions/example_extensions_IterativeGaussianModelEstimator.cxx @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 1; +typedef double TScalar; +typedef +cpExtensions::Algorithms:: +IterativeGaussianModelEstimator< TScalar, Dim > TEstimator; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " mean std samples" << std::endl; + return( 1 ); + + } // fi + TScalar mean = std::atof( argv[ 1 ] ); + TScalar var = std::atof( argv[ 2 ] ); + unsigned int samples = std::atoi( argv[ 3 ] ); + var *= var; + + // Prepare estimator + TEstimator::Pointer estimator = TEstimator::New( ); + + // Generate numbers + std::random_device r; + std::seed_seq seed{ r( ), r( ), r( ), r( ), r( ), r( ), r( ), r( ) }; + std::mt19937 e( seed ); + std::normal_distribution< > dist( mean, std::sqrt( var ) ); + double local_mean = double( 0 ); + std::vector< double > data; + for( unsigned int s = 0; s < samples; ++s ) + { + double v = dist( e ); + estimator->AddSample( v ); + local_mean += v; + data.push_back( v ); + + } // rof + local_mean /= double( samples ); + + double local_var = double( 0 ); + for( auto d = data.begin( ); d != data.end( ); ++d ) + local_var += ( *d - local_mean ) * ( *d - local_mean ); + local_var /= double( samples - 1 ); + + // Show results + std::cout + << "Mean: " + << mean << " <-> " + << estimator->GetMean( )[ 0 ] << " <-> " + << local_mean + << std::endl; + std::cout + << "Var: " + << var << " <-> " + << estimator->GetCovariance( )[ 0 ][ 0 ] << " <-> " + << estimator->GetUnbiasedCovariance( )[ 0 ][ 0 ] << " <-> " + << local_var + << std::endl; + + std::cout << "--------------------------------------" << std::endl; + for( unsigned int s = 0; s < 15; ++s ) + { + double v = dist( e ); + double d = std::sqrt( estimator->SquaredMahalanobis( v ) ); + std::cout << "Distante to " << v << " is " << d << std::endl; + + } // rof + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/extensions/example_extensions_KalmanVelocity.cxx b/appli/examples/extensions/example_extensions_KalmanVelocity.cxx new file mode 100644 index 0000000..89dca8a --- /dev/null +++ b/appli/examples/extensions/example_extensions_KalmanVelocity.cxx @@ -0,0 +1,59 @@ +#include + +#include + +// ------------------------------------------------------------------------- +const unsigned int Dim = 1; +typedef double TScalar; + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + // Kalman filters + typedef + cpExtensions::Algorithms::KalmanVelocityFilter< TScalar > + _TKalman; + _TKalman::Pointer kalman01 = _TKalman::New( ); + kalman01->Configure( 1 ); + kalman01->SetTimeOffset( TScalar( 1 ) ); + + _TKalman::TMatrix P0 = kalman01->GetP0( ); + P0.set_identity( ); + P0 *= TScalar( 10 ); + kalman01->SetP0( P0 ); + + _TKalman::TMatrix sigma = kalman01->GetSigma( ); + sigma.set_identity( ); + sigma *= TScalar( 1e-5 ); + kalman01->SetSigma( sigma ); + + _TKalman::TMatrix R = kalman01->GetR( ); + R.set_identity( ); + R *= TScalar( 0.09 ); + kalman01->SetR( R ); + + TScalar read; + std::cin >> read; + + _TKalman::TVector x0 = kalman01->Getx0( ); + x0[ 0 ] = read; + kalman01->Setx0( x0 ); + kalman01->Initialize( ); + + while( !std::cin.eof( ) ) + { + std::cin >> read; + + _TKalman::TVector m = kalman01->Getm( ); + m[ 0 ] = read; + kalman01->Setm( m ); + kalman01->OneStep( ); + + std::cout << m[ 0 ] << " " << kalman01->Getxp( )[ 0 ] << std::endl; + + } // eliwh + + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/plugins/CMakeLists.txt b/appli/examples/plugins/CMakeLists.txt new file mode 100644 index 0000000..5c99f74 --- /dev/null +++ b/appli/examples/plugins/CMakeLists.txt @@ -0,0 +1,21 @@ +## ============================ +## == Configure source files == +## ============================ + +FILE( + GLOB all_SOURCE_CXX_FILES RELATIVE + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx" + ) + +## ========================== +## == Compile source files == +## ========================== + +FOREACH(source ${all_SOURCE_CXX_FILES}) + GET_FILENAME_COMPONENT(name ${source} NAME_WE) + ADD_EXECUTABLE(${name} ${source}) + TARGET_LINK_LIBRARIES(${name} ${cpPlugins_LIB}) +ENDFOREACH(source) + +## eof - $RCSfile$ diff --git a/appli/examples/plugins/example_plugins_GuessPlugins.cxx b/appli/examples/plugins/example_plugins_GuessPlugins.cxx new file mode 100644 index 0000000..16a42e3 --- /dev/null +++ b/appli/examples/plugins/example_plugins_GuessPlugins.cxx @@ -0,0 +1,44 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + // Create interface and load library + cpPlugins::Interface interface; + try + { + interface.LoadEnvironment( ); + interface.GuessPlugins( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Show data + std::cout << "----- PATHS -----" << std::endl; + auto paths = interface.GetPaths( ); + for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt ) + std::cout << *paIt << std::endl; + std::cout << std::endl << "----- PLUGINS -----" << std::endl; + auto plugins = interface.GetPlugins( ); + for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt ) + std::cout << *plIt << std::endl; + std::cout << std::endl << "----- FILTERS -----" << std::endl; + auto categories = interface.GetCategories( ); + for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt ) + { + std::cout << "\t** Category: " << *cIt << " **" << std::endl; + auto filters = interface.GetFilters( *cIt ); + for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt ) + std::cout << "\t\tFilter: " << *fIt << std::endl; + + } // rof + + // Finish + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/plugins/example_plugins_LoadDirectory.cxx b/appli/examples/plugins/example_plugins_LoadDirectory.cxx new file mode 100644 index 0000000..7bd093f --- /dev/null +++ b/appli/examples/plugins/example_plugins_LoadDirectory.cxx @@ -0,0 +1,53 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + // Manage inputs + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " directory" << std::endl; + return( 1 ); + + } // fi + std::string directory = argv[ 1 ]; + + // Create interface and load library + cpPlugins::Interface interface; + try + { + interface.LoadEnvironment( ); + interface.LoadDirectory( directory ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Show data + std::cout << "----- PATHS -----" << std::endl; + auto paths = interface.GetPaths( ); + for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt ) + std::cout << *paIt << std::endl; + std::cout << std::endl << "----- PLUGINS -----" << std::endl; + auto plugins = interface.GetPlugins( ); + for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt ) + std::cout << *plIt << std::endl; + std::cout << std::endl << "----- FILTERS -----" << std::endl; + auto categories = interface.GetCategories( ); + for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt ) + { + std::cout << "\t** Category: " << *cIt << " **" << std::endl; + auto filters = interface.GetFilters( *cIt ); + for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt ) + std::cout << "\t\tFilter: " << *fIt << std::endl; + + } // rof + + // Finish + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/plugins/example_plugins_LoadFile.cxx b/appli/examples/plugins/example_plugins_LoadFile.cxx new file mode 100644 index 0000000..8749aef --- /dev/null +++ b/appli/examples/plugins/example_plugins_LoadFile.cxx @@ -0,0 +1,53 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + // Manage inputs + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " library_file" << std::endl; + return( 1 ); + + } // fi + std::string library_file = argv[ 1 ]; + + // Create interface and load library + cpPlugins::Interface interface; + try + { + interface.LoadEnvironment( ); + interface.LoadFile( library_file ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Show data + std::cout << "----- PATHS -----" << std::endl; + auto paths = interface.GetPaths( ); + for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt ) + std::cout << *paIt << std::endl; + std::cout << std::endl << "----- PLUGINS -----" << std::endl; + auto plugins = interface.GetPlugins( ); + for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt ) + std::cout << *plIt << std::endl; + std::cout << std::endl << "----- FILTERS -----" << std::endl; + auto categories = interface.GetCategories( ); + for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt ) + { + std::cout << "\t** Category: " << *cIt << " **" << std::endl; + auto filters = interface.GetFilters( *cIt ); + for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt ) + std::cout << "\t\tFilter: " << *fIt << std::endl; + + } // rof + + // Finish + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/plugins/example_plugins_LoadPlugin.cxx b/appli/examples/plugins/example_plugins_LoadPlugin.cxx new file mode 100644 index 0000000..8334e2e --- /dev/null +++ b/appli/examples/plugins/example_plugins_LoadPlugin.cxx @@ -0,0 +1,53 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + // Manage inputs + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " plugin" << std::endl; + return( 1 ); + + } // fi + std::string plugin = argv[ 1 ]; + + // Create interface and load library + cpPlugins::Interface interface; + try + { + interface.LoadEnvironment( ); + interface.LoadPlugin( plugin ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Show data + std::cout << "----- PATHS -----" << std::endl; + auto paths = interface.GetPaths( ); + for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt ) + std::cout << *paIt << std::endl; + std::cout << std::endl << "----- PLUGINS -----" << std::endl; + auto plugins = interface.GetPlugins( ); + for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt ) + std::cout << *plIt << std::endl; + std::cout << std::endl << "----- FILTERS -----" << std::endl; + auto categories = interface.GetCategories( ); + for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt ) + { + std::cout << "\t** Category: " << *cIt << " **" << std::endl; + auto filters = interface.GetFilters( *cIt ); + for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt ) + std::cout << "\t\tFilter: " << *fIt << std::endl; + + } // rof + + // Finish + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/plugins/example_plugins_ReadImage.cxx b/appli/examples/plugins/example_plugins_ReadImage.cxx new file mode 100644 index 0000000..43a00a7 --- /dev/null +++ b/appli/examples/plugins/example_plugins_ReadImage.cxx @@ -0,0 +1,64 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + // Manage inputs + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " image_file(s)" << std::endl; + return( 1 ); + + } // fi + + // Create interface and load library + cpPlugins::Interface interface; + try + { + interface.LoadEnvironment( ); + interface.GuessPlugins( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caught: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Create reader + auto reader = interface.CreateProcessObject( "IO", "ImageReader" ); + if( reader.IsNull( ) ) + { + std::cerr + << "Error caugh: Could not create a valid image reader." + << std::endl; + return( 1 ); + + } // fi + + // Configure reader + auto parameters = reader->GetParameters( ); + for( int i = 1; i < argc; ++i ) + parameters->AddToOpenFileNameList( "FileNames", argv[ i ] ); + + // Execute reader + try + { + reader->PrintExecutionOn( ); + reader->Update( ); + } + catch( std::exception& err ) + { + std::cerr << "Error caugth: " << err.what( ) << std::endl; + return( 1 ); + + } // yrt + + // Show simple information + reader->GetOutputData( "Output" )->Print( std::cout ); + + // Finish + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/plugins/CMakeLists.txt b/appli/plugins/CMakeLists.txt new file mode 100644 index 0000000..5c99f74 --- /dev/null +++ b/appli/plugins/CMakeLists.txt @@ -0,0 +1,21 @@ +## ============================ +## == Configure source files == +## ============================ + +FILE( + GLOB all_SOURCE_CXX_FILES RELATIVE + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/*.cxx" + ) + +## ========================== +## == Compile source files == +## ========================== + +FOREACH(source ${all_SOURCE_CXX_FILES}) + GET_FILENAME_COMPONENT(name ${source} NAME_WE) + ADD_EXECUTABLE(${name} ${source}) + TARGET_LINK_LIBRARIES(${name} ${cpPlugins_LIB}) +ENDFOREACH(source) + +## eof - $RCSfile$ diff --git a/appli/plugins/cpPlugins_ExecuteWorkspace.cxx b/appli/plugins/cpPlugins_ExecuteWorkspace.cxx new file mode 100644 index 0000000..e5ee4cb --- /dev/null +++ b/appli/plugins/cpPlugins_ExecuteWorkspace.cxx @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc == 1 ) + { + std::cout << "Usage: " << argv[ 0 ] << " workspace args" << std::endl; + return( 1 ); + + } // fi + std::string ws_file = argv[ 1 ]; + + // Configure a plugin interface and load given workspace + cpPlugins::Interface interface; + cpPlugins::Workspace ws; + ws.SetInterface( &interface ); + std::string err = ws.LoadWorkspace( ws_file ); + if( err != "" ) + { + std::cerr + << "Error loading workspace \"" << ws_file << "\": " + << err << std::endl; + return( 1 ); + + } // fi + + // Read arguments + for( unsigned int i = 2; i < argc; i += 2 ) + { + std::vector< std::string > tokens; + cpPlugins::TokenizeString( tokens, argv[ i ], "@" ); + std::string filter_name = tokens[ 1 ]; + std::string param_name = tokens[ 0 ]; + std::string param_value = argv[ i + 1 ]; + + auto filter = ws.GetFilter( filter_name ); + if( filter != NULL ) + filter->GetParameters( )->SetString( param_name, param_value ); + else + std::cerr + << "Warning: filter \"" << filter_name + << "\" is not defined inside the loaded workspace." << std::endl; + + } // rof + + // Execute workspace + ws.PrintExecutionOn( ); + try + { + ws.Execute( ); + } + catch( itk::ExceptionObject& err1 ) + { + std::cerr << "Error caught: " << err1 << std::endl; + return( 1 ); + } + catch( std::exception& err2 ) + { + std::cerr << "Error caught: " << err2.what( ) << std::endl; + return( 1 ); + } + catch( ... ) + { + std::cerr << "Unknown error caught." << std::endl; + return( 1 ); + + } // yrt + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 0000000..e942ae9 --- /dev/null +++ b/cmake/CMakeLists.txt @@ -0,0 +1,11 @@ +## ===================== +## == Configure files == +## ===================== + +CONFIGURE_FILE( + cpPluginsConfig.cmake.in + ${PROJECT_BINARY_DIR}/cpPluginsConfig.cmake + @ONLY + ) + +## eof - $RCSfile$ diff --git a/cmake/cpPluginsConfig.cmake.in b/cmake/cpPluginsConfig.cmake.in new file mode 100644 index 0000000..42871e9 --- /dev/null +++ b/cmake/cpPluginsConfig.cmake.in @@ -0,0 +1,118 @@ +## ================================= +## == Find installation directory == +## ================================= + +FIND_FILE( + cpPlugins_FUNCTIONS + NAMES cpPlugins_Functions.cmake + HINTS /usr/share/cmake /usr/local/share/cmake + PATHS @CMAKE_INSTALL_PREFIX@/share/cmake @PROJECT_SOURCE_DIR@/cmake + DOC "Where is \"cpPlugins_Functions.cmake\"?" + ) +IF(NOT cpPlugins_FUNCTIONS) + MESSAGE(FATAL_ERROR "Where is \"cpPlugins_Functions.cmake\"?") +ENDIF(NOT cpPlugins_FUNCTIONS) +GET_FILENAME_COMPONENT( + cpPlugins_FUNCTIONS_ABSOLUTE ${cpPlugins_FUNCTIONS} + ABSOLUTE + ) +GET_FILENAME_COMPONENT( + cpPlugins_CMAKE_DIR ${cpPlugins_FUNCTIONS_ABSOLUTE} + DIRECTORY + ) + +## =========================== +## == Include cmake scripts == +## =========================== + +INCLUDE(${cpPlugins_FUNCTIONS}) +INCLUDE(${cpPlugins_CMAKE_DIR}/cpPlugins_Options.cmake) + +SET(ITK_DIR @ITK_DIR@) +SET(VTK_DIR @VTK_DIR@) +INCLUDE(${cpPlugins_CMAKE_DIR}/cpPlugins_KitwareTools.cmake) + +SET(USE_QT4 "@QT4_FOUND@") +IF(USE_QT4 EQUAL "1") + INCLUDE(${cpPlugins_CMAKE_DIR}/cpPlugins_Qt4Tools.cmake) + cpPlugins_FindQt4() + SET(QT_QMAKE_EXECUTABLE @QT_QMAKE_EXECUTABLE@) +ENDIF(USE_QT4 EQUAL "1") + +## ========================= +## == Include directories == +## ========================= + +INCLUDE_DIRECTORIES( + @CMAKE_INSTALL_PREFIX@/include + @CMAKE_INSTALL_PREFIX@/include/cpPlugins/Itk2Vtk + @CMAKE_INSTALL_PREFIX@/include/cpPlugins/Instances + @PROJECT_SOURCE_DIR@ + @PROJECT_BINARY_DIR@ + @PROJECT_SOURCE_DIR@/lib + @PROJECT_BINARY_DIR@/lib + @PROJECT_SOURCE_DIR@/lib/Itk2Vtk + @PROJECT_BINARY_DIR@/lib/Itk2Vtk + @PROJECT_SOURCE_DIR@/lib/Instances + @PROJECT_BINARY_DIR@/lib/Instances + ) + +## ========================= +## == Library directories == +## ========================= + +IF(MSVC) + LINK_DIRECTORIES( + @PROJECT_BINARY_DIR@/$(ConfigurationName) + @CMAKE_INSTALL_PREFIX@/bin + @CMAKE_INSTALL_PREFIX@/lib + ) +ELSE(MSVC) + LINK_DIRECTORIES( + @PROJECT_BINARY_DIR@ + @CMAKE_INSTALL_PREFIX@/bin + @CMAKE_INSTALL_PREFIX@/lib + ) +ENDIF(MSVC) + +## =================== +## == Library names == +## =================== + +SET(cpPlugins_tinyxml2_LIB "@cpPlugins_tinyxml2_LIB@") +SET(cpExtensions_LIB "@cpExtensions_LIB@") +SET(cpPlugins_LIB "@cpPlugins_LIB@") +SET(cpBaseQtApplication_LIB "@cpBaseQtApplication_LIB@") +SET(cpPlugins_Instances "@cpPlugins_Instances@") + +## ====================== +## == Executable names == +## ====================== +SET( + exec_PROGRAMS + cpPlugins_CreateInstances + cpPlugins_HostCreator + ) +FOREACH(prog ${exec_PROGRAMS}) + IF(MSVC) + FIND_PROGRAM( + ${prog}_APP + NAMES ${prog} + HINTS /usr /usr/local + PATHS @CMAKE_INSTALL_PREFIX@/bin @PROJECT_BINARY_DIR@/Debug @PROJECT_BINARY_DIR@/Release @PROJECT_BINARY_DIR@/MinSizeRel @PROJECT_BINARY_DIR@/RelWithDebInfo + PATH_SUFFIXES bin sbin + DOC "Where is ${prog}?" + ) + ELSE(MSVC) + FIND_PROGRAM( + ${prog}_APP + NAMES ${prog} + HINTS /usr /usr/local + PATHS @CMAKE_INSTALL_PREFIX@/bin @PROJECT_BINARY_DIR@ + PATH_SUFFIXES bin sbin + DOC "Where is ${prog}?" + ) + ENDIF(MSVC) +ENDFOREACH(prog) + +## eof - $RCSfile$ diff --git a/cmake/cpPlugins_Functions.cmake b/cmake/cpPlugins_Functions.cmake new file mode 100644 index 0000000..4337bd9 --- /dev/null +++ b/cmake/cpPlugins_Functions.cmake @@ -0,0 +1,342 @@ + +## ================================= +## == Function to build a library == +## ================================= + +FUNCTION(cpPlugins_ManageLibrary library_name type sources headers qt_files version short_version) + +## -- Configure some simple values +SET(_all_sources ${sources}) +SET(_all_headers ${headers}) + +## -- Guess what headers sould be qt-moc'ed +IF(Qt4_FOUND) + FOREACH(_h ${headers}) + FILE(READ ${_h} _txt) + STRING(FIND "${_txt}" "Q_OBJECT" _r) + IF(NOT ${_r} EQUAL -1) + SET(_s) + QT4_WRAP_CPP(_s ${_h}) + SET(_all_sources ${_all_sources} ${_s}) + ENDIF(NOT ${_r} EQUAL -1) + ENDFOREACH(_h) +ENDIF(Qt4_FOUND) + +## -- 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 +IF(Qt4_FOUND) + FOREACH(_ui ${qt_files}) + SET(_base_dir ${CMAKE_CURRENT_SOURCE_DIR}) + STRING(FIND "${_ui}" "${_base_dir}" _pos) + IF(${_pos} EQUAL -1) + SET(_base_dir ${CMAKE_CURRENT_BINARY_DIR}) + STRING(FIND "${_ui}" "${_base_dir}" _pos) + ENDIF(${_pos} EQUAL -1) + SET(_relative_dir) + IF(NOT ${_pos} EQUAL -1) + FILE(TO_CMAKE_PATH ${_base_dir} _base_cmake_dir) + FILE(TO_CMAKE_PATH ${_ui} _ui_dir) + STRING(REPLACE "${_base_cmake_dir}/" "" _relative_dir ${_ui_dir}) + ENDIF(NOT ${_pos} EQUAL -1) + GET_FILENAME_COMPONENT(_ui_name ${_ui} NAME_WE) + STRING(FIND "${_relative_dir}" "/" _pos REVERSE) + STRING(SUBSTRING "${_relative_dir}" 0 ${_pos} _o) + SET(_o_name ${CMAKE_CURRENT_BINARY_DIR}/${_o}/ui_${_ui_name}.h) + ADD_CUSTOM_COMMAND( + OUTPUT ${_o_name} + COMMAND Qt4::uic + ARGS -o ${_o_name} ${_ui} + MAIN_DEPENDENCY ${_ui} VERBATIM + ) + SET(_all_sources ${_all_sources} ${_o_name}) + ENDFOREACH(_ui) +ENDIF(Qt4_FOUND) + +## -- Ok, compile library +IF(_all_sources) + + ## -- Try to guess the binary directory + SET(_relative_dir) + FOREACH(_s ${_all_sources}) + GET_FILENAME_COMPONENT(_d ${_s} DIRECTORY) + SET(_base_dir ${CMAKE_CURRENT_SOURCE_DIR}) + STRING(FIND "${_d}" "${_base_dir}" _pos) + IF(${_pos} EQUAL -1) + SET(_base_dir ${CMAKE_CURRENT_BINARY_DIR}) + STRING(FIND "${_d}" "${_base_dir}" _pos) + ENDIF(${_pos} EQUAL -1) + IF(NOT ${_pos} EQUAL -1) + FILE(TO_CMAKE_PATH ${_base_dir} _base_cmake_dir) + FILE(TO_CMAKE_PATH ${_d} _d_dir) + STRING(REPLACE "${_base_cmake_dir}/" "" _almost_relative_dir ${_d_dir}) + STRING(FIND "${_almost_relative_dir}" "/" _pos) + IF(NOT ${_pos} EQUAL -1) + STRING(SUBSTRING ${_almost_relative_dir} 0 ${_pos} _relative_dir) + ELSE(NOT ${_pos} EQUAL -1) + SET(_relative_dir ${_almost_relative_dir}) + ENDIF(NOT ${_pos} EQUAL -1) + BREAK() + ENDIF(NOT ${_pos} EQUAL -1) + ENDFOREACH(_s) + SET(_cur_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${_relative_dir}") + + ADD_LIBRARY(${library_name} SHARED ${_all_sources}) + SET_TARGET_PROPERTIES( + ${library_name} PROPERTIES + VERSION "${version}" + SOVERSION "${short_version}" + ) + GENERATE_EXPORT_HEADER( + ${library_name} + BASE_NAME ${library_name} + EXPORT_MACRO_NAME ${library_name}_EXPORT + EXPORT_FILE_NAME ${_cur_binary_dir}/${library_name}_Export.h + STATIC_DEFINE ${library_name}_BUILT_AS_STATIC + ) + TARGET_LINK_LIBRARIES(${library_name} ${ARGN}) + SET(${library_name}_LIB ${library_name} CACHE INTERNAL "Library ${name}") +ENDIF(_all_sources) + +ENDFUNCTION() + +## ================================================== +## == Function to build a library from a directory == +## ================================================== + +FUNCTION(cpPlugins_CreateLibraryFromDirectory library_name type source_dir binary_dir version short_version) + +## -- Some useful variables +SET(_all_sources_extensions c cpp cxx) +SET(_all_headers_extensions h hpp hxx) +SET(_all_qt_ui_extensions ui) +SET(_all_dirs ${source_dir} ${binary_dir}) +SET(_all_sources) +SET(_all_headers) +SET(_all_qt_ui) + +## -- Configure some files +FILE(GLOB_RECURSE _all_configs "${source_dir}/*.in") +FOREACH(_c ${_all_configs}) + SET(_base_dir ${CMAKE_CURRENT_SOURCE_DIR}) + STRING(FIND "${_c}" "${_base_dir}" _pos) + IF(${_pos} EQUAL -1) + SET(_base_dir ${CMAKE_CURRENT_BINARY_DIR}) + STRING(FIND "${_c}" "${_base_dir}" _pos) + ENDIF(${_pos} EQUAL -1) + SET(_relative_dir) + IF(NOT ${_pos} EQUAL -1) + FILE(TO_CMAKE_PATH ${_base_dir} _base_cmake_dir) + FILE(TO_CMAKE_PATH ${_c} _c_dir) + STRING(REPLACE "${_base_cmake_dir}/" "" _almost_relative_dir ${_c_dir}) + STRING(FIND "${_almost_relative_dir}" "/" _pos) + SET(_relative_dir ${_almost_relative_dir}) + IF(NOT ${_pos} EQUAL -1) + STRING(SUBSTRING ${_almost_relative_dir} 0 ${_pos} _relative_dir) + ENDIF(NOT ${_pos} EQUAL -1) + ENDIF(NOT ${_pos} EQUAL -1) + GET_FILENAME_COMPONENT(_c_name ${_c} NAME) + STRING(REGEX REPLACE ".in" "" _o_name ${_c_name}) + CONFIGURE_FILE( + ${_c} ${CMAKE_CURRENT_BINARY_DIR}/${_relative_dir}/${_o_name} @ONLY + ) + SET(_all_headers ${_all_headers} ${CMAKE_CURRENT_BINARY_DIR}/${_relative_dir}/${_o_name}) +ENDFOREACH(_c) + +## -- Glob source code +FOREACH(_d ${_all_dirs}) + FOREACH(_e ${_all_sources_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*.${_e}") + SET(_all_sources ${_all_sources} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_all_headers_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*.${_e}") + SET(_all_headers ${_all_headers} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_all_qt_ui_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*.${_e}") + SET(_all_qt_ui ${_all_qt_ui} ${_f}) + ENDFOREACH(_e) +ENDFOREACH(_d) + +## -- Create library +cpPlugins_ManageLibrary( + ${library_name} ${type} + "${_all_sources}" "${_all_headers}" "${_all_qt_ui}" + "${version}" "${short_version}" + ${ARGN} + ) + +ENDFUNCTION() + +## ================================ +## == Function to wrap instances == +## ================================ + +FUNCTION(cpPlugins_WrapInstances def_file prefix version short_version) + +## -- Configure some simple values +SET(_def_canonical_file "${CMAKE_CURRENT_SOURCE_DIR}/${def_file}.i") +SET(_header_file "${CMAKE_CURRENT_BINARY_DIR}/${prefix}${def_file}.h") +SET(_code_file "${CMAKE_CURRENT_BINARY_DIR}/${prefix}${def_file}.cxx") +SET(_extra_code_file "${CMAKE_CURRENT_SOURCE_DIR}/${def_file}_extra.cxx") +SET(_library_name "${prefix}${def_file}") + +## -- Add extra code, if any +SET(_all_code_files ${_code_file}) +IF(EXISTS ${_extra_code_file}) + SET(_all_code_files ${_all_code_files} ${_extra_code_file}) +ENDIF(EXISTS ${_extra_code_file}) + +## -- Command to write source code +ADD_CUSTOM_COMMAND( + OUTPUT ${_header_file} ${_code_file} + DEPENDS ${cpPlugins_CreateInstances_APP} ${_def_canonical_file} + COMMAND ${cpPlugins_CreateInstances_APP} ${_def_canonical_file} ${_library_name} ${CMAKE_CURRENT_BINARY_DIR} + ) + +## -- Create library +cpPlugins_ManageLibrary( + ${_library_name} SHARED + "${_all_code_files}" "" "" + "${version}" "${short_version}" + ${ARGN} + ) + +ENDFUNCTION() + +## ==================================== +## == Function to wrap plugins hosts == +## ==================================== + +FUNCTION(cpPlugins_WrapPlugins source_dir version short_version prefix) + +## -- Some configuration values +SET(_source_dir ${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}) +SET(_binary_dir ${CMAKE_CURRENT_BINARY_DIR}/${source_dir}) +SET(_lib_name ${prefix}${source_dir}) + +## -- Get source code +FILE(GLOB_RECURSE _hdr_h "${_source_dir}/*.h") +FILE(GLOB_RECURSE _hdr_hxx "${_source_dir}/*.hxx") +FILE(GLOB_RECURSE _hdr_hpp "${_source_dir}/*.hpp") +FILE(GLOB_RECURSE _src_c "${_source_dir}/*.c") +FILE(GLOB_RECURSE _src_cxx "${_source_dir}/*.cxx") +FILE(GLOB_RECURSE _src_cpp "${_source_dir}/*.cpp") +FILE(GLOB_RECURSE _qt_ui "${_source_dir}/*.ui") + +## -- Identify sources to wrap +SET(_hdr_to_wrap) +FOREACH(_h ${_hdr_h}) + FILE(READ ${_h} _txt) + STRING(FIND "${_txt}" "cpPluginsObject;" _res) + IF(NOT ${_res} EQUAL -1) + LIST(APPEND _hdr_to_wrap ${_h}) + ENDIF(NOT ${_res} EQUAL -1) +ENDFOREACH(_h) + +## -- Integrate all source files +SET(_all_src ${_src_c} ${_src_cpp} ${_src_cxx}) +SET(_all_hdr ${_hdr_h} ${_hdr_hpp} ${_hdr_hxx}) + +## -- Wrap plugins +IF(_hdr_to_wrap) + SET(_host ${_binary_dir}/${_lib_name}_host.cxx) + ADD_CUSTOM_COMMAND( + OUTPUT ${_host} + DEPENDS ${cpPlugins_HostCreator_APP} ${_hdr_to_wrap} + COMMAND ${cpPlugins_HostCreator_APP} ${_lib_name} ${_host} ${_hdr_to_wrap} + ) + SET(_all_src ${_all_src} ${_host}) +ENDIF(_hdr_to_wrap) + +## -- Ok, build library +IF(_all_src) + cpPlugins_ManageLibrary( + ${_lib_name} SHARED + "${_all_src}" "${_all_hdr}" "${_qt_ui}" + "${version}" "${short_version}" + ${ARGN} + ) +ELSE(_all_src) + MESSAGE(FATAL_ERROR "No source code found to build \"${_lib_name}\"") +ENDIF(_all_src) + +ENDFUNCTION() + +## ====================================== +## == Function to build an application == +## ====================================== + +FUNCTION(cpPlugins_BuildAppFromDirectory directory) + +## -- Some configuration values +FILE(TO_CMAKE_PATH ${directory} _src_dir) +STRING(REPLACE "${PROJECT_SOURCE_DIR}/" "" _bin_dir ${_src_dir}) +SET(_bin_dir "${PROJECT_BINARY_DIR}/${_bin_dir}") +GET_FILENAME_COMPONENT(_app_name ${_src_dir} NAME) +SET(_all_sources_extensions c cpp cxx) +SET(_all_headers_extensions h hpp hxx) +SET(_all_qt_ui_extensions ui) +SET(_all_dirs ${_src_dir} ${_bin_dir}) +SET(_all_sources) +SET(_all_headers) +SET(_all_qt_ui) + +## -- Compilation option +OPTION(BUILD_${_app_name} "Build \"${_app_name}\" application" OFF) + +## -- Glob source code +FOREACH(_d ${_all_dirs}) + FOREACH(_e ${_all_sources_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*.${_e}") + SET(_all_sources ${_all_sources} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_all_headers_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*.${_e}") + SET(_all_headers ${_all_headers} ${_f}) + ENDFOREACH(_e) + FOREACH(_e ${_all_qt_ui_extensions}) + FILE(GLOB_RECURSE _f "${_d}/*.${_e}") + SET(_all_qt_ui ${_all_qt_ui} ${_f}) + ENDFOREACH(_e) +ENDFOREACH(_d) + +## -- Guess what headers sould be qt-moc'ed +FOREACH(_h ${_all_headers}) + FILE(READ ${_h} _txt) + STRING(FIND "${_txt}" "Q_OBJECT" _r) + IF(NOT ${_r} EQUAL -1) + SET(_s) + QT4_WRAP_CPP(_s ${_h}) + SET(_all_sources ${_all_sources} ${_s}) + ENDIF(NOT ${_r} EQUAL -1) +ENDFOREACH(_h) + +## -- 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 +FOREACH(_ui ${_all_qt_ui}) + GET_FILENAME_COMPONENT(_r_ui ${_ui} NAME_WE) + SET(_o_ui ${_bin_dir}/ui_${_r_ui}.h) + ADD_CUSTOM_COMMAND( + OUTPUT ${_o_ui} + COMMAND Qt4::uic + ARGS -o ${_o_ui} ${_ui} + MAIN_DEPENDENCY ${_ui} VERBATIM + ) + SET(_all_sources ${_all_sources} ${_o_ui}) + SET(_all_headers ${_all_headers} ${_o_ui}) +ENDFOREACH(_ui) + +## -- Ok, compile application +IF(_all_sources) + ADD_EXECUTABLE(${_app_name} ${_all_sources}) + TARGET_LINK_LIBRARIES(${_app_name} ${ARGN}) +ELSE(_all_sources) + MESSAGE(FATAL_ERROR "No source code found to build \"${_app_name}\"") +ENDIF(_all_sources) + +ENDFUNCTION() + +## eof - $RCSfile$ diff --git a/cmake/cpPlugins_KitwareTools.cmake b/cmake/cpPlugins_KitwareTools.cmake new file mode 100644 index 0000000..b4493d2 --- /dev/null +++ b/cmake/cpPlugins_KitwareTools.cmake @@ -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/cpPlugins_Options.cmake b/cmake/cpPlugins_Options.cmake new file mode 100644 index 0000000..f399be9 --- /dev/null +++ b/cmake/cpPlugins_Options.cmake @@ -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/cpPlugins_Policies.cmake b/cmake/cpPlugins_Policies.cmake new file mode 100644 index 0000000..c7c8bad --- /dev/null +++ b/cmake/cpPlugins_Policies.cmake @@ -0,0 +1,23 @@ + +## ========================== +## == Some useful policies == +## ========================== + +SET( + _policies + CMP0015 + CMP0020 + CMP0042 + ) + +## ============== +## == Use them == +## ============== + +FOREACH(_p ${_policies}) + IF(POLICY ${_p}) + CMAKE_POLICY(SET ${_p} NEW) + ENDIF(POLICY ${_p}) +ENDFOREACH(_p) + +## eof - $RCSfile$ diff --git a/cmake/cpPlugins_Qt4Tools.cmake b/cmake/cpPlugins_Qt4Tools.cmake new file mode 100644 index 0000000..80a2ef7 --- /dev/null +++ b/cmake/cpPlugins_Qt4Tools.cmake @@ -0,0 +1,44 @@ +## ========================== +## == Function to find Qt4 == +## ========================== + +FUNCTION(cpPlugins_FindQt4) +FIND_PACKAGE(Qt4 REQUIRED) +INCLUDE(${QT_USE_FILE}) +SET( + _required_vtk_modules + vtkGUISupportQt + vtkGUISupportQtOpenGL + ) +FOREACH(_m ${_required_vtk_modules}) + IF(NOT ${_m}_LOADED) + MESSAGE(FATAL_ERROR "${_m} module is required but not available.") + BREAK() + ENDIF(NOT ${_m}_LOADED) +ENDFOREACH(_m) +ENDFUNCTION() + +## ================================================== +## == Find Qt4 and check if it was well configured == +## ================================================== + +SET(QT4_FOUND "0") +IF(USE_QT4) + cpPlugins_FindQt4() +# FIND_PACKAGE(Qt4 REQUIRED) +# INCLUDE(${QT_USE_FILE}) +# SET( +# _required_vtk_modules +# vtkGUISupportQt +# vtkGUISupportQtOpenGL +# ) +# FOREACH(_m ${_required_vtk_modules}) +# IF(NOT ${_m}_LOADED) +# MESSAGE(FATAL_ERROR "${_m} module is required but not available.") +# BREAK() +# ENDIF(NOT ${_m}_LOADED) +# ENDFOREACH(_m) + SET(QT4_FOUND "1") +ENDIF(USE_QT4) + +## eof - $RCSfile$ diff --git a/data/ReadWriteImage.wxml b/data/ReadWriteImage.wxml new file mode 100644 index 0000000..5d597c5 --- /dev/null +++ b/data/ReadWriteImage.wxml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/data/circles.png b/data/circles.png new file mode 100644 index 0000000000000000000000000000000000000000..8788dc6bda78bb2502a2af9eccbb95a66cf89564 GIT binary patch literal 4877 zcmds5dpy)x8$UB>7?-rUrL-zhY>^@&hNSm7GefG+`~JP3_YdWJp3C{3^Lx(sIY+GB>J{p0 zx@rg^b!)5T_6RA_@sA1-M%HT_F@yh9{jHn>5u#|~9|AgYQX2-9gRECsDmRgJsN{)@ z&pu3np((ueoFEIo?b|(kg8(9AvBP6akjGYf2rtN+zQTHy-Bv>nWrQ^LTQ6U>e%GUp zCr_?CDxbh#YxVqtYx0fbsZ-O&4=?K!WL)c9Q&+@mtNzKax?`Ly)Bou|*=?N~Tl;n` zp$%7d4%Z;^wJ5gR2m8ftf%?L|YdgHU(vlMRLbfr0re-+HR0gW|`~1Tm?}pLfuX~wp==G;1)BI`}m!IF%aA6m)OgX4rT47 z#W85e$8#SUd^v8vya3;8*!S^qE&-{q5WnG@!QTT-rJD>_s}i_Mnk@iU4$<^%gmwfr^u+cQJ-2K*Mn$G`i-@oegoqSa8$sqkq9L}!aO3c-H{Q}* z-@*$7)M)(Qyy}NF{eI$XHfg+zkbbh944xWKq)2;aX1L!?Ns8`fr}z*PB-R}z*K#U& zwd(0Rr2};2!yP5pd^L8RB&BB=s;?kX5WU_n38754cgst878=7kk_SQEQO$Z3{|igY z-}G&o#zA&neZwC=rd6CM4c5>3bM{S}P%}bi;Y+EGel^6$HC3m0CbVu?v$=ONXR7Eh za+s%U_L6Apeu0TL#_RW8diyO4c?T)Ise9;N&bf5YWdge(wRCo&`0Xk?C)79TX3yl7 z7%HL*U0wEVd*YvenUI|#y;faKx+CljQ{uN(-Z#kaOg$hZX2(h&R^KMwsqOs{hG*3o zoDZO+XQJ0r_I~U!D!Q^LtN`|xH|b+Ffj-dKu2CXva883L*LsTN!%o#I&e^1Lmg{u1 zAoe@SZygZ$bjdVMD{ZA@tss}kznaW_cTp#pjFgUZ)qm1`(@sVamZ=p-9buo_y&fE| zt#yFkjtMfMwk>~?qx$t$2kSC25dHo2P7NfUWZjt9Ci*bGalfJpjI~I7USYIwCVUTm z+m2vW#7&R2V6|N8!8Nt~)+Jkn0taT-J-~HCeUfEJKr83(itz|F$VP0~KKRI6x3hx3 zMxId~f?N#_VskvLu~(!5uH?O(`Hz*H{M-UtgjGW{m{9OOQHex5lOFwHh&LM!#SWVt z1R{mLXYI>bfYNPz08t$b!snOLpv8uMhOUs2?{oHzCixImN%^AOePzX|BOH|d4!E(&O-xO14&J}`6Q!L-C8>R zN*14o3cJRG@bvx>XN!upT>}ylim0%j^UN9!CK^$;uXzd7E;a06vxfL#d{%z@ge@_^ z2UD<;V6p72jI~9rb42M9(^1RuDw$5qIrS;}P=b+F{bXPqzf(snDF2YQ0; zhJ0s8Ak7t}4_^moJ=tk!ipwWaOQms!iw`hhtMKk{jaEd0^L&OOA+%Z=cj!G>3cc`I z2~!4!N%2{21yPVwPnI)JAKZ$iah(M*3>s^WLQZe!bVvfKl%KsgMit2C*_BW7kMGu6 z(yw8`k|wF*4RJYOiUF;Rw-}Uy&}LyC496E#0PHCZ{6R;TL+_g zk1Mf)4to|G@H^tOxM8kyN{9;eg^z+x1lUj5xEoQf`_B5dIDP4;F8^TY(;Q0e>wsSJ z5@&#-ko6eHlShgdP2?6GQ7?1nnBZoFv*2#QoKU_cN;&(f^xKv>Ea4X|#sB23iO)3G zI)2=T{r5`SX?{(UVdoPVZ-1T~)q?36=+!!IF#X4XE0GnI3ZUBc7_`jIzBD{5uX zGdhem*q)pyxrtM!zge`2xS)bc@hx-8F2NNxSOyj5r|ot(Z1Nn@J_E%Uq0c|-A{DGN zAM|BFiL1-n%;SkkNaPh`dFw;5R84lPh!H6TsL~@Dv_IxeY+*{vW%;I+81QFAbAlc& zjL!n)Ddj}GL1tj1eET# zb`w#%n0k=epT1jY}ammy-0&XZMk_m_wC}f$r%QDI- zIO#DWUVti>X2H7hnlvVXH|xF@sIGfjCKMLVCI@iZbSc3g!8KS{<$y@3;hbmUoiKL+ z)%`R9sICdET}@6`0YLV1?3|#$5sJ5@0tz;sjLV}0 z*wDX62^@B|k^x&x00UTIh4}^E}0Z+$(Amoy~n%{aO=lK05H5*hi0ZUI>o$nLghO3`G<8;wxqkowDP@ z;JV{saix;GePah-Ea`J^$+Ak1YZkCQ$VHF%qRdrRiolNEQX}osW)V$a& zkx0B#m6p?0nnNcVl&<*)w z^RYMjqtLza8^IjE3S^gfIiP3b2B>&F_@}$Vg^A7T;ZJY5w2kF#F%t5bmmKgVLs|?F zdX+Oh2j+_|X75wSG~_eeL+?lRw~S?dX;|ItYPUmWhEEJ|l36b9z|V)U>ZbO4x~_Gu zHPIaOJ-$j)!-|_)&+57cJKuvL6&7y#XS8JvD{pX$>95@mw-UF{Pcy|2sT1UN#gWjWSE=)|wAX@ic<6#+rH~ap}?k)AGQ?#ReoU zOLq45ygz#SPifp=QN9q##*v_v^t^qo)2fu6H@|}SiFPTRTPQ5_w_`_5$pHPdpa9+{ z(VucIngclp<3emy!~x)K&g;LQ=@a$Nii8BkUA8l(`c%}D`iYfei3eg)8`Y~Mt$9m3qn`!w**8{Q()}pGd zpR2hdC5|0w0p$C;PhU&AfypK;M$^A|MEP&Ja4u|VYt>*}f8=7+`jz#X@?Nl>d)}!U zGG=qMmdpvTDSx{m#8gE*V{~^<9GJFRb+=1fl`=saOQ?Kz`x;7qU{pJFhEn-Ca^>!z zgwL~JfpDXW(H9qU@4uUmWxpTX2^mMeG}Hsb5$YlIQ$0Y{FdU(3U}&UjR+*k-IA(d^ zq4ly7$r}tay~uD(`Vofs;#$xw6c-??(Bh^JB|SHX&6P0q-|`BrZt61DbF16*Ck&~u zuq2(CDXY+s;q7KO7>=oyKBHMk0<3)E2{JkTmXJ@1<~X?&j0VEX3WN=3$;gDY%fLG+ z69k|8f{-;n=dGb*3lmNzPD0PFfwP5yy%Y3KET1SMO8%BI5eVT0l>zdpV1$7zak9bX zk;Egj+y;GvKLlX?rgE^@0RY7WpbH`iq9F%!Z8rco3JM6tCkOT$gqVPQPVaSc^w}FO vqtSjnkn0tsr=kEItes?r- literal 0 HcmV?d00001 diff --git a/data/inertia.lyx b/data/inertia.lyx new file mode 100644 index 0000000..51740ff --- /dev/null +++ b/data/inertia.lyx @@ -0,0 +1,454 @@ +#LyX 2.1 created this file. For more info see http://www.lyx.org/ +\lyxformat 474 +\begin_document +\begin_header +\textclass article +\use_default_options true +\maintain_unincluded_children false +\language english +\language_package default +\inputencoding auto +\fontencoding global +\font_roman default +\font_sans default +\font_typewriter default +\font_math auto +\font_default_family default +\use_non_tex_fonts false +\font_sc false +\font_osf false +\font_sf_scale 100 +\font_tt_scale 100 +\graphics default +\default_output_format default +\output_sync 0 +\bibtex_command default +\index_command default +\paperfontsize default +\use_hyperref false +\papersize default +\use_geometry false +\use_package amsmath 1 +\use_package amssymb 1 +\use_package cancel 1 +\use_package esint 1 +\use_package mathdots 1 +\use_package mathtools 1 +\use_package mhchem 1 +\use_package stackrel 1 +\use_package stmaryrd 1 +\use_package undertilde 1 +\cite_engine basic +\cite_engine_type default +\biblio_style plain +\use_bibtopic false +\use_indices false +\paperorientation portrait +\suppress_date false +\justification true +\use_refstyle 1 +\index Index +\shortcut idx +\color #008000 +\end_index +\secnumdepth 3 +\tocdepth 3 +\paragraph_separation indent +\paragraph_indentation default +\quotes_language english +\papercolumns 1 +\papersides 1 +\paperpagestyle default +\tracking_changes false +\output_changes false +\html_math_output 0 +\html_css_as_file 0 +\html_be_strict false +\end_header + +\begin_body + +\begin_layout Standard +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left[\begin{array}{ccc} +\iota_{00} & \iota_{01} & \iota_{02}\\ +\iota_{10} & \iota_{11} & \iota_{12}\\ +\iota_{20} & \iota_{21} & \iota_{22} +\end{array}\right] +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left[\begin{array}{ccc} +{\displaystyle \sum_{i=1}^{n}m_{i}\left(x_{i1}^{2}+x_{i2}^{2}\right)} & -{\displaystyle \sum_{i=1}^{n}m_{i}x_{i0}x_{i1}} & -{\displaystyle \sum_{i=1}^{n}m_{i}x_{i0}x_{i2}}\\ +-{\displaystyle \sum_{i=1}^{n}m_{i}x_{i0}x_{i1}} & {\displaystyle \sum_{i=1}^{n}m_{i}\left(x_{i0}^{2}+x_{i2}^{2}\right)} & -{\displaystyle \sum_{i=1}^{n}m_{i}x_{i1}x_{i2}}\\ +-{\displaystyle \sum_{i=1}^{n}m_{i}x_{i0}x_{i2}} & -{\displaystyle \sum_{i=1}^{n}m_{i}x_{i1}x_{i2}} & {\displaystyle \sum_{i=1}^{n}}m_{i}\left(x_{i0}^{2}+x_{i1}^{2}\right) +\end{array}\right] +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left[\begin{array}{ccc} +\left(x_{i1}^{2}+x_{i2}^{2}\right) & -x_{i0}x_{i1} & -x_{i0}x_{i2}\\ +-x_{i0}x_{i1} & \left(x_{i0}^{2}+x_{i2}^{2}\right) & -x_{i1}x_{i2}\\ +-x_{i0}x_{i2} & -x_{i1}x_{i2} & \left(x_{i0}^{2}+x_{i1}^{2}\right) +\end{array}\right] +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left[\begin{array}{ccc} +\left|\mathbf{p}_{i}\right|^{2}-x_{i0}^{2} & -x_{i0}x_{i1} & -x_{i0}x_{i2}\\ +-x_{i0}x_{i1} & \left|\mathbf{p}_{i}\right|^{2}-x_{i1}^{2} & -x_{i1}x_{i2}\\ +-x_{i0}x_{i2} & -x_{i1}x_{i2} & \left|\mathbf{p}_{i}\right|^{2}-x_{i2}^{2} +\end{array}\right] +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left(\left[\begin{array}{ccc} +\left|\mathbf{p}_{i}\right|^{2} & 0 & 0\\ +0 & \left|\mathbf{p}_{i}\right|^{2} & 0\\ +0 & 0 & \left|\mathbf{p}_{i}\right|^{2} +\end{array}\right]-\left[\begin{array}{ccc} +x_{i0}^{2} & x_{i0}x_{i1} & x_{i0}x_{i2}\\ +x_{i0}x_{i1} & x_{i1}^{2} & x_{i1}x_{i2}\\ +x_{i0}x_{i2} & x_{i1}x_{i2} & x_{i2}^{2} +\end{array}\right]\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left(\left|\mathbf{p}_{i}\right|^{2}\mathbf{I}-\mathbf{p}_{i}\mathbf{p}_{i}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left|\mathbf{p}_{i}\right|^{2}\mathbf{I}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top} +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}\mathbf{I}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top} +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)^{\top}\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)\mathbf{I}-\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)^{\top} +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}^{\top}-\boldsymbol{\mu}^{\top}\right)\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)\mathbf{I}-\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)\left(\mathbf{p}_{i}^{\top}-\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}^{\top}\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)-\boldsymbol{\mu}^{\top}\left(\mathbf{p}_{i}-\boldsymbol{\mu}\right)\right)\mathbf{I}-\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}\left(\mathbf{p}_{i}^{\top}-\boldsymbol{\mu}^{\top}\right)-\boldsymbol{\mu}\left(\mathbf{p}_{i}^{\top}-\boldsymbol{\mu}^{\top}\right)\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\mathbf{p}_{i}^{\top}\boldsymbol{\mu}-\boldsymbol{\mu}^{\top}\mathbf{p}_{i}+\boldsymbol{\mu}^{\top}\boldsymbol{\mu}\right)\mathbf{I}-\sum_{i=1}^{n}m_{i}\left(\mathbf{p}_{i}\mathbf{p}_{i}^{\top}-\mathbf{p}_{i}\boldsymbol{\mu}^{\top}-\boldsymbol{\mu}\mathbf{p}_{i}^{\top}+\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\boldsymbol{\mu}-\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}^{\top}\mathbf{p}_{i}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}^{\top}\boldsymbol{\mu}\right)\mathbf{I}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\boldsymbol{\mu}^{\top}-\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\right)\boldsymbol{\mu}-\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}^{\top}\mathbf{p}_{i}+\left(\sum_{i=1}^{n}m_{i}\right)\boldsymbol{\mu}^{\top}\boldsymbol{\mu}\right)\mathbf{I}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}-\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\right)\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\right)\boldsymbol{\mu}-\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}^{\top}\mathbf{p}_{i}+\left(\sum_{i=1}^{n}m_{i}\right)\boldsymbol{\mu}^{\top}\boldsymbol{\mu}\right)\mathbf{I}+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-\left(\sum_{i=1}^{n}m_{i}\right)\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\mu}=\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{{\displaystyle \sum_{k=1}^{n}}m_{k}}=\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M} +\] + +\end_inset + + +\end_layout + +\begin_layout Standard +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\right)\boldsymbol{\mu}-\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}^{\top}\mathbf{p}_{i}+M\boldsymbol{\mu}^{\top}\boldsymbol{\mu}\right)\mathbf{I}+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\right)\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}-\sum_{i=1}^{n}m_{i}\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)^{\top}\mathbf{p}_{i}+M\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)^{\top}\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)\right)\mathbf{I}+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{\left({\displaystyle \sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)}{M}-\sum_{i=1}^{n}m_{i}\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)^{\top}\mathbf{p}_{i}+\frac{\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}^{\top}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)}{M}\right)\mathbf{I}+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\sum_{i=1}^{n}m_{i}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}^{\top}\right)\mathbf{p}_{i}\right)\mathbf{I}+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\mathbf{I}^{\top}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\sum_{i=1}^{n}m_{i}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}^{\top}\right)\mathbf{p}_{i}\right)^{\top}+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\mathbf{I}^{\top}\left(\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}\right)^{\top}-\left(\frac{1}{M}\sum_{i=1}^{n}m_{i}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}^{\top}\right)\mathbf{p}_{i}\right)^{\top}\right)+\left(-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\mathbf{I}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)+\left(\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\boldsymbol{\mu}^{\top}+\sum_{i=1}^{n}m_{i}\boldsymbol{\mu}\mathbf{p}_{i}^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}-M\boldsymbol{\mu}\boldsymbol{\mu}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\mathbf{I}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)+\left(\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)^{\top}+\sum_{i=1}^{n}m_{i}\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)\mathbf{p}_{i}^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}-M\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\mathbf{I}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)+\left(\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)^{\top}+\sum_{i=1}^{n}m_{i}\left(\frac{{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}}{M}\right)\mathbf{p}_{i}^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}-\frac{1}{M}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\mathbf{I}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)+\left(\frac{1}{M}\sum_{i=1}^{n}m_{i}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\mathbf{p}_{i}^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}^{\top}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)\mathbf{I}+\left(\frac{1}{M}\sum_{i=1}^{n}m_{i}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\mathbf{p}_{i}^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}\right)^{\top} +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)\mathbf{I}+\left(\frac{1}{M}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}\right) +\] + +\end_inset + + +\end_layout + +\begin_layout Standard +-------------------------------------------------------------------------------- +---------------------------------------- +\end_layout + +\begin_layout Standard +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n}=\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}^{\top}\mathbf{p}_{i}-\frac{1}{M_{n}}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)\right)\mathbf{I}+\left(\frac{1}{M_{n}}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n}=\left(\sum_{i=1}^{n}m_{i}\left|\mathbf{p}_{i}\right|^{2}-\frac{1}{M_{n}}\left|{\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right|^{2}\right)\mathbf{I}+\left(\frac{1}{M_{n}}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)\left({\displaystyle \sum_{j=1}^{n}}m_{j}\mathbf{p}_{j}\right)^{\top}-\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\mathbf{p}_{i}^{\top}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n}=\left(\alpha_{n}-\frac{1}{M_{n}}\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}\right)\mathbf{I}+\left(\frac{1}{M_{n}}\boldsymbol{\beta}_{n}\boldsymbol{\beta}_{n}^{\top}-\boldsymbol{\gamma}_{n}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n+1}=\left(\alpha_{n+1}-\frac{1}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n+1}^{\top}\boldsymbol{\beta}_{n+1}\right)\mathbf{I}+\left(\frac{1}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n+1}\boldsymbol{\beta}_{n+1}^{\top}-\boldsymbol{\gamma}_{n+1}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n+1}-\boldsymbol{\iota}_{n}=\left(\alpha_{n+1}-\alpha_{n}\right)\mathbf{I}-\frac{1}{M_{n+1}}\left(\boldsymbol{\beta}_{n+1}^{\top}\boldsymbol{\beta}_{n+1}\mathbf{I}-\boldsymbol{\beta}_{n+1}\boldsymbol{\beta}_{n+1}^{\top}\right)+\frac{1}{M_{n}}\left(\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}\mathbf{I}-\boldsymbol{\beta}_{n}\boldsymbol{\beta}_{n}^{\top}\right)-\left(\boldsymbol{\gamma}_{n+1}-\boldsymbol{\gamma}_{n}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n+1}-\boldsymbol{\iota}_{n}=\left(\alpha_{n+1}-\alpha_{n}\right)\mathbf{I}-\frac{M_{n}}{M_{n+1}}\frac{1}{M_{n}}\left(\boldsymbol{\beta}_{n+1}^{\top}\boldsymbol{\beta}_{n+1}\mathbf{I}-\boldsymbol{\beta}_{n+1}\boldsymbol{\beta}_{n+1}^{\top}\right)+\frac{1}{M_{n}}\left(\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}\mathbf{I}-\boldsymbol{\beta}_{n}\boldsymbol{\beta}_{n}^{\top}\right)-\left(\boldsymbol{\gamma}_{n+1}-\boldsymbol{\gamma}_{n}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\boldsymbol{\iota}_{n+1}-\boldsymbol{\iota}_{n}=\left(\alpha_{n+1}-\alpha_{n}\right)\mathbf{I}-\frac{1}{M_{n}}\left[\left(\frac{M_{n}}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n+1}^{\top}\boldsymbol{\beta}_{n+1}+\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}\right)\mathbf{I}-\left(\frac{M_{n}}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n+1}\boldsymbol{\beta}_{n+1}^{\top}+\boldsymbol{\beta}_{n}\boldsymbol{\beta}_{n}^{\top}\right)\right]-\left(\boldsymbol{\gamma}_{n+1}-\boldsymbol{\gamma}_{n}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +\alpha_{n+1}-\alpha_{n}=\sum_{i=1}^{n+1}m_{i}\left|\mathbf{p}_{i}\right|^{2}-\sum_{i=1}^{n}m_{i}\left|\mathbf{p}_{i}\right|^{2} +\] + +\end_inset + + +\begin_inset Formula +\[ +\alpha_{n+1}-\alpha_{n}=m_{n+1}\left|\mathbf{p}_{n+1}\right|^{2} +\] + +\end_inset + + +\begin_inset Formula +\[ +\frac{M_{n}}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n+1}^{\top}\boldsymbol{\beta}_{n+1}+\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}=\frac{M_{n}}{M_{n}+m_{n+1}}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}+m_{n+1}\mathbf{p}_{n+1}\right)^{\top}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}+m_{n+1}\mathbf{p}_{n+1}\right)+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +=\frac{M_{n}}{M_{n}+m_{n+1}}\left(\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}+m_{n+1}\mathbf{p}_{n+1}^{\top}\right)\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}+m_{n+1}\mathbf{p}_{n+1}\right)+\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right)^{\top}\left(\sum_{i=1}^{n}m_{i}\mathbf{p}_{i}\right) +\] + +\end_inset + + +\begin_inset Formula +\[ +=\frac{M_{n}}{M_{n}+m_{n+1}}\left(\boldsymbol{\beta}_{n}^{\top}+m_{n+1}\mathbf{p}_{n+1}^{\top}\right)\left(\boldsymbol{\beta}_{n}+m_{n+1}\mathbf{p}_{n+1}\right)+\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n} +\] + +\end_inset + + +\begin_inset Formula +\[ +=\frac{M_{n}}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}+2m_{n+1}\frac{M_{n}}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n}^{\top}\mathbf{p}_{n+1}+m_{n+1}^{2}\frac{M_{n}}{M_{n}+m_{n+1}}\mathbf{p}_{n+1}^{\top}\mathbf{p}_{n+1}+\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n} +\] + +\end_inset + + +\begin_inset Formula +\[ +=\left(\frac{2M_{n}+m_{n+1}}{M_{n}+m_{n+1}}\right)\boldsymbol{\beta}_{n}^{\top}\boldsymbol{\beta}_{n}+\frac{2m_{n+1}M_{n}}{M_{n}+m_{n+1}}\boldsymbol{\beta}_{n}^{\top}\mathbf{p}_{n+1}+\frac{m_{n+1}^{2}M_{n}}{M_{n}+m_{n+1}}\mathbf{p}_{n+1}^{\top}\mathbf{p}_{n+1} +\] + +\end_inset + + +\begin_inset Formula +\[ +=\frac{1}{M_{n}+m_{n+1}}\left[\boldsymbol{\beta}_{n}^{\top}\left(\left(2M_{n}+m_{n+1}\right)\boldsymbol{\beta}_{n}+2m_{n+1}M_{n}\mathbf{p}_{n+1}\right)+m_{n+1}^{2}M_{n}\mathbf{p}_{n+1}^{\top}\mathbf{p}_{n+1}\right] +\] + +\end_inset + + +\end_layout + +\end_body +\end_document diff --git a/data/line_rad_25.png b/data/line_rad_25.png new file mode 100644 index 0000000000000000000000000000000000000000..8d4ca75f93c3d59368db7f9e057122d4ded78956 GIT binary patch literal 6540 zcmcIp`y*6q_usS4m@!*&X$GU@QmJOUgyfuVN+MF~6dTcYji_`X=TK&7Dlxiph*MNb zHBDQJqRXao2$4!oD!QPgH-}SEs_)w4ocDeIfcN{uYKT&KuUP3tPVhNCa`-6c)54EYxIc-O(2 z#`nH!XyYL47FIyvMFf$?2K&|Gh!gqS0qS zB;SFuIxo)QAS*a6dF2Ou5hrJIl!6)H;f3%}6fuJm8Xj~D?f#z`g@z*I-&3l23GEl? z1G3mz^m4zEEfQLnuvLvP`!_$Eovg895^%N`B7Oeb&GJ6E53k}O&l4*}t{YJaJwJqn zpdRp8)8B5E_w|?IpK*lu3TugI)^Nz3`Ap)<(i)-o0%AI zTQet&MMqyJJC_|pY@R4Km^MF8ozXp02-2hzOTZA3IHM&ys~Vt~Q1)5XD549(B5^Q| z$RnJEXu!HqW_=E$2YM@I&F^H+bVsbF`Kl%W)e~7;U#QpM#w@-w`^eyVq>EpJ|37g_!65J~C9@%&EevK}XU#y9n ztR)Zoq1aE(A*`JzDkoA-A*@&F^GZC(pvw_B{o1aAEyU|^XMVb)o~BgB3Z2iY2tTAT ziL$w|crx8O?G{^@y|r2|+osC^#q^p;^e4{!#bl7^usgY6cum?Ov6?4YsjRm>K-=3i zX%hyDg}SZZ3?fi$bIUB$-#7$jt8$_Yf?Pusrj*SgPqTeq+0iJL(l!B|sdEr!OKaC_ z25l}V)+QX)(@lHF**swj?`qibwg?vH(WsnLs$q*sWdk?=syvCLEFqsSn6{O|XoVg@ zJ(o<|y3acTXA75zoVl2B`b??J{P(8HAGt5B8Y)~RPq7}p;#taGyS+#Pp&uNSl4?Q4 zj4_-+G?K41a3TgboZ%+67ou4ALEn@@tm~QYu<6!l^3;?TH500d$XC+K$8X>CGrP6c zPrG|mcEa!d94x`$fq)nS6Nfc*JXAxm{F&z-2;!u>OsJZ!UGwwAq%}Lw+n5!1fqyF% zJ$aN)ezPW5Cxnw+?{|0Uj*i#2#p*^2NU4#o)@aI;Ei|x-FCj~Kcuj}7P)m~v16$+q z1>{Q}ZqVq8kJY7by{t8-pIfk&`H%+2Z*PjZUOwq(V8?(0)6L$3O_q=%Rm$Kb&+ml@-#~;tukg{|*VZZLQyF@#hy6;Yay65-F>0CQyugTa)FDM}o@Hv%2Wzn3>qL=V(-Jb2WWKixH~=kx94`!Xw2iFhgYmMa9+3d=1+MK1ucPJPYMZSiKD`a zEtHgu@>br=S1~_iD|;xos7rJVx&}!165KD;3FK?f1houMbbUB7L4Id9v##jHfWU-8 z;+FXk$570qzOT_I!^*zpK!X*9jP)b0@NpY!Y8a7n`b6L2rp1W02}EluwI%BP3KUCM zZ`5-lS%d0`u&*~alSW?*C31K;VzQIr+*;EuCZ53yUCdTo4%5K%;*jj4V5^S}0{g6G zAoR&#n7QoyQS246rn|bHq!BW;Lf~eHNRAF_C8-HPDqP1%^`O@=f z;kH;IAu*i2ZMoV;xD_|Sxa8IBoJOCH>u@3?*pjv8L?oE+?fYWF;43qia;htrCgOiC zWcXe_|2YwS*byPf$K7jS3PLk>TsTk_3*(Lffuvw6MPf(KU)3jX-W3p+BOx-PNQ=?8 z=f32<@cwS`4QEzYk1mQqtew|2y{=nKuM!X>AL+O=m72qv)&Kcd4^8@2^>~JC%eRU4hTq^k5fY|22T|GD{ex$P5(ZS+0JFP=n_R@uuIX| z9pzwpo5&fBD^)HOb6V8cEtYg{UP%@xnQ*UMRid&hc8*3X#!05=CK)o@-u(nVCo5;< zM)ln37K=wkbJ;?NAHXjjJS69=_T5C9XDd-`=2);%&sv+K=NW0@SeM#c)n)YjfIo&{U*9|aSsiVHeisL>f=F)@a|}pNblWFFDmxhcwDgk!3plw8!Oxun zg0`U*yUx*7Z)Api6UxhHE%OD8dyvV+Oelly?Ki$0_hDQ5jAlW2RMN*dSRfhH-UU9* zU|#NHeBmJmI5ShmGiLivR5QohHIR8~6nty%xoL(^F0+MN6WWX#$3{#5?&L~{S=~)T ziSDfQ^=x5jQF&FrI$M}AK33K}8opy6z~trA!}ows!Euw)LmXSUrP9Ea4D$c+F6+q! zfPKfII)T-~SfKS%KT9gJTNq&3$pP0M`|L6ax(kn5_1wutqZ0w&h1g;p!0F6kPcxzD z$Wi|?lF(Hfk10c^k);^k>$J;0a6DrJ=~=iMoB|+!igESvX*D5PFgv^H4uYm#i|uq% zw<+U*V5{5VU^gwzSjf$=SlNuIN0L}EYPf>!7$()60i>3Hp3i z%pACTK;;X$I_R~`XM&Z6oP%OzYh9pici%0#&Q@`AiG8a1q7Uwj3W=z0=yQ6-X{T8 z%hZKa`v#nBAm$VoDig0)eYQ6Q06UYbZNWEX$1(iDQb@I($a_D}UI`X10Zkm0RK#?+ zR=sVl=7kuFfT_Fm;aLW^`;SMPh?86xv6W^HyFo4wrW3tARNud89=YFMxb6D<5W`8} zP0QFK3|w^w-QNN_AWYRDmHqI#m-Tk6YKPIUGunZnW!SK^+BOspDFPCGa8`$W$o_eX z+3B;I2z4#Ey5*Tqp;F7p(KVK~olsMsI^*>0B~3l={5L>$;i%ivY0ks9V%_{!OkIar zz48I9W@q^yf60#K=Kx116-GywS?t!UGwriF_t3UiqunT1d!aCsuBv4X&AiTu9&8EE*s2CmYOt)|;-SeBLG0M~(D8^OmyXEbd>HEwP z?$H@pFO59HO{thRHK-sijL{)lx9__OH5(vWMKXUDCsB1L!?QlE=d34;(YjyIyqKNF zD(%_{+q8du6B6DBQb)(-v3QWWUMz;<6WC@z`Q)-X?u%iK=<^59$8D^Gm3_sp6gzHo zVM59Au%<=tqlDww!ksf)cfPc(6RA8M)RNE_egU)DOlVjH@$3|XNb|&1+H8AhYd9Gq z${sn6Di3`kdyJ&o_J?!II21F|j9xC6&9I_yeWwshoNdQy}FyxrGcJ z3Nwtqho-&3Zp#cpvr_p05K5m_r5s`07}7invVDX(azqsMvQaiCc-lt0U)Xi760vpm z57RfkDV%wxtB-@_J2-kz-}RpOaV2?0uhmVmP7Bz`Gh;G8j63_G0aC+B4lQTu`>O?4 z=nHM@OljpK0<5I+p4(lfSmLv99+M>1{SF)85Ct4KWG+?(_DI@4Q+qxa01OBSn zt6ox>Sk&R>V5$RoMzD}LwAn>%Z0)2I&YsLIW|GRl*}tyC6_l zZEvANWRH_nS26gsx38$!ZALBDE>V+Q>&k;-5%KZTzgJZ@iBh37OsoBSHpx?Nm`N76f`aG4;E6e>+z)_$apN&^8Qet zgx2*U$gab*+5VY^9rX@2Iz%{E@`DE8^BdePqc{CvXN_#u-QW&c2oGO-pxqUx^Xy?2 zf;{p$4+oPnx7}G=8WvOEkR-u@9foXOrcJ1Gk(aK8dsQ9==k(J}nI<{QP7iRrog65q zFW9q~Y7fpkCCB+yE$aE8D+zyP0-~y((N-}Z_sEgZ#wGX5pm-{|Gcj06iJBqvMaaraZ-xIl;Af44pE<6OxOjk>*`>6$hiY2#5$= zl`B@eN5S2!TpHic^a0F}YHN-6PtCRUvQx-AhWOL&I;c>;w+>WG_W7>X;uUf_K7Ko= z_Q;$vB(}e2A8eTLW{#KD&z$SzJ5R3s!{7rizmD`>-FJQW(kuG4S2c0}LPTC-C6O-A|W@82(;+MCmPhCeB@*lUOn zDV@9?eXM?{{PFPcZ)^y&g8GTh`F$=tJlZseGbY1adTHpn(boukvryB_Xm!B2`Wr4a z`q+x_Ytd6vZDJaZcWZv&*>pX*M%Neb&kek@W7mcZ^Ab&-O;GgnBl`BQYI8ek@Plaj znB21N=^A*nL#VKN_w2V&KzjL|RL?g05_h&-7s8S)R?p8}LBfjp>6_9y70pJ9g#Lwg zU8ifcc1mVXrr5%d6T0SntdMtg-re4>ZdFHoAW`tAw6rKNIa8tvUJp0 zlJdjT{jk6tnL7%Qe5JbleujR~v>+>_=Z((?^x})ck}WsIRE<+46fROuFy`gM!}s}0%IA|TTkL`0 zA41xUo)DneK3|h_kjOTpk&ui0CCony1!x~C03uZA2JMFYi%vdL8f6G5AV-L6oIT)& zCZ$d*pzzO85tA*oSHjiC*?AFUPPS}fh- + + + + + + + + + + + diff --git a/data/test.png b/data/test.png new file mode 100644 index 0000000000000000000000000000000000000000..e54ce70a26001753f9655f8515afa52eb6c6964a GIT binary patch literal 4705 zcmeH~eN09B64g-gi|W(OR#4x z@32yq(c%k}W7dH!GV7=_N_)sv8((%93l){j6*uWXE~$x@mM>`geSUX%(f;d?{@Opd z`Tae2e$VImKEM0i+pE)avxY|MBN<~uv!`Y}!C07q{?r0iW@=ZZ<3AB)Q*DbF6Nk~C zg00^Wjm7ZA*^g(2pH}II$4(gjN$1a4iY=XKT|8yMym@oxFNS1n%ECFb7te7T%1alQ z7_zb-pYBYW6VBM(UuI`ao>_77yZ>17JCil0BmP@I<=k~WW=Nd!!6eI-Ps+m+??1OG zrn`M8-{m*IJaNOTbnV`~JNIVtq}~b4WG~&MN{{a&=x- zPaQBKwqshU0wGx(omQ-n{Hya*L_`J&rF+LwD>L=TA*H)m)hmir?(iF|~0?RX~t_lw(j0J}_=dz>PTr%0qxf^*&}dBUa572Rs`I zF$}R%!aW;_8*O1+eQ@EJ*04%p$lo&iuiHO49R7KXNC2%?)|%J{;H|N-nh7DrV>M%; zS_J8(-dN+Pu}s;XmRolG(9IJbhr-}h>QH(l$~BW}8=)6j)TQ|HaWmT4BHa0qzd+4`5b9c%c*TYSAS3szX-m3QOQtV7pLLy%YIsh2KLW(aL5x*rlx`V?=Cug}v-ey!E8omCu4Fi+ic5H%?DqBN`M`~1CWijDthfK7uc;pLd@ zHXHVJTuU^M-uH#7uBGSk|BjF6p_l|CRj0lcNEu=%+m|8mm?M0d_dl)p+5INs??|mk$j>m200;0m-`ftMfRzI7}a=t zY(U8|>{3|0aa};D212S1mSY!Itx6^o*#*#rcJWXK`ke>aG2e_3uMZ7*eSq8)EDm(t z{ybteHXYiQBDPv3^iqOJ_geMvjH`g4bO&ImzeSEI-7Qc=Q0HTTA&5DloTOx)ioH3v znxDftzGG9`#)+ec41Ifs>bPx7+JsCVw4+=TyG!)I*ibQqpCW3kSa5`D(S)GQ#VCwK ze?2s$1_Uq1fH{XsX_62>uZBdbPK~ib=EiS_xpHcg9b=Zf?FWE=A~ncl51CoqPvi23 z08+SxTqt!i&1%Xi3xgL#5FtB5G=tq7L}RkY$u#6jh^7yKqsfBXA)^J2vNxciKEn!CI|q98nw^8I1(x#29v>S%k(%6y>DOaeGM6 z1FEs&TzabfcxYraPD4V8Xb4RY01|ODVM$QVK{O;}fI&278udy5^wXs3DCcc7bv_w@ zqxE?M8hR>~bZehC9H2PP3+D&`MiC7iWEWWPpiz^J2Xtj1sZyUVm z#Nus;BsBC4%7%pyt3f3jWKmbWr0@01f-KATzF73r87Aq@W;~yVSt?5LhmtIxX2L_l#bh@57{FH zwDjD`UiCTgO;E=d-F~6p9-?xBNU0;QxR9I1s_~AXk*lQBCL;zh=Fv{-po|#gh~yQh zLWtnyqQ)kOux9|#gm!AJ><&cdV4742I^8l20Gzt+FaoK@QR2DbNGP{#4ctI0ZwC?`q#TeZR8oK6d2rFbgYd9xXooR4A~rU^&ZG8Lr>+Yy^8J z`7`0m+VSh`iV62h-C3{1v#V>;bWI=Z#21AB63a+WH7fj*&saO$3u_{D(l9}T5A3nW zhWG`sL-n%NUq81ho|TOZFIa1Rz{;W`@R?C!G+g`rUM<^s@So5ZBpCp`Xq2HXo z;bwNlR&jRQP+FcW$XlK6!Sa}`V*Sm{`>#@?1vh8)g1Ht}^ICaT(^IK-EPLf;r4Gl0Ur;{Hbw*UcdZcSEewvCoB?a)6=0(f-1s_RhzF*+;hhCsKkGQ}Fe(62&x|`MA z^Yfcg^HuF0@cN|gc_k5SN6Ke=U$l=LW@K3-`93vE&)EbiVrSC+SbIE{o1-+T#U0Mwf2-R6X(bvtC5p$U?%r%vu<<>StFF}NcvYQHlbg*;mp!~k@aIJyY2Tw|nqZ80Fp-S?;G>FX z?iMva$$1RZ^4l$F)qPlXDa4GFLL47l;Bb^ zy`>0)35X$qNl{}v8c7zKiy&I9ge0}B&et8&_N7a8Q#!-;_b8nwelyb5`FL&!qzf8L zF%&5x3!XbW0irQ6u_&aFe43>I$?Il4|LQ}sLPA5i=KuHq|AfEJfm1ia Yi^d$EId0+$KhOr*nYkHT%=XIv0qP->>Hq)$ literal 0 HcmV?d00001 diff --git a/data/test2.png b/data/test2.png new file mode 100644 index 0000000000000000000000000000000000000000..7453ca43fc0357e88648b16ecce015f204f82960 GIT binary patch literal 3812 zcmeHJZB$cN7JYdn0(qh-nx{pnL5vgky0s07J{{Cjf~E@?e_u}vwiO%0Fbl5@>$hN-2@n0uaEJt0e!Ld`neW;V9FJkdJoIB=#|jrh z&{Xc_<8FGJWkp((*R`&1L&!QdKq6naGcGRjJvl%OTemxMhdffoON^Dr@I1YI{ADX5 zO)+dvh}U{?z@G0$e+c!peU&5Xls&8)YPYj=TPFYKXi}j@QIh6Ss(r`gFy#Kpf9`K4 z6FvPCNvz4}WZf8BQSY`k?&Fu~kYEzya zjNt?gyaX~*4>*zy6z~qQ(SU(2wu}S=+e_3G$Oi*CfjkXpjpzfaOGpq@N2YkdWRCZoCA@jrVpX0-p<9zzqd{ zXJCZw0&cbh6{|tB21f?;V44AX#9*LQC5iw82`psI2&^ar`Vks{8(Oo!Jf)U}VGVX& z4~sfH7Xg)V(mH@v>(GdPqkV4#U`_?o3r@jD+er)%*Rg8 zY(v7tMVV791kJK3YTqiYVEFY!p;~e8Z;VoAib%_5*cEPqsawnF;N?5ZZ*wWcd56qc)=neP{l{&3{}>q-fcuwO%zo}-j6nCD-;L$WJd;NI`jT-^CV%6Fxyth zX`phx-1G2yXc*)6sT@A(Uj$i-dK_yRz2ngLMBG2raL3WczmS?MzTdszd@a7Oz$aHC zid-o{ZE3O%`&!4|v-UU`t3t+@(3~kDR;k;R?UacY@+KHth?nKR0@2@$x!2O4KQ&_Y`_kOo%lMZRHkaya5Gl z6`SAhjoM{FWV|SWZR0+3D-jl|9cU{N)3;KxAQASV_GH@=aq;|Vg?QXbDsOmA*xy!& zB$}xYNA~4oE$mR((BA}!#KzrdauHGZ*&TV5Ch{>xowX?X=%-d77V3$!zgJsay0E`~ zrv^oxAgUOCYoMVbE|WF+Mjm{(1Jw60_rvJAOMG%X*&#TLF=700Zd43h<}+(OazKYb zI-S?9&Yrs?ll2D7^q{|_kGzgIS`uY*ZMA~p7byO95yw5%O{rgf(xPJzU#05k%^Qgo zs-*)9t7`G@)YN(78ubsJw=nOuG@v>}Qyn%hf-|FRHV>%mDJm1$jcZj+sZalP4XCbD zRI~FRwhGn74~EsXI5W2y@8;GI(PyI9@{~2+!r_&2U}Vr`ee!rorzN4=v{)+;Nn?eg z?Tl^xTpM(Xw6ZC6n=>4v#bPkv z9|YG}gt7*YxnYf#!a2IY53Ue9&&&y~=z4vZq*w)aXEUAv7m^DJU`>C{YOwoQGk6O6 zVEt30jx7zCPQ;N|5#3zO*@U8{k?4bcJ|-|LQ{FOE-IRK<@rsU($~UU(C(%}DprFM! zb+#^f8yTDtr7gkZBA8b`%^#FIW!6|buTn;CFf;;nWrU5H1Vxmn;EZu1KI7_@n4}ev zfZiz6IXfg2XS-Vnyir_8#F=gYK%?YqL?Q5Akda+bP>C7}G85*fSECn`COZ(0wXF0S z0Il$*f<{N7|L{JFvMHyuV<|cC#w4AHDUeGm_=gNT80C-xfUd5spm2n&0Z>|fBv(Z# zA#y^^KLck#NwwSnIFby<%`E*0M>6c_4sve0TkSz^zG{UdLdv^#fAVwnIo6)5rMBi` literal 0 HcmV?d00001 diff --git a/data/test3.png b/data/test3.png new file mode 100644 index 0000000000000000000000000000000000000000..2d29c73049cb95c5aaf927065b980b23fe542e36 GIT binary patch literal 5600 zcmYj#2Q<}h{QotsY?AHTqZ`WJLN?hhu8eG#>=i;6*&!o)WMy5OkWHD{dnA!Bvdg~G z@9FZaZh2+5s)7Y-yVhaUWS%SS_7<<>VSBOMbLqWHZ#_>0*If%H*wcXhRQ^8r605G5~r zYae?%w&zYhC^j_>Z9TgO_O~Dq8e4P z_OXO#{&MABZ^%vX^VQ(<%f02iiXtU61P2$NkdjRSypVOTtgH+T#k}dGd{tWN7!nfV z`2X6oXSaHzhX9wh^V zle@caG|9`O-@j7|l}t?+Z~kDn#`ARv$#kQmqu&%pBKiOOeJNnsPA}!f#V#GhCM#=R zA$f(x1_uXga8a=b;e~AQCz1(A?Na$J9%JY7zQ|G$+bN)?9Nr{YkH!=&&HlDk>}- zv=e4mfOXH!o&DMz(S$WL)Yrq9nTc@LZ9iLn^x4^+uc6s&`S>w#wLRb!CB|^pjuX+X%}p}vP`z@*)nBV$@~Gbaidj>tJ9qBT(K))h-apqUM`&^+85kIRaQn(j z8y7`T{_*3-v$HdDa&qv(&dx3;C&xtp4Bb7zz&DE-!52KSUe56gwj^ z2EqGw$SyD-ATuiq1fK}~Yk|%SMQ?ZckZXSzm%VpEErIV!OX=w7&JVuIw921;$rNdl z701KFqm6s}=8c}dK0C84H7%`9rtqdA6z^v3;K1_96JE0{$lE6IC{g?2RB+1Yr>7c1 z5b~%yw{M3YZj^x8o4=Tm_!d-@+hb>Me|#BqFKuFV_2BR@(LI3~2D9u8A_}szu*iKs zAm}_(w!Ut2k4GPgM7g;oxF^uve}WH_!CqaZ@tYR5Hn+954*3y(S-W7pm6>(Ec)WLV@-{M7 zKInpyh2>^%QKYE`=H%p*Wd>8+kjWWm1 z?k)%(C_et+epNw1&-{FIQ4wBEilmGT(?!HAOW*eXzJ;M-(XevrJ<-4yFP1@D`q!MD zou{Uz0GLrTe~GzsccN@pz~bYpc?L{T(H%<4qw7oW;yLYXab~$7B=6gbO$%dVV+pqv zdifC9tf&B4OEa@yg7tFXCv$VVn z5a;j7j-mOO6+!sq(h{+M@b>O*<*o(DRs|8Yzn5G2+uJDGII+MJl!Sx?7=b6n$=>+7 zrb@P7(|!2xq4s0!z=rEWt#vII+s4IAxuIZBy1>(Z?w$t6aRTxb@BhB&|Dn;)&^QVZ zla>yg*j!s*=V*J1GtAm*T2~gFSnBI&0F62SVs`s%URtU#s~8gJ)J&YbQI?p5oz|TL1M$Q6$|gW@Rzb z)L5(UVD0E-{P^eafAvwwL-5812fLpRXJat@WcLfax5l7>a{fo}s;eK&6%8mZ0|Cc)$G?w)fS!w#^Q>cV$;WTb8SLPyo?8OCu z;C(`MHMOmkR&OLvhGKz#U?4{m*psAzjqfp5j*eSGw*7EVZUx+2ou}>oLI%&=+^S=* zT($c~Mo2uo>FMda7sZ?a0kE*Js8^Nho!g?#koUhnDa?M1^{L>#_!w`ie1b-IW%Av@|M!|!TkKwh_0S05a9{WWgXB?u3l znVFuRUS5u~_v7T`3_Uh6Htu}+mqh|UMZH)liX4Xm_AoGYe2Z`CeyxgUt9f@$0#sQ= zg|Pnx`2gDOG^vw(+sjKD-LP|H7wQH|M^pq@vKlKu6E4L z$H&Lry=LXgzryiR(Im=oEN61!sz&NnM8xU&IcI#pr|8=m4km8b(HOg>arwWP2f>s_ zg-c6MNMlip_4eHvI9Pd}>UNakE@=1p`DcEq>gwu>XOp$>?$&hmXQj?nncY%XwFo`> zIRNMhiW_R~moFQDyO2s9(b;)3nk^AJZ>=3sSX!E%mKG_xR8hhETJe2#Uc+`VSaWy{N}@KYeHK3gxJg%aok)^Yf!m+5mE8aQ@3e zk1?xq1Ym)R$(h#v{(cY5f8xvfQwudcJt3)YPZ)H;=K1GX8n0=A=H}*+b}>=j^^+4H zD^l|ZbeyGz3LQ&RQ(?jZ*=cJ#JNG0k*rNI-b&5a6$CF_!hDJv}hfUD_fU1Z+&^ zzP@6{gnrMTZ+W$P#U(f|ay;fq8PAueNUZ4Udg&oW;06Pt!_Utzqoo4R^saqNF!n=i z8pme0oiNVhm9_W6so%Rp@zjd~kJfN_W{_arHg)t5M2VFJQH(-DLa5{G;hp{TOiX~;-qk((+V%3= z>Z+w$9JE4EyEZ%=uU+!@Wl+;HRcd%;7I%-mj!{gU4dx;OM`{0N)Jfd`Cj}pgTan?j`!&^p08r?9ql8kCL(R+>fD@ z*=kpdS}U9*gZMO0X7^jA`1%(WhE2|@$pcOmRSP<>TnNF&!O>gwW1bdZY?VK#^wut{nBHQ?cP0&>Vd?m3jgl%vbHv+yiY$(3q!x= zDRTt)`$ImTMiPYFTyEW>V1ZC<@9e0ks`AcDd5~EP(%-qOGvogQ4e)yJFR5c46XVg* z5z5I4=f}~_pBF732&k<1bW~Ld-ryRzLc+F$%w`Sut?H0oMYX9JuBxi40LsySSgUVW zv0PkT^@h}M|M}!WhP3Acs{ZIhfgb$$_*kKN`n~pa|JSbSYI6Eddy5TGcs)Ri|q#X^GYyD-42B!Y>6~8Gb=4Er3eTE(5emifLHGQ`}a*vO*NJs24!Xi zdh}FOVLz&Qlhk$c<*JU|f1jPXp-_;pAk}zAF&Ix>RMf3x*v&&%FuIk0Sw+QEB+o9e zf$C6M`~Kem#3^ot@$vBi2qoD*RDDffpiE7wm;I=Sy!|gl?XruZVanJMBvUI=`?jg6 zY3x}m$Z59q$4nwfASot`)J{)NyFFPA7k`M}ic!WjX&@#hW|VNtQ4IF;^}SaxYtlu4 z@4+o3F0P}k4UMHFB9H(5a*T;yG6~cuAupl_i*aHk#qr89+FeQjG>iP zH8nMgniP^OME5qEu81DM;ouM+InU0{KJ?kv3ktgSV7mYvyF(Wj7Le>=e7wA9;d*sV zy?A)}9V#lcF(+qHuFP{kA0K#W#^?Fm3$RZ0DuAxUP$F77Iy@E8re@{c?d{^yQXn1r z#xpWAH@CI~%s#jf?v`;=X_%PM8B_xOpoq`sC_F{j1ALkM%|(#{8=6%_LP9>^*AFlt z5I>F96qC}g6xrWp%p?@WsS<+Z0ZI^+EXT;m2+ZKk*|PiP3#w6+qtj<4`X#i!X zBm{vGzgXxEe@kUMkYHreX(%t>1zf~C38VHJqllCg!@xl4t9HV_jPEXj5y_%Al~4Ch$}a?&OT42Tw(#(O^;O>FFbX z-Z+lunLc?^xHC69Yvks>bTp($WN0`I`VSZ4Ae8m>^%WHrm6bvDXp3zwKtxzLOVZN@ z2qXswo;{<>orCaByQexj`CO&do;OG`^n52q&1 z&B;Mv%KoKj{Yg}Au7!#U)BxfPDltn<&%hFDAJ>usCk7yrjD%!*i77yq<;tZDob=D( zcs^?4X4mDk|HtUHp#;w1RdLn9Ocpvm~{DR>iqW(L|Q)sJ^{WCZIzN*Tmt_VD3D5G!D-p{d>d zB+4B6Iyzt$@w~ViT3RknP9XSxct`>QTk~#^S&{;67l_4r} zbD5_?UhgQSt%!^*)Y*c{5-3=?y0|!u<;46EN>5E~Y-%z>AnY6*(o$2c?#qkQJ_0^i zlrdMwQ8+W>Ybg^W<5<2tE7&N*a+@Ag=m3utRZJtGS&bAP5OA!ltUM_i1$u*a^_bcR z5sH&#Q0@07pgU!Zvc0{1d3iaI{3e6qnv|G@>$BtIy5?pHAt44SuVN(s2LO=G&8%Y1 zGo`%L + + + + + + + + + + + + + + + diff --git a/doc/uml/cpPlugins_classes.dia b/doc/uml/cpPlugins_classes.dia new file mode 100644 index 0000000000000000000000000000000000000000..7e24d9a6680c0f444615ae14eef9a3c06d035abf GIT binary patch literal 5924 zcmZu#2UJtb)B!INgq(~=3n)D_TkWhj^ z00AL1DN+I?kUzeApZBfzzq8kx^?h?@=Cr-P+52!LTq5~>kdpn(HS=2Te=z`E)+tC` zFh}25Rq^shm7-Ku=!}*shX%CS4QQeuuX!(1ko#3B{eU@86pM0RrtM97bzlT(8#16v zaw17O_rW6Yhwfq8cO0w=y>HxsVKHgs7zd z+0o;Y*re(1u)wg;4Ey~KbMxS{Q^@1(o7U;YcC=!HTrI~P9uk+uaz^`3unRf4%79K# zX4LrtiopELgxN|Aw&u#HU4+F(dz?zs~WqIwxOG`cCiO zj9T83KT`UXR6Wj*HxFIwJTo@KjPCQ#DQ$V@3ESLBo%`CTrkT7=KiOFGBu;#5DZ4?ZG61LDdJQVIw0TAGyMQ*A># z4_rUp1t_(Zd_~>#|LHl>?a3GxaD0H^8$1jHF1sp!1B9MnVSWw(?e4xMya0*kA~1OW z9B-@JFtPd#{U(PFEitJS@Cn*Egvu|Uf3ML4+k!4qNP1@SuCRZAx@OLAuBWB^>4MfV zznKVTU&>Utnmw#;&D>z={?=Wu_F_o`YIj(Cgdl~r54{1ao|pP2u1az!1k@9NEgFPJ zLeUTWrQ4|*(U_urdeye&nkw&=SIcY8w8PIE*)UJ^i?Y{0chAn+T%F&zI2hy6c}N*a z(Z?}!&qTaMuxlrO6>>ta!xtk>??pM_^tliKdp>Yii&a~@T7`Eubb&BCUFyNCv%LV- zd23Ri+1iLWndWN6)@4xT8pa%po0NE_p~eZj+GSo8qNDk}UX*=Gp=g-S*;~Svqw=(aT?L}PhM!$FQL@YmOX9OC6lRZUwr931m?^dOg=$OA zRw|?3l-7svC5J)NTfJT~37$9~%@ap1}^)|S`TAl3fb{>VN+!}FjG`wR^Q~8_6 z=$Jeo30Ui;WOB-sReWT|G~R7*ym!K}Z+1PFx|ec^Y%l!yUNEN$4aXm<%y}Nu$8~Gq zgg-A_#VkTav1ZtJyuxbyhgR_N^=YQ~=Qdvt&*^2;)L|?r!hCgn4FoC(lpsbN5z?IW{6yH)L;64pP77b*{;lCv(Lbnf|Zc6#KY=$f- zp5}Dhrxy?Yx>u=7xD`;mV(-v|&(wF+>63dmY*@3_hq}QL>g9WLa6ao|%24M_oNFvSabfav848oScY2Ij0*AFP2|Lz|uZ~o4`5~h!jvNitGn79g z{!Ix#8pN{4+I1r@_9r)Sp(b+IjpB}S`2?r3n&26FG~7*WaWBa~Az6DO8Wz5AR*bga z9;0`JUQak8tj`}Vm&wj^d=1MLwn)3aO^J=bb)9`bS3vK)`((C_eXy2}%TBz2rv7uL zvHR?U0G36kR|DI5)^AHNeTxbG5V(A9NO8j0L@4!NdKKmYXyW*1M(7{f!L&UEYPPx< zDXD0aPOjn8tRMHJ_dxT8(W;(FVe>8(57MRBNbYfrY+L?P2^aB zM)p%%gRzzGB(T+wc5qAv+x^vy%XZk8GlsI%Pq3vyos6?VU){G-=b=I;I!&}hOP$)% z+|Z|`&@aC$qAw`C{AI_ltl4fZT`NwiJcDI@A^*_4hawnfN{1y2XTKmaIzU7_lc_BKss+^d_sc*ZDMUg?JC zO&m?sXv%FeY&h;4^Nl~aGvxa@-}ZP(lUOsiepg^;NX?^4sg)+NT#aoN>`PqL)q3V_ z$`XG+YAWnmBZa{BtA3i>v&hI`Ozqd-S1N4Z0C2NY{L|38fJ_bq^(y6l#J?#a5+Rl?0iaXE9d5P)LrWhGLP~Ou<+(L< zk(7Il5}%zD4k$}%O`*(|QG^}j9fBzTY&}IU^%CV?#IY)#Gn57p%khVv(R4Ulu9QZy zlmPG3EWZ3SE(qX#RbwDe(h)px>FrDiN{yo5*KEbzHq#(~A@$x(-_>QZoIXO((ljwd z$K3q@GHVY=NiLJ{kh~`8qzHLP!g=8(ISDPvU!W7fHPE=obG{JF`Bmb=!EL&H76(## z@osF_<_O(|nK?2SPyqWqS{Dw5U3htE0JHs~ubsG$ZE`N+OS)_w_s770&&c zS7SuLtn{bgb}Fdew*5vcAktNS?gfKc2h|ZiSw^nZ;~lS4z0&SW)BtpV#%J2(&4zgD zj&@)B4{hq^oFaq7x6_Cd${lE<@UPu$SgVIGEO`QE2RT*>Iz7aB!F`5)9!rEA*Yk%4 zY|2k7yl0evmw37}T8E1V^2pWo`>sQ875q}AYdjjmXv;UwS6xK=W|g`T!{jz-b05}m zC!n6u$+Xz%O^JHe{{k}^c=`%ys()zWHd}DqEdr!e-mR? z^-WdA=>j2~&>8j}u*-2wji)>(`!^-nF9N7cjWgAC=PAz>LFRjR@R*#@yxre^XqKtI z-rX&16WbT|7)gpJJHJ498P*B-&aq279yDD2b)p`A$v?w{1myZ% zTENDwQ|ukDAVKLs!1O&ITFBXz0c>g?kMaUPMt0Lz87ZnKTzn6!6nu{ zZ!-IqrXM1>#1ndjX<>f>S0|fv*^6Q74Z7yo*O@-Lu3n(c-b%g~hXHGG(|UB<49aPl zA@s^QnIWR_zh~9>{S+SO6dyA7i<|CAHkHcL7>d1G#^gEc!%<}w|5fvYm%)jkX^zLb zJ{9t5V?@UHaxFJwQNcA;8izT@+@2({amx@mYjTZY zaz*f3V~@cUbbmL{;?TA@IMT5wK*(dlW1?mToc%<>S(+6H5&*xb67ZYIGOl1?^@%H! zOxazPzfYgcOtcmRc$PRy*&H~WSVIby+aLpV0b{$tJw(fRUmmf|>f=PHbt+0^a+KFo z6aQd8a4UtVl({8Z%rqL;SWF7N-G(PmV~FAeIk(m(7doKMwmzf|L%6rGvt#6Ni6z!j z*NU8&Ks}DkpAw~-t!w8+huNil z>x^A2u^HMj5`4rft`TR*o6C??>7rh2{U$o(WK%Aa?;?y2HRQi+;3vQ^G6+fMsVmt>FR z6!bILyLyRfKv-KYDPp`p{#j|Pf==)t{y=fNP-O+frt80o(Hr3lF9=eGNkWaY#qQEq z-y&MTko5j}hRX7Ah6+s0>_gDE{B9Ro7f?I=F_R7dWQeOS^0$lWTKn9_l~XhURsgwl zPS()a4I!vVt^CEATcaZ{eJL6wpL$(skj&4$@bjvp!#zc^-~GB*&XY1!-X@ak)v|Xk zxLiSHDIE)Gl8P8}d?%(e3#7+5WdUN+@=v1iuN>wtN_f@Ov8UOhNn4V*5squ)YeD^J zwxa4zB%qbCMA2=0vYX-n4L|D)eF~`M_(r`&c|?Z$LkV299eX8LXK22ZuV29BmULE1 z2W-h^>8=C(QqHQb{u)lhsh;JB>H^9*Ca5LEUTuJsG z6TF2ZO6Y9NC9s?`(KaN2!#e9_EITLf?cG~*%nHe>+1cQRH9Uo)zgLA+4dpiT7y;vc zyKRRv&@Efe*;5nf7PDLi=hv8szVSXSyhwC9uIpV);6Cf^E5K_+vsf)#xy%N4{N&PO z8~Vg2?{wD;Q7yfqh19&i|234wq9=N@ObgTmoRDj&ZEyp3wCY%BT}Okb+>zl>_C)CX zV@Zz2R&5VW;GF->m;wAVOtPtFA;R=YUJ)u11C81K*JORV9-;VCk>$K>hZ=rXY1Ts_ z--%CgMJg*Qj)i-x*Hcc0N7&#Jy%fZKC0T)!sAk?k3+Ha-!kC^PkTMm`-ywQxpy-V3 z1w-pMA4pjyV#PbAn~P-99O0-mOqu+R6HI~P22pcvD6@hA@$AWE(7#@S4REe_Gs5@V zAy_8JRLW9n*d3&}lz6GYIA%nCA#ZGR(XdVnd*=zaXk4ui+%Q{aF4)^(^|4mrdhN4E z1m=?M#_e*mgWWBgK&cX-?O%;|?m80m>Z9{`5z&V&v{Rnb`~T-@;=qpjbtDI4f*q?n zpVc%On!}j6YCH`A%Bg~xJ9zaA5k#g+oSD}4i&v) zqLeb=>AO&n&g!`|sLiXxxO7d_GqdEJU}5ncFKCW^!9Xmbt`JM8sLkr?`%&aYyyjnS zjQ47Cw>%bCQ18+NKka>wwV@Y6gujB+DbF>^AyT+~}syYW;|Lkov8H=yEqC z>OoEXqJbIYN@W+)Eh~WyvZ`RRWv>g|k{Yuq~j}X1G(Q-Xl>=)y%qDx7<9knoOK%wa0mVQp$EECE{+trH!)h|K3s&g)eNuzXBxr zSWr11#HKMRCv#IhX@aFxZ_Dq#yYhEqiMIRD!u${a8-1ALioL2!u6l!9orYdjm%RM7 zdqd<2o{KwN=d^8(>k@ZK<{|nG=OL)Gx$1F*@ZES$_x4L%u72vT2@lbebJgLW`-N6< z>CIEVZFVdX+SP6KT&K3=6Ti4dmr=-`N1srkkv0E*_2Ye+*XPDqB;GTWHDof)$D>rvKT2B8dVN_*7vS^Ba^Ts_=|#DPxW*SHj}^Lz z?9pf_0tfh)KfbFU?tSrI@l$f42kpX$jAlYipf%Ppz#m(+v)o3lk)UNYv>HTDBSI>| z;ya)pAm47Qb{P~E1Y!D_osMrQJ(;1bKO(IVvq^X*LG?UAf$rfZ$Rn{*R@d78TRnrF z?8+!pGNi_8^2=2AHRDf%q}M;iY>Q0$JCJr{g*;u4ZHu5>P}Ga9SGX)U*hNboeGh1B~ey=_)_?#QIN*W~wTNgk2#T=*~W@;2{< z>kT`?rEh_YJ<8!MTMZX)5%UMuy)Y(+A&*~Alsv%(E^Mz9!5^4cCcsnKg{8NIel~nD zDCyabZit|-i2UiJ-v?{uPl9>KBv*eCHF1&g7Rx#~|DG?ywPkv92v=LtCpWE}|8a7d z!;e(V8_$aLI@x#@Z!@cmpznJOM$ohUdW`(EGU~X{j8J&~`~b8XeIl|%F1e~l5lLwY z<1G2OnlTz|>D_FrLGpZGnXc-HG2bQt37TxV3!Zsx%IetXlJluh|%UzT@+1 zZnY4< > +c itk::ImageSource< itk::Image< std::complex< #floats >, #dims > > +c itk::ImageSource< itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, #dims > > +c itk::ImageSource< itk::Image< itk::#vectors< #floats, #dims >, #dims > > +c itk::ImageSource< itk::Image< itk::DiffusionTensor3D< #floats >, 3 > > + +* eof - $RCSfile$ diff --git a/lib/Instances/BaseImages.i b/lib/Instances/BaseImages.i new file mode 100644 index 0000000..604cccc --- /dev/null +++ b/lib/Instances/BaseImages.i @@ -0,0 +1,24 @@ +* ====================== +* == Some definitions == +* ====================== + +d #dims=1;2;3;4 +d #objects=Region;Base + +* ============== +* == Includes == +* ============== + +t itkImage{#objects}.h + +* =============== +* == Instances == +* =============== + +c itk::Image{#objects}< #dims > + +* ================== +* == Dependencies == +* ================== + +* eof - $RCSfile$ diff --git a/lib/Instances/BaseImages_extra.cxx b/lib/Instances/BaseImages_extra.cxx new file mode 100644 index 0000000..bbee0ce --- /dev/null +++ b/lib/Instances/BaseImages_extra.cxx @@ -0,0 +1,18 @@ +#include + +#undef ITK_MANUAL_INSTANTIATION +#include + +// ------------------------------------------------------------------------- +#define cpPlugins_Instances_BaseImages_extra_SimpleArray( V, D ) \ + template cpPlugins_Instances_BaseImages_EXPORT \ + std::ostream& itk::operator<< < D >( \ + std::ostream& a, V< D > const& b \ + ) + +cpPlugins_Instances_BaseImages_extra_SimpleArray( itk::ImageRegion, 1 ); +cpPlugins_Instances_BaseImages_extra_SimpleArray( itk::ImageRegion, 2 ); +cpPlugins_Instances_BaseImages_extra_SimpleArray( itk::ImageRegion, 3 ); +cpPlugins_Instances_BaseImages_extra_SimpleArray( itk::ImageRegion, 4 ); + +// eof - $RCSfile$ diff --git a/lib/Instances/BaseObjects.i b/lib/Instances/BaseObjects.i new file mode 100644 index 0000000..e84f8de --- /dev/null +++ b/lib/Instances/BaseObjects.i @@ -0,0 +1,46 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #dims=1;2;3;4 +d #vectors=CovariantVector;Point;Vector;SymmetricSecondRankTensor +d #color_pixels=RGBPixel;RGBAPixel + +* ============== +* == Includes == +* ============== + +t itkArray.h +t itkArray2D.h +t itkFixedArray.h +t itk{#vectors}.h +t itkMatrix.h +t itkDiffusionTensor3D.h +t itkSymmetricEigenAnalysis.h +t itk{#color_pixels}.h +t itkSimpleDataObjectDecorator.h +t itkVariableLengthVector.h + +* =============== +* == Instances == +* =============== + +c itk::@{Array;Array2D;VariableLengthVector}< @{#ints;#uints;#floats} > +c itk::FixedArray< @{#ints;#uints}, #dims > +c itk::FixedArray< #floats, @{#dims;6;10} > +c itk::#vectors< #floats, #dims > +c itk::Matrix< #floats, @{#dims;5}, @{#dims;5} > +c itk::DiffusionTensor3D< #floats > +c itk::#color_pixels< @{#ints;#uints;#floats} > +c itk::SimpleDataObjectDecorator< @{#ints;#uints;#floats} > + +* ================== +* == Dependencies == +* ================== + +c itk::SymmetricEigenAnalysis< itk::Matrix< #floats, #dims, #dims >, itk::FixedArray< #floats, #dims >, itk::Matrix< #floats, #dims, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/BaseObjects_extra.cxx b/lib/Instances/BaseObjects_extra.cxx new file mode 100644 index 0000000..7798d3a --- /dev/null +++ b/lib/Instances/BaseObjects_extra.cxx @@ -0,0 +1,99 @@ +#include + +#undef ITK_MANUAL_INSTANTIATION +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpPlugins_Instances_BaseObjects_extra_Array( V, T, D ) \ + template cpPlugins_Instances_BaseObjects_EXPORT \ + std::ostream& itk::operator<< < T, D >( \ + std::ostream& a, V< T, D > const& b \ + ) + +#define cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, D ) \ + cpPlugins_Instances_BaseObjects_extra_Array( V, float, D ); \ + cpPlugins_Instances_BaseObjects_extra_Array( V, double, D ) + +#define cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( V ) \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 1 ); \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 2 ); \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 3 ); \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 4 ) + +cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( itk::FixedArray ); +cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( itk::Point ); +cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( itk::Vector ); + +/* + #include + #include + + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + +// ------------------------------------------------------------------------- +#define cpPlugins_Instances_BaseObjects_extra_SimpleArray( V, D ) \ + template cpPlugins_Instances_BaseObjects_EXPORT \ + std::ostream& itk::operator<< < D >( \ + std::ostream& a, V< D > const& b \ + ) + +cpPlugins_Instances_BaseObjects_extra_SimpleArray( itk::ImageRegion, 1 ); +cpPlugins_Instances_BaseObjects_extra_SimpleArray( itk::ImageRegion, 2 ); +cpPlugins_Instances_BaseObjects_extra_SimpleArray( itk::ImageRegion, 3 ); +cpPlugins_Instances_BaseObjects_extra_SimpleArray( itk::ImageRegion, 4 ); + +// ------------------------------------------------------------------------- +#define cpPlugins_Instances_BaseObjects_extra_Array( V, T, D ) \ + template cpPlugins_Instances_BaseObjects_EXPORT \ + std::ostream& itk::operator<< < T, D >( \ + std::ostream& a, V< T, D > const& b \ + ) + +#define cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, D ) \ + cpPlugins_Instances_BaseObjects_extra_Array( V, float, D ); \ + cpPlugins_Instances_BaseObjects_extra_Array( V, double, D ) + +#define cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( V ) \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 1 ); \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 2 ); \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 3 ); \ + cpPlugins_Instances_BaseObjects_extra_Array_AllScalars( V, 4 ) + +cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( itk::FixedArray ); +cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( itk::Point ); +cpPlugins_Instances_BaseObjects_extra_Array_AllScalars_AllDims( itk::Vector ); + +// ------------------------------------------------------------------------- +#ifndef cpPlugins_SYS_MACOS + +#define cpPlugins_Instances_BaseObjects_extra_VariableLengthVector_SetSize( T, P, Q ) \ + template cpPlugins_Instances_BaseObjects_EXPORT void itk::VariableLengthVector< T >:: \ + SetSize \ + < itk::VariableLengthVector< T >::P, itk::VariableLengthVector< T >::Q > \ + ( \ + unsigned int, \ + itk::VariableLengthVector< T >::P, \ + itk::VariableLengthVector< T >::Q \ + ) + +cpPlugins_Instances_BaseObjects_extra_VariableLengthVector_SetSize( float, AlwaysReallocate, KeepOldValues ); +cpPlugins_Instances_BaseObjects_extra_VariableLengthVector_SetSize( float, ShrinkToFit, KeepOldValues ); +cpPlugins_Instances_BaseObjects_extra_VariableLengthVector_SetSize( double, AlwaysReallocate, KeepOldValues ); +cpPlugins_Instances_BaseObjects_extra_VariableLengthVector_SetSize( double, ShrinkToFit, KeepOldValues ); + +#endif // cpPlugins_SYS_MACOS +*/ + +// eof - $RCSfile$ diff --git a/lib/Instances/BitwiseImageFilters.i b/lib/Instances/BitwiseImageFilters.i new file mode 100644 index 0000000..172dc70 --- /dev/null +++ b/lib/Instances/BitwiseImageFilters.i @@ -0,0 +1,14 @@ +f cpPlugins_Instances_ScalarImagesFilters.h + +d #filters=And;Or + +i itk{#filters}ImageFilter.h +t itkBinaryFunctorImageFilter.h + +d #dims=1;2;3;4 +d #int=char;short;int;long +d #scalar=#int;unsigned #int + +c itk::{#filters}ImageFilter< itk::Image< #scalar, #dims >, itk::Image< #scalar, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/CMakeLists.txt b/lib/Instances/CMakeLists.txt new file mode 100644 index 0000000..957fc7e --- /dev/null +++ b/lib/Instances/CMakeLists.txt @@ -0,0 +1,60 @@ +## ================================= +## == Compile instances libraries == +## ================================= + +SET(pfx "cpPlugins_Instances_") +SET(arg ${pfx} ${prj_VERSION} ${prj_SHORT_VERSION}) + +cpPlugins_WrapInstances(BaseObjects ${arg} ${ITK_LIBRARIES} ${VTK_LIBRARIES}) +cpPlugins_WrapInstances(Paths ${arg} ${pfx}BaseObjects) +cpPlugins_WrapInstances(BaseImages ${arg} ${pfx}BaseObjects) +cpPlugins_WrapInstances(Transforms ${arg} ${pfx}BaseObjects) +cpPlugins_WrapInstances(ScalarImages ${arg} ${pfx}BaseImages) +cpPlugins_WrapInstances(NeighborhoodIterators ${arg} ${pfx}ScalarImages) +cpPlugins_WrapInstances(ColorImages ${arg} ${pfx}BaseImages) +cpPlugins_WrapInstances(VectorImages ${arg} ${pfx}BaseImages) +cpPlugins_WrapInstances(BaseImageFilters ${arg} ${pfx}ScalarImages ${pfx}ColorImages ${pfx}VectorImages) +cpPlugins_WrapInstances(ImageReaders ${arg} ${pfx}BaseImageFilters) +cpPlugins_WrapInstances(ImageWriters ${arg} ${pfx}BaseImageFilters) +cpPlugins_WrapInstances(ScalarImagesFilters ${arg} ${pfx}BaseImageFilters) +cpPlugins_WrapInstances(CastImageFilters ${arg} ${pfx}ScalarImagesFilters) +cpPlugins_WrapInstances(BitwiseImageFilters ${arg} ${pfx}ScalarImagesFilters) +cpPlugins_WrapInstances(ThresholdFilters ${arg} ${pfx}ScalarImagesFilters) +cpPlugins_WrapInstances(DistanceMapFilters ${arg} ${pfx}ThresholdFilters ${pfx}NeighborhoodIterators) +cpPlugins_WrapInstances(MorphologicalImageFilters ${arg} ${pfx}ScalarImagesFilters ${pfx}ThresholdFilters) +cpPlugins_WrapInstances(GaussianImageFilters ${arg} ${cpExtensions_LIB} ${pfx}ScalarImagesFilters ${pfx}VectorImages) +cpPlugins_WrapInstances(ExtractImageFilters ${arg} ${pfx}ScalarImagesFilters) +cpPlugins_WrapInstances(ResamplingFilters ${arg} ${pfx}ScalarImagesFilters ${pfx}Transforms) +cpPlugins_WrapInstances(Mesh ${arg} ${pfx}BaseObjects) +cpPlugins_WrapInstances(ImageMeshFilters ${arg} ${pfx}ScalarImagesFilters ${pfx}Mesh) +cpPlugins_WrapInstances(MedialnessFilters ${arg} ${pfx}ScalarImages ${pfx}VectorImages) + +SET( + cpPlugins_Instances + ${pfx}BaseObjects + ${pfx}Paths + ${pfx}BaseImages + ${pfx}ScalarImages + ${pfx}NeighborhoodIterators + ${pfx}ColorImages + ${pfx}VectorImages + ${pfx}BaseImageFilters + ${pfx}ImageReaders + ${pfx}ImageWriters + ${pfx}ScalarImagesFilters + ${pfx}CastImageFilters + ${pfx}BitwiseImageFilters + ${pfx}MorphologicalImageFilters + ${pfx}ThresholdFilters + ${pfx}DistanceMapFilters + ${pfx}GaussianImageFilters + ${pfx}ExtractImageFilters + ${pfx}ResamplingFilters + ${pfx}Transforms + ${pfx}Mesh + ${pfx}ImageMeshFilters + ${pfx}MedialnessFilters + CACHE INTERNAL "All valid instances." FORCE + ) + +## eof - $RCSfile$ diff --git a/lib/Instances/CastImageFilters.i b/lib/Instances/CastImageFilters.i new file mode 100644 index 0000000..38eea6c --- /dev/null +++ b/lib/Instances/CastImageFilters.i @@ -0,0 +1,33 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #pixels=#ints;#uints;#floats +d #inputs=#pixels +d #outputs=#pixels +d #dims=1;2;3;4 +d #filters=CastImage + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_ScalarImages.h +t itk{#filters}Filter.h +t itkImageAlgorithm.h +t itkUnaryFunctorImageFilter.h + +* ================== +* == Dependencies == +* ================== + +* =============== +* == Instances == +* =============== + +c itk::{#filters}Filter< itk::Image< #inputs, #dims >, itk::Image< #outputs, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ColorImages.i b/lib/Instances/ColorImages.i new file mode 100644 index 0000000..838f28c --- /dev/null +++ b/lib/Instances/ColorImages.i @@ -0,0 +1,48 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #dims=1;2;3;4 +d #color_pixels=RGBPixel;RGBAPixel +d #it=ImageRegion;ImageScanline +d #it_wi=Image;ImageRegion;ImageLinear + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_BaseObjects.h +t itkImage.h +t itkImportImageContainer.h +t itkImageToVTKImageFilter.h +t itkVTKImageExport.h +t itk{#it}Iterator.h +t itk{#it}ConstIterator.h +t itk{#it_wi}IteratorWithIndex.h +t itk{#it_wi}ConstIteratorWithIndex.h + +* ================== +* == Dependencies == +* ================== + +c itk::ImportImageContainer< unsigned long, itk::#color_pixels< @{#ints;#uints;#floats} > > + +* =============== +* == Instances == +* =============== + +c itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, #dims > +c itk::ImageToVTKImageFilter< itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, @{2;3} > > + +* =============== +* == Iterators == +* =============== + +b #define ITK_LEGACY_REMOVE +c itk::{#it}@{Const;{}}Iterator< itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, #dims > > +c itk::{#it_wi}@{Const;{}}IteratorWithIndex< itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/DistanceMapFilters.i b/lib/Instances/DistanceMapFilters.i new file mode 100644 index 0000000..0eda54d --- /dev/null +++ b/lib/Instances/DistanceMapFilters.i @@ -0,0 +1,15 @@ +f cpPlugins_Instances_ScalarImagesFilters.h + +i itkProgressReporter.h +t itkBinaryContourImageFilter.h +t itkSignedMaurerDistanceMapImageFilter.h + +d #dims=2;3 +d #int=char;short;int;long +d #float=float;double +d #scalar=#int;unsigned #int;#float +d #filters=itk::BinaryContourImageFilter;itk::SignedMaurerDistanceMapImageFilter + +c #filters< itk::Image< #scalar, #dims >, itk::Image< #float, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ExtractImageFilters.i b/lib/Instances/ExtractImageFilters.i new file mode 100644 index 0000000..d4f10b7 --- /dev/null +++ b/lib/Instances/ExtractImageFilters.i @@ -0,0 +1,19 @@ +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #pixels=#ints;#uints;#floats +d #dims=2;3 + +f cpPlugins_Instances_ScalarImagesFilters.h +t cpExtensions/Algorithms/RegionOfInterestImageCalculator.h +t itkRegionOfInterestImageFilter.h +t itkImageAlgorithm.h + +* =========== +* = Filters = +* =========== + +c cpExtensions::Algorithms::RegionOfInterestImageCalculator< itk::Image< #pixels, #dims > > +c itk::RegionOfInterestImageFilter< itk::Image< #pixels, #dims >, itk::Image< #pixels, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/GaussianImageFilters.i b/lib/Instances/GaussianImageFilters.i new file mode 100644 index 0000000..b40b89d --- /dev/null +++ b/lib/Instances/GaussianImageFilters.i @@ -0,0 +1,26 @@ +f cpPlugins_Instances_ScalarImagesFilters.h +f cpPlugins_Instances_VectorImages.h + +t cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h +t itkGradientRecursiveGaussianImageFilter.h +t itkImageToImageFilter.h +t itkImageAdaptor.h +t itkRecursiveGaussianImageFilter.h +t itkRecursiveSeparableImageFilter.h +t itkInPlaceImageFilter.h +t itkUnaryFunctorImageFilter.h +t itkBinaryFunctorImageFilter.h +t itkImageRegionIteratorWithIndex.h +t itkImageConstIteratorWithIndex.h +t itkImageRegionConstIteratorWithIndex.h +t itkSimpleDataObjectDecorator.h + +d #dims=2;3 +d #int=char;short;int;long +d #float=float;double +d #scalar=#int;unsigned #int;#float +d #gradients=itk::CovariantVector + +c cpExtensions::Algorithms::MultiScaleGaussianImageFilter< itk::Image< #scalar, #dims >, itk::Image< #gradients< #float, #dims >, #dims > > + +** eof diff --git a/lib/Instances/ImageMeshFilters.i b/lib/Instances/ImageMeshFilters.i new file mode 100644 index 0000000..8e839bf --- /dev/null +++ b/lib/Instances/ImageMeshFilters.i @@ -0,0 +1,14 @@ +f cpPlugins_Instances_ScalarImages.h +f cpPlugins_Instances_Mesh.h + +t itkTriangleMeshToBinaryImageFilter.h + +d #dims=3 +d #int=char;short;int;long +d #uint=unsigned #int +d #pixels=#int;#uint +d #float=float;double + +c itk::TriangleMeshToBinaryImageFilter< itk::Mesh< #float, #dims >, itk::Image< #pixels, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ImageReaders.i b/lib/Instances/ImageReaders.i new file mode 100644 index 0000000..3f133e4 --- /dev/null +++ b/lib/Instances/ImageReaders.i @@ -0,0 +1,41 @@ +b #include +b #undef ITKIOImageBase_HIDDEN +b #define ITKIOImageBase_HIDDEN + +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #dims=1;2;3;4 +d #color_pixels=RGBPixel;RGBAPixel +d #vectors=CovariantVector;Point;Vector;SymmetricSecondRankTensor +d #src=File;Series + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_BaseImageFilters.h +t itkImage{#src}Reader.h +t itkConvertPixelBuffer.h +t itkSimpleDataObjectDecorator.h +t itkImageAlgorithm.h + +* ================== +* == Dependencies == +* ================== + +* =============== +* == Instances == +* =============== + +c itk::Image{#src}Reader< itk::Image< @{#ints;#uints;#floats}, #dims > > +c itk::Image{#src}Reader< itk::Image< std::complex< #floats >, #dims > > +c itk::Image{#src}Reader< itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, #dims > > +c itk::Image{#src}Reader< itk::Image< itk::#vectors< #floats, #dims >, #dims > > +c itk::Image{#src}Reader< itk::Image< itk::DiffusionTensor3D< #floats >, 3 > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ImageWriters.i b/lib/Instances/ImageWriters.i new file mode 100644 index 0000000..d8b3448 --- /dev/null +++ b/lib/Instances/ImageWriters.i @@ -0,0 +1,41 @@ +b #include +b #undef ITKIOImageBase_HIDDEN +b #define ITKIOImageBase_HIDDEN + +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #dims=1;2;3;4 +d #color_pixels=RGBPixel;RGBAPixel +d #vectors=CovariantVector;Point;Vector;SymmetricSecondRankTensor +d #src=File + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_BaseImageFilters.h +t itkImage{#src}Writer.h +* t itkConvertPixelBuffer.h +* t itkSimpleDataObjectDecorator.h +t itkImageAlgorithm.h + +* ================== +* == Dependencies == +* ================== + +* =============== +* == Instances == +* =============== + +c itk::Image{#src}Writer< itk::Image< @{#ints;#uints;#floats}, #dims > > +c itk::Image{#src}Writer< itk::Image< std::complex< #floats >, #dims > > +c itk::Image{#src}Writer< itk::Image< itk::#color_pixels< @{#ints;#uints;#floats} >, #dims > > +c itk::Image{#src}Writer< itk::Image< itk::#vectors< #floats, #dims >, #dims > > +c itk::Image{#src}Writer< itk::Image< itk::DiffusionTensor3D< #floats >, 3 > > + +* eof - $RCSfile$ diff --git a/lib/Instances/MedialnessFilters.i b/lib/Instances/MedialnessFilters.i new file mode 100644 index 0000000..8d4d94c --- /dev/null +++ b/lib/Instances/MedialnessFilters.i @@ -0,0 +1,22 @@ +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #pixels=#ints;#uints;#floats +d #dims=2;3 +d #functors=GulsunTek;Flux;MFlux + +i cpPlugins_Instances_ScalarImages.h +i cpPlugins_Instances_VectorImages.h +t itkImageFunction.h +t cpExtensions/Algorithms/GradientImageFunctionBase.h +t cpExtensions/Algorithms/{#functors}Medialness.h + +* =========== +* = Filters = +* =========== + +c itk::ImageFunction< itk::Image< itk::CovariantVector< #floats, #dims >, #dims >, #floats, #floats > +c cpExtensions::Algorithms::GradientImageFunctionBase< itk::Image< itk::CovariantVector< #floats, #dims >, #dims > > +c cpExtensions::Algorithms::{#functors}Medialness< itk::Image< itk::CovariantVector< #floats, #dims >, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/Mesh.i b/lib/Instances/Mesh.i new file mode 100644 index 0000000..66cc232 --- /dev/null +++ b/lib/Instances/Mesh.i @@ -0,0 +1,36 @@ +* ====================== +* == Some definitions == +* ====================== + +d #dims=2;3 +d #floats=float;double +d #objects=PointSet;Mesh +d #cells=Vertex;Line;Triangle;Polygon + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_BaseObjects.h +t itk{#objects}.h +t itk{#cells}Cell.h +t itkBoundingBox.h +t itkCellInterface.h +t itkMapContainer.h +t itkVectorContainer.h + +* ================== +* == Dependencies == +* ================== + +c itk::VectorContainer< unsigned long, itk::Point< #floats, #dims > > +c itk::BoundingBox< unsigned long, #dims, #floats, itk::VectorContainer< unsigned long, itk::Point< float, #dims > > > + +* =============== +* == Instances == +* =============== + +c itk::{#objects}< #floats, #dims > +c itk::{#cells}Cell< itk::Mesh< #floats, #dims >::CellType > + +* eof - $RCSfile$ diff --git a/lib/Instances/MorphologicalImageFilters.i b/lib/Instances/MorphologicalImageFilters.i new file mode 100644 index 0000000..c90d2cb --- /dev/null +++ b/lib/Instances/MorphologicalImageFilters.i @@ -0,0 +1,34 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #pixels=#ints;#uints;#floats +d #dims=1;2;3;4 +d #filters=BinaryDilateParaImage;BinaryErodeParaImage + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_ScalarImagesFilters.h +t itkParabolicErodeDilateImageFilter.h +t itk{#filters}Filter.h +t itkUnaryFunctorImageFilter.h + +* ================== +* == Dependencies == +* ================== + +c itk::UnaryFunctorImageFilter< itk::Image< #pixels, #dims >, itk::Image< double, #dims >, itk::Functor::GEConst< #pixels, double > > + +* =============== +* == Instances == +* =============== + +c itk::ParabolicErodeDilateImageFilter< itk::Image< double, #dims >, false, itk::Image< #pixels, #dims > > +c itk::{#filters}Filter< itk::Image< #pixels, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/NeighborhoodIterators.i b/lib/Instances/NeighborhoodIterators.i new file mode 100644 index 0000000..4445f38 --- /dev/null +++ b/lib/Instances/NeighborhoodIterators.i @@ -0,0 +1,22 @@ +f cpPlugins_Instances_ScalarImages.h + +t itkZeroFluxNeumannBoundaryCondition.h +t itkConstNeighborhoodIterator.h +t itkNeighborhoodIterator.h +t itkNeighborhood.h +t itkConstShapedNeighborhoodIterator.h +t itkShapedNeighborhoodIterator.h + +d #dims=1;2;3;4 +d #int=char;short;int;long +d #float=float;double +d #scalar=#int;unsigned #int;#float +d #pixels=#scalar;#color_pixels;#complex_pixels +d #conds=itk::ZeroFluxNeumannBoundaryCondition +d #neigh_iterators=itk::ConstNeighborhoodIterator;itk::NeighborhoodIterator;itk::ConstShapedNeighborhoodIterator;itk::ShapedNeighborhoodIterator + +c itk::Neighborhood< #pixels*, #dims, itk::NeighborhoodAllocator< #pixels* > > +c #conds< itk::Image< #scalar, #dims >, itk::Image< #scalar, #dims > > +c #neigh_iterators< itk::Image< #scalar, #dims >, #conds< itk::Image< #scalar, #dims >, itk::Image< #scalar, #dims > > > + +* eof - $RCSfile$ diff --git a/lib/Instances/Paths.i b/lib/Instances/Paths.i new file mode 100644 index 0000000..ebe407b --- /dev/null +++ b/lib/Instances/Paths.i @@ -0,0 +1,26 @@ +f cpPlugins_Instances_BaseObjects.h + +i cpExtensions/DataStructures/PolyLineParametricPath.h +i cpExtensions/DataStructures/ImageIndexesContainer.h +t itkPolyLineParametricPath.h +t itkPath.h +t itkParametricPath.h +t itkParametricPath.h +t itkVectorContainer.h +t cpExtensions/Visualization/PolyLineParametricPathToPolyData.h +t cpExtensions/Visualization/ImageIndexesContainerToPolyData.h +t itkSimpleDataObjectDecorator.h + +d #dims=2;3 + +c itk::SimpleDataObjectDecorator< std::vector< itk::Index< #dims > > > +c itk::VectorContainer< unsigned int, itk::ContinuousIndex< double, #dims > > + +c itk::ParametricPath< #dims > +c itk::PolyLineParametricPath< #dims > +c cpExtensions::DataStructures::ImageIndexesContainer< #dims > + +c cpExtensions::Visualization::PolyLineParametricPathToPolyData< cpExtensions::DataStructures::PolyLineParametricPath< #dims > > +c cpExtensions::Visualization::ImageIndexesContainerToPolyData< cpExtensions::DataStructures::ImageIndexesContainer< #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ResamplingFilters.i b/lib/Instances/ResamplingFilters.i new file mode 100644 index 0000000..4030f34 --- /dev/null +++ b/lib/Instances/ResamplingFilters.i @@ -0,0 +1,14 @@ +f cpPlugins_Instances_ScalarImagesFilters.h +f cpPlugins_Instances_Transforms.h + +t itkResampleImageFilter.h +t itkLinearInterpolateImageFunction.h +t itkImageFunction.h + +d #dims=2;3 +d #int=char;short;int;long +d #float=float;double +d #scalar=#int;unsigned #int;#float + +c itk::LinearInterpolateImageFunction< itk::Image< #scalar, #dims >, #float > +c itk::ResampleImageFilter< itk::Image< #scalar, #dims >, itk::Image< #scalar, #dims >, #float, #float > diff --git a/lib/Instances/ScalarImages.i b/lib/Instances/ScalarImages.i new file mode 100644 index 0000000..8349c86 --- /dev/null +++ b/lib/Instances/ScalarImages.i @@ -0,0 +1,51 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #dims=1;2;3;4 +d #it=ImageRegion;ImageScanline +d #it_wi=Image;ImageRegion;ImageLinear + +* ============== +* == Includes == +* ============== + +i complex +t itkImage.h +t itkImportImageContainer.h +t itkImageToVTKImageFilter.h +t itkVTKImageExport.h +t itk{#it}Iterator.h +t itk{#it}ConstIterator.h +t itk{#it_wi}IteratorWithIndex.h +t itk{#it_wi}ConstIteratorWithIndex.h + +* ================== +* == Dependencies == +* ================== + +c itk::ImportImageContainer< unsigned long, @{#ints;#uints;#floats} > +c itk::ImportImageContainer< unsigned long, std::complex< #floats > > + +* =============== +* == Instances == +* =============== + +c itk::Image< @{#ints;#uints;#floats}, #dims > +c itk::Image< std::complex< #floats >, #dims > +c itk::ImageToVTKImageFilter< itk::Image< @{#ints;#uints;#floats}, @{2;3} > > + +* =============== +* == Iterators == +* =============== + +b #define ITK_LEGACY_REMOVE +c itk::{#it}@{Const;{}}Iterator< itk::Image< @{#ints;#uints;#floats}, #dims > > +c itk::{#it_wi}@{Const;{}}IteratorWithIndex< itk::Image< @{#ints;#uints;#floats}, #dims > > +c itk::{#it}@{Const;{}}Iterator< itk::Image< std::complex< #floats >, #dims > > +c itk::{#it_wi}@{Const;{}}IteratorWithIndex< itk::Image< std::complex< #floats >, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ScalarImagesFilters.i b/lib/Instances/ScalarImagesFilters.i new file mode 100644 index 0000000..ae3a55d --- /dev/null +++ b/lib/Instances/ScalarImagesFilters.i @@ -0,0 +1,33 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #pixels=#ints;#uints;#floats +d #inputs=#pixels +d #outputs=#pixels +d #dims=1;2;3;4 +d #filters=ImageToImage;InPlaceImage + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_ScalarImages.h +t itk{#filters}Filter.h + +* ================== +* == Dependencies == +* ================== + +* =============== +* == Instances == +* =============== + +c itk::{#filters}Filter< itk::Image< #inputs, #dims >, itk::Image< #outputs, #dims > > +c itk::{#filters}Filter< itk::Image< #inputs, 3 >, itk::Image< #outputs, 2 > > +c itk::{#filters}Filter< itk::Image< #inputs, 2 >, itk::Image< #outputs, 3 > > + +* eof - $RCSfile$ diff --git a/lib/Instances/ThresholdFilters.i b/lib/Instances/ThresholdFilters.i new file mode 100644 index 0000000..e9e2150 --- /dev/null +++ b/lib/Instances/ThresholdFilters.i @@ -0,0 +1,34 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #pixels=#ints;#uints;#floats +d #inputs=#pixels +d #outputs=#pixels +d #dims=1;2;3;4 +d #filters=BinaryDilateParaImage;BinaryErodeParaImage + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_ScalarImagesFilters.h +t itkBinaryThresholdImageFilter.h +t itkUnaryFunctorImageFilter.h +t cpExtensions/Algorithms/UnaryThresholdImageFilter.h + +* ================== +* == Dependencies == +* ================== + +* =============== +* == Instances == +* =============== + +c itk::BinaryThresholdImageFilter< itk::Image< #inputs, #dims >, itk::Image< #outputs, #dims > > +c cpExtensions::Algorithms::UnaryThresholdImageFilter< itk::Image< #inputs, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/Transforms.i b/lib/Instances/Transforms.i new file mode 100644 index 0000000..c4df525 --- /dev/null +++ b/lib/Instances/Transforms.i @@ -0,0 +1,14 @@ +f cpPlugins_Instances_BaseObjects.h + +d #dims=2;3 +d #float=float;double + +t itkTransform.h +t itkOptimizerParameters.h +t itkDataObjectDecorator.h + +c itk::OptimizerParameters< #float > +c itk::Transform< #float, #dims, #dims > +c itk::DataObjectDecorator< itk::Transform< #float, #dims, #dims > > + +* eof - $RCSfile$ diff --git a/lib/Instances/VectorImages.i b/lib/Instances/VectorImages.i new file mode 100644 index 0000000..414ef3e --- /dev/null +++ b/lib/Instances/VectorImages.i @@ -0,0 +1,49 @@ +* ====================== +* == Some definitions == +* ====================== + +d #ints=char;short;int;long +d #uints=unsigned #ints +d #floats=float;double +d #dims=1;2;3;4 +d #vectors=CovariantVector;Point;Vector;SymmetricSecondRankTensor +d #it=ImageRegion;ImageScanline +d #it_wi=Image;ImageRegion;ImageLinear + +* ============== +* == Includes == +* ============== + +f cpPlugins_Instances_BaseObjects.h +t itkImage.h +t itkImportImageContainer.h +t itk{#it}Iterator.h +t itk{#it}ConstIterator.h +t itk{#it_wi}IteratorWithIndex.h +t itk{#it_wi}ConstIteratorWithIndex.h + +* ================== +* == Dependencies == +* ================== + +c itk::ImportImageContainer< unsigned long, itk::#vectors< #floats, #dims > > +c itk::ImportImageContainer< unsigned long, itk::DiffusionTensor3D< #floats > > + +* =============== +* == Instances == +* =============== + +c itk::Image< itk::#vectors< #floats, #dims >, #dims > +c itk::Image< itk::DiffusionTensor3D< #floats >, 3 > + +* =============== +* == Iterators == +* =============== + +b #define ITK_LEGACY_REMOVE +c itk::{#it}@{Const;{}}Iterator< itk::Image< itk::#vectors< #floats, #dims >, #dims > > +c itk::{#it_wi}@{Const;{}}IteratorWithIndex< itk::Image< itk::#vectors< #floats, #dims >, #dims > > +c itk::{#it}@{Const;{}}Iterator< itk::Image< itk::DiffusionTensor3D< #floats >, 3 > > +c itk::{#it_wi}@{Const;{}}IteratorWithIndex< itk::Image< itk::DiffusionTensor3D< #floats >, 3 > > + +* eof - $RCSfile$ diff --git a/lib/Itk2Vtk/itkImageToVTKImageFilter.h b/lib/Itk2Vtk/itkImageToVTKImageFilter.h new file mode 100644 index 0000000..9390eb8 --- /dev/null +++ b/lib/Itk2Vtk/itkImageToVTKImageFilter.h @@ -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 +class ImageToVTKImageFilter : public ProcessObject +{ +public: + /** Standard class typedefs. */ + typedef ImageToVTKImageFilter Self; + typedef ProcessObject Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer 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/Itk2Vtk/itkImageToVTKImageFilter.hxx b/lib/Itk2Vtk/itkImageToVTKImageFilter.hxx new file mode 100644 index 0000000..e134b3f --- /dev/null +++ b/lib/Itk2Vtk/itkImageToVTKImageFilter.hxx @@ -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 +ImageToVTKImageFilter +::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 +ImageToVTKImageFilter +::~ImageToVTKImageFilter() +{ + if( m_Importer ) + { + m_Importer->Delete(); + m_Importer = 0; + } +} + +/** + * Set an itk::Image as input + */ +template +void +ImageToVTKImageFilter +::SetInput( const InputImageType * inputImage ) +{ + m_Exporter->SetInput( inputImage ); +} + +template +typename ImageToVTKImageFilter::InputImageType * +ImageToVTKImageFilter +::GetInput() +{ + return m_Exporter->GetInput(); +} + +/** + * Get a vtkImage as output + */ +template +vtkImageData * +ImageToVTKImageFilter +::GetOutput() const +{ + return m_Importer->GetOutput(); +} + +/** + * Get the importer filter + */ +template +vtkImageImport * +ImageToVTKImageFilter +::GetImporter() const +{ + return m_Importer; +} + +/** + * Get the exporter filter + */ +template +typename ImageToVTKImageFilter::ExporterFilterType * +ImageToVTKImageFilter +::GetExporter() const +{ + return m_Exporter.GetPointer(); +} + +/** + * Delegate the Update to the importer + */ +template +void +ImageToVTKImageFilter +::Update() +{ + m_Importer->Update(); +} + +/** + * Delegate the UpdateLargestPossibleRegion to the importer + */ +template +void +ImageToVTKImageFilter +::UpdateLargestPossibleRegion() +{ + m_Importer->UpdateWholeExtent(); +} + +} // end namespace itk + +#endif diff --git a/lib/Itk2Vtk/itkVTKImageToImageFilter.h b/lib/Itk2Vtk/itkVTKImageToImageFilter.h new file mode 100644 index 0000000..b4427c8 --- /dev/null +++ b/lib/Itk2Vtk/itkVTKImageToImageFilter.h @@ -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 +class VTKImageToImageFilter : public VTKImageImport< TOutputImage > +{ +public: + /** Standard class typedefs. */ + typedef VTKImageToImageFilter Self; + typedef VTKImageImport< TOutputImage > Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer 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 ImageExportPointer; + ImageExportPointer m_Exporter; + +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkVTKImageToImageFilter.hxx" +#endif + +#endif diff --git a/lib/Itk2Vtk/itkVTKImageToImageFilter.hxx b/lib/Itk2Vtk/itkVTKImageToImageFilter.hxx new file mode 100644 index 0000000..334b02b --- /dev/null +++ b/lib/Itk2Vtk/itkVTKImageToImageFilter.hxx @@ -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 +VTKImageToImageFilter +::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 +VTKImageToImageFilter +::~VTKImageToImageFilter() +{ + if( m_Exporter ) + { + m_Exporter->Delete(); + m_Exporter = 0; + } +} + +/** + * Set a vtkImageData as input + */ +template +void +VTKImageToImageFilter +::SetInput( vtkImageData * inputImage ) +{ +#if VTK_MAJOR_VERSION <= 5 + m_Exporter->SetInput( inputImage ); +#else + m_Exporter->SetInputData( inputImage ); +#endif +} + +/** + * Get the exporter filter + */ +template +vtkImageExport * +VTKImageToImageFilter +::GetExporter() const +{ + return m_Exporter; +} + +/** + * Get the importer filter + */ +template +const typename VTKImageToImageFilter::Superclass * +VTKImageToImageFilter +::GetImporter() const +{ + return this; +} + +} // end namespace itk + +#endif diff --git a/lib/cpBaseQtApplication/ActorAxesProperties.cxx b/lib/cpBaseQtApplication/ActorAxesProperties.cxx new file mode 100644 index 0000000..a7c923f --- /dev/null +++ b/lib/cpBaseQtApplication/ActorAxesProperties.cxx @@ -0,0 +1,205 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorAxesProperties:: +ActorAxesProperties( QWidget* parent ) + : cpBaseQtApplication::ActorProperties( parent ), + m_UI( new Ui::ActorAxesProperties ) +{ + this->m_UI->setupUi( this ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorAxesProperties:: +~ActorAxesProperties( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorAxesProperties:: +addActor( vtkProp* obj ) +{ + auto actor = dynamic_cast< vtkAxesActor* >( obj ); + if( actor != NULL ) + { + this->m_Actors.insert( obj ); + if( this->m_Actors.size( ) == 1 ) + this->_updateWidgets( ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorAxesProperties:: +_updateWidgets( ) +{ + auto actor = + dynamic_cast< vtkAxesActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( actor == NULL ) + return; + + // Get properties + std::string xtext( actor->GetXAxisLabelText( ) ); + std::string ytext( actor->GetYAxisLabelText( ) ); + std::string ztext( actor->GetZAxisLabelText( ) ); + double scale = actor->GetScale( )[ 0 ]; + auto prop = actor->GetXAxisCaptionActor2D( )->GetCaptionTextProperty( ); + double rgb[ 3 ]; + prop->GetColor( rgb ); + rgb[ 0 ] *= double( 255 ); + rgb[ 1 ] *= double( 255 ); + rgb[ 2 ] *= double( 255 ); + + // Set widget values + auto palette = this->m_UI->TextColor->palette( ); + palette.setColor( + QPalette::Button, QColor( rgb[ 0 ], rgb[ 1 ], rgb[ 2 ] ) + ); + this->m_UI->TextColor->setAutoFillBackground( true ); + this->m_UI->TextColor->setPalette( palette ); + + this->m_UI->XText->setText( xtext.c_str( ) ); + this->m_UI->YText->setText( ytext.c_str( ) ); + this->m_UI->ZText->setText( ztext.c_str( ) ); + this->m_UI->Scale->setValue( scale ); + + // Connect stuff + this->connect( + this->m_UI->Scale, SIGNAL( valueChanged( double ) ), + this, SLOT( _Scale( double ) ) + ); + this->connect( + this->m_UI->XText, SIGNAL( textChanged( const QString& ) ), + this, SLOT( _TextChanged( const QString& ) ) + ); + this->connect( + this->m_UI->YText, SIGNAL( textChanged( const QString& ) ), + this, SLOT( _TextChanged( const QString& ) ) + ); + this->connect( + this->m_UI->ZText, SIGNAL( textChanged( const QString& ) ), + this, SLOT( _TextChanged( const QString& ) ) + ); + this->connect( + this->m_UI->TextColor, SIGNAL( clicked( ) ), + this, SLOT( _TextColor( ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorAxesProperties:: +_Scale( double v ) +{ + itk::Vector< double, 3 > x, y, z; + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkAxesActor* >( aIt->GetPointer( ) ); + auto matrix = ma->GetUserMatrix( ); + for( unsigned int d = 0; d < 3; ++d ) + { + x[ d ] = matrix->GetElement( d, 0 ); + y[ d ] = matrix->GetElement( d, 1 ); + z[ d ] = matrix->GetElement( d, 2 ); + + } // rof + auto nx = x.GetNorm( ); + auto ny = y.GetNorm( ); + auto nz = z.GetNorm( ); + if( nx > double( 0 ) ) x /= nx; + if( ny > double( 0 ) ) y /= ny; + if( nz > double( 0 ) ) z /= nz; + x *= v; + y *= v; + z *= v; + for( unsigned int d = 0; d < 3; ++d ) + { + matrix->SetElement( d, 0, x[ d ] ); + matrix->SetElement( d, 1, y[ d ] ); + matrix->SetElement( d, 2, z[ d ] ); + + } // rof + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorAxesProperties:: +_TextChanged( const QString& text ) +{ + auto obj = this->sender( ); + auto aIt = this->m_Actors.begin( ); + auto str = text.toStdString( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkAxesActor* >( aIt->GetPointer( ) ); + if( obj == this->m_UI->XText ) + ma->SetXAxisLabelText( str.c_str( ) ); + else if( obj == this->m_UI->YText ) + ma->SetYAxisLabelText( str.c_str( ) ); + else if( obj == this->m_UI->ZText ) + ma->SetZAxisLabelText( str.c_str( ) ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorAxesProperties:: +_TextColor( ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + QPalette pal = this->m_UI->TextColor->palette( ); + QColor color = + QColorDialog::getColor( + pal.color( QPalette::Button ), + this, + "Select Color", + QColorDialog::DontUseNativeDialog + ); + if( color.isValid( ) ) + { + pal.setColor( QPalette::Button, color ); + this->m_UI->TextColor->setAutoFillBackground( true ); + this->m_UI->TextColor->setPalette( pal ); + this->m_UI->TextColor->update( ); + + double rgb[ 3 ]; + rgb[ 0 ] = double( color.red( ) ) / double( 255 ); + rgb[ 1 ] = double( color.green( ) ) / double( 255 ); + rgb[ 2 ] = double( color.blue( ) ) / double( 255 ); + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkAxesActor* >( aIt->GetPointer( ) ); + ma->GetXAxisCaptionActor2D( )->GetCaptionTextProperty( )->SetColor( rgb ); + ma->GetYAxisCaptionActor2D( )->GetCaptionTextProperty( )->SetColor( rgb ); + ma->GetZAxisCaptionActor2D( )->GetCaptionTextProperty( )->SetColor( rgb ); + ma->GetXAxisCaptionActor2D( )->Modified( ); + ma->GetYAxisCaptionActor2D( )->Modified( ); + ma->GetZAxisCaptionActor2D( )->Modified( ); + ma->Modified( ); + + } // rof + this->_render( ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorAxesProperties.h b/lib/cpBaseQtApplication/ActorAxesProperties.h new file mode 100644 index 0000000..e56a2b1 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorAxesProperties.h @@ -0,0 +1,45 @@ +#ifndef __CPBASEQTAPPLICATION__ACTORAXESPROPERTIES__H__ +#define __CPBASEQTAPPLICATION__ACTORAXESPROPERTIES__H__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class ActorAxesProperties; +} + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + /** + */ + class cpBaseQtApplication_EXPORT ActorAxesProperties + : public ActorProperties + { + Q_OBJECT; + + public: + explicit ActorAxesProperties( QWidget* parent = 0 ); + virtual ~ActorAxesProperties( ); + + virtual bool addActor( vtkProp* obj ) ITK_OVERRIDE; + + protected: + virtual void _updateWidgets( ) ITK_OVERRIDE; + + protected slots: + void _Scale( double v ); + void _TextChanged( const QString& text ); + void _TextColor( ); + + protected: + Ui::ActorAxesProperties* m_UI; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__ACTORAXESPROPERTIES__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorAxesProperties.ui b/lib/cpBaseQtApplication/ActorAxesProperties.ui new file mode 100644 index 0000000..078f1bb --- /dev/null +++ b/lib/cpBaseQtApplication/ActorAxesProperties.ui @@ -0,0 +1,157 @@ + + + ActorAxesProperties + + + + 0 + 0 + 339 + 223 + + + + + 339 + 223 + + + + + 339 + 223 + + + + Form + + + + + + + + + 39 + 17 + + + + + 39 + 17 + + + + Scale: + + + + + + + 4 + + + 0.000100000000000 + + + 100000.000000000000000 + + + 1.000000000000000 + + + + + + + + + + + + 44 + 17 + + + + + 44 + 17 + + + + X text: + + + + + + + + + + + + + + + 44 + 17 + + + + + 44 + 17 + + + + Y text: + + + + + + + + + + + + + + + 43 + 17 + + + + + 43 + 17 + + + + Z text: + + + + + + + + + + + + Text color + + + + + + + + diff --git a/lib/cpBaseQtApplication/ActorImageProperties.cxx b/lib/cpBaseQtApplication/ActorImageProperties.cxx new file mode 100644 index 0000000..3aa94b6 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorImageProperties.cxx @@ -0,0 +1,241 @@ +#include + +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorImageProperties:: +ActorImageProperties( QWidget* parent ) + : cpBaseQtApplication::ActorProperties( parent ), + m_UI( new Ui::ActorImageProperties ) +{ + this->m_UI->setupUi( this ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorImageProperties:: +~ActorImageProperties( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorImageProperties:: +addActor( vtkProp* obj ) +{ + auto actor = dynamic_cast< vtkImageActor* >( obj ); + if( actor != NULL ) + { + this->m_Actors.insert( obj ); + if( this->m_Actors.size( ) == 1 ) + this->_updateWidgets( ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_updateWidgets( ) +{ + auto actor = + dynamic_cast< vtkImageActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( actor == NULL ) + return; + + // Get properties + auto prop = actor->GetProperty( ); + auto mapper = actor->GetMapper( ); + auto image = mapper->GetInput( ); + double r[ 2 ]; + image->GetScalarRange( r ); + double win = prop->GetColorWindow( ); + double lev = prop->GetColorLevel( ); + double op = prop->GetOpacity( ); + int interp = prop->GetInterpolationType( ); + + this->m_UI->ValueWindow->setMinimum( 0 ); + this->m_UI->ValueWindow->setMaximum( r[ 1 ] - r[ 0 ] ); + this->m_UI->ValueLevel->setMinimum( r[ 0 ] ); + this->m_UI->ValueLevel->setMaximum( r[ 1 ] ); + this->m_UI->ValueWindow->setValue( win ); + this->m_UI->ValueLevel->setValue( lev ); + + double w = win / ( r[ 1 ] - r[ 0 ] ); + double l = ( lev - r[ 0 ] ) / ( r[ 1 ] - r[ 0 ] ); + + op *= double( this->m_UI->Opacity->maximum( ) ); + this->m_UI->Opacity->setValue( int( op ) ); + + w *= double( this->m_UI->Window->maximum( ) ); + this->m_UI->Window->setValue( int( w ) ); + + l *= double( this->m_UI->Level->maximum( ) ); + this->m_UI->Level->setValue( int( l ) ); + + if( interp == VTK_CUBIC_INTERPOLATION ) + this->m_UI->Interpolation->setCurrentIndex( 0 ); + else if( interp == VTK_LINEAR_INTERPOLATION ) + this->m_UI->Interpolation->setCurrentIndex( 1 ); + else if( interp == VTK_NEAREST_INTERPOLATION ) + this->m_UI->Interpolation->setCurrentIndex( 2 ); + + // Connect stuff + this->connect( + this->m_UI->Opacity, SIGNAL( valueChanged( int ) ), + this, SLOT( _Opacity( int ) ) + ); + this->connect( + this->m_UI->Window, SIGNAL( valueChanged( int ) ), + this, SLOT( _Window( int ) ) + ); + this->connect( + this->m_UI->Level, SIGNAL( valueChanged( int ) ), + this, SLOT( _Level( int ) ) + ); + this->connect( + this->m_UI->ValueWindow, SIGNAL( valueChanged( double ) ), + this, SLOT( _Window( double ) ) + ); + this->connect( + this->m_UI->ValueLevel, SIGNAL( valueChanged( double ) ), + this, SLOT( _Level( double ) ) + ); + this->connect( + this->m_UI->Interpolation, SIGNAL( currentIndexChanged( int ) ), + this, SLOT( _Interpolation( int ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_Opacity( int v ) +{ + double op = double( v ) / double( this->m_UI->Opacity->maximum( ) ); + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetOpacity( op ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_Window( int v ) +{ + double x = this->m_UI->ValueWindow->minimum( ); + double y = this->m_UI->ValueWindow->maximum( ); + double z = double( v ) / double( this->m_UI->Window->maximum( ) ); + double w = ( ( y - x ) * z ) + x; + bool prev = this->m_UI->ValueWindow->blockSignals( true ); + this->m_UI->ValueWindow->setValue( w ); + this->m_UI->ValueWindow->blockSignals( prev ); + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetColorWindow( w ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_Level( int v ) +{ + double x = this->m_UI->ValueLevel->minimum( ); + double y = this->m_UI->ValueLevel->maximum( ); + double z = double( v ) / double( this->m_UI->Level->maximum( ) ); + double l = ( ( y - x ) * z ) + x; + bool prev = this->m_UI->ValueLevel->blockSignals( true ); + this->m_UI->ValueLevel->setValue( l ); + this->m_UI->ValueLevel->blockSignals( prev ); + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetColorLevel( l ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_Window( double v ) +{ + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetColorWindow( v ); + ma->Modified( ); + + } // rof + this->_render( ); + + double x = this->m_UI->ValueWindow->minimum( ); + double y = this->m_UI->ValueWindow->maximum( ); + double z = ( v - x ) / ( y - x ); + double w = double( z ) * double( this->m_UI->Window->maximum( ) ); + bool prev = this->m_UI->Window->blockSignals( true ); + this->m_UI->Window->setValue( int( w ) ); + this->m_UI->Window->blockSignals( prev ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_Level( double v ) +{ + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetColorLevel( v ); + ma->Modified( ); + + } // rof + this->_render( ); + + double x = this->m_UI->ValueLevel->minimum( ); + double y = this->m_UI->ValueLevel->maximum( ); + double z = ( v - x ) / ( y - x ); + double l = double( z ) * double( this->m_UI->Level->maximum( ) ); + bool prev = this->m_UI->Level->blockSignals( true ); + this->m_UI->Level->setValue( int( l ) ); + this->m_UI->Level->blockSignals( prev ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorImageProperties:: +_Interpolation( int v ) +{ + int interp = VTK_NEAREST_INTERPOLATION; + if ( v == 0 ) interp = VTK_CUBIC_INTERPOLATION; + else if( v == 1 ) interp = VTK_LINEAR_INTERPOLATION; + else if( v == 2 ) interp = VTK_NEAREST_INTERPOLATION; + + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetInterpolationType( interp ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorImageProperties.h b/lib/cpBaseQtApplication/ActorImageProperties.h new file mode 100644 index 0000000..4f50371 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorImageProperties.h @@ -0,0 +1,48 @@ +#ifndef __CPBASEQTAPPLICATION__ACTORIMAGEPROPERTIES__H__ +#define __CPBASEQTAPPLICATION__ACTORIMAGEPROPERTIES__H__ + +#include +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class ActorImageProperties; +} + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + /** + */ + class cpBaseQtApplication_EXPORT ActorImageProperties + : public ActorProperties + { + Q_OBJECT; + + public: + explicit ActorImageProperties( QWidget* parent = 0 ); + virtual ~ActorImageProperties( ); + + virtual bool addActor( vtkProp* obj ) ITK_OVERRIDE; + + protected: + virtual void _updateWidgets( ) ITK_OVERRIDE; + + protected slots: + void _Opacity( int v ); + void _Window( int v ); + void _Level( int v ); + void _Window( double v ); + void _Level( double v ); + void _Interpolation( int v ); + + protected: + Ui::ActorImageProperties* m_UI; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__ACTORIMAGEPROPERTIES__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorImageProperties.ui b/lib/cpBaseQtApplication/ActorImageProperties.ui new file mode 100644 index 0000000..249a055 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorImageProperties.ui @@ -0,0 +1,215 @@ + + + ActorImageProperties + + + + 0 + 0 + 626 + 158 + + + + + 626 + 158 + + + + + 626 + 158 + + + + Form + + + + + + + + + 92 + 17 + + + + + 92 + 17 + + + + Interpolation: + + + + + + + + Cubic + + + + + Linear + + + + + Nearest + + + + + + + + + + + + + 59 + 17 + + + + + 59 + 17 + + + + Window: + + + + + + + 4 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + 0 + + + 1000 + + + 0 + + + Qt::Horizontal + + + + + + + + + + + + 39 + 17 + + + + + 39 + 17 + + + + Level: + + + + + + + 4 + + + -100000.000000000000000 + + + 100000.000000000000000 + + + + + + + 0 + + + 1000 + + + 0 + + + Qt::Horizontal + + + + + + + + + + + + 55 + 17 + + + + + 55 + 17 + + + + Opacity: + + + + + + + 100 + + + 100 + + + Qt::Horizontal + + + + + + + + + + diff --git a/lib/cpBaseQtApplication/ActorPolyDataProperties.cxx b/lib/cpBaseQtApplication/ActorPolyDataProperties.cxx new file mode 100644 index 0000000..8da904f --- /dev/null +++ b/lib/cpBaseQtApplication/ActorPolyDataProperties.cxx @@ -0,0 +1,250 @@ +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorPolyDataProperties:: +ActorPolyDataProperties( QWidget* parent ) + : cpBaseQtApplication::ActorProperties( parent ), + m_UI( new Ui::ActorPolyDataProperties ) +{ + this->m_UI->setupUi( this ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorPolyDataProperties:: +~ActorPolyDataProperties( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorPolyDataProperties:: +addActor( vtkProp* obj ) +{ + auto actor = dynamic_cast< vtkActor* >( obj ); + if( actor != NULL ) + { + this->m_Actors.insert( obj ); + if( this->m_Actors.size( ) == 1 ) + this->_updateWidgets( ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_updateWidgets( ) +{ + auto actor = + dynamic_cast< vtkActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( actor == NULL ) + return; + + // Get properties + auto mapp = actor->GetMapper( ); + auto prop = actor->GetProperty( ); + double rgb[ 3 ]; + prop->GetColor( rgb ); + rgb[ 0 ] *= double( 255 ); + rgb[ 1 ] *= double( 255 ); + rgb[ 2 ] *= double( 255 ); + double op = prop->GetOpacity( ); + double lw = prop->GetLineWidth( ); + double ps = prop->GetPointSize( ); + bool sv = ( mapp->GetScalarVisibility( ) == 1 ); + int rep = prop->GetRepresentation( ); + + // Set widget values + auto palette = this->m_UI->Color->palette( ); + palette.setColor( + QPalette::Button, QColor( rgb[ 0 ], rgb[ 1 ], rgb[ 2 ] ) + ); + this->m_UI->Color->setAutoFillBackground( true ); + this->m_UI->Color->setPalette( palette ); + + op *= double( this->m_UI->Opacity->maximum( ) ); + this->m_UI->Opacity->setValue( int( op ) ); + this->m_UI->LineWidth->setValue( int( lw ) ); + this->m_UI->PointSize->setValue( int( ps ) ); + this->m_UI->ScalarVisibility->setChecked( sv ); + + if( rep == VTK_POINTS ) + this->m_UI->Representation->setCurrentIndex( 0 ); + else if( rep == VTK_WIREFRAME ) + this->m_UI->Representation->setCurrentIndex( 1 ); + else if( rep == VTK_SURFACE ) + this->m_UI->Representation->setCurrentIndex( 2 ); + + // Connect stuff + this->connect( + this->m_UI->ScalarVisibility, SIGNAL( stateChanged( int ) ), + this, SLOT( _ScalarVisibility( int ) ) + ); + this->connect( + this->m_UI->Color, SIGNAL( clicked( ) ), + this, SLOT( _Color( ) ) + ); + this->connect( + this->m_UI->Opacity, SIGNAL( valueChanged( int ) ), + this, SLOT( _Opacity( int ) ) + ); + this->connect( + this->m_UI->LineWidth, SIGNAL( valueChanged( int ) ), + this, SLOT( _LineWidth( int ) ) + ); + this->connect( + this->m_UI->PointSize, SIGNAL( valueChanged( int ) ), + this, SLOT( _PointSize( int ) ) + ); + this->connect( + this->m_UI->Representation, SIGNAL( currentIndexChanged( int ) ), + this, SLOT( _Representation( int ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_ScalarVisibility( int v ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + QPalette pal = this->m_UI->Color->palette( ); + QColor color = pal.color( QPalette::Button ); + double rgb[ 3 ]; + rgb[ 0 ] = double( color.red( ) ) / double( 255 ); + rgb[ 1 ] = double( color.green( ) ) / double( 255 ); + rgb[ 2 ] = double( color.blue( ) ) / double( 255 ); + + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + if( !( this->m_UI->ScalarVisibility->isChecked( ) ) ) + { + ma->GetMapper( )->ScalarVisibilityOff( ); + ma->GetProperty( )->SetColor( rgb ); + } + else + ma->GetMapper( )->ScalarVisibilityOn( ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_Color( ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + QPalette pal = this->m_UI->Color->palette( ); + QColor color = + QColorDialog::getColor( + pal.color( QPalette::Button ), + this, + "Select Color", + QColorDialog::DontUseNativeDialog + ); + if( color.isValid( ) ) + { + pal.setColor( QPalette::Button, color ); + this->m_UI->Color->setAutoFillBackground( true ); + this->m_UI->Color->setPalette( pal ); + this->m_UI->Color->update( ); + this->_ScalarVisibility( 0 ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_Opacity( int v ) +{ + double op = double( v ) / double( this->m_UI->Opacity->maximum( ) ); + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetOpacity( op ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_LineWidth( int v ) +{ + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetLineWidth( v ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_PointSize( int v ) +{ + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + ma->GetProperty( )->SetPointSize( v ); + ma->Modified( ); + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPolyDataProperties:: +_Representation( int v ) +{ + int rep = VTK_POINTS + VTK_WIREFRAME + VTK_SURFACE; + if ( v == 0 ) rep = VTK_POINTS; + else if( v == 1 ) rep = VTK_WIREFRAME; + else if( v == 2 ) rep = VTK_SURFACE; + + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + auto prop = ma->GetProperty( ); + if( rep != VTK_POINTS && rep != VTK_WIREFRAME && rep != VTK_SURFACE ) + { + double rgb[ 3 ]; + prop->GetColor( rgb ); + rgb[ 0 ] = double( 1 ) - rgb[ 0 ]; + rgb[ 1 ] = double( 1 ) - rgb[ 1 ]; + rgb[ 2 ] = double( 1 ) - rgb[ 2 ]; + prop->SetRepresentation( VTK_SURFACE ); + prop->SetEdgeColor( rgb ); + prop->EdgeVisibilityOn( ); + } + else + { + prop->EdgeVisibilityOff( ); + prop->SetRepresentation( rep ); + + } // fi + ma->Modified( ); + + } // rof + this->_render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorPolyDataProperties.h b/lib/cpBaseQtApplication/ActorPolyDataProperties.h new file mode 100644 index 0000000..00e47a5 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorPolyDataProperties.h @@ -0,0 +1,49 @@ +#ifndef __CPBASEQTAPPLICATION__ACTORPOLYDATAPROPERTIES__H__ +#define __CPBASEQTAPPLICATION__ACTORPOLYDATAPROPERTIES__H__ + +#include + +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class ActorPolyDataProperties; +} + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + /** + */ + class cpBaseQtApplication_EXPORT ActorPolyDataProperties + : public ActorProperties + { + Q_OBJECT; + + public: + explicit ActorPolyDataProperties( QWidget* parent = 0 ); + virtual ~ActorPolyDataProperties( ); + + virtual bool addActor( vtkProp* obj ) ITK_OVERRIDE; + + protected: + virtual void _updateWidgets( ) ITK_OVERRIDE; + + protected slots: + void _ScalarVisibility( int v ); + void _Color( ); + void _Opacity( int v ); + void _LineWidth( int v ); + void _PointSize( int v ); + void _Representation( int v ); + + protected: + Ui::ActorPolyDataProperties* m_UI; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__ACTORPOLYDATAPROPERTIES__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorPolyDataProperties.ui b/lib/cpBaseQtApplication/ActorPolyDataProperties.ui new file mode 100644 index 0000000..08ec1a8 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorPolyDataProperties.ui @@ -0,0 +1,233 @@ + + + ActorPolyDataProperties + + + + 0 + 0 + 398 + 193 + + + + + 398 + 193 + + + + + 398 + 193 + + + + Form + + + + + + + + + 107 + 17 + + + + + 107 + 17 + + + + Representation: + + + + + + + + Points + + + + + Wireframe + + + + + Surface + + + + + Surface with edges + + + + + + + + + + + + + 73 + 17 + + + + + 73 + 17 + + + + Line width: + + + + + + + 1 + + + 10 + + + 1 + + + Qt::Horizontal + + + + + + + + + + + + 68 + 17 + + + + + 68 + 17 + + + + Point size: + + + + + + + 1 + + + 10 + + + Qt::Horizontal + + + + + + + + + + + + 55 + 17 + + + + + 55 + 17 + + + + Opacity: + + + + + + + 100 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + + 135 + 22 + + + + + 135 + 22 + + + + Scalar visibility? + + + + + + + + 98 + 27 + + + + + 16777215 + 27 + + + + Color + + + + + + + + + + diff --git a/lib/cpBaseQtApplication/ActorProperties.cxx b/lib/cpBaseQtApplication/ActorProperties.cxx new file mode 100644 index 0000000..7c15f9b --- /dev/null +++ b/lib/cpBaseQtApplication/ActorProperties.cxx @@ -0,0 +1,34 @@ +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorProperties:: +ActorProperties( QWidget* parent ) + : QWidget( parent ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorProperties:: +~ActorProperties( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorProperties:: +addRenderWindow( vtkRenderWindow* win ) +{ + if( win == NULL ) + return( false ); + this->m_Windows.insert( win ); + return( true ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorProperties:: +_render( ) +{ + for( auto i = this->m_Windows.begin( ); i != this->m_Windows.end( ); ++i ) + ( *i )->Render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorProperties.h b/lib/cpBaseQtApplication/ActorProperties.h new file mode 100644 index 0000000..a6caec5 --- /dev/null +++ b/lib/cpBaseQtApplication/ActorProperties.h @@ -0,0 +1,57 @@ +#ifndef __CPBASEQTAPPLICATION__ACTORPROPERTIES__H__ +#define __CPBASEQTAPPLICATION__ACTORPROPERTIES__H__ + +#include +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +namespace cpBaseQtApplication +{ + /** + */ + class cpBaseQtApplication_EXPORT ActorProperties + : public QWidget + { + Q_OBJECT; + + public: + template< class _TObj > + struct TCmp + { + bool operator()( + const vtkSmartPointer< _TObj >& a, + const vtkSmartPointer< _TObj >& b ) const + { return( a.GetPointer( ) < b.GetPointer( ) ); } + }; + typedef vtkSmartPointer< vtkProp > TActor; + typedef vtkSmartPointer< vtkRenderWindow > TRenderWindow; + typedef std::set< TActor, TCmp< vtkProp > > TActors; + typedef std::set< TRenderWindow, TCmp< vtkRenderWindow > > TWindows; + + public: + explicit ActorProperties( QWidget* parent = 0 ); + virtual ~ActorProperties( ); + + virtual bool addActor( vtkProp* obj ) = 0; + bool addRenderWindow( vtkRenderWindow* win ); + void _render( ); + + protected: + virtual void _updateWidgets( ) = 0; + + protected: + TActors m_Actors; + TWindows m_Windows; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__ACTORPROPERTIES__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorPropertiesQDialog.cxx b/lib/cpBaseQtApplication/ActorPropertiesQDialog.cxx new file mode 100644 index 0000000..0a52ded --- /dev/null +++ b/lib/cpBaseQtApplication/ActorPropertiesQDialog.cxx @@ -0,0 +1,685 @@ +#include + +#include +#include +#include + +#include +#include +#include +/* + #include + #include + #include + #include + + #include + #include + #include + #include + #include +*/ + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorPropertiesQDialog:: +ActorPropertiesQDialog( QWidget* parent, Qt::WindowFlags f ) + : QDialog( parent, f ), + m_MainWidget( NULL ) +{ + this->m_Title = new QLabel( this ); + this->m_Title->setText( "Visualization properties" ); + 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 ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::ActorPropertiesQDialog:: +~ActorPropertiesQDialog( ) +{ +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorPropertiesQDialog:: +addActor( vtkProp* obj ) +{ + if( this->m_MainWidget == NULL ) + { + std::stringstream title; + title << "Parameters for an object of class"; + auto mesh = dynamic_cast< vtkActor* >( obj ); + auto axes = dynamic_cast< vtkAxesActor* >( obj ); + auto image = dynamic_cast< vtkImageActor* >( obj ); + if( mesh != NULL ) + { + title << "\"Mesh\""; + this->m_MainWidget = new cpBaseQtApplication::ActorPolyDataProperties( this ); + } + else if( axes != NULL ) + { + title << "\"Axes\""; + this->m_MainWidget = new cpBaseQtApplication::ActorAxesProperties( this ); + } + else if( image != NULL ) + { + title << "\"Image\""; + this->m_MainWidget = new cpBaseQtApplication::ActorImageProperties( this ); + } + /* TODO + else if( axes != NULL ) + */ + + if( this->m_MainWidget != NULL ) + { + this->m_Title->setText( title.str( ).c_str( ) ); + this->m_ToolsLayout->addWidget( this->m_MainWidget ); + this->m_Buttons = new QDialogButtonBox( QDialogButtonBox::Ok ); + 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 ); + + } // fi + + } // fi + + if( this->m_MainWidget != NULL ) + return( this->m_MainWidget->addActor( obj ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorPropertiesQDialog:: +addRenderWindow( vtkRenderWindow* win ) +{ + if( this->m_MainWidget != NULL && win != NULL ) + return( this->m_MainWidget->addRenderWindow( win ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +int cpBaseQtApplication::ActorPropertiesQDialog:: +exec( ) +{ + int ret = this->QDialog::exec( ); + /* TODO + if( ret == 1 ) + this->updateParameters( ); + else + this->updateView( ); + */ + return( ret ); +} + +// ------------------------------------------------------------------------- +/* TODO +void cpBaseQtApplication::ActorPropertiesQDialog:: +_addButtons( ) +{ + // Add buttons + this->m_Buttons = new QDialogButtonBox( QDialogButtonBox::Ok ); + 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->m_WidgetsUpdated = true; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_updateWidgets( ) +{ + if( this->m_WidgetsUpdated || this->m_Actors.size( ) == 0 ) + return; + bool s = this->_configureForAxes( ); + if( !s ) s = this->_configureForImage( ); + if( !s ) s = this->_configureForMesh( ); + this->_addButtons( ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorPropertiesQDialog:: +_configureForAxes( ) +{ + if( this->m_Actors.size( ) == 0 ) + return( false ); + auto actor = + dynamic_cast< vtkAxesActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( actor == NULL ) + return( false ); + + // Set dialog title + std::stringstream title; + title << "Parameters for an object of class \"Axes\""; + this->m_Title->setText( title.str( ).c_str( ) ); + + return( true ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorPropertiesQDialog:: +_configureForImage( ) +{ + if( this->m_Actors.size( ) == 0 ) + return( false ); + auto actor = + dynamic_cast< vtkImageActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( actor == NULL ) + return( false ); + auto image = actor->GetInput( ); + if( image == NULL ) + return( false ); + + // Get properties + auto prop = actor->GetProperty( ); + double r[ 2 ]; + image->GetScalarRange( r ); + double w = actor->GetProperty( )->GetColorWindow( ); + double l = actor->GetProperty( )->GetColorLevel( ); + double sw = double( 1000 ) * w / ( r[ 1 ] - r[ 0 ] ); + double sl = double( 1000 ) * ( l - r[ 0 ] ) / ( r[ 1 ] - r[ 0 ] ); + double op = double( 10 ) * prop->GetOpacity( ); + + // Set dialog title + std::stringstream title; + title << "Parameters for an object of class \"Image\""; + this->m_Title->setText( title.str( ).c_str( ) ); + + // Create widgets + QDoubleSpinBox* win_box = new QDoubleSpinBox( this ); + win_box->setObjectName( "win_box" ); + win_box->setDecimals( 3 ); + win_box->setMinimum( 0 ); + win_box->setMaximum( r[ 1 ] - r[ 0 ] ); + win_box->setValue( w ); + win_box->connect( + win_box, SIGNAL( valueChanged( double ) ), + this, SLOT( _boxWindow( double ) ) + ); + + QSlider* win_sld = new QSlider( Qt::Horizontal, this ); + win_sld->setObjectName( "win_sld" ); + win_sld->setRange( 0, 1000 ); + win_sld->setValue( ( unsigned int )( sw ) ); + win_sld->connect( + win_sld, SIGNAL( valueChanged( int ) ), + this, SLOT( _sldWindow( int ) ) + ); + + QHBoxLayout* win_layout = new QHBoxLayout( ); + QLabel* win_label = new QLabel( this ); + win_label->setText( QString( "Window: " ) ); + win_layout->addWidget( win_label ); + win_layout->addWidget( win_box ); + win_layout->addWidget( win_sld ); + this->m_ToolsLayout->addLayout( win_layout ); + + QDoubleSpinBox* lev_box = new QDoubleSpinBox( this ); + lev_box->setObjectName( "lev_box" ); + lev_box->setDecimals( 3 ); + lev_box->setMinimum( r[ 0 ] ); + lev_box->setMaximum( r[ 1 ] ); + lev_box->setValue( l ); + lev_box->connect( + lev_box, SIGNAL( valueChanged( double ) ), + this, SLOT( _boxLevel( double ) ) + ); + + QSlider* lev_sld = new QSlider( Qt::Horizontal, this ); + lev_sld->setObjectName( "lev_sld" ); + lev_sld->setRange( 0, 1000 ); + lev_sld->setValue( ( unsigned int )( sl ) ); + lev_sld->connect( + lev_sld, SIGNAL( valueChanged( int ) ), + this, SLOT( _sldLevel( int ) ) + ); + + QHBoxLayout* lev_layout = new QHBoxLayout( ); + QLabel* lev_label = new QLabel( this ); + lev_label->setText( QString( "Level: " ) ); + lev_layout->addWidget( lev_label ); + lev_layout->addWidget( lev_box ); + lev_layout->addWidget( lev_sld ); + this->m_ToolsLayout->addLayout( lev_layout ); + + // Configure generic objects + QSlider* op_sld = new QSlider( Qt::Horizontal, this ); + op_sld->setObjectName( "op_sld" ); + op_sld->setRange( 0, 10 ); + op_sld->setValue( ( unsigned int )( op ) ); + op_sld->connect( + op_sld, SIGNAL( valueChanged( int ) ), + this, SLOT( _sldOpacity( int ) ) + ); + + QHBoxLayout* op_layout = new QHBoxLayout( ); + QLabel* op_label = new QLabel( this ); + op_label->setText( QString( "Opacity: " ) ); + op_layout->addWidget( op_label ); + op_layout->addWidget( op_sld ); + this->m_ToolsLayout->addLayout( op_layout ); + + return( true ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::ActorPropertiesQDialog:: +_configureForMesh( ) +{ + if( this->m_Actors.size( ) == 0 ) + return( false ); + auto actor = + dynamic_cast< vtkActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( actor == NULL ) + return( false ); + auto prop = actor->GetProperty( ); + + // Set dialog title + std::stringstream title; + title << "Parameters for an object of class \"Mesh\""; + this->m_Title->setText( title.str( ).c_str( ) ); + + // Input boxes + QSpinBox* ps_box = new QSpinBox( this ); + ps_box->setObjectName( "ps_box" ); + ps_box->setMinimum( 1 ); + ps_box->setMaximum( 100 ); + ps_box->setValue( prop->GetPointSize( ) ); + ps_box->connect( + ps_box, SIGNAL( valueChanged( int ) ), + this, SLOT( _boxPointSize( int ) ) + ); + + QHBoxLayout* ps_layout = new QHBoxLayout( ); + QLabel* ps_label = new QLabel( this ); + ps_label->setText( QString( "Point size: " ) ); + ps_layout->addWidget( ps_label ); + ps_layout->addWidget( ps_box ); + this->m_ToolsLayout->addLayout( ps_layout ); + + QSpinBox* lw_box = new QSpinBox( this ); + lw_box->setObjectName( "lw_box" ); + lw_box->setMinimum( 1 ); + lw_box->setMaximum( 100 ); + lw_box->setValue( prop->GetLineWidth( ) ); + lw_box->connect( + lw_box, SIGNAL( valueChanged( int ) ), + this, SLOT( _boxLineWidth( int ) ) + ); + + QHBoxLayout* lw_layout = new QHBoxLayout( ); + QLabel* lw_label = new QLabel( this ); + lw_label->setText( QString( "Line width: " ) ); + lw_layout->addWidget( lw_label ); + lw_layout->addWidget( lw_box ); + this->m_ToolsLayout->addLayout( lw_layout ); + + QCheckBox* sv_box = new QCheckBox( this ); + sv_box->setObjectName( "sv_box" ); + sv_box->setText( "Scalar visibility: " ); + sv_box->setChecked( ( actor->GetMapper( )->GetScalarVisibility( ) == 1 ) ); + sv_box->connect( + sv_box, SIGNAL( stateChanged( int ) ), + this, SLOT( _scalarVisibility( int ) ) + ); + + QHBoxLayout* sv_layout = new QHBoxLayout( ); + sv_layout->addWidget( sv_box ); + this->m_ToolsLayout->addLayout( sv_layout ); + + double cr, cg, cb; + prop->GetColor( cr, cg, cb ); + cr *= double( 255 ); + cg *= double( 255 ); + cb *= double( 255 ); + + QPushButton* color_button = new QPushButton( "Color", this ); + color_button->setObjectName( "color_button" ); + QPalette color_palette = color_button->palette( ); + color_palette.setColor( QPalette::Button, QColor( cr, cg, cb ) ); + color_button->setAutoFillBackground( true ); + color_button->setPalette( color_palette ); + color_button->update( ); + color_button->connect( + color_button, SIGNAL( clicked( ) ), + this, SLOT( _color( ) ) + ); + + QHBoxLayout* color_layout = new QHBoxLayout( ); + color_layout->addWidget( color_button ); + this->m_ToolsLayout->addLayout( color_layout ); + + // Configure generic objects + QSlider* op_sld = new QSlider( Qt::Horizontal, this ); + op_sld->setObjectName( "op_sld" ); + op_sld->setRange( 0, 10 ); + op_sld->setValue( + ( unsigned int )( prop->GetOpacity( ) * double( 10 ) ) + ); + op_sld->connect( + op_sld, SIGNAL( valueChanged( int ) ), + this, SLOT( _sldOpacity( int ) ) + ); + + QHBoxLayout* op_layout = new QHBoxLayout( ); + QLabel* op_label = new QLabel( this ); + op_label->setText( QString( "Opacity: " ) ); + op_layout->addWidget( op_label ); + op_layout->addWidget( op_sld ); + this->m_ToolsLayout->addLayout( op_layout ); + + return( true ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_setWindow( double w ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto actor = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + if( actor != NULL ) + { + actor->GetProperty( )->SetColorWindow( w ); + actor->Modified( ); + + } // fi + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_setLevel( double l ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto actor = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + if( actor != NULL ) + { + actor->GetProperty( )->SetColorLevel( l ); + actor->Modified( ); + + } // fi + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_render( ) +{ + for( auto i = this->m_Windows.begin( ); i != this->m_Windows.end( ); ++i ) + ( *i )->Render( ); +} + +// ------------------------------------------------------------------------- +template< class _TActor > +bool cpBaseQtApplication::ActorPropertiesQDialog:: +_addActor( vtkProp* obj ) +{ + auto new_obj = dynamic_cast< _TActor* >( obj ); + auto pre_obj = + dynamic_cast< _TActor* >( this->m_Actors.begin( )->GetPointer( ) ); + if( new_obj != NULL && pre_obj != NULL ) + { + this->m_Actors.insert( obj ); + this->m_WidgetsUpdated = false; + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_boxWindow( double v ) +{ + auto* box = this->findChild< QDoubleSpinBox* >( "win_box" ); + auto* sld = this->findChild< QSlider* >( "win_sld" ); + if( box == NULL || sld == NULL ) + return; + + double min = double( sld->minimum( ) ); + double max = double( sld->maximum( ) ); + double vmin = box->minimum( ); + double vmax = box->maximum( ); + double s = ( v - vmin ) / ( vmax - vmin ); + s = ( ( max - min ) * s ) + min; + + bool o = sld->blockSignals( true ); + sld->setValue( ( unsigned int )( s ) ); + sld->blockSignals( o ); + this->_setWindow( v ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_sldWindow( int v ) +{ + auto* box = this->findChild< QDoubleSpinBox* >( "win_box" ); + auto* sld = this->findChild< QSlider* >( "win_sld" ); + if( box == NULL || sld == NULL ) + return; + + double min = double( sld->minimum( ) ); + double max = double( sld->maximum( ) ); + double vmin = box->minimum( ); + double vmax = box->maximum( ); + double s = ( double( v ) - min ) / ( max - min ); + s = ( ( vmax - vmin ) * s ) + vmin; + + bool o = box->blockSignals( true ); + box->setValue( s ); + box->blockSignals( o ); + this->_setWindow( s ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_boxLevel( double v ) +{ + auto* box = this->findChild< QDoubleSpinBox* >( "lev_box" ); + auto* sld = this->findChild< QSlider* >( "lev_sld" ); + if( box == NULL || sld == NULL ) + return; + + double min = double( sld->minimum( ) ); + double max = double( sld->maximum( ) ); + double vmin = box->minimum( ); + double vmax = box->maximum( ); + double s = ( v - vmin ) / ( vmax - vmin ); + s = ( ( max - min ) * s ) + min; + + bool o = sld->blockSignals( true ); + sld->setValue( ( unsigned int )( s ) ); + sld->blockSignals( o ); + this->_setLevel( v ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_sldLevel( int v ) +{ + auto* box = this->findChild< QDoubleSpinBox* >( "lev_box" ); + auto* sld = this->findChild< QSlider* >( "lev_sld" ); + if( box == NULL || sld == NULL ) + return; + + double min = double( sld->minimum( ) ); + double max = double( sld->maximum( ) ); + double vmin = box->minimum( ); + double vmax = box->maximum( ); + double s = ( double( v ) - min ) / ( max - min ); + s = ( ( vmax - vmin ) * s ) + vmin; + + bool o = box->blockSignals( true ); + box->setValue( s ); + box->blockSignals( o ); + this->_setLevel( s ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_sldOpacity( int v ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto* sld = this->findChild< QSlider* >( "op_sld" ); + if( sld == NULL ) + return; + + double min = double( sld->minimum( ) ); + double max = double( sld->maximum( ) ); + double s = ( double( v ) - min ) / ( max - min ); + + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ia = dynamic_cast< vtkImageActor* >( aIt->GetPointer( ) ); + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + if( ia != NULL ) + { + ia->GetProperty( )->SetOpacity( s ); + ia->Modified( ); + } + else if( ma != NULL ) + { + ma->GetProperty( )->SetOpacity( s ); + ma->Modified( ); + + } // fi + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_boxPointSize( int v ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + if( ma != NULL ) + { + ma->GetProperty( )->SetPointSize( v ); + ma->Modified( ); + + } // fi + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_boxLineWidth( int v ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + if( ma != NULL ) + { + ma->GetProperty( )->SetLineWidth( v ); + ma->Modified( ); + + } // fi + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_scalarVisibility( int v ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto* btn = this->findChild< QPushButton* >( "color_button" ); + auto* chk = this->findChild< QCheckBox* >( "sv_box" ); + if( btn == NULL || chk == NULL ) + return; + QPalette pal = btn->palette( ); + QColor color = pal.color( QPalette::Button ); + double rgb[ 3 ]; + rgb[ 0 ] = double( color.red( ) ) / double( 255 ); + rgb[ 1 ] = double( color.green( ) ) / double( 255 ); + rgb[ 2 ] = double( color.blue( ) ) / double( 255 ); + + auto aIt = this->m_Actors.begin( ); + for( ; aIt != this->m_Actors.end( ); ++aIt ) + { + auto ma = dynamic_cast< vtkActor* >( aIt->GetPointer( ) ); + if( ma != NULL ) + { + if( !( chk->isChecked( ) ) ) + { + ma->GetMapper( )->ScalarVisibilityOff( ); + ma->GetProperty( )->SetColor( rgb ); + } + else + ma->GetMapper( )->ScalarVisibilityOn( ); + ma->Modified( ); + + } // fi + + } // rof + this->_render( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::ActorPropertiesQDialog:: +_color( ) +{ + if( this->m_Actors.size( ) == 0 ) + return; + auto* btn = this->findChild< QPushButton* >( "color_button" ); + auto* chk = this->findChild< QCheckBox* >( "sv_box" ); + if( btn == NULL || chk == NULL ) + return; + + QPalette pal = btn->palette( ); + QColor color = + QColorDialog::getColor( + pal.color( QPalette::Button ), + this, + "Select Color", + QColorDialog::DontUseNativeDialog + ); + if( color.isValid( ) ) + { + pal.setColor( QPalette::Button, color ); + btn->setAutoFillBackground( true ); + btn->setPalette( pal ); + btn->update( ); + this->_scalarVisibility( 0 ); + + } // fi +} +*/ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/ActorPropertiesQDialog.h b/lib/cpBaseQtApplication/ActorPropertiesQDialog.h new file mode 100644 index 0000000..c6e6a7e --- /dev/null +++ b/lib/cpBaseQtApplication/ActorPropertiesQDialog.h @@ -0,0 +1,99 @@ +#ifndef __CPBASEQTAPPLICATION__ACTORPROPERTIESQDIALOG__H__ +#define __CPBASEQTAPPLICATION__ACTORPROPERTIESQDIALOG__H__ + +#include + +#include +#include +#include +#include +#include +/* + #include + #include + #include + #include + + #include + + class vtkProp; +*/ + +namespace cpBaseQtApplication +{ + /** + */ + class cpBaseQtApplication_EXPORT ActorPropertiesQDialog + : public QDialog + { + Q_OBJECT; + + public: + ActorPropertiesQDialog( + QWidget* parent = 0, Qt::WindowFlags f = 0 + ); + virtual ~ActorPropertiesQDialog( ); + + virtual bool addActor( vtkProp* obj ); + virtual bool addRenderWindow( vtkRenderWindow* win ); + virtual int exec( ); + + protected: + /* TODO + virtual void _addButtons( ); + virtual void _updateWidgets( ); + + virtual bool _configureForAxes( ); + virtual bool _configureForImage( ); + virtual bool _configureForMesh( ); + + void _setWindow( double w ); + void _setLevel( double l ); + void _render( ); + + template< class _TActor > + inline bool _addActor( vtkProp* obj ); + + protected slots: + void _boxWindow( double v ); + void _sldWindow( int v ); + void _boxLevel( double v ); + void _sldLevel( int v ); + void _sldOpacity( int v ); + void _boxPointSize( int v ); + void _boxLineWidth( int v ); + void _scalarVisibility( int v ); + void _color( ); + */ + + /* TODO + virtual void updateParameters( ); + virtual void updateView( ); + + protected: + virtual void _addButtons( ); + virtual void _updateWidgets( ); + + protected slots: + 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: + cpBaseQtApplication::ActorProperties* m_MainWidget; + QLabel* m_Title; + QGridLayout* m_MainLayout; + QVBoxLayout* m_ToolsLayout; + QDialogButtonBox* m_Buttons; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__ACTORPROPERTIESQDIALOG__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Block.cxx b/lib/cpBaseQtApplication/Block.cxx new file mode 100644 index 0000000..77a8e56 --- /dev/null +++ b/lib/cpBaseQtApplication/Block.cxx @@ -0,0 +1,317 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Block:: +Block( + TFilter* filter, const QString& name, + QGraphicsItem* parent, QGraphicsScene* scene + ) + : Superclass( parent, scene ), + m_HorzMargin( 20 ), + m_VertMargin( 5 ), + m_NamePort( NULL ), + m_Filter( filter ), + m_Editor( NULL ) +{ + QPainterPath p; + p.addRoundedRect( -50, -15, 100, 30, 5, 5 ); + + this->setPath( p ); + this->setPen( QPen( Qt::darkGreen ) ); + this->setBrush( Qt::green ); + this->setFlag( QGraphicsItem::ItemIsMovable ); + this->setFlag( QGraphicsItem::ItemIsSelectable ); + + this->m_Width = this->m_HorzMargin; + this->m_Height = this->m_VertMargin; + + // Configure names + this->setNamePort( name ); + this->_setTypeInfo( this->m_Filter->GetClassName( ) ); + + // Add input ports + auto inputs = this->m_Filter->GetInputsNames( ); + for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt ) + this->addInputPort( iIt->c_str( ) ); + + // Add output ports + auto outputs = this->m_Filter->GetOutputsNames( ); + for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt ) + this->addOutputPort( oIt->c_str( ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Block:: +~Block( ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Block:: +TFilter* cpBaseQtApplication::Block:: +filter( ) +{ + return( this->m_Filter ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Block:: +TFilter* cpBaseQtApplication::Block:: +filter( ) const +{ + return( this->m_Filter ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Editor* cpBaseQtApplication::Block:: +editor( ) +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Editor* cpBaseQtApplication::Block:: +editor( ) const +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +setEditor( cpBaseQtApplication::Editor* editor ) +{ + this->m_Editor = editor; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +setNamePort( const QString& txt ) +{ + if( this->m_NamePort == NULL ) + this->m_NamePort = new NamePort( this ); + this->m_NamePort->setName( txt ); + this->_configPort( this->m_NamePort ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::InputPort* cpBaseQtApplication::Block:: +addInputPort( const QString& txt ) +{ + InputPort* ip = new InputPort( this ); + ip->setExtendedName( + ( + txt.toStdString( ) + + std::string( "@" ) + + this->namePort( ).toStdString( ) + ).c_str( ) + ); + ip->setName( txt ); + this->m_InputPorts[ txt.toStdString( ) ] = ip; + this->_configPort( ip ); + return( ip ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::OutputPort* cpBaseQtApplication::Block:: +addOutputPort( const QString& txt ) +{ + OutputPort* op = new OutputPort( this ); + op->setExtendedName( + ( + txt.toStdString( ) + + std::string( "@" ) + + this->namePort( ).toStdString( ) + ).c_str( ) + ); + op->setName( txt ); + this->m_OutputPorts[ txt.toStdString( ) ] = op; + this->_configPort( op ); + return( op ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::InputPort* cpBaseQtApplication::Block:: +inputPort( const QString& txt ) +{ + auto i = this->m_InputPorts.find( txt.toStdString( ) ); + if( i != this->m_InputPorts.end( ) ) + return( i->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::OutputPort* cpBaseQtApplication::Block:: +outputPort( const QString& txt ) +{ + auto o = this->m_OutputPorts.find( txt.toStdString( ) ); + if( o != this->m_OutputPorts.end( ) ) + return( o->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +QString cpBaseQtApplication::Block:: +namePort( ) const +{ + return( this->m_NamePort->name( ) ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::InputPort* cpBaseQtApplication::Block:: +inputPort( const QString& txt ) const +{ + auto i = this->m_InputPorts.find( txt.toStdString( ) ); + if( i != this->m_InputPorts.end( ) ) + return( i->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::OutputPort* cpBaseQtApplication::Block:: +outputPort( const QString& txt ) const +{ + auto o = this->m_OutputPorts.find( txt.toStdString( ) ); + if( o != this->m_OutputPorts.end( ) ) + return( o->second ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +paint( + QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget + ) +{ + Q_UNUSED( option ); + Q_UNUSED( widget ); + + if( this->isSelected( ) ) + { + painter->setPen( QPen( Qt::darkYellow ) ); + painter->setBrush( Qt::yellow ); + } + else + { + painter->setPen( QPen( Qt::darkGreen ) ); + painter->setBrush( Qt::green ); + + } // fi + painter->drawPath( this->path( ) ); +} + +// ------------------------------------------------------------------------- +QVariant cpBaseQtApplication::Block:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + return( value ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +_setTypeInfo( const QString& txt ) +{ + this->setToolTip( txt ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +_configPort( Port* port ) +{ + port->setBlock( this ); + + QFontMetrics fm( this->scene( )->font( ) ); + this->m_Width = 0; + foreach( QGraphicsItem* i, this->children( ) ) + { + Port* p = dynamic_cast< Port* >( i ); + if( p == NULL ) + continue; + int w = fm.width( p->name( ) ) + ( 4 * p->radius( ) ); + if( w > this->m_Width - this->m_HorzMargin ) + this->m_Width = w + this->m_HorzMargin; + + } // rof + int h = fm.height( ); + this->m_Height = this->m_InputPorts.size( ) + this->m_OutputPorts.size( ); + this->m_Height += 3; + this->m_Height *= h; + + QPainterPath pth; + pth.addRoundedRect( + -this->m_Width / 2, + -this->m_Height / 2, + this->m_Width, + this->m_Height, 5, 5 + ); + this->setPath( pth ); + + int y = -this->m_Height / 2 + this->m_VertMargin + port->radius( ); + foreach( QGraphicsItem* i, this->children( ) ) + { + Port* p = dynamic_cast< Port* >( i ); + if( p == NULL ) + continue; + + if( dynamic_cast< NamePort* >( i ) != NULL ) + { + i->setPos( -this->m_Width / 2 + port->radius( ), y ); + y += h; + } + else if( dynamic_cast< InputPort* >( i ) != NULL ) + i->setPos( -this->m_Width / 2 - 2 * port->radius( ), y ); + else if( dynamic_cast< OutputPort* >( i ) != NULL ) + i->setPos( this->m_Width / 2, y ); + y += h; + + } // rof +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +mouseReleaseEvent( QGraphicsSceneMouseEvent* evt ) +{ + if( this->m_Filter != NULL ) + this->m_Filter->SetViewCoords( + this->scenePos( ).x( ), this->scenePos( ).y( ) + ); + this->Superclass::mouseReleaseEvent( evt ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Block:: +contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ) +{ + QMenu menu; + QAction* configureAction = menu.addAction( "Configure" ); + QAction* updateAction = menu.addAction( "Update" ); + QAction* selectedAction = menu.exec( evt->screenPos( ) ); + + if( selectedAction == configureAction ) + { + auto dlg = this->m_Filter->CreateQDialog( ); + if( dlg != NULL ) + dlg->exec( ); + } + else if( selectedAction == updateAction ) + this->m_Editor->updateFilter( this->namePort( ).toStdString( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Block.h b/lib/cpBaseQtApplication/Block.h new file mode 100644 index 0000000..920adbb --- /dev/null +++ b/lib/cpBaseQtApplication/Block.h @@ -0,0 +1,88 @@ +#ifndef __CPBASEQTAPPLICATION__BLOCK__H__ +#define __CPBASEQTAPPLICATION__BLOCK__H__ + +#include +#include +#include + +namespace cpBaseQtApplication +{ + class Editor; + class Port; + class NamePort; + class InputPort; + class OutputPort; + + /** + */ + class cpBaseQtApplication_EXPORT Block + : public QGraphicsPathItem + { + public: + typedef Block Self; + typedef QGraphicsPathItem Superclass; + typedef cpPlugins::ProcessObject TFilter; + + public: + enum { Type = QGraphicsItem::UserType + 6 }; + + Block( + TFilter* filter, const QString& name, + QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL + ); + virtual ~Block( ); + + TFilter* filter( ); + const TFilter* filter( ) const; + + Editor* editor( ); + const Editor* editor( ) const; + void setEditor( Editor* editor ); + + void setNamePort( const QString& txt ); + InputPort* addInputPort( const QString& txt ); + OutputPort* addOutputPort( const QString& txt ); + + InputPort* inputPort( const QString& txt ); + OutputPort* outputPort( const QString& txt ); + + QString namePort( ) const; + const InputPort* inputPort( const QString& txt ) const; + const OutputPort* outputPort( const QString& txt ) const; + + inline int type( ) const + { return( this->Type ); } + + virtual void paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ); + + protected: + QVariant itemChange( GraphicsItemChange change, const QVariant& value ); + void _setTypeInfo( const QString& txt ); + void _configPort( Port* port ); + + virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent* evt ); + virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ); + + private: + int m_HorzMargin; + int m_VertMargin; + int m_Width; + int m_Height; + + NamePort* m_NamePort; + std::map< std::string, InputPort* > m_InputPorts; + std::map< std::string, OutputPort* > m_OutputPorts; + + TFilter* m_Filter; + Editor* m_Editor; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__BLOCK__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Canvas.cxx b/lib/cpBaseQtApplication/Canvas.cxx new file mode 100644 index 0000000..c873b34 --- /dev/null +++ b/lib/cpBaseQtApplication/Canvas.cxx @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Canvas:: +Canvas( QWidget* parent ) + : QGraphicsView( parent ) +{ + QGraphicsScene* scene = new QGraphicsScene( this ); + this->setScene( scene ); + this->setRenderHint( QPainter::Antialiasing ); + this->setAcceptDrops( true ); + + this->m_Editor = new Editor( this ); + this->m_Editor->install( scene ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Canvas:: +~Canvas( ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication:: +Editor* cpBaseQtApplication::Canvas:: +editor( ) +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication:: +Editor* cpBaseQtApplication::Canvas:: +editor( ) const +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Canvas:: +keyPressEvent( QKeyEvent* event ) +{ + static const int del_key = 16777223; + if( event->key( ) == del_key ) + { + auto _items = this->items( ); + auto i = _items.begin( ); + while( i != _items.end( ) ) + { + if( ( *i )->isSelected( ) ) + { + Block* b = dynamic_cast< Block* >( *i ); + Connection* c = dynamic_cast< Connection* >( *i ); + if( b != NULL ) + { + if( this->m_Editor->deleteFilter( b->namePort( ).toStdString( ) ) ) + delete b; + } + else if( c != NULL ) + { + if( + this->m_Editor->deleteConnection( + c->port1( )->block( )->namePort( ).toStdString( ), + c->port2( )->block( )->namePort( ).toStdString( ), + c->port1( )->name( ).toStdString( ), + c->port2( )->name( ).toStdString( ) + ) + ) + delete c; + + } // fi + i = _items.end( ); + } + else + i++; + + } // elihw + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Canvas:: +wheelEvent( QWheelEvent* event ) +{ + this->_scaleView( + std::pow( double( 2 ), event->delta( ) / double( 240 ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Canvas:: +dragEnterEvent( QDragEnterEvent* event ) +{ + const QMimeData* mime = event->mimeData( ); + if( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) + event->acceptProposedAction( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Canvas:: +dragLeaveEvent( QDragLeaveEvent* event ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Canvas:: +dragMoveEvent( QDragMoveEvent* event ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Canvas:: +dropEvent( QDropEvent* event ) +{ + 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; + + QList< QTreeWidgetItem* > items = tree->selectedItems( ); + for( auto iIt = items.begin( ); iIt != items.end( ); ++iIt ) + { + auto parent = ( *iIt )->parent( ); + if( parent != NULL ) + this->m_Editor->createFilter( + parent->text( 0 ).toStdString( ), + ( *iIt )->text( 0 ).toStdString( ), + this->mapToScene( event->pos( ) ) + ); + + } // rof +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::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 ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Canvas.h b/lib/cpBaseQtApplication/Canvas.h new file mode 100644 index 0000000..3b63b54 --- /dev/null +++ b/lib/cpBaseQtApplication/Canvas.h @@ -0,0 +1,50 @@ +#ifndef __CPBASEQTAPPLICATION__CANVAS__H__ +#define __CPBASEQTAPPLICATION__CANVAS__H__ + +#include +#include + +namespace cpBaseQtApplication +{ + // Some other forward declarations + class Block; + class Connection; + class Editor; + + /** + */ + class cpBaseQtApplication_EXPORT Canvas + : public QGraphicsView + { + Q_OBJECT; + + public: + Canvas( QWidget* parent = 0 ); + virtual ~Canvas( ); + + Editor* editor( ); + const Editor* editor( ) const; + + protected: + /* TODO + void timerEvent( QTimerEvent* event ); + */ + 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 ); + + protected: + Editor* m_Editor; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__CANVAS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Connection.cxx b/lib/cpBaseQtApplication/Connection.cxx new file mode 100644 index 0000000..81ac61d --- /dev/null +++ b/lib/cpBaseQtApplication/Connection.cxx @@ -0,0 +1,139 @@ +#include +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Connection:: +Connection( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ + this->setPen( QPen( Qt::black, 2 ) ); + this->setBrush( Qt::NoBrush ); + this->setZValue( -1 ); + this->m_Port1 = NULL; + this->m_Port2 = NULL; + this->setFlag( QGraphicsItem::ItemIsSelectable ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Connection:: +~Connection( ) +{ + if( this->m_Port1 != NULL ) + this->m_Port1->connections( ). + remove( this->m_Port1->connections( ).indexOf( this ) ); + + if( this->m_Port2 != NULL ) + this->m_Port2->setConnection( NULL ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +setPos1( const QPointF& p ) +{ + this->m_Pos1 = p; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +setPos2( const QPointF& p ) +{ + this->m_Pos2 = p; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +setPort1( OutputPort* p ) +{ + if( p != NULL ) + { + p->connections( ).append( this ); + this->m_Port1 = p; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +setPort2( InputPort* p ) +{ + if( p != NULL ) + { + if( p->connection( ) == NULL ) + { + p->setConnection( this ); + this->m_Port2 = p; + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +updatePosFromPorts( ) +{ + if( this->m_Port1 != NULL ) + this->m_Pos1 = + this->m_Port1->scenePos( ) + + QPointF( this->m_Port1->radius( ), this->m_Port1->radius( ) ); + if( this->m_Port2 != NULL ) + this->m_Pos2 = + this->m_Port2->scenePos( ) + + QPointF( this->m_Port2->radius( ), this->m_Port2->radius( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +updatePath( ) +{ + QPainterPath p; + p.moveTo( this->m_Pos1 ); + + qreal dx = this->m_Pos2.x( ) - this->m_Pos1.x( ); + qreal dy = this->m_Pos2.y( ) - this->m_Pos1.y( ); + QPointF c1( this->m_Pos1.x( ) + dx * 0.25, this->m_Pos1.y( ) + dy * 0.1 ); + QPointF c2( this->m_Pos1.x( ) + dx * 0.75, this->m_Pos1.y( ) + dy * 0.9 ); + p.cubicTo( c1, c2, this->m_Pos2 ); + + this->setPath( p ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::OutputPort* cpBaseQtApplication::Connection:: +port1( ) const +{ + return( this->m_Port1 ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::InputPort* cpBaseQtApplication::Connection:: +port2( ) const +{ + return( this->m_Port2 ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Connection:: +paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ) +{ + Q_UNUSED( option ); + Q_UNUSED( widget ); + + if( this->isSelected( ) ) + painter->setPen( QPen( Qt::red, 5 ) ); + else + painter->setPen( QPen( Qt::black, 2 ) ); + this->setBrush( Qt::NoBrush ); + painter->drawPath( this->path( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Connection.h b/lib/cpBaseQtApplication/Connection.h new file mode 100644 index 0000000..2a30d55 --- /dev/null +++ b/lib/cpBaseQtApplication/Connection.h @@ -0,0 +1,56 @@ +#ifndef __CPBASEQTAPPLICATION__CONNECTION__H__ +#define __CPBASEQTAPPLICATION__CONNECTION__H__ + +#include +#include + +namespace cpBaseQtApplication +{ + class InputPort; + class OutputPort; + + /** + */ + class cpBaseQtApplication_EXPORT Connection + : public QGraphicsPathItem + { + public: + typedef Connection Self; + typedef QGraphicsPathItem Superclass; + + public: + enum { Type = QGraphicsItem::UserType + 5 }; + + Connection( QGraphicsItem* parent = 0, QGraphicsScene* scene = 0 ); + virtual ~Connection( ); + + void setPos1( const QPointF& p ); + void setPos2( const QPointF& p ); + void setPort1( OutputPort* p ); + void setPort2( InputPort* p ); + void updatePosFromPorts( ); + void updatePath( ); + OutputPort* port1( ) const; + InputPort* port2( ) const; + + inline int type( ) const + { return( this->Type ); } + + virtual void paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ); + + private: + QPointF m_Pos1; + QPointF m_Pos2; + OutputPort* m_Port1; + InputPort* m_Port2; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__CONNECTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Editor.cxx b/lib/cpBaseQtApplication/Editor.cxx new file mode 100644 index 0000000..35b8a61 --- /dev/null +++ b/lib/cpBaseQtApplication/Editor.cxx @@ -0,0 +1,623 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_Editor_Callback_SWITCH( E, e ) \ + case QEvent::GraphicsScene##E: \ + { \ + QGraphicsScene##E##Event* evt = \ + dynamic_cast< QGraphicsScene##E##Event* >( e ); \ + if( evt != NULL ) \ + this->_##E##_cbk( evt ); \ + } \ + break; + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_Editor_Callback_CODE( E ) \ + void cpBaseQtApplication::Editor::_##E##_cbk( QGraphicsScene##E##Event* evt ) + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Editor:: +Editor( QObject* parent ) + : Superclass( parent ), + m_ActualConnection( NULL ), + m_Workspace( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Editor:: +~Editor( ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Editor:: +TWorkspace* cpBaseQtApplication::Editor:: +workspace( ) +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +const cpBaseQtApplication::Editor:: +TWorkspace* cpBaseQtApplication::Editor:: +workspace( ) const +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +setWorkspace( TWorkspace* ws ) +{ + this->m_Workspace = ws; + this->m_Graph = TGraph::New( ); + + // Create blocks + auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( ); + auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( ); + for( ; vIt != vIt_end; ++vIt ) + { + auto b = this->_createBlock( + dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ), + vIt->first.c_str( ), + QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) ) + ); + if( b != NULL ) + this->m_Graph->SetVertex( vIt->first, b ); + + } // rof + + // Add edges + auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( ); + auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( ); + for( ; rIt != rIt_end; ++rIt ) + { + Block* orig = this->m_Graph->GetVertex( rIt->first ); + auto cIt = rIt->second.begin( ); + for( ; cIt != rIt->second.end( ); ++cIt ) + { + Block* dest = this->m_Graph->GetVertex( cIt->first ); + auto eIt = cIt->second.begin( ); + for( ; eIt != cIt->second.end( ); ++eIt ) + { + OutputPort* op = orig->outputPort( eIt->first.c_str( ) ); + InputPort* ip = dest->inputPort( eIt->second.c_str( ) ); + if( op == NULL || ip == NULL ) + continue; + + Connection* c = new Connection( 0, this->m_Scene ); + c->setPort1( op ); + c->setPort2( ip ); + c->updatePosFromPorts( ); + c->updatePath( ); + this->m_Graph->AddEdge( rIt->first, cIt->first, c ); + + } // rof + + } // rof + + } // rof +} + +// ------------------------------------------------------------------------- +std::string cpBaseQtApplication::Editor:: +createFilter( + const std::string& category, + const std::string& filter, + const QPointF& pnt + ) +{ + std::string name = filter; + while( this->m_Workspace->HasFilter( name ) ) + name += std::string( "_" ); + if( this->m_Workspace->CreateFilter( category, filter, name ) ) + { + auto b = this->_createBlock( + this->m_Workspace->GetFilter( name ), + name.c_str( ), + pnt + ); + return( name ); + } + else + return( "" ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Editor:: +deleteFilter( const std::string& name ) +{ + std::cout << name << std::endl; + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Editor:: +deleteConnection( + const std::string& src, const std::string& des, + const std::string& in, const std::string& out + ) +{ + std::cout + << src << " " + << des << " " + << in << " " + << out << std::endl; + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +clear( ) +{ + std::cout << "Editor::clear" << std::endl; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +install( QGraphicsScene* s ) +{ + s->installEventFilter( this ); + this->m_Scene = s; +} + +// ------------------------------------------------------------------------- +QGraphicsItem* cpBaseQtApplication::Editor:: +itemAt( const QPointF& pos ) +{ + QList< QGraphicsItem* > items = + this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) ); + + foreach( QGraphicsItem* item, items ) + if( item->type( ) > QGraphicsItem::UserType ) + return( item ); + return( NULL ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Block* cpBaseQtApplication::Editor:: +_createBlock( TFilter* f, const QString& name, const QPointF& pnt ) +{ + if( f == NULL ) + return( NULL ); + + // Add block + Block* b = new Block( f, name, 0, this->m_Scene ); + b->setEditor( this ); + b->setPos( pnt ); + + // Mark exposed inputs + auto& e_in = this->m_Workspace->GetExposedInputPorts( ); + auto f_in = f->GetInputsNames( ); + for( auto iIt = f_in.begin( ); iIt != f_in.end( ); ++iIt ) + { + auto eIt = e_in.begin( ); + auto fIt = e_in.end( ); + for( ; eIt != e_in.end( ) && fIt == e_in.end( ); ++eIt ) + if( eIt->second.second == *iIt ) + fIt = eIt; + if( fIt == e_in.end( ) ) + continue; + + auto port = b->inputPort( iIt->c_str( ) ); + port->setExtendedName( fIt->first.c_str( ) ); + port->setExtend( true ); + + } // rof + + // Mark exposed outputs + auto& e_out = this->m_Workspace->GetExposedOutputPorts( ); + auto f_out = f->GetOutputsNames( ); + for( auto iIt = f_out.begin( ); iIt != f_out.end( ); ++iIt ) + { + auto eIt = e_out.begin( ); + auto fIt = e_out.end( ); + for( ; eIt != e_out.end( ) && fIt == e_out.end( ); ++eIt ) + if( eIt->second.second == *iIt ) + fIt = eIt; + if( fIt == e_out.end( ) ) + continue; + + auto port = b->outputPort( iIt->c_str( ) ); + port->setExtendedName( fIt->first.c_str( ) ); + port->setExtend( true ); + + } // rof + + return( b ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::Editor:: +eventFilter( QObject* o, QEvent* e ) +{ + // Event type + switch( int( e->type( ) ) ) + { + cpBaseQtApplication_Editor_Callback_SWITCH( ContextMenu, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( DragEnter, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( DragLeave, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( DragMove, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( Drop, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( Help, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( HoverEnter, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( HoverLeave, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( HoverMove, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( MouseDoubleClick, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( MouseMove, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( MousePress, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( MouseRelease, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( Move, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( Resize, e ); + cpBaseQtApplication_Editor_Callback_SWITCH( Wheel, e ); + default: + break; + } // hctiws + return( this->Superclass::eventFilter( o, e ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +updateFilter( const std::string& filter_name ) +{ + emit execFilter( filter_name ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +showOutputData( + const std::string& filter_name, const std::string& output_name + ) +{ + emit showFilterOutput( filter_name, output_name ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +hideOutputData( + const std::string& filter_name, const std::string& output_name + ) +{ + emit hideFilterOutput( filter_name, output_name ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Editor:: +visualPropertiesOutputData( + const std::string& filter_name, const std::string& output_name + ) +{ + emit visualPropertiesFilterOutput( filter_name, output_name ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( ContextMenu ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( DragEnter ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( DragLeave ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( DragMove ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( Drop ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( Help ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( HoverEnter ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( HoverLeave ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( HoverMove ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( MouseDoubleClick ) +{ + QGraphicsItem* item = this->itemAt( evt->scenePos( ) ); + if( item == NULL ) + return; + + switch( evt->button( ) ) + { + case Qt::LeftButton: + { + Block* block = dynamic_cast< Block* >( item ); + Port* port = dynamic_cast< Port* >( item ); + Connection* conn = dynamic_cast< Connection* >( item ); + + if( block != NULL ) + { + QString old_name = block->namePort( ); + bool ok; + QString new_name = + QInputDialog::getText( + dynamic_cast< QWidget* >( this->parent( ) ), + "Change filter name", + "Filter name:", + QLineEdit::Normal, + old_name, + &ok + ); + if( ok && !new_name.isEmpty( ) && old_name != new_name ) + { + ok = this->m_Graph->RenameVertex( + old_name.toStdString( ), + new_name.toStdString( ) + ); + block->setNamePort( new_name ); + this->m_Workspace->RenameFilter( + old_name.toStdString( ), + new_name.toStdString( ) + ); + + } // fi + } + else if( port != NULL ) + { + if( evt->modifiers( ) == Qt::ControlModifier ) + { + port->setExtend( !( port->isExtended( ) ) ); + InputPort* in_port = dynamic_cast< InputPort* >( port ); + OutputPort* out_port = dynamic_cast< OutputPort* >( port ); + if( port->isExtended( ) ) + { + if( in_port != NULL ) + { + this->m_Workspace->ExposeInputPort( + in_port->extendedName( ).toStdString( ), + in_port->block( )->namePort( ).toStdString( ), + in_port->name( ).toStdString( ) + ); + } + else if( out_port != NULL ) + { + this->m_Workspace->ExposeOutputPort( + out_port->extendedName( ).toStdString( ), + out_port->block( )->namePort( ).toStdString( ), + out_port->name( ).toStdString( ) + ); + + } // fi + } + else + { + if( in_port != NULL ) + this->m_Workspace->HideInputPort( + in_port->extendedName( ).toStdString( ) + ); + else if( out_port != NULL ) + this->m_Workspace->HideOutputPort( + out_port->extendedName( ).toStdString( ) + ); + + } // fi + this->m_Scene->update( ); + } + else if( evt->modifiers( ) == Qt::NoModifier ) + { + if( port->isExtended( ) ) + { + QString old_name = port->extendedName( ); + bool ok; + QString new_name = + QInputDialog::getText( + dynamic_cast< QWidget* >( this->parent( ) ), + "Change filter name", + "Filter name:", + QLineEdit::Normal, + old_name, + &ok + ); + if( ok && !new_name.isEmpty( ) && old_name != new_name ) + { + port->setExtendedName( new_name ); + InputPort* in_port = dynamic_cast< InputPort* >( port ); + OutputPort* out_port = dynamic_cast< OutputPort* >( port ); + if( in_port != NULL ) + this->m_Workspace-> + RenameExposedInputPort( + old_name.toStdString( ), + new_name.toStdString( ) + ); + else if( out_port != NULL ) + this->m_Workspace-> + RenameExposedOutputPort( + old_name.toStdString( ), + new_name.toStdString( ) + ); + this->m_Scene->update( ); + + } // fi + + } // fi + + } // fi + } + else if( conn != NULL ) + { + } // fi + } + break; + /* TODO: + case Qt::RightButton: + { + } + break; + case Qt::MiddleButton: + { + } + break; + */ + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( MouseMove ) +{ + if( this->m_ActualConnection != NULL ) + { + if( this->m_ActualConnection->port1( ) == NULL ) + this->m_ActualConnection->setPos1( evt->scenePos( ) ); + else if( this->m_ActualConnection->port2( ) == NULL ) + this->m_ActualConnection->setPos2( evt->scenePos( ) ); + this->m_ActualConnection->updatePath( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( MousePress ) +{ + InputPort* in_port = + dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) ); + OutputPort* out_port = + dynamic_cast< OutputPort* >( this->itemAt( evt->scenePos( ) ) ); + if( in_port == NULL && out_port == NULL ) + return; + + switch( evt->button( ) ) + { + case Qt::LeftButton: + { + if( out_port != NULL ) + { + if( out_port->block( ) != NULL ) + { + // Start new connection + this->m_ActualConnection = new Connection( 0, this->m_Scene ); + this->m_ActualConnection->setPort1( out_port ); + this->m_ActualConnection->setPos1( out_port->scenePos( ) ); + this->m_ActualConnection->setPos2( evt->scenePos( ) ); + this->m_ActualConnection->updatePosFromPorts( ); + this->m_ActualConnection->updatePath( ); + + } // fi + + } // fi + } + break; + default: + break; + + } // hctiws +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( MouseRelease ) +{ + if( this->m_ActualConnection == NULL ) + return; + + switch( evt->button( ) ) + { + case Qt::LeftButton: + { + InputPort* port2 = + dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) ); + if( port2 != NULL ) + { + OutputPort* port1 = + dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) ); + if( port1 != NULL ) + { + if( + port1->block( ) != port2->block( ) && + !port2->hasConnection( ) && + !port1->isConnected( port2 ) && + !port2->isExtended( ) + ) + { + this->m_ActualConnection->setPos2( port2->scenePos( ) ); + this->m_ActualConnection->setPort2( port2 ); + this->m_ActualConnection->updatePosFromPorts( ); + this->m_ActualConnection->updatePath( ); + + this->m_Workspace->Connect( + port1->block( )->namePort( ).toStdString( ), + port2->block( )->namePort( ).toStdString( ), + port1->name( ).toStdString( ), + port2->name( ).toStdString( ) + ); + this->m_Graph->AddEdge( + port1->block( )->namePort( ).toStdString( ), + port2->block( )->namePort( ).toStdString( ), + this->m_ActualConnection + ); + } + else + delete this->m_ActualConnection; + } + else + delete this->m_ActualConnection; + } + else + delete this->m_ActualConnection; + this->m_ActualConnection = NULL; + } + break; + default: + break; + } // hctisw +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( Move ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( Resize ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication_Editor_Callback_CODE( Wheel ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Editor.h b/lib/cpBaseQtApplication/Editor.h new file mode 100644 index 0000000..5e17673 --- /dev/null +++ b/lib/cpBaseQtApplication/Editor.h @@ -0,0 +1,148 @@ +#ifndef __CPBASEQTAPPLICATION__EDITOR__H__ +#define __CPBASEQTAPPLICATION__EDITOR__H__ + +#include +#include +#include +#include +#include + +class QGraphicsScene; +class QGraphicsSceneMouseEvent; +class QGraphicsItem; +class QGraphicsSceneContextMenuEvent; +class QGraphicsSceneDragDropEvent; +class QGraphicsSceneHelpEvent; +class QGraphicsSceneHoverEvent; +class QGraphicsSceneMouseEvent; +class QGraphicsSceneMoveEvent; +class QGraphicsSceneResizeEvent; +class QGraphicsSceneWheelEvent; + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_Editor_Callback_DCL( E ) \ + void _##E##_cbk( QGraphicsScene##E##Event* e ); + +namespace cpBaseQtApplication +{ + class Connection; + class Block; + + /** + */ + class cpBaseQtApplication_EXPORT Editor + : public QObject + { + Q_OBJECT; + + public: + typedef Editor Self; + typedef QObject Superclass; + + typedef cpPlugins::Workspace TWorkspace; + typedef cpPlugins::ProcessObject TFilter; + typedef + cpExtensions::DataStructures:: + Graph< Block*, Connection*, std::string > TGraph; + + public: + explicit Editor( QObject* parent = 0 ); + virtual ~Editor( ); + + TWorkspace* workspace( ); + const TWorkspace* workspace( ) const; + void setWorkspace( TWorkspace* ws ); + + std::string createFilter( + const std::string& category, const std::string& filter, + const QPointF& pnt = QPointF( qreal( 0 ), qreal( 0 ) ) + ); + bool deleteFilter( const std::string& name ); + bool deleteConnection( + const std::string& src, const std::string& des, + const std::string& in, const std::string& out + ); + void clear( ); + + void install( QGraphicsScene* s ); + bool eventFilter( QObject* o, QEvent* e ); + + void updateFilter( const std::string& filter_name ); + void showOutputData( + const std::string& filter_name, + const std::string& output_name + ); + void hideOutputData( + const std::string& filter_name, + const std::string& output_name + ); + void visualPropertiesOutputData( + const std::string& filter_name, + const std::string& output_name + ); + + signals: + void execFilter( const std::string& filter_name ); + void showFilterOutput( + const std::string& filter_name, + const std::string& output_name + ); + void hideFilterOutput( + const std::string& filter_name, + const std::string& output_name + ); + void visualPropertiesFilterOutput( + const std::string& filter_name, + const std::string& output_name + ); + + private: + QGraphicsItem* itemAt( const QPointF& pos ); + + inline Block* _createBlock( + TFilter* f, const QString& name, const QPointF& pnt + ); + + protected: + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragEnterEvent; + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragLeaveEvent; + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragMoveEvent; + typedef QGraphicsSceneDragDropEvent QGraphicsSceneDropEvent; + typedef QGraphicsSceneHoverEvent QGraphicsSceneHoverEnterEvent; + typedef QGraphicsSceneHoverEvent QGraphicsSceneHoverMoveEvent; + typedef QGraphicsSceneHoverEvent QGraphicsSceneHoverLeaveEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMouseDoubleClickEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMouseMoveEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMousePressEvent; + typedef QGraphicsSceneMouseEvent QGraphicsSceneMouseReleaseEvent; + + cpBaseQtApplication_Editor_Callback_DCL( ContextMenu ); + cpBaseQtApplication_Editor_Callback_DCL( DragEnter ); + cpBaseQtApplication_Editor_Callback_DCL( DragLeave ); + cpBaseQtApplication_Editor_Callback_DCL( DragMove ); + cpBaseQtApplication_Editor_Callback_DCL( Drop ); + cpBaseQtApplication_Editor_Callback_DCL( Help ); + cpBaseQtApplication_Editor_Callback_DCL( HoverEnter ); + cpBaseQtApplication_Editor_Callback_DCL( HoverLeave ); + cpBaseQtApplication_Editor_Callback_DCL( HoverMove ); + cpBaseQtApplication_Editor_Callback_DCL( MouseDoubleClick ); + cpBaseQtApplication_Editor_Callback_DCL( MouseMove ); + cpBaseQtApplication_Editor_Callback_DCL( MousePress ); + cpBaseQtApplication_Editor_Callback_DCL( MouseRelease ); + cpBaseQtApplication_Editor_Callback_DCL( Move ); + cpBaseQtApplication_Editor_Callback_DCL( Resize ); + cpBaseQtApplication_Editor_Callback_DCL( Wheel ); + + private: + QGraphicsScene* m_Scene; + Connection* m_ActualConnection; + + TWorkspace* m_Workspace; + TGraph::Pointer m_Graph; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__EDITOR__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/MainHelper.h b/lib/cpBaseQtApplication/MainHelper.h new file mode 100644 index 0000000..243c526 --- /dev/null +++ b/lib/cpBaseQtApplication/MainHelper.h @@ -0,0 +1,90 @@ +#ifndef __CPBASEQTAPPLICATION__MAINHELPER__H__ +#define __CPBASEQTAPPLICATION__MAINHELPER__H__ + +#include +#include + +// ------------------------------------------------------------------------- +#define cpBaseQtApplication_Main( _window_class_ ) \ + int main( int argc, char* argv[] ) \ + { \ + QApplication a( argc, argv ); \ + _window_class_ w( argc, argv, &a ); \ + w.show( ); \ + return( a.exec( ) ); \ + } + +// ------------------------------------------------------------------------- +#include + +#ifdef cpPlugins_SYS_WINDOWS + +# include +# include +# include +# include + +// ------------------------------------------------------------------------- +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_SYS_WINDOWS +# define cpBaseQtApplication_MainComplement +#endif // cpPlugins_SYS_WINDOWS + +#endif // __CPBASEQTAPPLICATION__MAINHELPER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/MainWindow.cxx b/lib/cpBaseQtApplication/MainWindow.cxx new file mode 100644 index 0000000..1a42557 --- /dev/null +++ b/lib/cpBaseQtApplication/MainWindow.cxx @@ -0,0 +1,551 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::MainWindow::_TBlocker:: +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 ) ); + */ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::MainWindow:: +MainWindow( + int argc, char* argv[], + QApplication* app, + QWidget* parent + ) + : Superclass( parent ), + m_Application( app ), + m_PluginsPath( "." ), + m_TreeWidget( NULL ), + m_Editor( NULL ), + m_MPR( NULL ) +{ + QFileInfo i( argv[ 0 ] ); + if( i.exists( ) ) + this->m_Interface.UpdateEnvironments( i.canonicalPath( ).toStdString( ) ); + this->m_Workspace.SetInterface( &( this->m_Interface ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::MainWindow:: +~MainWindow( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +UpdateEnvironment( ) +{ + try + { + this->m_Interface.LoadEnvironment( ); + this->m_Interface.GuessPlugins( ); + } + catch( std::exception& err ) + { + QMessageBox::critical( + this, "Error loading required libraries", err.what( ) + ); + return; + + } // yrt +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_Configure( + QTreeWidget* tree, + cpExtensions::QT::SimpleMPRWidget* mpr, + cpBaseQtApplication::Editor* editor + ) +{ + this->m_TreeWidget = tree; + this->_UpdateLoadedPlugins( ); + this->m_Editor = editor; + this->m_MPR = mpr; + if( this->m_Editor != NULL ) + { + this->m_Editor->setWorkspace( &( this->m_Workspace ) ); + + // Slots <-> signals + this->connect( + this->m_Editor, + SIGNAL( execFilter( const std::string& ) ), + this, + SLOT( _ExecFilter( const std::string& ) ) + ); + this->connect( + this->m_Editor, + SIGNAL( showFilterOutput( const std::string&, const std::string& ) ), + this, + SLOT( _ShowData( const std::string&, const std::string& ) ) + ); + this->connect( + this->m_Editor, + SIGNAL( hideFilterOutput( const std::string&, const std::string& ) ), + this, + SLOT( _HideData( const std::string&, const std::string& ) ) + ); + this->connect( + this->m_Editor, + SIGNAL( visualPropertiesFilterOutput( const std::string&, const std::string& ) ), + this, + SLOT( _DataProperties( const std::string&, const std::string& ) ) + ); + + } // fi + if( this->m_MPR != NULL ) + this->m_Workspace.SetMPRViewer( this->m_MPR ); + this->_ClearWorkspace( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_ClearWorkspace( ) +{ + if( this->m_Editor != NULL ) + this->m_Editor->clear( ); + if( this->m_MPR != NULL ) + this->m_MPR->Clear( ); + this->m_Workspace.Clear( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_LoadPlugins( const std::string& filename ) +{ + try + { + this->m_Interface.LoadFile( filename ); + this->_UpdateLoadedPlugins( ); + } + catch( std::exception& err ) + { + QMessageBox::critical( + this, + "Error loading plugins path", + err.what( ) + ); + + } // yrt +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_LoadPluginsFromPath( const std::string& path ) +{ + try + { + this->m_Interface.LoadDirectory( path ); + this->_UpdateLoadedPlugins( ); + } + catch( std::exception& err ) + { + QMessageBox::critical( + this, + "Error loading plugins path", + err.what( ) + ); + + } // yrt +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_UpdateLoadedPlugins( ) +{ + if( this->m_TreeWidget == NULL ) + return; + this->_Block( ); + auto categories = this->m_Interface.GetCategories( ); + unsigned int filter_count = 0; + for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt ) + { + // Create or get category + QList< QTreeWidgetItem* > cat_items = + this->m_TreeWidget->findItems( + cIt->c_str( ), Qt::MatchExactly | Qt::MatchRecursive + ); + QTreeWidgetItem* cat = NULL; + if( cat_items.size( ) == 0 ) + { + cat = new QTreeWidgetItem( + ( QTreeWidgetItem* )( NULL ), QStringList( cIt->c_str( ) ) + ); + this->m_TreeWidget->addTopLevelItem( cat ); + } + else + cat = cat_items[ 0 ]; + + // Create filters + auto filters = this->m_Interface.GetFilters( *cIt ); + filter_count += filters.size( ); + for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt ) + { + QList< QTreeWidgetItem* > filter_items = + this->m_TreeWidget->findItems( + fIt->c_str( ), Qt::MatchExactly | Qt::MatchRecursive + ); + auto fiIt = filter_items.begin( ); + auto found_fiIt = filter_items.end( ); + for( ; fiIt != filter_items.end( ); ++fiIt ) + if( ( *fiIt )->parent( ) == cat ) + found_fiIt = fiIt; + + // Add filter + if( found_fiIt == filter_items.end( ) ) + QTreeWidgetItem* filter = new QTreeWidgetItem( + cat, QStringList( fIt->c_str( ) ) + ); + + } // rof + + } // rof + this->m_TreeWidget->expandAll( ); + this->_UnBlock( ); + + if( filter_count == 0 ) + QMessageBox::critical( + this, + "Error loading default plugins", + "No plugins loaded: remember to load some!!!" + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_ShowPlugins( ) +{ + auto paths = this->m_Interface.GetPaths( ); + auto plugins = this->m_Interface.GetPlugins( ); + std::stringstream info; + info << "----- PATHS -----" << std::endl; + for( auto i = paths.begin( ); i != paths.end( ); ++i ) + info << " " << *i << std::endl; + info << std::endl << "----- PLUGINS -----" << std::endl; + for( auto i = plugins.begin( ); i != plugins.end( ); ++i ) + info << " " << *i << std::endl; + QMessageBox::information( + this, + "Loaded libraries and plugins information", + info.str( ).c_str( ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_Block( ) +{ + this->m_Application->setOverrideCursor( Qt::WaitCursor ); + this->m_Application->installEventFilter( &( this->m_Blocker ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_UnBlock( ) +{ + while( this->m_Application->overrideCursor( ) ) + this->m_Application->restoreOverrideCursor( ); + this->m_Application->removeEventFilter( &( this->m_Blocker ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_LoadWorkspace( const std::string& filename ) +{ + this->_ClearWorkspace( ); + std::string err = this->m_Workspace.LoadWorkspace( filename ); + if( err != "" ) + { + QMessageBox::critical( + this, + QMessageBox::tr( "Error loading workspace" ), + QMessageBox::tr( err.c_str( ) ) + ); + } + else + { + /* TODO + if( this->m_Editor != NULL ) + this->m_Editor->setWorkspace( this->m_Workspace ); + */ + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_SaveWorkspace( const std::string& filename ) +{ + std::string err = this->m_Workspace.SaveWorkspace( filename ); + if( err != "" ) + QMessageBox::critical( + this, + QMessageBox::tr( "Error saving workspace" ), + QMessageBox::tr( err.c_str( ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_BackgroundProperties( unsigned int i ) +{ + if( this->m_MPR == NULL ) + return; + + QColor color = + QColorDialog::getColor( + QColor( 0, 0, 0 ), + this, + "Select Color", + QColorDialog::DontUseNativeDialog + ); + if( color.isValid( ) ) + { + double r = double( color.red( ) ) / double( 255 ); + double g = double( color.green( ) ) / double( 255 ); + double b = double( color.blue( ) ) / double( 255 ); + if( i >= 4 ) + { + unsigned int maxId = ( i == 4 )? 3: 4; + for( unsigned int j = 0; j < maxId; ++j ) + { + auto ren = this->m_MPR->GetRenderer( j ); + if( ren != NULL ) + { + ren->SetBackground( r, g, b ); + ren->Render( ); + + } // fi + + } // rof + } + else + { + auto ren = this->m_MPR->GetRenderer( i ); + if( ren != NULL ) + { + ren->SetBackground( r, g, b ); + ren->Render( ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_ShowData( const std::string& filter_name, const std::string& output_name ) +{ + if( this->m_MPR == NULL ) + return; + + auto output = this->m_Workspace.GetOutput( filter_name, output_name ); + if( output != NULL ) + { + this->_Block( ); + auto actor = output->GetVTKActor( ); + if( actor != NULL ) + { + this->m_MPR->AddActor( + actor, output_name + std::string( "@" ) + filter_name + ); + this->_UnBlock( ); + } + else + { + this->_UnBlock( ); + QMessageBox::critical( + this, + QMessageBox::tr( "Error showing data" ), + QMessageBox::tr( "Unknown VTK conversion." ) + ); + + } // fi + } + else + QMessageBox::critical( + this, + QMessageBox::tr( "Error showing data" ), + QMessageBox::tr( "Unknown port name." ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_HideData( const std::string& filter, const std::string& output ) +{ + std::cout << "MainWindow::HideData" << std::endl; + /* TODO + */ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_DataProperties( + const std::string& filter_name, const std::string& output_name + ) +{ + if( this->m_MPR == NULL ) + return; + + auto output = this->m_Workspace.GetOutput( filter_name, output_name ); + if( output != NULL ) + { + this->_Block( ); + auto actors = this->m_MPR->GetActors( + output_name + std::string( "@" ) + filter_name + ); + auto dlg = new ActorPropertiesQDialog( NULL ); + for( auto i = actors.begin( ); i != actors.end( ); ++i ) + dlg->addActor( *i ); + dlg->addRenderWindow( this->m_MPR->GetRenderWindow( 0 ) ); + dlg->addRenderWindow( this->m_MPR->GetRenderWindow( 1 ) ); + dlg->addRenderWindow( this->m_MPR->GetRenderWindow( 2 ) ); + dlg->addRenderWindow( this->m_MPR->GetRenderWindow( 3 ) ); + this->_UnBlock( ); + dlg->exec( ); + } + else + QMessageBox::critical( + this, + QMessageBox::tr( "Error showing data" ), + QMessageBox::tr( "Unknown port name." ) + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_InteractiveLoadPlugins( ) +{ + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::ExistingFiles ); + dlg.setDirectory( this->m_PluginsPath.c_str( ) ); + + 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:: +_InteractiveLoadPluginsFromPath( ) +{ + QFileDialog d( this ); + d.setFileMode( QFileDialog::DirectoryOnly ); + d.setDirectory( this->m_PluginsPath.c_str( ) ); + if( !( d.exec( ) ) ) + return; + this->_LoadPluginsFromPath( d.selectedFiles( ).begin( )->toStdString( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_InteractiveLoadWorkspace( ) +{ + 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:: +_InteractiveSaveWorkspace( ) +{ + 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" ) ); + if( !( dlg.exec( ) ) ) + return; + this->_SaveWorkspace( dlg.selectedFiles( ).begin( )->toStdString( ) ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::MainWindow:: +_ExecFilter( const std::string& filter_name ) +{ + this->_Block( ); + try + { + this->m_Workspace.Execute( filter_name ); + this->_UnBlock( ); + } + catch( itk::ExceptionObject& err1 ) + { + this->_UnBlock( ); + QMessageBox::critical( + this, + QMessageBox::tr( "Error executing filter" ), + QMessageBox::tr( err1.GetDescription( ) ) + ); + } + catch( std::exception& err2 ) + { + this->_UnBlock( ); + QMessageBox::critical( + this, + QMessageBox::tr( "Error executing filter" ), + QMessageBox::tr( err2.what( ) ) + ); + } + catch( ... ) + { + this->_UnBlock( ); + QMessageBox::critical( + this, + QMessageBox::tr( "Error executing filter" ), + QMessageBox::tr( "Unknown error" ) + ); + + } // yrt +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/MainWindow.h b/lib/cpBaseQtApplication/MainWindow.h new file mode 100644 index 0000000..eca0a16 --- /dev/null +++ b/lib/cpBaseQtApplication/MainWindow.h @@ -0,0 +1,105 @@ +#ifndef __CPBASEQTAPPLICATION__MAINWINDOW__H__ +#define __CPBASEQTAPPLICATION__MAINWINDOW__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace QT + { + class SimpleMPRWidget; + } +} +class QTreeWidget; + +namespace cpBaseQtApplication +{ + class Editor; + + /** + */ + class cpBaseQtApplication_EXPORT MainWindow + : public QMainWindow + { + Q_OBJECT; + + public: + typedef MainWindow Self; + typedef QMainWindow Superclass; + + protected: + /** + */ + class _TBlocker + : public QObject + { + protected: + virtual bool eventFilter( QObject* obj, QEvent* event ) ITK_OVERRIDE; + }; + + public: + explicit MainWindow( + int argc, char* argv[], + QApplication* app, + QWidget* parent = NULL + ); + virtual ~MainWindow( ); + + void UpdateEnvironment( ); + + protected: + void _Configure( + QTreeWidget* tree, + cpExtensions::QT::SimpleMPRWidget* mpr, + cpBaseQtApplication::Editor* editor + ); + void _ClearWorkspace( ); + void _LoadPlugins( const std::string& filename ); + void _LoadPluginsFromPath( const std::string& path ); + void _UpdateLoadedPlugins( ); + void _ShowPlugins( ); + void _Block( ); + void _UnBlock( ); + + void _LoadWorkspace( const std::string& filename ); + void _SaveWorkspace( const std::string& filename ); + + void _BackgroundProperties( unsigned int i ); + + protected slots: + void _InteractiveLoadPlugins( ); + void _InteractiveLoadPluginsFromPath( ); + void _InteractiveLoadWorkspace( ); + void _InteractiveSaveWorkspace( ); + void _ExecFilter( const std::string& filter_name ); + void _ShowData( + const std::string& filter_name, const std::string& output_name + ); + void _HideData( + const std::string& filter_name, const std::string& output_name + ); + void _DataProperties( + const std::string& filter_name, const std::string& output_name + ); + + protected: + QApplication* m_Application; + _TBlocker m_Blocker; + std::string m_PluginsPath; + + cpPlugins::Interface m_Interface; + cpPlugins::Workspace m_Workspace; + + QTreeWidget* m_TreeWidget; + Editor* m_Editor; + cpExtensions::QT::SimpleMPRWidget* m_MPR; + }; + +} // ecapseman + +#endif // __CPBASEQTAPPLICATION__MAINWINDOW__H__ + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Port.cxx b/lib/cpBaseQtApplication/Port.cxx new file mode 100644 index 0000000..d3e15f6 --- /dev/null +++ b/lib/cpBaseQtApplication/Port.cxx @@ -0,0 +1,305 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Port:: +Port( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ), + m_Radius( 5 ), + m_Margin( 2 ) +{ + this->m_Label = new QGraphicsTextItem( this ); + this->m_ExtendedLabel = new QGraphicsTextItem( this ); + this->setExtend( false ); + + QPainterPath p; + p.addEllipse( 0, 0, 2 * this->m_Radius, 2 * this->m_Radius ); + + this->setPath( p ); + this->setPen( QPen( Qt::darkRed ) ); + this->setBrush( Qt::red ); + this->setFlag( QGraphicsItem::ItemSendsScenePositionChanges ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::Port:: +~Port( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Port:: +setBlock( Block* b ) +{ + this->m_Block = b; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Port:: +setName( const QString& n ) +{ + this->m_Label->setPlainText( n ); + this->_updateLabels( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Port:: +setExtendedName( const QString& n ) +{ + this->m_ExtendedLabel->setPlainText( n ); + this->_updateLabels( ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Port:: +setExtend( bool extend ) +{ + // Do nothing! + this->m_IsExtended = false; + this->m_ExtendedLabel->setVisible( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::Port:: +paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ) +{ + Q_UNUSED( option ); + Q_UNUSED( widget ); + + if( this->isExtended( ) ) + { + painter->setPen( QPen( Qt::darkBlue ) ); + painter->setBrush( Qt::blue ); + } + else + { + painter->setPen( QPen( Qt::darkRed ) ); + painter->setBrush( Qt::red ); + + } // fi + painter->drawPath( this->path( ) ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::NamePort:: +NamePort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::NamePort:: +~NamePort( ) +{ +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::NamePort:: +_updateLabels( ) +{ + QFont font( this->scene( )->font( ) ); + font.setBold( true ); + this->m_Label->setFont( font ); + this->m_ExtendedLabel->setFont( font ); + this->setPath( QPainterPath( ) ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::NamePort:: +isConnected( Port* other ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::InputPort:: +InputPort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ), + m_Connection( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::InputPort:: +~InputPort( ) +{ + if( this->m_Connection != NULL ) + delete this->m_Connection; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::InputPort:: +_updateLabels( ) +{ + QFontMetrics fm( this->scene( )->font( ) ); + this->m_Label->setPos( this->m_Radius * 2, -fm.height( ) / 2 ); + this->m_ExtendedLabel->setPos( + -fm.width( this->extendedName( ) ) - this->m_Radius * 2, + -fm.height( ) / 2 + ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::InputPort:: +setExtend( bool extend ) +{ + if( this->m_Connection == NULL ) + { + this->m_IsExtended = extend; + this->m_ExtendedLabel->setVisible( extend ); + } + else + this->Superclass::setExtend( false ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::InputPort:: +isConnected( Port* other ) +{ + if( this->m_Connection != NULL ) + return( + this->m_Connection->port1( ) == other && + this->m_Connection->port2( ) == this + ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::InputPort:: +setConnection( Connection* c ) +{ + this->m_Connection = c; +} + +// ------------------------------------------------------------------------- +QVariant cpBaseQtApplication::InputPort:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + if( change == ItemScenePositionHasChanged ) + { + if( this->m_Connection != NULL ) + { + this->m_Connection->updatePosFromPorts( ); + this->m_Connection->updatePath( ); + + } // fi + + } // fi + return( value ); +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::OutputPort:: +OutputPort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpBaseQtApplication::OutputPort:: +~OutputPort( ) +{ + foreach( Connection* conn, this->m_Connections ) + delete conn; +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::OutputPort:: +_updateLabels( ) +{ + QFontMetrics fm( this->scene( )->font( ) ); + this->m_Label->setPos( + -fm.width( this->name( ) ) - this->m_Radius * 2, -fm.height( ) / 2 + ); + this->m_ExtendedLabel->setPos( this->m_Radius * 2, -fm.height( ) / 2 ); + +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::OutputPort:: +setExtend( bool extend ) +{ + this->m_IsExtended = extend; + this->m_ExtendedLabel->setVisible( extend ); +} + +// ------------------------------------------------------------------------- +bool cpBaseQtApplication::OutputPort:: +isConnected( Port* other ) +{ + auto i = this->m_Connections.begin( ); + bool conn = false; + for( ; i != this->m_Connections.end( ) && !conn; ++i ) + conn |= ( ( *i )->port1( ) == this && ( *i )->port2( ) == other ); + return( conn ); +} + +// ------------------------------------------------------------------------- +QVariant cpBaseQtApplication::OutputPort:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + if( change == ItemScenePositionHasChanged ) + { + foreach( Connection* conn, this->m_Connections ) + { + conn->updatePosFromPorts( ); + conn->updatePath( ); + + } // rof + + } // fi + return( value ); +} + +// ------------------------------------------------------------------------- +void cpBaseQtApplication::OutputPort:: +contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ) +{ + if( this->m_Block == NULL ) + return; + + QMenu menu; + QAction* showAction = menu.addAction( "Show" ); + QAction* hideAction = menu.addAction( "Hide" ); + QAction* propertiesAction = menu.addAction( "Properties" ); + QAction* selectedAction = menu.exec( evt->screenPos( ) ); + + if( selectedAction == showAction ) + { + this->m_Block->editor( )->showOutputData( + this->m_Block->namePort( ).toStdString( ), + this->name( ).toStdString( ) + ); + } + else if( selectedAction == hideAction ) + { + this->m_Block->editor( )->hideOutputData( + this->m_Block->namePort( ).toStdString( ), + this->name( ).toStdString( ) + ); + } + else if( selectedAction == propertiesAction ) + { + this->m_Block->editor( )->visualPropertiesOutputData( + this->m_Block->namePort( ).toStdString( ), + this->name( ).toStdString( ) + ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpBaseQtApplication/Port.h b/lib/cpBaseQtApplication/Port.h new file mode 100644 index 0000000..72bdf90 --- /dev/null +++ b/lib/cpBaseQtApplication/Port.h @@ -0,0 +1,169 @@ +#ifndef __CPBASEQTAPPLICATION__PORT__H__ +#define __CPBASEQTAPPLICATION__PORT__H__ + +#include +#include + +namespace cpBaseQtApplication +{ + class Block; + class Connection; + + /** + */ + class cpBaseQtApplication_EXPORT Port + : public QGraphicsPathItem + { + public: + typedef Port Self; + typedef QGraphicsPathItem Superclass; + + enum { Type = QGraphicsItem::UserType + 1 }; + + public: + Port( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~Port( ); + + void setBlock( Block* b ); + inline Block* block( ) const + { return( this->m_Block ); } + + virtual void setName( const QString& n ); + virtual void setExtendedName( const QString& n ); + inline QString name( ) const + { return( this->m_Label->toPlainText( ) ); } + inline QString extendedName( ) const + { return( this->m_ExtendedLabel->toPlainText( ) ); } + + inline int radius( ) const + { return( this->m_Radius ); } + + inline bool isExtended( ) const + { return( this->m_IsExtended ); } + virtual void setExtend( bool extend ); + + virtual bool isConnected( Port* other ) = 0; + inline int type( ) const + { return( this->Type ); } + + virtual void paint( + QPainter* painter, + const QStyleOptionGraphicsItem* option, + QWidget* widget + ); + + protected: + virtual void _updateLabels( ) { } + + protected: + Block* m_Block; + + int m_Radius; + int m_Margin; + bool m_IsExtended; + + QGraphicsTextItem* m_Label; + QGraphicsTextItem* m_ExtendedLabel; + }; + + /** + */ + class NamePort + : public Port + { + public: + typedef NamePort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 1 }; + + public: + NamePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~NamePort( ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + protected: + virtual void _updateLabels( ); + }; + + /** + */ + class InputPort + : public Port + { + public: + typedef InputPort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 3 }; + + public: + InputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~InputPort( ); + + virtual void setExtend( bool extend ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + void setConnection( Connection* c ); + inline Connection* connection( ) + { return( this->m_Connection ); } + inline const Connection* connection( ) const + { return( this->m_Connection ); } + inline bool hasConnection( ) const + { return( this->m_Connection != NULL ); } + + protected: + QVariant itemChange( GraphicsItemChange change, const QVariant& value ); + virtual void _updateLabels( ); + + protected: + Connection* m_Connection; + }; + + /** + */ + class OutputPort + : public Port + { + public: + typedef OutputPort Self; + typedef Port Superclass; + + enum { Type = Superclass::Type + 4 }; + + public: + OutputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL ); + virtual ~OutputPort( ); + + virtual void setExtend( bool extend ); + + virtual bool isConnected( Port* other ); + inline int type( ) const + { return( this->Type ); } + + inline QVector< Connection* >& connections( ) + { return( this->m_Connections ); } + inline const QVector< Connection* >& connections( ) const + { return( this->m_Connections ); } + + protected: + QVariant itemChange( GraphicsItemChange change, const QVariant& value ); + virtual void _updateLabels( ); + + virtual void contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ); + + protected: + QVector< Connection* > m_Connections; + }; + +} // ecapseman + +#endif // __CPBASEQTQPPLICATION__PORT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/BezierCurveFunction.h b/lib/cpExtensions/Algorithms/BezierCurveFunction.h new file mode 100644 index 0000000..6bc0582 --- /dev/null +++ b/lib/cpExtensions/Algorithms/BezierCurveFunction.h @@ -0,0 +1,76 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__BEZIERCURVEFUNCTION__H__ + +#include +#include +#include + +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 ITK_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 +#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 index 0000000..684360f --- /dev/null +++ b/lib/cpExtensions/Algorithms/BezierCurveFunction.hxx @@ -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/FluxMedialness.h b/lib/cpExtensions/Algorithms/FluxMedialness.h new file mode 100644 index 0000000..f71da00 --- /dev/null +++ b/lib/cpExtensions/Algorithms/FluxMedialness.h @@ -0,0 +1,74 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TGradient > + class FluxMedialness + : public GradientImageFunctionBase< _TGradient > + { + public: + typedef FluxMedialness Self; + typedef GradientImageFunctionBase< _TGradient > 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 ITK_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 +#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 index 0000000..f4d8b9c --- /dev/null +++ b/lib/cpExtensions/Algorithms/FluxMedialness.hxx @@ -0,0 +1,108 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__FLUXMEDIALNESS__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::FluxMedialness< _TGradient >:: +FluxMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_RadialSampling( 4 ), + m_RadiusStep( double( 1 ) ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::FluxMedialness< _TGradient >:: +~FluxMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +typename cpExtensions::Algorithms::FluxMedialness< _TGradient >:: +TOutput cpExtensions::Algorithms::FluxMedialness< _TGradient >:: +_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:"<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 index 0000000..308b3c5 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GaussianDensityImageFilter.h @@ -0,0 +1,103 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__GAUSSIANDENSITYIMAGEFILTER__H__ + +#include +#include +#include +#include + +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 index 0000000..d416e04 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.h @@ -0,0 +1,68 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__ +#define __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + * Base class to compute values based on image gradients (vector). + */ + template< class _TGradient > + class GradientImageFunctionBase + : public itk::ImageFunction< _TGradient, typename _TGradient::PixelType::ValueType, typename _TGradient::PixelType::ValueType > + { + public: + // Types from input arguments + typedef _TGradient TGradient; + 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 ); + + public: + virtual void Prepare( ) const; + virtual TOutput Evaluate( const TPoint& p ) const ITK_OVERRIDE; + virtual TOutput EvaluateAtIndex( const TIndex& i ) const ITK_OVERRIDE; + virtual TOutput EvaluateAtContinuousIndex( const TContIndex& i ) const ITK_OVERRIDE; + + protected: + GradientImageFunctionBase( ); + virtual ~GradientImageFunctionBase( ); + + virtual TOutput _Evaluate( const TIndex& i ) const = 0; + + private: + // Purposely not implemented. + GradientImageFunctionBase( const Self& ); + void operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#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 index 0000000..f4cb928 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GradientImageFunctionBase.hxx @@ -0,0 +1,59 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__GRADIENTIMAGEFUNCTIONBASE__HXX__ + +// ------------------------------------------------------------------------- +template< class _TGradient > +void cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +Prepare( ) const +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +typename cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +TOutput cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +Evaluate( const TPoint& p ) const +{ + TIndex i; + this->GetInputImage( )->TransformPhysicalPointToIndex( p, i ); + return( this->EvaluateAtIndex( i ) ); +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +typename cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +TOutput cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +EvaluateAtIndex( const TIndex& i ) const +{ + return( this->_Evaluate( i ) ); +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +typename cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +TOutput cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +EvaluateAtContinuousIndex( const TContIndex& i ) const +{ + TPoint p; + this->GetInputImage( )->TransformContinuousIndexToPhysicalPoint( i, p ); + return( this->Evaluate( p ) ); +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +GradientImageFunctionBase( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::GradientImageFunctionBase< _TGradient >:: +~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 index 0000000..49eb762 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GulsunTekMedialness.h @@ -0,0 +1,76 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TGradient > + class GulsunTekMedialness + : public GradientImageFunctionBase< _TGradient > + { + public: + typedef GulsunTekMedialness Self; + typedef GradientImageFunctionBase< _TGradient > 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 ITK_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 +#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 index 0000000..941a37c --- /dev/null +++ b/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx @@ -0,0 +1,114 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::GulsunTekMedialness< _TGradient >:: +GulsunTekMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_ProfileSampling( 4 ), + m_RadialSampling( 10 ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::GulsunTekMedialness< _TGradient >:: +~GulsunTekMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +typename cpExtensions::Algorithms::GulsunTekMedialness< _TGradient >:: +TOutput cpExtensions::Algorithms::GulsunTekMedialness< _TGradient >:: +_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/ImageFunctionFilter.h b/lib/cpExtensions/Algorithms/ImageFunctionFilter.h new file mode 100644 index 0000000..731f0f5 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctionFilter.h @@ -0,0 +1,68 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ + +#include + +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( ) ITK_OVERRIDE; + virtual void ThreadedGenerateData( + const TRegion& region, + itk::ThreadIdType threadId + ) ITK_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 +#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 index 0000000..c96c092 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctionFilter.hxx @@ -0,0 +1,67 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__HXX__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..d8a7eca --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctorFilter.h @@ -0,0 +1,102 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ + +#include +#include +#include +#include + +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/InertiaMedialness.h b/lib/cpExtensions/Algorithms/InertiaMedialness.h new file mode 100644 index 0000000..e385513 --- /dev/null +++ b/lib/cpExtensions/Algorithms/InertiaMedialness.h @@ -0,0 +1,215 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__INERTIAMEDIALNESS__H__ + +#include +#include + +#include +#include + +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 +#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 index 0000000..ecb341d --- /dev/null +++ b/lib/cpExtensions/Algorithms/InertiaTensorFunction.h @@ -0,0 +1,180 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__INERTIATENSORFUNCTION__H__ + +#include + +#include +#include +#include +#include + + +#include +#include + + +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 +#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 index 0000000..d3dec08 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IsoImageSlicer.h @@ -0,0 +1,184 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__ +#define __CPEXTENSIONS__ALGORITHMS__ISOIMAGESLICER__H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +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 ITK_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( ) ITK_OVERRIDE; // TODO { } + virtual void GenerateInputRequestedRegion( ) ITK_OVERRIDE; + virtual void GenerateData( ) ITK_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 +#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 index 0000000..041d874 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IsoImageSlicer.hxx @@ -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 index 0000000..b38e06e --- /dev/null +++ b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h @@ -0,0 +1,171 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ +#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ + +#include +#include +#include +#include + +#include +#include +#include +#include + +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 + +#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 index 0000000..acd1da7 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx @@ -0,0 +1,365 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ + +#include + +// ------------------------------------------------------------------------- +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 index 0000000..0fd5d6c --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanConstantFilter.cxx @@ -0,0 +1,49 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#include + +// ------------------------------------------------------------------------- +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 index 0000000..ce038e1 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanConstantFilter.h @@ -0,0 +1,56 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANCONSTANTFILTER__H__ + +#include + +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( ) ITK_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 index 0000000..add2041 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanFilter.cxx @@ -0,0 +1,137 @@ +#include + +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..bd0c17a --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanFilter.h @@ -0,0 +1,215 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANFILTER__H__ + +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#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 + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#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 index 0000000..e81cae2 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanFilter.hxx @@ -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 index 0000000..a725e16 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.cxx @@ -0,0 +1,90 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..781e911 --- /dev/null +++ b/lib/cpExtensions/Algorithms/KalmanVelocityFilter.h @@ -0,0 +1,66 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__KALMANVELOCITYFILTER__H__ + +#include + +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( ) ITK_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 index 0000000..a3c28ff --- /dev/null +++ b/lib/cpExtensions/Algorithms/LightCompensationFilter.h @@ -0,0 +1,65 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__H__ + +#include +#include + +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 +#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 index 0000000..f75ffcd --- /dev/null +++ b/lib/cpExtensions/Algorithms/LightCompensationFilter.hxx @@ -0,0 +1,96 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__LIGHTCOMPENSATIONFILTER__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..e050392 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MFluxMedialness.h @@ -0,0 +1,74 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__H__ + +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TGradient > + class MFluxMedialness + : public GradientImageFunctionBase< _TGradient > + { + public: + typedef MFluxMedialness Self; + typedef GradientImageFunctionBase< _TGradient > 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 ITK_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 +#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 index 0000000..20e7f15 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MFluxMedialness.hxx @@ -0,0 +1,159 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__MFLUXMEDIALNESS__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::MFluxMedialness< _TGradient >:: +MFluxMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_RadialSampling( 4 ), + m_RadiusStep( double( 1 ) ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +cpExtensions::Algorithms::MFluxMedialness< _TGradient >:: +~MFluxMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TGradient > +typename cpExtensions::Algorithms::MFluxMedialness< _TGradient >:: +TOutput cpExtensions::Algorithms::MFluxMedialness< _TGradient >:: +_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:"<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:"<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 index 0000000..d9d3c32 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MacheteImageFilter.h @@ -0,0 +1,72 @@ +// ------------------------------------------------------------------------- +// @author Jose Luis Guzman (cycopepe@gmail.com) +// ------------------------------------------------------------------------- + + +#ifndef __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__H__ + +#include + +#include + +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 & 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 point; + + private: + MacheteImageFilter(const Self &); //purposely not implemented + void operator=(const Self &); //purposely not implemented + + + }; + + } // ecapseman + +} // ecapseman + + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#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 index 0000000..a984df1 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MacheteImageFilter.hxx @@ -0,0 +1,92 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__MACHETEIMAGEFILTER__HXX__ + +#include + +//filter stuff +#include "itkObjectFactory.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" + +//typedef itk::Image 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 outputIterator(output, output->GetLargestPossibleRegion()); + itk::ImageRegionConstIterator inputIterator(input, input->GetLargestPossibleRegion()); + + while (!outputIterator.IsAtEnd()) + { + auto p0 = inputIterator.GetIndex(); + itk::Point 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 & 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 index 0000000..272e839 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h @@ -0,0 +1,85 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__MULTISCALEGAUSSIANIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__MULTISCALEGAUSSIANIMAGEFILTER__H__ + +#include +#include + +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( ) ITK_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 +#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 index 0000000..aff0fd8 --- /dev/null +++ b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx @@ -0,0 +1,226 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__MULTISCALEGAUSSIANIMAGEFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__MULTISCALEGAUSSIANIMAGEFILTER__HXX__ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..6122ce3 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ParallelImageMean.h @@ -0,0 +1,70 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__ +#define __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__H__ + +#include +#include +#include +#include + +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 +#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 index 0000000..b3e4716 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ParallelImageMean.hxx @@ -0,0 +1,65 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__PARALLELIMAGEMEAN__HXX__ + +#include + +// ------------------------------------------------------------------------- +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/RGBExtractFunction.h b/lib/cpExtensions/Algorithms/RGBExtractFunction.h new file mode 100644 index 0000000..ec7126b --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBExtractFunction.h @@ -0,0 +1,54 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBEXTRACTFUNCTION__H__ + +#include +#include +#include + +#include + +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 index 0000000..4ce6754 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.h @@ -0,0 +1,67 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__H__ + +#include + +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 +#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 index 0000000..74578d4 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBImageToOtherChannelsFilter.hxx @@ -0,0 +1,71 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__RGBIMAGETOOTHERCHANNELSFILTER__HXX__ + +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..b10f295 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBToHSVFunction.h @@ -0,0 +1,87 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBTOHSVFUNCTION__H__ + +#include +#include +#include + +#include + +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 index 0000000..83085fe --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBToYPbPrFunction.h @@ -0,0 +1,72 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__ +#define __CPEXTENSIONS__ALGORITHMS__RGBTOYPBPRFUNCTION__H__ + +#include +#include +#include +#include + +#include +#include +#include + +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/RegionOfInterestImageCalculator.h b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h new file mode 100644 index 0000000..84102ad --- /dev/null +++ b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.h @@ -0,0 +1,73 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__ +#define __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__H__ + +#include +#include + +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 +#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 index 0000000..fd7867f --- /dev/null +++ b/lib/cpExtensions/Algorithms/RegionOfInterestImageCalculator.hxx @@ -0,0 +1,92 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__REGIONOFINTERESTIMAGECALCULATOR__HXX__ + +#include + +// ------------------------------------------------------------------------- +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/SpatialObjectMaskImageFilter.h b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h new file mode 100644 index 0000000..2b81fb7 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.h @@ -0,0 +1,87 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__H__ + +#include +#include +#include + +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 +#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 index 0000000..2c3cac7 --- /dev/null +++ b/lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.hxx @@ -0,0 +1,136 @@ +#ifndef __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__SPATIALOBJECTMASKIMAGEFILTER__HXX__ + +#include +#include + +// ------------------------------------------------------------------------- +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 index 0000000..7de8b66 --- /dev/null +++ b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.h @@ -0,0 +1,102 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__UNARYTHRESHOLDIMAGEFILTER__H__ + +#include + +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 +#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 index 0000000..ff85edd --- /dev/null +++ b/lib/cpExtensions/Algorithms/UnaryThresholdImageFilter.hxx @@ -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/CMakeLists.txt b/lib/cpExtensions/CMakeLists.txt new file mode 100644 index 0000000..4920b81 --- /dev/null +++ b/lib/cpExtensions/CMakeLists.txt @@ -0,0 +1,72 @@ +SET(_curdir ${CMAKE_CURRENT_SOURCE_DIR}) +GET_FILENAME_COMPONENT(_lib_name ${_curdir} NAME_WE) + +## ========================= +## = Configure local files = +## ========================= + +FILE(GLOB_RECURSE _lib_config RELATIVE "${_curdir}" "${_curdir}/*.in") +FOREACH(_file ${_lib_config}) + STRING(REGEX REPLACE ".in" "" _outfile ${_file}) + CONFIGURE_FILE(${_file} ${CMAKE_CURRENT_BINARY_DIR}/${_outfile} @ONLY) +ENDFOREACH(_file) + +## ===================== +## == Get source code == +## ===================== + +FILE(GLOB_RECURSE _hdr_h "${_curdir}/*.h") +FILE(GLOB_RECURSE _hdr_hpp "${_curdir}/*.hxx") +FILE(GLOB_RECURSE _hdr_hxx "${_curdir}/*.hpp") +FILE(GLOB_RECURSE _src_c "${_curdir}/*.c") +FILE(GLOB_RECURSE _src_cpp "${_curdir}/*.cpp") +FILE(GLOB_RECURSE _src_cxx "${_curdir}/*.cxx") +FILE(GLOB_RECURSE _qt_ui "${_curdir}/*.ui") + +SET(_src_all ${_src_c} ${_src_cpp} ${_src_cxx}) + +## ==================== +## == Create library == +## ==================== + +IF(_src_all) + IF(USE_QT4) + SET(_hdr_to_wrap) + FOREACH(_h ${_hdr_h}) + FILE(READ ${_h} _txt) + STRING(FIND "${_txt}" "Q_OBJECT" _res) + IF(NOT ${_res} EQUAL -1) + LIST(APPEND _hdr_to_wrap ${_h}) + ENDIF(NOT ${_res} EQUAL -1) + ENDFOREACH(_h) + IF(_hdr_to_wrap) + QT4_WRAP_CPP(_src_qt_moc ${_hdr_to_wrap}) + ENDIF(_hdr_to_wrap) + QT4_WRAP_UI(_hdr_qt_ui ${_qt_ui}) + SET(_src_all ${_src_all} ${_hdr_qt_ui} ${_src_qt_moc}) + ENDIF(USE_QT4) + + ADD_LIBRARY(${_lib_name} SHARED ${_src_all}) + SET_TARGET_PROPERTIES( + ${_lib_name} PROPERTIES + VERSION "${prj_VER}" + SOVERSION "${prj_sVER}" + ) + GENERATE_EXPORT_HEADER( + ${_lib_name} + BASE_NAME ${_lib_name} + EXPORT_MACRO_NAME ${_lib_name}_EXPORT + EXPORT_FILE_NAME ${CMAKE_CURRENT_BINARY_DIR}/${_lib_name}_Export.h + STATIC_DEFINE ${_lib_name}_BUILT_AS_STATIC + ) + IF(USE_QT4) + TARGET_LINK_LIBRARIES( + ${_lib_name} ${ITK_LIBRARIES} ${VTK_LIBRARIES} ${QT_LIBRARIES} + ) + ELSE(USE_QT4) + TARGET_LINK_LIBRARIES(${_lib_name} ${ITK_LIBRARIES} ${VTK_LIBRARIES}) + ENDIF(USE_QT4) + SET(${_lib_name}_LIB ${_lib_name} CACHE INTERNAL "library ${_lib_name}") +ENDIF(_src_all) + +## eof - $RCSfile$ diff --git a/lib/cpExtensions/Config.h.in b/lib/cpExtensions/Config.h.in new file mode 100644 index 0000000..01915ba --- /dev/null +++ b/lib/cpExtensions/Config.h.in @@ -0,0 +1,87 @@ +#ifndef __CPEXTENSIONS__CONFIG__H__ +#define __CPEXTENSIONS__CONFIG__H__ + +#include + +/* + * ========================================================================= + * Identify OS + * ========================================================================= + */ + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +# define cpExtensions_SYS_WINDOWS +# define cpExtensions_PATH_SEPARATOR '\\' +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# define NOMINMAX +# include +# include +#elif defined( linux ) || defined( __linux ) +# define cpExtensions_SYS_LINUX +# define cpExtensions_PATH_SEPARATOR '/' +#elif defined( __APPLE__ ) || defined( MACOSX ) || defined( macintosh ) || defined( Macintosh ) +# define cpExtensions_SYS_MACOS +# define cpExtensions_PATH_SEPARATOR '/' +#elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) +# define cpExtensions_SYS_FREEBSD +# define cpExtensions_PATH_SEPARATOR '/' +#else +# error "This operating system is not supported by this project" +#endif + +/* + * ========================================================================= + * Some global values + * ========================================================================= + */ + +#define cpExtensions_QT4_USED @QT4_FOUND@ +#if cpExtensions_QT4_USED == 1 +# define cpExtensions_QT4 +#else // cpExtensions_QT4_USED == 1 +# undef cpExtensions_QT4 +#endif // cpExtensions_QT4_USED == 1 + +/* + * ========================================================================= + * Version numbers and strings + * ========================================================================= + */ + +#define cpExtensions_MAJOR_VERSION @prj_MAJ_VER@ +#define cpExtensions_MINOR_VERSION @prj_MIN_VER@ +#define cpExtensions_RELEASE_VERSION @prj_REL_VER@ +#define cpExtensions_VERSION "@prj_VERSION@" +#define cpExtensions_SHORT_VERSION "@prj_SHORT_VERSION@" + +/* + * ========================================================================= + * ITK related macros + * ========================================================================= + */ + +#include +#define ITK_MANUAL_INSTANTIATION +#ifndef ITK_DELETE_FUNCTION +# define ITK_DELETE_FUNCTION +#endif // ITK_DELETE_FUNCTION +#ifndef ITK_OVERRIDE +# define ITK_OVERRIDE +#endif // ITK_OVERRIDE + +/* + * ========================================================================= + * VTK related macros + * ========================================================================= + */ + +#include +#ifndef VTK_OVERRIDE +# define VTK_OVERRIDE +#endif // VTK_OVERRIDE + +#endif // __CPEXTENSIONS__CONFIG__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/Graph.h b/lib/cpExtensions/DataStructures/Graph.h new file mode 100644 index 0000000..75bdd68 --- /dev/null +++ b/lib/cpExtensions/DataStructures/Graph.h @@ -0,0 +1,166 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__GRAPH__H__ + +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** \brief A generic graph with templated index types. + * + * @param V Vertex type. + * @param C Cost type. + * @param I Index type (it should be a strict weak ordering type). + */ + template< class V, class C, class I = unsigned long > + class Graph + : public itk::LightObject + { + public: + typedef Graph Self; + typedef itk::LightObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef V TVertex; + typedef C TCost; + typedef I TIndex; + + // Base types + typedef std::map< TIndex, TVertex > TVertices; + typedef std::vector< TCost > TEdges; + typedef std::map< TIndex, TEdges > TMatrixRow; + typedef std::map< TIndex, TMatrixRow > TMatrix; + + public: + itkNewMacro( Self ); + itkTypeMacro( Graph, itk::LightObject ); + + 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 I& i ) const + { return( this->m_Vertices.find( i ) != this->m_Vertices.end( ) ); } + inline void SetVertex( const I& index, V& vertex ) + { this->m_Vertices[ index ] = vertex; } + inline V& GetVertex( const I& index ) + { return( this->m_Vertices[ index ] ); } + inline const V& GetVertex( const I& index ) const + { return( this->m_Vertices[ index ] ); } + bool RenameVertex( const I& old_index, const I& new_index ); + void RemoveVertex( const I& index ); + + /*! \brief Edge manipulation methods. + * Names are self-explanatory. + */ + inline void AddEdge( const I& orig, const I& dest, const C& cost ) + { this->m_Matrix[ orig ][ dest ].push_back( cost ); } + inline TEdges& GetEdges( const I& orig, const I& dest ) + { return( this->m_Matrix[ orig ][ dest ] ); } + inline const TEdges& GetEdges( const I& orig, const I& dest ) const + { return( this->m_Matrix[ orig ][ dest ] ); } + bool HasEdge( const I& orig, const I& dest ) const; + void RemoveEdge( const I& orig, const I& dest, const C& cost ); + void RemoveEdges( const I& orig, const I& 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< I > 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 +#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 index 0000000..d2d2d23 --- /dev/null +++ b/lib/cpExtensions/DataStructures/Graph.hxx @@ -0,0 +1,208 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__GRAPH__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__GRAPH__HXX__ + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +void cpExtensions::DataStructures::Graph< V, C, I >:: +Clear( ) +{ + this->m_Vertices.clear( ); + this->m_Matrix.clear( ); +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +bool cpExtensions::DataStructures::Graph< V, C, I >:: +RenameVertex( const I& old_index, const I& 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 V, class C, class I > +void cpExtensions::DataStructures::Graph< V, C, I >:: +RemoveVertex( const I& 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 V, class C, class I > +bool cpExtensions::DataStructures::Graph< V, C, I >:: +HasEdge( const I& orig, const I& 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 V, class C, class I > +void cpExtensions::DataStructures::Graph< V, C, I >:: +RemoveEdge( const I& orig, const I& dest, const C& 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 = std::find( r->second.begin( ), r->second.end( ), cost ); + 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 V, class C, class I > +void cpExtensions::DataStructures::Graph< V, C, I >:: +RemoveEdges( const I& orig, const I& 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 V, class C, class I > +std::set< I > cpExtensions::DataStructures::Graph< V, C, I >:: +GetSinks( ) const +{ + std::set< I > 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 V, class C, class I > +cpExtensions::DataStructures::Graph< V, C, I >:: +Graph( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class V, class C, class I > +cpExtensions::DataStructures::Graph< V, C, I >:: +~Graph( ) +{ +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__GRAPH__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/ImageIndexesContainer.h b/lib/cpExtensions/DataStructures/ImageIndexesContainer.h new file mode 100644 index 0000000..00dbf64 --- /dev/null +++ b/lib/cpExtensions/DataStructures/ImageIndexesContainer.h @@ -0,0 +1,66 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__IMAGEINDEXESCONTAINER__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__IMAGEINDEXESCONTAINER__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< unsigned int _NDim > + class ImageIndexesContainer + : public itk::SimpleDataObjectDecorator< std::vector< itk::Index< _NDim > > > + { + public: + typedef itk::Index< _NDim > TIndex; + typedef std::vector< TIndex > TContainer; + typedef itk::SimpleDataObjectDecorator< TContainer > Superclass; + + typedef ImageIndexesContainer Self; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef itk::ImageBase< _NDim > TImageBase; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageIndexesContainer, itk::SimpleDataObjectDecorator ); + + public: + TImageBase* GetReferenceImage( ) + { return( this->m_ReferenceImage ); } + const TImageBase* GetReferenceImage( ) const + { return( this->m_ReferenceImage ); } + void SetReferenceImage( const TImageBase* image ) + { + this->m_ReferenceImage = TImageBase::New( ); + this->m_ReferenceImage->SetDirection( image->GetDirection( ) ); + this->m_ReferenceImage->SetOrigin( image->GetOrigin( ) ); + this->m_ReferenceImage->SetSpacing( image->GetSpacing( ) ); + this->Modified( ); + } + + protected: + ImageIndexesContainer( ) { } + virtual ~ImageIndexesContainer( ) { } + + private: + // Purposely not implemented + ImageIndexesContainer( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TImageBase::Pointer m_ReferenceImage; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__DATASTRUCTURES__IMAGEINDEXESCONTAINER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/PolyLineParametricPath.h b/lib/cpExtensions/DataStructures/PolyLineParametricPath.h new file mode 100644 index 0000000..77828ee --- /dev/null +++ b/lib/cpExtensions/DataStructures/PolyLineParametricPath.h @@ -0,0 +1,62 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__POLYLINEPARAMETRICPATH__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__POLYLINEPARAMETRICPATH__H__ + +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< unsigned int _NDim > + class PolyLineParametricPath + : public itk::PolyLineParametricPath< _NDim > + { + public: + typedef PolyLineParametricPath Self; + typedef itk::PolyLineParametricPath< _NDim > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef itk::ImageBase< _NDim > TImageBase; + + public: + itkNewMacro( Self ); + itkTypeMacro( PolyLineParametricPath, itk::PolyLineParametricPath ); + + public: + TImageBase* GetReferenceImage( ) + { return( this->m_ReferenceImage ); } + const TImageBase* GetReferenceImage( ) const + { return( this->m_ReferenceImage ); } + void SetReferenceImage( const TImageBase* image ) + { + this->m_ReferenceImage = TImageBase::New( ); + this->m_ReferenceImage->SetDirection( image->GetDirection( ) ); + this->m_ReferenceImage->SetOrigin( image->GetOrigin( ) ); + this->m_ReferenceImage->SetSpacing( image->GetSpacing( ) ); + this->Modified( ); + } + + protected: + PolyLineParametricPath( ) { } + virtual ~PolyLineParametricPath( ) { } + + private: + // Purposely not implemented + PolyLineParametricPath( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename TImageBase::Pointer m_ReferenceImage; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__DATASTRUCTURES__POLYLINEPARAMETRICPATH__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/BaseInteractorStyle.cxx b/lib/cpExtensions/Interaction/BaseInteractorStyle.cxx new file mode 100644 index 0000000..6c0ebbe --- /dev/null +++ b/lib/cpExtensions/Interaction/BaseInteractorStyle.cxx @@ -0,0 +1,568 @@ +#include + +#include + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +long cpExtensions::Interaction::BaseInteractorStyle::_TMouseButtonEvent:: +MaxDoubleClick = 350; // ms + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +SetSetDoubleClickDelay( long delay ) +{ + Self::_TMouseButtonEvent::MaxDoubleClick = delay; +} + +// ------------------------------------------------------------------------- +vtkObject* cpExtensions::Interaction::BaseInteractorStyle:: +GetAssociatedObject( ) +{ + return( this->m_AssociatedObject ); +} + +// ------------------------------------------------------------------------- +const vtkObject* cpExtensions::Interaction::BaseInteractorStyle:: +GetAssociatedObject( ) const +{ + return( this->m_AssociatedObject ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +SetAssociatedObject( vtkObject* obj ) +{ + if( this->m_AssociatedObject != obj ) + { + this->m_AssociatedObject = obj; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +DelegateTDxEvent( unsigned long event, void* calldata ) +{ + // TODO + std::cerr << "No TDx support at this time!" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnMouseMove( ) +{ + // Get current position on the associated actors + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Get modifiers + bool alt = ( rwi->GetAltKey( ) == 1 ); + bool ctr = ( rwi->GetControlKey( ) == 1 ); + bool sft = ( rwi->GetShiftKey( ) == 1 ); + ButtonID button = this->GetButtonID( ); + + // Invoke possible generic events + if( button == Self::ButtonID_Right ) + { + if( !alt && !ctr && !sft ) + { + this->FindPokedRenderer( + rwi->GetEventPosition( )[ 0 ], + rwi->GetEventPosition( )[ 1 ] + ); + this->Dolly( ); + + } // fi + } + else if( button == Self::ButtonID_Middle ) + { + if( !alt && !ctr && !sft ) + { + this->FindPokedRenderer( + rwi->GetEventPosition( )[ 0 ], + rwi->GetEventPosition( )[ 1 ] + ); + this->Pan( ); + + } // fi + + } // fi + + // Get mouse pointer position + static int idx[ 2 ]; + static double pos[ 3 ]; + if( !( this->_PickPosition( idx, pos ) ) ) + return; + + // Invoke possible specialized events + auto i = this->m_MouseMoveCommands.begin( ); + for( ; i != this->m_MouseMoveCommands.end( ); ++i ) + i->first( i->second, button, idx, pos, alt, ctr, sft ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnMouseWheelForward( ) +{ + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Invoke possible events + auto i = this->m_MouseWheelCommands.begin( ); + for( ; i != this->m_MouseWheelCommands.end( ); ++i ) + i->first( + i->second, 1, + rwi->GetAltKey( ) == 1, + rwi->GetControlKey( ) == 1, + rwi->GetShiftKey( ) == 1 + ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnMouseWheelBackward( ) +{ + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Invoke possible events + auto i = this->m_MouseWheelCommands.begin( ); + for( ; i != this->m_MouseWheelCommands.end( ); ++i ) + i->first( + i->second, -1, + rwi->GetAltKey( ) == 1, + rwi->GetControlKey( ) == 1, + rwi->GetShiftKey( ) == 1 + ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnLeftButtonDown( ) +{ + this->m_ActiveButton = Self::ButtonID_Left; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnLeftButtonUp( ) +{ + this->m_ActiveButton = Self::ButtonID_None; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnMiddleButtonDown( ) +{ + this->m_ActiveButton = Self::ButtonID_Middle; + + // Get current position on the associated actors + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Get modifiers + bool alt = ( rwi->GetAltKey( ) == 1 ); + bool ctr = ( rwi->GetControlKey( ) == 1 ); + bool sft = ( rwi->GetShiftKey( ) == 1 ); + + if( !alt && !ctr && !sft ) + this->StartPan( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnMiddleButtonUp( ) +{ + this->m_ActiveButton = Self::ButtonID_None; + + // Get current position on the associated actors + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Get modifiers + bool alt = ( rwi->GetAltKey( ) == 1 ); + bool ctr = ( rwi->GetControlKey( ) == 1 ); + bool sft = ( rwi->GetShiftKey( ) == 1 ); + + switch( this->State ) + { + case VTKIS_PAN: + this->EndPan( ); + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnRightButtonDown( ) +{ + this->m_ActiveButton = Self::ButtonID_Right; + + // Get current position on the associated actors + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Get modifiers + bool alt = ( rwi->GetAltKey( ) == 1 ); + bool ctr = ( rwi->GetControlKey( ) == 1 ); + bool sft = ( rwi->GetShiftKey( ) == 1 ); + + if( !alt && !ctr && !sft ) + this->StartDolly( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnRightButtonUp( ) +{ + this->m_ActiveButton = Self::ButtonID_None; + + // Get current position on the associated actors + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Get modifiers + bool alt = ( rwi->GetAltKey( ) == 1 ); + bool ctr = ( rwi->GetControlKey( ) == 1 ); + bool sft = ( rwi->GetShiftKey( ) == 1 ); + + switch( this->State ) + { + case VTKIS_DOLLY: + this->EndDolly( ); + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +#define cpExtensions_BaseInteractorStyle_Click( S, T ) \ + void cpExtensions::Interaction::BaseInteractorStyle:: \ + On##S##T( ) \ + { \ + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); \ + if( rwi == 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, \ + rwi->GetAltKey( ) == 1, \ + rwi->GetControlKey( ) == 1, \ + rwi->GetShiftKey( ) == 1 \ + ); \ + } + +cpExtensions_BaseInteractorStyle_Click( Left, Click ); +cpExtensions_BaseInteractorStyle_Click( Middle, Click ); +cpExtensions_BaseInteractorStyle_Click( Right, Click ); +cpExtensions_BaseInteractorStyle_Click( Left, DoubleClick ); +cpExtensions_BaseInteractorStyle_Click( Middle, DoubleClick ); +cpExtensions_BaseInteractorStyle_Click( Right, DoubleClick ); + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +OnChar( ) +{ + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return; + + // Invoke possible events + auto i = this->m_KeyCommands.begin( ); + for( ; i != this->m_KeyCommands.end( ); ++i ) + i->first( i->second, rwi->GetKeyCode( ) ); +} + +// ------------------------------------------------------------------------- +#define cpExtensions_BaseInteractorStyle_Global( N ) \ + void cpExtensions::Interaction::BaseInteractorStyle:: \ + On##N( ) \ + { \ + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); \ + if( rwi == NULL ) \ + return; \ + auto i = this->m_##N##Commands.begin( ); \ + for( ; i != this->m_##N##Commands.end( ); ++i ) \ + i->first( i->second ); \ + } + +cpExtensions_BaseInteractorStyle_Global( Expose ); +cpExtensions_BaseInteractorStyle_Global( Configure ); +cpExtensions_BaseInteractorStyle_Global( Enter ); +cpExtensions_BaseInteractorStyle_Global( Leave ); + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +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::BaseInteractorStyle:: +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::BaseInteractorStyle:: +BaseInteractorStyle( ) + : Superclass( ), + m_AssociatedObject( NULL ), + 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::BaseInteractorStyle:: +~BaseInteractorStyle( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::BaseInteractorStyle:: +_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::BaseInteractorStyle:: +_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/BaseInteractorStyle.h b/lib/cpExtensions/Interaction/BaseInteractorStyle.h new file mode 100644 index 0000000..679fb9e --- /dev/null +++ b/lib/cpExtensions/Interaction/BaseInteractorStyle.h @@ -0,0 +1,226 @@ +#ifndef __CPEXTENSIONS__INTERACTION__BASEINTERACTORSTYLE__H__ +#define __CPEXTENSIONS__INTERACTION__BASEINTERACTORSTYLE__H__ + +#include + +#include +#include +#include + +#include + +/* ========================================================================= + * Double click algorithm inspired from: + * http://www.autohotkey.com/board/topic/56493-easiest-way-to-detect-double-clicks/ + * ========================================================================= + */ + +// ------------------------------------------------------------------------- +#define cpExtensions_BaseInteractorStyle_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( ); \ + } \ + } + +// ------------------------------------------------------------------------- +#define BaseInteractorStyle_DIFF_TIME \ + std::chrono::duration_cast< std::chrono::milliseconds >( \ + std::chrono::system_clock::now( ).time_since_epoch( ) \ + ).count( ) + +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT BaseInteractorStyle + : public vtkInteractorStyle + { + public: + typedef BaseInteractorStyle Self; + vtkTypeMacro( BaseInteractorStyle, 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 void ( *TMouseWheelCommand )( void*, const int&, bool, bool, bool ); + typedef void ( *TKeyCommand )( void*, const char& ); + typedef void ( *TVoidCommand )( void* ); + typedef TMouseCommand TMouseMoveCommand; + typedef TMouseCommand TMouseClickCommand; + typedef TMouseCommand TMouseDoubleClickCommand; + typedef TVoidCommand TExposeCommand; + typedef TVoidCommand TConfigureCommand; + typedef TVoidCommand TEnterCommand; + typedef TVoidCommand TLeaveCommand; + + // Associate callbacks for each event + cpExtensions_BaseInteractorStyle_Commands( MouseMove ); + cpExtensions_BaseInteractorStyle_Commands( MouseClick ); + cpExtensions_BaseInteractorStyle_Commands( MouseDoubleClick ); + cpExtensions_BaseInteractorStyle_Commands( MouseWheel ); + cpExtensions_BaseInteractorStyle_Commands( Key ); + cpExtensions_BaseInteractorStyle_Commands( Expose ); + cpExtensions_BaseInteractorStyle_Commands( Configure ); + cpExtensions_BaseInteractorStyle_Commands( Enter ); + cpExtensions_BaseInteractorStyle_Commands( Leave ); + + public: + vtkObject* GetAssociatedObject( ); + const vtkObject* GetAssociatedObject( ) const; + void SetAssociatedObject( vtkObject* obj ); + + static void SetSetDoubleClickDelay( long delay ); + void DelegateTDxEvent( unsigned long event, void* calldata ); + + // Possible mouse motion events + virtual void OnMouseMove( ); + virtual void OnMouseWheelForward( ); + virtual void OnMouseWheelBackward( ); + + // Possible mouse click-related events + inline ButtonID GetButtonID( ) const + { + return( this->m_ActiveButton ); + } + + virtual void OnLeftButtonDown( ); + virtual void OnLeftButtonUp( ); + virtual void OnMiddleButtonDown( ); + virtual void OnMiddleButtonUp( ); + virtual void OnRightButtonDown( ); + virtual void OnRightButtonUp( ); + + virtual void OnLeftClick( ); + virtual void OnLeftDoubleClick( ); + virtual void OnMiddleClick( ); + virtual void OnMiddleDoubleClick( ); + virtual void OnRightClick( ); + virtual void OnRightDoubleClick( ); + + // Keyboard-related events + virtual void OnChar( ); + virtual void OnKeyDown( ) { } + virtual void OnKeyUp( ) { } + virtual void OnKeyPress( ) { } + virtual void OnKeyRelease( ) { } + + // Other events + virtual void OnExpose( ); + virtual void OnConfigure( ); + virtual void OnEnter( ); + virtual void OnLeave( ); + + virtual void Dolly( ); + virtual void Pan( ); + + protected: + BaseInteractorStyle( ); + virtual ~BaseInteractorStyle( ); + + 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 + BaseInteractorStyle( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkObject* m_AssociatedObject; + 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( ) + { + long c = BaseInteractorStyle_DIFF_TIME; + this->m_LastButtonUp = c; + this->m_LastButtonHeld = c - this->m_LastButtonDown; + this->m_LastButtonDown = -1; + } + inline unsigned char Clicks( ) + { + unsigned char n = 0; + long c = BaseInteractorStyle_DIFF_TIME; + 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 ); + } + }; + _TMouseButtonEvent m_LeftButtonEvent; + _TMouseButtonEvent m_MiddleButtonEvent; + _TMouseButtonEvent m_RightButtonEvent; + ButtonID m_ActiveButton; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__INTERACTION__BASEINTERACTORSTYLE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx b/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx new file mode 100644 index 0000000..f2781dc --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx @@ -0,0 +1,259 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +/* TODO + cpExtensions::Interaction::ImageInteractorStyle::TSeedWidget:: + TSeedWidget( vtkRenderWindowInteractor* interactor, vtkImageActor* actor ) + { + this->Placer = vtkSmartPointer< vtkImageActorPointPlacer >::New( ); + this->Handle = vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + this->Representation = vtkSmartPointer< vtkSeedRepresentation >::New( ); + this->Widget = vtkSmartPointer< SeedWidget >::New( ); + + this->Placer->SetImageActor( actor ); + this->Handle->GetProperty( )->SetColor( 1, 0, 0 ); + this->Handle->SetPointPlacer( this->Placer ); + this->Representation->SetHandleRepresentation( this->Handle ); + this->Widget->SetRepresentation( this->Representation ); + this->Widget->SetInteractor( interactor ); + } + + // ------------------------------------------------------------------------- + void cpExtensions::Interaction::ImageInteractorStyle::TSeedWidget:: + On( ) + { + this->Widget->On( ); + } + + // ------------------------------------------------------------------------- + void cpExtensions::Interaction::ImageInteractorStyle::TSeedWidget:: + Off( ) + { + this->Widget->Off( ); + } +*/ + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageInteractorStyle:: +Self* cpExtensions::Interaction::ImageInteractorStyle:: +New( ) +{ + return( new Self ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +SetCurrentRenderer( vtkRenderer* r ) +{ + this->Superclass::SetCurrentRenderer( r ); + + if( !( this->m_Configured ) ) + { + auto lst = this->m_PropPicker->GetPickList( ); + if( lst == NULL ) + return; + if( lst->GetNumberOfItems( ) == 1 ) + { + auto actor = dynamic_cast< vtkImageActor* >( lst->GetItemAsObject( 0 ) ); + if( actor != NULL ) + { + this->_ConfigureCamera( actor ); + this->Modified( ); + + } // fi + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +AssociateImageActor( vtkImageActor* actor ) +{ + if( actor != NULL ) + { + // Update picker + this->m_PropPicker->GetPickList( )->RemoveAllItems( ); + this->m_PropPicker->AddPickList( actor ); + this->m_Configured = false; + this->_ConfigureCamera( actor ); + + // Ok, done + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +/* +void cpExtensions::Interaction::ImageInteractorStyle:: +SeedWidgetOn( ) +{ + if( this->m_SeedWidget != NULL ) delete this->m_SeedWidget; + + this->m_PropPicker->GetPickList( )->InitTraversal( ); + this->m_SeedWidget = new TSeedWidget( + this->Interactor, + dynamic_cast< vtkImageActor* >( + this->m_PropPicker->GetPickList( )->GetNextProp( ) + ) + ); + this->m_SeedWidget->On( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +SeedWidgetOff( ) +{ + if( this->m_SeedWidget != NULL ) + { + this->m_SeedWidget->Off( ); + delete this->m_SeedWidget; + this->m_SeedWidget = NULL; + + } // fi +} +*/ + +// ------------------------------------------------------------------------- +/* +void cpExtensions::Interaction::ImageInteractorStyle:: +SetSeedWidgetCommand( vtkCommand* cmd ) +{ + if( cmd == NULL || this->m_SeedWidget == NULL ) + return; + this->m_SeedWidget->Widget-> + AddObserver( vtkCommand::PlacePointEvent, cmd ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Interaction::ImageInteractorStyle:: +GetNumberOfSeeds( ) const +{ + if( this->m_SeedWidget != NULL ) + return( this->m_SeedWidget->Representation->GetNumberOfSeeds( ) ); + else + return( 0 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +GetSeedAsPoint( unsigned int id, double pos[ 3 ] ) const +{ + if( this->m_SeedWidget != NULL ) + this->m_SeedWidget->Representation->GetSeedWorldPosition( id, pos ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +GetSeedAsIndex( unsigned int id, int idx[ 3 ] ) const +{ + if( this->m_SeedWidget != NULL ) + this->m_SeedWidget->Representation->GetSeedWorldPosition( id, pos ); +} +*/ + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageInteractorStyle:: +ImageInteractorStyle( ) + : Superclass( ), + m_Configured( false ) + /* + , + m_SeedWidget( NULL ) + */ +{ + this->m_PropPicker = vtkSmartPointer< vtkPropPicker >::New( ); + this->m_PropPicker->PickFromListOn( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageInteractorStyle:: +~ImageInteractorStyle( ) +{ + // if( this->m_SeedWidget != NULL ) delete this->m_SeedWidget; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::ImageInteractorStyle:: +_ConfigureCamera( vtkImageActor* actor ) +{ + if( this->CurrentRenderer != NULL ) + { + // Update camera + auto camera = this->CurrentRenderer->GetActiveCamera( ); + auto mapper = dynamic_cast< vtkImageSliceMapper* >( actor->GetMapper( ) ); + if( mapper != NULL && camera != NULL ) + { + double bounds[ 6 ]; + actor->GetBounds( bounds ); + camera->ParallelProjectionOn( ); + camera->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) ); + int orientation = mapper->GetOrientation( ); + switch( orientation ) + { + case 0: + { + camera->SetPosition( double( 1 ), double( 0 ), double( 0 ) ); + camera->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) ); + } + break; + case 1: + { + camera->SetPosition( double( 0 ), double( 1 ), double( 0 ) ); + camera->SetViewUp ( double( 0 ), double( 0 ), double( -1 ) ); + } + break; + case 2: + { + camera->SetPosition( double( 0 ), double( 0 ), double( 1 ) ); + camera->SetViewUp ( double( 0 ), double( 1 ), double( 0 ) ); + } + break; + default: + break; + } // hctiws + this->CurrentRenderer->ResetCamera( ); + this->m_Configured = true; + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpExtensions::Interaction::ImageInteractorStyle:: +_PickPosition( int idx[ 2 ], double pos[ 3 ] ) +{ + vtkRenderWindowInteractor* rwi = this->GetInteractor( ); + if( rwi == NULL ) + return( false ); + + // Find the renderer where the event has been raised + idx[ 0 ] = rwi->GetEventPosition( )[ 0 ]; + idx[ 1 ] = rwi->GetEventPosition( )[ 1 ]; + this->FindPokedRenderer( double( idx[ 0 ] ), double( idx[ 1 ] ) ); + + // 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( pos ); + return( true ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/ImageInteractorStyle.h b/lib/cpExtensions/Interaction/ImageInteractorStyle.h new file mode 100644 index 0000000..c02f65d --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageInteractorStyle.h @@ -0,0 +1,108 @@ +#ifndef __CPEXTENSIONS__INTERACTION__IMAGEINTERACTORSTYLE__H__ +#define __CPEXTENSIONS__INTERACTION__IMAGEINTERACTORSTYLE__H__ + +#include + +#include + +#include +#include +/* TODO + #include + #include + #include + #include +*/ + +// Forward definitions +class vtkCommand; +class vtkImageActor; + +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT ImageInteractorStyle + : public BaseInteractorStyle + { + public: + typedef ImageInteractorStyle Self; + vtkTypeMacro( ImageInteractorStyle, BaseInteractorStyle ); + + // Callbacks types + typedef Superclass::TMouseCommand TMouseCommand; + typedef Superclass::TMouseWheelCommand TMouseWheelCommand; + typedef Superclass::TKeyCommand TKeyCommand; + typedef Superclass::TVoidCommand TVoidCommand; + typedef Superclass::TMouseMoveCommand TMouseMoveCommand; + typedef Superclass::TMouseClickCommand TMouseClickCommand; + typedef Superclass::TMouseDoubleClickCommand TMouseDoubleClickCommand; + typedef Superclass::TExposeCommand TExposeCommand; + typedef Superclass::TConfigureCommand TConfigureCommand; + typedef Superclass::TEnterCommand TEnterCommand; + typedef Superclass::TLeaveCommand TLeaveCommand; + + // Widgets + /* TODO + struct TSeedWidget + { + vtkSmartPointer< vtkImageActorPointPlacer > Placer; + vtkSmartPointer< vtkPointHandleRepresentation3D > Handle; + vtkSmartPointer< vtkSeedRepresentation > Representation; + vtkSmartPointer< SeedWidget > Widget; + + TSeedWidget( + vtkRenderWindowInteractor* interactor, vtkImageActor* actor + ); + void On( ); + void Off( ); + }; + */ + + public: + static Self* New( ); + + virtual void SetCurrentRenderer( vtkRenderer* r ) VTK_OVERRIDE; + + // Data for local picker + virtual void AssociateImageActor( vtkImageActor* actor ); + + // Widgets + /* TODO + void SeedWidgetOn( ); + void SeedWidgetOff( ); + void SetSeedWidgetCommand( vtkCommand* cmd ); + unsigned int GetNumberOfSeeds( ) const; + void GetSeedAsPoint( unsigned int id, double pos[ 3 ] ) const; + void GetSeedAsIndex( unsigned int id, int pos[ 3 ] ) const; + */ + + protected: + ImageInteractorStyle( ); + virtual ~ImageInteractorStyle( ); + + void _ConfigureCamera( vtkImageActor* actor ); + virtual bool _PickPosition( int idx[ 2 ], double pos[ 3 ] ); + + private: + // Purposely not implemented + ImageInteractorStyle( const Self& ); + Self& operator=( const Self& ); + + protected: + bool m_Configured; + vtkSmartPointer< vtkPropPicker > m_PropPicker; + /* TODO + TSeedWidget* m_SeedWidget; + */ + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__INTERACTION__IMAGEINTERACTORSTYLE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/SeedWidget.cxx b/lib/cpExtensions/Interaction/SeedWidget.cxx new file mode 100644 index 0000000..73d13a5 --- /dev/null +++ b/lib/cpExtensions/Interaction/SeedWidget.cxx @@ -0,0 +1,93 @@ +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SeedWidget:: +Self* cpExtensions::Interaction::SeedWidget:: +New( ) +{ + return( new Self ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SeedWidget:: +SetInteractor( vtkRenderWindowInteractor* rwi ) +{ + this->Superclass::SetInteractor( rwi ); + 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( ) +{ + // Remove default translations + vtkWidgetEventTranslator* t = this->GetEventTranslator( ); + t->RemoveTranslation( vtkCommand::LeftButtonPressEvent ); + t->RemoveTranslation( vtkCommand::MiddleButtonPressEvent ); + t->RemoveTranslation( vtkCommand::RightButtonPressEvent ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SeedWidget:: +~SeedWidget( ) +{ +} + +// ------------------------------------------------------------------------- +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 index 0000000..964f1c2 --- /dev/null +++ b/lib/cpExtensions/Interaction/SeedWidget.h @@ -0,0 +1,54 @@ +#ifndef __CPEXTENSIONS__INTERACTION__SEEDWIDGET__H__ +#define __CPEXTENSIONS__INTERACTION__SEEDWIDGET__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT SeedWidget + : public vtkSeedWidget + { + public: + typedef SeedWidget Self; + vtkTypeMacro( SeedWidget, vtkSeedWidget ); + + typedef cpExtensions::Interaction::BaseInteractorStyle TBaseStyle; + typedef TBaseStyle::TMouseCommand TMouseCommand; + + public: + static Self* New( ); + + virtual void SetInteractor( vtkRenderWindowInteractor* rwi ); + + protected: + SeedWidget( ); + virtual ~SeedWidget( ); + + 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/DicomSeriesSelectorWidget.cxx b/lib/cpExtensions/QT/DicomSeriesSelectorWidget.cxx new file mode 100644 index 0000000..bb81a84 --- /dev/null +++ b/lib/cpExtensions/QT/DicomSeriesSelectorWidget.cxx @@ -0,0 +1,162 @@ +#include + +#ifdef cpExtensions_QT4 + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::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( ) ) + ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::DicomSeriesSelectorWidget:: +~DicomSeriesSelectorWidget( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +QString cpExtensions::QT::DicomSeriesSelectorWidget:: +startDir( ) const +{ + return( this->m_UI->Directory->text( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::DicomSeriesSelectorWidget:: +setStartDir( const QString& dir, bool build ) +{ + 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 ); + + itk::GDCMSeriesFileNames::GlobalWarningDisplayOff( ); + 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( ); + + // Get series + itk::GDCMSeriesFileNames::Pointer series = + itk::GDCMSeriesFileNames::New( ); + series->SetUseSeriesDetails( true ); + series->AddSeriesRestriction( "0008|0021" ); + series->SetDirectory( dir_name ); + const std::vector< std::string >& seriesUID = series->GetSeriesUIDs( ); + for( auto sIt = seriesUID.begin( ); sIt != seriesUID.end( ); ++sIt ) + { + unsigned long rows = this->m_UI->Series->rowCount( ); + this->m_UI->Series->insertRow( rows ); + std::stringstream str_count; + str_count << series->GetFileNames( *sIt ).size( ); + QTableWidgetItem* count_item = + new QTableWidgetItem( str_count.str( ).c_str( ) ); + QTableWidgetItem* uid_item = + new QTableWidgetItem( sIt->c_str( ) ); + QTableWidgetItem* dir_item = + new QTableWidgetItem( dir_name.substr( dir.size( ) + 1 ).c_str( ) ); + 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 ); + + } // rof + + // Update queue + QDir dir( dir_name.c_str( ) ); + QFileInfoList contents = dir.entryInfoList( ); + QFileInfoList::const_iterator i = contents.begin( ); + 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 ); + + } // fi + + } // rof + + } // elihw + + // Restore cursor + QApplication::restoreOverrideCursor( ); + itk::GDCMSeriesFileNames::GlobalWarningDisplayOn( ); +} + +// ------------------------------------------------------------------------- +std::vector< std::string > cpExtensions::QT::DicomSeriesSelectorWidget:: +selectedFilenames( ) +{ + std::vector< std::string > filenames; + auto items = this->m_UI->Series->selectedItems( ); + if( items.size( ) > 0 ) + { + std::string dir = + this->m_UI->Series-> + item( items[ 0 ]->row( ), 2 )->text( ).toStdString( ); + dir = this->startDir( ).toStdString( ) + "/" + dir; + itk::GDCMSeriesFileNames::GlobalWarningDisplayOff( ); + + itk::GDCMSeriesFileNames::Pointer series = + itk::GDCMSeriesFileNames::New( ); + series->SetUseSeriesDetails( true ); + series->AddSeriesRestriction( "0008|0021" ); + series->SetDirectory( dir ); + filenames = series->GetFileNames( + this->m_UI->Series->item( + items[ 0 ]->row( ), 1 + )->text( ).toStdString( ) + ); + itk::GDCMSeriesFileNames::GlobalWarningDisplayOn( ); + + } // fi + return( filenames ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::DicomSeriesSelectorWidget:: +_Choose( ) +{ + QString qdir = + QFileDialog::getExistingDirectory( + this, tr( "Open Directory" ), + this->startDir( ), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks + ); + if( qdir.toStdString( ) != "" ) + this->setStartDir( qdir ); +} + +#endif // cpExtensions_QT4 + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/DicomSeriesSelectorWidget.h b/lib/cpExtensions/QT/DicomSeriesSelectorWidget.h new file mode 100644 index 0000000..b30df8e --- /dev/null +++ b/lib/cpExtensions/QT/DicomSeriesSelectorWidget.h @@ -0,0 +1,55 @@ +#ifndef __CPEXTENSIONS__QT__DICOMSERIESSELECTORWIDGET__H__ +#define __CPEXTENSIONS__QT__DICOMSERIESSELECTORWIDGET__H__ + +#include + +#ifdef cpExtensions_QT4 + +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class DicomSeriesSelectorWidget; +} + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + /** + */ + class cpExtensions_EXPORT DicomSeriesSelectorWidget + : public QWidget + { + Q_OBJECT; + + public: + typedef DicomSeriesSelectorWidget Self; + + 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; + }; + + } // ecapseman + +} // ecapseman + +#endif // cpExtensions_QT4 + +#endif // __CPEXTENSIONS__QT__DICOMSERIESSELECTORWIDGET__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/DicomSeriesSelectorWidget.ui b/lib/cpExtensions/QT/DicomSeriesSelectorWidget.ui new file mode 100644 index 0000000..6ab392c --- /dev/null +++ b/lib/cpExtensions/QT/DicomSeriesSelectorWidget.ui @@ -0,0 +1,89 @@ + + + DicomSeriesSelectorWidget + + + + 0 + 0 + 358 + 299 + + + + Form + + + + 1 + + + 1 + + + + + + + + 101 + 14 + + + + + 101 + 14 + + + + DICOM directory: + + + + + + + true + + + true + + + + + + + + 25 + 25 + + + + + 25 + 25 + + + + ... + + + + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + + diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.cxx b/lib/cpExtensions/QT/SimpleMPRWidget.cxx new file mode 100644 index 0000000..d8c6822 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.cxx @@ -0,0 +1,408 @@ +#include + +#ifdef cpExtensions_QT4 + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget::_3DInteractorStyle* +cpExtensions::QT::SimpleMPRWidget::_3DInteractorStyle:: +New( ) +{ + return( new _3DInteractorStyle( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget::_3DInteractorStyle:: +OnKeyPress( ) +{ + vtkRenderWindowInteractor* i = this->Interactor; + std::string key = i->GetKeySym( ); + if( key == "r" || key == "R" ) + { + this->CurrentRenderer->ResetCamera( ); + i->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +SimpleMPRWidget( QWidget* parent ) + : QWidget( parent ), + m_UI( new Ui::SimpleMPRWidget ) +{ + this->m_UI->setupUi( this ); + + // Configure VTK widgets + this->m_VTK[ 0 ] = this->m_UI->VTK_1; + this->m_VTK[ 1 ] = this->m_UI->VTK_2; + this->m_VTK[ 2 ] = this->m_UI->VTK_4; + this->m_VTK[ 3 ] = this->m_UI->VTK_3; + for( unsigned int i = 0; i < 4; ++i ) + { + this->m_Renderers[ i ] = vtkSmartPointer< vtkRenderer >::New( ); + this->m_VTK[ i ]->GetRenderWindow( )-> + AddRenderer( this->m_Renderers[ i ] ); + + } // rof + vtkSmartPointer< _3DInteractorStyle > style = + vtkSmartPointer< _3DInteractorStyle >::New( ); + this->m_VTK[ 3 ]->GetRenderWindow( )-> + GetInteractor( )->SetInteractorStyle( style ); + style->SetCurrentRenderer( this->m_Renderers[ 3 ] ); + + // Connect slots + QObject::connect( + this->m_UI->TopSplitter, SIGNAL( splitterMoved( int, int ) ), + this, SLOT( _SyncBottom( int, int ) ) + ); + QObject::connect( + this->m_UI->BottomSplitter, SIGNAL( splitterMoved( int, int ) ), + this, SLOT( _SyncTop( int, int ) ) + ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +~SimpleMPRWidget( ) +{ + this->Clear( ); + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +Clear( ) +{ + for( unsigned int i = 0; i < 4; ++i ) + this->m_Renderers[ i ]->RemoveAllViewProps( ); + for( unsigned int i = 0; i < 3; ++i ) + { + if( this->m_2DSlices[ i ].GetPointer( ) != NULL ) + this->m_2DSlices[ i ]->Clear( ); + if( this->m_3DSlices[ i ].GetPointer( ) != NULL ) + this->m_3DSlices[ i ]->Clear( ); + + } // rof + this->m_NamedActors.clear( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetMainImage( vtkImageData* image, const std::string& name ) +{ + this->Clear( ); + for( unsigned int i = 0; i < 3; ++i ) + { + this->m_2DSlices[ i ] = vtkSmartPointer< TSliceActors >::New( ); + this->m_2DSlices[ i ]->SetInputData( image, i ); + this->m_2DSlices[ i ]->PushInto( this->m_Renderers[ i ] ); + this->m_VTK[ i ]->GetRenderWindow( )->GetInteractor( )-> + SetInteractorStyle( this->m_2DSlices[ i ]->GetStyle( ) ); + + this->m_3DSlices[ i ] = vtkSmartPointer< TSliceActors >::New( ); + this->m_3DSlices[ i ]->SetInputData( image, i ); + this->m_3DSlices[ i ]->PushInto( this->m_Renderers[ 3 ] ); + this->m_3DSlices[ i ]->SetStyle( + dynamic_cast< vtkInteractorStyle* >( + this->m_Renderers[ 3 ]->GetRenderWindow( )-> + GetInteractor( )->GetInteractorStyle( ) + ) + ); + + this->m_NamedActors[ name ].insert( + this->m_2DSlices[ i ]->GetImageActor( ) + ); + this->m_NamedActors[ name ].insert( + this->m_3DSlices[ i ]->GetImageActor( ) + ); + + } // rof + this->_AssociateSlices( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetMainActor( vtkImageActor* actor, const std::string& name ) +{ + this->Clear( ); + vtkImageData* image = NULL; + int interp = actor->GetProperty( )->GetInterpolationType( ); + for( unsigned int i = 0; i < 3; ++i ) + { + this->m_2DSlices[ i ] = vtkSmartPointer< TSliceActors >::New( ); + if( i == 0 ) + { + this->m_2DSlices[ i ]->SetInputActor( actor, i ); + image = this->m_2DSlices[ i ]->GetInputData( ); + } + else + this->m_2DSlices[ i ]->SetInputData( image, i ); + this->m_2DSlices[ i ]->PushInto( this->m_Renderers[ i ] ); + this->m_VTK[ i ]->GetRenderWindow( )->GetInteractor( )-> + SetInteractorStyle( this->m_2DSlices[ i ]->GetStyle( ) ); + + this->m_3DSlices[ i ] = vtkSmartPointer< TSliceActors >::New( ); + this->m_3DSlices[ i ]->SetInputData( image, i ); + this->m_3DSlices[ i ]->PushInto( this->m_Renderers[ 3 ] ); + this->m_3DSlices[ i ]->SetStyle( + dynamic_cast< vtkInteractorStyle* >( + this->m_Renderers[ 3 ]->GetRenderWindow( )-> + GetInteractor( )->GetInteractorStyle( ) + ) + ); + + this->m_NamedActors[ name ].insert( + this->m_2DSlices[ i ]->GetImageActor( ) + ); + this->m_NamedActors[ name ].insert( + this->m_3DSlices[ i ]->GetImageActor( ) + ); + this->m_2DSlices[ i ]->GetImageActor( )-> + GetProperty( )->SetInterpolationType( interp ); + this->m_3DSlices[ i ]->GetImageActor( )-> + GetProperty( )->SetInterpolationType( interp ); + + } // rof + this->_AssociateSlices( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +AddImage( vtkImageData* image, const std::string& name ) +{ + std::cerr << "SimpleMPR: adding image" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +AddImageActor( vtkImageActor* actor, const std::string& name ) +{ + unsigned int i = 0; + bool cont = true; + while( i < 3 && cont ) + { + if( this->m_2DSlices[ i ].GetPointer( ) != NULL ) + { + if( this->m_2DSlices[ i ]->GetImageActor( ) != NULL ) + { + // TODO: add image actor + } + else + cont = false; + + } // fi + i++; + + } // rof + + // Add if no actors were found + if( cont ) + this->SetMainActor( actor, name ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +AddMesh( vtkPolyData* mesh, const std::string& name ) +{ + std::cerr << "SimpleMPR: adding mesh" << std::endl; + std::exit( 1 ); + /* TODO + PolyDataActor a; + a.Configure( mesh ); + this->m_PolyDatas[ mesh ] = a; + this->m_Renderers[ 3 ]->AddViewProp( a.Actor ); + + bool has_main_image = false; + for( unsigned int i = 0; i < 3; ++i ) + { + if( this->m_2DSlices[ i ].GetPointer( ) != NULL ) + { + if( this->m_2DSlices[ i ]->GetInputData( ) != NULL ) + { + has_main_image = true; + this->m_2DSlices[ i ]->AddMesh( mesh ); + this->m_2DSlices[ i ]->Render( ); + + } // fi + + } // fi + + } // rof + if( !has_main_image ) + this->m_Renderers[ 3 ]->ResetCamera( ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); + */ +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +AddMeshActor( vtkProp3D* actor, const std::string& name ) +{ + if( actor != NULL ) + { + this->m_Renderers[ 3 ]->AddViewProp( actor ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); + this->m_NamedActors[ name ].insert( actor ); + if( this->m_Renderers[ 3 ]->GetViewProps( )->GetNumberOfItems( ) == 1 ) + { + this->m_Renderers[ 3 ]->ResetCamera( ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +AddActor( vtkProp* actor, const std::string& name ) +{ + auto ia = dynamic_cast< vtkImageActor* >( actor ); + if( ia == NULL ) + { + auto ma = dynamic_cast< vtkProp3D* >( actor ); + if( ma != NULL ) + this->AddMeshActor( ma, name ); + } + else + this->AddImageActor( ia, name ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::QT::SimpleMPRWidget:: +TActors& cpExtensions::QT::SimpleMPRWidget:: +GetActors( const std::string& name ) const +{ + static const TActors empty; + auto i = this->m_NamedActors.find( name ); + if( i != this->m_NamedActors.end( ) ) + return( i->second ); + else + return( empty ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetInteractor( unsigned int i ) +{ + if( i < 4 ) + return( this->m_VTK[ i ]->GetRenderWindow( )->GetInteractor( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::QT::SimpleMPRWidget:: +GetRenderer( unsigned int i ) +{ + if( i < 4 ) + return( this->m_Renderers[ i ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindow* cpExtensions::QT::SimpleMPRWidget:: +GetRenderWindow( unsigned int i ) +{ + if( i < 4 ) + { + if( this->m_Renderers[ i ].GetPointer( ) != NULL ) + return( this->m_Renderers[ i ]->GetRenderWindow( ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +/* TODO + std::vector< std::pair< vtkImageActor*, vtkRenderer* > > + cpExtensions::QT::SimpleMPRWidget:: + GetMainImageActors( ) + { + std::vector< std::pair< vtkImageActor*, vtkRenderer* > > actors; + for( unsigned int i = 0; i < 3; ++i ) + { + actors.push_back( + std::pair< vtkImageActor*, vtkRenderer* >( + this->m_2DSlices[ i ]->GetImageActor( ), + this->m_Renderers[ i ] + ) + ); + actors.push_back( + std::pair< vtkImageActor*, vtkRenderer* >( + this->m_3DSlices[ i ]->GetImageActor( ), + this->m_Renderers[ 3 ] + ) + ); + + } // rof + return( actors ); + } +*/ + +// ------------------------------------------------------------------------- +/* TODO + vtkActor* cpExtensions::QT::SimpleMPRWidget:: + GetActor( vtkPolyData* mesh ) + { + auto i = this->m_PolyDatas.find( mesh ); + if( i != this->m_PolyDatas.end( ) ) + return( i->second.Actor.GetPointer( ) ); + else + return( NULL ); + } +*/ + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +_AssociateSlices( ) +{ + for( unsigned int i = 0; i < 3; ++i ) + { + for( unsigned int j = 0; j < 3; ++j ) + { + if( i != j ) + this->m_2DSlices[ i ]->AssociateSlice( this->m_2DSlices[ j ] ); + this->m_2DSlices[ i ]->AssociateSlice( this->m_3DSlices[ j ] ); + + } // rof + + } // rof + for( unsigned int i = 0; i < 3; ++i ) + { + this->m_2DSlices[ i ]->GetStyle( )-> + SetCurrentRenderer( this->m_Renderers[ i ] ); + this->m_Renderers[ i ]->ResetCamera( ); + this->m_VTK[ i ]->GetRenderWindow( )->Render( ); + + } // rof + this->m_Renderers[ 3 ]->ResetCamera( ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +_SyncBottom( int a, int b ) +{ + this->m_UI->BottomSplitter->setSizes( this->m_UI->TopSplitter->sizes( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +_SyncTop( int a, int b ) +{ + this->m_UI->TopSplitter->setSizes( this->m_UI->BottomSplitter->sizes( ) ); +} + +#endif // cpExtensions_QT4 + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.h b/lib/cpExtensions/QT/SimpleMPRWidget.h new file mode 100644 index 0000000..4b1ceb7 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.h @@ -0,0 +1,121 @@ +#ifndef __CPEXTENSIONS__QT__SIMPLEMPRWIDGET__H__ +#define __CPEXTENSIONS__QT__SIMPLEMPRWIDGET__H__ + +#include + +#ifdef cpExtensions_QT4 + +#include +#include +#include +#include +#include +#include +#include +#include + +#define cpExtensions_MAX_POLYS 65535 + +// ------------------------------------------------------------------------- +class QVTKWidget2; + +namespace Ui +{ + class SimpleMPRWidget; +} + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + /** + */ + class cpExtensions_EXPORT SimpleMPRWidget + : public QWidget + { + Q_OBJECT; + + public: + typedef SimpleMPRWidget Self; + + struct TActorCmp + { + bool operator()( + const vtkSmartPointer< vtkProp >& a, + const vtkSmartPointer< vtkProp >& b + ) const + { return( a.GetPointer( ) < b.GetPointer( ) ); } + }; + typedef std::set< vtkSmartPointer< vtkProp >, TActorCmp > TActors; + typedef std::map< std::string, TActors > TNamedActors; + typedef cpExtensions::Visualization::ImageSliceActors TSliceActors; + + protected: + /** + */ + class _3DInteractorStyle + : public vtkInteractorStyleTrackballCamera + { + public: + vtkTypeMacro( + _3DInteractorStyle, vtkInteractorStyleTrackballCamera + ); + + public: + static _3DInteractorStyle* New( ); + + virtual void OnChar( ) { } + virtual void OnKeyDown( ) { } + virtual void OnKeyUp( ) { } + virtual void OnKeyRelease( ) { } + virtual void OnKeyPress( ); + }; + + public: + explicit SimpleMPRWidget( QWidget* parent = 0 ); + virtual ~SimpleMPRWidget( ); + + // Data management + void Clear( ); + void SetMainImage( vtkImageData* image, const std::string& name ); + void SetMainActor( vtkImageActor* actor, const std::string& name ); + void AddImage( vtkImageData* image, const std::string& name ); + void AddImageActor( vtkImageActor* actor, const std::string& name ); + void AddMesh( vtkPolyData* mesh, const std::string& name ); + void AddMeshActor( vtkProp3D* actor, const std::string& name ); + void AddActor( vtkProp* actor, const std::string& name ); + const TActors& GetActors( const std::string& name ) const; + + // Visual objects + vtkRenderWindowInteractor* GetInteractor( unsigned int i ); + vtkRenderer* GetRenderer( unsigned int i ); + vtkRenderWindow* GetRenderWindow( unsigned int i ); + + protected: + void _AssociateSlices( ); + + private slots: + void _SyncBottom( int a, int b ); + void _SyncTop( int a, int b ); + + protected: + Ui::SimpleMPRWidget* m_UI; + QVTKWidget2* m_VTK[ 4 ]; + + vtkSmartPointer< vtkRenderer > m_Renderers[ 4 ]; + vtkSmartPointer< TSliceActors > m_2DSlices[ 3 ]; + vtkSmartPointer< TSliceActors > m_3DSlices[ 3 ]; + + TNamedActors m_NamedActors; + }; + + } // ecapseman + +} // ecapseman + +#endif // cpExtensions_QT4 + +#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 index 0000000..82b6608 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.ui @@ -0,0 +1,94 @@ + + + SimpleMPRWidget + + + + 0 + 0 + 94 + 48 + + + + Form + + + + 1 + + + 1 + + + + + Qt::Vertical + + + + Qt::Horizontal + + + + + 20 + 20 + + + + + 200 + 200 + + + + + + + 20 + 20 + + + + + 200 + 200 + + + + + + + Qt::Horizontal + + + + + 20 + 20 + + + + + 200 + 200 + + + + + + + + + + + + QVTKWidget2 + QWidget +
QVTKWidget2.h
+
+
+ + +
diff --git a/lib/cpExtensions/Utility.h b/lib/cpExtensions/Utility.h new file mode 100644 index 0000000..ab42807 --- /dev/null +++ b/lib/cpExtensions/Utility.h @@ -0,0 +1,127 @@ +#ifndef __CPEXTENSIONS__UTILITY__H__ +#define __CPEXTENSIONS__UTILITY__H__ + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#ifdef cpExtensions_SYS_WINDOWS +# define cpExtensions_STRTOK( A, B, N ) strtok_s( A, B, N ) +#else // cpExtensions_SYS_WINDOWS +# define cpExtensions_STRTOK( A, B, N ) std::strtok( A, B ) +#endif // cpExtensions_SYS_WINDOWS + +// ------------------------------------------------------------------------- +#define cpExtensions_CHRONO \ + std::chrono::duration_cast< std::chrono::milliseconds >( \ + std::chrono::system_clock::now( ).time_since_epoch( ) \ + ).count( ) + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + // ----------------------------------------------------------------------- + inline bool IsPathSeparator( char c ) + { +#ifdef cpExtensions_SYS_WINDOWS + return( c == '\\' || c == cpExtensions_PATH_SEPARATOR ); +#else // cpExtensions_SYS_WINDOWS + return( c == cpExtensions_PATH_SEPARATOR ); +#endif // cpExtensions_SYS_WINDOWS + } + + // ----------------------------------------------------------------------- + inline bool IsBlank( const char& v ) + { + return( v == ' ' || v == '\t' || v == '\n' || v == '\r' ); + } + + // ----------------------------------------------------------------------- + template< class _TTokens > + inline void TokenizeString( + _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 = cpExtensions_STRTOK( buffer, delims.c_str( ), &next ); + while( it != NULL ) + { + tokens.push_back( std::string( it ) ); + it = cpExtensions_STRTOK( NULL, delims.c_str( ), &next ); + + } // elihw + delete [] buffer; + + } // fi + } + + // ----------------------------------------------------------------------- + inline std::string ReplaceString( + 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 ReadFileIntoBuffer( + 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 std::string CanonicalPath( const std::string& path ) + { + std::string ret = ""; +#ifdef cpExtensions_SYS_WINDOWS + TCHAR buffer[ 4096 ] = TEXT( "" ); + TCHAR** lppPart = { NULL }; + GetFullPathName( path.c_str( ), 4096, buffer, lppPart ); + ret = std::string( buffer ); +#else // cpExtensions_SYS_WINDOWS + char* canonical_path = realpath( path.c_str( ), NULL ); + if( canonical_path != NULL ) + { + ret = canonical_path; + free( canonical_path ); + + } // fi +#endif // cpExtensions_SYS_WINDOWS + return( ret ); + } + +} // ecapseman + +#endif // __CPEXTENSIONS__UTILITY__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageBlender.cxx b/lib/cpExtensions/Visualization/ImageBlender.cxx new file mode 100644 index 0000000..44a08ab --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageBlender.cxx @@ -0,0 +1,239 @@ +#include + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageBlender:: +Self* cpExtensions::Visualization::ImageBlender:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::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::Visualization::ImageBlender:: +ImageBlender( ) + : Superclass( ) +{ + this->SetNumberOfInputPorts( 1 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageBlender:: +~ImageBlender( ) +{ +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::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::Visualization::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_Visualization_ImageBlender_Execute( + cpExtensions::Visualization::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 + double vmax = double( 0 ); + for( int k = 1; k < numInputs; ++k ) + { + double v = + ( ( double( k ) * double( *inSI[ k ] ) ) - ranges[ k << 1 ] ) / + ( ranges[ ( k << 1 ) + 1 ] - ranges[ k << 1 ] ); + vmax = ( vmax < v )? v: vmax; + + } // rof + *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::Visualization::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 = 1; 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_Visualization_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::Visualization::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/Visualization/ImageBlender.h b/lib/cpExtensions/Visualization/ImageBlender.h new file mode 100644 index 0000000..0585b7d --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageBlender.h @@ -0,0 +1,65 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEBLENDER__H__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGEBLENDER__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + * @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__VISUALIZATION__IMAGEBLENDER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h new file mode 100644 index 0000000..5129512 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.h @@ -0,0 +1,71 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__H__ + +#include +#include + +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 +#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 index 0000000..a1403ce --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageIndexesContainerToPolyData.hxx @@ -0,0 +1,188 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGEINDEXESCONTAINERTOPOLYDATA__HXX__ + +#include +#include + +// ------------------------------------------------------------------------- +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/ImageSliceActors.cxx b/lib/cpExtensions/Visualization/ImageSliceActors.cxx new file mode 100644 index 0000000..838cc84 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceActors.cxx @@ -0,0 +1,658 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +Self* cpExtensions::Visualization::ImageSliceActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +Clear( ) +{ + this->RemoveAllItems( ); + + // Main image + this->m_Mapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); + this->m_Actor = vtkSmartPointer< vtkImageActor >::New( ); + this->m_Actor->SetMapper( this->m_Mapper ); + + // Cursor + this->m_Cursor.Create( ); + this->m_Cursor.Actor->GetProperty( )->SetColor( 1, 1, 0 ); + + // Text + this->m_TextBuffer[ 0 ] = '\0'; + this->m_TextActor = vtkSmartPointer< vtkTextActor >::New( ); + this->m_TextActor->SetTextScaleModeToNone( ); + vtkTextProperty* textprop = this->m_TextActor->GetTextProperty( ); + textprop->SetColor( 1, 1, 0 ); + textprop->SetFontFamilyToCourier( ); + textprop->SetFontSize( 18 ); + textprop->BoldOff( ); + textprop->ItalicOff( ); + textprop->ShadowOff( ); + textprop->SetJustificationToLeft( ); + textprop->SetVerticalJustificationToBottom( ); + vtkCoordinate* coord = this->m_TextActor->GetPositionCoordinate( ); + coord->SetCoordinateSystemToNormalizedViewport( ); + coord->SetValue( 0.01, 0.05 ); + + // Configure style + vtkSmartPointer< TStyle > st = vtkSmartPointer< TStyle >::New( ); + st->SetAssociatedObject( this ); + st->AddMouseMoveCommand( Self::_MouseMoveCommand, this ); + st->AddMouseClickCommand( Self::_MouseClickCommand, this ); + st->AddMouseWheelCommand( Self::_MouseWheelCommand, this ); + st->AddKeyCommand( Self::_KeyCommand, this ); + st->AddEnterCommand( Self::_EnterCommand, this ); + st->AddLeaveCommand( Self::_LeaveCommand, this ); + this->m_Style = st; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetInputConnection( vtkAlgorithmOutput* aout, int orientation ) +{ + if( aout == NULL ) + return; + this->m_Mapper->SetInputConnection( aout ); + this->_ConfigureInput( orientation ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetInputData( vtkImageData* data, int orientation ) +{ + if( data == NULL ) + return; + this->m_Mapper->SetInputData( data ); + this->_ConfigureInput( orientation ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetInputActor( vtkProp* actor, int orientation ) +{ + auto real_actor = dynamic_cast< vtkImageActor* >( actor ); + if( real_actor == NULL ) + return; + auto real_mapper = + dynamic_cast< vtkImageSliceMapper* >( real_actor->GetMapper( ) ); + if( real_mapper == NULL ) + return; + this->m_Actor = real_actor; + this->m_Mapper = real_mapper; + this->_ConfigureInput( orientation ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::ImageSliceActors:: +GetInputData( ) +{ + if( this->m_Mapper.GetPointer( ) != NULL ) + return( this->m_Mapper->GetInput( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetImageActor( ) +{ + return( this->m_Actor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetImageActor( ) const +{ + return( this->m_Actor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +AddMesh( vtkPolyData* mesh ) +{ + SourceActor< vtkCutter > a; + a.Create( ); + a.Source->SetInputData( mesh ); + a.Source->SetCutFunction( this->m_Mapper->GetSlicePlane( ) ); + a.Source->SetValue( 0, 0 ); + a.Source->GenerateTrianglesOff( ); + a.Source->Update( ); + a.Modified( ); + this->m_Meshes[ mesh ] = a; + this->AddItem( a.Actor ); + + auto ren = this->m_Style->GetCurrentRenderer( ); + if( ren != NULL ) + if( ren->HasViewProp( this->m_Actor ) ) + ren->AddViewProp( a.Actor ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +AssociateSlice( Self* slice ) +{ + this->m_AssociatedSlices.push_back( slice ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +CleanAssociatedSlices( ) +{ + this->m_AssociatedSlices.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageInteractorStyle* +cpExtensions::Visualization::ImageSliceActors:: +GetStyle( ) +{ + return( dynamic_cast< TStyle* >( this->m_Style.GetPointer( ) ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetStyle( vtkInteractorStyle* st ) +{ + this->m_Style = st; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +PushInto( vtkRenderer* ren ) +{ + this->InitTraversal( ); + vtkProp* prop; + while( ( prop = this->GetNextProp( ) ) != NULL ) + ren->AddViewProp( prop ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +PopFrom( vtkRenderer* ren ) +{ + this->InitTraversal( ); + vtkProp* prop; + while( ( prop = this->GetNextProp( ) ) != NULL ) + ren->RemoveViewProp( prop ); +} + +// ------------------------------------------------------------------------- +long cpExtensions::Visualization::ImageSliceActors:: +GetSliceNumber( ) const +{ + if( this->m_Mapper.GetPointer( ) != NULL ) + return( this->m_Mapper->GetSliceNumber( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetSliceNumber( long slice ) +{ + if( this->m_Mapper.GetPointer( ) == NULL ) + return; + + // Get orientation + int a = this->m_Mapper->GetOrientation( ); + + // Check extent + int ext[ 6 ]; + this->m_Mapper->GetInput( )->GetExtent( ext ); + long rs = slice; + rs = ( rs > ext[ a << 1 ] )? rs: ext[ a << 1 ]; + rs = ( rs < ext[ ( a << 1 ) + 1 ] )? rs: ext[ ( a << 1 ) + 1 ]; + + // Update pipeline + this->m_Mapper->SetSliceNumber( rs ); + + // Update display extent (this isn't done automatically) + ext[ a << 1 ] = ext[ ( a << 1 ) + 1 ] = rs; + this->m_Actor->SetDisplayExtent( ext ); + + this->m_Mapper->Modified( ); + this->m_Actor->Modified( ); + this->_ConfigureCursor( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +ShowPixelText( double* pos ) +{ + if( this->m_Mapper.GetPointer( ) != NULL ) + { + char axis; + int axId = this->m_Mapper->GetOrientation( ); + if ( axId == 0 ) axis = 'X'; + else if( axId == 1 ) axis = 'Y'; + else if( axId == 2 ) axis = 'Z'; + long slice = this->GetSliceNumber( ); + + vtkImageData* image = this->m_Actor->GetInput( ); + int ijk[ 3 ]; + double pcoords[ 3 ]; + image->ComputeStructuredCoordinates( pos, ijk, pcoords ); + ijk[ axId ] = slice; + + int ext[ 6 ]; + image->GetExtent( ext ); + if( + ext[ 0 ] <= ijk[ 0 ] && ijk[ 0 ] <= ext[ 1 ] && + ext[ 2 ] <= ijk[ 1 ] && ijk[ 1 ] <= ext[ 3 ] && + ext[ 4 ] <= ijk[ 2 ] && ijk[ 2 ] <= ext[ 5 ] + ) + { + int nScl = image->GetNumberOfScalarComponents( ); + std::stringstream str; + str + << "[" << ijk[ 0 ] + << "," << ijk[ 1 ] + << "," << ijk[ 2 ] << "]=("; + str << + image->GetScalarComponentAsFloat( ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], 0 ); + for( int n = 1; n < nScl; ++n ) + str + << " " + << image->GetScalarComponentAsFloat( + ijk[ 0 ], ijk[ 1 ], ijk[ 2 ], n + ); + str << ")"; + +#if defined(WIN32) + sprintf_s( + this->m_TextBuffer, MAX_TEXT_BUFFER, "Axis: %c (%d)\nPixel %s", + axis, slice, str.str( ).c_str( ) + ); +#else // defined(WIN32) + std::sprintf( + this->m_TextBuffer, "Axis: %c (%ld)\nPixel %s", + axis, slice, str.str( ).c_str( ) + ); +#endif // defined(WIN32) + } // fi + } + else + this->m_TextBuffer[ 0 ] = '\0'; + this->m_TextActor->SetInput( this->m_TextBuffer ); + this->m_TextActor->Modified( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +GetScalarRange( double r[ 2 ] ) const +{ + r[ 0 ] = this->m_ScalarRange[ 0 ]; + r[ 1 ] = this->m_ScalarRange[ 1 ]; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetScalarRange( const double& a, const double& b ) +{ + this->m_ManualScalarRange = true; + this->m_ScalarRange[ 0 ] = a; + this->m_ScalarRange[ 1 ] = b; + this->SetWindowLevel( 1, 0.5 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +UnsetScalarRange( ) +{ + auto image = this->m_Actor->GetInput( ); + if( image != NULL ) + { + double r[ 2 ]; + image->GetScalarRange( r ); + this->SetScalarRange( r[ 0 ], r[ 1 ] ); + + } // fi + this->m_ManualScalarRange = false; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetWindowLevel( const double& w, const double& l ) +{ + static const double _0 = double( 0 ); + static const double _1 = double( 1 ); + + double rw = ( w < _0 )? _0: ( ( w > _1 )? _1: w ); + double rl = ( l < _0 )? _0: ( ( l > _1 )? _1: l ); + + double d = this->m_ScalarRange[ 1 ] - this->m_ScalarRange[ 0 ]; + rw *= d; + rl *= d; + rl += this->m_ScalarRange[ 0 ]; + + if( this->m_Actor.GetPointer( ) != NULL ) + { + this->m_Actor->GetProperty( )->SetColorWindow( rw ); + this->m_Actor->GetProperty( )->SetColorLevel( rl ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetWindow( ) const +{ + if( this->m_Actor.GetPointer( ) != NULL ) + return( this->m_Actor->GetProperty( )->GetColorWindow( ) ); + else + return( double( 0 ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetLevel( ) const +{ + if( this->m_Actor.GetPointer( ) != NULL ) + return( this->m_Actor->GetProperty( )->GetColorLevel( ) ); + else + return( double( 0 ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +Render( ) +{ + auto ren = this->m_Style->GetCurrentRenderer( ); + if( ren == NULL ) + return; + auto win = ren->GetRenderWindow( ); + if( win == NULL ) + return; + win->Render( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +ImageSliceActors( ) + : Superclass( ), + m_ManualScalarRange( false ) +{ + this->Clear( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +~ImageSliceActors( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_ConfigureInput( int orientation ) +{ + // Prepare main image + this->m_Mapper->SetOrientation( orientation ); + this->m_Mapper->Update( ); + this->m_Actor->GetProperty( )->SetOpacity( 0.8 ); + this->m_Actor->Modified( ); + auto st = this->GetStyle( ); + if( st != NULL ) + st->AssociateImageActor( this->m_Actor ); + this->AddItem( this->m_Actor ); + + // Prepare main cursor + this->_ConfigureCursor( ); + this->AddItem( this->m_Cursor.Actor ); + + // Prepare window/level + if( !( this->m_ManualScalarRange ) ) + this->UnsetScalarRange( ); + + // Add all other actors + this->AddItem( this->m_TextActor ); + + // Put it in the first slice + auto image = this->m_Mapper->GetInput( ); + int ext[ 6 ]; + image->GetExtent( ext ); + this->SetSliceNumber( ext[ orientation << 1 ] ); + + /* + if( this->m_Style.GetPointer( ) != NULL ) + this->AddItem( this->m_Actor ); + + this->SetSliceNumber( this->GetSliceNumberMinValue( ) ); + this->ResetCursor( ); + this->Modified( ); + + // Reset cursors + this->ResetCursor( ); + this->ResetAxesCursor( ); + + // Update window/level ranges + vtkImageData* data = this->GetInputImage( ); + if( data != NULL ) + { + double r[ 2 ]; + data->GetScalarRange( r ); + this->m_WLRange[ 0 ] = double( 0 ); + this->m_WLRange[ 1 ] = r[ 1 ] - r[ 0 ]; + this->m_WLRange[ 2 ] = r[ 0 ]; + this->m_WLRange[ 3 ] = r[ 1 ]; + this->ResetWindowLevel( ); + + // Configure blender + this->m_BlenderBase = vtkSmartPointer< vtkImageData >::New( ); + this->m_BlenderBase->ShallowCopy( data ); + this->m_BlenderBase->AllocateScalars( VTK_UNSIGNED_CHAR, 1 ); + std::memset( + this->m_BlenderBase->GetScalarPointer( ), 0, + this->m_BlenderBase->GetActualMemorySize( ) + ); + this->m_Blender->AddInputData( this->m_BlenderBase ); + + } // fi + */ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_ConfigureCursor( ) +{ + int a = this->m_Mapper->GetOrientation( ); + double bounds[ 6 ]; + this->m_Actor->GetBounds( bounds ); + bounds[ a << 1 ] += 1e-5; + bounds[ ( a << 1 ) + 1 ] += 1e-5; + + this->m_Cursor.Source->SetModelBounds( bounds ); + this->m_Cursor.Source->AllOn( ); + this->m_Cursor.Actor->GetProperty( )->SetOpacity( 1 ); + this->m_Cursor.Actor->GetProperty( )->SetLineWidth( 3 ); + this->m_Cursor.Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_MouseMoveCommand( + void* data, + const TStyle::ButtonID& btn, + int* idx, double* pos, + bool alt, bool ctr, bool sft + ) +{ + ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data ); + if( self == NULL ) + return; + + if( btn == TStyle::ButtonID_None ) + { + self->ShowPixelText( pos ); + self->m_Cursor.Source->SetFocalPoint( pos ); + self->m_Cursor.Source->Modified( ); + self->m_Cursor.Modified( ); + self->Render( ); + } + else if( btn == TStyle::ButtonID_Right ) + { + if( !alt && !ctr && sft ) + { + int a0 = self->m_Mapper->GetOrientation( ); + int a1 = ( a0 + 1 ) % 3; + int a2 = ( a0 + 2 ) % 3; + double dx = pos[ a1 ] - self->m_StartMouseEvent[ a1 ]; + double dy = pos[ a2 ] - self->m_StartMouseEvent[ a2 ]; + double bounds[ 6 ]; + self->m_Actor->GetBounds( bounds ); + dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ]; + dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ]; + double w = self->m_StartWindow + dx; + double l = self->m_StartLevel + dy; + + self->SetWindowLevel( w, l ); + self->Render( ); + for( + auto aIt = self->m_AssociatedSlices.begin( ); + aIt != self->m_AssociatedSlices.end( ); + ++aIt + ) + { + ( *aIt )->SetWindowLevel( w, l ); + ( *aIt )->Render( ); + + } // rof + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_MouseClickCommand( + void* data, + const TStyle::ButtonID& btn, + int* idx, double* pos, + bool alt, bool ctr, bool sft + ) +{ + ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data ); + if( self == NULL ) + return; + + self->m_StartMouseEvent[ 0 ] = pos[ 0 ]; + self->m_StartMouseEvent[ 1 ] = pos[ 1 ]; + self->m_StartMouseEvent[ 2 ] = pos[ 2 ]; + + if( btn == TStyle::ButtonID_Right ) + { + if( !alt && !ctr && sft ) + { + double r[ 2 ]; + self->GetScalarRange( r ); + double d = r[ 1 ] - r[ 0 ]; + self->m_StartWindow = self->GetWindow( ) / d; + self->m_StartLevel = ( self->GetLevel( ) - r[ 0 ] ) / d; + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_MouseWheelCommand( + void* data, + const int& dir, bool alt, bool ctr, bool sft + ) +{ + ImageSliceActors* self = reinterpret_cast< ImageSliceActors* >( data ); + if( self == NULL ) + return; + auto ren = self->m_Style->GetCurrentRenderer( ); + if( ren == NULL ) + return; + auto cam = ren->GetActiveCamera( ); + if( cam == NULL ) + return; + auto win = ren->GetRenderWindow( ); + if( win == NULL ) + return; + + // Get previous values + int a = self->m_Mapper->GetOrientation( ); + double bounds[ 6 ]; + self->m_Actor->GetBounds( bounds ); + double prev_pos = bounds[ a << 1 ]; + + // Move slice + long slice = self->GetSliceNumber( ) + dir * ( ( sft )? 10: 1 ); + self->SetSliceNumber( slice ); + self->m_Actor->GetBounds( bounds ); + + // Reset camera + double cam_pos[ 3 ]; + cam->GetPosition( cam_pos ); + cam_pos[ a ] += bounds[ a << 1 ] - prev_pos; + cam->SetPosition( cam_pos ); + + // Update text + self->ShowPixelText( self->m_Cursor.Source->GetFocalPoint( ) ); + + // Update all + win->Render( ); + for( + auto aIt = self->m_AssociatedSlices.begin( ); + aIt != self->m_AssociatedSlices.end( ); + ++aIt + ) + { + if( ( *aIt )->m_Mapper->GetOrientation( ) == a ) + { + ( *aIt )->SetSliceNumber( slice ); + ( *aIt )->Render( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_KeyCommand( + void* data, + const char& key + ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_EnterCommand( void* data ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_LeaveCommand( void* data ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.h b/lib/cpExtensions/Visualization/ImageSliceActors.h new file mode 100644 index 0000000..703a552 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceActors.h @@ -0,0 +1,190 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGESLICEACTORS__H__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGESLICEACTORS__H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_TEXT_BUFFER 1024 + +class vtkAlgorithmOutput; +class vtkImageData; +class vtkRenderer; + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT ImageSliceActors + : public vtkPropCollection + { + public: + typedef ImageSliceActors Self; + typedef cpExtensions::Interaction::ImageInteractorStyle TStyle; + typedef TStyle::TMouseCommand TMouseCommand; + typedef TStyle::TMouseWheelCommand TMouseWheelCommand; + typedef TStyle::TKeyCommand TKeyCommand; + typedef TStyle::TVoidCommand TVoidCommand; + typedef TStyle::TMouseMoveCommand TMouseMoveCommand; + typedef TStyle::TMouseClickCommand TMouseClickCommand; + typedef TStyle::TMouseDoubleClickCommand TMouseDoubleClickCommand; + typedef TStyle::TExposeCommand TExposeCommand; + typedef TStyle::TConfigureCommand TConfigureCommand; + typedef TStyle::TEnterCommand TEnterCommand; + typedef TStyle::TLeaveCommand TLeaveCommand; + typedef void ( *TSlicesCommand )( double*, int, void* ); + typedef void ( *TWindowLevelCommand )( double, double, void* ); + typedef TVoidCommand TRenderCommand; + + template< class _TSource > + struct SourceActor + { + vtkSmartPointer< _TSource > Source; + vtkSmartPointer< vtkPolyDataMapper > Mapper; + vtkSmartPointer< vtkActor > Actor; + void Create( ) + { + this->Source = vtkSmartPointer< _TSource >::New( ); + this->Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->Actor = vtkSmartPointer< vtkActor >::New( ); + this->Mapper->SetInputConnection( this->Source->GetOutputPort( ) ); + this->Actor->SetMapper( this->Mapper ); + } + void Modified( ) + { + this->Source->Modified( ); + this->Mapper->Modified( ); + this->Actor->Modified( ); + } + }; + + public: + vtkTypeMacro( ImageSliceActors, vtkPropCollection ); + + cpExtensions_BaseInteractorStyle_Commands( Slices ); + cpExtensions_BaseInteractorStyle_Commands( WindowLevel ); + cpExtensions_BaseInteractorStyle_Commands( Render ); + + public: + static Self* New( ); + + void Clear( ); + void SetInputConnection( vtkAlgorithmOutput* aout, int orientation ); + void SetInputData( vtkImageData* data, int orientation ); + void SetInputActor( vtkProp* actor, int orientation ); + vtkImageData* GetInputData( ); + + vtkImageActor* GetImageActor( ); + const vtkImageActor* GetImageActor( ) const; + + void AddMesh( vtkPolyData* mesh ); + + void AssociateSlice( Self* slice ); + void CleanAssociatedSlices( ); + + TStyle* GetStyle( ); + void SetStyle( vtkInteractorStyle* st ); + + void PushInto( vtkRenderer* ren ); + void PopFrom( vtkRenderer* ren ); + + long GetSliceNumber( ) const; + void SetSliceNumber( long slice ); + + void ShowPixelText( double* pos ); + + void GetScalarRange( double r[ 2 ] ) const; + void SetScalarRange( const double& a, const double& b ); + void UnsetScalarRange( ); + void SetWindowLevel( const double& w, const double& l ); + double GetWindow( ) const; + double GetLevel( ) const; + + void Render( ); + + protected: + ImageSliceActors( ); + virtual ~ImageSliceActors( ); + + void _ConfigureInput( int orientation ); + void _ConfigureCursor( ); + + // Events + static void _MouseMoveCommand( + void* data, + const TStyle::ButtonID& btn, + int* idx, double* pos, + bool alt, bool ctr, bool sft + ); + static void _MouseClickCommand( + void* data, + const TStyle::ButtonID& btn, + int* idx, double* pos, + bool alt, bool ctr, bool sft + ); + static void _MouseWheelCommand( + void* data, + const int& dir, bool alt, bool ctr, bool sft + ); + static void _KeyCommand( + void* data, + const char& key + ); + static void _EnterCommand( void* data ); + static void _LeaveCommand( void* data ); + + private: + // Purposely not implemented + ImageSliceActors( const Self& ); + Self& operator=( const Self& ); + + protected: + // Main image + vtkSmartPointer< vtkImageSliceMapper > m_Mapper; + vtkSmartPointer< vtkImageActor > m_Actor; + + // Secondary slices + std::vector< vtkSmartPointer< Self > > m_AssociatedSlices; + + // Associated meshes + std::map< vtkPolyData*, SourceActor< vtkCutter > > m_Meshes; + + // Cursor + SourceActor< vtkCursor3D > m_Cursor; + + // Text + char m_TextBuffer[ MAX_TEXT_BUFFER ]; + vtkSmartPointer< vtkTextActor > m_TextActor; + + // WindowLevel + double m_ScalarRange[ 2 ]; + bool m_ManualScalarRange; + + // Style + vtkSmartPointer< vtkInteractorStyle > m_Style; + + // Events-related data + double m_StartMouseEvent[ 3 ]; + double m_StartWindow; + double m_StartLevel; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__VISUALIZATION__IMAGESLICEACTORS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h new file mode 100644 index 0000000..cfc481e --- /dev/null +++ b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.h @@ -0,0 +1,69 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__POLYLINEPARAMETRICPATHTOPOLYDATA__H__ +#define __CPEXTENSIONS__VISUALIZATION__POLYLINEPARAMETRICPATHTOPOLYDATA__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class _TPolyLine > + class PolyLineParametricPathToPolyData + : public vtkPolyDataAlgorithm + { + public: + typedef PolyLineParametricPathToPolyData Self; + + typedef _TPolyLine TPolyLine; + typedef itk::ImageBase< TPolyLine::PathDimension > TImage; + + public: + vtkTypeMacro( PolyLineParametricPathToPolyData, vtkPolyDataAlgorithm ); + + public: + static Self* New( ); + + const TPolyLine* GetInput( ) const; + const TImage* GetReferenceImage( ) const; + void SetInput( const TPolyLine* pl ); + void SetReferenceImage( const TImage* i ); + + 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; + const TImage* m_ReferenceImage; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__VISUALIZATION__POLYLINEPARAMETRICPATHTOPOLYDATA__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.hxx b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.hxx new file mode 100644 index 0000000..e3d23c7 --- /dev/null +++ b/lib/cpExtensions/Visualization/PolyLineParametricPathToPolyData.hxx @@ -0,0 +1,213 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__POLYLINEPARAMETRICPATHTOPOLYDATA__HXX__ +#define __CPEXTENSIONS__VISUALIZATION__POLYLINEPARAMETRICPATHTOPOLYDATA__HXX__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +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 > +const typename +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +TImage* +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +GetReferenceImage( ) const +{ + return( this->m_ReferenceImage ); +} + +// ------------------------------------------------------------------------- +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 > +void +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +SetReferenceImage( const TImage* i ) +{ + if( this->m_ReferenceImage != i ) + { + this->m_ReferenceImage = i; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +PolyLineParametricPathToPolyData( ) + : vtkPolyDataAlgorithm( ), + m_PolyLine( NULL ), + m_ReferenceImage( 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( ) ) + ); + + // Get input data + auto lst = this->m_PolyLine->GetVertexList( ); + + // Prepare points + vtkPoints* points = out->GetPoints( ); + if( points == NULL ) + { + points = vtkPoints::New( ); + out->SetPoints( points ); + points->Delete( ); + + } // fi + points->SetNumberOfPoints( lst->Size( ) ); + + // Prepare cells + /* TODO + vtkSmartPointer< vtkCellArray > verts = + vtkSmartPointer< vtkCellArray >::New( ); + */ + vtkSmartPointer< vtkCellArray > lines = + vtkSmartPointer< vtkCellArray >::New( ); + + for( unsigned int i = 0; i < lst->Size( ); ++i ) + { + auto idx = lst->GetElement( i ); + if( this->m_ReferenceImage != NULL ) + { + typename TImage::PointType pnt; + this->m_ReferenceImage->TransformContinuousIndexToPhysicalPoint( 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 + /* TODO + verts->InsertNextCell( 1 ); + verts->InsertCellPoint( i ); + */ + if( i > 0 ) + { + lines->InsertNextCell( 2 ); + lines->InsertCellPoint( i - 1 ); + lines->InsertCellPoint( i ); + + } // fi + + } // rof + out->SetPoints( points ); + // TODO: out->SetVerts( verts ); + out->SetLines( lines ); + return( 1 ); +} + +// ------------------------------------------------------------------------- +template< class _TPolyLine > +int +cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPolyLine >:: +RequestInformation( + vtkInformation* information, + vtkInformationVector** input, + vtkInformationVector* output + ) +{ + vtkInformation* info = output->GetInformationObject( 0 ); + /* TODO + info->Set( + vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES( ), -1 + ); + */ + + if( this->m_PolyLine != 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__POLYLINEPARAMETRICPATHTOPOLYDATA__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/SeedWidgetCorrector.cxx b/lib/cpExtensions/Visualization/SeedWidgetCorrector.cxx new file mode 100644 index 0000000..f76cc9f --- /dev/null +++ b/lib/cpExtensions/Visualization/SeedWidgetCorrector.cxx @@ -0,0 +1,79 @@ +#include + +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::SeedWidgetCorrector* +cpExtensions::Visualization::SeedWidgetCorrector:: +New( ) +{ + return( new cpExtensions::Visualization::SeedWidgetCorrector ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::SeedWidgetCorrector:: +Configure( vtkCellPicker* picker ) +{ + this->m_Picker = picker; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::SeedWidgetCorrector:: +Execute( vtkObject* caller, unsigned long eventId, void* arguments ) +{ + vtkSeedWidget* wdg = dynamic_cast< vtkSeedWidget* >( caller ); + if( wdg == NULL || this->m_Picker == NULL ) + return; + + if( eventId == vtkCommand::PlacePointEvent ) + { + // Get newly added handle and its associated objects + int hId = *( reinterpret_cast< int* >( arguments ) ); + vtkHandleWidget* hWdg = wdg->GetSeed( hId ); + if( hWdg == NULL ) + return; + vtkHandleRepresentation* hRep = + dynamic_cast< vtkHandleRepresentation* >( hWdg->GetRepresentation( ) ); + if( hRep == NULL ) + return; + + // Get clicked point and 3D scene + double p[ 3 ]; + hRep->GetDisplayPosition( p ); + vtkRenderWindowInteractor* iren = wdg->GetInteractor( ); + if( iren == NULL ) + return; + vtkRenderer* ren = + iren->FindPokedRenderer( int( p[ 0 ] ), int( p[ 1 ] ) ); + if( ren == NULL ) + return; + + // Correct point with given picker + double q[ 3 ]; + this->m_Picker->Pick( p[ 0 ], p[ 1 ], p[ 2 ], ren ); + this->m_Picker->GetPickPosition( q ); + hRep->SetWorldPosition( q ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::SeedWidgetCorrector:: +SeedWidgetCorrector( ) + : vtkCommand( ), + m_Picker( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::SeedWidgetCorrector:: +~SeedWidgetCorrector( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/SeedWidgetCorrector.h b/lib/cpExtensions/Visualization/SeedWidgetCorrector.h new file mode 100644 index 0000000..b8e8524 --- /dev/null +++ b/lib/cpExtensions/Visualization/SeedWidgetCorrector.h @@ -0,0 +1,44 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__SEEDWIDGETCORRECTOR__H__ +#define __CPEXTENSIONS__VISUALIZATION__SEEDWIDGETCORRECTOR__H__ + +#include +#include + +class vtkCellPicker; +class vtkSeedWidget; + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT SeedWidgetCorrector + : public vtkCommand + { + public: + static SeedWidgetCorrector* New( ); + + void Configure( vtkCellPicker* picker ); + + virtual void Execute( + vtkObject* caller, + unsigned long eventId, + void* arguments + ); + + protected: + SeedWidgetCorrector( ); + virtual ~SeedWidgetCorrector( ); + + protected: + vtkCellPicker* m_Picker; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__VISUALIZATION__SEEDWIDGETCORRECTOR__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/BaseWidget.cxx b/lib/cpPlugins/BaseWidget.cxx new file mode 100644 index 0000000..3750bde --- /dev/null +++ b/lib/cpPlugins/BaseWidget.cxx @@ -0,0 +1,95 @@ +#include + +// ------------------------------------------------------------------------- +itk::ModifiedTimeType cpPlugins::BaseWidget:: +GetMTime( ) const +{ + // Let time only be managed by itk -> synch issues when data is + // represented by vtk + return( this->itk::Object::GetMTime( ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::BaseWidget::TMPRWidget* cpPlugins::BaseWidget:: +GetMPRViewer( ) const +{ + return( this->m_MPRViewer ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindowInteractor* cpPlugins::BaseWidget:: +GetSingleInteractor( ) const +{ + return( this->m_SingleInteractor ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::BaseWidget:: +SetMPRViewer( cpPlugins::BaseWidget::TMPRWidget* v ) +{ + if( this->m_MPRViewer != v ) + { + this->m_MPRViewer = v; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::BaseWidget:: +SetSingleInteractor( vtkRenderWindowInteractor* i ) +{ + if( this->m_SingleInteractor != i ) + { + this->m_SingleInteractor = i; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +bool cpPlugins::BaseWidget:: +IsInteractive( ) +{ + return( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::BaseWidget:: +SetInteractionObjects( const std::vector< void* >& objs ) +{ + if( objs.size( ) > 0 ) + { + vtkRenderWindowInteractor* rwi = + reinterpret_cast< vtkRenderWindowInteractor* >( objs[ 0 ] ); + this->SetSingleInteractor( rwi ); + } + if( objs.size( ) > 1 ) + { + TMPRWidget* wdg = reinterpret_cast< TMPRWidget* >( objs[ 1 ] ); + this->SetMPRViewer( wdg ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins::BaseWidget:: +BaseWidget( ) + : Superclass( ), + m_MPRViewer( NULL ), + m_SingleInteractor( NULL ) +{ + this->m_Parameters.ConfigureAsString( "Text" ); + this->m_Parameters.SetString( "Text", "" ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BaseWidget:: +~BaseWidget( ) +{ + // Warning: Qt's smartpointers require this to avoid segfaults + this->m_MPRViewer = NULL; + this->m_SingleInteractor = NULL; +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/BaseWidget.h b/lib/cpPlugins/BaseWidget.h new file mode 100644 index 0000000..02bf86c --- /dev/null +++ b/lib/cpPlugins/BaseWidget.h @@ -0,0 +1,69 @@ +#ifndef __CPPLUGINS__BASEWIDGET__H__ +#define __CPPLUGINS__BASEWIDGET__H__ + +#include + +#include + +// Some forward declarations +class vtkRenderWindowInteractor; +namespace cpExtensions +{ + namespace QT + { + class SimpleMPRWidget; + } +} + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT BaseWidget + : public ProcessObject + { + public: + typedef BaseWidget Self; + typedef ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef cpExtensions::QT::SimpleMPRWidget TMPRWidget; + + public: + itkTypeMacro( BaseWidget, ProcessObject ); + cpPlugins_Id_Macro( Widgets::BaseWidget, Widgets ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const ITK_OVERRIDE; + + const TMPRWidget* GetMPRViewer( ) const; + const vtkRenderWindowInteractor* GetSingleInteractor( ) const; + + void SetMPRViewer( TMPRWidget* v ); + void SetSingleInteractor( vtkRenderWindowInteractor* i ); + + virtual bool IsInteractive( ) ITK_OVERRIDE; + virtual void SetInteractionObjects( + const std::vector< void* >& objs + ) ITK_OVERRIDE; + + protected: + BaseWidget( ); + virtual ~BaseWidget( ); + + private: + // Purposely not implemented + BaseWidget( const Self& ); + Self& operator=( const Self& ); + + protected: + TMPRWidget* m_MPRViewer; + vtkRenderWindowInteractor* m_SingleInteractor; + }; + +} // ecapseman + +#endif // __CPPLUGINS__BASEWIDGET__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/BoundingBox.cxx b/lib/cpPlugins/BoundingBox.cxx new file mode 100644 index 0000000..14f48f4 --- /dev/null +++ b/lib/cpPlugins/BoundingBox.cxx @@ -0,0 +1,97 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpPlugins::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 ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::BoundingBox:: +SetITK( itk::LightObject* o ) +{ + bool r = this->_ITKImage< 1 >( o ); + if( !r ) r = this->_ITKImage< 2 >( o ); + if( !r ) r = this->_ITKImage< 3 >( o ); + if( !r ) r = this->_ITKImage< 4 >( o ); + if( !r ) r = this->_ITKPointSet< float, 2 >( o ); + if( !r ) r = this->_ITKPointSet< double, 2 >( o ); + if( !r ) r = this->_ITKPointSet< float, 3 >( o ); + if( !r ) r = this->_ITKPointSet< double, 3 >( o ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::BoundingBox:: +SetVTK( vtkObjectBase* o ) +{ + auto ds = dynamic_cast< vtkDataSet* >( o ); + if( ds != NULL ) + { + double bounds[ 6 ]; + ds->GetBounds( bounds ); + this->m_Points[ 0 ].clear( ); + this->m_Points[ 1 ].clear( ); + this->m_Points[ 0 ].push_back( bounds[ 0 ] ); + this->m_Points[ 1 ].push_back( bounds[ 1 ] ); + this->m_Points[ 0 ].push_back( bounds[ 2 ] ); + this->m_Points[ 1 ].push_back( bounds[ 3 ] ); + this->m_Points[ 0 ].push_back( bounds[ 4 ] ); + this->m_Points[ 1 ].push_back( bounds[ 5 ] ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::BoundingBox:: +Copy( Self* other ) +{ + this->m_Points[ 0 ] = other->m_Points[ 0 ]; + this->m_Points[ 1 ] = other->m_Points[ 1 ]; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::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( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BoundingBox:: +BoundingBox( ) + : Superclass( ) +{ + this->m_Points[ 0 ].push_back( double( 0 ) ); + this->m_Points[ 1 ].push_back( double( 0 ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins::BoundingBox:: +~BoundingBox( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/BoundingBox.h b/lib/cpPlugins/BoundingBox.h new file mode 100644 index 0000000..b29cf2d --- /dev/null +++ b/lib/cpPlugins/BoundingBox.h @@ -0,0 +1,76 @@ +#ifndef __CPPLUGINS__BOUNDINGBOX__H__ +#define __CPPLUGINS__BOUNDINGBOX__H__ + +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT BoundingBox + : public DataObject + { + public: + typedef BoundingBox Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BoundingBox, DataObject ); + cpPlugins_Id_Macro( BoundingBox, Object ); + + public: + void SetDataObject( DataObject* o ); + virtual void SetITK( itk::LightObject* o ) ITK_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) ITK_OVERRIDE; + + void Copy( Self* other ); + void Blend( Self* other ); + + template< class _TPoint > + inline void SetMinimum( const _TPoint& p ); + + template< class _TPoint > + inline void SetMaximum( const _TPoint& p ); + + template< class _TPoint > + inline _TPoint GetMinimum( ) const; + + template< class _TPoint > + inline _TPoint GetMaximum( ) const; + + protected: + BoundingBox( ); + virtual ~BoundingBox( ); + + template< class _TPoint > + inline void _SetPoint( unsigned int m, const _TPoint& p ); + + template< class _TPoint > + inline _TPoint _GetPoint( unsigned int m ) const; + + template< unsigned int _NDim > + inline bool _ITKImage( itk::LightObject* o ); + + template< class _TScalar, unsigned int _NDim > + inline bool _ITKPointSet( itk::LightObject* o ); + + private: + // Purposely not implemented + BoundingBox( const Self& ); + Self& operator=( const Self& ); + + protected: + std::vector< double > m_Points[ 2 ]; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__BOUNDINGBOX__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/BoundingBox.hxx b/lib/cpPlugins/BoundingBox.hxx new file mode 100644 index 0000000..be95c3a --- /dev/null +++ b/lib/cpPlugins/BoundingBox.hxx @@ -0,0 +1,131 @@ +#ifndef __CPPLUGINS__BOUNDINGBOX__HXX__ +#define __CPPLUGINS__BOUNDINGBOX__HXX__ + +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TPoint > +void cpPlugins::BoundingBox:: +SetMinimum( const _TPoint& p ) +{ + this->_SetPoint( 0, p ); +} + +// ------------------------------------------------------------------------- +template< class _TPoint > +void cpPlugins::BoundingBox:: +SetMaximum( const _TPoint& p ) +{ + this->_SetPoint( 1, p ); +} + +// ------------------------------------------------------------------------- +template< class _TPoint > +_TPoint cpPlugins::BoundingBox:: +GetMinimum( ) const +{ + return( this->_GetPoint< _TPoint >( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPoint > +_TPoint cpPlugins::BoundingBox:: +GetMaximum( ) const +{ + return( this->_GetPoint< _TPoint >( 1 ) ); +} + +// ------------------------------------------------------------------------- +template< class _TPoint > +void cpPlugins::BoundingBox:: +_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->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class _TPoint > +_TPoint cpPlugins::BoundingBox:: +_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 ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _NDim > +bool cpPlugins::BoundingBox:: +_ITKImage( itk::LightObject* o ) +{ + auto image = dynamic_cast< itk::ImageBase< _NDim >* >( o ); + if( image == NULL ) + return( false ); + + auto region = image->GetLargestPossibleRegion( ); + auto i0 = region.GetIndex( ); + auto i1 = i0 + region.GetSize( ); + + typename itk::ImageBase< _NDim >::PointType p0, p1; + image->TransformIndexToPhysicalPoint( i0, p0 ); + image->TransformIndexToPhysicalPoint( i1, p1 ); + this->m_Points[ 0 ].clear( ); + this->m_Points[ 1 ].clear( ); + + for( unsigned int d = 0; d < _NDim; ++d ) + { + this->m_Points[ 0 ].push_back( double( p0[ d ] ) ); + this->m_Points[ 1 ].push_back( double( p1[ d ] ) ); + + } // rof + this->Modified( ); + return( true ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar, unsigned int _NDim > +bool cpPlugins::BoundingBox:: +_ITKPointSet( itk::LightObject* o ) +{ + typedef itk::PointSet< _TScalar, _NDim > _TPointSet; + typedef itk::BoundingBox< typename _TPointSet::PointIdentifier, _NDim, _TScalar, typename _TPointSet::PointsContainer > _TBBox; + + auto ps = dynamic_cast< _TPointSet* >( o ); + if( ps == NULL ) + return( false ); + + this->m_Points[ 0 ].clear( ); + this->m_Points[ 1 ].clear( ); + + typename _TBBox::Pointer bb = _TBBox::New( ); + bb->SetPoints( ps->GetPoints( ) ); + if( bb->ComputeBoundingBox( ) ) + { + auto p0 = bb->GetMinimum( ); + auto p1 = bb->GetMaximum( ); + for( unsigned int d = 0; d < _NDim; ++d ) + { + this->m_Points[ 0 ].push_back( double( p0[ d ] ) ); + this->m_Points[ 1 ].push_back( double( p1[ d ] ) ); + + } // rof + this->Modified( ); + return( true ); + } + else + return( false ); +} + +#endif // __CPPLUGINS__BOUNDINGBOX__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/CMakeLists.txt b/lib/cpPlugins/CMakeLists.txt new file mode 100644 index 0000000..de69dce --- /dev/null +++ b/lib/cpPlugins/CMakeLists.txt @@ -0,0 +1,239 @@ + +## ============================= +## = Set names and directories = +## ============================= + +SET(lib_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +SET(lib_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) +GET_FILENAME_COMPONENT(lib_NAME ${lib_SOURCE_DIR} NAME) + +## ========================= +## = Configure local files = +## ========================= + +FILE(GLOB lib_CONFIG_FILES "${lib_SOURCE_DIR}/*.in") +FOREACH(_file ${lib_CONFIG_FILES}) + GET_FILENAME_COMPONENT(_filename ${_file} NAME) + STRING(REGEX REPLACE ".in" "" _outfile ${_filename}) + CONFIGURE_FILE(${_filename} ${lib_BUILD_DIR}/${_outfile} @ONLY) +ENDFOREACH(_file) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_SOURCE_HEADERS_H "${lib_SOURCE_DIR}/*.h") +FILE(GLOB lib_SOURCE_HEADERS_HPP "${lib_SOURCE_DIR}/*.hpp") +FILE(GLOB lib_SOURCE_HEADERS_HXX "${lib_SOURCE_DIR}/*.hxx") +FILE(GLOB lib_SOURCE_CODE_C "${lib_SOURCE_DIR}/*.c") +FILE(GLOB lib_SOURCE_CODE_CPP "${lib_SOURCE_DIR}/*.cpp") +FILE(GLOB lib_SOURCE_CODE_CXX "${lib_SOURCE_DIR}/*.cxx") +FILE(GLOB lib_SOURCE_QT_UI "${lib_SOURCE_DIR}/*.ui") +FILE(GLOB lib_BUILD_HEADERS_H "${lib_BUILD_DIR}/*.h") +FILE(GLOB lib_BUILD_HEADERS_HPP "${lib_BUILD_DIR}/*.hpp") +FILE(GLOB lib_BUILD_HEADERS_HXX "${lib_BUILD_DIR}/*.hxx") +FILE(GLOB lib_BUILD_CODE_C "${lib_BUILD_DIR}/*.c") +FILE(GLOB lib_BUILD_CODE_CPP "${lib_BUILD_DIR}/*.cpp") +FILE(GLOB lib_BUILD_CODE_CXX "${lib_BUILD_DIR}/*.cxx") + +# =================================== +# = Integrate all source file names = +# =================================== + +SET( + lib_CODE + ${lib_SOURCE_CODE_C} + ${lib_SOURCE_CODE_CPP} + ${lib_SOURCE_CODE_CXX} + ${lib_BUILD_CODE_C} + ${lib_BUILD_CODE_CPP} + ${lib_BUILD_CODE_CXX} + ) + +SET( + lib_HEADERS + ${lib_SOURCE_HEADERS_H} + ${lib_SOURCE_HEADERS_HPP} + ${lib_SOURCE_HEADERS_HXX} + ${lib_BUILD_HEADERS_H} + ${lib_BUILD_HEADERS_HPP} + ${lib_BUILD_HEADERS_HXX} + ) + +IF(USE_QT4) + SET(_hdr_to_wrap) + FOREACH(_h ${lib_SOURCE_HEADERS_H}) + FILE(READ ${_h} _txt) + STRING(FIND "${_txt}" "Q_OBJECT" _res) + IF(NOT ${_res} EQUAL -1) + LIST(APPEND _hdr_to_wrap ${_h}) + ENDIF(NOT ${_res} EQUAL -1) + ENDFOREACH(_h) + IF(_hdr_to_wrap) + QT4_WRAP_CPP(_src_qt_moc ${_hdr_to_wrap}) + ENDIF(_hdr_to_wrap) + QT4_WRAP_UI(_hdr_qt_ui ${lib_SOURCE_QT_UI}) + SET(lib_CODE ${lib_CODE} ${_hdr_qt_ui} ${_src_qt_moc}) + SET(lib_HEADERS ${lib_HEADERS} ${_hdr_qt_ui}) +ENDIF(USE_QT4) + +## ========================== +## = Library's dependencies = +## ========================== + +SET( + lib_LINKS + ${ITK_LIBRARIES} + ${VTK_LIBRARIES} + cpPlugins_tinyxml2 + cpPlugins_Instances_ScalarImages + cpPlugins_Instances_ColorImages + cpPlugins_Instances_Mesh + ) +IF(USE_QT4) + SET(lib_LINKS ${lib_LINKS} ${QT_LIBRARIES}) +ENDIF(USE_QT4) +IF(NOT WIN32) + SET(lib_LINKS ${lib_LINKS} dl) +ENDIF(NOT WIN32) + +## ============================================================== +## = Compile library, if there is at least one source code file = +## ============================================================== + +IF(lib_CODE) + ADD_LIBRARY(${lib_NAME} SHARED ${lib_CODE}) + SET_TARGET_PROPERTIES( + ${lib_NAME} PROPERTIES + VERSION "${prj_VER}" + SOVERSION "${prj_sVER}" + ) + # ADD_DEPENDENCIES(${lib_NAME} ${cpPlugins_LIBRARIES}) + GENERATE_EXPORT_HEADER( + ${lib_NAME} + BASE_NAME ${lib_NAME} + EXPORT_MACRO_NAME ${lib_NAME}_EXPORT + EXPORT_FILE_NAME ${lib_BUILD_DIR}/${lib_NAME}_Export.h + STATIC_DEFINE ${lib_NAME}_BUILT_AS_STATIC + ) + TARGET_LINK_LIBRARIES(${lib_NAME} ${lib_LINKS}) + SET(${lib_NAME}_LIB ${lib_NAME} CACHE INTERNAL "library ${lib_NAME}") +ENDIF(lib_CODE) + +# IF(USE_QT4) +# SET( +# lib_QT_UI +# ActorAxesProperties.ui +# ActorImageProperties.ui +# ActorPolyDataProperties.ui +# ) +# SET( +# lib_QT_Headers +# ActorProperties.h +# ActorAxesProperties.h +# ActorImageProperties.h +# ActorPolyDataProperties.h +# ActorPropertiesQtDialog.h +# ParametersQtDialog.h +# ) +# SET( +# lib_QT_Sources +# ActorProperties.cxx +# ActorAxesProperties.cxx +# ActorImageProperties.cxx +# ActorPolyDataProperties.cxx +# ActorPropertiesQtDialog.cxx +# ParametersQtDialog.cxx +# ) +# SET( +# lib_QT_Resources +# ) + +# QT4_WRAP_UI(lib_QT_Wrapped_Headers ${lib_QT_UI}) +# QT4_WRAP_CPP(lib_QT_Wrapped_MOC_Sources ${lib_QT_Headers}) +# QT4_ADD_RESOURCES(lib_QT_Wrapped_Resources_Sources ${lib_QT_Resources}) + +# SET( +# lib_HEADERS_H +# ${lib_HEADERS_H} +# ${lib_QT_Wrapped_Headers} +# ) + +# SET( +# lib_BUILDS_CXX +# ${lib_BUILDS_CXX} +# ${lib_QT_Sources} +# ${lib_QT_Wrapped_Headers} +# ${lib_QT_Wrapped_MOC_Sources} +# ${lib_QT_Wrapped_Resources_Sources} +# ) + +# ENDIF(USE_QT4) + +# SET( +# lib_HEADERS +# ${lib_HEADERS_H} +# ${lib_HEADERS_HPP} +# ${lib_HEADERS_HXX} +# ) + +# SET( +# lib_BUILDS +# ${lib_BUILDS_C} +# ${lib_BUILDS_CPP} +# ${lib_BUILDS_CXX} +# ) + +# SET( +# target_LIBRARIES +# ${ITK_LIBRARIES} +# ${VTK_LIBRARIES} +# cpExtensions +# cpPlugins_tinyxml2 +# ${cpPlugins_LIBRARIES} +# ) +# IF(NOT WIN32) +# SET( +# target_LIBRARIES +# ${target_LIBRARIES} +# dl +# ) +# ENDIF(NOT WIN32) + +# ## ===================== +# ## = Compilation rules = +# ## ===================== + +# ADD_LIBRARY(${lib_NAME} SHARED ${lib_BUILDS}) +# SET_TARGET_PROPERTIES( +# ${lib_NAME} PROPERTIES +# VERSION "${prj_VER}" +# SOVERSION "${prj_sVER}" +# ) +# ADD_DEPENDENCIES(${lib_NAME} ${cpPlugins_LIBRARIES}) +# GENERATE_EXPORT_HEADER( +# ${lib_NAME} +# BASE_NAME ${lib_NAME} +# EXPORT_MACRO_NAME ${lib_NAME}_EXPORT +# EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/${lib_DIR}/${lib_NAME}_Export.h +# STATIC_DEFINE ${lib_NAME}_BUILT_AS_STATIC +# ) +# TARGET_LINK_LIBRARIES(${lib_NAME} ${target_LIBRARIES}) + +# ## ======================== +# ## == Installation rules == +# ## ======================== + +# INSTALL( +# TARGETS ${lib_NAME} +# RUNTIME DESTINATION bin +# LIBRARY DESTINATION lib +# ARCHIVE DESTINATION lib/static +# ) +# INSTALL( +# FILES +# ${lib_HEADERS} +# DESTINATION include/${lib_DIR} +# ) + +## eof - $RCSfile$ diff --git a/lib/cpPlugins/Config.h.in b/lib/cpPlugins/Config.h.in new file mode 100644 index 0000000..53b6242 --- /dev/null +++ b/lib/cpPlugins/Config.h.in @@ -0,0 +1,103 @@ +#ifndef __CPPLUGINS__CONFIG__H__ +#define __CPPLUGINS__CONFIG__H__ + +#include +#include + +/* + * ========================================================================= + * Identify OS + * ========================================================================= + */ + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +# define cpPlugins_SYS_WINDOWS +# define cpPlugins_LIB_PREFIX "" +# define cpPlugins_LIB_EXT "dll" +# define cpPlugins_SEPARATOR ";" +# define cpPlugins_PATH_SEPARATOR '/' +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# define NOMINMAX +# include +# include +#elif defined( linux ) || defined( __linux ) +# define cpPlugins_SYS_LINUX +# define cpPlugins_LIB_PREFIX "lib" +# define cpPlugins_LIB_EXT "so" +# define cpPlugins_SEPARATOR ":" +# define cpPlugins_PATH_SEPARATOR '/' +#elif defined( __APPLE__ ) || defined( MACOSX ) || defined( macintosh ) || defined( Macintosh ) +# define cpPlugins_SYS_MACOS +# define cpPlugins_LIB_PREFIX "lib" +# define cpPlugins_LIB_EXT "dylib" +# define cpPlugins_SEPARATOR ":" +# define cpPlugins_PATH_SEPARATOR '/' +#elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) +# define cpPlugins_SYS_FREEBSD +# define cpPlugins_LIB_PREFIX "lib" +# define cpPlugins_LIB_EXT "so" +# define cpPlugins_SEPARATOR ":" +# define cpPlugins_PATH_SEPARATOR '/' +#else +# error "This operating system is not supported by cpPlugins" +#endif + +/* + * ========================================================================= + * Some global values + * ========================================================================= + */ + +#define cpPluginsObject +#define cpPlugins_PATHS "cpPlugins_PATHS" +#define cpPlugins_CONFIG "cpPlugins_Libraries.config" +#define cpPlugins_QT4_USED @QT4_FOUND@ +#if cpPlugins_QT4_USED == 1 +# define cpPlugins_QT4 +#else // cpPlugins_QT4_USED == 1 +# undef cpPlugins_QT4 +#endif // cpPlugins_QT4_USED == 1 + +/* + * ========================================================================= + * Version numbers and strings + * ========================================================================= + */ + +#define cpPlugins_MAJ_VERSION @prj_MAJ_VER@ +#define cpPlugins_MIN_VERSION @prj_MIN_VER@ +#define cpPlugins_REL_VERSION @prj_REL_VER@ +#define cpPlugins_VERSION "@prj_VER@" +#define cpPlugins_SHORT_VERSION "@prj_sVER@" + +/* + * ========================================================================= + * ITK related macros + * ========================================================================= + */ + +#include +#define ITK_MANUAL_INSTANTIATION +#ifndef ITK_DELETE_FUNCTION +# define ITK_DELETE_FUNCTION +#endif // ITK_DELETE_FUNCTION +#ifndef ITK_OVERRIDE +# define ITK_OVERRIDE +#endif // ITK_OVERRIDE + +/* + * ========================================================================= + * VTK related macros + * ========================================================================= + */ + +#include +#ifndef VTK_OVERRIDE +# define VTK_OVERRIDE +#endif // VTK_OVERRIDE + +#endif // __CPPLUGINS__CONFIG__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/DataObject.cxx b/lib/cpPlugins/DataObject.cxx new file mode 100644 index 0000000..d374fa3 --- /dev/null +++ b/lib/cpPlugins/DataObject.cxx @@ -0,0 +1,103 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject* cpPlugins::DataObject:: +GetSource( ) +{ + return( this->m_Source ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::ProcessObject* cpPlugins::DataObject:: +GetSource( ) const +{ + return( this->m_Source ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::DataObject:: +SetSource( cpPlugins::ProcessObject* src ) +{ + if( this->m_Source != src ) + { + this->m_Source = src; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::DataObject:: +DisconnectFromPipeline( ) +{ + // Disconnect input pipelines (ITK) + itk::DataObject* itk_obj = this->GetITK< itk::DataObject >( ); + if( itk_obj != NULL ) + itk_obj->DisconnectPipeline( ); + + // Disconnect input pipelines (VTK) + vtkImageData* vtk_image = this->GetVTK< vtkImageData >( ); + vtkPolyData* vtk_pd = this->GetVTK< vtkPolyData >( ); + if( vtk_image != NULL ) + { + vtkSmartPointer< vtkImageData > d = + vtkSmartPointer< vtkImageData >::New( ); + d->ShallowCopy( vtk_image ); + this->m_VTKObject = d; + } + else if( vtk_pd != NULL ) + { + vtkSmartPointer< vtkPolyData > d = + vtkSmartPointer< vtkPolyData >::New( ); + d->ShallowCopy( vtk_pd ); + this->m_VTKObject = d; + + } // fi + + // Unbind source + this->m_Source = NULL; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +vtkProp* cpPlugins::DataObject:: +GetVTKActor( ) +{ + if( this->m_Actor.GetPointer( ) == NULL ) + this->_CreateVTKActor( ); + return( this->m_Actor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const vtkProp* cpPlugins::DataObject:: +GetVTKActor( ) const +{ + if( this->m_Actor.GetPointer( ) == NULL ) + this->_CreateVTKActor( ); + return( this->m_Actor.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject:: +DataObject( ) + : Superclass( ), + m_Source( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject:: +~DataObject( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::DataObject:: +_CreateVTKActor( ) const +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/DataObject.h b/lib/cpPlugins/DataObject.h new file mode 100644 index 0000000..e59ede2 --- /dev/null +++ b/lib/cpPlugins/DataObject.h @@ -0,0 +1,60 @@ +#ifndef __CPPLUGINS__DATAOBJECT__H__ +#define __CPPLUGINS__DATAOBJECT__H__ + +#include +#include +#include + +namespace cpPlugins +{ + // Some forward declarations + class ProcessObject; + + /** + */ + class cpPlugins_EXPORT DataObject + : public Object + { + 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: + ProcessObject* GetSource( ); + const ProcessObject* GetSource( ) const; + void SetSource( ProcessObject* src ); + + void DisconnectFromPipeline( ); + + // VTK actors + vtkProp* GetVTKActor( ); + const vtkProp* GetVTKActor( ) const; + + protected: + DataObject( ); + virtual ~DataObject( ); + + virtual void _CreateVTKActor( ) const; + + private: + // Purposely not implemented + DataObject( const Self& ); + Self& operator=( const Self& ); + + protected: + ProcessObject* m_Source; + mutable vtkSmartPointer< vtkProp > m_Actor; + }; + +} // ecapseman + +#endif // __CPPLUGINS__DATAOBJECT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Image.cxx b/lib/cpPlugins/Image.cxx new file mode 100644 index 0000000..994e643 --- /dev/null +++ b/lib/cpPlugins/Image.cxx @@ -0,0 +1,66 @@ +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpPlugins::Image:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + bool s = this->_ITK_2_VTK_0_Scalar< 2 >( o ); + if( !s ) s = this->_ITK_2_VTK_0_Scalar< 3 >( o ); + if( !s ) s = this->_ITK_2_VTK_0_Color< 2 >( o ); + if( !s ) s = this->_ITK_2_VTK_0_Color< 3 >( o ); + if( !s ) + { + this->m_VTKObject = NULL; + this->m_ITKvVTK = NULL; + + } // fi + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Image:: +SetVTK( vtkObjectBase* o ) +{ + this->Superclass::SetVTK( o ); + std::cerr << "Image: TODO this!!!!" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Image:: +Image( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Image:: +~Image( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Image:: +_CreateVTKActor( ) const +{ + vtkImageData* image = + const_cast< vtkImageData* >( this->GetVTK< vtkImageData >( ) ); + if( image != NULL ) + { + vtkImageSliceMapper* mapper = vtkImageSliceMapper::New( ); + vtkImageActor* actor = vtkImageActor::New( ); + mapper->SetInputData( image ); + actor->SetMapper( mapper ); + actor->GetProperty( )->SetInterpolationTypeToNearest( ); + this->m_Actor = actor; + mapper->Delete( ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Image.h b/lib/cpPlugins/Image.h new file mode 100644 index 0000000..c5cb760 --- /dev/null +++ b/lib/cpPlugins/Image.h @@ -0,0 +1,63 @@ +#ifndef __CPPLUGINS__IMAGE__H__ +#define __CPPLUGINS__IMAGE__H__ + +#include + +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT Image + : public DataObject + { + public: + typedef Image Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Image, DataObject ); + cpPlugins_Id_Macro( Image, Object ); + + public: + virtual void SetITK( itk::LightObject* o ) ITK_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) ITK_OVERRIDE; + + protected: + Image( ); + virtual ~Image( ); + + virtual void _CreateVTKActor( ) const ITK_OVERRIDE; + + template< unsigned int D > + inline bool _ITK_2_VTK_0_Scalar( itk::LightObject* o ); + + template< unsigned int D > + inline bool _ITK_2_VTK_0_Color( itk::LightObject* o ); + + template< class P, unsigned int D > + inline bool _ITK_2_VTK_1( itk::LightObject* o ); + + template< class T > + inline bool _ITK_2_VTK_2( itk::LightObject* o ); + + private: + // Purposely not implemented + Image( const Self& ); + Self& operator=( const Self& ); + + protected: + itk::ProcessObject::Pointer m_ITKvVTK; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__IMAGE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Image.hxx b/lib/cpPlugins/Image.hxx new file mode 100644 index 0000000..91c44bb --- /dev/null +++ b/lib/cpPlugins/Image.hxx @@ -0,0 +1,165 @@ +#ifndef __CPPLUGINS__IMAGE__HXX__ +#define __CPPLUGINS__IMAGE__HXX__ + +#include +#include + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpPlugins::Image:: +_ITK_2_VTK_0_Scalar( itk::LightObject* o ) +{ + bool s = false; + if( dynamic_cast< itk::ImageBase< D >* >( o ) != NULL ) + { + s |= this->_ITK_2_VTK_1< char, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< short, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< int, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< long, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< float, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< double, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< unsigned char, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< unsigned short, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< unsigned int, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< unsigned long, D >( o ); + + } // fi + return( s ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpPlugins::Image:: +_ITK_2_VTK_0_Color( itk::LightObject* o ) +{ + bool s = false; + if( dynamic_cast< itk::ImageBase< D >* >( o ) != NULL ) + { + s |= this->_ITK_2_VTK_1< itk::RGBPixel< char >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< short >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< int >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< long >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< float >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< double >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned char >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned short >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned int >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned long >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< char >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< short >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< int >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< long >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< float >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< double >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned char >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned short >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned int >, D >( o ); + if( !s ) s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned long >, D >( o ); + + } // fi + return( s ); +} + +// ------------------------------------------------------------------------- +template< class P, unsigned int D > +bool cpPlugins::Image:: +_ITK_2_VTK_1( itk::LightObject* o ) +{ + if( dynamic_cast< itk::Image< P, D >* >( o ) != NULL ) + return( this->_ITK_2_VTK_2< itk::Image< P, D > >( o ) ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class T > +bool cpPlugins::Image:: +_ITK_2_VTK_2( itk::LightObject* o ) +{ + typedef itk::ImageToVTKImageFilter< T > _I2V; + + T* image = dynamic_cast< T* >( o ); + if( image != NULL ) + { + _I2V* f = dynamic_cast< _I2V* >( this->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + typename _I2V::Pointer nf = _I2V::New( ); + this->m_ITKvVTK = nf; + f = nf.GetPointer( ); + + } // fi + f->SetInput( image ); + f->Update( ); + + // Keep object track + this->m_ITKObject = o; + this->m_VTKObject = f->GetOutput( ); + return( true ); + } + else + return( false ); +} + +/* + * ========================================================================= + * Demangle macros + * ========================================================================= + */ +#define cpPlugins_Image_Demangle_Dim( F, I, D ) \ + if( dynamic_cast< itk::ImageBase< D >* >( I ) != NULL ) \ + this->F( dynamic_cast< itk::ImageBase< D >* >( I ) ) + +#define cpPlugins_Image_Demangle_Pixel_Dim( F, I, P, D ) \ + if( dynamic_cast< itk::Image< P, D >* >( I ) != NULL ) \ + this->F( dynamic_cast< itk::Image< P, D >* >( I ) ) + +#define cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, P, D ) \ + if( dynamic_cast< itk::Image< itk::C##Pixel< P >, D >* >( I ) != NULL ) \ + this->F( dynamic_cast< itk::Image< itk::C##Pixel< P >, D >* >( I ) ) + +#define cpPlugins_Image_Demangle_Pixel_AllInts( F, I, D ) \ + cpPlugins_Image_Demangle_Pixel_Dim ( F, I, char, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, short, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, int, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, long, D ) + +#define cpPlugins_Image_Demangle_Pixel_AllUInts( F, I, D ) \ + cpPlugins_Image_Demangle_Pixel_Dim ( F, I, unsigned char, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, unsigned short, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, unsigned int, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, unsigned long, D ) + +#define cpPlugins_Image_Demangle_Pixel_AllFloats( F, I, D ) \ + cpPlugins_Image_Demangle_Pixel_Dim ( F, I, float, D ); \ + else cpPlugins_Image_Demangle_Pixel_Dim( F, I, double, D ) + +#define cpPlugins_Image_Demangle_Pixel_AllScalars( F, I, D ) \ + cpPlugins_Image_Demangle_Pixel_AllInts ( F, I, D ); \ + else cpPlugins_Image_Demangle_Pixel_AllUInts ( F, I, D ); \ + else cpPlugins_Image_Demangle_Pixel_AllFloats( F, I, D ) + +#define cpPlugins_Image_Demangle_ColorPixel_AllInts( F, I, C, D ) \ + cpPlugins_Image_Demangle_ColorPixel_Dim ( F, I, C, char, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, short, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, int, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, long, D ) + +#define cpPlugins_Image_Demangle_ColorPixel_AllUInts( F, I, C, D ) \ + cpPlugins_Image_Demangle_ColorPixel_Dim ( F, I, C, unsigned char, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, unsigned short, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, unsigned int, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, unsigned long, D ) + +#define cpPlugins_Image_Demangle_ColorPixel_AllFloats( F, I, C, D ) \ + cpPlugins_Image_Demangle_ColorPixel_Dim ( F, I, C, float, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_Dim( F, I, C, double, D ) + +#define cpPlugins_Image_Demangle_ColorPixel_AllScalars( F, I, C, D ) \ + cpPlugins_Image_Demangle_ColorPixel_AllInts ( F, I, C, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_AllUInts ( F, I, C, D ); \ + else cpPlugins_Image_Demangle_ColorPixel_AllFloats( F, I, C, D ) + +#endif // __CPPLUGINS__IMAGE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ImageIndexesContainer.cxx b/lib/cpPlugins/ImageIndexesContainer.cxx new file mode 100644 index 0000000..c7d2f8a --- /dev/null +++ b/lib/cpPlugins/ImageIndexesContainer.cxx @@ -0,0 +1,39 @@ +#include + +// ------------------------------------------------------------------------- +void cpPlugins::ImageIndexesContainer:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + bool s = this->_ITK_2_VTK< 2 >( o ); + if( !s ) s = this->_ITK_2_VTK< 3 >( o ); + if( !s ) + { + this->m_VTKObject = NULL; + this->m_ITKvVTK = NULL; + + } // fi + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ImageIndexesContainer:: +SetVTK( vtkObjectBase* o ) +{ + // Do nothing +} + +// ------------------------------------------------------------------------- +cpPlugins::ImageIndexesContainer:: +ImageIndexesContainer( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::ImageIndexesContainer:: +~ImageIndexesContainer( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ImageIndexesContainer.h b/lib/cpPlugins/ImageIndexesContainer.h new file mode 100644 index 0000000..3edfda3 --- /dev/null +++ b/lib/cpPlugins/ImageIndexesContainer.h @@ -0,0 +1,53 @@ +#ifndef __CPPLUGINS__IMAGEINDEXESCONTAINER__H__ +#define __CPPLUGINS__IMAGEINDEXESCONTAINER__H__ + +#include + +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT ImageIndexesContainer + : public DataObject + { + public: + typedef ImageIndexesContainer Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageIndexesContainer, DataObject ); + cpPlugins_Id_Macro( ImageIndexesContainer, Object ); + + public: + virtual void SetITK( itk::LightObject* o ) ITK_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) ITK_OVERRIDE; + + protected: + ImageIndexesContainer( ); + virtual ~ImageIndexesContainer( ); + + template< unsigned int _NDim > + inline bool _ITK_2_VTK( itk::LightObject* o ); + + private: + // Purposely not implemented + ImageIndexesContainer( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkPolyDataAlgorithm > m_ITKvVTK; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__IMAGEINDEXESCONTAINER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ImageIndexesContainer.hxx b/lib/cpPlugins/ImageIndexesContainer.hxx new file mode 100644 index 0000000..2346ad6 --- /dev/null +++ b/lib/cpPlugins/ImageIndexesContainer.hxx @@ -0,0 +1,44 @@ +#ifndef __CPPLUGINS__IMAGEINDEXESCONTAINER__HXX__ +#define __CPPLUGINS__IMAGEINDEXESCONTAINER__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< unsigned int _NDim > +bool cpPlugins::ImageIndexesContainer:: +_ITK_2_VTK( itk::LightObject* o ) +{ + typedef + cpExtensions::DataStructures::ImageIndexesContainer< _NDim > + _TImageIndexesContainer; + typedef + cpExtensions::Visualization::ImageIndexesContainerToPolyData< _TImageIndexesContainer > + _TFilter; + + auto cont = dynamic_cast< _TImageIndexesContainer* >( o ); + if( cont != NULL ) + { + _TFilter* f = dynamic_cast< _TFilter* >( this->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + vtkSmartPointer< _TFilter > nf = _TFilter::New( ); + this->m_ITKvVTK = nf.GetPointer( ); + f = nf.GetPointer( ); + + } // fi + f->SetInput( cont ); + f->SetReferenceImage( cont->GetReferenceImage( ) ); + f->Update( ); + + // Keep object track + this->m_ITKObject = o; + this->m_VTKObject = f->GetOutput( ); + return( true ); + } + else + return( false ); +} + +#endif // __CPPLUGINS__IMAGEINDEXESCONTAINER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface.cxx b/lib/cpPlugins/Interface.cxx new file mode 100644 index 0000000..8ca6832 --- /dev/null +++ b/lib/cpPlugins/Interface.cxx @@ -0,0 +1,374 @@ +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +Interface( ) +{ + char* p = std::getenv( cpPlugins_PATHS ); + std::stringstream str; + if( p != NULL ) + str << p << cpPlugins_SEPARATOR; + str << "."; + this->UpdateEnvironments( str.str( ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +~Interface( ) +{ +} + +// ------------------------------------------------------------------------- +const std::set< std::string >& cpPlugins::Interface:: +GetPaths( ) const +{ + return( this->m_Paths ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Interface:: +GetLibraries( ) const +{ + std::set< std::string > res; + for( + auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i + ) + res.insert( i->first ); + return( res ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Interface:: +GetPlugins( ) const +{ + std::set< std::string > res; + for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i ) + res.insert( i->first ); + return( res ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Interface:: +GetCategories( ) const +{ + std::set< std::string > res; + for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i ) + res.insert( i->first ); + return( res ); +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::Interface:: +GetFilters( const std::string& category ) const +{ + std::set< std::string > res; + auto cIt = this->m_Filters.find( category ); + if( cIt != this->m_Filters.end( ) ) + { + for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i ) + res.insert( i->first ); + + } // rof + return( res ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +UpdateEnvironments( const std::string& new_environment ) +{ + std::vector< std::string > tokens; + cpPlugins::TokenizeString( tokens, new_environment, cpPlugins_SEPARATOR ); + for( auto i = tokens.begin( ); i != tokens.end( ); ++i ) + { + std::string dir = cpPlugins::CanonicalPath( *i ); + if( dir != "" ) + this->m_Paths.insert( dir ); + + } // rof +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +LoadEnvironment( ) +{ + std::stringstream all_errors; + for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i ) + { + std::stringstream dir; + dir << *i; + if( !cpPlugins::IsPathSeparator( i->back( ) ) ) + dir << cpPlugins_PATH_SEPARATOR; + std::string config_file; + if( + cpPlugins::ReadFileIntoBuffer( + config_file, + cpPlugins::CanonicalPath( + dir.str( ) + std::string( cpPlugins_CONFIG ) + ) + ) + ) + { + std::istringstream input( config_file ); + for( std::string line; std::getline( input, line ); ) + { + std::vector< std::string > tokens; + cpPlugins::TokenizeString( tokens, line, "@" ); + std::string library_file = ""; + if( tokens[ 0 ] == "local" ) + library_file = + cpPlugins::CanonicalPath( + dir.str( ) + + std::string( cpPlugins_LIB_PREFIX ) + + tokens[ 1 ] + + std::string( "." ) + + std::string( cpPlugins_LIB_EXT ) + ); + else if( tokens[ 0 ] == "global" ) + library_file = tokens[ 1 ]; + + if( library_file != "" ) + { + std::string error = ""; + void* hnd = cpPlugins::DLLManager::Load( library_file, error ); + if( hnd != NULL ) + this->m_Libraries[ library_file ] = hnd; + else + all_errors << " ; " << error; + + } // fi + + } // rof + + } // fi + + } // rof + + // Throw errors + if( all_errors.str( ) != "" ) + throw std::runtime_error( + std::string( "Loading environment libraries errors: " ) + + all_errors.str( ) + ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +LoadFile( const std::string& fname ) +{ + // Resolve canonical filename + std::string can_name = cpPlugins::CanonicalPath( fname ); + if( can_name == "" ) + throw std::runtime_error( + std::string( "Loading file: can't find library \"" ) + + fname + + std::string( "\"" ) + ); + if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) ) + return; + + // Load the library + std::string error = ""; + void* hnd = cpPlugins::DLLManager::Load( can_name, error ); + if( hnd == NULL ) + throw std::runtime_error( + std::string( "Loading plugin library: " ) + error + ); + + // Get plugins name + typedef const char* ( *_TFunction )( ); + _TFunction plugins_name_function = ( _TFunction )( + cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" ) + ); + if( plugins_name_function == NULL ) + { + cpPlugins::DLLManager::UnLoad( hnd ); + throw std::runtime_error( + std::string( "Library \"" ) + + can_name + + std::string( "\" not recognized as a cpPlugins library" ) + ); + + } // fi + std::string plugins_name = plugins_name_function( ); + + // Get loaded filters + _TFunction function = ( _TFunction )( + cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" ) + ); + if( function == NULL ) + { + cpPlugins::DLLManager::UnLoad( hnd ); + throw std::runtime_error( + std::string( "Library \"" ) + + can_name + + std::string( "\" not recognized as a cpPlugins library" ) + ); + + } // fi + std::string descriptors = function( ); + std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' ); + std::istringstream str( descriptors ); + TFilters filters; + while( str ) + { + std::string value, category, name; + str >> value; + if( value == "" ) + continue; + std::replace( value.begin( ), value.end( ), ':', ' ' ); + std::istringstream value_str( value ); + value_str >> category >> name; + + // Check if the filter has been already loaded + bool found = false; + auto fIt = this->m_Filters.find( category ); + if( fIt != this->m_Filters.end( ) ) + found = fIt->second.find( name ) != fIt->second.end( ); + if( found ) + { + cpPlugins::DLLManager::UnLoad( hnd ); + throw std::runtime_error( + std::string( "Filter \"" ) + + category + std::string( "::" ) + name + + std::string( "\" already exists." ) + ); + + } // fi + + // Get filter creator + TCreator creator = ( TCreator )( + cpPlugins::DLLManager::GetFunctionHandle( hnd, category + "_" + name ) + ); + if( creator == NULL ) + { + cpPlugins::DLLManager::UnLoad( hnd ); + throw std::runtime_error( + std::string( "Filter \"" ) + + category + std::string( "::" ) + name + + std::string( "\" does not have a valid creator." ) + ); + + } // fi + + TCreatorData data; + data.PluginName = plugins_name; + data.LibraryHandle = hnd; + data.Creator = creator; + filters[ category ][ name ] = data; + + } // elihw + + // Keep track of all loaded handlers + for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) + for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt ) + this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second; + this->m_Plugins[ can_name ] = hnd; +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +LoadPlugin( const std::string& pname ) +{ + std::stringstream fname; + fname << cpPlugins_LIB_PREFIX << pname << "." << cpPlugins_LIB_EXT; + unsigned int count = 0; + for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i ) + { + std::stringstream dir; + dir << *i; + if( !cpPlugins::IsPathSeparator( i->back( ) ) ) + dir << cpPlugins_PATH_SEPARATOR; + dir << fname.str( ); + try + { + this->LoadFile( dir.str( ) ); + } + catch( ... ) + { + count++; + + } // yrt + + } // rof + + // Throw error, if any + if( count == this->m_Paths.size( ) ) + throw std::runtime_error( + std::string( "Could not load plugin " ) + + std::string( "\"" ) + pname + + std::string( "\" from any registered path." ) + ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +LoadDirectory( const std::string& dirname ) +{ + DIR* dir; + struct dirent* ent; + if( ( dir = opendir( dirname.c_str( ) ) ) != NULL ) + { + while( ( ent = readdir( dir ) ) != NULL ) + { + try + { + std::stringstream fname; + fname << dirname << cpPlugins_PATH_SEPARATOR << ent->d_name; + this->LoadFile( fname.str( ) ); + } + catch( ... ) { } + + } // elihw + closedir( dir ); + } + else + throw std::runtime_error( + std::string( "Could not load directory " ) + + std::string( "\"" ) + dirname + std::string( "\"" ) + ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +GuessPlugins( ) +{ + for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i ) + { + try + { + this->LoadDirectory( *i ); + } + catch( ... ) + { + } // yrt + + } // rof +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject::Pointer cpPlugins::Interface:: +CreateProcessObject( const std::string& category, const std::string& name ) +{ + typedef cpPlugins::ProcessObject::Pointer _Ptr; + _Ptr o = NULL; + auto cIt = this->m_Filters.find( category ); + if( cIt != this->m_Filters.end( ) ) + { + auto nIt = cIt->second.find( name ); + if( nIt != cIt->second.end( ) ) + { + o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( ); + o->SetName( name ); + o->SetPluginName( nIt->second.PluginName ); + + } // fi + + } // fi + return( o ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface.h b/lib/cpPlugins/Interface.h new file mode 100644 index 0000000..0f46554 --- /dev/null +++ b/lib/cpPlugins/Interface.h @@ -0,0 +1,112 @@ +#ifndef __CPPLUGINS__INTERFACE__H__ +#define __CPPLUGINS__INTERFACE__H__ + +#include +#include +#include +#include +#include +#include + +/* TODO + #include +*/ + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT Interface + { + public: + typedef Interface Self; + + typedef void* ( *TCreator )( ); + typedef std::map< std::string, void* > TLibraries; + struct TCreatorData + { + std::string PluginName; + void* LibraryHandle; + TCreator Creator; + }; + typedef std::map< std::string, std::map< std::string, TCreatorData > > TFilters; + + /* TODO + typedef std::pair< std::string, TCreator > TDynFunc; + typedef std::map< std::string, TDynFunc > TDynFilter; + typedef std::map< std::string, TDynFilter > TDynFilters; + typedef std::pair< std::string, void* > TDynFileInfo; + typedef std::map< std::string, TDynFileInfo > TDynLibraries; + */ + + public: + Interface( ); + virtual ~Interface( ); + + const std::set< std::string >& GetPaths( ) const; + std::set< std::string > GetLibraries( ) const; + std::set< std::string > GetPlugins( ) const; + std::set< std::string > GetCategories( ) const; + std::set< std::string > GetFilters( const std::string& category ) const; + + void UpdateEnvironments( const std::string& new_environment ); + void LoadEnvironment( ); + void LoadFile( const std::string& fname ); + void LoadPlugin( const std::string& pname ); + void LoadDirectory( const std::string& dirname ); + void GuessPlugins( ); + + cpPlugins::ProcessObject::Pointer CreateProcessObject( + const std::string& category, const std::string& name + ); + + protected: + std::set< std::string > m_Paths; + TLibraries m_Libraries; + TLibraries m_Plugins; + TFilters m_Filters; + + + /* TODO + const TFilters& GetFilters( ); + + void UpdatePaths( ); + void GuessAccesiblePlugins( ); + void LoadPlugin( const std::string& name ); + void LoadPluginDir( const std::string& dirname ); + void LoadPluginFile( const std::string& filename ); + void UnloadAll( ); + + ProcessObject::Pointer Create( + const std::string& category, const std::string& name + ); + std::string GetPluginName( + const std::string& category, const std::string& name + ) const; + std::string GetPluginName( const ProcessObject* obj ) const; + std::set< std::string > GetPlugins( ) const; + + protected: + static void* _DLOpen( const std::string& fname, std::string& error ); + static const char* _DLGetName( void* hnd ); + static TFilters _DLGetFilters( void* hnd ); + static TCreator _DLGetCreator( + void* hnd, const std::string& category, const std::string& name + ); + static void _DLClose( void* hnd ); + + protected: + std::vector< std::string > m_Paths; + TDynLibraries m_DynLibraries; + TDynFilters m_DynFilters; + TFilters m_Filters; + + static unsigned int InterfacesCount; + */ + }; + +} // ecapseman + +#endif // __CPPLUGINS__INTERFACE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/LoadDynamicLibrariesFunctions.cxx b/lib/cpPlugins/LoadDynamicLibrariesFunctions.cxx new file mode 100644 index 0000000..9aeafee --- /dev/null +++ b/lib/cpPlugins/LoadDynamicLibrariesFunctions.cxx @@ -0,0 +1,53 @@ +#include + +#ifdef cpPlugins_SYS_WINDOWS +# include +#else // cpPlugins_SYS_WINDOWS +# include +#endif // cpPlugins_SYS_WINDOWS + +// ------------------------------------------------------------------------- +void* cpPlugins::DLLManager:: +Load( const std::string& fname, std::string& error ) +{ + void* hnd = NULL; +#ifdef cpPlugins_SYS_WINDOWS + hnd = ::LoadLibraryA( fname.c_str( ) ); +#else // cpPlugins_SYS_WINDOWS + hnd = dlopen( fname.c_str( ), RTLD_LAZY | RTLD_GLOBAL ); + if( hnd == NULL ) + error = dlerror( ); + else + dlerror( ); +#endif // cpPlugins_SYS_WINDOWS + return( hnd ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::DLLManager:: +UnLoad( void* hnd ) +{ +#ifdef cpPlugins_SYS_WINDOWS + ::FreeLibrary( ( HMODULE )hnd ); +#else // cpPlugins_SYS_WINDOWS + dlclose( hnd ); +#endif // cpPlugins_SYS_WINDOWS +} + +// ------------------------------------------------------------------------- +void* cpPlugins::DLLManager:: +GetFunctionHandle( void* hnd, const std::string& function ) +{ + void* f = NULL; + if( hnd != NULL ) + { +#ifdef cpPlugins_SYS_WINDOWS + f = ::GetProcAddress( ( HMODULE )hnd, function.c_str( ) ); +#else // cpPlugins_SYS_WINDOWS + f = dlsym( hnd, function.c_str( ) ); +#endif // cpPlugins_SYS_WINDOWS + } // fi + return( f ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/LoadDynamicLibrariesFunctions.h b/lib/cpPlugins/LoadDynamicLibrariesFunctions.h new file mode 100644 index 0000000..0fa1df5 --- /dev/null +++ b/lib/cpPlugins/LoadDynamicLibrariesFunctions.h @@ -0,0 +1,22 @@ +#ifndef __CPPLUGINS__LOADDYNAMICLIBRARIESFUNCTIONS__H__ +#define __CPPLUGINS__LOADDYNAMICLIBRARIESFUNCTIONS__H__ + +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT DLLManager + { + public: + static void* Load( const std::string& fname, std::string& error ); + static void UnLoad( void* hnd ); + static void* GetFunctionHandle( void* hnd, const std::string& function ); + }; + +} // ecapseman + +#endif // __CPPLUGINS__LOADDYNAMICLIBRARIESFUNCTIONS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Mesh.cxx b/lib/cpPlugins/Mesh.cxx new file mode 100644 index 0000000..700e534 --- /dev/null +++ b/lib/cpPlugins/Mesh.cxx @@ -0,0 +1,220 @@ +#include + +#define cpPlugins_Mesh_MAX_POLYS 65535 + +// ------------------------------------------------------------------------- +void cpPlugins::Mesh::MeshActor:: +SetMesh( vtkPolyData* mesh ) +{ + this->Normals = NULL; + this->Stripper = NULL; + this->Mapper = NULL; + this->LODActor = NULL; + this->Actor = NULL; + if( mesh != NULL ) + { + unsigned long nPolys = mesh->GetNumberOfPolys( ); + if( nPolys >= cpPlugins_Mesh_MAX_POLYS ) + { + this->Normals = vtkSmartPointer< vtkPolyDataNormals >::New( ); + this->Stripper = vtkSmartPointer< vtkStripper >::New( ); + this->Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->LODActor = vtkSmartPointer< vtkQuadricLODActor >::New( ); + + double r[ 2 ]; + mesh->GetScalarRange( r ); + + this->Normals->SetInputData( mesh ); + this->Normals->SetFeatureAngle( 60.0 ); + this->Stripper->SetInputConnection( this->Normals->GetOutputPort( ) ); + this->Mapper->SetInputConnection( this->Stripper->GetOutputPort( ) ); + this->Mapper->UseLookupTableScalarRangeOff( ); + this->Mapper->SetScalarRange( r[ 0 ], r[ 1 ] ); + this->LODActor->SetMapper( this->Mapper ); + this->LODActor->DeferLODConstructionOff( ); + } + else + { + this->Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->Actor = vtkSmartPointer< vtkActor >::New( ); + this->Mapper->SetInputData( mesh ); + this->Actor->SetMapper( this->Mapper ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Mesh:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + bool r = this->_ITK_2_VTK< itk::Mesh< float, 2 > >( o ); + if( !r ) r = this->_ITK_2_VTK< itk::Mesh< double, 2 > >( o ); + if( !r ) r = this->_ITK_2_VTK< itk::Mesh< float, 3 > >( o ); + if( !r ) r = this->_ITK_2_VTK< itk::Mesh< double, 3 > >( o ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Mesh:: +SetVTK( vtkObjectBase* o ) +{ + 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; + + vtkPolyData* mesh = dynamic_cast< vtkPolyData* >( o ); + if( mesh == NULL ) + { + this->m_ITKObject = NULL; + this->Modified( ); + return; + + } // fi + + if( this->m_VTKObject.GetPointer( ) != mesh ) + { + this->m_VTKObject = mesh; + + // 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_ITKObject = imesh; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins::Mesh:: +Mesh( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Mesh:: +~Mesh( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Mesh:: +_CreateVTKActor( ) const +{ + this->m_MeshActor.SetMesh( + const_cast< vtkPolyData* >( this->GetVTK< vtkPolyData >( ) ) + ); + if( this->m_MeshActor.LODActor.GetPointer( ) != NULL ) + this->m_Actor = this->m_MeshActor.LODActor.GetPointer( ); + else if( this->m_MeshActor.Actor.GetPointer( ) != NULL ) + this->m_Actor = this->m_MeshActor.Actor.GetPointer( ); + else + this->m_Actor = NULL; + + /* TODO + vtkPolyData* mesh = + const_cast< vtkPolyData* >( this->GetVTK< vtkPolyData >( ) ); + if( mesh != NULL ) + { + unsigned long nPolys = mesh->GetNumberOfPolys( ); + if( nPolys >= cpPlugins_Mesh_MAX_POLYS ) + { + auto normals = vtkPolyDataNormals::New( ); + auto stripper = vtkStripper::New( ); + auto mapper = vtkPolyDataMapper::New( ); + auto actor = vtkQuadricLODActor::New( ); + + double r[ 2 ]; + mesh->GetScalarRange( r ); + + normals->SetInputData( mesh ); + normals->SetFeatureAngle( 60.0 ); + stripper->SetInputConnection( normals->GetOutputPort( ) ); + mapper->SetInputConnection( stripper->GetOutputPort( ) ); + mapper->UseLookupTableScalarRangeOff( ); + mapper->SetScalarRange( r[ 0 ], r[ 1 ] ); + actor->SetMapper( mapper ); + actor->DeferLODConstructionOff( ); + this->m_Actor = actor; + mapper->Delete( ); + stripper->Delete( ); + normals->Delete( ); + } + else + { + auto mapper = vtkPolyDataMapper::New( ); + mapper->SetInputData( mesh ); + auto actor = vtkActor::New( ); + actor->SetMapper( mapper ); + this->m_Actor = actor; + mapper->Delete( ); + + } // fi + + } // fi + */ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Mesh.h b/lib/cpPlugins/Mesh.h new file mode 100644 index 0000000..c1e7cab --- /dev/null +++ b/lib/cpPlugins/Mesh.h @@ -0,0 +1,72 @@ +#ifndef __CPPLUGINS__MESH__H__ +#define __CPPLUGINS__MESH__H__ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT Mesh + : public DataObject + { + public: + typedef Mesh Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + struct MeshActor + { + vtkSmartPointer< vtkPolyDataNormals > Normals; + vtkSmartPointer< vtkStripper > Stripper; + vtkSmartPointer< vtkPolyDataMapper > Mapper; + vtkSmartPointer< vtkQuadricLODActor > LODActor; + vtkSmartPointer< vtkActor > Actor; + + void SetMesh( vtkPolyData* mesh ); + }; + + public: + itkNewMacro( Self ); + itkTypeMacro( Mesh, DataObject ); + cpPlugins_Id_Macro( Mesh, Object ); + + public: + virtual void SetITK( itk::LightObject* o ) ITK_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) ITK_OVERRIDE; + + protected: + Mesh( ); + virtual ~Mesh( ); + + virtual void _CreateVTKActor( ) const ITK_OVERRIDE; + + template< class M > + inline bool _ITK_2_VTK( itk::LightObject* o ); + + private: + // Purposely not implemented + Mesh( const Self& ); + Self& operator=( const Self& ); + + protected: + mutable MeshActor m_MeshActor; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__MESH__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Mesh.hxx b/lib/cpPlugins/Mesh.hxx new file mode 100644 index 0000000..ccd269f --- /dev/null +++ b/lib/cpPlugins/Mesh.hxx @@ -0,0 +1,72 @@ +#ifndef __CPPLUGINS__MESH__HXX__ +#define __CPPLUGINS__MESH__HXX__ + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class M > +bool cpPlugins::Mesh:: +_ITK_2_VTK( itk::LightObject* o ) +{ + M* mesh = dynamic_cast< M* >( o ); + if( mesh == NULL ) + return( false ); + + long numPoints = mesh->GetNumberOfPoints( ); + if( numPoints == 0 ) + return( false ); + + 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( M::PointDimension == 2 ) + vpoints->SetPoint( + VTKId, + i->Value( )[ 0 ], i->Value( )[ 1 ], 0 + ); + else if( M::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_VTKObject = vmesh; + this->Modified( ); + return( true ); +} + +#endif // __CPPLUGINS__MESH__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Object.cxx b/lib/cpPlugins/Object.cxx new file mode 100644 index 0000000..0f68762 --- /dev/null +++ b/lib/cpPlugins/Object.cxx @@ -0,0 +1,101 @@ +#include + +#include +#include + +// ------------------------------------------------------------------------- +const float& cpPlugins::Object:: +GetViewX( ) const +{ + return( this->m_ViewX ); +} + +// ------------------------------------------------------------------------- +const float& cpPlugins::Object:: +GetViewY( ) const +{ + return( this->m_ViewY ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Object:: +SetViewCoords( float x, float y ) +{ + this->m_ViewX = x; + this->m_ViewY = y; + // WARNING: do not call "this->Modified( )" -> It could lead to a + // re-execution of all pipeline +} + +// ------------------------------------------------------------------------- +void cpPlugins::Object:: +Modified( ) const +{ + const itk::Object* i = this->GetITK< itk::Object >( ); + vtkObject* v = const_cast< vtkObject* >( this->GetVTK< vtkObject >( ) ); + if( i != NULL ) i->Modified( ); + if( v != NULL ) v->Modified( ); + this->Superclass::Modified( ); +} + +// ------------------------------------------------------------------------- +itk::ModifiedTimeType cpPlugins::Object:: +GetMTime( ) const +{ + const itk::Object* i = this->GetITK< itk::Object >( ); + vtkObject* v = const_cast< vtkObject* >( this->GetVTK< vtkObject >( ) ); + if( i != NULL && v == NULL ) + return( i->GetMTime( ) ); + else if( i == NULL && v != NULL ) + return( v->GetMTime( ) ); + else if( i != NULL && v != NULL ) + { + auto iTime = i->GetMTime( ); + auto vTime = i->GetMTime( ); + return( itk::ModifiedTimeType( ( iTime > vTime )? iTime: vTime ) ); + } + else + return( this->Superclass::GetMTime( ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Object:: +SetITK( itk::LightObject* o ) +{ + if( this->m_ITKObject.GetPointer( ) != o ) + { + this->m_ITKObject = o; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Object:: +SetVTK( vtkObjectBase* o ) +{ + if( this->m_VTKObject.GetPointer( ) != o ) + { + this->m_VTKObject = o; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins::Object:: +Object( ) + : m_ITKObject( NULL ), + m_VTKObject( NULL ), + m_ViewX( float( 0 ) ), + m_ViewY( float( 0 ) ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Object:: +~Object( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Object.h b/lib/cpPlugins/Object.h new file mode 100644 index 0000000..7ddecbd --- /dev/null +++ b/lib/cpPlugins/Object.h @@ -0,0 +1,78 @@ +#ifndef __CPPLUGINS__OBJECT__H__ +#define __CPPLUGINS__OBJECT__H__ + +#include + +#include +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + /** + */ + 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 ITK_OVERRIDE; + virtual itk::ModifiedTimeType GetMTime( ) const ITK_OVERRIDE; + + virtual void SetITK( itk::LightObject* o ); + virtual void SetVTK( vtkObjectBase* o ); + + template< class T > + inline T* GetITK( ); + + template< class T > + inline const T* GetITK( ) const; + + template< class T > + inline T* GetVTK( ); + + template< class T > + inline const T* GetVTK( ) const; + + protected: + Object( ); + virtual ~Object( ); + + private: + // Purposely not implemented + Object( const Self& ); + Self& operator=( const Self& ); + + protected: + itk::LightObject::Pointer m_ITKObject; + vtkSmartPointer< vtkObjectBase > m_VTKObject; + + float m_ViewX; + float m_ViewY; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__OBJECT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Object.hxx b/lib/cpPlugins/Object.hxx new file mode 100644 index 0000000..4e3f873 --- /dev/null +++ b/lib/cpPlugins/Object.hxx @@ -0,0 +1,38 @@ +#ifndef __CPPLUGINS__OBJECT__HXX__ +#define __CPPLUGINS__OBJECT__HXX__ + +// ------------------------------------------------------------------------- +template< class T > +T* cpPlugins::Object:: +GetITK( ) +{ + return( dynamic_cast< T* >( this->m_ITKObject.GetPointer( ) ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +const T* cpPlugins::Object:: +GetITK( ) const +{ + return( dynamic_cast< const T* >( this->m_ITKObject.GetPointer( ) ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +T* cpPlugins::Object:: +GetVTK( ) +{ + return( dynamic_cast< T* >( this->m_VTKObject.GetPointer( ) ) ); +} + +// ------------------------------------------------------------------------- +template< class T > +const T* cpPlugins::Object:: +GetVTK( ) const +{ + return( dynamic_cast< const T* >( this->m_VTKObject.GetPointer( ) ) ); +} + +#endif // __CPPLUGINS__OBJECT__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OrthoNormalBase.cxx b/lib/cpPlugins/OrthoNormalBase.cxx new file mode 100644 index 0000000..9a02c0b --- /dev/null +++ b/lib/cpPlugins/OrthoNormalBase.cxx @@ -0,0 +1,73 @@ +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +void cpPlugins::OrthoNormalBase:: +SetITK( itk::LightObject* o ) +{ + // WARNING: Do nothing since itk::Matrix does not belong to the + // itk::LightObject hierarchy. +} + +// ------------------------------------------------------------------------- +void cpPlugins::OrthoNormalBase:: +SetVTK( vtkObjectBase* o ) +{ + auto matrix = dynamic_cast< vtkMatrix4x4* >( o ); + if( matrix != NULL ) + this->Superclass::SetVTK( matrix ); +} + +// ------------------------------------------------------------------------- +cpPlugins::OrthoNormalBase:: +OrthoNormalBase( ) + : Superclass( ) +{ + vtkSmartPointer< vtkTextProperty > t1, t2, t3; + + t1 = vtkSmartPointer< vtkTextProperty >::New( ); + t2 = vtkSmartPointer< vtkTextProperty >::New( ); + t3 = vtkSmartPointer< vtkTextProperty >::New( ); + + t1->ItalicOff( ); + t1->ShadowOff( ); + t1->SetFontFamilyToTimes( ); + t2->ShallowCopy( t1 ); + t3->ShallowCopy( t1 ); + + this->m_BaseActor = vtkSmartPointer< vtkAxesActor >::New( ); + this->m_BaseActor->GetXAxisCaptionActor2D( )->SetCaptionTextProperty( t1 ); + this->m_BaseActor->GetYAxisCaptionActor2D( )->SetCaptionTextProperty( t2 ); + this->m_BaseActor->GetZAxisCaptionActor2D( )->SetCaptionTextProperty( t3 ); + this->m_BaseActor->SetShaftTypeToLine( ); + this->m_BaseActor->SetXAxisLabelText( "x" ); + this->m_BaseActor->SetYAxisLabelText( "y" ); + this->m_BaseActor->SetZAxisLabelText( "z" ); + this->m_BaseActor->SetTotalLength( 1.0, 1.0, 1.0 ); +} + +// ------------------------------------------------------------------------- +cpPlugins::OrthoNormalBase:: +~OrthoNormalBase( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::OrthoNormalBase:: +_CreateVTKActor( ) const +{ + auto matrix = + const_cast< vtkMatrix4x4* >( this->GetVTK< vtkMatrix4x4 >( ) ); + if( matrix != NULL ) + { + this->m_BaseActor->SetUserMatrix( matrix ); + this->m_Actor = this->m_BaseActor.GetPointer( ); + this->m_Actor->Modified( ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OrthoNormalBase.h b/lib/cpPlugins/OrthoNormalBase.h new file mode 100644 index 0000000..11bf87b --- /dev/null +++ b/lib/cpPlugins/OrthoNormalBase.h @@ -0,0 +1,58 @@ +#ifndef __CPPLUGINS__ORTHONORMALBASE__H__ +#define __CPPLUGINS__ORTHONORMALBASE__H__ + +#include + +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT OrthoNormalBase + : public DataObject + { + public: + typedef OrthoNormalBase Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( OrthoNormalBase, DataObject ); + cpPlugins_Id_Macro( OrthoNormalBase, Object ); + + public: + virtual void SetITK( itk::LightObject* o ) ITK_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) ITK_OVERRIDE; + + template< class _TMatrix > + inline void SetITK( const _TMatrix& m ); + + template< class _TMatrix, class _TVector > + inline void SetITK( const _TMatrix& m, const _TVector& v ); + + protected: + OrthoNormalBase( ); + virtual ~OrthoNormalBase( ); + + virtual void _CreateVTKActor( ) const ITK_OVERRIDE; + + private: + // Purposely not implemented + OrthoNormalBase( const Self& ); + Self& operator=( const Self& ); + + protected: + mutable vtkSmartPointer< vtkAxesActor > m_BaseActor; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__ORTHONORMALBASE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/OrthoNormalBase.hxx b/lib/cpPlugins/OrthoNormalBase.hxx new file mode 100644 index 0000000..193ff72 --- /dev/null +++ b/lib/cpPlugins/OrthoNormalBase.hxx @@ -0,0 +1,43 @@ +#ifndef __CPPLUGINS__ORTHONORMALBASE__HXX__ +#define __CPPLUGINS__ORTHONORMALBASE__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< class _TMatrix > +void cpPlugins::OrthoNormalBase:: +SetITK( const _TMatrix& m ) +{ + vtkMatrix4x4* matrix = vtkMatrix4x4::New( ); + matrix->Identity( ); + for( unsigned int i = 0; i < 4; ++i ) + if( i < _TMatrix::RowDimensions ) + for( unsigned int j = 0; j < 4; ++j ) + if( j < _TMatrix::ColumnDimensions ) + matrix->SetElement( i, j, m[ i ][ j ] ); + this->m_VTKObject = matrix; + this->_CreateVTKActor( ); +} + +// ------------------------------------------------------------------------- +template< class _TMatrix, class _TVector > +void cpPlugins::OrthoNormalBase:: +SetITK( const _TMatrix& m, const _TVector& v ) +{ + vtkMatrix4x4* matrix = vtkMatrix4x4::New( ); + matrix->Identity( ); + for( unsigned int i = 0; i < 3; ++i ) + if( i < _TMatrix::RowDimensions ) + for( unsigned int j = 0; j < 3; ++j ) + if( j < _TMatrix::ColumnDimensions ) + matrix->SetElement( i, j, m[ i ][ j ] ); + for( unsigned int i = 0; i < 3; ++i ) + if( i < _TVector::Dimension ) + matrix->SetElement( i, 3, v[ i ] ); + this->m_VTKObject = matrix; + this->_CreateVTKActor( ); +} + +#endif // __CPPLUGINS__ORTHONORMALBASE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Parameters.cxx b/lib/cpPlugins/Parameters.cxx new file mode 100644 index 0000000..1ffb65d --- /dev/null +++ b/lib/cpPlugins/Parameters.cxx @@ -0,0 +1,581 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Parameters:: +Parameters( ) +{ + this->Clear( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Parameters:: +~Parameters( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Parameters:: +Modified( ) const +{ + this->m_TimeStamp.Modified( ); +} + +// ------------------------------------------------------------------------- +itk::ModifiedTimeType cpPlugins::Parameters:: +GetMTime( ) const +{ + return( this->m_TimeStamp.GetMTime( ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Parameters:: +Clear( ) +{ + this->m_Parameters.clear( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::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::Parameters:: +Type cpPlugins::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_Parameters_TypeAsString( Y ) \ + if( i->second.first == Self::Y ) \ + return( #Y ) + +std::string cpPlugins::Parameters:: +GetTypeAsString( const std::string& name ) const +{ + auto i = this->m_Parameters.find( name ); + cpPlugins_Parameters_TypeAsString( String ); + else cpPlugins_Parameters_TypeAsString( Bool ); + else cpPlugins_Parameters_TypeAsString( Int ); + else cpPlugins_Parameters_TypeAsString( Uint ); + else cpPlugins_Parameters_TypeAsString( Real ); + else cpPlugins_Parameters_TypeAsString( OpenFileName ); + else cpPlugins_Parameters_TypeAsString( SaveFileName ); + else cpPlugins_Parameters_TypeAsString( PathName ); + else cpPlugins_Parameters_TypeAsString( StringList ); + else cpPlugins_Parameters_TypeAsString( BoolList ); + else cpPlugins_Parameters_TypeAsString( IntList ); + else cpPlugins_Parameters_TypeAsString( UintList ); + else cpPlugins_Parameters_TypeAsString( RealList ); + else cpPlugins_Parameters_TypeAsString( OpenFileNameList ); + else cpPlugins_Parameters_TypeAsString( SaveFileNameList ); + else cpPlugins_Parameters_TypeAsString( PathNameList ); + else cpPlugins_Parameters_TypeAsString( Choices ); + else return( "NoType" ); +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_TypeFromString( Y, str ) \ + if( str == std::string( #Y ) ) \ + return( Self::Y ) + +cpPlugins::Parameters:: +Type cpPlugins::Parameters:: +GetTypeFromString( const std::string& t ) +{ + cpPlugins_Parameters_TypeFromString( String, t ); + else cpPlugins_Parameters_TypeFromString( Bool, t ); + else cpPlugins_Parameters_TypeFromString( Int, t ); + else cpPlugins_Parameters_TypeFromString( Uint, t ); + else cpPlugins_Parameters_TypeFromString( Real, t ); + else cpPlugins_Parameters_TypeFromString( OpenFileName, t ); + else cpPlugins_Parameters_TypeFromString( SaveFileName, t ); + else cpPlugins_Parameters_TypeFromString( PathName, t ); + else cpPlugins_Parameters_TypeFromString( StringList, t ); + else cpPlugins_Parameters_TypeFromString( BoolList, t ); + else cpPlugins_Parameters_TypeFromString( IntList, t ); + else cpPlugins_Parameters_TypeFromString( UintList, t ); + else cpPlugins_Parameters_TypeFromString( RealList, t ); + else cpPlugins_Parameters_TypeFromString( OpenFileNameList, t ); + else cpPlugins_Parameters_TypeFromString( SaveFileNameList, t ); + else cpPlugins_Parameters_TypeFromString( PathNameList, t ); + else cpPlugins_Parameters_TypeFromString( Choices, t ); + else return( Self::NoType ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::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::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::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( ); +} + +// ------------------------------------------------------------------------- +std::vector< std::string > cpPlugins::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::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::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::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::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::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::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::Parameters:: +TParameters& cpPlugins::Parameters:: +GetRawParameters( ) +{ + return( this->m_Parameters ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Parameters:: +TParameters& cpPlugins::Parameters:: +GetRawParameters( ) const +{ + return( this->m_Parameters ); +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_Configure_Code( Y ) \ + void cpPlugins::Parameters::ConfigureAs##Y( const std::string& name ) \ + { this->_Configure< Y >( name ); } \ + bool cpPlugins::Parameters::Has##Y( const std::string& name ) const \ + { return( this->_Has< Y >( name ) ); } + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_GetSet_Code( Y ) \ + cpPlugins::Parameters::T##Y \ + cpPlugins::Parameters::Get##Y( const std::string& name ) const \ + { return( this->_Get< T##Y, Y >( name ) ); } \ + void cpPlugins::Parameters::Set##Y( \ + const std::string& name, const T##Y& v \ + ) \ + { this->_Set< T##Y, Y >( name, v ); } + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_GetSetList_Code( Y ) \ + std::vector< cpPlugins::Parameters::T##Y > \ + cpPlugins::Parameters::Get##Y##List( const std::string& name ) const \ + { return( this->_GetList< T##Y, Y##List >( name ) ); } \ + void cpPlugins::Parameters::AddTo##Y##List( \ + const std::string& name, const cpPlugins::Parameters::T##Y& v \ + ) \ + { this->_AddToList< T##Y, Y##List >( name, v ); } \ + void cpPlugins::Parameters::Clear##Y##List( const std::string& name ) \ + { this->_ClearList< Y##List >( name ); } + +// ------------------------------------------------------------------------- +cpPlugins_Parameters_Configure_Code( String ); +cpPlugins_Parameters_Configure_Code( Bool ); +cpPlugins_Parameters_Configure_Code( Int ); +cpPlugins_Parameters_Configure_Code( Uint ); +cpPlugins_Parameters_Configure_Code( Real ); +cpPlugins_Parameters_Configure_Code( OpenFileName ); +cpPlugins_Parameters_Configure_Code( SaveFileName ); +cpPlugins_Parameters_Configure_Code( PathName ); +cpPlugins_Parameters_Configure_Code( StringList ); +cpPlugins_Parameters_Configure_Code( BoolList ); +cpPlugins_Parameters_Configure_Code( IntList ); +cpPlugins_Parameters_Configure_Code( UintList ); +cpPlugins_Parameters_Configure_Code( RealList ); +cpPlugins_Parameters_Configure_Code( OpenFileNameList ); +cpPlugins_Parameters_Configure_Code( SaveFileNameList ); +cpPlugins_Parameters_Configure_Code( PathNameList ); +cpPlugins_Parameters_Configure_Code( Choices ); +cpPlugins_Parameters_GetSet_Code( Bool ); +cpPlugins_Parameters_GetSet_Code( Int ); +cpPlugins_Parameters_GetSet_Code( Uint ); +cpPlugins_Parameters_GetSet_Code( Real ); +cpPlugins_Parameters_GetSet_Code( OpenFileName ); +cpPlugins_Parameters_GetSet_Code( SaveFileName ); +cpPlugins_Parameters_GetSet_Code( PathName ); +cpPlugins_Parameters_GetSetList_Code( String ); +cpPlugins_Parameters_GetSetList_Code( Bool ); +cpPlugins_Parameters_GetSetList_Code( Int ); +cpPlugins_Parameters_GetSetList_Code( Uint ); +cpPlugins_Parameters_GetSetList_Code( Real ); +cpPlugins_Parameters_GetSetList_Code( OpenFileName ); +cpPlugins_Parameters_GetSetList_Code( SaveFileName ); +cpPlugins_Parameters_GetSetList_Code( PathName ); + +// ------------------------------------------------------------------------- +template< unsigned int _Enum > +void cpPlugins::Parameters:: +_Configure( const std::string& name ) +{ + this->m_Parameters[ name ] = TParameter( ( Self::Type )( _Enum ), "" ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int _Enum > +bool cpPlugins::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::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::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::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::TokenizeString( tokens, 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::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::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/Parameters.h b/lib/cpPlugins/Parameters.h new file mode 100644 index 0000000..95c90b3 --- /dev/null +++ b/lib/cpPlugins/Parameters.h @@ -0,0 +1,208 @@ +#ifndef __CPPLUGINS__PARAMETERS__H__ +#define __CPPLUGINS__PARAMETERS__H__ + +#include + +#include +#include +#include +#include +#include +#include +#include + +// Some forward declarations +namespace tinyxml2 +{ + class XMLElement; + class XMLDocument; +} + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_Configure( Y ) \ + void ConfigureAs##Y( const std::string& name ); \ + bool Has##Y( const std::string& name ) const + +// ------------------------------------------------------------------------- +#define cpPlugins_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_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 +{ + // Forward declaration to improve Qt dialog execution + class ParametersQDialog; + + /** + */ + class cpPlugins_EXPORT Parameters + { + // Frienship with forward declaration to improve Qt dialog execution + friend class ParametersQDialog; + 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_Parameters_Configure( String ); + cpPlugins_Parameters_Configure( Bool ); + cpPlugins_Parameters_Configure( Int ); + cpPlugins_Parameters_Configure( Uint ); + cpPlugins_Parameters_Configure( Real ); + cpPlugins_Parameters_Configure( OpenFileName ); + cpPlugins_Parameters_Configure( SaveFileName ); + cpPlugins_Parameters_Configure( PathName ); + cpPlugins_Parameters_Configure( StringList ); + cpPlugins_Parameters_Configure( BoolList ); + cpPlugins_Parameters_Configure( IntList ); + cpPlugins_Parameters_Configure( UintList ); + cpPlugins_Parameters_Configure( RealList ); + cpPlugins_Parameters_Configure( OpenFileNameList ); + cpPlugins_Parameters_Configure( SaveFileNameList ); + cpPlugins_Parameters_Configure( PathNameList ); + cpPlugins_Parameters_Configure( Choices ); + + cpPlugins_Parameters_GetSet( Bool ); + cpPlugins_Parameters_GetSet( Int ); + cpPlugins_Parameters_GetSet( Uint ); + cpPlugins_Parameters_GetSet( Real ); + cpPlugins_Parameters_GetSet( OpenFileName ); + cpPlugins_Parameters_GetSet( SaveFileName ); + cpPlugins_Parameters_GetSet( PathName ); + + cpPlugins_Parameters_GetSetList( String ); + cpPlugins_Parameters_GetSetList( Bool ); + cpPlugins_Parameters_GetSetList( Int ); + cpPlugins_Parameters_GetSetList( Uint ); + cpPlugins_Parameters_GetSetList( Real ); + cpPlugins_Parameters_GetSetList( OpenFileName ); + cpPlugins_Parameters_GetSetList( SaveFileName ); + cpPlugins_Parameters_GetSetList( PathName ); + + public: + Parameters( ); + virtual ~Parameters( ); + + virtual void Modified( ) const; + virtual itk::ModifiedTimeType GetMTime( ) 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 + ); + 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: + mutable itk::TimeStamp m_TimeStamp; + TParameters m_Parameters; + std::map< std::string, std::string > m_AcceptedFileExtensions; + }; + +} // ecapseman + +#endif // __CPPLUGINS__PARAMETERS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ParametersQDialog.cxx b/lib/cpPlugins/ParametersQDialog.cxx new file mode 100644 index 0000000..9273154 --- /dev/null +++ b/lib/cpPlugins/ParametersQDialog.cxx @@ -0,0 +1,906 @@ +#include + +#ifdef cpPlugins_QT4 + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::ParametersQDialog:: +ParametersQDialog( 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::ParametersQDialog:: +~ParametersQDialog( ) +{ + if( !this->m_Manual ) + { + delete this->m_Title; + delete this->m_ToolsLayout; + delete this->m_MainLayout; + + } // fi +} + +// ------------------------------------------------------------------------- +cpPlugins:: +ProcessObject* cpPlugins::ParametersQDialog:: +getProcessObject( ) const +{ + return( this->m_ProcessObject ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::ParametersQDialog:: +setProcessObject( 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::ParametersQDialog:: +updateParameters( ) +{ + if( this->m_ProcessObject == NULL ) + return; + if( this->m_Manual ) + return; + + // Check if an explicit re-execution button is needed + if( this->m_ProcessObject->GetCouldHaveExplicitReExecution( ) ) + { + QCheckBox* v_bool = + this->findChild< QCheckBox* >( "___ExplicitReExecution___" ); + if( v_bool != NULL ) + this->m_ProcessObject->SetExplicitReExecution( v_bool->isChecked( ) ); + + } // fi + + // 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 Parameters::String: + case Parameters::OpenFileName: + case Parameters::SaveFileName: + case Parameters::PathName: + case Parameters::IntList: + case Parameters::UintList: + case Parameters::RealList: + case Parameters::OpenFileNameList: + { + QLineEdit* v_string = this->findChild< QLineEdit* >( pName ); + if( v_string != NULL ) + pIt->second.second = v_string->text( ).toStdString( ); + } + break; + case Parameters::Bool: + { + QCheckBox* v_bool = this->findChild< QCheckBox* >( pName ); + if( v_bool != NULL ) + pIt->second.second = ( v_bool->isChecked( ) )? "1": "0"; + } + break; + case Parameters::Int: + case 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 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 Parameters::StringList: + break; + case Parameters::BoolList: + break; + case Parameters::SaveFileNameList: + break; + case Parameters::PathNameList: + break; + case 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::ParametersQDialog:: +updateView( ) +{ + if( this->m_ProcessObject == NULL ) + return; + if( this->m_Manual ) + return; + + // Check if an explicit re-execution button is needed + if( this->m_ProcessObject->GetCouldHaveExplicitReExecution( ) ) + { + QCheckBox* v_bool = + this->findChild< QCheckBox* >( "___ExplicitReExecution___" ); + if( v_bool != NULL ) + v_bool->setChecked( this->m_ProcessObject->GetExplicitReExecution( ) ); + + } // fi + + // 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 Parameters::String: + case Parameters::OpenFileName: + case Parameters::SaveFileName: + case Parameters::PathName: + case Parameters::IntList: + case Parameters::UintList: + case Parameters::RealList: + case Parameters::OpenFileNameList: + { + QLineEdit* v_string = this->findChild< QLineEdit* >( pName ); + if( v_string != NULL ) + v_string->setText( pIt->second.second.c_str( ) ); + } + break; + case Parameters::Bool: + { + QCheckBox* v_bool = this->findChild< QCheckBox* >( pName ); + if( v_bool != NULL ) + v_bool->setChecked( pIt->second.second == "1" ); + } + break; + case Parameters::Int: + case 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 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 Parameters::StringList: + break; + case Parameters::BoolList: + break; + case Parameters::SaveFileNameList: + break; + case Parameters::PathNameList: + break; + case 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::ParametersQDialog:: +_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::ParametersQDialog:: +_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 + if( this->m_ProcessObject->GetCouldHaveExplicitReExecution( ) ) + { + QCheckBox* v_bool = new QCheckBox( this ); + v_bool->setObjectName( "___ExplicitReExecution___" ); + v_bool->setText( "Explicit re-execution" ); + v_bool->setChecked( this->m_ProcessObject->GetExplicitReExecution( ) ); + + QHBoxLayout* new_layout = new QHBoxLayout( ); + new_layout->addWidget( v_bool ); + this->m_ToolsLayout->addLayout( new_layout ); + + } // fi + + // 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 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 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 Parameters::Int: + case 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 == 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 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 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 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 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 Parameters::StringList: + break; + case Parameters::BoolList: + break; + case 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 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 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 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 Parameters::SaveFileNameList: + break; + case Parameters::PathNameList: + break; + case 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::ParametersQDialog:: +_dlg_Accepted( ) +{ + this->updateParameters( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ParametersQDialog:: +_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::ParametersQDialog:: +_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::ParametersQDialog:: +_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::ParametersQDialog:: +_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::ParametersQDialog:: +_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::ParametersQDialog:: +_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::ParametersQDialog:: +_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 +} + +#endif // cpPlugins_QT4 + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ParametersQDialog.h b/lib/cpPlugins/ParametersQDialog.h new file mode 100644 index 0000000..eda6f9d --- /dev/null +++ b/lib/cpPlugins/ParametersQDialog.h @@ -0,0 +1,70 @@ +#ifndef __CPPLUGINS__PARAMETERSQDIALOG__H__ +#define __CPPLUGINS__PARAMETERSQDIALOG__H__ + +#include + +#ifdef cpPlugins_QT4 + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT ParametersQDialog + : public QDialog + { + Q_OBJECT; + + public: + ParametersQDialog( + QWidget* parent = 0, Qt::WindowFlags f = 0, bool manual = false + ); + virtual ~ParametersQDialog( ); + + ProcessObject* getProcessObject( ) const; + virtual bool setProcessObject( 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: + ProcessObject* m_ProcessObject; + bool m_WidgetsUpdated; + bool m_Manual; + QLabel* m_Title; + QGridLayout* m_MainLayout; + QVBoxLayout* m_ToolsLayout; + QDialogButtonBox* m_Buttons; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __CPPLUGINS__PARAMETERSQDIALOG__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Path.cxx b/lib/cpPlugins/Path.cxx new file mode 100644 index 0000000..5f58269 --- /dev/null +++ b/lib/cpPlugins/Path.cxx @@ -0,0 +1,39 @@ +#include + +// ------------------------------------------------------------------------- +void cpPlugins::Path:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + bool s = this->_ITK_2_VTK< 2 >( o ); + if( !s ) s = this->_ITK_2_VTK< 3 >( o ); + if( !s ) + { + this->m_VTKObject = NULL; + this->m_ITKvVTK = NULL; + + } // fi + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Path:: +SetVTK( vtkObjectBase* o ) +{ + // Do nothing +} + +// ------------------------------------------------------------------------- +cpPlugins::Path:: +Path( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Path:: +~Path( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Path.h b/lib/cpPlugins/Path.h new file mode 100644 index 0000000..d7aa111 --- /dev/null +++ b/lib/cpPlugins/Path.h @@ -0,0 +1,53 @@ +#ifndef __CPPLUGINS__PATH__H__ +#define __CPPLUGINS__PATH__H__ + +#include + +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT Path + : public DataObject + { + public: + typedef Path Self; + typedef DataObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( Path, DataObject ); + cpPlugins_Id_Macro( Path, Object ); + + public: + virtual void SetITK( itk::LightObject* o ) ITK_OVERRIDE; + virtual void SetVTK( vtkObjectBase* o ) ITK_OVERRIDE; + + protected: + Path( ); + virtual ~Path( ); + + template< unsigned int _NDim > + inline bool _ITK_2_VTK( itk::LightObject* o ); + + private: + // Purposely not implemented + Path( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkPolyDataAlgorithm > m_ITKvVTK; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__PATH__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Path.hxx b/lib/cpPlugins/Path.hxx new file mode 100644 index 0000000..04047d1 --- /dev/null +++ b/lib/cpPlugins/Path.hxx @@ -0,0 +1,44 @@ +#ifndef __CPPLUGINS__PATH__HXX__ +#define __CPPLUGINS__PATH__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< unsigned int _NDim > +bool cpPlugins::Path:: +_ITK_2_VTK( itk::LightObject* o ) +{ + typedef + cpExtensions::DataStructures::PolyLineParametricPath< _NDim > + _TPath; + typedef + cpExtensions::Visualization::PolyLineParametricPathToPolyData< _TPath > + _TFilter; + + auto path = dynamic_cast< _TPath* >( o ); + if( path != NULL ) + { + _TFilter* f = dynamic_cast< _TFilter* >( this->m_ITKvVTK.GetPointer( ) ); + if( f == NULL ) + { + vtkSmartPointer< _TFilter > nf = _TFilter::New( ); + this->m_ITKvVTK = nf.GetPointer( ); + f = nf.GetPointer( ); + + } // fi + f->SetInput( path ); + f->SetReferenceImage( path->GetReferenceImage( ) ); + f->Update( ); + + // Keep object track + this->m_ITKObject = o; + this->m_VTKObject = f->GetOutput( ); + return( true ); + } + else + return( false ); +} + +#endif // __CPPLUGINS__PATH__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Port.cxx b/lib/cpPlugins/Port.cxx new file mode 100644 index 0000000..316cbc8 --- /dev/null +++ b/lib/cpPlugins/Port.cxx @@ -0,0 +1,135 @@ +#include + +// ------------------------------------------------------------------------- +cpPlugins::Port:: +Port( ) +{ + this->m_Data = NULL; +} + +// ------------------------------------------------------------------------- +cpPlugins::Port:: +~Port( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Port:: +Self& cpPlugins::Port:: +operator=( DataObject* obj ) +{ + this->m_Data = obj; + return( *this ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Port:: +Self& cpPlugins::Port:: +operator=( const Self& other ) +{ + this->m_Data = other.m_Data; + return( *this ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Port:: +IsValid( ) const +{ + return( this->m_Data.IsNotNull( ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins::InputPort:: +InputPort( bool required ) + : Superclass( ), + m_Required( required ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::InputPort:: +~InputPort( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::InputPort:: +Self& cpPlugins::InputPort:: +operator=( DataObject* obj ) +{ + this->Superclass::operator=( obj ); + return( *this ); +} + +// ------------------------------------------------------------------------- +cpPlugins::InputPort:: +Self& cpPlugins::InputPort:: +operator=( const Superclass& other ) +{ + this->Superclass::operator=( other ); + auto i = dynamic_cast< const InputPort* >( &other ); + if( i != NULL ) + this->m_Required = i->m_Required; + return( *this ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::InputPort:: +IsRequired( ) const +{ + return( this->m_Required ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::InputPort:: +RequiredOn( ) +{ + this->SetRequired( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::InputPort:: +RequiredOff( ) +{ + this->SetRequired( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::InputPort:: +SetRequired( bool required ) +{ + this->m_Required = required; +} + +// ------------------------------------------------------------------------- +cpPlugins::OutputPort:: +OutputPort( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::OutputPort:: +~OutputPort( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::OutputPort:: +Self& cpPlugins::OutputPort:: +operator=( DataObject* obj ) +{ + this->Superclass::operator=( obj ); + return( *this ); +} + +// ------------------------------------------------------------------------- +cpPlugins::OutputPort:: +Self& cpPlugins::OutputPort:: +operator=( const Superclass& other ) +{ + this->Superclass::operator=( other ); + return( *this ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Port.h b/lib/cpPlugins/Port.h new file mode 100644 index 0000000..c7f8170 --- /dev/null +++ b/lib/cpPlugins/Port.h @@ -0,0 +1,82 @@ +#ifndef __CPPLUGINS__PORT__H__ +#define __CPPLUGINS__PORT__H__ + +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT Port + { + public: + typedef Port Self; + + public: + Port( ); + virtual ~Port( ); + Self& operator=( DataObject* obj ); + Self& operator=( const Self& other ); + + bool IsValid( ) const; + + // This could be seen as a pointer to DataObject's + inline DataObject* GetPointer( ) + { return( this->m_Data.GetPointer( ) ); } + inline const DataObject* GetPointer( ) const + { return( this->m_Data.GetPointer( ) ); } + inline DataObject* operator->( ) const + { return( this->m_Data.GetPointer( ) ); } + + inline void SetPointer( DataObject* ptr ) + { this->m_Data = ptr; } + + protected: + cpPlugins::DataObject::Pointer m_Data; + }; + + /** + */ + class cpPlugins_EXPORT InputPort + : public Port + { + public: + typedef InputPort Self; + typedef Port Superclass; + + public: + InputPort( bool required = false ); + virtual ~InputPort( ); + Self& operator=( DataObject* obj ); + Self& operator=( const Superclass& other ); + + bool IsRequired( ) const; + void RequiredOn( ); + void RequiredOff( ); + void SetRequired( bool required ); + + protected: + bool m_Required; + }; + + /** + */ + class cpPlugins_EXPORT OutputPort + : public Port + { + public: + typedef OutputPort Self; + typedef Port Superclass; + + public: + OutputPort( ); + virtual ~OutputPort( ); + Self& operator=( DataObject* obj ); + Self& operator=( const Superclass& other ); + }; + +} // ecapseman + +#endif // __CPPLUGINS__PORT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ProcessObject.cxx b/lib/cpPlugins/ProcessObject.cxx new file mode 100644 index 0000000..92df445 --- /dev/null +++ b/lib/cpPlugins/ProcessObject.cxx @@ -0,0 +1,305 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Parameters* cpPlugins::ProcessObject:: +GetParameters( ) +{ + return( &( this->m_Parameters ) ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Parameters* cpPlugins::ProcessObject:: +GetParameters( ) const +{ + return( &( this->m_Parameters ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +SetITK( itk::LightObject* o ) +{ + // Polymorphism: do nothing -> this is a filter!!! +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +SetVTK( vtkObjectBase* o ) +{ + // Polymorphism: do nothing -> this is a filter!!! +} + +// ------------------------------------------------------------------------- +std::set< std::string > cpPlugins::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::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 ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::ProcessObject:: +GetNumberOfInputs( ) const +{ + return( this->m_Inputs.size( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpPlugins::ProcessObject:: +GetNumberOfOutputs( ) const +{ + return( this->m_Outputs.size( ) ); +} + +// ------------------------------------------------------------------------- +cpPlugins:: +OutputPort& cpPlugins::ProcessObject:: +GetOutputPort( const std::string& id ) +{ + static OutputPort null_port; + auto i = this->m_Outputs.find( id ); + if( i == this->m_Outputs.end( ) ) + { + null_port = NULL; + return( null_port ); + } + else + return( i->second ); +} + +// ------------------------------------------------------------------------- +const cpPlugins:: +OutputPort& cpPlugins::ProcessObject:: +GetOutputPort( const std::string& id ) const +{ + static const OutputPort null_port; + auto i = this->m_Outputs.find( id ); + if( i == this->m_Outputs.end( ) ) + return( null_port ); + else + return( i->second ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::ProcessObject:: +SetInputPort( const std::string& id, const OutputPort& port ) +{ + auto i = this->m_Inputs.find( id ); + if( i != this->m_Inputs.end( ) ) + { + if( i->second.GetPointer( ) != port.GetPointer( ) ) + { + i->second = port; + this->Modified( ); + + } // fi + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +DisconnectInputs( ) +{ + auto i = this->m_Inputs.begin( ); + for( ; i != this->m_Inputs.end( ); ++i ) + i->second = NULL; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +DisconnectOutputs( ) +{ + auto i = this->m_Outputs.begin( ); + for( ; i != this->m_Outputs.end( ); ++i ) + if( i->second.IsValid( ) ) + i->second->DisconnectFromPipeline( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +Disconnect( ) +{ + this->DisconnectInputs( ); + this->DisconnectOutputs( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +Modified( ) const +{ + this->Superclass::Modified( ); + this->m_LastExecutionSpan = -1; +} + +// ------------------------------------------------------------------------- +itk::ModifiedTimeType cpPlugins::ProcessObject:: +GetMTime( ) const +{ + auto params_time = this->m_Parameters.GetMTime( ); + auto filter_time = this->Superclass::GetMTime( ); + return( ( params_time > filter_time )? params_time: filter_time ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +Update( ) +{ + // Force upstream updates + auto i = this->m_Inputs.begin( ); + bool need_to_update = this->m_CouldHaveExplicitReExecution; + need_to_update &= this->m_ExplicitReExecution; + for( ; i != this->m_Inputs.end( ); ++i ) + { + bool iv = i->second.IsValid( ); + bool ir = i->second.IsRequired( ); + if( !iv && ir ) + this->_Error( + std::string( "Required input \"" ) + i->first + + std::string( "\" is not valid." ) + ); + if( iv ) + { + Self* src = dynamic_cast< Self* >( i->second->GetSource( ) ); + if( src != NULL ) + { + need_to_update |= ( this->m_LastExecutionTime < src->GetMTime( ) ); + src->Update( ); + + } // fi + + } // fi + + } // rof + + // Current update + if( this->m_LastExecutionTime < this->GetMTime( ) || need_to_update ) + { + if( this->m_PrintExecution && this->m_PrintExecutionStream != NULL ) + { + *( this->m_PrintExecutionStream ) + << "cpPlugins: Updating \"" + << this->GetName( ) << " (" + << this->GetClassCategory( ) << ":" << this->GetClassName( ) + << ")\"... "; + this->m_PrintExecutionStream->flush( ); + + } // fi + + auto t_start = cpPlugins_CHRONO; + this->_GenerateData( ); + auto t_end = cpPlugins_CHRONO; + this->m_LastExecutionSpan = long( t_end - t_start ); + this->m_LastExecutionTime = this->GetMTime( ); + + if( this->m_PrintExecution && this->m_PrintExecutionStream != NULL ) + { + *( this->m_PrintExecutionStream ) + << "done in " + << double( this->m_LastExecutionSpan ) / double( 1000 ) + << " s." << std::endl; + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +QDialog* cpPlugins::ProcessObject:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + ParametersQDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new ParametersQDialog( ); + dlg->setProcessObject( this ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +bool cpPlugins::ProcessObject:: +IsInteractive( ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: + SetInteractionObjects( const std::vector< void* >& objs ) +{ + // Do nothing +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject:: +ProcessObject( ) + : Superclass( ), + m_Name( "" ), + m_PluginName( "" ), + m_CouldHaveExplicitReExecution( false ), + m_ExplicitReExecution( false ), + m_LastExecutionTime( 0 ), + m_LastExecutionSpan( -1 ), + m_PrintExecution( false ), + m_PrintExecutionStream( &( std::cout ) ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject:: +~ProcessObject( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +_AddInput( const std::string& name, bool required ) +{ + auto i = this->m_Inputs.find( name ); + if( i == this->m_Inputs.end( ) ) + { + this->m_Inputs[ name ] = InputPort( required ); + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::ProcessObject:: +_Error( const std::string& error ) +{ + if( error != "" ) + { + itkExceptionMacro( + "Error: \"" << this->GetClassCategory( ) << "::" << + this->GetClassName( ) << "\": " << error + ); + + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ProcessObject.h b/lib/cpPlugins/ProcessObject.h new file mode 100644 index 0000000..d161e77 --- /dev/null +++ b/lib/cpPlugins/ProcessObject.h @@ -0,0 +1,142 @@ +#ifndef __CPPLUGINS__PROCESSOBJECT__H__ +#define __CPPLUGINS__PROCESSOBJECT__H__ + +#include +#include +#include +#include +#include + +class QDialog; + +namespace cpPlugins +{ + /** + */ + 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( ExplicitReExecution ); + itkBooleanMacro( PrintExecution ); + + itkGetStringMacro( Name ); + itkGetStringMacro( PluginName ); + itkGetConstMacro( ExplicitReExecution, bool ); + itkGetConstMacro( CouldHaveExplicitReExecution, bool ); + itkGetConstMacro( LastExecutionSpan, long ); + itkGetConstMacro( PrintExecution, bool ); + + itkSetStringMacro( Name ); + itkSetStringMacro( PluginName ); + itkSetMacro( ExplicitReExecution, bool ); + itkSetMacro( PrintExecution, bool ); + itkSetObjectMacro( PrintExecutionStream, std::ofstream ); + + public: + Parameters* GetParameters( ); + const Parameters* GetParameters( ) const; + + virtual void SetITK( itk::LightObject* o ) final; + virtual void SetVTK( vtkObjectBase* o ) final; + + // IO management + std::set< std::string > GetInputsNames( ) const; + std::set< std::string > GetOutputsNames( ) const; + unsigned int GetNumberOfInputs( ) const; + unsigned int GetNumberOfOutputs( ) const; + + OutputPort& GetOutputPort( const std::string& id ); + const OutputPort& GetOutputPort( const std::string& id ) const; + + template< class _TType = DataObject > + inline _TType* GetInput( const std::string& id ); + + template< class _TType = DataObject > + inline const _TType* GetInput( const std::string& id ) const; + + template< class _TType = DataObject > + inline _TType* GetOutput( const std::string& id ); + + template< class _TType = DataObject > + inline const _TType* GetOutput( const std::string& id ) const; + + template< class _TType = itk::LightObject > + inline _TType* GetInputData( const std::string& name ); + + template< class _TType = itk::LightObject > + inline _TType* GetOutputData( const std::string& name ); + + bool SetInputPort( const std::string& id, const OutputPort& port ); + + void DisconnectInputs( ); + void DisconnectOutputs( ); + void Disconnect( ); + + // Pipeline execution + virtual void Modified( ) const ITK_OVERRIDE; + virtual itk::ModifiedTimeType GetMTime( ) const ITK_OVERRIDE; + virtual void Update( ); + + // Qt dialog creation + virtual QDialog* CreateQDialog( ); + virtual bool IsInteractive( ); + virtual void SetInteractionObjects( const std::vector< void* >& objs ); + + protected: + ProcessObject( ); + virtual ~ProcessObject( ); + + void _AddInput( const std::string& name, bool required = true ); + void _Error( const std::string& error ); + + template< class O > + inline void _AddOutput( const std::string& name ); + + template< class F > + inline F* _CreateITK( ); + template< class F > + inline F* _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_CouldHaveExplicitReExecution; + bool m_ExplicitReExecution; + + typedef std::map< std::string, InputPort > _TInputs; + typedef std::map< std::string, OutputPort > _TOutputs; + _TInputs m_Inputs; + _TOutputs m_Outputs; + + itk::ModifiedTimeType m_LastExecutionTime; + mutable long m_LastExecutionSpan; + + bool m_PrintExecution; + std::ostream* m_PrintExecutionStream; + }; + +} // ecapseman + +#include + +#endif // __CPPLUGINS__PROCESSOBJECT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ProcessObject.hxx b/lib/cpPlugins/ProcessObject.hxx new file mode 100644 index 0000000..9be2675 --- /dev/null +++ b/lib/cpPlugins/ProcessObject.hxx @@ -0,0 +1,142 @@ +#ifndef __CPPLUGINS__PROCESSOBJECT__HXX__ +#define __CPPLUGINS__PROCESSOBJECT__HXX__ + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::ProcessObject:: +GetInput( const std::string& id ) +{ + auto i = this->m_Inputs.find( id ); + if( i != this->m_Inputs.end( ) ) + return( dynamic_cast< _TType* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +const _TType* cpPlugins::ProcessObject:: +GetInput( const std::string& id ) const +{ + auto i = this->m_Inputs.find( id ); + if( i != this->m_Inputs.end( ) ) + return( dynamic_cast< const _TType* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::ProcessObject:: +GetOutput( const std::string& id ) +{ + auto i = this->m_Outputs.find( id ); + if( i != this->m_Outputs.end( ) ) + return( dynamic_cast< _TType* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +const _TType* cpPlugins::ProcessObject:: +GetOutput( const std::string& id ) const +{ + auto i = this->m_Outputs.find( id ); + if( i != this->m_Outputs.end( ) ) + return( dynamic_cast< const _TType* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::ProcessObject:: +GetInputData( const std::string& name ) +{ + auto in = this->GetInput( name ); + if( in != NULL ) + { + auto i = in->GetITK< _TType >( ); + auto v = in->GetVTK< _TType >( ); + if ( i != NULL ) return( i ); + else if( v != NULL ) return( v ); + else return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class _TType > +_TType* cpPlugins::ProcessObject:: +GetOutputData( const std::string& name ) +{ + auto out = this->GetOutput( name ); + if( out != NULL ) + { + auto i = out->GetITK< _TType >( ); + auto v = out->GetVTK< _TType >( ); + if ( i != NULL ) return( i ); + else if( v != NULL ) return( v ); + else return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< class O > +void cpPlugins::ProcessObject:: +_AddOutput( const std::string& name ) +{ + auto i = this->m_Outputs.find( name ); + if( i == this->m_Outputs.end( ) ) + { + typename O::Pointer o = O::New( ); + o->SetSource( this ); + this->m_Outputs[ name ] = o; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class F > +F* cpPlugins::ProcessObject:: +_CreateITK( ) +{ + F* filter = this->GetITK< F >( ); + if( filter == NULL ) + { + typename F::Pointer filter_ptr = F::New( ); + this->m_ITKObject = filter_ptr; + this->m_VTKObject = NULL; + filter = filter_ptr.GetPointer( ); + this->Modified( ); + + } // fi + return( filter ); +} + +// ------------------------------------------------------------------------- +template< class F > +F* cpPlugins::ProcessObject:: +_CreateVTK( ) +{ + F* filter = this->GetVTK< F >( ); + if( filter == NULL ) + { + vtkSmartPointer< F > filter_ptr = vtkSmartPointer< F >::New( ); + this->m_ITKObject = NULL; + this->m_VTKObject = filter_ptr; + filter = filter_ptr.GetPointer( ); + this->Modified( ); + + } // fi + return( filter ); +} + +#endif // __CPPLUGINS__PROCESSOBJECT__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Utilities.h b/lib/cpPlugins/Utilities.h new file mode 100644 index 0000000..b919c20 --- /dev/null +++ b/lib/cpPlugins/Utilities.h @@ -0,0 +1,135 @@ +#ifndef __CPPLUGINS__UTILITY__H__ +#define __CPPLUGINS__UTILITY__H__ + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +#ifdef cpPlugins_SYS_WINDOWS +# define cpPlugins_STRTOK( A, B, N ) strtok_s( A, B, N ) +#else // cpPlugins_SYS_WINDOWS +# define cpPlugins_STRTOK( A, B, N ) std::strtok( A, B ) +#endif // cpPlugins_SYS_WINDOWS + +// ------------------------------------------------------------------------- +#define cpPlugins_CHRONO \ + std::chrono::duration_cast< std::chrono::milliseconds >( \ + std::chrono::system_clock::now( ).time_since_epoch( ) \ + ).count( ) + +// ------------------------------------------------------------------------- +#define cpPlugins_Id_Macro( N, C ) \ + public: \ + virtual const char* GetClassName( ) const ITK_OVERRIDE \ + { return( #N ); } \ + virtual const char* GetClassCategory( ) const ITK_OVERRIDE \ + { return( #C ); } + + +// ------------------------------------------------------------------------- +namespace cpPlugins +{ + // ----------------------------------------------------------------------- + inline bool IsPathSeparator( char c ) + { +#ifdef cpPlugins_SYS_WINDOWS + return( c == '\\' || c == cpPlugins_PATH_SEPARATOR ); +#else // cpPlugins_SYS_WINDOWS + return( c == cpPlugins_PATH_SEPARATOR ); +#endif // cpPlugins_SYS_WINDOWS + } + + // ----------------------------------------------------------------------- + inline bool IsBlank( const char& v ) + { + return( v == ' ' || v == '\t' || v == '\n' || v == '\r' ); + } + + // ----------------------------------------------------------------------- + template< class _TTokens > + inline void TokenizeString( + _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_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 + } + + // ----------------------------------------------------------------------- + inline std::string ReplaceString( + 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 ReadFileIntoBuffer( + 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 std::string CanonicalPath( const std::string& path ) + { + std::string ret = ""; +#ifdef cpPlugins_SYS_WINDOWS + TCHAR buffer[ 4096 ] = TEXT( "" ); + TCHAR** lppPart = { NULL }; + GetFullPathName( path.c_str( ), 4096, buffer, lppPart ); + ret = std::string( buffer ); +#else // cpPlugins_SYS_WINDOWS + char* canonical_path = realpath( path.c_str( ), NULL ); + if( canonical_path != NULL ) + { + ret = canonical_path; + free( canonical_path ); + + } // fi +#endif // cpPlugins_SYS_WINDOWS + return( ret ); + } + +} // ecapseman + +#endif // __CPPLUGINS__UTILITY__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Workspace.cxx b/lib/cpPlugins/Workspace.cxx new file mode 100644 index 0000000..dd4ade8 --- /dev/null +++ b/lib/cpPlugins/Workspace.cxx @@ -0,0 +1,480 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Workspace:: +Workspace( ) + : m_Interface( NULL ), + m_PrintExecution( false ), + m_MPRViewer( NULL ) +{ + this->m_Graph = TGraph::New( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Workspace:: +~Workspace( ) +{ + this->m_Graph->Clear( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface* cpPlugins::Workspace:: +GetInterface( ) +{ + return( this->m_Interface ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface* cpPlugins::Workspace:: +GetInterface( ) const +{ + return( this->m_Interface ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +SetInterface( cpPlugins::Interface* i ) +{ + if( this->m_Interface != i ) + this->m_Interface = i; +} + +// ------------------------------------------------------------------------- +cpPlugins::Workspace:: +TGraph* cpPlugins::Workspace:: +GetGraph( ) +{ + return( this->m_Graph ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Workspace:: +TGraph* cpPlugins::Workspace:: +GetGraph( ) const +{ + return( this->m_Graph ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +Clear( ) +{ + if( this->m_Graph.IsNotNull( ) ) + this->m_Graph->Clear( ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +ClearConnections( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject* cpPlugins::Workspace:: +GetFilter( const std::string& name ) +{ + ProcessObject* f = + dynamic_cast< ProcessObject* >( + this->m_Graph->GetVertex( name ).GetPointer( ) + ); + return( f ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::ProcessObject* cpPlugins::Workspace:: +GetFilter( const std::string& name ) const +{ + const ProcessObject* f = + dynamic_cast< const ProcessObject* >( + this->m_Graph->GetVertex( name ).GetPointer( ) + ); + return( f ); +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject* cpPlugins::Workspace:: +GetOutput( const std::string& filter, const std::string& output ) +{ + auto f = this->GetFilter( filter ); + if( f != NULL ) + return( f->GetOutput( output ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::DataObject* cpPlugins::Workspace:: +GetOutput( const std::string& filter, const std::string& output ) const +{ + auto f = this->GetFilter( filter ); + if( f != NULL ) + return( f->GetOutput( output ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +HasFilter( const std::string& name ) const +{ + if( this->m_Graph->HasVertexIndex( name ) ) + return( this->GetFilter( name ) != NULL ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject* cpPlugins::Workspace:: +CreateFilter( + const std::string& category, + const std::string& filter, + const std::string& name + ) +{ + if( this->m_Interface == NULL ) + return( NULL ); + + // Get or create new filter from name + if( !( this->m_Graph->HasVertexIndex( name ) ) ) + { + ProcessObject::Pointer f = + this->m_Interface->CreateProcessObject( category, filter ); + if( f.IsNotNull( ) ) + { + if( f->IsInteractive( ) ) + { + std::vector< void* > interactive_objects; + interactive_objects.push_back( this->m_SingleInteractor ); + interactive_objects.push_back( this->m_MPRViewer ); + f->SetInteractionObjects( interactive_objects ); + + } // fi + f->SetPrintExecution( this->m_PrintExecution ); + Object::Pointer o = f.GetPointer( ); + this->m_Graph->SetVertex( name, o ); + f->SetName( name ); + + } // fi + return( f.GetPointer( ) ); + } + else + return( this->GetFilter( name ) ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +RenameFilter( const std::string& old_name, const std::string& new_name ) +{ + return( this->m_Graph->RenameVertex( old_name, new_name ) ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +RemoveFilter( const std::string& name ) +{ +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +SetParameter( const std::string& name, const std::string& value ) +{ + std::vector< std::string > tokens; + cpPlugins::TokenizeString( tokens, name, "@" ); + + if( this->HasFilter( tokens[ 1 ] ) ) + { + auto filter = this->GetFilter( tokens[ 1 ] ); + filter->GetParameters( )->SetString( tokens[ 0 ], value ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +SetPrintExecution( bool b ) +{ + this->m_PrintExecution = b; + auto vIt = this->m_Graph->BeginVertices( ); + for( ; vIt != this->m_Graph->EndVertices( ); ++vIt ) + { + auto f = dynamic_cast< ProcessObject* >( vIt->second.GetPointer( ) ); + if( f != NULL ) + f->SetPrintExecution( b ); + + } // rof +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +PrintExecutionOn( ) +{ + this->SetPrintExecution( true ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +PrintExecutionOff( ) +{ + this->SetPrintExecution( false ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpPlugins::Workspace:: +GetSingleInteractor( ) +{ + return( this->m_SingleInteractor ); +} + +// ------------------------------------------------------------------------- +const vtkRenderWindowInteractor* cpPlugins::Workspace:: +GetSingleInteractor( ) const +{ + return( this->m_SingleInteractor ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +SetSingleInteractor( vtkRenderWindowInteractor* interactor ) +{ + this->m_SingleInteractor = interactor; +} + +// ------------------------------------------------------------------------- +cpPlugins::Workspace::TMPRWidget* cpPlugins::Workspace:: +GetMPRViewer( ) +{ + return( this->m_MPRViewer ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Workspace::TMPRWidget* cpPlugins::Workspace:: +GetMPRViewer( ) const +{ + return( this->m_MPRViewer ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +SetMPRViewer( cpPlugins::Workspace::TMPRWidget* wdg ) +{ + this->m_MPRViewer = wdg; +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +Connect( + const std::string& orig_filter, const std::string& dest_filter, + const std::string& output_name, const std::string& input_name + ) +{ + // Get filters + ProcessObject* orig = this->GetFilter( orig_filter ); + ProcessObject* dest = this->GetFilter( dest_filter ); + if( orig == NULL || dest == NULL ) + return( false ); + + // Real connection + if( dest->SetInputPort( input_name, orig->GetOutputPort( output_name ) ) ) + { + this->m_Graph->AddEdge( + orig_filter, dest_filter, + TConnection( output_name, input_name ) + ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +Connect( const OutputPort& port, const std::string& exposed_port ) +{ + auto i = this->m_ExposedInputPorts.find( exposed_port ); + if( i != this->m_ExposedInputPorts.end( ) ) + { + ProcessObject* filter = this->GetFilter( i->second.first ); + if( filter != NULL ) + return( filter->SetInputPort( i->second.second, port ) ); + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +Reduce( const std::string& name ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +ExposeInputPort( + const std::string& name, + const std::string& filter, const std::string& filter_input + ) +{ + this->m_ExposedInputPorts[ name ] = TExposedPort( filter, filter_input ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +ExposeOutputPort( + const std::string& name, + const std::string& filter, const std::string& filter_output + ) +{ + this->m_ExposedOutputPorts[ name ] = TExposedPort( filter, filter_output ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +HideInputPort( const std::string& name ) +{ + auto i = this->m_ExposedInputPorts.find( name ); + if( i != this->m_ExposedInputPorts.end( ) ) + this->m_ExposedInputPorts.erase( i ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +HideOutputPort( const std::string& name ) +{ + auto i = this->m_ExposedOutputPorts.find( name ); + if( i != this->m_ExposedOutputPorts.end( ) ) + this->m_ExposedOutputPorts.erase( i ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +RenameExposedInputPort( + const std::string& old_name, + const std::string& new_name + ) +{ + auto o = this->m_ExposedInputPorts.find( old_name ); + auto n = this->m_ExposedInputPorts.find( new_name ); + if( + o != this->m_ExposedInputPorts.end( ) && + n == this->m_ExposedInputPorts.end( ) + ) + { + this->m_ExposedInputPorts[ new_name ] = o->second; + this->m_ExposedInputPorts.erase( o ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::Workspace:: +RenameExposedOutputPort( + const std::string& old_name, + const std::string& new_name + ) +{ + auto o = this->m_ExposedOutputPorts.find( old_name ); + auto n = this->m_ExposedOutputPorts.find( new_name ); + if( + o != this->m_ExposedOutputPorts.end( ) && + n == this->m_ExposedOutputPorts.end( ) + ) + { + this->m_ExposedOutputPorts[ new_name ] = o->second; + this->m_ExposedOutputPorts.erase( o ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Workspace:: +TExposedPorts& cpPlugins::Workspace:: +GetExposedInputPorts( ) const +{ + return( this->m_ExposedInputPorts ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Workspace:: +TExposedPorts& cpPlugins::Workspace:: +GetExposedOutputPorts( ) const +{ + return( this->m_ExposedOutputPorts ); +} + +// ------------------------------------------------------------------------- +cpPlugins:: +OutputPort& cpPlugins::Workspace:: +GetExposedOutput( const std::string& name ) +{ + static OutputPort null_port; + + auto i = this->m_ExposedOutputPorts.find( name ); + if( i != this->m_ExposedOutputPorts.end( ) ) + { + ProcessObject* filter = this->GetFilter( i->second.first ); + if( filter != NULL ) + return( filter->GetOutputPort( i->second.second ) ); + + } // fi + return( null_port ); +} + +// ------------------------------------------------------------------------- +const cpPlugins:: +OutputPort& cpPlugins::Workspace:: +GetExposedOutput( const std::string& name ) const +{ + static const OutputPort null_port; + + auto i = this->m_ExposedOutputPorts.find( name ); + if( i != this->m_ExposedOutputPorts.end( ) ) + { + const ProcessObject* filter = this->GetFilter( i->second.first ); + if( filter != NULL ) + return( filter->GetOutputPort( i->second.second ) ); + + } // fi + return( null_port ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +Execute( ) +{ + // Find sinks + std::set< std::string > sinks = this->m_Graph->GetSinks( ); + + // Update sinks + for( auto sIt = sinks.begin( ); sIt != sinks.end( ); ++sIt ) + this->Execute( *sIt ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Workspace:: +Execute( const std::string& name ) +{ + // Get filter + ProcessObject* f = this->GetFilter( name ); + if( f == NULL ) + { + itkGenericExceptionMacro( + "cpPlugins::Workspace: Vertex \"" << name << "\" is not a filter." + ); + + } // fi + + // Execute + f->Update( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Workspace.h b/lib/cpPlugins/Workspace.h new file mode 100644 index 0000000..eb14690 --- /dev/null +++ b/lib/cpPlugins/Workspace.h @@ -0,0 +1,164 @@ +#ifndef __CPPLUGINS__WORKSPACE__H__ +#define __CPPLUGINS__WORKSPACE__H__ + +#include +#include +#include +#include + +#include +#include + +// Some forward declarations +class QWidget; +class vtkRenderWindowInteractor; +namespace cpExtensions +{ + namespace QT + { +// TODO: #ifdef cpPlugins_QT4 + class SimpleMPRWidget; +// TODO: #else // cpPlugins_QT4 +// TODO: typedef char SimpleMPRWidget; +// TODO: #endif // cpPlugins_QT4 + } +} + +namespace cpPlugins +{ + /** \brief A complex pipeline + */ + class cpPlugins_EXPORT Workspace + { + public: + // Various types + typedef std::set< std::string > TStringContainer; + typedef std::pair< std::string, std::string > TExposedPort; + typedef std::map< std::string, TExposedPort > TExposedPorts; + + // Graph type + typedef std::pair< std::string, std::string > TConnection; + typedef + cpExtensions::DataStructures:: + Graph< Object::Pointer, TConnection, std::string > TGraph; + + // Associated MPR + typedef cpExtensions::QT::SimpleMPRWidget TMPRWidget; + + public: + Workspace( ); + virtual ~Workspace( ); + + // Plugins management + Interface* GetInterface( ); + const Interface* GetInterface( ) const; + void SetInterface( Interface* i ); + + // Workspace IO + std::string LoadWorkspace( const std::string& fname ); + std::string SaveWorkspace( const std::string& fname ) const; + + // Graph management + TGraph* GetGraph( ); + const TGraph* GetGraph( ) const; + + void Clear( ); + void ClearConnections( ); + + // Filter management + ProcessObject* GetFilter( const std::string& name ); + const ProcessObject* GetFilter( const std::string& name ) const; + DataObject* GetOutput( + const std::string& filter, const std::string& output + ); + const DataObject* GetOutput( + const std::string& filter, const std::string& output + ) const; + bool HasFilter( const std::string& name ) const; + ProcessObject* CreateFilter( + const std::string& category, + const std::string& filter, + const std::string& name + ); + bool RenameFilter( + const std::string& old_name, const std::string& new_name + ); + void RemoveFilter( const std::string& name ); + void SetParameter( const std::string& name, const std::string& value ); + + void SetPrintExecution( bool b ); + void PrintExecutionOn( ); + void PrintExecutionOff( ); + + // Widgets management + vtkRenderWindowInteractor* GetSingleInteractor( ); + const vtkRenderWindowInteractor* GetSingleInteractor( ) const; + void SetSingleInteractor( vtkRenderWindowInteractor* interactor ); + + TMPRWidget* GetMPRViewer( ); + const TMPRWidget* GetMPRViewer( ) const; + void SetMPRViewer( TMPRWidget* wdg ); + + // Connection management + bool Connect( + const std::string& orig_filter, const std::string& dest_filter, + const std::string& output_name, const std::string& input_name + ); + bool Connect( const OutputPort& port, const std::string& exposed_port ); + void RemoveConnection( + const std::string& dest_filter, const std::string& input_name + ); + void RemoveConnection( const std::string& exposed_port ); + void RemoveConnections( const std::string& dest_filter ); + + // Graph reduction + bool Reduce( const std::string& name ); + void ExposeInputPort( + const std::string& name, + const std::string& filter, const std::string& filter_input + ); + void ExposeOutputPort( + const std::string& name, + const std::string& filter, const std::string& filter_output + ); + void HideInputPort( const std::string& name ); + void HideOutputPort( const std::string& name ); + + bool RenameExposedInputPort( + const std::string& old_name, + const std::string& new_name + ); + bool RenameExposedOutputPort( + const std::string& old_name, + const std::string& new_name + ); + + const TExposedPorts& GetExposedInputPorts( ) const; + const TExposedPorts& GetExposedOutputPorts( ) const; + + OutputPort& GetExposedOutput( const std::string& name ); + const OutputPort& GetExposedOutput( const std::string& name ) const; + + // Pipeline execution + void Execute( ); + void Execute( const std::string& name ); + + protected: + // Plugins interface + Interface* m_Interface; + bool m_PrintExecution; + + // Processing graph + TGraph::Pointer m_Graph; + TExposedPorts m_ExposedInputPorts; + TExposedPorts m_ExposedOutputPorts; + + vtkSmartPointer< vtkRenderWindowInteractor > m_SingleInteractor; + TMPRWidget* m_MPRViewer; + }; + +} // ecapseman + +#endif // __CPPLUGINS__WORKSPACE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/WorkspaceIO.cxx b/lib/cpPlugins/WorkspaceIO.cxx new file mode 100644 index 0000000..b9c1558 --- /dev/null +++ b/lib/cpPlugins/WorkspaceIO.cxx @@ -0,0 +1,251 @@ +#include +#include + +// ------------------------------------------------------------------------- +std::string cpPlugins::Workspace:: +LoadWorkspace( const std::string& fname ) +{ + if( this->m_Interface == NULL ) + return( "cpPlugins::Workspace: No valid plugins interface" ); + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( ); + doc->LoadFile( fname.c_str( ) ); + tinyxml2::XMLElement* root = doc->RootElement( ); + if( root == NULL ) + return( "cpPlugins::Workspace: No valid file" ); + if( std::string( root->Value( ) ) != "cpPlugins_Workspace" ) + return( "cpPlugins::Workspace: No valid workspace" ); + std::stringstream err; + + // Load plugins + auto loaded_plugins = this->m_Interface->GetPlugins( ); + tinyxml2::XMLElement* plugins = root->FirstChildElement( "plugins" ); + std::string plugins_errors = ""; + while( plugins != NULL ) + { + tinyxml2::XMLElement* plugin = plugins->FirstChildElement( "plugin" ); + while( plugin != NULL ) + { + std::string name = plugin->Attribute( "name" ); + if( loaded_plugins.find( name ) == loaded_plugins.end( ) ) + { + try + { + this->m_Interface->LoadPlugin( name ); + } + catch( std::exception& err ) + { + plugins_errors += err.what( ) + std::string( "\n" ); + + } // yrt + + } // fi + plugin = plugin->NextSiblingElement( "plugin" ); + + } // elihw + plugins = plugins->NextSiblingElement( "plugins" ); + + } // elihw + if( plugins_errors != "" ) + return( std::string( "cpPlugins::Workspace: " ) + plugins_errors ); + + // Read filters + 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_re_execution = 0; + filter->QueryIntAttribute( + "ExplicitReExecution", &explicit_re_execution + ); + if( class_value != NULL && name_value != NULL ) + { + if( this->CreateFilter( category_value, class_value, name_value ) ) + { + auto new_filter = this->GetFilter( name_value ); + new_filter->SetViewCoords( viewX, viewY ); + new_filter->SetExplicitReExecution( explicit_re_execution == 1 ); + + // Read parameters + auto parameters = new_filter->GetParameters( ); + parameters->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 + ) + this->Connect( orig_filter, dest_filter, orig_name, dest_name ); + + } // fi + connection = connection->NextSiblingElement( "connection" ); + + } // elihw + + // Read exposed inputs + tinyxml2::XMLElement* port = root->FirstChildElement( "exposed_input_port" ); + while( port != NULL ) + { + this->ExposeInputPort( + port->Attribute( "port_name" ), + port->Attribute( "filter" ), + port->Attribute( "filter_port_name" ) + ); + port = port->NextSiblingElement( "exposed_input_port" ); + + } // elihw + + // Read exposed outputs + port = root->FirstChildElement( "exposed_output_port" ); + while( port != NULL ) + { + this->ExposeOutputPort( + port->Attribute( "port_name" ), + port->Attribute( "filter" ), + port->Attribute( "filter_port_name" ) + ); + port = port->NextSiblingElement( "exposed_output_port" ); + + } // elihw + + // Finish and return + delete doc; + return( err.str( ) ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::Workspace:: +SaveWorkspace( const std::string& fname ) const +{ + std::stringstream err; + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument( ); + tinyxml2::XMLElement* root = doc->NewElement( "cpPlugins_Workspace" ); + std::set< std::string > used_plugins; + + // Save vertices + auto vIt = this->m_Graph->BeginVertices( ); + for( ; vIt != this->m_Graph->EndVertices( ); ++vIt ) + { + auto filter = dynamic_cast< ProcessObject* >( vIt->second.GetPointer( ) ); + auto data = dynamic_cast< DataObject* >( vIt->second.GetPointer( ) ); + if( filter != NULL ) + { + used_plugins.insert( filter->GetPluginName( ) ); + + tinyxml2::XMLElement* e = doc->NewElement( "filter" ); + e->SetAttribute( "category", filter->GetClassCategory( ) ); + e->SetAttribute( "class", filter->GetClassName( ) ); + e->SetAttribute( "name", vIt->first.c_str( ) ); + e->SetAttribute( "ViewX", filter->GetViewX( ) ); + e->SetAttribute( "ViewY", filter->GetViewY( ) ); + e->SetAttribute( + "ExplicitReExecution", ( filter->GetExplicitReExecution( ) )? 1: 0 + ); + + auto params = filter->GetParameters( ); + params->ToXML( doc, e ); + root->LinkEndChild( e ); + } + else if( data != NULL ) + { + // TODO + } // fi + + } // rof + + // Save used plugins + 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 + auto mIt = this->m_Graph->BeginEdgesRows( ); + for( ; mIt != this->m_Graph->EndEdgesRows( ); ++mIt ) + { + auto rIt = mIt->second.begin( ); + for( ; rIt != mIt->second.end( ); ++rIt ) + { + auto eIt = rIt->second.begin( ); + for( ; eIt != rIt->second.end( ); ++eIt ) + { + tinyxml2::XMLElement* conn = doc->NewElement( "connection" ); + tinyxml2::XMLElement* orig = doc->NewElement( "origin" ); + tinyxml2::XMLElement* dest = doc->NewElement( "destination" ); + orig->SetAttribute( "filter", mIt->first.c_str( ) ); + orig->SetAttribute( "name", eIt->first.c_str( ) ); + dest->SetAttribute( "filter", rIt->first.c_str( ) ); + dest->SetAttribute( "name", eIt->second.c_str( ) ); + + conn->LinkEndChild( orig ); + conn->LinkEndChild( dest ); + root->LinkEndChild( conn ); + + } // rof + + } // rof + + } // rof + + // Save exposed ports + auto eipIt = this->m_ExposedInputPorts.begin( ); + for( ; eipIt != this->m_ExposedInputPorts.end( ); ++eipIt ) + { + tinyxml2::XMLElement* port = doc->NewElement( "exposed_input_port" ); + port->SetAttribute( "port_name", eipIt->first.c_str( ) ); + port->SetAttribute( "filter", eipIt->second.first.c_str( ) ); + port->SetAttribute( "filter_port_name", eipIt->second.second.c_str( ) ); + root->LinkEndChild( port ); + + } // rof + + auto eopIt = this->m_ExposedOutputPorts.begin( ); + for( ; eopIt != this->m_ExposedOutputPorts.end( ); ++eopIt ) + { + tinyxml2::XMLElement* port = doc->NewElement( "exposed_output_port" ); + port->SetAttribute( "port_name", eopIt->first.c_str( ) ); + port->SetAttribute( "filter", eopIt->second.first.c_str( ) ); + port->SetAttribute( "filter_port_name", eopIt->second.second.c_str( ) ); + root->LinkEndChild( port ); + + } // rof + + // Physical write and return + doc->LinkEndChild( root ); + doc->SaveFile( fname.c_str( ) ); + delete doc; + return( err.str( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/dirent.h b/lib/cpPlugins/dirent.h new file mode 100644 index 0000000..76238e3 --- /dev/null +++ b/lib/cpPlugins/dirent.h @@ -0,0 +1,848 @@ +/* + * dirent.h - dirent API for Microsoft Visual Studio + * + * Copyright (C) 2006-2012 Toni Ronkko + * Modified by Leonardo Florez-Valencia (florez-l@javeriana.edu.co) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * ``Software''), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $ + */ +#ifndef __CPPLUGINS_DIRENT___H__ +#define __CPPLUGINS_DIRENT___H__ + +// florez-l: use this file in windows environments +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + +/* + * Define architecture flags so we don't need to include windows.h. + * Avoiding windows.h makes it simpler to use windows sockets in conjunction + * with dirent.h. + */ +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) +# define _X86_ +#endif +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64) +#define _AMD64_ +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define ___CPPLUGINS_DIRENT___H__AVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define ___CPPLUGINS_DIRENT___H__AVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat() */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT /* File type mask */ +#endif +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR /* Directory */ +#endif +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR /* Character device */ +#endif +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO /* Pipe */ +#endif +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG /* Regular file */ +#endif +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD /* Read permission */ +#endif +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE /* Write permission */ +#endif +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC /* Execute permission */ +#endif +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO /* Pipe */ +#endif +#if !defined(S_IFBLK) +# define S_IFBLK 0 /* Block device */ +#endif +#if !defined(S_IFLNK) +# define S_IFLNK 0 /* Link */ +#endif +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 /* Socket */ +#endif + +#if defined(_MSC_VER) +# define S_IRUSR S_IREAD /* Read user */ +# define S_IWUSR S_IWRITE /* Write user */ +# define S_IXUSR 0 /* Execute user */ +# define S_IRGRP 0 /* Read group */ +# define S_IWGRP 0 /* Write group */ +# define S_IXGRP 0 /* Execute group */ +# define S_IROTH 0 /* Read others */ +# define S_IWOTH 0 /* Write others */ +# define S_IXOTH 0 /* Execute others */ +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) + +/* Return the exact length of d_namlen without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return number of bytes needed to store d_namlen */ +#define _D_ALLOC_NAMLEN(p) (PATH_MAX) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + long d_ino; /* Always zero */ + unsigned short d_reclen; /* Structure size */ + size_t d_namlen; /* Length of name without \0 */ + int d_type; /* File type */ + wchar_t d_name[PATH_MAX]; /* File name */ +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + struct _wdirent ent; /* Current directory entry */ + WIN32_FIND_DATAW data; /* Private file data */ + int cached; /* True if data is valid */ + HANDLE handle; /* Win32 search handle */ + wchar_t *patt; /* Initial directory name */ +}; +typedef struct _WDIR _WDIR; + +static _WDIR *_wopendir (const wchar_t *dirname); +static struct _wdirent *_wreaddir (_WDIR *dirp); +static int _wclosedir (_WDIR *dirp); +static void _wrewinddir (_WDIR* dirp); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Multi-byte character versions */ +struct dirent { + long d_ino; /* Always zero */ + unsigned short d_reclen; /* Structure size */ + size_t d_namlen; /* Length of name without \0 */ + int d_type; /* File type */ + char d_name[PATH_MAX]; /* File name */ +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + +static DIR *opendir (const char *dirname); +static struct dirent *readdir (DIR *dirp); +static int closedir (DIR *dirp); +static void rewinddir (DIR* dirp); + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (dirp != NULL) { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator */ + n = GetFullPathNameW (dirname, 0, NULL, NULL); + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt) { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + */ + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first (dirp)) { + /* Directory stream opened successfully */ + error = 0; + } else { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno (ENOENT); + } + + } else { + /* Cannot retrieve full path name */ + dirent_set_errno (ENOENT); + error = 1; + } + + } else { + /* Cannot allocate memory for search pattern */ + error = 1; + } + + } else { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir (dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. The directory entry is returned in dirent + * structure in the d_name field. Individual directory entries returned by + * this function include regular files, sub-directories, pseudo-directories + * "." and ".." as well as volume labels, hidden files and system files. + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct _wdirent *entp; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* Pointer to directory entry to return */ + entp = &dirp->ent; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { + entp->d_name[n] = datap->cFileName[n]; + n++; + } + dirp->ent.d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof (struct _wdirent); + + } else { + + /* Last directory entry read */ + entp = NULL; + + } + + return entp; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) { + free (dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileW (dirp->patt, &dirp->data); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + } + return datap; +} + +/* Get next directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occured */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } else { + /* Failed to open directory stream */ + error = 1; + } + + } else { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + error = 1; + } + + } else { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + free (dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. + * + * When working with text consoles, please note that file names returned by + * readdir() are represented in the default ANSI code page while any output to + * console is typically formatted on another code page. Thus, non-ASCII + * characters in file names will not usually display correctly on console. The + * problem can be fixed in two ways: (1) change the character set of console + * to 1252 using chcp utility and use Lucida Console font, or (2) use + * _cprintf function when writing to console. The _cprinf() will re-encode + * ANSI strings to the console code page so many non-ASCII characters will + * display correcly. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct dirent *entp; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, + datap->cAlternateFileName, PATH_MAX); + } + + if (!error) { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof (struct dirent); + + } else { + /* + * Cannot convert file name to multi-byte string so construct + * an errornous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + + } else { + /* No more directory entries */ + entp = NULL; + } + + return entp; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resuting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Lenght of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif + +// florez-l: use the standard linux header +#else // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +#include +#endif // defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + +#endif /*__CPPLUGINS_DIRENT___H__*/ + diff --git a/lib/tinyxml2/OLD_CMakeLists.txt.old b/lib/tinyxml2/OLD_CMakeLists.txt.old new file mode 100644 index 0000000..6579b71 --- /dev/null +++ b/lib/tinyxml2/OLD_CMakeLists.txt.old @@ -0,0 +1,32 @@ +SET(lib_NAME cpPlugins_tinyxml2) +SET(lib_DIR third_party/tinyxml) + +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +ENDIF(MSVC) + +ADD_LIBRARY(${lib_NAME} SHARED tinyxml2.cpp tinyxml2.h) +SET_TARGET_PROPERTIES( + ${lib_NAME} PROPERTIES + VERSION "${prj_VER}" + SOVERSION "${prj_sVER}" + ) +GENERATE_EXPORT_HEADER( + ${lib_NAME} + BASE_NAME ${lib_NAME} + EXPORT_MACRO_NAME ${lib_NAME}_EXPORT + EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/${lib_DIR}/${lib_NAME}_Export.h + STATIC_DEFINE ${lib_NAME}_BUILT_AS_STATIC + ) +INSTALL( + TARGETS ${lib_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + ) +INSTALL( + FILES tinyxml2.h + DESTINATION include + ) + +## eof - $RCSfile$ diff --git a/lib/tinyxml2/readme.md b/lib/tinyxml2/readme.md new file mode 100644 index 0000000..30424c3 --- /dev/null +++ b/lib/tinyxml2/readme.md @@ -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: + + Hello, World + +The leading space before the "Hello" and the double space after the comma are +preserved. Line-feeds are preserved, as in this example: + + Hello again, + World + +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: + + + 1 + 2 + 3 + + + 123 + +#### 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: + + & & + < < + > > + " " + ' ' + +These are recognized when the XML document is read, and translated to their +UTF-8 equivalents. For instance, text with the XML of: + + Far & 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 ` ` or ` ` 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/tinyxml2/tinyxml2.cpp b/lib/tinyxml2/tinyxml2.cpp new file mode 100644 index 0000000..df49d0d --- /dev/null +++ b/lib/tinyxml2/tinyxml2.cpp @@ -0,0 +1,2467 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +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. +*/ + +#include "tinyxml2.h" + +#include // yes, this one new style header, is in the Android SDK. +#if defined(ANDROID_NDK) || defined(__QNXNTO__) +# include +# include +#else +# include +# include +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + // Microsoft Visual Studio, version 2005 and higher. Not WinCE. + /*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... + );*/ + static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) + { + va_list va; + va_start( va, format ); + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; + } + + static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va ) + { + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + return result; + } + + #define TIXML_VSCPRINTF _vscprintf + #define TIXML_SSCANF sscanf_s +#elif defined _MSC_VER + // Microsoft Visual Studio 2003 and earlier or WinCE + #define TIXML_SNPRINTF _snprintf + #define TIXML_VSNPRINTF _vsnprintf + #define TIXML_SSCANF sscanf + #if (_MSC_VER < 1400 ) && (!defined WINCE) + // Microsoft Visual Studio 2003 and not WinCE. + #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have. + #else + // Microsoft Visual Studio 2003 and earlier or WinCE. + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = 512; + for (;;) { + len = len*2; + char* str = new char[len](); + const int required = _vsnprintf(str, len, format, va); + delete[] str; + if ( required != -1 ) { + TIXMLASSERT( required >= 0 ); + len = required; + break; + } + } + TIXMLASSERT( len >= 0 ); + return len; + } + #endif +#else + // GCC version 3 and higher + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_VSNPRINTF vsnprintf + static inline int TIXML_VSCPRINTF( const char* format, va_list va ) + { + int len = vsnprintf( 0, 0, format, va ); + TIXMLASSERT( len >= 0 ); + return len; + } + #define TIXML_SSCANF sscanf +#endif + + +static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF +static const char LF = LINE_FEED; +static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out +static const char CR = CARRIAGE_RETURN; +static const char SINGLE_QUOTE = '\''; +static const char DOUBLE_QUOTE = '\"'; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// ef bb bf (Microsoft "lead bytes") - designates UTF-8 + +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +namespace tinyxml2 +{ + +struct Entity { + const char* pattern; + int length; + char value; +}; + +static const int NUM_ENTITIES = 5; +static const Entity entities[NUM_ENTITIES] = { + { "quot", 4, DOUBLE_QUOTE }, + { "amp", 3, '&' }, + { "apos", 4, SINGLE_QUOTE }, + { "lt", 2, '<' }, + { "gt", 2, '>' } +}; + + +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + +void StrPair::Reset() +{ + if ( _flags & NEEDS_DELETE ) { + delete [] _start; + } + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + TIXMLASSERT( str ); + Reset(); + size_t len = strlen( str ); + TIXMLASSERT( _start == 0 ); + _start = new char[ len+1 ]; + memcpy( _start, str, len+1 ); + _end = _start + len; + _flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) +{ + TIXMLASSERT( endTag && *endTag ); + + char* start = p; + char endChar = *endTag; + size_t length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } + ++p; + } + return 0; +} + + +char* StrPair::ParseName( char* p ) +{ + if ( !p || !(*p) ) { + return 0; + } + if ( !XMLUtil::IsNameStartChar( *p ) ) { + return 0; + } + + char* const start = p; + ++p; + while ( *p && XMLUtil::IsNameChar( *p ) ) { + ++p; + } + + Set( start, p, 0 ); + return p; +} + + +void StrPair::CollapseWhitespace() +{ + // Adjusting _start would cause undefined behavior on delete[] + TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); + // Trim leading space. + _start = XMLUtil::SkipWhiteSpace( _start ); + + if ( *_start ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( *p ) { + if ( XMLUtil::IsWhiteSpace( *p )) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p == 0 ) { + break; // don't write to q; this trims the trailing space. + } + *q = ' '; + ++q; + } + *q = *p; + ++q; + ++p; + } + *q = 0; + } +} + + +const char* StrPair::GetStr() +{ + TIXMLASSERT( _start ); + TIXMLASSERT( _end ); + if ( _flags & NEEDS_FLUSH ) { + *_end = 0; + _flags ^= NEEDS_FLUSH; + + if ( _flags ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( p < _end ) { + if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { + // CR-LF pair becomes LF + // CR alone becomes LF + // LF-CR becomes LF + if ( *(p+1) == LF ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { + if ( *(p+1) == CR ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { + // Entities handled by tinyXML2: + // - special entities in the entity table [in/out] + // - numeric character reference [in] + // 中 or 中 + + if ( *(p+1) == '#' ) { + const int buflen = 10; + char buf[buflen] = { 0 }; + int len = 0; + char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); + if ( adjusted == 0 ) { + *q = *p; + ++p; + ++q; + } + else { + TIXMLASSERT( 0 <= len && len <= buflen ); + TIXMLASSERT( q + len <= adjusted ); + p = adjusted; + memcpy( q, buf, len ); + q += len; + } + } + else { + bool entityFound = false; + for( int i = 0; i < NUM_ENTITIES; ++i ) { + const Entity& entity = entities[i]; + if ( strncmp( p + 1, entity.pattern, entity.length ) == 0 + && *( p + entity.length + 1 ) == ';' ) { + // Found an entity - convert. + *q = entity.value; + ++q; + p += entity.length + 2; + entityFound = true; + break; + } + } + if ( !entityFound ) { + // fixme: treat as error? + ++p; + ++q; + } + } + } + else { + *q = *p; + ++p; + ++q; + } + } + *q = 0; + } + // The loop below has plenty going on, and this + // is a less useful mode. Break it out. + if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) { + CollapseWhitespace(); + } + _flags = (_flags & NEEDS_DELETE); + } + TIXMLASSERT( _start ); + return _start; +} + + + + +// --------- XMLUtil ----------- // + +const char* XMLUtil::ReadBOM( const char* p, bool* bom ) +{ + TIXMLASSERT( p ); + TIXMLASSERT( bom ); + *bom = false; + const unsigned char* pu = reinterpret_cast(p); + // Check for BOM: + if ( *(pu+0) == TIXML_UTF_LEAD_0 + && *(pu+1) == TIXML_UTF_LEAD_1 + && *(pu+2) == TIXML_UTF_LEAD_2 ) { + *bom = true; + p += 3; + } + TIXMLASSERT( p ); + return p; +} + + +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) { + *length = 1; + } + else if ( input < 0x800 ) { + *length = 2; + } + else if ( input < 0x10000 ) { + *length = 3; + } + else if ( input < 0x200000 ) { + *length = 4; + } + else { + *length = 0; // This code won't convert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs. + switch (*length) { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + break; + default: + TIXMLASSERT( false ); + } +} + + +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) +{ + // Presume an entity, and pull it out. + *length = 0; + + if ( *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + TIXMLASSERT( sizeof( ucs ) >= 4 ); + ptrdiff_t delta = 0; + unsigned mult = 1; + static const char SEMICOLON = ';'; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + const char* q = p+3; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != 'x' ) { + unsigned int digit = 0; + + if ( *q >= '0' && *q <= '9' ) { + digit = *q - '0'; + } + else if ( *q >= 'a' && *q <= 'f' ) { + digit = *q - 'a' + 10; + } + else if ( *q >= 'A' && *q <= 'F' ) { + digit = *q - 'A' + 10; + } + else { + return 0; + } + TIXMLASSERT( digit >= 0 && digit < 16); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + TIXMLASSERT( mult <= UINT_MAX / 16 ); + mult *= 16; + --q; + } + } + else { + // Decimal. + const char* q = p+2; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) { + const unsigned int digit = *q - '0'; + TIXMLASSERT( digit >= 0 && digit < 10); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + } + else { + return 0; + } + TIXMLASSERT( mult <= UINT_MAX / 10 ); + mult *= 10; + --q; + } + } + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + return p + delta + 1; + } + return p+1; +} + + +void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); +} + + +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); +} + + +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); +} + +/* + ToStr() of a number is a very tricky topic. + https://github.com/leethomason/tinyxml2/issues/106 +*/ +void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); +} + + +void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); +} + + +bool XMLUtil::ToInt( const char* str, int* value ) +{ + if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) +{ + if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToBool( const char* str, bool* value ) +{ + int ival = 0; + if ( ToInt( str, &ival )) { + *value = (ival==0) ? false : true; + return true; + } + if ( StringEqual( str, "true" ) ) { + *value = true; + return true; + } + else if ( StringEqual( str, "false" ) ) { + *value = false; + return true; + } + return false; +} + + +bool XMLUtil::ToFloat( const char* str, float* value ) +{ + if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToDouble( const char* str, double* value ) +{ + if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { + return true; + } + return false; +} + + +char* XMLDocument::Identify( char* p, XMLNode** node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( p ); + char* const start = p; + p = XMLUtil::SkipWhiteSpace( p ); + if( !*p ) { + *node = 0; + TIXMLASSERT( p ); + return p; + } + + // These strings define the matching patterns: + static const char* xmlHeader = { "_memPool = &_commentPool; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode->_memPool = &_commentPool; + p += commentHeaderLen; + } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + returnNode = text; + returnNode->_memPool = &_textPool; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode->_memPool = &_commentPool; + p += dtdHeaderLen; + } + else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode->_memPool = &_elementPool; + p += elementHeaderLen; + } + else { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + returnNode = new (_textPool.Alloc()) XMLText( this ); + returnNode->_memPool = &_textPool; + p = start; // Back it up, all the text counts. + } + + TIXMLASSERT( returnNode ); + TIXMLASSERT( p ); + *node = returnNode; + return p; +} + + +bool XMLDocument::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLNode ----------- // + +XMLNode::XMLNode( XMLDocument* doc ) : + _document( doc ), + _parent( 0 ), + _firstChild( 0 ), _lastChild( 0 ), + _prev( 0 ), _next( 0 ), + _memPool( 0 ) +{ +} + + +XMLNode::~XMLNode() +{ + DeleteChildren(); + if ( _parent ) { + _parent->Unlink( this ); + } +} + +const char* XMLNode::Value() const +{ + // Catch an edge case: XMLDocuments don't have a a Value. Carefully return nullptr. + if ( this->ToDocument() ) + return 0; + return _value.GetStr(); +} + +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) { + _value.SetInternedStr( str ); + } + else { + _value.SetStr( str ); + } +} + + +void XMLNode::DeleteChildren() +{ + while( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_document == _document ); + XMLNode* node = _firstChild; + Unlink( node ); + + DeleteNode( node ); + } + _firstChild = _lastChild = 0; +} + + +void XMLNode::Unlink( XMLNode* child ) +{ + TIXMLASSERT( child ); + TIXMLASSERT( child->_document == _document ); + TIXMLASSERT( child->_parent == this ); + if ( child == _firstChild ) { + _firstChild = _firstChild->_next; + } + if ( child == _lastChild ) { + _lastChild = _lastChild->_prev; + } + + if ( child->_prev ) { + child->_prev->_next = child->_next; + } + if ( child->_next ) { + child->_next->_prev = child->_prev; + } + child->_parent = 0; +} + + +void XMLNode::DeleteChild( XMLNode* node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( node->_document == _document ); + TIXMLASSERT( node->_parent == this ); + Unlink( node ); + DeleteNode( node ); +} + + +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _lastChild ) { + TIXMLASSERT( _firstChild ); + TIXMLASSERT( _lastChild->_next == 0 ); + _lastChild->_next = addThis; + addThis->_prev = _lastChild; + _lastChild = addThis; + + addThis->_next = 0; + } + else { + TIXMLASSERT( _firstChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_prev == 0 ); + + _firstChild->_prev = addThis; + addThis->_next = _firstChild; + _firstChild = addThis; + + addThis->_prev = 0; + } + else { + TIXMLASSERT( _lastChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + + TIXMLASSERT( afterThis ); + + if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); + return 0; + } + + if ( afterThis->_next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + InsertChildPreamble( addThis ); + addThis->_prev = afterThis; + addThis->_next = afterThis->_next; + afterThis->_next->_prev = addThis; + afterThis->_next = addThis; + addThis->_parent = this; + return addThis; +} + + + + +const XMLElement* XMLNode::FirstChildElement( const char* name ) const +{ + for( const XMLNode* node = _firstChild; node; node = node->_next ) { + const XMLElement* element = node->ToElement(); + if ( element ) { + if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::LastChildElement( const char* name ) const +{ + for( const XMLNode* node = _lastChild; node; node = node->_prev ) { + const XMLElement* element = node->ToElement(); + if ( element ) { + if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::NextSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _next; node; node = node->_next ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!name || XMLUtil::StringEqual( name, element->Name() ))) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const +{ + for( const XMLNode* node = _prev; node; node = node->_prev ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!name || XMLUtil::StringEqual( name, element->Name() ))) { + return element; + } + } + return 0; +} + + +char* XMLNode::ParseDeep( char* p, StrPair* parentEnd ) +{ + // This is a recursive method, but thinking about it "at the current level" + // it is a pretty simple flat list: + // + // + // + // With a special case: + // + // + // + // + // Where the closing element (/foo) *must* be the next thing after the opening + // element, and the names must match. BUT the tricky bit is that the closing + // element will be read by the child. + // + // 'endTag' is the end tag for this node, it is returned by a call to a child. + // 'parentEnd' is the end tag for the parent, which is filled in and returned. + + while( p && *p ) { + XMLNode* node = 0; + + p = _document->Identify( p, &node ); + if ( node == 0 ) { + break; + } + + StrPair endTag; + p = node->ParseDeep( p, &endTag ); + if ( !p ) { + DeleteNode( node ); + if ( !_document->Error() ) { + _document->SetError( XML_ERROR_PARSING, 0, 0 ); + } + break; + } + + XMLDeclaration* decl = node->ToDeclaration(); + if ( decl ) { + // A declaration can only be the first child of a document. + // Set error, if document already has children. + if ( !_document->NoChildren() ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, decl->Value(), 0); + DeleteNode( decl ); + break; + } + } + + XMLElement* ele = node->ToElement(); + if ( ele ) { + // We read the end tag. Return it to the parent. + if ( ele->ClosingType() == XMLElement::CLOSING ) { + if ( parentEnd ) { + ele->_value.TransferTo( parentEnd ); + } + node->_memPool->SetTracked(); // created and then immediately deleted. + DeleteNode( node ); + return p; + } + + // Handle an end tag returned to this level. + // And handle a bunch of annoying errors. + bool mismatch = false; + if ( endTag.Empty() ) { + if ( ele->ClosingType() == XMLElement::OPEN ) { + mismatch = true; + } + } + else { + if ( ele->ClosingType() != XMLElement::OPEN ) { + mismatch = true; + } + else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) { + mismatch = true; + } + } + if ( mismatch ) { + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, ele->Name(), 0 ); + DeleteNode( node ); + break; + } + } + InsertEndChild( node ); + } + return 0; +} + +void XMLNode::DeleteNode( XMLNode* node ) +{ + if ( node == 0 ) { + return; + } + MemPool* pool = node->_memPool; + node->~XMLNode(); + pool->Free( node ); +} + +void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const +{ + TIXMLASSERT( insertThis ); + TIXMLASSERT( insertThis->_document == _document ); + + if ( insertThis->_parent ) + insertThis->_parent->Unlink( insertThis ); + else + insertThis->_memPool->SetTracked(); +} + +// --------- XMLText ---------- // +char* XMLText::ParseDeep( char* p, StrPair* ) +{ + const char* start = p; + if ( this->CData() ) { + p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 ); + } + return p; + } + else { + int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; + if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { + flags |= StrPair::NEEDS_WHITESPACE_COLLAPSING; + } + + p = _value.ParseText( p, "<", flags ); + if ( p && *p ) { + return p-1; + } + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 ); + } + } + return 0; +} + + +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? + text->SetCData( this->CData() ); + return text; +} + + +bool XMLText::ShallowEqual( const XMLNode* compare ) const +{ + const XMLText* text = compare->ToText(); + return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); +} + + +bool XMLText::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLComment ---------- // + +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLComment::~XMLComment() +{ +} + + +char* XMLComment::ParseDeep( char* p, StrPair* ) +{ + // Comment parses as text. + const char* start = p; + p = _value.ParseText( p, "-->", StrPair::COMMENT ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 ); + } + return p; +} + + +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? + return comment; +} + + +bool XMLComment::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLComment* comment = compare->ToComment(); + return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); +} + + +bool XMLComment::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p, StrPair* ) +{ + // Declaration parses as text. + const char* start = p; + p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 ); + } + return p; +} + + +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? + return dec; +} + + +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLDeclaration* declaration = compare->ToDeclaration(); + return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); +} + + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p, StrPair* ) +{ + // Unknown parses as text. + const char* start = p; + + p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); + } + return p; +} + + +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLUnknown* unknown = compare->ToUnknown(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLAttribute ---------- // + +const char* XMLAttribute::Name() const +{ + return _name.GetStr(); +} + +const char* XMLAttribute::Value() const +{ + return _value.GetStr(); +} + +char* XMLAttribute::ParseDeep( char* p, bool processEntities ) +{ + // Parse using the name rules: bug fix, was using ParseText before + p = _name.ParseName( p ); + if ( !p || !*p ) { + return 0; + } + + // Skip white space before = + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '=' ) { + return 0; + } + + ++p; // move up to opening quote + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '\"' && *p != '\'' ) { + return 0; + } + + char endTag[2] = { *p, 0 }; + ++p; // move past opening quote + + p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES ); + return p; +} + + +void XMLAttribute::SetName( const char* n ) +{ + _name.SetStr( n ); +} + + +XMLError XMLAttribute::QueryIntValue( int* value ) const +{ + if ( XMLUtil::ToInt( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const +{ + if ( XMLUtil::ToUnsigned( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryBoolValue( bool* value ) const +{ + if ( XMLUtil::ToBool( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryFloatValue( float* value ) const +{ + if ( XMLUtil::ToFloat( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryDoubleValue( double* value ) const +{ + if ( XMLUtil::ToDouble( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + _value.SetStr( v ); +} + + +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +// --------- XMLElement ---------- // +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), + _closingType( 0 ), + _rootAttribute( 0 ) +{ +} + + +XMLElement::~XMLElement() +{ + while( _rootAttribute ) { + XMLAttribute* next = _rootAttribute->_next; + DeleteAttribute( _rootAttribute ); + _rootAttribute = next; + } +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) { + return a; + } + } + return 0; +} + + +const char* XMLElement::Attribute( const char* name, const char* value ) const +{ + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return 0; + } + if ( !value || XMLUtil::StringEqual( a->Value(), value )) { + return a->Value(); + } + return 0; +} + + +const char* XMLElement::GetText() const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + return FirstChild()->Value(); + } + return 0; +} + + +void XMLElement::SetText( const char* inText ) +{ + if ( FirstChild() && FirstChild()->ToText() ) + FirstChild()->SetValue( inText ); + else { + XMLText* theText = GetDocument()->NewText( inText ); + InsertFirstChild( theText ); + } +} + + +void XMLElement::SetText( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +XMLError XMLElement::QueryIntText( int* ival ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToInt( t, ival ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToUnsigned( t, uval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryBoolText( bool* bval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToBool( t, bval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryDoubleText( double* dval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToDouble( t, dval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryFloatText( float* fval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToFloat( t, fval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* last = 0; + XMLAttribute* attrib = 0; + for( attrib = _rootAttribute; + attrib; + last = attrib, attrib = attrib->_next ) { + if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { + break; + } + } + if ( !attrib ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + if ( last ) { + last->_next = attrib; + } + else { + _rootAttribute = attrib; + } + attrib->SetName( name ); + attrib->_memPool->SetTracked(); // always created and linked. + } + return attrib; +} + + +void XMLElement::DeleteAttribute( const char* name ) +{ + XMLAttribute* prev = 0; + for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { + if ( XMLUtil::StringEqual( name, a->Name() ) ) { + if ( prev ) { + prev->_next = a->_next; + } + else { + _rootAttribute = a->_next; + } + DeleteAttribute( a ); + break; + } + prev = a; + } +} + + +char* XMLElement::ParseAttributes( char* p ) +{ + const char* start = p; + XMLAttribute* prevAttribute = 0; + + // Read the attributes. + while( p ) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( !(*p) ) { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() ); + return 0; + } + + // attribute. + if (XMLUtil::IsNameStartChar( *p ) ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + attrib->_memPool->SetTracked(); + + p = attrib->ParseDeep( p, _document->ProcessEntities() ); + if ( !p || Attribute( attrib->Name() ) ) { + DeleteAttribute( attrib ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); + return 0; + } + // There is a minor bug here: if the attribute in the source xml + // document is duplicated, it will not be detected and the + // attribute will be doubly added. However, tracking the 'prevAttribute' + // avoids re-scanning the attribute list. Preferring performance for + // now, may reconsider in the future. + if ( prevAttribute ) { + prevAttribute->_next = attrib; + } + else { + _rootAttribute = attrib; + } + prevAttribute = attrib; + } + // end of the tag + else if ( *p == '>' ) { + ++p; + break; + } + // end of the tag + else if ( *p == '/' && *(p+1) == '>' ) { + _closingType = CLOSED; + return p+2; // done; sealed element. + } + else { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p ); + return 0; + } + } + return p; +} + +void XMLElement::DeleteAttribute( XMLAttribute* attribute ) +{ + if ( attribute == 0 ) { + return; + } + MemPool* pool = attribute->_memPool; + attribute->~XMLAttribute(); + pool->Free( attribute ); +} + +// +// +// foobar +// +char* XMLElement::ParseDeep( char* p, StrPair* strPair ) +{ + // Read the element name. + p = XMLUtil::SkipWhiteSpace( p ); + + // The closing element is the form. It is + // parsed just like a regular element then deleted from + // the DOM. + if ( *p == '/' ) { + _closingType = CLOSING; + ++p; + } + + p = _value.ParseName( p ); + if ( _value.Empty() ) { + return 0; + } + + p = ParseAttributes( p ); + if ( !p || !*p || _closingType ) { + return p; + } + + p = XMLNode::ParseDeep( p, strPair ); + return p; +} + + + +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? + for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { + element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? + } + return element; +} + + +bool XMLElement::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLElement* other = compare->ToElement(); + if ( other && XMLUtil::StringEqual( other->Name(), Name() )) { + + const XMLAttribute* a=FirstAttribute(); + const XMLAttribute* b=other->FirstAttribute(); + + while ( a && b ) { + if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { + return false; + } + a = a->Next(); + b = b->Next(); + } + if ( a || b ) { + // different count + return false; + } + return true; + } + return false; +} + + +bool XMLElement::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this, _rootAttribute ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLDocument ----------- // + +// Warning: List must match 'enum XMLError' +const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { + "XML_SUCCESS", + "XML_NO_ATTRIBUTE", + "XML_WRONG_ATTRIBUTE_TYPE", + "XML_ERROR_FILE_NOT_FOUND", + "XML_ERROR_FILE_COULD_NOT_BE_OPENED", + "XML_ERROR_FILE_READ_ERROR", + "XML_ERROR_ELEMENT_MISMATCH", + "XML_ERROR_PARSING_ELEMENT", + "XML_ERROR_PARSING_ATTRIBUTE", + "XML_ERROR_IDENTIFYING_TAG", + "XML_ERROR_PARSING_TEXT", + "XML_ERROR_PARSING_CDATA", + "XML_ERROR_PARSING_COMMENT", + "XML_ERROR_PARSING_DECLARATION", + "XML_ERROR_PARSING_UNKNOWN", + "XML_ERROR_EMPTY_DOCUMENT", + "XML_ERROR_MISMATCHED_ELEMENT", + "XML_ERROR_PARSING", + "XML_CAN_NOT_CONVERT_TEXT", + "XML_NO_TEXT_NODE" +}; + + +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : + XMLNode( 0 ), + _writeBOM( false ), + _processEntities( processEntities ), + _errorID( XML_NO_ERROR ), + _whitespace( whitespace ), + _errorStr1( 0 ), + _errorStr2( 0 ), + _charBuffer( 0 ) +{ + // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+) + _document = this; +} + + +XMLDocument::~XMLDocument() +{ + Clear(); +} + + +void XMLDocument::Clear() +{ + DeleteChildren(); + +#ifdef DEBUG + const bool hadError = Error(); +#endif + _errorID = XML_NO_ERROR; + _errorStr1 = 0; + _errorStr2 = 0; + + delete [] _charBuffer; + _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif +} + + +XMLElement* XMLDocument::NewElement( const char* name ) +{ + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); + ele->_memPool = &_elementPool; + ele->SetName( name ); + return ele; +} + + +XMLComment* XMLDocument::NewComment( const char* str ) +{ + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); + comment->_memPool = &_commentPool; + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + text->_memPool = &_textPool; + text->SetValue( str ); + return text; +} + + +XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) +{ + TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); + XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); + dec->_memPool = &_commentPool; + dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); + return dec; +} + + +XMLUnknown* XMLDocument::NewUnknown( const char* str ) +{ + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); + unk->_memPool = &_commentPool; + unk->SetValue( str ); + return unk; +} + +static FILE* callfopen( const char* filepath, const char* mode ) +{ + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filepath, mode ); + if ( err ) { + return 0; + } +#else + FILE* fp = fopen( filepath, mode ); +#endif + return fp; +} + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + + +XMLError XMLDocument::LoadFile( const char* filename ) +{ + Clear(); + FILE* fp = callfopen( filename, "rb" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 ); + return _errorID; + } + LoadFile( fp ); + fclose( fp ); + return _errorID; +} + +// This is likely overengineered template art to have a check that unsigned long value incremented +// by one still fits into size_t. If size_t type is larger than unsigned long type +// (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit +// -Wtype-limits warning. This piece makes the compiler select code with a check when a check +// is useful and code with no check when a check is redundant depending on how size_t and unsigned long +// types sizes relate to each other. +template += sizeof(size_t))> +struct LongFitsIntoSizeTMinusOne { + static bool Fits( unsigned long value ) + { + return value < (size_t)-1; + } +}; + +template <> +bool LongFitsIntoSizeTMinusOne::Fits( unsigned long /*value*/ ) +{ + return true; +} + +XMLError XMLDocument::LoadFile( FILE* fp ) +{ + Clear(); + + fseek( fp, 0, SEEK_SET ); + if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + fseek( fp, 0, SEEK_END ); + const long filelength = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + if ( filelength == -1L ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + TIXMLASSERT( filelength >= 0 ); + + if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) { + // Cannot handle files which won't fit in buffer together with null terminator + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + if ( filelength == 0 ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + + const size_t size = filelength; + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = new char[size+1]; + size_t read = fread( _charBuffer, 1, size, fp ); + if ( read != size ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + _charBuffer[size] = 0; + + Parse(); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( const char* filename, bool compact ) +{ + FILE* fp = callfopen( filename, "w" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); + return _errorID; + } + SaveFile(fp, compact); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) +{ + // Clear any error from the last save, otherwise it will get reported + // for *this* call. + SetError( XML_NO_ERROR, 0, 0 ); + XMLPrinter stream( fp, compact ); + Print( &stream ); + return _errorID; +} + + +XMLError XMLDocument::Parse( const char* p, size_t len ) +{ + Clear(); + + if ( len == 0 || !p || !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + if ( len == (size_t)(-1) ) { + len = strlen( p ); + } + TIXMLASSERT( _charBuffer == 0 ); + _charBuffer = new char[ len+1 ]; + memcpy( _charBuffer, p, len ); + _charBuffer[len] = 0; + + Parse(); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } + return _errorID; +} + + +void XMLDocument::Print( XMLPrinter* streamer ) const +{ + if ( streamer ) { + Accept( streamer ); + } + else { + XMLPrinter stdoutStreamer( stdout ); + Accept( &stdoutStreamer ); + } +} + + +void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) +{ + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); + _errorID = error; + _errorStr1 = str1; + _errorStr2 = str2; +} + +const char* XMLDocument::ErrorName() const +{ + TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT ); + const char* errorName = _errorNames[_errorID]; + TIXMLASSERT( errorName && errorName[0] ); + return errorName; +} + +void XMLDocument::PrintError() const +{ + if ( Error() ) { + static const int LEN = 20; + char buf1[LEN] = { 0 }; + char buf2[LEN] = { 0 }; + + if ( _errorStr1 ) { + TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 ); + } + if ( _errorStr2 ) { + TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 ); + } + + // Should check INT_MIN <= _errorID && _errorId <= INT_MAX, but that + // causes a clang "always true" -Wtautological-constant-out-of-range-compare warning + TIXMLASSERT( 0 <= _errorID && XML_ERROR_COUNT - 1 <= INT_MAX ); + printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n", + static_cast( _errorID ), ErrorName(), buf1, buf2 ); + } +} + +void XMLDocument::Parse() +{ + TIXMLASSERT( NoChildren() ); // Clear() must have been called previously + TIXMLASSERT( _charBuffer ); + char* p = _charBuffer; + p = XMLUtil::SkipWhiteSpace( p ); + p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); + if ( !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return; + } + ParseDeep(p, 0 ); +} + +XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : + _elementJustOpened( false ), + _firstElement( true ), + _fp( file ), + _depth( depth ), + _textDepth( -1 ), + _processEntities( true ), + _compactMode( compact ) +{ + for( int i=0; i'] = true; // not required, but consistency is nice + _buffer.Push( 0 ); +} + + +void XMLPrinter::Print( const char* format, ... ) +{ + va_list va; + va_start( va, format ); + + if ( _fp ) { + vfprintf( _fp, format, va ); + } + else { + const int len = TIXML_VSCPRINTF( format, va ); + // Close out and re-start the va-args + va_end( va ); + TIXMLASSERT( len >= 0 ); + va_start( va, format ); + TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); + char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. + TIXML_VSNPRINTF( p, len+1, format, va ); + } + va_end( va ); +} + + +void XMLPrinter::PrintSpace( int depth ) +{ + for( int i=0; i 0 && *q < ENTITY_RANGE ) { + // Check for entities. If one is found, flush + // the stream up until the entity, write the + // entity, and keep looking. + if ( flag[(unsigned char)(*q)] ) { + while ( p < q ) { + const size_t delta = q - p; + // %.*s accepts type int as "precision" + const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta; + Print( "%.*s", toPrint, p ); + p += toPrint; + } + bool entityPatternPrinted = false; + for( int i=0; i" ); + } + else { + if ( _textDepth < 0 && !compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + Print( "", name ); + } + + if ( _textDepth == _depth ) { + _textDepth = -1; + } + if ( _depth == 0 && !compactMode) { + Print( "\n" ); + } + _elementJustOpened = false; +} + + +void XMLPrinter::SealElementIfJustOpened() +{ + if ( !_elementJustOpened ) { + return; + } + _elementJustOpened = false; + Print( ">" ); +} + + +void XMLPrinter::PushText( const char* text, bool cdata ) +{ + _textDepth = _depth-1; + + SealElementIfJustOpened(); + if ( cdata ) { + Print( "", text ); + } + else { + PrintString( text, true ); + } +} + +void XMLPrinter::PushText( int value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( unsigned value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( bool value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( float value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( double value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushComment( const char* comment ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", comment ); +} + + +void XMLPrinter::PushDeclaration( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +void XMLPrinter::PushUnknown( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +bool XMLPrinter::VisitEnter( const XMLDocument& doc ) +{ + _processEntities = doc.ProcessEntities(); + if ( doc.HasBOM() ) { + PushHeader( true, false ); + } + return true; +} + + +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) +{ + const XMLElement* parentElem = 0; + if ( element.Parent() ) { + parentElem = element.Parent()->ToElement(); + } + const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode; + OpenElement( element.Name(), compactMode ); + while ( attribute ) { + PushAttribute( attribute->Name(), attribute->Value() ); + attribute = attribute->Next(); + } + return true; +} + + +bool XMLPrinter::VisitExit( const XMLElement& element ) +{ + CloseElement( CompactMode(element) ); + return true; +} + + +bool XMLPrinter::Visit( const XMLText& text ) +{ + PushText( text.Value(), text.CData() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLComment& comment ) +{ + PushComment( comment.Value() ); + return true; +} + +bool XMLPrinter::Visit( const XMLDeclaration& declaration ) +{ + PushDeclaration( declaration.Value() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLUnknown& unknown ) +{ + PushUnknown( unknown.Value() ); + return true; +} + +} // namespace tinyxml2 + diff --git a/lib/tinyxml2/tinyxml2.h b/lib/tinyxml2/tinyxml2.h new file mode 100644 index 0000000..fec68dd --- /dev/null +++ b/lib/tinyxml2/tinyxml2.h @@ -0,0 +1,2106 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +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. +*/ + +#ifndef TINYXML2_INCLUDED +#define TINYXML2_INCLUDED + +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +#endif + +/* + TODO: intern strings instead of allocation. +*/ +/* + gcc: + g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe + + Formatting, Artistic Style: + AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h +*/ + +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +# ifndef DEBUG +# define DEBUG +# endif +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4251) +#endif + +#ifdef _WIN32 +# ifdef TINYXML2_EXPORT +# define TINYXML2_LIB __declspec(dllexport) +# elif defined(TINYXML2_IMPORT) +# define TINYXML2_LIB __declspec(dllimport) +# else +# define TINYXML2_LIB +# endif +#else +# define TINYXML2_LIB +#endif + + +#if defined(DEBUG) +# if defined(_MSC_VER) +# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like +# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } +# elif defined (ANDROID_NDK) +# include +# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } +# else +# include +# define TIXMLASSERT assert +# endif +#else +# define TIXMLASSERT( x ) {} +#endif + + +/* Versioning, past 1.0.14: + http://semver.org/ +*/ +static const int TIXML2_MAJOR_VERSION = 3; +static const int TIXML2_MINOR_VERSION = 0; +static const int TIXML2_PATCH_VERSION = 0; + +#include +#undef TINYXML2_LIB +#define TINYXML2_LIB cpPlugins_tinyxml2_EXPORT + +namespace tinyxml2 +{ +class XMLDocument; +class XMLElement; +class XMLAttribute; +class XMLComment; +class XMLText; +class XMLDeclaration; +class XMLUnknown; +class XMLPrinter; + +/* + A class that wraps strings. Normally stores the start and end + pointers into the XML file itself, and will apply normalization + and entity translation if actually read. Can also store (and memory + manage) a traditional char[] +*/ +class StrPair +{ +public: + enum { + NEEDS_ENTITY_PROCESSING = 0x01, + NEEDS_NEWLINE_NORMALIZATION = 0x02, + NEEDS_WHITESPACE_COLLAPSING = 0x04, + + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_NAME = 0, + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + COMMENT = NEEDS_NEWLINE_NORMALIZATION + }; + + StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} + ~StrPair(); + + void Set( char* start, char* end, int flags ) { + Reset(); + _start = start; + _end = end; + _flags = flags | NEEDS_FLUSH; + } + + const char* GetStr(); + + bool Empty() const { + return _start == _end; + } + + void SetInternedStr( const char* str ) { + Reset(); + _start = const_cast(str); + } + + void SetStr( const char* str, int flags=0 ); + + char* ParseText( char* in, const char* endTag, int strFlags ); + char* ParseName( char* in ); + + void TransferTo( StrPair* other ); + +private: + void Reset(); + void CollapseWhitespace(); + + enum { + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 + }; + + int _flags; + char* _start; + char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( StrPair& other ); // not supported, use TransferTo() +}; + + +/* + A dynamic array of Plain Old Data. Doesn't support constructors, etc. + Has a small initial memory pool, so that low or no usage will not + cause a call to new/delete +*/ +template +class DynArray +{ +public: + DynArray() { + _mem = _pool; + _allocated = INITIAL_SIZE; + _size = 0; + } + + ~DynArray() { + if ( _mem != _pool ) { + delete [] _mem; + } + } + + void Clear() { + _size = 0; + } + + void Push( T t ) { + TIXMLASSERT( _size < INT_MAX ); + EnsureCapacity( _size+1 ); + _mem[_size++] = t; + } + + T* PushArr( int count ) { + TIXMLASSERT( count >= 0 ); + TIXMLASSERT( _size <= INT_MAX - count ); + EnsureCapacity( _size+count ); + T* ret = &_mem[_size]; + _size += count; + return ret; + } + + T Pop() { + TIXMLASSERT( _size > 0 ); + return _mem[--_size]; + } + + void PopArr( int count ) { + TIXMLASSERT( _size >= count ); + _size -= count; + } + + bool Empty() const { + return _size == 0; + } + + T& operator[](int i) { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& operator[](int i) const { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& PeekTop() const { + TIXMLASSERT( _size > 0 ); + return _mem[ _size - 1]; + } + + int Size() const { + TIXMLASSERT( _size >= 0 ); + return _size; + } + + int Capacity() const { + TIXMLASSERT( _allocated >= INITIAL_SIZE ); + return _allocated; + } + + const T* Mem() const { + TIXMLASSERT( _mem ); + return _mem; + } + + T* Mem() { + TIXMLASSERT( _mem ); + return _mem; + } + +private: + DynArray( const DynArray& ); // not supported + void operator=( const DynArray& ); // not supported + + void EnsureCapacity( int cap ) { + TIXMLASSERT( cap > 0 ); + if ( cap > _allocated ) { + TIXMLASSERT( cap <= INT_MAX / 2 ); + int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs + if ( _mem != _pool ) { + delete [] _mem; + } + _mem = newMem; + _allocated = newAllocated; + } + } + + T* _mem; + T _pool[INITIAL_SIZE]; + int _allocated; // objects allocated + int _size; // number objects in use +}; + + +/* + Parent virtual class of a pool for fast allocation + and deallocation of objects. +*/ +class MemPool +{ +public: + MemPool() {} + virtual ~MemPool() {} + + virtual int ItemSize() const = 0; + virtual void* Alloc() = 0; + virtual void Free( void* ) = 0; + virtual void SetTracked() = 0; + virtual void Clear() = 0; +}; + + +/* + Template child class to create pools of the correct type. +*/ +template< int SIZE > +class MemPoolT : public MemPool +{ +public: + MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} + ~MemPoolT() { + Clear(); + } + + void Clear() { + // Delete the blocks. + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; + } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; + } + + virtual int ItemSize() const { + return SIZE; + } + int CurrentAllocs() const { + return _currentAllocs; + } + + virtual void* Alloc() { + if ( !_root ) { + // Need a new block. + Block* block = new Block(); + _blockPtrs.Push( block ); + + for( int i=0; ichunk[i].next = &block->chunk[i+1]; + } + block->chunk[COUNT-1].next = 0; + _root = block->chunk; + } + void* result = _root; + _root = _root->next; + + ++_currentAllocs; + if ( _currentAllocs > _maxAllocs ) { + _maxAllocs = _currentAllocs; + } + _nAllocs++; + _nUntracked++; + return result; + } + + virtual void Free( void* mem ) { + if ( !mem ) { + return; + } + --_currentAllocs; + Chunk* chunk = static_cast( mem ); +#ifdef DEBUG + memset( chunk, 0xfe, sizeof(Chunk) ); +#endif + chunk->next = _root; + _root = chunk; + } + void Trace( const char* name ) { + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", + name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); + } + + void SetTracked() { + _nUntracked--; + } + + int Untracked() const { + return _nUntracked; + } + + // This number is perf sensitive. 4k seems like a good tradeoff on my machine. + // The test file is large, 170k. + // Release: VS2010 gcc(no opt) + // 1k: 4000 + // 2k: 4000 + // 4k: 3900 21000 + // 16k: 5200 + // 32k: 4300 + // 64k: 4000 21000 + enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private + +private: + MemPoolT( const MemPoolT& ); // not supported + void operator=( const MemPoolT& ); // not supported + + union Chunk { + Chunk* next; + char mem[SIZE]; + }; + struct Block { + Chunk chunk[COUNT]; + }; + DynArray< Block*, 10 > _blockPtrs; + Chunk* _root; + + int _currentAllocs; + int _nAllocs; + int _maxAllocs; + int _nUntracked; +}; + + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a XMLVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its siblings will be visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the XMLDocument, although all nodes support visiting. + + You should never change the document from a callback. + + @sa XMLNode::Accept() +*/ +class TINYXML2_LIB XMLVisitor +{ +public: + virtual ~XMLVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const XMLElement& /*element*/ ) { + return true; + } + + /// Visit a declaration. + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node. + virtual bool Visit( const XMLText& /*text*/ ) { + return true; + } + /// Visit a comment node. + virtual bool Visit( const XMLComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node. + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { + return true; + } +}; + +// WARNING: must match XMLDocument::_errorNames[] +enum XMLError { + XML_SUCCESS = 0, + XML_NO_ERROR = 0, + XML_NO_ATTRIBUTE, + XML_WRONG_ATTRIBUTE_TYPE, + XML_ERROR_FILE_NOT_FOUND, + XML_ERROR_FILE_COULD_NOT_BE_OPENED, + XML_ERROR_FILE_READ_ERROR, + XML_ERROR_ELEMENT_MISMATCH, + XML_ERROR_PARSING_ELEMENT, + XML_ERROR_PARSING_ATTRIBUTE, + XML_ERROR_IDENTIFYING_TAG, + XML_ERROR_PARSING_TEXT, + XML_ERROR_PARSING_CDATA, + XML_ERROR_PARSING_COMMENT, + XML_ERROR_PARSING_DECLARATION, + XML_ERROR_PARSING_UNKNOWN, + XML_ERROR_EMPTY_DOCUMENT, + XML_ERROR_MISMATCHED_ELEMENT, + XML_ERROR_PARSING, + XML_CAN_NOT_CONVERT_TEXT, + XML_NO_TEXT_NODE, + + XML_ERROR_COUNT +}; + + +/* + Utility functionality. +*/ +class XMLUtil +{ +public: + static const char* SkipWhiteSpace( const char* p ) { + TIXMLASSERT( p ); + while( IsWhiteSpace(*p) ) { + ++p; + } + TIXMLASSERT( p ); + return p; + } + static char* SkipWhiteSpace( char* p ) { + return const_cast( SkipWhiteSpace( const_cast(p) ) ); + } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. + static bool IsWhiteSpace( char p ) { + return !IsUTF8Continuation(p) && isspace( static_cast(p) ); + } + + inline static bool IsNameStartChar( unsigned char ch ) { + if ( ch >= 128 ) { + // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() + return true; + } + if ( isalpha( ch ) ) { + return true; + } + return ch == ':' || ch == '_'; + } + + inline static bool IsNameChar( unsigned char ch ) { + return IsNameStartChar( ch ) + || isdigit( ch ) + || ch == '.' + || ch == '-'; + } + + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { + if ( p == q ) { + return true; + } + return strncmp( p, q, nChar ) == 0; + } + + inline static bool IsUTF8Continuation( char p ) { + return ( p & 0x80 ) != 0; + } + + static const char* ReadBOM( const char* p, bool* hasBOM ); + // p is the starting location, + // the UTF-8 value of the entity will be placed in value, and length filled in. + static const char* GetCharacterRef( const char* p, char* value, int* length ); + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + + // converts primitive types to strings + static void ToStr( int v, char* buffer, int bufferSize ); + static void ToStr( unsigned v, char* buffer, int bufferSize ); + static void ToStr( bool v, char* buffer, int bufferSize ); + static void ToStr( float v, char* buffer, int bufferSize ); + static void ToStr( double v, char* buffer, int bufferSize ); + + // converts strings to primitive types + static bool ToInt( const char* str, int* value ); + static bool ToUnsigned( const char* str, unsigned* value ); + static bool ToBool( const char* str, bool* value ); + static bool ToFloat( const char* str, float* value ); + static bool ToDouble( const char* str, double* value ); +}; + + +/** XMLNode is a base class for every object that is in the + XML Document Object Model (DOM), except XMLAttributes. + Nodes have siblings, a parent, and children which can + be navigated. A node is always in a XMLDocument. + The type of a XMLNode can be queried, and it can + be cast to its more defined type. + + A XMLDocument allocates memory for all its Nodes. + When the XMLDocument gets deleted, all its Nodes + will also be deleted. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + @endverbatim +*/ +class TINYXML2_LIB XMLNode +{ + friend class XMLDocument; + friend class XMLElement; +public: + + /// Get the XMLDocument that owns this XMLNode. + const XMLDocument* GetDocument() const { + TIXMLASSERT( _document ); + return _document; + } + /// Get the XMLDocument that owns this XMLNode. + XMLDocument* GetDocument() { + TIXMLASSERT( _document ); + return _document; + } + + /// Safely cast to an Element, or null. + virtual XMLElement* ToElement() { + return 0; + } + /// Safely cast to Text, or null. + virtual XMLText* ToText() { + return 0; + } + /// Safely cast to a Comment, or null. + virtual XMLComment* ToComment() { + return 0; + } + /// Safely cast to a Document, or null. + virtual XMLDocument* ToDocument() { + return 0; + } + /// Safely cast to a Declaration, or null. + virtual XMLDeclaration* ToDeclaration() { + return 0; + } + /// Safely cast to an Unknown, or null. + virtual XMLUnknown* ToUnknown() { + return 0; + } + + virtual const XMLElement* ToElement() const { + return 0; + } + virtual const XMLText* ToText() const { + return 0; + } + virtual const XMLComment* ToComment() const { + return 0; + } + virtual const XMLDocument* ToDocument() const { + return 0; + } + virtual const XMLDeclaration* ToDeclaration() const { + return 0; + } + virtual const XMLUnknown* ToUnknown() const { + return 0; + } + + /** The meaning of 'value' changes for the specific type. + @verbatim + Document: empty (NULL is returned, not an empty string) + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + const char* Value() const; + + /** Set the Value of an XML node. + @sa Value() + */ + void SetValue( const char* val, bool staticMem=false ); + + /// Get the parent of this node on the DOM. + const XMLNode* Parent() const { + return _parent; + } + + XMLNode* Parent() { + return _parent; + } + + /// Returns true if this node has no children. + bool NoChildren() const { + return !_firstChild; + } + + /// Get the first child node, or null if none exists. + const XMLNode* FirstChild() const { + return _firstChild; + } + + XMLNode* FirstChild() { + return _firstChild; + } + + /** Get the first child element, or optionally the first child + element with the specified name. + */ + const XMLElement* FirstChildElement( const char* name = 0 ) const; + + XMLElement* FirstChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->FirstChildElement( name )); + } + + /// Get the last child node, or null if none exists. + const XMLNode* LastChild() const { + return _lastChild; + } + + XMLNode* LastChild() { + return _lastChild; + } + + /** Get the last child element or optionally the last child + element with the specified name. + */ + const XMLElement* LastChildElement( const char* name = 0 ) const; + + XMLElement* LastChildElement( const char* name = 0 ) { + return const_cast(const_cast(this)->LastChildElement(name) ); + } + + /// Get the previous (left) sibling node of this node. + const XMLNode* PreviousSibling() const { + return _prev; + } + + XMLNode* PreviousSibling() { + return _prev; + } + + /// Get the previous (left) sibling element of this node, with an optionally supplied name. + const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ; + + XMLElement* PreviousSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->PreviousSiblingElement( name ) ); + } + + /// Get the next (right) sibling node of this node. + const XMLNode* NextSibling() const { + return _next; + } + + XMLNode* NextSibling() { + return _next; + } + + /// Get the next (right) sibling element of this node, with an optionally supplied name. + const XMLElement* NextSiblingElement( const char* name = 0 ) const; + + XMLElement* NextSiblingElement( const char* name = 0 ) { + return const_cast(const_cast(this)->NextSiblingElement( name ) ); + } + + /** + Add a child node as the last (right) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertEndChild( XMLNode* addThis ); + + XMLNode* LinkEndChild( XMLNode* addThis ) { + return InsertEndChild( addThis ); + } + /** + Add a child node as the first (left) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + Add a node after the specified child node. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the afterThis node + is not a child of this node, or if the node does not + belong to the same document. + */ + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); + + /** + Delete all the children of this node. + */ + void DeleteChildren(); + + /** + Delete a child of this node. + */ + void DeleteChild( XMLNode* node ); + + /** + Make a copy of this node, but not its children. + You may pass in a Document pointer that will be + the owner of the new Node. If the 'document' is + null, then the node returned will be allocated + from the current Document. (this->GetDocument()) + + Note: if called on a XMLDocument, this will return null. + */ + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + + /** + Test if 2 nodes are the same, but don't test children. + The 2 nodes do not need to be in the same Document. + + Note: if called on a XMLDocument, this will return false. + */ + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; + + /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the XMLVisitor interface. + + This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + XMLPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( XMLVisitor* visitor ) const = 0; + +protected: + XMLNode( XMLDocument* ); + virtual ~XMLNode(); + + virtual char* ParseDeep( char*, StrPair* ); + + XMLDocument* _document; + XMLNode* _parent; + mutable StrPair _value; + + XMLNode* _firstChild; + XMLNode* _lastChild; + + XMLNode* _prev; + XMLNode* _next; + +private: + MemPool* _memPool; + void Unlink( XMLNode* child ); + static void DeleteNode( XMLNode* node ); + void InsertChildPreamble( XMLNode* insertThis ) const; + + XMLNode( const XMLNode& ); // not supported + XMLNode& operator=( const XMLNode& ); // not supported +}; + + +/** XML text. + + Note that a text node can have child element nodes, for example: + @verbatim + This is bold + @endverbatim + + A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCData() and query it with CData(). +*/ +class TINYXML2_LIB XMLText : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLText* ToText() { + return this; + } + virtual const XMLText* ToText() const { + return this; + } + + /// Declare whether this should be CDATA or standard text. + void SetCData( bool isCData ) { + _isCData = isCData; + } + /// Returns true if this is a CDATA text element. + bool CData() const { + return _isCData; + } + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + virtual ~XMLText() {} + + char* ParseDeep( char*, StrPair* endTag ); + +private: + bool _isCData; + + XMLText( const XMLText& ); // not supported + XMLText& operator=( const XMLText& ); // not supported +}; + + +/** An XML Comment. */ +class TINYXML2_LIB XMLComment : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLComment* ToComment() { + return this; + } + virtual const XMLComment* ToComment() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLComment( XMLDocument* doc ); + virtual ~XMLComment(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLComment( const XMLComment& ); // not supported + XMLComment& operator=( const XMLComment& ); // not supported +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXML-2 will happily read or write files without a declaration, + however. + + The text of the declaration isn't interpreted. It is parsed + and written as a string. +*/ +class TINYXML2_LIB XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { + return this; + } + virtual const XMLDeclaration* ToDeclaration() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLDeclaration( const XMLDeclaration& ); // not supported + XMLDeclaration& operator=( const XMLDeclaration& ); // not supported +}; + + +/** Any tag that TinyXML-2 doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into XMLUnknowns. +*/ +class TINYXML2_LIB XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { + return this; + } + virtual const XMLUnknown* ToUnknown() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); + + char* ParseDeep( char*, StrPair* endTag ); + +private: + XMLUnknown( const XMLUnknown& ); // not supported + XMLUnknown& operator=( const XMLUnknown& ); // not supported +}; + + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not XMLNodes. You may only query the + Next() attribute in a list. +*/ +class TINYXML2_LIB XMLAttribute +{ + friend class XMLElement; +public: + /// The name of the attribute. + const char* Name() const; + + /// The value of the attribute. + const char* Value() const; + + /// The next attribute in the list. + const XMLAttribute* Next() const { + return _next; + } + + /** IntValue interprets the attribute as an integer, and returns the value. + If the value isn't an integer, 0 will be returned. There is no error checking; + use QueryIntValue() if you need error checking. + */ + int IntValue() const { + int i=0; + QueryIntValue( &i ); + return i; + } + /// Query as an unsigned integer. See IntValue() + unsigned UnsignedValue() const { + unsigned i=0; + QueryUnsignedValue( &i ); + return i; + } + /// Query as a boolean. See IntValue() + bool BoolValue() const { + bool b=false; + QueryBoolValue( &b ); + return b; + } + /// Query as a double. See IntValue() + double DoubleValue() const { + double d=0; + QueryDoubleValue( &d ); + return d; + } + /// Query as a float. See IntValue() + float FloatValue() const { + float f=0; + QueryFloatValue( &f ); + return f; + } + + /** QueryIntValue interprets the attribute as an integer, and returns the value + in the provided parameter. The function will return XML_NO_ERROR on success, + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. + */ + XMLError QueryIntValue( int* value ) const; + /// See QueryIntValue + XMLError QueryUnsignedValue( unsigned int* value ) const; + /// See QueryIntValue + XMLError QueryBoolValue( bool* value ) const; + /// See QueryIntValue + XMLError QueryDoubleValue( double* value ) const; + /// See QueryIntValue + XMLError QueryFloatValue( float* value ) const; + + /// Set the attribute to a string value. + void SetAttribute( const char* value ); + /// Set the attribute to value. + void SetAttribute( int value ); + /// Set the attribute to value. + void SetAttribute( unsigned value ); + /// Set the attribute to value. + void SetAttribute( bool value ); + /// Set the attribute to value. + void SetAttribute( double value ); + /// Set the attribute to value. + void SetAttribute( float value ); + +private: + enum { BUF_SIZE = 200 }; + + XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + virtual ~XMLAttribute() {} + + XMLAttribute( const XMLAttribute& ); // not supported + void operator=( const XMLAttribute& ); // not supported + void SetName( const char* name ); + + char* ParseDeep( char* p, bool processEntities ); + + mutable StrPair _name; + mutable StrPair _value; + XMLAttribute* _next; + MemPool* _memPool; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TINYXML2_LIB XMLElement : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + /// Get the name of an element (which is the Value() of the node.) + const char* Name() const { + return Value(); + } + /// Set the name of the element. + void SetName( const char* str, bool staticMem=false ) { + SetValue( str, staticMem ); + } + + virtual XMLElement* ToElement() { + return this; + } + virtual const XMLElement* ToElement() const { + return this; + } + virtual bool Accept( XMLVisitor* visitor ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none + exists. For example: + + @verbatim + const char* value = ele->Attribute( "foo" ); + @endverbatim + + The 'value' parameter is normally null. However, if specified, + the attribute will only be returned if the 'name' and 'value' + match. This allow you to write code: + + @verbatim + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); + @endverbatim + + rather than: + @verbatim + if ( ele->Attribute( "foo" ) ) { + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); + } + @endverbatim + */ + const char* Attribute( const char* name, const char* value=0 ) const; + + /** Given an attribute name, IntAttribute() returns the value + of the attribute interpreted as an integer. 0 will be + returned if there is an error. For a method with error + checking, see QueryIntAttribute() + */ + int IntAttribute( const char* name ) const { + int i=0; + QueryIntAttribute( name, &i ); + return i; + } + /// See IntAttribute() + unsigned UnsignedAttribute( const char* name ) const { + unsigned i=0; + QueryUnsignedAttribute( name, &i ); + return i; + } + /// See IntAttribute() + bool BoolAttribute( const char* name ) const { + bool b=false; + QueryBoolAttribute( name, &b ); + return b; + } + /// See IntAttribute() + double DoubleAttribute( const char* name ) const { + double d=0; + QueryDoubleAttribute( name, &d ); + return d; + } + /// See IntAttribute() + float FloatAttribute( const char* name ) const { + float f=0; + QueryFloatAttribute( name, &f ); + return f; + } + + /** Given an attribute name, QueryIntAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryIntAttribute( const char* name, int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryIntValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsignedValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryBoolAttribute( const char* name, bool* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryBoolValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryDoubleAttribute( const char* name, double* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryDoubleValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryFloatAttribute( const char* name, float* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryFloatValue( value ); + } + + + /** Given an attribute name, QueryAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. It is overloaded for the primitive types, + and is a generally more convenient replacement of + QueryIntAttribute() and related functions. + + If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + int QueryAttribute( const char* name, int* value ) const { + return QueryIntAttribute( name, value ); + } + + int QueryAttribute( const char* name, unsigned int* value ) const { + return QueryUnsignedAttribute( name, value ); + } + + int QueryAttribute( const char* name, bool* value ) const { + return QueryBoolAttribute( name, value ); + } + + int QueryAttribute( const char* name, double* value ) const { + return QueryDoubleAttribute( name, value ); + } + + int QueryAttribute( const char* name, float* value ) const { + return QueryFloatAttribute( name, value ); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, const char* value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, int value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, unsigned value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, bool value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, double value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, float value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /** + Delete an attribute. + */ + void DeleteAttribute( const char* name ); + + /// Return the first attribute in the list. + const XMLAttribute* FirstAttribute() const { + return _rootAttribute; + } + /// Query a specific attribute in the list. + const XMLAttribute* FindAttribute( const char* name ) const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the XMLText child + and accessing it directly. + + If the first child of 'this' is a XMLText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + */ + const char* GetText() const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, SetText() is limited compared to creating an XMLText child + and mutating it directly. + + If the first child of 'this' is a XMLText, SetText() sets its value to + the given string, otherwise it will create a first child that is an XMLText. + + This is a convenient method for setting the text of simple contained text: + @verbatim + This is text + fooElement->SetText( "Hullaballoo!" ); + Hullaballoo! + @endverbatim + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then it will not change "This is text", but rather prefix it with a text element: + @verbatim + Hullaballoo!This is text + @endverbatim + + For this XML: + @verbatim + + @endverbatim + SetText() will generate + @verbatim + Hullaballoo! + @endverbatim + */ + void SetText( const char* inText ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( int value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( unsigned value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( bool value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( double value ); + /// Convenience method for setting text inside an element. See SetText() for important limitations. + void SetText( float value ); + + /** + Convenience method to query the value of a child text node. This is probably best + shown by example. Given you have a document is this form: + @verbatim + + 1 + 1.4 + + @endverbatim + + The QueryIntText() and similar functions provide a safe and easier way to get to the + "value" of x and y. + + @verbatim + int x = 0; + float y = 0; // types of x and y are contrived for example + const XMLElement* xElement = pointElement->FirstChildElement( "x" ); + const XMLElement* yElement = pointElement->FirstChildElement( "y" ); + xElement->QueryIntText( &x ); + yElement->QueryFloatText( &y ); + @endverbatim + + @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted + to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. + + */ + XMLError QueryIntText( int* ival ) const; + /// See QueryIntText() + XMLError QueryUnsignedText( unsigned* uval ) const; + /// See QueryIntText() + XMLError QueryBoolText( bool* bval ) const; + /// See QueryIntText() + XMLError QueryDoubleText( double* dval ) const; + /// See QueryIntText() + XMLError QueryFloatText( float* fval ) const; + + // internal: + enum { + OPEN, // + CLOSED, // + CLOSING // + }; + int ClosingType() const { + return _closingType; + } + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + char* ParseDeep( char* p, StrPair* endTag ); + +private: + XMLElement( XMLDocument* doc ); + virtual ~XMLElement(); + XMLElement( const XMLElement& ); // not supported + void operator=( const XMLElement& ); // not supported + + XMLAttribute* FindAttribute( const char* name ) { + return const_cast(const_cast(this)->FindAttribute( name )); + } + XMLAttribute* FindOrCreateAttribute( const char* name ); + //void LinkAttribute( XMLAttribute* attrib ); + char* ParseAttributes( char* p ); + static void DeleteAttribute( XMLAttribute* attribute ); + + enum { BUF_SIZE = 200 }; + int _closingType; + // The attribute list is ordered; there is no 'lastAttribute' + // because the list needs to be scanned for dupes before adding + // a new attribute. + XMLAttribute* _rootAttribute; +}; + + +enum Whitespace { + PRESERVE_WHITESPACE, + COLLAPSE_WHITESPACE +}; + + +/** A Document binds together all the functionality. + It can be saved, loaded, and printed to the screen. + All Nodes are connected and allocated to a Document. + If the Document is deleted, all its Nodes are also deleted. +*/ +class TINYXML2_LIB XMLDocument : public XMLNode +{ + friend class XMLElement; +public: + /// constructor + XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + ~XMLDocument(); + + virtual XMLDocument* ToDocument() { + TIXMLASSERT( this == _document ); + return this; + } + virtual const XMLDocument* ToDocument() const { + TIXMLASSERT( this == _document ); + return this; + } + + /** + Parse an XML file from a character string. + Returns XML_NO_ERROR (0) on success, or + an errorID. + + You may optionally pass in the 'nBytes', which is + the number of bytes which will be parsed. If not + specified, TinyXML-2 will assume 'xml' points to a + null terminated string. + */ + XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); + + /** + Load an XML file from disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( const char* filename ); + + /** + Load an XML file from disk. You are responsible + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( FILE* ); + + /** + Save the XML file to disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( const char* filename, bool compact = false ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( FILE* fp, bool compact = false ); + + bool ProcessEntities() const { + return _processEntities; + } + Whitespace WhitespaceMode() const { + return _whitespace; + } + + /** + Returns true if this document has a leading Byte Order Mark of UTF8. + */ + bool HasBOM() const { + return _writeBOM; + } + /** Sets whether to write the BOM when writing the file. + */ + void SetBOM( bool useBOM ) { + _writeBOM = useBOM; + } + + /** Return the root element of DOM. Equivalent to FirstChildElement(). + To get the first node, use FirstChild(). + */ + XMLElement* RootElement() { + return FirstChildElement(); + } + const XMLElement* RootElement() const { + return FirstChildElement(); + } + + /** Print the Document. If the Printer is not provided, it will + print to stdout. If you provide Printer, this can print to a file: + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Or you can use a printer to print to memory: + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + @endverbatim + */ + void Print( XMLPrinter* streamer=0 ) const; + virtual bool Accept( XMLVisitor* visitor ) const; + + /** + Create a new Element associated with + this Document. The memory for the Element + is managed by the Document. + */ + XMLElement* NewElement( const char* name ); + /** + Create a new Comment associated with + this Document. The memory for the Comment + is managed by the Document. + */ + XMLComment* NewComment( const char* comment ); + /** + Create a new Text associated with + this Document. The memory for the Text + is managed by the Document. + */ + XMLText* NewText( const char* text ); + /** + Create a new Declaration associated with + this Document. The memory for the object + is managed by the Document. + + If the 'text' param is null, the standard + declaration is used.: + @verbatim + + @endverbatim + */ + XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new Unknown associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLUnknown* NewUnknown( const char* text ); + + /** + Delete a node associated with this document. + It will be unlinked from the DOM. + */ + void DeleteNode( XMLNode* node ); + + void SetError( XMLError error, const char* str1, const char* str2 ); + + /// Return true if there was an error parsing the document. + bool Error() const { + return _errorID != XML_NO_ERROR; + } + /// Return the errorID. + XMLError ErrorID() const { + return _errorID; + } + const char* ErrorName() const; + + /// Return a possibly helpful diagnostic location or string. + const char* GetErrorStr1() const { + return _errorStr1; + } + /// Return a possibly helpful secondary diagnostic location or string. + const char* GetErrorStr2() const { + return _errorStr2; + } + /// If there is an error, print it to stdout. + void PrintError() const; + + /// Clear the document, resetting it to the initial state. + void Clear(); + + // internal + char* Identify( char* p, XMLNode** node ); + + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { + return 0; + } + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { + return false; + } + +private: + XMLDocument( const XMLDocument& ); // not supported + void operator=( const XMLDocument& ); // not supported + + bool _writeBOM; + bool _processEntities; + XMLError _errorID; + Whitespace _whitespace; + const char* _errorStr1; + const char* _errorStr2; + char* _charBuffer; + + MemPoolT< sizeof(XMLElement) > _elementPool; + MemPoolT< sizeof(XMLAttribute) > _attributePool; + MemPoolT< sizeof(XMLText) > _textPool; + MemPoolT< sizeof(XMLComment) > _commentPool; + + static const char* _errorNames[XML_ERROR_COUNT]; + + void Parse(); +}; + + +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class TINYXML2_LIB XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + XMLHandle( XMLNode* node ) { + _node = node; + } + /// Create a handle from a node. + XMLHandle( XMLNode& node ) { + _node = &node; + } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) { + _node = ref._node; + } + /// Assignment + XMLHandle& operator=( const XMLHandle& ref ) { + _node = ref._node; + return *this; + } + + /// Get the first child of this handle. + XMLHandle FirstChild() { + return XMLHandle( _node ? _node->FirstChild() : 0 ); + } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + /// Get the last child of this handle. + XMLHandle LastChild() { + return XMLHandle( _node ? _node->LastChild() : 0 ); + } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { + return XMLHandle( _node ? _node->PreviousSibling() : 0 ); + } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { + return XMLHandle( _node ? _node->NextSibling() : 0 ); + } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* name = 0 ) { + return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { + return _node; + } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + XMLNode* _node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class TINYXML2_LIB XMLConstHandle +{ +public: + XMLConstHandle( const XMLNode* node ) { + _node = node; + } + XMLConstHandle( const XMLNode& node ) { + _node = &node; + } + XMLConstHandle( const XMLConstHandle& ref ) { + _node = ref._node; + } + + XMLConstHandle& operator=( const XMLConstHandle& ref ) { + _node = ref._node; + return *this; + } + + const XMLConstHandle FirstChild() const { + return XMLConstHandle( _node ? _node->FirstChild() : 0 ); + } + const XMLConstHandle FirstChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 ); + } + const XMLConstHandle LastChild() const { + return XMLConstHandle( _node ? _node->LastChild() : 0 ); + } + const XMLConstHandle LastChildElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 ); + } + const XMLConstHandle PreviousSibling() const { + return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); + } + const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 ); + } + const XMLConstHandle NextSibling() const { + return XMLConstHandle( _node ? _node->NextSibling() : 0 ); + } + const XMLConstHandle NextSiblingElement( const char* name = 0 ) const { + return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 ); + } + + + const XMLNode* ToNode() const { + return _node; + } + const XMLElement* ToElement() const { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + const XMLText* ToText() const { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + const XMLUnknown* ToUnknown() const { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + const XMLDeclaration* ToDeclaration() const { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + const XMLNode* _node; +}; + + +/** + Printing functionality. The XMLPrinter gives you more + options than the XMLDocument::Print() method. + + It can: + -# Print to memory. + -# Print to a file you provide. + -# Print XML without a XMLDocument. + + Print to Memory + + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + SomeFunction( printer.CStr() ); + @endverbatim + + Print to a File + + You provide the file pointer. + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Print without a 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. + + @verbatim + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + @endverbatim +*/ +class TINYXML2_LIB XMLPrinter : public XMLVisitor +{ +public: + /** Construct the printer. If the FILE* is specified, + this will print to the FILE. Else it will print + to memory, and the result is available in CStr(). + If 'compact' is set to true, then output is created + with only required whitespace and newlines. + */ + XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); + virtual ~XMLPrinter() {} + + /** If streaming, write the BOM and declaration. */ + void PushHeader( bool writeBOM, bool writeDeclaration ); + /** If streaming, start writing an element. + The element must be closed with CloseElement() + */ + void OpenElement( const char* name, bool compactMode=false ); + /// If streaming, add an attribute to an open element. + void PushAttribute( const char* name, const char* value ); + void PushAttribute( const char* name, int value ); + void PushAttribute( const char* name, unsigned value ); + void PushAttribute( const char* name, bool value ); + void PushAttribute( const char* name, double value ); + /// If streaming, close the Element. + virtual void CloseElement( bool compactMode=false ); + + /// Add a text node. + void PushText( const char* text, bool cdata=false ); + /// Add a text node from an integer. + void PushText( int value ); + /// Add a text node from an unsigned. + void PushText( unsigned value ); + /// Add a text node from a bool. + void PushText( bool value ); + /// Add a text node from a float. + void PushText( float value ); + /// Add a text node from a double. + void PushText( double value ); + + /// Add a comment + void PushComment( const char* comment ); + + void PushDeclaration( const char* value ); + void PushUnknown( const char* value ); + + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); + virtual bool VisitExit( const XMLElement& element ); + + virtual bool Visit( const XMLText& text ); + virtual bool Visit( const XMLComment& comment ); + virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLUnknown& unknown ); + + /** + If in print to memory mode, return a pointer to + the XML file in memory. + */ + const char* CStr() const { + return _buffer.Mem(); + } + /** + If in print to memory mode, return the size + of the XML file in memory. (Note the size returned + includes the terminating null.) + */ + int CStrSize() const { + return _buffer.Size(); + } + /** + If in print to memory mode, reset the buffer to the + beginning. + */ + void ClearBuffer() { + _buffer.Clear(); + _buffer.Push(0); + } + +protected: + virtual bool CompactMode( const XMLElement& ) { return _compactMode; } + + /** Prints out the space before an element. You may override to change + the space and tabs used. A PrintSpace() override should call Print(). + */ + virtual void PrintSpace( int depth ); + void Print( const char* format, ... ); + + void SealElementIfJustOpened(); + bool _elementJustOpened; + DynArray< const char*, 10 > _stack; + +private: + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. + + bool _firstElement; + FILE* _fp; + int _depth; + int _textDepth; + bool _processEntities; + bool _compactMode; + + enum { + ENTITY_RANGE = 64, + BUF_SIZE = 200 + }; + bool _entityFlag[ENTITY_RANGE]; + bool _restrictedEntityFlag[ENTITY_RANGE]; + + DynArray< char, 20 > _buffer; +}; + + +} // tinyxml2 + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // TINYXML2_INCLUDED diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt new file mode 100644 index 0000000..967f6e0 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,27 @@ +## ================= +## == Get subdirs == +## ================= + +SET(_curdir ${CMAKE_CURRENT_SOURCE_DIR}) +FILE(GLOB _children RELATIVE ${_curdir} ${_curdir}/*) +SET(_dirlist "") +FOREACH(_child ${_children}) + IF(IS_DIRECTORY ${_curdir}/${_child}) + LIST(APPEND _dirlist ${_child}) + ENDIF(IS_DIRECTORY ${_curdir}/${_child}) +ENDFOREACH(_child) + +## =============================== +## == Build each plugin library == +## =============================== + +FOREACH(_dir ${_dirlist}) + cpPlugins_WrapPlugins( + ${_dir} + ${prj_VERSION} ${prj_SHORT_VERSION} + cpPlugins + ${cpPlugins_LIB} ${cpExtensions_LIB} ${cpPlugins_Instances} + ) +ENDFOREACH(_dir) + +## eof - $RCSfile$ diff --git a/plugins/GenericFilters/JoinBoundingBoxes.cxx b/plugins/GenericFilters/JoinBoundingBoxes.cxx new file mode 100644 index 0000000..d3a0708 --- /dev/null +++ b/plugins/GenericFilters/JoinBoundingBoxes.cxx @@ -0,0 +1,55 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsGenericFilters::JoinBoundingBoxes:: +JoinBoundingBoxes( ) + : Superclass( ) +{ + this->_AddInput( "Input0" ); + this->_AddInput( "Input1", false ); + this->_AddInput( "Input2", false ); + this->_AddInput( "Input3", false ); + this->_AddInput( "Input4", false ); + this->_AddInput( "Input5", false ); + this->_AddOutput< cpPlugins::BoundingBox >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsGenericFilters::JoinBoundingBoxes:: +~JoinBoundingBoxes( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsGenericFilters::JoinBoundingBoxes:: +_GenerateData( ) +{ + typedef cpPlugins::DataObject _TDO; + typedef cpPlugins::BoundingBox _TBB; + _TDO* dobjs[ 5 ]; + + auto do0 = dynamic_cast< _TDO* >( this->GetInput( "Input0" ) ); + dobjs[ 0 ] = dynamic_cast< _TDO* >( this->GetInput( "Input1" ) ); + dobjs[ 1 ] = dynamic_cast< _TDO* >( this->GetInput( "Input2" ) ); + dobjs[ 2 ] = dynamic_cast< _TDO* >( this->GetInput( "Input3" ) ); + dobjs[ 3 ] = dynamic_cast< _TDO* >( this->GetInput( "Input4" ) ); + dobjs[ 4 ] = dynamic_cast< _TDO* >( this->GetInput( "Input5" ) ); + auto out = dynamic_cast< _TBB* >( this->GetOutput( "Output" ) ); + + out->SetDataObject( do0 ); + for( unsigned int d = 0; d < 5; ++d ) + { + if( dobjs[ d ] != NULL ) + { + _TBB::Pointer bb = _TBB::New( ); + bb->SetDataObject( dobjs[ d ] ); + out->Blend( bb ); + + } // fi + + } // rof +} + +// eof - $RCSfile$ diff --git a/plugins/GenericFilters/JoinBoundingBoxes.h b/plugins/GenericFilters/JoinBoundingBoxes.h new file mode 100644 index 0000000..b2cf4c1 --- /dev/null +++ b/plugins/GenericFilters/JoinBoundingBoxes.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__ +#define __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__ + +#include +#include + +namespace cpPluginsGenericFilters +{ + /** + */ + class cpPluginsGenericFilters_EXPORT JoinBoundingBoxes + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef JoinBoundingBoxes Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( JoinBoundingBoxes, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( JoinBoundingBoxes, GenericFilters ); + + protected: + JoinBoundingBoxes( ); + virtual ~JoinBoundingBoxes( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + JoinBoundingBoxes( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSGENERICFILTERS__JOINBOUNDINGBOXES__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/DataReproducer.cxx b/plugins/IO/DataReproducer.cxx new file mode 100644 index 0000000..9f4daf1 --- /dev/null +++ b/plugins/IO/DataReproducer.cxx @@ -0,0 +1,31 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsIO::DataReproducer:: +DataReproducer( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::DataObject >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::DataReproducer:: +~DataReproducer( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::DataReproducer:: +_GenerateData( ) +{ + auto i = this->m_Inputs.find( "Input" ); + auto o = this->m_Outputs.find( "Output" ); + if( i == this->m_Inputs.end( ) || o == this->m_Outputs.end( ) ) + this->_Error( "No input/output ports." ); + o->second->SetITK( i->second->GetITK< itk::LightObject >( ) ); + o->second->SetVTK( i->second->GetVTK< vtkObjectBase >( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/IO/DataReproducer.h b/plugins/IO/DataReproducer.h new file mode 100644 index 0000000..bae2979 --- /dev/null +++ b/plugins/IO/DataReproducer.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSIO__DATAREPRODUCER__H__ +#define __CPPLUGINSIO__DATAREPRODUCER__H__ + +#include +#include + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT DataReproducer + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef DataReproducer Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( DataReproducer, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( DataReproducer, IO ); + + protected: + DataReproducer( ); + virtual ~DataReproducer( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + DataReproducer( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIO__DATAREPRODUCER__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/DicomSeriesReader.cxx b/plugins/IO/DicomSeriesReader.cxx new file mode 100644 index 0000000..2c665a7 --- /dev/null +++ b/plugins/IO/DicomSeriesReader.cxx @@ -0,0 +1,95 @@ +#include +#include + +#ifdef cpPlugins_QT4 + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsIO::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" ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::DicomSeriesReaderQDialog:: +~DicomSeriesReaderQDialog( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::DicomSeriesReaderQDialog:: +setProcessObject( cpPlugins::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 cpPluginsIO::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* cpPluginsIO::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 +} + +// ------------------------------------------------------------------------- +cpPluginsIO::DicomSeriesReader:: +DicomSeriesReader( ) + : Superclass( ) +{ +} +// ------------------------------------------------------------------------- +cpPluginsIO::DicomSeriesReader:: +~DicomSeriesReader( ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/IO/DicomSeriesReader.h b/plugins/IO/DicomSeriesReader.h new file mode 100644 index 0000000..907131c --- /dev/null +++ b/plugins/IO/DicomSeriesReader.h @@ -0,0 +1,43 @@ +#ifndef __CPPLUGINSIO__DICOMSERIESREADER__H__ +#define __CPPLUGINSIO__DICOMSERIESREADER__H__ + +#include + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT DicomSeriesReader + : public ImageReader + { + cpPluginsObject; + public: + typedef DicomSeriesReader Self; + typedef ImageReader Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( DicomSeriesReader, ImageReader ); + cpPlugins_Id_Macro( DicomSeriesReader, IO ); + + public: + // Qt dialog creation + virtual QDialog* CreateQDialog( ) ITK_OVERRIDE; + + protected: + DicomSeriesReader( ); + virtual ~DicomSeriesReader( ); + + private: + // Purposely not implemented + DicomSeriesReader( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIO__DICOMSERIESREADER__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/DicomSeriesReaderQDialog.h b/plugins/IO/DicomSeriesReaderQDialog.h new file mode 100644 index 0000000..07d9dbe --- /dev/null +++ b/plugins/IO/DicomSeriesReaderQDialog.h @@ -0,0 +1,47 @@ +#ifndef __CPPLUGINSIO__DICOMSERIESREADERQDIALOG__H__ +#define __CPPLUGINSIO__DICOMSERIESREADERQDIALOG__H__ + +#include + +#ifdef cpPlugins_QT4 + +#include +#include + +namespace cpPlugins +{ + class ProcessObject; +} +namespace Ui +{ + class DicomSeriesReaderQDialog; +} + +namespace cpPluginsIO +{ + /** + */ + class DicomSeriesReaderQDialog + : public QDialog + { + Q_OBJECT; + public: + DicomSeriesReaderQDialog( QWidget* parent = 0 ); + virtual ~DicomSeriesReaderQDialog( ); + void setProcessObject( cpPlugins::ProcessObject* obj ); + + protected slots: + void _dlg_Accepted( ); + + protected: + Ui::DicomSeriesReaderQDialog* m_UI; + cpPlugins::ProcessObject* m_ProcessObject; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __CPPLUGINS__IO__DICOMSERIESREADERQDIALOG__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/DicomSeriesReaderQDialog.ui b/plugins/IO/DicomSeriesReaderQDialog.ui new file mode 100644 index 0000000..b06b180 --- /dev/null +++ b/plugins/IO/DicomSeriesReaderQDialog.ui @@ -0,0 +1,81 @@ + + + DicomSeriesReaderQDialog + + + + 0 + 0 + 511 + 335 + + + + + 511 + 335 + + + + Dialog + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + cpExtensions::QT::DicomSeriesSelectorWidget + QWidget +
cpExtensions/QT/DicomSeriesSelectorWidget.h
+ 1 +
+
+ + + + ButtonBox + accepted() + DicomSeriesReaderQDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + ButtonBox + rejected() + DicomSeriesReaderQDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/plugins/IO/ImageReader.cxx b/plugins/IO/ImageReader.cxx new file mode 100644 index 0000000..5897bdb --- /dev/null +++ b/plugins/IO/ImageReader.cxx @@ -0,0 +1,336 @@ +#include +#include +#include +#include +#include + +#ifdef cpPlugins_QT4 + +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageReaderQDialog:: +ImageReaderQDialog( QWidget* parent ) + : QFileDialog( parent ), + m_ProcessObject( NULL ) +{ + this->connect( + this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) ) + ); + this->setWindowTitle( "Open an(some) image(s)" ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageReaderQDialog:: +~ImageReaderQDialog( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::ImageReaderQDialog:: +setProcessObject( cpPlugins::ProcessObject* obj ) +{ + if( obj == NULL ) + return; + this->m_ProcessObject = obj; + auto param = this->m_ProcessObject->GetParameters( ); + auto extensions = param->GetAcceptedFileExtensions( "FileNames" ); + auto files = param->GetOpenFileNameList( "FileNames" ); + + QStringList filters; + if( extensions != "" ) + filters << extensions.c_str( ); + filters << "Any file (*)"; + this->setFileMode( QFileDialog::ExistingFiles ); + this->setNameFilters( filters ); + this->setAcceptMode( QFileDialog::AcceptOpen ); + if( files.size( ) > 0 ) + { + QFileInfo info( files[ 0 ].c_str( ) ); + this->setDirectory( info.canonicalPath( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::ImageReaderQDialog:: +_dlg_Accepted( ) +{ + if( this->m_ProcessObject != NULL ) + { + auto param = this->m_ProcessObject->GetParameters( ); + auto files = this->selectedFiles( ); + param->ClearOpenFileNameList( "FileNames" ); + for( auto fIt = files.begin( ); fIt != files.end( ); ++fIt ) + param->AddToOpenFileNameList( "FileNames", fIt->toStdString( ) ); + + } // fi +} + +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsIO::ImageReader:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + ImageReaderQDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new ImageReaderQDialog( ); + dlg->setProcessObject( this ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageReader:: +ImageReader( ) + : Superclass( ) +{ + this->_AddOutput< cpPlugins::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)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageReader:: +~ImageReader( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::ImageReader:: +_GenerateData( ) +{ + // Get filenames + auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" ); + if( fnames.size( ) >= 1 ) + { + // Guess image properties + itk::ImageIOBase::Pointer io = + itk::ImageIOFactory::CreateImageIO( + fnames[ 0 ].c_str( ), + itk::ImageIOFactory::ReadMode + ); + if( io.IsNotNull( ) ) + { + io->SetFileName( fnames[ 0 ] ); + io->ReadImageInformation( ); + if( fnames.size( ) >= 1 ) + { + switch( io->GetNumberOfDimensions( ) ) + { + case 1: this->_GD0< 1 >( io ); break; + case 2: this->_GD0< 2 >( io ); break; + case 3: this->_GD0< 3 >( io ); break; + case 4: this->_GD0< 4 >( io ); break; + default: + this->_Error( "Image dimension not supported." ); + break; + } // hctiws + + } // fi + } + 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 > +void cpPluginsIO::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( ); + + if( pt == itk::ImageIOBase::SCALAR ) + { + switch( ct ) + { + case itk::ImageIOBase::CHAR : this->_GD1< char, _Dim >( io ); break; + case itk::ImageIOBase::SHORT : this->_GD1< short, _Dim >( io ); break; + case itk::ImageIOBase::INT : this->_GD1< int, _Dim >( io ); break; + case itk::ImageIOBase::LONG : this->_GD1< long, _Dim >( io ); break; + case itk::ImageIOBase::FLOAT : this->_GD1< float, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< double, _Dim >( io ); break; + case itk::ImageIOBase::UCHAR : this->_GD1< uchar, _Dim >( io ); break; + case itk::ImageIOBase::USHORT : this->_GD1< ushort, _Dim >( io ); break; + case itk::ImageIOBase::UINT : this->_GD1< uint, _Dim >( io ); break; + case itk::ImageIOBase::ULONG : this->_GD1< ulong, _Dim >( io ); break; + default: this->_Error( "Scalar pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::RGB ) + { + switch( ct ) + { + case itk::ImageIOBase::CHAR : this->_GD1< itk::RGBPixel< char >, _Dim >( io ); break; + case itk::ImageIOBase::SHORT : this->_GD1< itk::RGBPixel< short >, _Dim >( io ); break; + case itk::ImageIOBase::INT : this->_GD1< itk::RGBPixel< int >, _Dim >( io ); break; + case itk::ImageIOBase::LONG : this->_GD1< itk::RGBPixel< long >, _Dim >( io ); break; + case itk::ImageIOBase::FLOAT : this->_GD1< itk::RGBPixel< float >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::RGBPixel< double >, _Dim >( io ); break; + case itk::ImageIOBase::UCHAR : this->_GD1< itk::RGBPixel< uchar >, _Dim >( io ); break; + case itk::ImageIOBase::USHORT : this->_GD1< itk::RGBPixel< ushort >, _Dim >( io ); break; + case itk::ImageIOBase::UINT : this->_GD1< itk::RGBPixel< uint >, _Dim >( io ); break; + case itk::ImageIOBase::ULONG : this->_GD1< itk::RGBPixel< ulong >, _Dim >( io ); break; + default: this->_Error( "RGB pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::RGBA ) + { + switch( ct ) + { + case itk::ImageIOBase::CHAR : this->_GD1< itk::RGBAPixel< char >, _Dim >( io ); break; + case itk::ImageIOBase::SHORT : this->_GD1< itk::RGBAPixel< short >, _Dim >( io ); break; + case itk::ImageIOBase::INT : this->_GD1< itk::RGBAPixel< int >, _Dim >( io ); break; + case itk::ImageIOBase::LONG : this->_GD1< itk::RGBAPixel< long >, _Dim >( io ); break; + case itk::ImageIOBase::FLOAT : this->_GD1< itk::RGBAPixel< float >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::RGBAPixel< double >, _Dim >( io ); break; + case itk::ImageIOBase::UCHAR : this->_GD1< itk::RGBAPixel< uchar >, _Dim >( io ); break; + case itk::ImageIOBase::USHORT : this->_GD1< itk::RGBAPixel< ushort >, _Dim >( io ); break; + case itk::ImageIOBase::UINT : this->_GD1< itk::RGBAPixel< uint >, _Dim >( io ); break; + case itk::ImageIOBase::ULONG : this->_GD1< itk::RGBAPixel< ulong >, _Dim >( io ); break; + default: this->_Error( "RGBA pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::COMPLEX ) + { + switch( ct ) + { + case itk::ImageIOBase::FLOAT : this->_GD1< std::complex< float >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< std::complex< double >, _Dim >( io ); break; + default: this->_Error( "Complex pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::COVARIANTVECTOR ) + { + switch( ct ) + { + case itk::ImageIOBase::FLOAT : this->_GD1< itk::CovariantVector< float, _Dim >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::CovariantVector< double, _Dim >, _Dim >( io ); break; + default: this->_Error( "CovariantVector pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::POINT ) + { + switch( ct ) + { + case itk::ImageIOBase::FLOAT : this->_GD1< itk::Point< float, _Dim >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::Point< double, _Dim >, _Dim >( io ); break; + default: this->_Error( "Point pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::VECTOR ) + { + switch( ct ) + { + case itk::ImageIOBase::FLOAT : this->_GD1< itk::Vector< float, _Dim >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::Vector< double, _Dim >, _Dim >( io ); break; + default: this->_Error( "Vector pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR ) + { + switch( ct ) + { + case itk::ImageIOBase::FLOAT : this->_GD1< itk::SymmetricSecondRankTensor< float, _Dim >, _Dim >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::SymmetricSecondRankTensor< double, _Dim >, _Dim >( io ); break; + default: this->_Error( "SymmetricSecondRankTensor pixel type not supported." ); break; + } // hctiws + } + else if( pt == itk::ImageIOBase::DIFFUSIONTENSOR3D ) + { + if( _Dim == 3 ) + { + switch( ct ) + { + case itk::ImageIOBase::FLOAT : this->_GD1< itk::DiffusionTensor3D< float >, 3 >( io ); break; + case itk::ImageIOBase::DOUBLE : this->_GD1< itk::DiffusionTensor3D< double >, 3 >( io ); break; + default: this->_Error( "DiffusionTensor3D pixel type not supported." ); break; + } // hctiws + } + else + this->_Error( "DiffusionTensor3D dimension not supported." ); + } + /* TODO + else if( pt == itk::ImageIOBase::OFFSET ) + { + } + else if( pt == itk::ImageIOBase::FIXEDARRAY ) + { + } + else if( pt == itk::ImageIOBase::MATRIX ) + { + } + */ + else + this->_Error( "Image pixel type not yet supported." ); +} + +// ------------------------------------------------------------------------- +template< class _TPixel, unsigned int _Dim > +void cpPluginsIO::ImageReader:: +_GD1( itk::ImageIOBase* io ) +{ + typedef itk::Image< _TPixel, _Dim > _TImage; + + // Get filenames + auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" ); + if( fnames.size( ) == 1 ) + { + auto f = this->_CreateITK< itk::ImageFileReader< _TImage > >( ); + f->SetFileName( fnames[ 0 ] ); + f->SetImageIO( io ); + try + { + f->Update( ); + this->GetOutput( "Output" )->SetITK( f->GetOutput( ) ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + } + } + else // if( fnames.size( ) > 1 ) + { + auto f = this->_CreateITK< itk::ImageSeriesReader< _TImage > >( ); + for( auto i = fnames.begin( ); i != fnames.end( ); ++i ) + f->AddFileName( *i ); + f->SetImageIO( io ); + try + { + f->Update( ); + this->GetOutput( "Output" )->SetITK( f->GetOutput( ) ); + } + catch( itk::ExceptionObject& err ) + { + this->_Error( err.GetDescription( ) ); + } + + } // fi +} + +// eof - $RCSfile$ diff --git a/plugins/IO/ImageReader.h b/plugins/IO/ImageReader.h new file mode 100644 index 0000000..6b2392a --- /dev/null +++ b/plugins/IO/ImageReader.h @@ -0,0 +1,57 @@ +#ifndef __CPPLUGINSIO__IMAGEREADER__H__ +#define __CPPLUGINSIO__IMAGEREADER__H__ + +#include +#include + +namespace itk +{ + class ImageIOBase; +} + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT ImageReader + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef ImageReader Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageReader, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( ImageReader, IO ); + + public: + // Qt dialog creation + virtual QDialog* CreateQDialog( ) ITK_OVERRIDE; + + protected: + ImageReader( ); + virtual ~ImageReader( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< unsigned int _Dim > + inline void _GD0( itk::ImageIOBase* io ); + + template< class _TPixel, unsigned int _Dim > + inline void _GD1( itk::ImageIOBase* io ); + + private: + // Purposely not implemented + ImageReader( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINS__IO__IMAGEREADER__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/ImageReaderQDialog.h b/plugins/IO/ImageReaderQDialog.h new file mode 100644 index 0000000..8fdd960 --- /dev/null +++ b/plugins/IO/ImageReaderQDialog.h @@ -0,0 +1,41 @@ +#ifndef __CPPLUGINSIO__IMAGEREADERQDIALOG__H__ +#define __CPPLUGINSIO__IMAGEREADERQDIALOG__H__ + +#include + +#ifdef cpPlugins_QT4 + +#include + +namespace cpPlugins +{ + class ProcessObject; +} + +namespace cpPluginsIO +{ + /** + */ + class ImageReaderQDialog + : public QFileDialog + { + Q_OBJECT; + public: + ImageReaderQDialog( QWidget* parent = 0 ); + virtual ~ImageReaderQDialog( ); + void setProcessObject( cpPlugins::ProcessObject* obj ); + + protected slots: + void _dlg_Accepted( ); + + protected: + cpPlugins::ProcessObject* m_ProcessObject; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __CPPLUGINS__IO__IMAGEREADERQDIALOG__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/ImageWriter.cxx b/plugins/IO/ImageWriter.cxx new file mode 100644 index 0000000..a8b30b4 --- /dev/null +++ b/plugins/IO/ImageWriter.cxx @@ -0,0 +1,159 @@ +#include +#include +#include +#include + +#ifdef cpPlugins_QT4 + +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageWriterQDialog:: +ImageWriterQDialog( QWidget* parent ) + : QFileDialog( parent ), + m_ProcessObject( NULL ) +{ + this->connect( + this, SIGNAL( accepted( ) ), this, SLOT( _dlg_Accepted( ) ) + ); + this->setWindowTitle( "Save an image" ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageWriterQDialog:: +~ImageWriterQDialog( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::ImageWriterQDialog:: +setProcessObject( cpPlugins::ProcessObject* obj ) +{ + if( obj == NULL ) + return; + this->m_ProcessObject = obj; + auto parameters = this->m_ProcessObject->GetParameters( ); + auto extensions = parameters->GetAcceptedFileExtensions( "FileName" ); + auto filename = parameters->GetSaveFileName( "FileName" ); + + QStringList filters; + if( extensions != "" ) + filters << extensions.c_str( ); + filters << "Any file (*)"; + this->setFileMode( QFileDialog::AnyFile ); + this->setNameFilters( filters ); + this->setAcceptMode( QFileDialog::AcceptSave ); + if( filename != "" ) + { + QFileInfo info( filename.c_str( ) ); + if( info.exists( ) ) + this->setDirectory( info.canonicalPath( ) ); + else + this->setDirectory( "." ); + } + else + this->setDirectory( "." ); +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::ImageWriterQDialog:: +_dlg_Accepted( ) +{ + if( this->m_ProcessObject != NULL ) + { + auto param = this->m_ProcessObject->GetParameters( ); + auto files = this->selectedFiles( ); + if( files.size( ) > 0 ) + param->SetSaveFileName( "FileName", files.begin( )->toStdString( ) ); + + } // fi +} + +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +QDialog* cpPluginsIO::ImageWriter:: +CreateQDialog( ) +{ +#ifdef cpPlugins_QT4 + ImageWriterQDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new ImageWriterQDialog( ); + dlg->setProcessObject( this ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageWriter:: +ImageWriter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->m_Parameters.Clear( ); + this->m_Parameters.ConfigureAsSaveFileName( "FileName" ); + this->m_Parameters.SetAcceptedFileExtensions( + "FileName", + "Image files (*.bmp *.png *.jpg *.jpeg *.dcm *.mhd *.nhdr *.nrrd *.tiff)" + ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::ImageWriter:: +~ImageWriter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsIO::ImageWriter:: +_GenerateData( ) +{ + auto image = this->GetInputData( "Input" ); + cpPlugins_Image_Demangle_Dim( _GD0, image, 1 ); + else cpPlugins_Image_Demangle_Dim( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Dim( _GD0, image, 3 ); + else cpPlugins_Image_Demangle_Dim( _GD0, image, 4 ); + else + this->_Error( "Invalid input itk::ImageBase" ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsIO::ImageWriter:: +_GD0( _TImage* image ) +{ + static const unsigned int D = _TImage::ImageDimension; + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD1, image, D ); + else cpPlugins_Image_Demangle_ColorPixel_AllScalars( _GD1, image, RGB, D ); + else cpPlugins_Image_Demangle_ColorPixel_AllScalars( _GD1, image, RGBA, D ); + else + this->_Error( "Invalid pixel type" ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsIO::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/IO/ImageWriter.h b/plugins/IO/ImageWriter.h new file mode 100644 index 0000000..a5c0061 --- /dev/null +++ b/plugins/IO/ImageWriter.h @@ -0,0 +1,57 @@ +#ifndef __CPPLUGINSIO__IMAGEWRITER__H__ +#define __CPPLUGINSIO__IMAGEWRITER__H__ + +#include +#include + +namespace itk +{ + class ImageIOBase; +} + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT ImageWriter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef ImageWriter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageWriter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( ImageWriter, IO ); + + public: + // Qt dialog creation + virtual QDialog* CreateQDialog( ) ITK_OVERRIDE; + + protected: + ImageWriter( ); + virtual ~ImageWriter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage > + inline void _GD1( _TImage* image ); + + private: + // Purposely not implemented + ImageWriter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINS__IO__IMAGEWRITER__H__ + +// eof - $RCSfile$ diff --git a/plugins/IO/ImageWriterQDialog.h b/plugins/IO/ImageWriterQDialog.h new file mode 100644 index 0000000..64147bd --- /dev/null +++ b/plugins/IO/ImageWriterQDialog.h @@ -0,0 +1,41 @@ +#ifndef __CPPLUGINSIO__IMAGEWRITERQDIALOG__H__ +#define __CPPLUGINSIO__IMAGEWRITERQDIALOG__H__ + +#include + +#ifdef cpPlugins_QT4 + +#include + +namespace cpPlugins +{ + class ProcessObject; +} + +namespace cpPluginsIO +{ + /** + */ + class ImageWriterQDialog + : public QFileDialog + { + Q_OBJECT; + public: + ImageWriterQDialog( QWidget* parent = 0 ); + virtual ~ImageWriterQDialog( ); + void setProcessObject( cpPlugins::ProcessObject* obj ); + + protected slots: + void _dlg_Accepted( ); + + protected: + cpPlugins::ProcessObject* m_ProcessObject; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __CPPLUGINS__IO__IMAGEWRITERQDIALOG__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/AndImageFilter.cxx b/plugins/ImageFilters/AndImageFilter.cxx new file mode 100644 index 0000000..77a6eee --- /dev/null +++ b/plugins/ImageFilters/AndImageFilter.cxx @@ -0,0 +1,64 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::AndImageFilter:: +AndImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input0" ); + this->_AddInput( "Input1" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::AndImageFilter:: +~AndImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::AndImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input0" ); + cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 1 ); + else cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 3 ); + else cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 4 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 1 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 3 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 4 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::AndImageFilter:: +_GD0( _TImage* image0 ) +{ + typedef itk::AndImageFilter< _TImage, _TImage > _TFilter; + if( image0 != NULL ) + { + auto image1 = this->GetInputData< _TImage >( "Input1" ); + if( image1 != NULL ) + { + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( 0, image0 ); + filter->SetInput( 1, image1 ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); + } + else + this->_Error( "No valid second input image." ); + } + else + this->_Error( "No valid first input image." ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/AndImageFilter.h b/plugins/ImageFilters/AndImageFilter.h new file mode 100644 index 0000000..b559435 --- /dev/null +++ b/plugins/ImageFilters/AndImageFilter.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__ANDIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__ANDIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT AndImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef AndImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( AndImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( AndImageFilter, ImageFilters ); + + protected: + AndImageFilter( ); + virtual ~AndImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image0 ); + + private: + // Purposely not implemented + AndImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__ANDIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/BinaryContourImageFilter.cxx b/plugins/ImageFilters/BinaryContourImageFilter.cxx new file mode 100644 index 0000000..e49d810 --- /dev/null +++ b/plugins/ImageFilters/BinaryContourImageFilter.cxx @@ -0,0 +1,86 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryContourImageFilter:: +BinaryContourImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsBool( "FullyConnected" ); + this->m_Parameters.ConfigureAsReal( "BackgroundValue" ); + this->m_Parameters.ConfigureAsReal( "ForegroundValue" ); + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "OutputResolution", choices ); + + this->m_Parameters.SetBool( "FullyConnected", false ); + this->m_Parameters.SetReal( "BackgroundValue", 0 ); + this->m_Parameters.SetReal( "ForegroundValue", 1 ); + this->m_Parameters.SetSelectedChoice( "OutputResolution", "float" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryContourImageFilter:: +~BinaryContourImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::BinaryContourImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::BinaryContourImageFilter:: +_GD0( _TImage* image ) +{ + static const unsigned int D = _TImage::ImageDimension; + if( image != NULL ) + { + std::string out_res = + this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( out_res == "float" ) + this->_GD1< _TImage, itk::Image< float, D > >( image ); + else // if( out_res == "double" ) + this->_GD1< _TImage, itk::Image< double, D > >( image ); + } + else + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TContourImage > +void cpPluginsImageFilters::BinaryContourImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::BinaryContourImageFilter< _TImage, _TContourImage > _F; + + // Get parameters + bool fc = this->m_Parameters.GetBool( "FullyConnected" ); + double bv = this->m_Parameters.GetReal( "BackgroundValue" ); + double fv = this->m_Parameters.GetReal( "ForegroundValue" ); + + // Configure filter + _F* filter = this->_CreateITK< _F >( ); + filter->SetInput( image ); + filter->SetFullyConnected( fc ); + filter->SetBackgroundValue( bv ); + filter->SetForegroundValue( fv ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/BinaryContourImageFilter.h b/plugins/ImageFilters/BinaryContourImageFilter.h new file mode 100644 index 0000000..0a1c0d6 --- /dev/null +++ b/plugins/ImageFilters/BinaryContourImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__BINARYCONTOURIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__BINARYCONTOURIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT BinaryContourImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef BinaryContourImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BinaryContourImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( BinaryContourImageFilter, ImageFilters ); + + protected: + BinaryContourImageFilter( ); + virtual ~BinaryContourImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TContourImage > + inline void _GD1( _TImage* image ); + + private: + // Purposely not implemented + BinaryContourImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__BINARYCONTOURIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/BinaryDilateParaImageFilter.cxx b/plugins/ImageFilters/BinaryDilateParaImageFilter.cxx new file mode 100644 index 0000000..ec6336b --- /dev/null +++ b/plugins/ImageFilters/BinaryDilateParaImageFilter.cxx @@ -0,0 +1,53 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryDilateParaImageFilter:: +BinaryDilateParaImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Radius" ); + this->m_Parameters.ConfigureAsBool( "Circular" ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing" ); + + this->m_Parameters.SetReal( "Radius", 3 ); + this->m_Parameters.SetBool( "Circular", true ); + this->m_Parameters.SetBool( "UseImageSpacing", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryDilateParaImageFilter:: +~BinaryDilateParaImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::BinaryDilateParaImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage > +void cpPluginsImageFilters::BinaryDilateParaImageFilter:: +_GD0( _TInputImage* input_image ) +{ + typedef itk::BinaryDilateParaImageFilter< _TInputImage > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( input_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/ImageFilters/BinaryDilateParaImageFilter.h b/plugins/ImageFilters/BinaryDilateParaImageFilter.h new file mode 100644 index 0000000..2882ad4 --- /dev/null +++ b/plugins/ImageFilters/BinaryDilateParaImageFilter.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__BINARYDILATEPARAIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__BINARYDILATEPARAIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT BinaryDilateParaImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef BinaryDilateParaImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BinaryDilateParaImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( BinaryDilateParaImageFilter, ImageFilters ); + + protected: + BinaryDilateParaImageFilter( ); + virtual ~BinaryDilateParaImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TInputImage > + inline void _GD0( _TInputImage* input_image ); + + private: + // Purposely not implemented + BinaryDilateParaImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__BINARYDILATEPARAIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/BinaryErodeParaImageFilter.cxx b/plugins/ImageFilters/BinaryErodeParaImageFilter.cxx new file mode 100644 index 0000000..9006e0b --- /dev/null +++ b/plugins/ImageFilters/BinaryErodeParaImageFilter.cxx @@ -0,0 +1,53 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryErodeParaImageFilter:: +BinaryErodeParaImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Radius" ); + this->m_Parameters.ConfigureAsBool( "Circular" ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing" ); + + this->m_Parameters.SetReal( "Radius", 3 ); + this->m_Parameters.SetBool( "Circular", true ); + this->m_Parameters.SetBool( "UseImageSpacing", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryErodeParaImageFilter:: +~BinaryErodeParaImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::BinaryErodeParaImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage > +void cpPluginsImageFilters::BinaryErodeParaImageFilter:: +_GD0( _TInputImage* input_image ) +{ + typedef itk::BinaryErodeParaImageFilter< _TInputImage > _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( input_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/ImageFilters/BinaryErodeParaImageFilter.h b/plugins/ImageFilters/BinaryErodeParaImageFilter.h new file mode 100644 index 0000000..b7d1e01 --- /dev/null +++ b/plugins/ImageFilters/BinaryErodeParaImageFilter.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__BINARYERODEPARAIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__BINARYERODEPARAIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT BinaryErodeParaImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef BinaryErodeParaImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BinaryErodeParaImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( BinaryErodeParaImageFilter, ImageFilters ); + + protected: + BinaryErodeParaImageFilter( ); + virtual ~BinaryErodeParaImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TInputImage > + inline void _GD0( _TInputImage* input_image ); + + private: + // Purposely not implemented + BinaryErodeParaImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__BINARYERODEPARAIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/BinaryThresholdImageFilter.cxx b/plugins/ImageFilters/BinaryThresholdImageFilter.cxx new file mode 100644 index 0000000..0374b5b --- /dev/null +++ b/plugins/ImageFilters/BinaryThresholdImageFilter.cxx @@ -0,0 +1,80 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryThresholdImageFilter:: +BinaryThresholdImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "LowerThresholdValue" ); + this->m_Parameters.ConfigureAsReal( "UpperThresholdValue" ); + this->m_Parameters.ConfigureAsUint( "InsideValue" ); + this->m_Parameters.ConfigureAsUint( "OutsideValue" ); + + this->m_Parameters.SetReal( "LowerThresholdValue", 0 ); + this->m_Parameters.SetReal( "UpperThresholdValue", 10000 ); + this->m_Parameters.SetReal( "InsideValue", 1 ); + this->m_Parameters.SetReal( "OutsideValue", 0 ); + this->m_Parameters.SetSelectedChoice( "OutputResolution", "unsigned char" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryThresholdImageFilter:: +~BinaryThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::BinaryThresholdImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::BinaryThresholdImageFilter:: +_GD0( _TImage* image ) +{ + if( image != NULL ) + this->_GD1< _TImage, unsigned char >( image ); + else + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TBinaryPixel > +void cpPluginsImageFilters::BinaryThresholdImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::Image< _TBinaryPixel, _TImage::ImageDimension > _TBinaryImage; + typedef itk::BinaryThresholdImageFilter< _TImage, _TBinaryImage > _F; + typedef typename _TImage::PixelType _TP; + + // Get parameters + _TP lower_val = _TP( this->m_Parameters.GetReal( "LowerThresholdValue" ) ); + _TP upper_val = _TP( this->m_Parameters.GetReal( "UpperThresholdValue" ) ); + _TBinaryPixel in_val = _TBinaryPixel( this->m_Parameters.GetReal( "InsideValue" ) ); + _TBinaryPixel out_val = _TBinaryPixel( this->m_Parameters.GetReal( "OutsideValue" ) ); + + // Configure filter + _F* filter = this->_CreateITK< _F >( ); + filter->SetInput( image ); + filter->SetLowerThreshold( lower_val ); + filter->SetUpperThreshold( upper_val ); + filter->SetInsideValue( in_val ); + filter->SetOutsideValue( out_val ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/BinaryThresholdImageFilter.h b/plugins/ImageFilters/BinaryThresholdImageFilter.h new file mode 100644 index 0000000..f09fd29 --- /dev/null +++ b/plugins/ImageFilters/BinaryThresholdImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__BINARYTHRESHOLDIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__BINARYTHRESHOLDIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT BinaryThresholdImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef BinaryThresholdImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( BinaryThresholdImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( BinaryThresholdImageFilter, ImageFilters ); + + protected: + BinaryThresholdImageFilter( ); + virtual ~BinaryThresholdImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TBinaryPixel > + inline void _GD1( _TImage* image ); + + private: + // Purposely not implemented + BinaryThresholdImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__BINARYTHRESHOLDIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/CastImageFilter.cxx b/plugins/ImageFilters/CastImageFilter.cxx new file mode 100644 index 0000000..0cf15cc --- /dev/null +++ b/plugins/ImageFilters/CastImageFilter.cxx @@ -0,0 +1,93 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::CastImageFilter:: +CastImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + std::vector< std::string > choices; + choices.push_back( "char" ); + choices.push_back( "short" ); + choices.push_back( "int" ); + choices.push_back( "long" ); + choices.push_back( "uchar" ); + choices.push_back( "ushort" ); + choices.push_back( "uint" ); + choices.push_back( "ulong" ); + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "CastType", choices ); + this->m_Parameters.SetSelectedChoice( "CastType", "uchar" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::CastImageFilter:: +~CastImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::CastImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 1 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 4 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage > +void cpPluginsImageFilters::CastImageFilter:: +_GD0( _TInputImage* image ) +{ + auto out = this->m_Parameters.GetSelectedChoice( "CastType" ); + if( out == "char" ) + this->_GD1< _TInputImage, char >( image ); + else if( out == "short" ) + this->_GD1< _TInputImage, short >( image ); + else if( out == "int" ) + this->_GD1< _TInputImage, int >( image ); + else if( out == "long" ) + this->_GD1< _TInputImage, long >( image ); + else if( out == "float" ) + this->_GD1< _TInputImage, float >( image ); + else if( out == "double" ) + this->_GD1< _TInputImage, double >( image ); + else if( out == "uchar" ) + this->_GD1< _TInputImage, unsigned char >( image ); + else if( out == "ushort" ) + this->_GD1< _TInputImage, unsigned short >( image ); + else if( out == "uint" ) + this->_GD1< _TInputImage, unsigned int >( image ); + else if( out == "ulong" ) + this->_GD1< _TInputImage, unsigned long >( image ); + else + this->_Error( "Invalid output casting type." ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputPixel > +void cpPluginsImageFilters::CastImageFilter:: +_GD1( _TInputImage* image ) +{ + typedef itk::Image< _TOutputPixel, _TInputImage::ImageDimension > _TOutputImage; + typedef itk::CastImageFilter< _TInputImage, _TOutputImage > _TFilter; + + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/CastImageFilter.h b/plugins/ImageFilters/CastImageFilter.h new file mode 100644 index 0000000..de1d87b --- /dev/null +++ b/plugins/ImageFilters/CastImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__CASTIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__CASTIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT CastImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef CastImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( CastImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( CastImageFilter, ImageFilters ); + + protected: + CastImageFilter( ); + virtual ~CastImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TInputImage > + inline void _GD0( _TInputImage* image ); + + template< class _TInputImage, class _TOutputPixel > + inline void _GD1( _TInputImage* image ); + + private: + // Purposely not implemented + CastImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__CASTIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/GaussianDensityImageFilter.cxx b/plugins/ImageFilters/GaussianDensityImageFilter.cxx new file mode 100644 index 0000000..9cfc618 --- /dev/null +++ b/plugins/ImageFilters/GaussianDensityImageFilter.cxx @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::GaussianDensityImageFilter:: +GaussianDensityImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Image" ); + this->_AddInput( "Estimator" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + /* TODO + this->m_Parameters.ConfigureAsReal( "LowerThresholdValue" ); + this->m_Parameters.ConfigureAsReal( "UpperThresholdValue" ); + this->m_Parameters.ConfigureAsUint( "InsideValue" ); + this->m_Parameters.ConfigureAsUint( "OutsideValue" ); + + this->m_Parameters.SetReal( "LowerThresholdValue", 0 ); + this->m_Parameters.SetReal( "UpperThresholdValue", 10000 ); + this->m_Parameters.SetReal( "InsideValue", 1 ); + this->m_Parameters.SetReal( "OutsideValue", 0 ); + this->m_Parameters.SetSelectedChoice( "OutputResolution", "unsigned char" ); + */ +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::GaussianDensityImageFilter:: +~GaussianDensityImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::GaussianDensityImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Image" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::GaussianDensityImageFilter:: +_GD0( _TImage* image ) +{ + static const unsigned int Dim = 1; + typedef cpExtensions::Algorithms::IterativeGaussianModelEstimator< float, Dim > _TFloatEst; + typedef cpExtensions::Algorithms::IterativeGaussianModelEstimator< double, Dim > _TDoubleEst; + + auto float_est = this->GetInputData< _TFloatEst >( "Estimator" ); + auto double_est = this->GetInputData< _TDoubleEst >( "Estimator" ); + if( float_est != NULL ) + this->_GD1( image, float_est ); + else if( double_est != NULL ) + this->_GD1( image, double_est ); + else + this->_Error( "Invalid gaussian model estimator." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TEstimator > +void cpPluginsImageFilters::GaussianDensityImageFilter:: +_GD1( _TImage* image, _TEstimator* estimator ) +{ + typedef + cpExtensions::Algorithms::GaussianDensityImageFilter< _TImage, _TEstimator > + _TFilter; + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetEstimator( estimator ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/GaussianDensityImageFilter.h b/plugins/ImageFilters/GaussianDensityImageFilter.h new file mode 100644 index 0000000..51d94fd --- /dev/null +++ b/plugins/ImageFilters/GaussianDensityImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__GAUSSIANDENSITYIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__GAUSSIANDENSITYIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT GaussianDensityImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef GaussianDensityImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( GaussianDensityImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( GaussianDensityImageFilter, ImageFilters ); + + protected: + GaussianDensityImageFilter( ); + virtual ~GaussianDensityImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TEstimator > + inline void _GD1( _TImage* image, _TEstimator* estimator ); + + private: + // Purposely not implemented + GaussianDensityImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__GAUSSIANDENSITYIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/MultiScaleGaussianImageFilter.cxx b/plugins/ImageFilters/MultiScaleGaussianImageFilter.cxx new file mode 100644 index 0000000..612f447 --- /dev/null +++ b/plugins/ImageFilters/MultiScaleGaussianImageFilter.cxx @@ -0,0 +1,80 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::MultiScaleGaussianImageFilter:: +MultiScaleGaussianImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsRealList( "Sigmas" ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "ScalarType", choices ); + this->m_Parameters.SetSelectedChoice( "ScalarType", "float" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::MultiScaleGaussianImageFilter:: +~MultiScaleGaussianImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::MultiScaleGaussianImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::MultiScaleGaussianImageFilter:: +_GD0( _TImage* image ) +{ + if( image != NULL ) + { + auto choice = this->m_Parameters.GetSelectedChoice( "ScalarType" ); + if ( choice == "float" ) this->_GD1< _TImage, float >( image ); + else if( choice == "double" ) this->_GD1< _TImage, double >( image ); + else this->_Error( "No valid scalar type." ); + } + else + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsImageFilters::MultiScaleGaussianImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::CovariantVector< _TScalar, _TImage::ImageDimension > _TVector; + typedef itk::Image< _TVector, _TImage::ImageDimension > _TGradient; + typedef + cpExtensions::Algorithms::MultiScaleGaussianImageFilter< _TImage, _TGradient > + _TFilter; + + auto sigmas = this->m_Parameters.GetRealList( "Sigmas" ); + if( sigmas.size( ) == 0 ) + this->_Error( "No given sigmas." ); + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + for( auto sIt = sigmas.begin( ); sIt != sigmas.end( ); ++sIt ) + filter->AddScale( *sIt ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/MultiScaleGaussianImageFilter.h b/plugins/ImageFilters/MultiScaleGaussianImageFilter.h new file mode 100644 index 0000000..3ee659e --- /dev/null +++ b/plugins/ImageFilters/MultiScaleGaussianImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__MULTISCALEGAUSSIANIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__MULTISCALEGAUSSIANIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT MultiScaleGaussianImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef MultiScaleGaussianImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( MultiScaleGaussianImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( MultiScaleGaussianImageFilter, ImageFilters ); + + protected: + MultiScaleGaussianImageFilter( ); + virtual ~MultiScaleGaussianImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + + private: + // Purposely not implemented + MultiScaleGaussianImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__MULTISCALEGAUSSIANIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/OrImageFilter.cxx b/plugins/ImageFilters/OrImageFilter.cxx new file mode 100644 index 0000000..b5b3884 --- /dev/null +++ b/plugins/ImageFilters/OrImageFilter.cxx @@ -0,0 +1,64 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::OrImageFilter:: +OrImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input0" ); + this->_AddInput( "Input1" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::OrImageFilter:: +~OrImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::OrImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input0" ); + cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 1 ); + else cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 3 ); + else cpPlugins_Image_Demangle_Pixel_AllInts ( _GD0, image, 4 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 1 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 3 ); + else cpPlugins_Image_Demangle_Pixel_AllUInts( _GD0, image, 4 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::OrImageFilter:: +_GD0( _TImage* image0 ) +{ + typedef itk::OrImageFilter< _TImage, _TImage > _TFilter; + if( image0 != NULL ) + { + auto image1 = this->GetInputData< _TImage >( "Input1" ); + if( image1 != NULL ) + { + // Configure filter + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( 0, image0 ); + filter->SetInput( 1, image1 ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); + } + else + this->_Error( "No valid second input image." ); + } + else + this->_Error( "No valid first input image." ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/OrImageFilter.h b/plugins/ImageFilters/OrImageFilter.h new file mode 100644 index 0000000..87965c3 --- /dev/null +++ b/plugins/ImageFilters/OrImageFilter.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__ORIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__ORIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT OrImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef OrImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( OrImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( OrImageFilter, ImageFilters ); + + protected: + OrImageFilter( ); + virtual ~OrImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image0 ); + + private: + // Purposely not implemented + OrImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__ORIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/RegionOfInterestImageFilter.cxx b/plugins/ImageFilters/RegionOfInterestImageFilter.cxx new file mode 100644 index 0000000..69ee700 --- /dev/null +++ b/plugins/ImageFilters/RegionOfInterestImageFilter.cxx @@ -0,0 +1,72 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::RegionOfInterestImageFilter:: +RegionOfInterestImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + this->m_Parameters.ConfigureAsBool( "AutomaticRegion" ); + this->m_Parameters.ConfigureAsReal( "BackgroundValue" ); + this->m_Parameters.SetBool( "AutomaticRegion", true ); + this->m_Parameters.SetReal( "BackgroundValue", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::RegionOfInterestImageFilter:: +~RegionOfInterestImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::RegionOfInterestImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage > +void cpPluginsImageFilters::RegionOfInterestImageFilter:: +_GD0( _TInputImage* image ) +{ + typedef + itk::RegionOfInterestImageFilter< _TInputImage, _TInputImage > + _TFilter; + typedef + cpExtensions::Algorithms::RegionOfInterestImageCalculator< _TInputImage > + _TCalculator; + + if( this->m_Parameters.GetBool( "AutomaticRegion" ) ) + { + typename _TCalculator::Pointer calculator = _TCalculator::New( ); + calculator->SetImage( image ); + calculator->Compute( ); + + auto minidx = calculator->GetMinimum( ); + auto maxidx = calculator->GetMaximum( ); + typename _TInputImage::SizeType size; + for( unsigned int d = 0; d < _TInputImage::ImageDimension; ++d ) + size[ d ] = maxidx[ d ] - minidx[ d ] + 1; + + typename _TInputImage::RegionType roi; + roi.SetIndex( minidx ); + roi.SetSize( size ); + + auto filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + filter->SetRegionOfInterest( roi ); + filter->Update( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); + } + else + this->_Error( "Manual region not yet implemented." ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/RegionOfInterestImageFilter.h b/plugins/ImageFilters/RegionOfInterestImageFilter.h new file mode 100644 index 0000000..3cd60f4 --- /dev/null +++ b/plugins/ImageFilters/RegionOfInterestImageFilter.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__REGIONOFINTERESTIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__REGIONOFINTERESTIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT RegionOfInterestImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef RegionOfInterestImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( RegionOfInterestImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( RegionOfInterestImageFilter, ImageFilters ); + + protected: + RegionOfInterestImageFilter( ); + virtual ~RegionOfInterestImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TInputImage > + inline void _GD0( _TInputImage* image ); + + private: + // Purposely not implemented + RegionOfInterestImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__REGIONOFINTERESTIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/ResampleImageFilter.cxx b/plugins/ImageFilters/ResampleImageFilter.cxx new file mode 100644 index 0000000..34eeea4 --- /dev/null +++ b/plugins/ImageFilters/ResampleImageFilter.cxx @@ -0,0 +1,73 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::ResampleImageFilter:: +ResampleImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "ScalarType", choices ); + this->m_Parameters.SetSelectedChoice( "ScalarType", "float" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::ResampleImageFilter:: +~ResampleImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::ResampleImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::ResampleImageFilter:: +_GD0( _TImage* image ) +{ + if( image != NULL ) + { + auto choice = this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( choice == "float" ) + this->_GD1< _TImage, float >( image ); + else if( choice == "double" ) + this->_GD1< _TImage, double >( image ); + else this->_Error( "No valid scalar type." ); + } + else + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TScalar > +void cpPluginsImageFilters::ResampleImageFilter:: +_GD1( _TImage* image ) +{ + typedef + itk::ResampleImageFilter< _TImage, _TImage, _TScalar, _TScalar > + _TFilter; + + if( image == NULL ) + this->_Error( "No valid input image." ); + + // Configure filter + _TFilter* filter = this->_CreateITK< _TFilter >( ); + filter->SetInput( image ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/ResampleImageFilter.h b/plugins/ImageFilters/ResampleImageFilter.h new file mode 100644 index 0000000..7dec074 --- /dev/null +++ b/plugins/ImageFilters/ResampleImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__RESAMPLEIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__RESAMPLEIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT ResampleImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef ResampleImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( ResampleImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( ResampleImageFilter, ImageFilters ); + + protected: + ResampleImageFilter( ); + virtual ~ResampleImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TScalar > + inline void _GD1( _TImage* image ); + + private: + // Purposely not implemented + ResampleImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__RESAMPLEIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.cxx b/plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.cxx new file mode 100644 index 0000000..57aefa0 --- /dev/null +++ b/plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.cxx @@ -0,0 +1,93 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +SignedMaurerDistanceMapImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "BackgroundValue" ); + this->m_Parameters.ConfigureAsBool( "InsideIsPositive" ); + this->m_Parameters.ConfigureAsBool( "SquaredDistance" ); + this->m_Parameters.ConfigureAsBool( "UseImageSpacing" ); + + std::vector< std::string > choices; + choices.push_back( "float" ); + choices.push_back( "double" ); + this->m_Parameters.ConfigureAsChoices( "OutputResolution", choices ); + + this->m_Parameters.SetReal( "BackgroundValue", 0 ); + this->m_Parameters.SetBool( "InsideIsPositive", true ); + this->m_Parameters.SetBool( "SquaredDistance", false ); + this->m_Parameters.SetBool( "UseImageSpacing", true ); + this->m_Parameters.SetSelectedChoice( "OutputResolution", "float" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +~SignedMaurerDistanceMapImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +_GD0( _TImage* image ) +{ + static const unsigned int D = _TImage::ImageDimension; + if( image != NULL ) + { + std::string out_res = + this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( out_res == "float" ) + this->_GD1< _TImage, itk::Image< float, D > >( image ); + else if( out_res == "double" ) + this->_GD1< _TImage, itk::Image< double, D > >( image ); + else + this->_Error( "Output resolution not supported." ); + } + else + this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage, class _TDMap > +void cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +_GD1( _TImage* image ) +{ + typedef itk::SignedMaurerDistanceMapImageFilter< _TImage, _TDMap > _F; + + // Get parameters + double back_value = this->m_Parameters.GetReal( "BackgroundValue" ); + bool pos_inside = this->m_Parameters.GetBool( "InsideIsPositive" ); + bool sqr_dist = this->m_Parameters.GetBool( "SquaredDistance" ); + bool use_spac = this->m_Parameters.GetBool( "UseImageSpacing" ); + + // Configure filter + _F* filter = this->_CreateITK< _F >( ); + filter->SetInput( image ); + filter->SetBackgroundValue( ( typename _TImage::PixelType )( back_value ) ); + filter->SetInsideIsPositive( pos_inside ); + filter->SetSquaredDistance( sqr_dist ); + filter->SetUseImageSpacing( use_spac ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.h b/plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.h new file mode 100644 index 0000000..dea132f --- /dev/null +++ b/plugins/ImageFilters/SignedMaurerDistanceMapImageFilter.h @@ -0,0 +1,53 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__SIGNEDMAURERDISTANCEMAPIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__SIGNEDMAURERDISTANCEMAPIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT SignedMaurerDistanceMapImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef SignedMaurerDistanceMapImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( + SignedMaurerDistanceMapImageFilter, cpPlugins::ProcessObject + ); + cpPlugins_Id_Macro( + SignedMaurerDistanceMapImageFilter, + ImageFilters + ); + + protected: + SignedMaurerDistanceMapImageFilter( ); + virtual ~SignedMaurerDistanceMapImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + template< class _TImage, class _TDMap > + inline void _GD1( _TImage* image ); + + private: + // Purposely not implemented + SignedMaurerDistanceMapImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__SIGNEDMAURERDISTANCEMAPIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/UnaryThresholdImageFilter.cxx b/plugins/ImageFilters/UnaryThresholdImageFilter.cxx new file mode 100644 index 0000000..240bc88 --- /dev/null +++ b/plugins/ImageFilters/UnaryThresholdImageFilter.cxx @@ -0,0 +1,59 @@ +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::UnaryThresholdImageFilter:: +UnaryThresholdImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsReal( "Threshold" ); + this->m_Parameters.ConfigureAsReal( "InsideValue" ); + this->m_Parameters.ConfigureAsReal( "OutsideValue" ); + this->m_Parameters.ConfigureAsBool( "Strict" ); + + this->m_Parameters.SetReal( "Threshold", 0 ); + this->m_Parameters.SetReal( "InsideValue", 1 ); + this->m_Parameters.SetReal( "OutsideValue", 0 ); + this->m_Parameters.SetBool( "Strict", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::UnaryThresholdImageFilter:: +~UnaryThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageFilters::UnaryThresholdImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData< itk::DataObject >( "Input" ); + cpPlugins_Image_Demangle_Pixel_AllScalars ( _GD0, image, 2 ); + else cpPlugins_Image_Demangle_Pixel_AllScalars( _GD0, image, 3 ); + else this->_Error( "No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsImageFilters::UnaryThresholdImageFilter:: +_GD0( _TImage* image ) +{ + typedef + cpExtensions::Algorithms::UnaryThresholdImageFilter< _TImage > + _TFilter; + + _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( ); + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageFilters/UnaryThresholdImageFilter.h b/plugins/ImageFilters/UnaryThresholdImageFilter.h new file mode 100644 index 0000000..008d22e --- /dev/null +++ b/plugins/ImageFilters/UnaryThresholdImageFilter.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__UNARYTHRESHOLDIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__UNARYTHRESHOLDIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT UnaryThresholdImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef UnaryThresholdImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( UnaryThresholdImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( UnaryThresholdImageFilter, ImageFilters ); + + protected: + UnaryThresholdImageFilter( ); + virtual ~UnaryThresholdImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + private: + // Purposely not implemented + UnaryThresholdImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__UNARYTHRESHOLDIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageMeshFilters/MarchingCubes.cxx b/plugins/ImageMeshFilters/MarchingCubes.cxx new file mode 100644 index 0000000..81efbe0 --- /dev/null +++ b/plugins/ImageMeshFilters/MarchingCubes.cxx @@ -0,0 +1,64 @@ +#include +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageMeshFilters::MarchingCubes:: +MarchingCubes( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Mesh >( "Output" ); + this->m_Parameters.ConfigureAsRealList( "Thresholds" ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageMeshFilters::MarchingCubes:: +~MarchingCubes( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageMeshFilters::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/ImageMeshFilters/MarchingCubes.h b/plugins/ImageMeshFilters/MarchingCubes.h new file mode 100644 index 0000000..5861bf3 --- /dev/null +++ b/plugins/ImageMeshFilters/MarchingCubes.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSIMAGEMESH__MARCHINGCUBES__H__ +#define __CPPLUGINSIMAGEMESH__MARCHINGCUBES__H__ + +#include +#include + +namespace cpPluginsImageMeshFilters +{ + /** + */ + class cpPluginsImageMeshFilters_EXPORT MarchingCubes + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef MarchingCubes Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( MarchingCubes, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( MarchingCubes, ImageToMeshFilters ); + + protected: + MarchingCubes( ); + virtual ~MarchingCubes( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + MarchingCubes( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEMESH__MARCHINGCUBES__H__ + +// eof - $RCSfile$ diff --git a/plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.cxx b/plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.cxx new file mode 100644 index 0000000..b5dc0d4 --- /dev/null +++ b/plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.cxx @@ -0,0 +1,133 @@ +#include +#include +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsImageMeshFilters::TriangleMeshToBinaryImageFilter:: +TriangleMeshToBinaryImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddInput( "BoundingBox", false ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsUint( "InsideValue" ); + this->m_Parameters.ConfigureAsUint( "OutsideValue" ); + this->m_Parameters.ConfigureAsUint( "MinimumSize" ); + + this->m_Parameters.SetUint( "InsideValue", 1 ); + this->m_Parameters.SetUint( "OutsideValue", 0 ); + this->m_Parameters.SetUint( "MinimumSize", 100 ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageMeshFilters::TriangleMeshToBinaryImageFilter:: +~TriangleMeshToBinaryImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsImageMeshFilters::TriangleMeshToBinaryImageFilter:: +_GenerateData( ) +{ + typedef itk::Mesh< float, 3 > _3F; + typedef itk::Mesh< double, 3 > _3D; + + auto _3f = this->GetInputData< _3F >( "Input" ); + auto _3d = this->GetInputData< _3D >( "Input" ); + if ( _3f != NULL ) this->_GD0( _3f ); + else if( _3d != NULL ) this->_GD0( _3d ); + else this->_Error( "No valid input mesh." ); +} + +// ------------------------------------------------------------------------- +template< class _TMesh > +void cpPluginsImageMeshFilters::TriangleMeshToBinaryImageFilter:: +_GD0( _TMesh* mesh ) +{ + this->_GD1< _TMesh, unsigned char >( mesh ); +} + +// ------------------------------------------------------------------------- +template< class _TMesh, class _TPixel > +void cpPluginsImageMeshFilters::TriangleMeshToBinaryImageFilter:: +_GD1( _TMesh* mesh ) +{ + typedef cpPlugins::BoundingBox _TBB; + typedef itk::Image< _TPixel, _TMesh::PointDimension > _TImage; + typedef itk::TriangleMeshToBinaryImageFilter< _TMesh, _TImage > _TFilter; + typedef typename _TImage::PointType _TPoint; + + static const unsigned int PAD = 10; + + _TFilter* filter = this->_CreateITK< _TFilter >( ); + + auto in_bb = dynamic_cast< _TBB* >( this->GetInput( "BoundingBox" ) ); + _TPoint minBB, maxBB; + if( in_bb == NULL ) + { + auto bb = mesh->GetBoundingBox( ); + minBB = bb->GetMinimum( ); + maxBB = bb->GetMaximum( ); + } + else + { + minBB = in_bb->GetMinimum< _TPoint >( ); + maxBB = in_bb->GetMaximum< _TPoint >( ); + + } // fi + + double lx = double( maxBB[ 0 ] - minBB[ 0 ] ); + double ly = double( maxBB[ 1 ] - minBB[ 1 ] ); + double lz = double( maxBB[ 2 ] - minBB[ 2 ] ); + double lm = ( lx < ly )? lx: ly; + lm = ( lm < lz )? lm: lz; + + // Compute spacing + double mSpac = lm / double( this->m_Parameters.GetUint( "MinimumSize" ) ); + typename _TImage::SpacingType spac; + spac.Fill( mSpac ); + filter->SetSpacing( spac ); + + // Compute size + typename _TImage::SizeType size; + size[ 0 ] = ( unsigned long )( std::ceil( lx / mSpac ) ); + size[ 1 ] = ( unsigned long )( std::ceil( ly / mSpac ) ); + size[ 2 ] = ( unsigned long )( std::ceil( lz / mSpac ) ); + + // ... add some padding pixels + size[ 0 ] += PAD; + size[ 1 ] += PAD; + size[ 2 ] += PAD; + filter->SetSize( size ); + + // Set origin + typename _TImage::PointType origin = minBB; + origin[ 0 ] -= double( PAD >> 1 ) * spac[ 0 ]; + origin[ 1 ] -= double( PAD >> 1 ) * spac[ 1 ]; + origin[ 2 ] -= double( PAD >> 1 ) * spac[ 2 ]; + filter->SetOrigin( origin ); + + // Remaining values + typename _TImage::DirectionType direction; + direction.SetIdentity( ); + filter->SetDirection( direction ); + + typename _TImage::IndexType index; + index.Fill( 0 ); + filter->SetIndex( index ); + + // Execute + filter->SetInput( mesh ); + filter->SetInsideValue( this->m_Parameters.GetUint( "InsideValue" ) ); + filter->SetOutsideValue( this->m_Parameters.GetUint( "OutsideValue" ) ); + filter->Update( ); + + // Connect output + this->GetOutput( "Output" )->SetITK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.h b/plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.h new file mode 100644 index 0000000..48c47ce --- /dev/null +++ b/plugins/ImageMeshFilters/TriangleMeshToBinaryImageFilter.h @@ -0,0 +1,48 @@ +#ifndef __CPPLUGINSIMAGEMESH__TRIANGLEMESHTOBINARYIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEMESH__TRIANGLEMESHTOBINARYIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageMeshFilters +{ + /** + */ + class cpPluginsImageMeshFilters_EXPORT TriangleMeshToBinaryImageFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef TriangleMeshToBinaryImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( TriangleMeshToBinaryImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( TriangleMeshToBinaryImageFilter, MeshToImageFilters ); + + protected: + TriangleMeshToBinaryImageFilter( ); + virtual ~TriangleMeshToBinaryImageFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TMesh > + inline void _GD0( _TMesh* mesh ); + + template< class _TMesh, class _TPixel > + inline void _GD1( _TMesh* mesh ); + + private: + // Purposely not implemented + TriangleMeshToBinaryImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEMESH__TRIANGLEMESHTOBINARYIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/MedialnessFilters/GulsunTekMedialness.cxx b/plugins/MedialnessFilters/GulsunTekMedialness.cxx new file mode 100644 index 0000000..d74f346 --- /dev/null +++ b/plugins/MedialnessFilters/GulsunTekMedialness.cxx @@ -0,0 +1,30 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsMedialnessFilters::GulsunTekMedialness:: +GulsunTekMedialness( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPluginsMedialnessFilters::GulsunTekMedialness:: +~GulsunTekMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsMedialnessFilters::GulsunTekMedialness:: +_GenerateData( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TImage > +void cpPluginsMedialnessFilters::GulsunTekMedialness:: +_GD0( _TImage* image ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/MedialnessFilters/GulsunTekMedialness.h b/plugins/MedialnessFilters/GulsunTekMedialness.h new file mode 100644 index 0000000..084307e --- /dev/null +++ b/plugins/MedialnessFilters/GulsunTekMedialness.h @@ -0,0 +1,45 @@ +#ifndef __CPPLUGINSMEDIALNESSFILTERS__GULSUNTEKMEDIALNESS__H__ +#define __CPPLUGINSMEDIALNESSFILTERS__GULSUNTEKMEDIALNESS__H__ + +#include +#include + +namespace cpPluginsMedialnessFilters +{ + /** + */ + class cpPluginsMedialnessFilters_EXPORT GulsunTekMedialness + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef GulsunTekMedialness Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( GulsunTekMedialness, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( GulsunTekMedialness, MedialnessFilters ); + + protected: + GulsunTekMedialness( ); + virtual ~GulsunTekMedialness( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + template< class _TImage > + inline void _GD0( _TImage* image ); + + private: + // Purposely not implemented + GulsunTekMedialness( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSMEDIALNESSFILTERS__GULSUNTEKMEDIALNESS__H__ + +// eof - $RCSfile$ diff --git a/plugins/MeshFilters/AppendMeshesFilter.cxx b/plugins/MeshFilters/AppendMeshesFilter.cxx new file mode 100644 index 0000000..453c474 --- /dev/null +++ b/plugins/MeshFilters/AppendMeshesFilter.cxx @@ -0,0 +1,52 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsMeshFilters::AppendMeshesFilter:: +AppendMeshesFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input0" ); + this->_AddInput( "Input1" ); + this->_AddInput( "Input2", false ); + this->_AddInput( "Input3", false ); + this->_AddInput( "Input4", false ); + this->_AddInput( "Input5", false ); + this->_AddOutput< cpPlugins::Mesh >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsMeshFilters::AppendMeshesFilter:: +~AppendMeshesFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsMeshFilters::AppendMeshesFilter:: +_GenerateData( ) +{ + auto m0 = this->GetInputData< vtkPolyData >( "Input0" ); + auto m1 = this->GetInputData< vtkPolyData >( "Input1" ); + auto m2 = this->GetInput( "Input2" ); + auto m3 = this->GetInput( "Input3" ); + auto m4 = this->GetInput( "Input4" ); + auto m5 = this->GetInput( "Input5" ); + + if( m0 == NULL || m1 == NULL ) + this->_Error( "Invalid inputs." ); + + auto filter = this->_CreateVTK< vtkAppendPolyData >( ); + filter->AddInputData( m0 ); + filter->AddInputData( m1 ); + if( m2 != NULL ) filter->AddInputData( m2->GetVTK< vtkPolyData >( ) ); + if( m3 != NULL ) filter->AddInputData( m3->GetVTK< vtkPolyData >( ) ); + if( m4 != NULL ) filter->AddInputData( m4->GetVTK< vtkPolyData >( ) ); + if( m5 != NULL ) filter->AddInputData( m5->GetVTK< vtkPolyData >( ) ); + filter->Update( ); + + this->GetOutput( "Output" )->SetVTK( filter->GetOutput( ) ); +} + +// eof - $RCSfile$ diff --git a/plugins/MeshFilters/AppendMeshesFilter.h b/plugins/MeshFilters/AppendMeshesFilter.h new file mode 100644 index 0000000..168229b --- /dev/null +++ b/plugins/MeshFilters/AppendMeshesFilter.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSIMAGEMESH__APPENDMESHESFILTER__H__ +#define __CPPLUGINSIMAGEMESH__APPENDMESHESFILTER__H__ + +#include +#include + +namespace cpPluginsMeshFilters +{ + /** + */ + class cpPluginsMeshFilters_EXPORT AppendMeshesFilter + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef AppendMeshesFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( AppendMeshesFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( AppendMeshesFilter, MeshFilters ); + + protected: + AppendMeshesFilter( ); + virtual ~AppendMeshesFilter( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + AppendMeshesFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEMESH__APPENDMESHESFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/MeshSources/CylinderSource.cxx b/plugins/MeshSources/CylinderSource.cxx new file mode 100644 index 0000000..02587b7 --- /dev/null +++ b/plugins/MeshSources/CylinderSource.cxx @@ -0,0 +1,37 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsMeshSources::CylinderSource:: +CylinderSource( ) + : Superclass( ) +{ + this->_AddOutput< cpPlugins::Mesh >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Height" ); + this->m_Parameters.ConfigureAsReal( "Radius" ); + this->m_Parameters.ConfigureAsUint( "Resolution" ); + this->m_Parameters.SetReal( "Radius", 1 ); + this->m_Parameters.SetUint( "Resolution", 8 ); +} + +// ------------------------------------------------------------------------- +cpPluginsMeshSources::CylinderSource:: +~CylinderSource( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsMeshSources::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/MeshSources/CylinderSource.h b/plugins/MeshSources/CylinderSource.h new file mode 100644 index 0000000..d2d36c3 --- /dev/null +++ b/plugins/MeshSources/CylinderSource.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSMESHSOURCES__CYLINDERSOURCE__H__ +#define __CPPLUGINSMESHSOURCES__CYLINDERSOURCE__H__ + +#include +#include + +namespace cpPluginsMeshSources +{ + /** + */ + class cpPluginsMeshSources_EXPORT CylinderSource + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef CylinderSource Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( CylinderSource, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( CylinderSource, MeshSources ); + + protected: + CylinderSource( ); + virtual ~CylinderSource( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + CylinderSource( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSMESHSOURCES__CYLINDERSOURCE__H__ + +// eof - $RCSfile$ diff --git a/plugins/MeshSources/SphereSource.cxx b/plugins/MeshSources/SphereSource.cxx new file mode 100644 index 0000000..fcf27cf --- /dev/null +++ b/plugins/MeshSources/SphereSource.cxx @@ -0,0 +1,38 @@ +#include +#include + +#include + +// ------------------------------------------------------------------------- +cpPluginsMeshSources::SphereSource:: +SphereSource( ) + : Superclass( ) +{ + this->_AddOutput< cpPlugins::Mesh >( "Output" ); + this->m_Parameters.ConfigureAsReal( "Radius" ); + this->m_Parameters.ConfigureAsUint( "PhiResolution" ); + this->m_Parameters.ConfigureAsUint( "ThetaResolution" ); + this->m_Parameters.SetReal( "Radius", 1 ); + this->m_Parameters.SetUint( "PhiResolution", 8 ); + this->m_Parameters.SetUint( "ThetaResolution", 8 ); +} + +// ------------------------------------------------------------------------- +cpPluginsMeshSources::SphereSource:: +~SphereSource( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsMeshSources::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/MeshSources/SphereSource.h b/plugins/MeshSources/SphereSource.h new file mode 100644 index 0000000..f6d3381 --- /dev/null +++ b/plugins/MeshSources/SphereSource.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSMESHSOURCES__SPHERESOURCE__H__ +#define __CPPLUGINSMESHSOURCES__SPHERESOURCE__H__ + +#include +#include + +namespace cpPluginsMeshSources +{ + /** + */ + class cpPluginsMeshSources_EXPORT SphereSource + : public cpPlugins::ProcessObject + { + cpPluginsObject; + public: + typedef SphereSource Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( SphereSource, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( SphereSource, MeshSources ); + + protected: + SphereSource( ); + virtual ~SphereSource( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + SphereSource( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSMESHSOURCES__SPHERESOURCE__H__ + +// eof - $RCSfile$ diff --git a/plugins/Widgets/SeedWidget.cxx b/plugins/Widgets/SeedWidget.cxx new file mode 100644 index 0000000..d60159d --- /dev/null +++ b/plugins/Widgets/SeedWidget.cxx @@ -0,0 +1,202 @@ +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +// This callback is responsible for changing update time +namespace cpPluginsWidgets +{ + /** + */ + class SeedWidgetCallback + : public vtkCommand + { + public: + static SeedWidgetCallback* New( ) + { return( new SeedWidgetCallback ); } + virtual void Execute( vtkObject* caller, unsigned long id, void* data ) + { + if( + id == vtkCommand::CursorChangedEvent || + id == vtkCommand::PlacePointEvent + ) + this->Widget->Modified( ); + } + SeedWidget* Widget; + }; + +} // ecapseman + +// ------------------------------------------------------------------------- +void cpPluginsWidgets::SeedWidget::WidgetData:: +Configure( + cpPluginsWidgets::SeedWidget* parent, + vtkRenderWindowInteractor* interactor, vtkImageActor* actor + ) +{ + this->Placer = vtkSmartPointer< vtkImageActorPointPlacer >::New( ); + this->Handle = vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + this->Seed = vtkSmartPointer< vtkSeedRepresentation >::New( ); + this->Widget = + vtkSmartPointer< cpExtensions::Interaction::SeedWidget >::New( ); + + this->Placer->SetImageActor( actor ); + this->Handle->GetProperty( )->SetColor( 1, 0, 0 ); + this->Handle->SetPointPlacer( this->Placer ); + this->Seed->SetHandleRepresentation( this->Handle ); + this->Widget->SetRepresentation( this->Seed ); + this->Widget->SetInteractor( interactor ); + + vtkSmartPointer< SeedWidgetCallback > cb = + vtkSmartPointer< SeedWidgetCallback >::New( ); + cb->Widget = parent; + this->Widget->AddObserver( vtkCommand::PlacePointEvent, cb ); + this->Widget->AddObserver( vtkCommand::CursorChangedEvent, cb ); +} + +// ------------------------------------------------------------------------- +void cpPluginsWidgets::SeedWidget::WidgetData:: +On( ) +{ + this->Widget->On( ); +} + +// ------------------------------------------------------------------------- +void cpPluginsWidgets::SeedWidget::WidgetData:: +Off( ) +{ + this->Widget->Off( ); +} + +// ------------------------------------------------------------------------- +cpPluginsWidgets::SeedWidget:: +SeedWidget( ) + : Superclass( ), + m_Configured( false ), + m_InitialNumberOfSeeds( 0 ) +{ + this->_AddOutput< cpPlugins::DataObject >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsWidgets::SeedWidget:: +~SeedWidget( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginsWidgets::SeedWidget:: +_GenerateData( ) +{ + auto points = this->_CreateVTK< vtkPoints >( ); + if( this->m_Configured ) + { + std::stringstream text; + points->Resize( this->m_InitialNumberOfSeeds ); + for( + auto wIt = this->m_Widgets.begin( ); + wIt != this->m_Widgets.end( ); + ++wIt + ) + { + double pos[ 3 ]; + for( unsigned int i = 0; i < wIt->Seed->GetNumberOfSeeds( ); ++i ) + { + wIt->Seed->GetSeedWorldPosition( i, pos ); + if( i > 0 ) + text << "#"; + text << pos[ 0 ] << " " << pos[ 1 ] << " " << pos[ 2 ]; + points->InsertNextPoint( pos ); + + } // rof + + } // rof + this->m_Parameters.SetString( "Text", text.str( ) ); + } + else + { + std::vector< std::string > tokens; + cpPlugins::TokenizeString( + tokens, this->m_Parameters.GetString( "Text" ), "#" + ); + this->m_InitialNumberOfSeeds = tokens.size( ); + points->SetNumberOfPoints( 0 ); + for( auto tIt = tokens.begin( ); tIt != tokens.end( ); ++tIt ) + { + std::vector< std::string > coords; + cpPlugins::TokenizeString( coords, *tIt, " \t" ); + int dim = ( coords.size( ) < 3 )? coords.size( ): 3; + double pos[ 3 ]; + for( unsigned int d = 0; d < 3; ++d ) + { + pos[ d ] = double( 0 ); + if( d < dim ) + { + std::istringstream value( coords[ d ] ); + value >> pos[ d ]; + + } // fi + + } // rof + points->InsertNextPoint( pos ); + this->m_Configured = true; + + } // rof + + std::vector< vtkRenderWindowInteractor* > ints; + if( this->m_MPRViewer != NULL ) + { + ints.push_back( this->m_MPRViewer->GetInteractor( 0 ) ); + ints.push_back( this->m_MPRViewer->GetInteractor( 1 ) ); + ints.push_back( this->m_MPRViewer->GetInteractor( 2 ) ); + + } // fi + if( this->m_SingleInteractor != NULL ) + ints.push_back( this->m_SingleInteractor ); + + for( auto iIt = ints.begin( ); iIt != ints.end( ); ++iIt ) + { + auto ren = ( *iIt )->GetInteractorStyle( )->GetCurrentRenderer( ); + if( ren != NULL ) + { + auto props = ren->GetViewProps( ); + if( props != NULL ) + { + props->InitTraversal( ); + vtkProp* prop; + while( ( prop = props->GetNextProp( ) ) != NULL ) + { + auto actor = dynamic_cast< vtkImageActor* >( prop ); + if( actor != NULL ) + { + WidgetData d; + d.Configure( this, *iIt, actor ); + d.On( ); + this->m_Widgets.push_back( d ); + this->m_Configured = true; + + } // fi + + } // elihw + + } // fi + + } // fi + + } // rof + + } // fi + if( this->m_Configured ) + this->Modified( ); + else + this->_Error( + "Could not create valid widget: are there any valid actors?" + ); + this->GetOutput( "Output" )->SetVTK( points ); +} + +// eof - $RCSfile$ diff --git a/plugins/Widgets/SeedWidget.h b/plugins/Widgets/SeedWidget.h new file mode 100644 index 0000000..5c9e68a --- /dev/null +++ b/plugins/Widgets/SeedWidget.h @@ -0,0 +1,68 @@ +#ifndef __CPPLUGINSWIDGETS__SEEDWIDGET__H__ +#define __CPPLUGINSWIDGETS__SEEDWIDGET__H__ + +#include +#include + +#include +#include +#include +#include +#include + +namespace cpPluginsWidgets +{ + /** + */ + class cpPluginsWidgets_EXPORT SeedWidget + : public cpPlugins::BaseWidget + { + cpPluginsObject; + public: + typedef SeedWidget Self; + typedef cpPlugins::BaseWidget Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( SeedWidget, cpPlugins::BaseWidget ); + cpPlugins_Id_Macro( SeedWidget, Widgets ); + + struct WidgetData + { + vtkSmartPointer< cpExtensions::Interaction::SeedWidget > Widget; + vtkSmartPointer< vtkImageActorPointPlacer > Placer; + vtkSmartPointer< vtkPointHandleRepresentation3D > Handle; + vtkSmartPointer< vtkSeedRepresentation > Seed; + + void Configure( + cpPluginsWidgets::SeedWidget* parent, + vtkRenderWindowInteractor* interactor, vtkImageActor* actor + ); + void On( ); + void Off( ); + }; + + protected: + SeedWidget( ); + virtual ~SeedWidget( ); + + virtual void _GenerateData( ) ITK_OVERRIDE; + + private: + // Purposely not implemented + SeedWidget( const Self& ); + Self& operator=( const Self& ); + + protected: + bool m_Configured; + std::vector< WidgetData > m_Widgets; + unsigned int m_InitialNumberOfSeeds; + }; + +} // ecapseman + +#endif // __CPPLUGINSWIDGETS__SEEDWIDGET__H__ + +// eof - $RCSfile$ diff --git a/third_party_installers/cpPlugins_Install_CMAKE.sh b/third_party_installers/cpPlugins_Install_CMAKE.sh new file mode 100755 index 0000000..ed6256f --- /dev/null +++ b/third_party_installers/cpPlugins_Install_CMAKE.sh @@ -0,0 +1,194 @@ +#!/bin/bash + +function abspath() +{ + pushd . > /dev/null + if [ -d "$1" ]; then + cd "$1" + dirs -l +0 + else + cd "`dirname \"$1\"`" + cur_dir=`dirs -l +0` + if [ "$cur_dir" == "/" ]; then + echo "$cur_dir`basename \"$1\"`" + else + echo "$cur_dir/`basename \"$1\"`" + fi + fi + popd > /dev/null +} + +function get_file_extension +{ + valid_extensions=("zip" "tar" "tar.gz" "tar.bz2") + actual_file=`abspath $1` + actual_ext="" + for ext in ${valid_extensions[@]}; do + test_str=`dirname $actual_file`/`basename $actual_file $ext` + if [ $test_str != $actual_file ]; then + actual_ext=$ext + fi + done + echo "$actual_ext" +} + +function print_help() +{ + echo "Usage: `basename $0` -f=compressed_code -c=source_dir -b=build_dir [-p=instalation_prefix] [-q=qmake_executable]" +} + +## Analyze command-line arguments +if [ $# -eq 0 ]; then + print_help + exit 1 +fi +prefix="${HOME}/local" +for i in "$@"; do + case $i in + -f=*|--file=*) + source_file="${i#*=}" + shift + ;; + -c=*|--source_dir=*) + source_dir="${i#*=}" + shift + ;; + -b=*|--build_dir=*) + build_dir="${i#*=}" + shift + ;; + -p=*|--prefix=*) + prefix="${i#*=}" + shift + ;; + -q=*|--qmake=*) + qmake_exec="${i#*=}" + shift + ;; + *) + ;; + esac +done + +## Check command line arguments +if [ "x$source_dir" == "x" ]; then + if [ "x$source_file" != "x" ]; then + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + base_dir=`dirname $base_path` + if [ "x$base_ext" != "x" ]; then + source_dir="$base_dir"/`basename $base_path .$base_ext` + else + echo "Error: Input compressed file extension not recognized." + exit 1 + fi + else + print_help + exit 1 + fi +fi +if [ "x$build_dir" == "x" ]; then + if [ "x$source_dir" != "x" ]; then + base_dir=$source_dir + if [ "${source_dir:$((${#str}-1)):1}" == "/" ]; then + base_dir=`echo $source_dir | rev | cut -c 2- | rev` + fi + build_dir="$base_dir-build" + else + print_help + exit 1 + fi +fi + +# Locate qmake executable +if [ "x$qmake_exec" == "x" ]; then + qmake_locations=("/usr/bin" "/usr/local/bin" "${HOME}/local/bin") + for loc in ${qmake_locations[@]}; do + qmake_file="$loc/qmake" + if [ -x $qmake_file ]; then + version=`$qmake_file --version | grep Using\ Qt\ version | cut -d ' ' -f 4` + if [ "${version:0:3}" == "4.8" ]; then + qmake_exec=$qmake_file + fi + fi + done +fi +qmake_exec=`abspath $qmake_exec` +if [ -x $qmake_exec ]; then + qt_options="--qt-gui --qt-qmake=$qmake_exec" +else + qt_options="--no-qt-gui" +fi + +## Other configuration variables +platform=`uname` +number_of_cores=`grep -c ^processor /proc/cpuinfo` +number_of_threads=`expr $number_of_cores / 2` +if [ "x$source_file" != "x" ]; then + source_file=`abspath $source_file` +fi +source_dir=`abspath $source_dir` +build_dir=`abspath $build_dir` + +echo "=====================================================================" +echo "==> Source file : $source_file" +echo "==> Source dir : $source_dir" +echo "==> Build dir : $build_dir" +echo "==> Prefix : $prefix" +echo "==> qmake : $qmake_exec" +echo "==> Qt options : $qt_options" +echo "==> Platform : $platform" +echo "==> Number of cores : $number_of_cores" +echo "==> Number of threads : $number_of_threads" +echo "=====================================================================" +read -n1 -r -p "Continue? [Y/N]... " key +echo +if [ "$key" != 'Y' -a "$key" != 'y' ] ; then + exit 1 +fi + +## Create paths +if [ "x$source_file" != "x" ]; then + echo -n "==> Cleaning directories... " + rm -rf $source_dir + rm -rf $build_dir + echo "done." + echo -n "==> Creating directories... " + mkdir -p $source_dir + mkdir -p $build_dir + echo "done." +fi + +## Extract source code +if [ "x$source_file" != "x" ]; then + echo -n "==> Extracting sources... " + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + if [ "$base_ext" == "zip" ]; then + echo unzip $base_path + elif [ "$base_ext" == "tar" ]; then + tar xf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.gz" ]; then + tar xzf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.bz2" ]; then + tar xjf $base_path -C $source_dir --strip-components=1 + fi + echo "done." +fi + +echo "==> Configuring sources... " +cd $build_dir +$source_dir/bootstrap --prefix=$prefix $qt_options +echo "==> Configuring sources... done." + +echo "==> Compiling sources..." +cd $build_dir +make -j$number_of_threads +echo "==> Compiling sources... done." + +echo "==> Installing package..." +cd $build_dir +make -j install +echo "==> Installing package... done." + +## eof - $RCSfile$ diff --git a/third_party_installers/cpPlugins_Install_ITK.sh b/third_party_installers/cpPlugins_Install_ITK.sh new file mode 100755 index 0000000..51e0ea0 --- /dev/null +++ b/third_party_installers/cpPlugins_Install_ITK.sh @@ -0,0 +1,212 @@ +#!/bin/bash + +function abspath() +{ + pushd . > /dev/null + if [ -d "$1" ]; then + cd "$1" + dirs -l +0 + else + cd "`dirname \"$1\"`" + cur_dir=`dirs -l +0` + if [ "$cur_dir" == "/" ]; then + echo "$cur_dir`basename \"$1\"`" + else + echo "$cur_dir/`basename \"$1\"`" + fi + fi + popd > /dev/null +} + +function get_file_extension +{ + valid_extensions=("zip" "tar" "tar.gz" "tar.bz2") + actual_file=`abspath $1` + actual_ext="" + for ext in ${valid_extensions[@]}; do + test_str=`dirname $actual_file`/`basename $actual_file $ext` + if [ $test_str != $actual_file ]; then + actual_ext=$ext + fi + done + echo "$actual_ext" +} + +function print_help() +{ + echo "Usage: `basename $0` -f=compressed_code -c=source_dir -b=build_dir [-p=instalation_prefix] [-m=cmake_executable] [-t=build_type[MinSizeRel/Debug/Release]]" +} + +## Analyze command-line arguments +if [ $# -eq 0 ]; then + print_help + exit 1 +fi +prefix="${HOME}/local" +build_type="MinSizeRel" +for i in "$@"; do + case $i in + -f=*|--file=*) + source_file="${i#*=}" + shift + ;; + -c=*|--source_dir=*) + source_dir="${i#*=}" + shift + ;; + -b=*|--build_dir=*) + build_dir="${i#*=}" + shift + ;; + -t=*|--build_type=*) + build_type="${i#*=}" + shift + ;; + -p=*|--prefix=*) + prefix="${i#*=}" + shift + ;; + -m=*|--cmake=*) + cmake_exec="${i#*=}" + shift + ;; + *) + ;; + esac +done + +## Check command line arguments +if [ "x$source_dir" == "x" ]; then + if [ "x$source_file" != "x" ]; then + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + base_dir=`dirname $base_path` + if [ "x$base_ext" != "x" ]; then + source_dir="$base_dir"/`basename $base_path .$base_ext` + else + echo "Error: Input compressed file extension not recognized." + exit 1 + fi + else + print_help + exit 1 + fi +fi +if [ "x$build_dir" == "x" ]; then + if [ "x$source_dir" != "x" ]; then + base_dir=$source_dir + if [ "${source_dir:$((${#str}-1)):1}" == "/" ]; then + base_dir=`echo $source_dir | rev | cut -c 2- | rev` + fi + build_dir="$base_dir-build" + else + print_help + exit 1 + fi +fi + +## Locate cmake executable +if [ "x$cmake_exec" == "x" ]; then + cmake_locations=("/usr/bin" "/usr/local/bin" "${HOME}/local/bin") + cmake_ver="" + for loc in ${cmake_locations[@]}; do + cmake_file="$loc/cmake" + if [ -x $cmake_file ]; then + str=`$cmake_file --version | grep version` + version=${str:14} + if [ "$cmake_ver" \< "$version" ]; then + cmake_ver=$version + cmake_exec=$cmake_file + fi + fi + done +fi +if [ ! -x $cmake_exec ]; then + echo "ERROR: no valid cmake found." + exit 1 +fi +cmake_exec=`abspath $cmake_exec` + +## Other configuration variables +platform=`uname` +number_of_cores=`grep -c ^processor /proc/cpuinfo` +number_of_threads=`expr $number_of_cores / 2` +if [ "x$source_file" != "x" ]; then + source_file=`abspath $source_file` +fi +source_dir=`abspath $source_dir` +build_dir=`abspath $build_dir` + +echo "=====================================================================" +echo "==> Source file : $source_file" +echo "==> Source dir : $source_dir" +echo "==> Build dir : $build_dir" +echo "==> Build type : $build_type" +echo "==> Prefix : $prefix" +echo "==> cmake : $cmake_exec" +echo "==> Platform : $platform" +echo "==> Number of cores : $number_of_cores" +echo "==> Number of threads : $number_of_threads" +echo "=====================================================================" +read -n1 -r -p "Continue? [Y/N]... " key +echo +if [ "$key" != 'Y' -a "$key" != 'y' ] ; then + exit 1 +fi + +## Create paths +if [ "x$source_file" != "x" ]; then + echo -n "==> Cleaning directories... " + rm -rf $source_dir + rm -rf $build_dir + echo "done." + echo -n "==> Creating directories... " + mkdir -p $source_dir + mkdir -p $build_dir + echo "done." +fi + +## Extract source code +if [ "x$source_file" != "x" ]; then + echo -n "==> Extracting sources... " + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + if [ "$base_ext" == "zip" ]; then + echo unzip $base_path + elif [ "$base_ext" == "tar" ]; then + tar xf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.gz" ]; then + tar xzf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.bz2" ]; then + tar xjf $base_path -C $source_dir --strip-components=1 + fi + echo "done." +fi + +echo "==> Configuring sources... " +cd $build_dir +$cmake_exec \ + -DCMAKE_CXX_FLAGS:STRING=-std=c++11 \ + -DBUILD_DOCUMENTATION:BOOL=OFF \ + -DBUILD_EXAMPLES:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ + -DBUILD_TESTING:BOOL=OFF \ + -DCMAKE_BUILD_TYPE:STRING=$build_type \ + -DModule_ITKReview:BOOL=ON \ + -DModule_ITKVtkGlue:BOOL=OFF \ + -DModule_ParabolicMorphology:BOOL=ON \ + -DCMAKE_INSTALL_PREFIX:PATH=$prefix \ + ${source_dir} +echo "==> Configuring sources... done." + +echo "==> Compiling sources..." +cd $build_dir +make -j$number_of_threads +echo "==> Compiling sources... done." + +echo "==> Installing package..." +cd $build_dir +make -j install +echo "==> Installing package... done." + +## eof - $RCSfile$ diff --git a/third_party_installers/cpPlugins_Install_QT4.sh b/third_party_installers/cpPlugins_Install_QT4.sh new file mode 100755 index 0000000..36c5d13 --- /dev/null +++ b/third_party_installers/cpPlugins_Install_QT4.sh @@ -0,0 +1,219 @@ +#!/bin/bash + +function abspath() +{ + pushd . > /dev/null + if [ -d "$1" ]; then + cd "$1" + dirs -l +0 + else + cd "`dirname \"$1\"`" + cur_dir=`dirs -l +0` + if [ "$cur_dir" == "/" ]; then + echo "$cur_dir`basename \"$1\"`" + else + echo "$cur_dir/`basename \"$1\"`" + fi + fi + popd > /dev/null +} + +function get_file_extension +{ + valid_extensions=("zip" "tar" "tar.gz" "tar.bz2") + actual_file=`abspath $1` + actual_ext="" + for ext in ${valid_extensions[@]}; do + test_str=`dirname $actual_file`/`basename $actual_file $ext` + if [ $test_str != $actual_file ]; then + actual_ext=$ext + fi + done + echo "$actual_ext" +} + +function print_help() +{ + echo "Usage: `basename $0` -f=compressed_code -c=source_dir -b=build_dir [-t=build_type[release/debug]] [-p=instalation_prefix] [--full]" +} + +## Analyze command-line arguments +if [ $# -eq 0 ]; then + print_help + exit 1 +fi +full_compile="0" +prefix="${HOME}/local" +build_type="release" +for i in "$@"; do + case $i in + -f=*|--file=*) + source_file="${i#*=}" + shift + ;; + -c=*|--source_dir=*) + source_dir="${i#*=}" + shift + ;; + -b=*|--build_dir=*) + build_dir="${i#*=}" + shift + ;; + -t=*|--build_type=*) + build_type="${i#*=}" + shift + ;; + -p=*|--prefix=*) + prefix="${i#*=}" + shift + ;; + --full) + full_compile="1" + shift + ;; + *) + ;; + esac +done + +## Check command line arguments +if [ "x$source_dir" == "x" ]; then + if [ "x$source_file" != "x" ]; then + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + base_dir=`dirname $base_path` + if [ "x$base_ext" != "x" ]; then + source_dir="$base_dir"/`basename $base_path .$base_ext` + else + echo "Error: Input compressed file extension not recognized." + exit 1 + fi + else + print_help + exit 1 + fi +fi +if [ "x$build_dir" == "x" ]; then + if [ "x$source_dir" != "x" ]; then + base_dir=$source_dir + if [ "${source_dir:$((${#str}-1)):1}" == "/" ]; then + base_dir=`echo $source_dir | rev | cut -c 2- | rev` + fi + build_dir="$base_dir-build" + else + print_help + exit 1 + fi +fi + +## Other configuration variables +platform=`uname` +particular_options="" +patch_file="" +if [ "$platform" == "Darwin" ]; then + particular_options=-no-framework + bash_path=`abspath $0` + bash_dir=`dirname $bash_path` + patch_file=$bash_dir/qt-4.8.6.patch +fi +number_of_cores=`grep -c ^processor /proc/cpuinfo` +number_of_threads=`expr $number_of_cores / 2` +if [ "x$source_file" != "x" ]; then + source_file=`abspath $source_file` +fi +source_dir=`abspath $source_dir` +build_dir=`abspath $build_dir` + +echo "=====================================================================" +echo "==> Source file : $source_file" +echo "==> Source dir : $source_dir" +echo "==> Build dir : $build_dir" +echo "==> Build type : $build_type" +echo "==> Prefix : $prefix" +echo "==> Full compile : $full_compile" +echo "==> Platform : $platform" +echo "==> Number of cores : $number_of_cores" +echo "==> Number of threads : $number_of_threads" +echo "==> Patch file : $patch_file" +echo "=====================================================================" +read -n1 -r -p "Continue? [Y/N]... " key +echo +if [ "$key" != 'Y' -a "$key" != 'y' ] ; then + exit 1 +fi + +## Create paths +if [ "x$source_file" != "x" ]; then + echo -n "==> Cleaning directories... " + rm -rf $source_dir + rm -rf $build_dir + echo "done." + echo -n "==> Creating directories... " + mkdir -p $source_dir + mkdir -p $build_dir + echo "done." +fi + +## Extract source code +if [ "x$source_file" != "x" ]; then + echo -n "==> Extracting sources... " + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + if [ "$base_ext" == "zip" ]; then + echo unzip $base_path + elif [ "$base_ext" == "tar" ]; then + tar xf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.gz" ]; then + tar xzf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.bz2" ]; then + tar xjf $base_path -C $source_dir --strip-components=1 + fi + echo "done." +fi + +# Apply patch +if [ "x$patch_file" != "x" ]; then + echo -n "==> Applying patch... " + cd $source_dir + patch -p0 < $patch_file + echo "done." +fi + +echo "==> Configuring sources... " +cd $build_dir +if [ "x$full_compile" == "xfull" ]; then + $source_dir/configure \ + -prefix $prefix \ + -$build_type \ + -opensource -shared -fast \ + -no-webkit \ + -optimized-qmake \ + $particular_options \ + -confirm-license +else + $source_dir/configure \ + -prefix $prefix \ + -$build_type \ + -opensource -shared -fast \ + -no-phonon \ + -no-phonon-backend \ + -no-webkit \ + -no-openvg \ + -nomake demos -nomake examples \ + -optimized-qmake \ + $particular_options \ + -confirm-license +fi +echo "==> Configuring sources... done." + +echo "==> Compiling sources..." +cd $build_dir +make -j$number_of_threads +echo "==> Compiling sources... done." + +echo "==> Installing package..." +cd $build_dir +make -j install +echo "==> Installing package... done." + +## eof - $RCSfile$ diff --git a/third_party_installers/cpPlugins_Install_VTK.sh b/third_party_installers/cpPlugins_Install_VTK.sh new file mode 100755 index 0000000..1f8ecc3 --- /dev/null +++ b/third_party_installers/cpPlugins_Install_VTK.sh @@ -0,0 +1,252 @@ +#!/bin/bash + +function abspath() +{ + pushd . > /dev/null + if [ -d "$1" ]; then + cd "$1" + dirs -l +0 + else + cd "`dirname \"$1\"`" + cur_dir=`dirs -l +0` + if [ "$cur_dir" == "/" ]; then + echo "$cur_dir`basename \"$1\"`" + else + echo "$cur_dir/`basename \"$1\"`" + fi + fi + popd > /dev/null +} + +function get_file_extension +{ + valid_extensions=("zip" "tar" "tar.gz" "tar.bz2") + actual_file=`abspath $1` + actual_ext="" + for ext in ${valid_extensions[@]}; do + test_str=`dirname $actual_file`/`basename $actual_file $ext` + if [ $test_str != $actual_file ]; then + actual_ext=$ext + fi + done + echo "$actual_ext" +} + +function print_help() +{ + echo "Usage: `basename $0` -f=compressed_code -c=source_dir -b=build_dir [-p=instalation_prefix] [-q=qmake_executable] [-m=cmake_executable] [-t=build_type[MinSizeRel/Debug/Release]]" +} + +## Analyze command-line arguments +if [ $# -eq 0 ]; then + print_help + exit 1 +fi +prefix="${HOME}/local" +build_type="MinSizeRel" +for i in "$@"; do + case $i in + -f=*|--file=*) + source_file="${i#*=}" + shift + ;; + -c=*|--source_dir=*) + source_dir="${i#*=}" + shift + ;; + -b=*|--build_dir=*) + build_dir="${i#*=}" + shift + ;; + -t=*|--build_type=*) + build_type="${i#*=}" + shift + ;; + -p=*|--prefix=*) + prefix="${i#*=}" + shift + ;; + -m=*|--cmake=*) + cmake_exec="${i#*=}" + shift + ;; + -q=*|--qmake=*) + qmake_exec="${i#*=}" + shift + ;; + *) + ;; + esac +done + +## Check command line arguments +if [ "x$source_dir" == "x" ]; then + if [ "x$source_file" != "x" ]; then + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + base_dir=`dirname $base_path` + if [ "x$base_ext" != "x" ]; then + source_dir="$base_dir"/`basename $base_path .$base_ext` + else + echo "Error: Input compressed file extension not recognized." + exit 1 + fi + else + print_help + exit 1 + fi +fi +if [ "x$build_dir" == "x" ]; then + if [ "x$source_dir" != "x" ]; then + base_dir=$source_dir + if [ "${source_dir:$((${#str}-1)):1}" == "/" ]; then + base_dir=`echo $source_dir | rev | cut -c 2- | rev` + fi + build_dir="$base_dir-build" + else + print_help + exit 1 + fi +fi + +## Locate cmake executable +if [ "x$cmake_exec" == "x" ]; then + cmake_locations=("/usr/bin" "/usr/local/bin" "${HOME}/local/bin") + cmake_ver="" + for loc in ${cmake_locations[@]}; do + cmake_file="$loc/cmake" + if [ -x $cmake_file ]; then + str=`$cmake_file --version | grep version` + version=${str:14} + if [ "$cmake_ver" \< "$version" ]; then + cmake_ver=$version + cmake_exec=$cmake_file + fi + fi + done +fi +if [ ! -x $cmake_exec ]; then + echo "ERROR: no valid cmake found." + exit 1 +fi +cmake_exec=`abspath $cmake_exec` + +# Locate qmake executable +if [ "x$qmake_exec" == "x" ]; then + qmake_locations=("/usr/bin" "/usr/local/bin" "${HOME}/local/bin") + for loc in ${qmake_locations[@]}; do + qmake_file="$loc/qmake" + if [ -x $qmake_file ]; then + version=`$qmake_file --version | grep Using\ Qt\ version | cut -d ' ' -f 4` + if [ "${version:0:3}" == "4.8" ]; then + qmake_exec=$qmake_file + fi + fi + done +fi +qmake_exec=`abspath $qmake_exec` +if [ -x $qmake_exec ]; then + use_qt="1" +else + use_qt="0" +fi + +## Other configuration variables +platform=`uname` +number_of_cores=`grep -c ^processor /proc/cpuinfo` +number_of_threads=`expr $number_of_cores / 2` +if [ "x$source_file" != "x" ]; then + source_file=`abspath $source_file` +fi +source_dir=`abspath $source_dir` +build_dir=`abspath $build_dir` + +echo "=====================================================================" +echo "==> Source file : $source_file" +echo "==> Source dir : $source_dir" +echo "==> Build dir : $build_dir" +echo "==> Build type : $build_type" +echo "==> Prefix : $prefix" +echo "==> cmake : $cmake_exec" +echo "==> qmake : $qmake_exec" +echo "==> Use Qt : $use_qt" +echo "==> Platform : $platform" +echo "==> Number of cores : $number_of_cores" +echo "==> Number of threads : $number_of_threads" +echo "=====================================================================" +read -n1 -r -p "Continue? [Y/N]... " key +echo +if [ "$key" != 'Y' -a "$key" != 'y' ] ; then + exit 1 +fi + +## Create paths +if [ "x$source_file" != "x" ]; then + echo -n "==> Cleaning directories... " + rm -rf $source_dir + rm -rf $build_dir + echo "done." + echo -n "==> Creating directories... " + mkdir -p $source_dir + mkdir -p $build_dir + echo "done." +fi + +## Extract source code +if [ "x$source_file" != "x" ]; then + echo -n "==> Extracting sources... " + base_path=`abspath $source_file` + base_ext=`get_file_extension $base_path` + if [ "$base_ext" == "zip" ]; then + echo unzip $base_path + elif [ "$base_ext" == "tar" ]; then + tar xf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.gz" ]; then + tar xzf $base_path -C $source_dir --strip-components=1 + elif [ "$base_ext" == "tar.bz2" ]; then + tar xjf $base_path -C $source_dir --strip-components=1 + fi + echo "done." +fi + +echo "==> Configuring sources... " +cd $build_dir +if [ "$use_qt" == "1" ]; then + $cmake_exec \ + -DCMAKE_CXX_FLAGS:STRING=-std=c++11 \ + -DBUILD_DOCUMENTATION:BOOL=OFF \ + -DBUILD_EXAMPLES:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ + -DBUILD_TESTING:BOOL=OFF \ + -DQT_QMAKE_EXECUTABLE:PATH=$qmake_exec \ + -DCMAKE_BUILD_TYPE:STRING=$build_type \ + -DModule_vtkGUISupportQt:BOOL=ON \ + -DModule_vtkGUISupportQtOpenGL:BOOL=ON \ + -DModule_vtkGUISupportQtSQL:BOOL=OFF \ + -DModule_vtkGUISupportQtWebkit:BOOL=OFF \ + -DCMAKE_INSTALL_PREFIX:PATH=$prefix \ + ${source_dir} +else + $cmake_exec \ + -DCMAKE_CXX_FLAGS:STRING=-std=c++11 \ + -DBUILD_DOCUMENTATION:BOOL=OFF \ + -DBUILD_EXAMPLES:BOOL=OFF \ + -DBUILD_SHARED_LIBS:BOOL=ON \ + -DBUILD_TESTING:BOOL=OFF \ + -DCMAKE_BUILD_TYPE:STRING=$build_type \ + -DCMAKE_INSTALL_PREFIX:PATH=$prefix \ + ${source_dir} +fi +echo "==> Configuring sources... done." + +echo "==> Compiling sources..." +cd $build_dir +make -j$number_of_threads +echo "==> Compiling sources... done." + +echo "==> Installing package..." +cd $build_dir +make -j install +echo "==> Installing package... done." + +## eof - $RCSfile$ diff --git a/third_party_installers/qt-4.8.6.patch b/third_party_installers/qt-4.8.6.patch new file mode 100644 index 0000000..f0d2122 --- /dev/null +++ b/third_party_installers/qt-4.8.6.patch @@ -0,0 +1,18 @@ +--- src/gui/painting/qpaintengine_mac.cpp.orig 2015-05-07 14:14:43.000000000 +0000 ++++ src/gui/painting/qpaintengine_mac.cpp +@@ -340,13 +340,7 @@ CGColorSpaceRef QCoreGraphicsPaintEngine + } + + // Get the color space from the display profile. +- CGColorSpaceRef colorSpace = 0; +- CMProfileRef displayProfile = 0; +- CMError err = CMGetProfileByAVID((CMDisplayIDType)displayID, &displayProfile); +- if (err == noErr) { +- colorSpace = CGColorSpaceCreateWithPlatformColorSpace(displayProfile); +- CMCloseProfile(displayProfile); +- } ++ CGColorSpaceRef colorSpace = CGDisplayCopyColorSpace(displayID); + + // Fallback: use generic DeviceRGB + if (colorSpace == 0) + -- 2.45.1