From 1b0022070ff3b5f80f6f8c8b87f73032f5685eaf Mon Sep 17 00:00:00 2001 From: Leonardo Florez-Valencia Date: Tue, 8 Mar 2016 17:44:02 -0500 Subject: [PATCH] First dump for version 0.1.0 --- CMakeLists.txt | 146 +- appli/CMakeLists.txt | 17 + appli/PipelineEditor/CMakeLists.txt | 51 + appli/PipelineEditor/PipelineEditor.cxx | 390 +++ appli/PipelineEditor/PipelineEditor.h | 56 + appli/PipelineEditor/PipelineEditor.ui | 235 ++ appli/PipelineEditor/main.cxx | 81 + appli/bash/CMakeLists.txt | 16 + appli/bash/cpPlugins_HostCreator.cxx | 169 ++ appli/examples/CMakeLists.txt | 13 + appli/examples/example_LoadPluginsFile.cxx | 44 + appli/examples/example_ReadWriteImage.cxx | 95 + .../example_ReadWriteImageWithWorkspace.cxx | 60 + cmake/CMakeLists.txt | 1 + cmake/cpPlugins_KitwareTools.cmake | 19 + cmake/cpPlugins_Options.cmake | 48 + cmake/cpPlugins_Policies.cmake | 13 + cmake/cpPlugins_Qt4Tools.cmake | 24 + doc/third_party/Pluma/build/Doxyfile | 1597 ----------- doc/third_party/Pluma/build/Doxygen.hpp | 101 - doc/third_party/Pluma/build/doxygen.css | 384 --- doc/third_party/Pluma/build/footer.htm | 8 - doc/third_party/Pluma/build/header.htm | 12 - .../Pluma/html/Config_8hpp_source.htm | 170 -- .../Pluma/html/Connector_8hpp_source.htm | 119 - .../Pluma/html/DLibrary_8cpp_source.htm | 141 - .../Pluma/html/DLibrary_8hpp_source.htm | 117 - .../Pluma/html/Dir_8cpp_source.htm | 137 - .../Pluma/html/Dir_8hpp_source.htm | 88 - .../Pluma/html/Doxygen_8hpp_source.htm | 39 - .../Pluma/html/Host_8cpp_source.htm | 203 -- .../Pluma/html/Host_8hpp_source.htm | 136 - .../Pluma/html/PluginManager_8cpp_source.htm | 237 -- .../Pluma/html/PluginManager_8hpp_source.htm | 131 - .../Pluma/html/Pluma_8hpp_source.htm | 137 - .../Pluma/html/Pluma_8inl_source.htm | 86 - .../Pluma/html/Provider_8cpp_source.htm | 89 - .../Pluma/html/Provider_8hpp_source.htm | 99 - doc/third_party/Pluma/html/annotated.htm | 52 - doc/third_party/Pluma/html/bc_s.png | Bin 676 -> 0 bytes doc/third_party/Pluma/html/bdwn.png | Bin 147 -> 0 bytes doc/third_party/Pluma/html/classes.htm | 53 - .../html/classpluma_1_1DLibrary-members.htm | 52 - .../Pluma/html/classpluma_1_1DLibrary.htm | 163 -- .../Pluma/html/classpluma_1_1Host-members.htm | 52 - .../Pluma/html/classpluma_1_1Host.htm | 109 - .../classpluma_1_1PluginManager-members.htm | 61 - .../html/classpluma_1_1PluginManager.htm | 515 ---- .../html/classpluma_1_1PluginManager.png | Bin 609 -> 0 bytes .../html/classpluma_1_1Pluma-members.htm | 66 - .../Pluma/html/classpluma_1_1Pluma.htm | 650 ----- .../Pluma/html/classpluma_1_1Pluma.png | Bin 602 -> 0 bytes .../html/classpluma_1_1Provider-members.htm | 53 - .../Pluma/html/classpluma_1_1Provider.htm | 233 -- doc/third_party/Pluma/html/closed.png | Bin 132 -> 0 bytes doc/third_party/Pluma/html/doxygen.css | 384 --- doc/third_party/Pluma/html/doxygen.png | Bin 3779 -> 0 bytes doc/third_party/Pluma/html/dynsections.js | 104 - doc/third_party/Pluma/html/files.htm | 58 - doc/third_party/Pluma/html/ftv2blank.png | Bin 86 -> 0 bytes doc/third_party/Pluma/html/ftv2cl.png | Bin 453 -> 0 bytes doc/third_party/Pluma/html/ftv2doc.png | Bin 746 -> 0 bytes .../Pluma/html/ftv2folderclosed.png | Bin 616 -> 0 bytes doc/third_party/Pluma/html/ftv2folderopen.png | Bin 597 -> 0 bytes doc/third_party/Pluma/html/ftv2lastnode.png | Bin 86 -> 0 bytes doc/third_party/Pluma/html/ftv2link.png | Bin 746 -> 0 bytes doc/third_party/Pluma/html/ftv2mlastnode.png | Bin 246 -> 0 bytes doc/third_party/Pluma/html/ftv2mnode.png | Bin 246 -> 0 bytes doc/third_party/Pluma/html/ftv2mo.png | Bin 403 -> 0 bytes doc/third_party/Pluma/html/ftv2node.png | Bin 86 -> 0 bytes doc/third_party/Pluma/html/ftv2ns.png | Bin 388 -> 0 bytes doc/third_party/Pluma/html/ftv2plastnode.png | Bin 229 -> 0 bytes doc/third_party/Pluma/html/ftv2pnode.png | Bin 229 -> 0 bytes doc/third_party/Pluma/html/ftv2splitbar.png | Bin 314 -> 0 bytes doc/third_party/Pluma/html/ftv2vertline.png | Bin 86 -> 0 bytes doc/third_party/Pluma/html/functions.htm | 105 - doc/third_party/Pluma/html/functions_func.htm | 105 - doc/third_party/Pluma/html/hierarchy.htm | 51 - doc/third_party/Pluma/html/index.htm | 112 - doc/third_party/Pluma/html/logo.png | Bin 32867 -> 0 bytes doc/third_party/Pluma/html/nav_f.png | Bin 153 -> 0 bytes doc/third_party/Pluma/html/nav_g.png | Bin 95 -> 0 bytes doc/third_party/Pluma/html/nav_h.png | Bin 98 -> 0 bytes doc/third_party/Pluma/html/open.png | Bin 123 -> 0 bytes doc/third_party/Pluma/html/sync_off.png | Bin 853 -> 0 bytes doc/third_party/Pluma/html/sync_on.png | Bin 845 -> 0 bytes doc/third_party/Pluma/html/tab_a.png | Bin 142 -> 0 bytes doc/third_party/Pluma/html/tab_b.png | Bin 169 -> 0 bytes doc/third_party/Pluma/html/tab_h.png | Bin 177 -> 0 bytes doc/third_party/Pluma/html/tab_s.png | Bin 184 -> 0 bytes doc/third_party/Pluma/html/tabs.css | 60 - lib/CMakeLists.txt | 14 + lib/ItkVtkGlue/CMakeLists.txt | 1 + lib/ItkVtkGlue/itkImageToVTKImageFilter.h | 111 + lib/ItkVtkGlue/itkImageToVTKImageFilter.hxx | 141 + lib/ItkVtkGlue/itkVTKImageToImageFilter.h | 100 + lib/ItkVtkGlue/itkVTKImageToImageFilter.hxx | 107 + .../Algorithms/BezierCurveFunction.h | 76 + .../Algorithms/BezierCurveFunction.hxx | 155 ++ .../Algorithms/GradientFunctionBase.h | 84 + .../Algorithms/GradientFunctionBase.hxx | 82 + .../Algorithms/GulsunTekMedialness.h | 85 + .../Algorithms/GulsunTekMedialness.hxx | 197 ++ .../Algorithms/ImageFunctionFilter.h | 106 + .../Algorithms/ImageFunctorFilter.h | 102 + .../Algorithms/InertiaMedialness.h | 215 ++ .../Algorithms/InertiaTensorFunction.h | 180 ++ lib/cpExtensions/Algorithms/IsoImageSlicer.h | 184 ++ .../Algorithms/IsoImageSlicer.hxx | 234 ++ .../IterativeGaussianModelEstimator.h | 111 + .../IterativeGaussianModelEstimator.hxx | 291 ++ .../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 + .../Algorithms/MacheteImageFilter.h | 72 + .../Algorithms/MacheteImageFilter.hxx | 92 + .../MultiScaleGaussianImageFilter.h | 102 + .../MultiScaleGaussianImageFilter.hxx | 315 +++ .../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 + .../Algorithms/SpatialObjectMaskImageFilter.h | 87 + .../SpatialObjectMaskImageFilter.hxx | 136 + lib/cpExtensions/CMakeLists.txt | 133 + lib/cpExtensions/Config.h.in | 20 + lib/cpExtensions/DataStructures/Graph.h | 166 ++ lib/cpExtensions/DataStructures/Graph.hxx | 208 ++ .../DataStructures/ITKAndVTKImage.h | 107 + .../InfinitePlaneSpatialObject.h | 88 + .../InfinitePlaneSpatialObject.hxx | 109 + lib/cpExtensions/DataStructures/QuadEdge.h | 471 ++++ lib/cpExtensions/DataStructures/QuadEdge.hxx | 241 ++ .../DataStructures/QuadEdgeCell.h | 126 + .../DataStructures/QuadEdgeCell.hxx | 258 ++ .../DataStructures/QuadEdgeIterators.h | 173 ++ .../DataStructures/QuadEdgeIterators.hxx | 275 ++ .../DataStructures/QuadEdgeMesh.h | 285 ++ .../DataStructures/QuadEdgeMesh.hxx | 527 ++++ .../DataStructures/VectorValuesContainer.h | 66 + lib/cpExtensions/IO/MementoState.cxx | 148 + lib/cpExtensions/IO/MementoState.h | 63 + lib/cpExtensions/IO/MeshReader.h | 64 + lib/cpExtensions/IO/MeshReader.hxx | 92 + lib/cpExtensions/IO/WaveFrontOBJReader.h | 81 + lib/cpExtensions/IO/WaveFrontOBJReader.hxx | 123 + .../Interaction/BaseInteractorStyle.cxx | 568 ++++ .../Interaction/BaseInteractorStyle.h | 226 ++ .../Interaction/ImageInteractorStyle.cxx | 168 ++ .../Interaction/ImageInteractorStyle.h | 97 + lib/cpExtensions/Interaction/SeedWidget.cxx | 93 + lib/cpExtensions/Interaction/SeedWidget.h | 54 + lib/cpExtensions/Interaction/SphereWidget.cxx | 263 ++ lib/cpExtensions/Interaction/SphereWidget.h | 71 + lib/cpExtensions/QT/SimpleMPRWidget.cxx | 622 +++++ lib/cpExtensions/QT/SimpleMPRWidget.h | 147 + lib/cpExtensions/QT/SimpleMPRWidget.ui | 96 + lib/cpExtensions/Visualization/Image3DMPR.cxx | 364 +++ lib/cpExtensions/Visualization/Image3DMPR.h | 95 + .../Visualization/ImageBlender.cxx | 239 ++ lib/cpExtensions/Visualization/ImageBlender.h | 67 + .../Visualization/ImageSliceActors.cxx | 1323 +++++++++ .../Visualization/ImageSliceActors.h | 236 ++ lib/cpExtensions/Visualization/MPRActors.cxx | 500 ++++ lib/cpExtensions/Visualization/MPRActors.h | 128 + lib/cpExtensions/Visualization/MPRObjects.cxx | 519 ++++ lib/cpExtensions/Visualization/MPRObjects.h | 137 + lib/cpExtensions/Visualization/MeshMapper.h | 105 + lib/cpExtensions/Visualization/MeshMapper.hxx | 224 ++ .../Visualization/OpenGLMeshMapper.h | 78 + .../Visualization/OpenGLMeshMapper.hxx | 672 +++++ .../Visualization/SeedWidgetCorrector.cxx | 79 + .../Visualization/SeedWidgetCorrector.h | 45 + lib/cpPipelineEditor/Block.cxx | 301 ++ lib/cpPipelineEditor/Block.h | 85 + lib/cpPipelineEditor/CMakeLists.txt | 55 + lib/cpPipelineEditor/Canvas.cxx | 160 ++ lib/cpPipelineEditor/Canvas.h | 50 + lib/cpPipelineEditor/Connection.cxx | 140 + lib/cpPipelineEditor/Connection.h | 56 + lib/cpPipelineEditor/Editor.cxx | 598 ++++ lib/cpPipelineEditor/Editor.h | 131 + lib/cpPipelineEditor/Port.cxx | 292 ++ lib/cpPipelineEditor/Port.h | 169 ++ lib/cpPlugins/BaseWidget.cxx | 59 + lib/cpPlugins/BaseWidget.h | 60 + lib/cpPlugins/CMakeLists.txt | 133 + lib/cpPlugins/Config.h.in | 112 + lib/cpPlugins/DataObject.cxx | 81 + lib/cpPlugins/DataObject.h | 51 + lib/cpPlugins/Image.cxx | 41 + lib/cpPlugins/Image.h | 55 + lib/cpPlugins/Image.hxx | 149 + lib/cpPlugins/Interface.cxx | 157 ++ lib/cpPlugins/Interface.h | 41 + lib/cpPlugins/Object.cxx | 116 + lib/cpPlugins/Object.h | 86 + lib/cpPlugins/Object.hxx | 38 + lib/cpPlugins/Parameters.cxx | 348 +++ lib/cpPlugins/Parameters.h | 308 ++ lib/cpPlugins/ParametersQtDialog.cxx | 858 ++++++ lib/cpPlugins/ParametersQtDialog.h | 68 + lib/cpPlugins/Port.cxx | 135 + lib/cpPlugins/Port.h | 82 + lib/cpPlugins/ProcessObject.cxx | 294 ++ lib/cpPlugins/ProcessObject.h | 104 + lib/cpPlugins/ProcessObject.hxx | 58 + lib/cpPlugins/Workspace.cxx | 415 +++ lib/cpPlugins/Workspace.h | 152 + lib/cpPlugins/WorkspaceIO.cxx | 195 ++ lib/cpPlugins_ITKInstances/Base.cxx | 6 + lib/cpPlugins_ITKInstances/Base.h | 89 + lib/cpPlugins_ITKInstances/CMakeLists.txt | 78 + lib/cpPlugins_ITKInstances/Config.h | 21 + lib/cpPlugins_ITKInstances/Image.cxx | 19 + lib/cpPlugins_ITKInstances/Image.h | 251 ++ lib/third_party/CMakeLists.txt | 5 + lib/third_party/tinyxml/CMakeLists.txt | 25 + lib/third_party/tinyxml/readme.md | 324 +++ lib/third_party/tinyxml/tinyxml2.cpp | 2467 +++++++++++++++++ lib/third_party/tinyxml/tinyxml2.h | 2102 ++++++++++++++ plugins/CMakeLists.txt | 7 + plugins/cpPluginsIO/CMakeLists.txt | 73 + plugins/cpPluginsIO/DataReproducer.cxx | 32 + plugins/cpPluginsIO/DataReproducer.h | 41 + plugins/cpPluginsIO/DicomSeriesReader.cxx | 233 ++ plugins/cpPluginsIO/DicomSeriesReader.h | 42 + plugins/cpPluginsIO/ImageReader.cxx | 220 ++ plugins/cpPluginsIO/ImageReader.h | 52 + plugins/cpPluginsIO/ImageWriter.cxx | 75 + plugins/cpPluginsIO/ImageWriter.h | 47 + .../BinaryThresholdImageFilter.cxx | 93 + .../BinaryThresholdImageFilter.h | 47 + plugins/cpPluginsImageFilters/CMakeLists.txt | 74 + .../OtsuThresholdImageFilter.cxx | 88 + .../OtsuThresholdImageFilter.h | 47 + .../SignedMaurerDistanceMapImageFilter.cxx | 106 + .../SignedMaurerDistanceMapImageFilter.h | 52 + plugins/cpPluginsWidgets/CMakeLists.txt | 74 + plugins/cpPluginsWidgets/SeedWidget.cxx | 214 ++ plugins/cpPluginsWidgets/SeedWidget.h | 56 + 250 files changed, 30361 insertions(+), 7196 deletions(-) create mode 100644 appli/CMakeLists.txt create mode 100644 appli/PipelineEditor/CMakeLists.txt create mode 100644 appli/PipelineEditor/PipelineEditor.cxx create mode 100644 appli/PipelineEditor/PipelineEditor.h create mode 100644 appli/PipelineEditor/PipelineEditor.ui create mode 100644 appli/PipelineEditor/main.cxx create mode 100644 appli/bash/CMakeLists.txt create mode 100644 appli/bash/cpPlugins_HostCreator.cxx create mode 100644 appli/examples/CMakeLists.txt create mode 100644 appli/examples/example_LoadPluginsFile.cxx create mode 100644 appli/examples/example_ReadWriteImage.cxx create mode 100644 appli/examples/example_ReadWriteImageWithWorkspace.cxx create mode 100644 cmake/CMakeLists.txt 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 delete mode 100644 doc/third_party/Pluma/build/Doxyfile delete mode 100644 doc/third_party/Pluma/build/Doxygen.hpp delete mode 100644 doc/third_party/Pluma/build/doxygen.css delete mode 100644 doc/third_party/Pluma/build/footer.htm delete mode 100644 doc/third_party/Pluma/build/header.htm delete mode 100644 doc/third_party/Pluma/html/Config_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Connector_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/DLibrary_8cpp_source.htm delete mode 100644 doc/third_party/Pluma/html/DLibrary_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Dir_8cpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Dir_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Doxygen_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Host_8cpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Host_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/PluginManager_8cpp_source.htm delete mode 100644 doc/third_party/Pluma/html/PluginManager_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Pluma_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Pluma_8inl_source.htm delete mode 100644 doc/third_party/Pluma/html/Provider_8cpp_source.htm delete mode 100644 doc/third_party/Pluma/html/Provider_8hpp_source.htm delete mode 100644 doc/third_party/Pluma/html/annotated.htm delete mode 100644 doc/third_party/Pluma/html/bc_s.png delete mode 100644 doc/third_party/Pluma/html/bdwn.png delete mode 100644 doc/third_party/Pluma/html/classes.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1DLibrary-members.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1DLibrary.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Host-members.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Host.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1PluginManager-members.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1PluginManager.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1PluginManager.png delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Pluma-members.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Pluma.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Pluma.png delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Provider-members.htm delete mode 100644 doc/third_party/Pluma/html/classpluma_1_1Provider.htm delete mode 100644 doc/third_party/Pluma/html/closed.png delete mode 100644 doc/third_party/Pluma/html/doxygen.css delete mode 100644 doc/third_party/Pluma/html/doxygen.png delete mode 100644 doc/third_party/Pluma/html/dynsections.js delete mode 100644 doc/third_party/Pluma/html/files.htm delete mode 100644 doc/third_party/Pluma/html/ftv2blank.png delete mode 100644 doc/third_party/Pluma/html/ftv2cl.png delete mode 100644 doc/third_party/Pluma/html/ftv2doc.png delete mode 100644 doc/third_party/Pluma/html/ftv2folderclosed.png delete mode 100644 doc/third_party/Pluma/html/ftv2folderopen.png delete mode 100644 doc/third_party/Pluma/html/ftv2lastnode.png delete mode 100644 doc/third_party/Pluma/html/ftv2link.png delete mode 100644 doc/third_party/Pluma/html/ftv2mlastnode.png delete mode 100644 doc/third_party/Pluma/html/ftv2mnode.png delete mode 100644 doc/third_party/Pluma/html/ftv2mo.png delete mode 100644 doc/third_party/Pluma/html/ftv2node.png delete mode 100644 doc/third_party/Pluma/html/ftv2ns.png delete mode 100644 doc/third_party/Pluma/html/ftv2plastnode.png delete mode 100644 doc/third_party/Pluma/html/ftv2pnode.png delete mode 100644 doc/third_party/Pluma/html/ftv2splitbar.png delete mode 100644 doc/third_party/Pluma/html/ftv2vertline.png delete mode 100644 doc/third_party/Pluma/html/functions.htm delete mode 100644 doc/third_party/Pluma/html/functions_func.htm delete mode 100644 doc/third_party/Pluma/html/hierarchy.htm delete mode 100644 doc/third_party/Pluma/html/index.htm delete mode 100644 doc/third_party/Pluma/html/logo.png delete mode 100644 doc/third_party/Pluma/html/nav_f.png delete mode 100644 doc/third_party/Pluma/html/nav_g.png delete mode 100644 doc/third_party/Pluma/html/nav_h.png delete mode 100644 doc/third_party/Pluma/html/open.png delete mode 100644 doc/third_party/Pluma/html/sync_off.png delete mode 100644 doc/third_party/Pluma/html/sync_on.png delete mode 100644 doc/third_party/Pluma/html/tab_a.png delete mode 100644 doc/third_party/Pluma/html/tab_b.png delete mode 100644 doc/third_party/Pluma/html/tab_h.png delete mode 100644 doc/third_party/Pluma/html/tab_s.png delete mode 100644 doc/third_party/Pluma/html/tabs.css create mode 100644 lib/CMakeLists.txt create mode 100644 lib/ItkVtkGlue/CMakeLists.txt create mode 100644 lib/ItkVtkGlue/itkImageToVTKImageFilter.h create mode 100644 lib/ItkVtkGlue/itkImageToVTKImageFilter.hxx create mode 100644 lib/ItkVtkGlue/itkVTKImageToImageFilter.h create mode 100644 lib/ItkVtkGlue/itkVTKImageToImageFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/BezierCurveFunction.h create mode 100644 lib/cpExtensions/Algorithms/BezierCurveFunction.hxx create mode 100644 lib/cpExtensions/Algorithms/GradientFunctionBase.h create mode 100644 lib/cpExtensions/Algorithms/GradientFunctionBase.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/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/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/SpatialObjectMaskImageFilter.h create mode 100644 lib/cpExtensions/Algorithms/SpatialObjectMaskImageFilter.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/ITKAndVTKImage.h create mode 100644 lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.h create mode 100644 lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.hxx create mode 100644 lib/cpExtensions/DataStructures/QuadEdge.h create mode 100644 lib/cpExtensions/DataStructures/QuadEdge.hxx create mode 100644 lib/cpExtensions/DataStructures/QuadEdgeCell.h create mode 100644 lib/cpExtensions/DataStructures/QuadEdgeCell.hxx create mode 100644 lib/cpExtensions/DataStructures/QuadEdgeIterators.h create mode 100644 lib/cpExtensions/DataStructures/QuadEdgeIterators.hxx create mode 100644 lib/cpExtensions/DataStructures/QuadEdgeMesh.h create mode 100644 lib/cpExtensions/DataStructures/QuadEdgeMesh.hxx create mode 100644 lib/cpExtensions/DataStructures/VectorValuesContainer.h create mode 100644 lib/cpExtensions/IO/MementoState.cxx create mode 100644 lib/cpExtensions/IO/MementoState.h create mode 100644 lib/cpExtensions/IO/MeshReader.h create mode 100644 lib/cpExtensions/IO/MeshReader.hxx create mode 100644 lib/cpExtensions/IO/WaveFrontOBJReader.h create mode 100644 lib/cpExtensions/IO/WaveFrontOBJReader.hxx 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/Interaction/SphereWidget.cxx create mode 100644 lib/cpExtensions/Interaction/SphereWidget.h 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/Visualization/Image3DMPR.cxx create mode 100644 lib/cpExtensions/Visualization/Image3DMPR.h create mode 100644 lib/cpExtensions/Visualization/ImageBlender.cxx create mode 100644 lib/cpExtensions/Visualization/ImageBlender.h create mode 100644 lib/cpExtensions/Visualization/ImageSliceActors.cxx create mode 100644 lib/cpExtensions/Visualization/ImageSliceActors.h create mode 100644 lib/cpExtensions/Visualization/MPRActors.cxx create mode 100644 lib/cpExtensions/Visualization/MPRActors.h create mode 100644 lib/cpExtensions/Visualization/MPRObjects.cxx create mode 100644 lib/cpExtensions/Visualization/MPRObjects.h create mode 100644 lib/cpExtensions/Visualization/MeshMapper.h create mode 100644 lib/cpExtensions/Visualization/MeshMapper.hxx create mode 100644 lib/cpExtensions/Visualization/OpenGLMeshMapper.h create mode 100644 lib/cpExtensions/Visualization/OpenGLMeshMapper.hxx create mode 100644 lib/cpExtensions/Visualization/SeedWidgetCorrector.cxx create mode 100644 lib/cpExtensions/Visualization/SeedWidgetCorrector.h create mode 100644 lib/cpPipelineEditor/Block.cxx create mode 100644 lib/cpPipelineEditor/Block.h create mode 100644 lib/cpPipelineEditor/CMakeLists.txt create mode 100644 lib/cpPipelineEditor/Canvas.cxx create mode 100644 lib/cpPipelineEditor/Canvas.h create mode 100644 lib/cpPipelineEditor/Connection.cxx create mode 100644 lib/cpPipelineEditor/Connection.h create mode 100644 lib/cpPipelineEditor/Editor.cxx create mode 100644 lib/cpPipelineEditor/Editor.h create mode 100644 lib/cpPipelineEditor/Port.cxx create mode 100644 lib/cpPipelineEditor/Port.h create mode 100644 lib/cpPlugins/BaseWidget.cxx create mode 100644 lib/cpPlugins/BaseWidget.h 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/Interface.cxx create mode 100644 lib/cpPlugins/Interface.h 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/Parameters.cxx create mode 100644 lib/cpPlugins/Parameters.h create mode 100644 lib/cpPlugins/ParametersQtDialog.cxx create mode 100644 lib/cpPlugins/ParametersQtDialog.h 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/Workspace.cxx create mode 100644 lib/cpPlugins/Workspace.h create mode 100644 lib/cpPlugins/WorkspaceIO.cxx create mode 100644 lib/cpPlugins_ITKInstances/Base.cxx create mode 100644 lib/cpPlugins_ITKInstances/Base.h create mode 100644 lib/cpPlugins_ITKInstances/CMakeLists.txt create mode 100644 lib/cpPlugins_ITKInstances/Config.h create mode 100644 lib/cpPlugins_ITKInstances/Image.cxx create mode 100644 lib/cpPlugins_ITKInstances/Image.h create mode 100644 lib/third_party/CMakeLists.txt create mode 100644 lib/third_party/tinyxml/CMakeLists.txt create mode 100644 lib/third_party/tinyxml/readme.md create mode 100644 lib/third_party/tinyxml/tinyxml2.cpp create mode 100644 lib/third_party/tinyxml/tinyxml2.h create mode 100644 plugins/CMakeLists.txt create mode 100644 plugins/cpPluginsIO/CMakeLists.txt create mode 100644 plugins/cpPluginsIO/DataReproducer.cxx create mode 100644 plugins/cpPluginsIO/DataReproducer.h create mode 100644 plugins/cpPluginsIO/DicomSeriesReader.cxx create mode 100644 plugins/cpPluginsIO/DicomSeriesReader.h create mode 100644 plugins/cpPluginsIO/ImageReader.cxx create mode 100644 plugins/cpPluginsIO/ImageReader.h create mode 100644 plugins/cpPluginsIO/ImageWriter.cxx create mode 100644 plugins/cpPluginsIO/ImageWriter.h create mode 100644 plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.cxx create mode 100644 plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.h create mode 100644 plugins/cpPluginsImageFilters/CMakeLists.txt create mode 100644 plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.cxx create mode 100644 plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.h create mode 100644 plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.cxx create mode 100644 plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.h create mode 100644 plugins/cpPluginsWidgets/CMakeLists.txt create mode 100644 plugins/cpPluginsWidgets/SeedWidget.cxx create mode 100644 plugins/cpPluginsWidgets/SeedWidget.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 823705e..97d52ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,20 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) - -## ============ -## = Policies = -## ============ - -SET( - policies - CMP0015 - CMP0020 - CMP0042 - ) -FOREACH(policy ${policies}) - IF(POLICY ${policy}) - CMAKE_POLICY(SET ${policy} NEW) - ENDIF(POLICY ${policy}) -ENDFOREACH(policy) +INCLUDE(cmake/cpPlugins_Policies.cmake) ## ================ ## = Project name = @@ -22,136 +7,42 @@ ENDFOREACH(policy) PROJECT(cpPlugins) SET(prj_MAJ_VER "0") -SET(prj_MIN_VER "0") -SET(prj_REL_VER "2") -SET(prj_VERSION "${prj_MAJ_VER}.${prj_MIN_VER}.${prj_REL_VER}") +SET(prj_MIN_VER "1") +SET(prj_REL_VER "0") +SET(prj_VER "${prj_MAJ_VER}.${prj_MIN_VER}.${prj_REL_VER}") +SET(prj_sVER "${prj_MAJ_VER}") ## =========== ## = Options = ## =========== -OPTION(USE_QT4 "Build Qt4-based code" OFF) OPTION(BUILD_EXAMPLES "Build examples" OFF) -SET(LIBRARY_TYPE SHARED) - ## ======================== ## = Packages and options = ## ======================== -# Force c++11 language version -# NOTE: It seems that by default on Visual Studio Compiler supports c++11, -# so it only need to be test on other O.S. -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 to build shared libs (windows) -INCLUDE(GenerateExportHeader) - -# 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) - -SET(QT4_FOUND "0") -IF(USE_QT4) - FIND_PACKAGE(Qt4 REQUIRED) - INCLUDE(${QT_USE_FILE}) - - ## Check for required vtk-qt4 modules - SET( - vtk_required_modules - vtkGUISupportQt - vtkGUISupportQtOpenGL - ) - FOREACH(vtk_module ${vtk_required_modules}) - IF(NOT ${vtk_module}_LOADED) - MESSAGE( - FATAL_ERROR - "${vtk_module} module is required but not available." - ) - SET(QT4_FOUND "0") - ENDIF(NOT ${vtk_module}_LOADED) - ENDFOREACH(vtk_module) - SET(QT4_FOUND "1") -ENDIF(USE_QT4) - -## ================================================ -## = 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}) +INCLUDE(cmake/cpPlugins_Options.cmake) +INCLUDE(cmake/cpPlugins_KitwareTools.cmake) +INCLUDE(cmake/cpPlugins_Qt4Tools.cmake) -## ===================================== -## = Where to put 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 - ) - -## ============================== -## = Subdirs containing headers = -## ============================== +## ======================= +## = Include directories = +## ======================= INCLUDE_DIRECTORIES( + ${PROJECT_SOURCE_DIR} + ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/lib - ${PROJECT_SOURCE_DIR}/lib/third_party - ${PROJECT_SOURCE_DIR}/lib/third_party/ItkVtkGlue ${PROJECT_BINARY_DIR}/lib + ${PROJECT_SOURCE_DIR}/plugins + ${PROJECT_BINARY_DIR}/plugins + ${PROJECT_SOURCE_DIR}/lib/third_party ${PROJECT_BINARY_DIR}/lib/third_party - ${PROJECT_BINARY_DIR}/lib/third_party/ItkVtkGlue - ) -IF(WIN32 OR APPLE) - INCLUDE_DIRECTORIES( - ${PROJECT_SOURCE_DIR}/lib/third_party/glext - ) -ENDIF(WIN32 OR APPLE) - -## ======================= -## = Local bash commands = -## ======================= -SET( - bash_PROGRAMS - cpPlugins_createHost + ${PROJECT_SOURCE_DIR}/lib/ItkVtkGlue + ${PROJECT_BINARY_DIR}/lib/ItkVtkGlue ) -FOREACH(prog ${bash_PROGRAMS}) - IF(MSVC) - SET(${prog}_APP ${PROJECT_BINARY_DIR}/$(ConfigurationName)/${prog}) - ELSE(MSVC) - SET(${prog}_APP ${PROJECT_BINARY_DIR}/${prog}) - ENDIF(MSVC) -ENDFOREACH(prog) - ## =========================== ## = Subdirs containing code = ## =========================== @@ -159,6 +50,7 @@ ENDFOREACH(prog) SUBDIRS( cmake lib + plugins appli ) diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt new file mode 100644 index 0000000..a290efe --- /dev/null +++ b/appli/CMakeLists.txt @@ -0,0 +1,17 @@ +SUBDIRS( + bash + ) +IF(BUILD_EXAMPLES) + SUBDIRS( + examples + ) +ENDIF(BUILD_EXAMPLES) + +IF(USE_QT4) + SUBDIRS( + PipelineEditor + ) +ENDIF(USE_QT4) + + +## eof - $RCSfile$ diff --git a/appli/PipelineEditor/CMakeLists.txt b/appli/PipelineEditor/CMakeLists.txt new file mode 100644 index 0000000..33f7148 --- /dev/null +++ b/appli/PipelineEditor/CMakeLists.txt @@ -0,0 +1,51 @@ +SET(App_NAME "PipelineEditor") +SET(Dir_NAME "PipelineEditor") + +## ==================================================== +## = Source code, user interafaces and resources here = +## ==================================================== + +SET(App_SOURCE_DIR "${PROJECT_SOURCE_DIR}/appli/${Dir_NAME}") +SET(App_BINARY_DIR "${PROJECT_BINARY_DIR}/appli/${Dir_NAME}") +SET(App_QT_SOURCES PipelineEditor.cxx) +SET(App_SOURCES main.cxx) +SET(App_QT_HEADERS PipelineEditor.h) +FILE(GLOB App_QT_UI "${App_SOURCE_DIR}/*.ui") +FILE(GLOB App_QT_RES "${App_SOURCE_DIR}/*.qrc") + +## ===================== +## = Compilation rules = +## ===================== +INCLUDE_DIRECTORIES( + ${App_SOURCE_DIR} + ${App_BINARY_DIR} + ) + +QT4_WRAP_UI(App_QT_UI_Headers ${App_QT_UI}) +QT4_WRAP_CPP(App_QT_HEADERS_MOC_SOURCES ${App_QT_HEADERS}) +QT4_ADD_RESOURCES(App_QT_RES_SOURCES ${App_QT_RES}) + +SET(GUI_TYPE "") +IF(WIN32) + SET(GUI_TYPE WIN32) +ENDIF(WIN32) +IF(APPLE) + SET(GUI_TYPE MACOSX_BUNDLE) +ENDIF(APPLE) + +ADD_EXECUTABLE( + ${App_NAME} + ${GUI_TYPE} + ${App_QT_UI_Headers} + ${App_SOURCES} + ${App_QT_SOURCES} + ${App_QT_HEADERS_MOC_SOURCES} + ${App_QT_RES_SOURCES} + ) +TARGET_LINK_LIBRARIES( + ${App_NAME} + cpExtensions + cpPipelineEditor + ) + +## eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditor.cxx b/appli/PipelineEditor/PipelineEditor.cxx new file mode 100644 index 0000000..139ae71 --- /dev/null +++ b/appli/PipelineEditor/PipelineEditor.cxx @@ -0,0 +1,390 @@ +#include "PipelineEditor.h" +#include "ui_PipelineEditor.h" + +#include + +#include +#include + +#include +#include + +#include + +// ------------------------------------------------------------------------- +#define PipelineEditor_ConnectAction( ACTION ) \ + this->connect( \ + this->m_UI->Action##ACTION, SIGNAL( triggered( ) ), \ + this, SLOT( _Action##ACTION( ) ) \ + ) + +// ------------------------------------------------------------------------- +#define PipelineEditor_ConnectButton( BUTTON ) \ + this->connect( \ + this->m_UI->Button##BUTTON, SIGNAL( clicked( ) ), \ + this, SLOT( _Button##BUTTON( ) ) \ + ) + +// ------------------------------------------------------------------------- +PipelineEditor:: +PipelineEditor( int argc, char* argv[], QWidget* parent ) + : QMainWindow( parent ), + m_UI( new Ui::PipelineEditor ), + m_Workspace( NULL ), + m_PluginsPath( "." ) +{ + this->m_UI->setupUi( this ); + + // Prepare plugins interface + QFileInfo info( argv[ 0 ] ); + if( info.exists( ) ) + { + this->m_PluginsPath = info.canonicalPath( ).toStdString( ); + this->_LoadPluginsFromPath( this->m_PluginsPath ); + + } // fi + + /* TODO + this->m_Interface = new cpPlugins::Interface( ); + this->m_PluginsPath = info.canonicalPath( ).toStdString( ); + if( !( this->m_Interface->LoadDefaultConfiguration( this->m_PluginsPath ) ) ) + if( this->m_Interface->LoadFromFolder( this->m_PluginsPath, false ) != "" ) + if( !( this->m_Interface->SaveDefaultConfiguration( this->m_PluginsPath ) ) ) + QMessageBox::critical( + this, + "Error creating default plugins configuration", + "Could not save default plugins configuration" + ); + this->_UpdateLoadedPlugins( ); + + } // fi + */ + + // Create an empty workspace + this->m_Workspace = new cpPlugins::Workspace( ); + this->m_Workspace->SetInterface( &( this->m_Interface ) ); + this->m_UI->Canvas->editor( )->setWorkspace( this->m_Workspace ); + this->m_Workspace->SetMPRViewer( this->m_UI->Viewer ); + + // Connect actions to slots + PipelineEditor_ConnectButton( LoadPluginsFile ); + PipelineEditor_ConnectButton( LoadPluginsPath ); + PipelineEditor_ConnectAction( OpenWorkspace ); + PipelineEditor_ConnectAction( SaveWorkspace ); + this->connect( + this->m_UI->Canvas->editor( ), + SIGNAL( execFilter( const std::string& ) ), + this, + SLOT( _ExecFilter( const std::string& ) ) + ); + this->connect( + this->m_UI->Canvas->editor( ), + SIGNAL( showFilterOutput( const std::string&, const std::string& ) ), + this, + SLOT( _ShowFilterOutput( const std::string&, const std::string& ) ) + ); +} + +// ------------------------------------------------------------------------- +PipelineEditor:: +~PipelineEditor( ) +{ + if( this->m_Workspace != NULL ) + delete this->m_Workspace; + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_LoadPluginsFromPath( const std::string& path ) +{ + QDir dir( path.c_str( ) ); + std::stringstream filters_str; + filters_str << "*." << cpPlugins_PLUGIN_EXT; + QStringList filters; + filters << filters_str.str( ).c_str( ); + auto files = dir.entryList( filters ); + for( auto fIt = files.begin( ); fIt != files.end( ); ++fIt ) + { + try + { + this->m_Interface.LoadPluginFile( fIt->toStdString( ) ); + } + catch( ... ) + { + // Just ignore un-loadable libraries + } + + } // yrt + this->_UpdateLoadedPlugins( ); +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_UpdateLoadedPlugins( ) +{ + auto filters = this->m_Interface.GetFilters( ); + if( filters.size( ) == 0 ) + { + QMessageBox::critical( + this, + "Error loading default plugins", + "No plugins loaded: remember to load some!!!" + ); + return; + + } // fi + + for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) + { + // Create or get category + QList< QTreeWidgetItem* > cat_items = + this->m_UI->LoadedPlugins->findItems( + cIt->first.c_str( ), Qt::MatchExactly | Qt::MatchRecursive + ); + QTreeWidgetItem* cat = NULL; + if( cat_items.size( ) == 0 ) + { + cat = new QTreeWidgetItem( + ( QTreeWidgetItem* )( NULL ), QStringList( cIt->first.c_str( ) ) + ); + this->m_UI->LoadedPlugins->addTopLevelItem( cat ); + } + else + cat = cat_items[ 0 ]; + + // Create filters + auto fIt = cIt->second.begin( ); + for( ; fIt != cIt->second.end( ); ++fIt ) + { + QList< QTreeWidgetItem* > filter_items = + this->m_UI->LoadedPlugins->findItems( + fIt->first.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->first.c_str( ) ) + ); + + } // rof + + } // rof +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_ButtonLoadPluginsFile( ) +{ + /* + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::ExistingFiles ); + dlg.setDirectory( "." ); + + std::stringstream name_filter; + std::string suffix = std::string( cpPlugins_PLUGIN_EXT ).substr( 1 ); + + name_filter << "Plugins file (*" << cpPlugins_PLUGIN_EXT << ");;All files (*)"; + dlg.setNameFilter( name_filter.str( ).c_str( ) ); + dlg.setDefaultSuffix( suffix.c_str( ) ); + + if( !( dlg.exec( ) ) ) + return; + + // Read + QStringList names = dlg.selectedFiles( ); + std::stringstream err_str; + for( auto qIt = names.begin( ); qIt != names.end( ); ++qIt ) + err_str << this->m_Interface->Load( qIt->toStdString( ) ); + + // Show an error message + std::string err = err_str.str( ); + if( err.size( ) > 0 ) + QMessageBox::critical( + this, + "Error loading plugins", + err.c_str( ) + ); + + // Update view + this->m_Interface->SaveDefaultConfiguration( this->m_PluginsPath ); + this->_UpdateLoadedPlugins( ); + */ +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_ButtonLoadPluginsPath( ) +{ + /* + QFileDialog dlg( this ); + dlg.setFileMode( QFileDialog::DirectoryOnly ); + dlg.setDirectory( "." ); + if( !( dlg.exec( ) ) ) + return; + + // Read + std::string dir = dlg.selectedFiles( ).begin( )->toStdString( ); + std::string err = this->m_Interface->LoadFromFolder( dir, false ); + if( err != "" ) + QMessageBox::critical( + this, + "Error loading plugins directory", + err.c_str( ) + ); + + // Update view + this->m_Interface->SaveDefaultConfiguration( this->m_PluginsPath ); + this->_UpdateLoadedPlugins( ); + */ +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_ActionOpenWorkspace( ) +{ + 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; + std::string fname = dlg.selectedFiles( ).at( 0 ).toStdString( ); + + if( this->m_Workspace != NULL ) + delete this->m_Workspace; + this->m_Workspace = new cpPlugins::Workspace( ); + this->m_Workspace->SetInterface( &( this->m_Interface ) ); + this->m_Workspace->SetMPRViewer( this->m_UI->Viewer ); + std::string err = this->m_Workspace->LoadWorkspace( fname ); + if( err != "" ) + { + delete this->m_Workspace; + this->m_Workspace = NULL; + QMessageBox::critical( + this, + QMessageBox::tr( "Error loading workspace" ), + QMessageBox::tr( err.c_str( ) ) + ); + } + else + this->m_UI->Canvas->editor( )->setWorkspace( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_ActionSaveWorkspace( ) +{ + if( this->m_Workspace == NULL ) + return; + + 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; + std::string fname = dlg.selectedFiles( ).at( 0 ).toStdString( ); + + std::string err = this->m_Workspace->SaveWorkspace( fname ); + if( err != "" ) + QMessageBox::critical( + this, + QMessageBox::tr( "Error saving workspace" ), + QMessageBox::tr( err.c_str( ) ) + ); +} + + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_ExecFilter( const std::string& filter_name ) +{ + if( this->m_Workspace != NULL ) + { + // Update filter, if needed + std::string err = this->m_Workspace->Execute( filter_name ); + if( err != "" ) + QMessageBox::critical( + this, + QMessageBox::tr( "Error executing filter" ), + QMessageBox::tr( err.c_str( ) ) + ); + + } // fi +} + +// ------------------------------------------------------------------------- +void PipelineEditor:: +_ShowFilterOutput( + const std::string& filter_name, const std::string& output_name + ) +{ + typedef cpPlugins::DataObject _TDataObject; + + // Update filter, if needed + this->_ExecFilter( filter_name ); + + // Get output + auto filter = this->m_Workspace->GetFilter( filter_name ); + if( filter != NULL ) + { + auto output = filter->GetOutputData( output_name ); + if( output != NULL ) + { + std::string data_name = output_name + "@" + filter_name; + auto idata = output->GetVTK< vtkImageData >( ); + auto mdata = output->GetVTK< vtkPolyData >( ); + if( idata != NULL ) + { + if( this->m_UI->Viewer->AddData( idata, data_name, "" ) ) + { + if( this->m_UI->Viewer->GetNumberOfData( ) > 1 ) + this->m_UI->Viewer->SetDataColor( data_name, 1, 0, 0 ); + else + this->m_UI->Viewer->SetMainImage( data_name ); + this->m_UI->Viewer->ShowData( data_name ); + + } // fi + } + else if( mdata != NULL ) + { + } + else + QMessageBox::critical( + this, + QMessageBox::tr( "Error showing data" ), + QMessageBox::tr( "No known VTK conversion!" ) + ); + + /* TODO + if( this->m_UI->Viewer->AddData( output, data_name, "" ) ) + { + if( this->m_UI->Viewer->GetNumberOfData( ) > 1 ) + this->m_UI->Viewer->SetDataColor( data_name, 1, 0, 0 ); + else + this->m_UI->Viewer->SetMainImage( data_name ); + this->m_UI->Viewer->ShowData( data_name ); + } + else + */ + + } // fi + + } // fi +} + +// eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditor.h b/appli/PipelineEditor/PipelineEditor.h new file mode 100644 index 0000000..ffeeafd --- /dev/null +++ b/appli/PipelineEditor/PipelineEditor.h @@ -0,0 +1,56 @@ +#ifndef __PIPELINEEDITOR__H__ +#define __PIPELINEEDITOR__H__ + +// Qt stuff +#include +#include +#include + +// ------------------------------------------------------------------------- +namespace Ui +{ + class PipelineEditor; +} + +/** + */ +class PipelineEditor + : public QMainWindow +{ + Q_OBJECT; + +public: + typedef PipelineEditor Self; + typedef QMainWindow Superclass; + +public: + explicit PipelineEditor( + int argc, char* argv[], + QWidget* parent = 0 + ); + virtual ~PipelineEditor( ); + +protected: + void _LoadPluginsFromPath( const std::string& path ); + void _UpdateLoadedPlugins( ); + +protected slots: + void _ButtonLoadPluginsFile( ); + void _ButtonLoadPluginsPath( ); + void _ActionOpenWorkspace( ); + void _ActionSaveWorkspace( ); + void _ExecFilter( const std::string& filter_name ); + void _ShowFilterOutput( + const std::string& filter_name, const std::string& output_name + ); + +private: + Ui::PipelineEditor* m_UI; + cpPlugins::Workspace* m_Workspace; + cpPlugins::Interface m_Interface; + std::string m_PluginsPath; +}; + +#endif // __CPPIPELINEEDITOR__H__ + +// eof - $RCSfile$ diff --git a/appli/PipelineEditor/PipelineEditor.ui b/appli/PipelineEditor/PipelineEditor.ui new file mode 100644 index 0000000..4a3e330 --- /dev/null +++ b/appli/PipelineEditor/PipelineEditor.ui @@ -0,0 +1,235 @@ + + + PipelineEditor + + + + 0 + 0 + 800 + 600 + + + + + 800 + 600 + + + + MainWindow + + + + + + + Qt::Vertical + + + + + 0 + 200 + + + + + + Qt::Horizontal + + + + + 251 + 331 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 202 + 67 + + + + + 202 + 67 + + + + Plugins + + + + + + + 85 + 31 + + + + + 85 + 31 + + + + File + + + + + + + + 85 + 31 + + + + + 85 + 31 + + + + Path + + + + + + + + + + + 229 + 0 + + + + true + + + QAbstractItemView::DragOnly + + + true + + + true + + + + Loaded plugins + + + + + + + + + + 500 + 0 + + + + true + + + + + + + + + + + 0 + 0 + 800 + 27 + + + + + &File + + + + Workspace + + + + + + + + + + + + + + Open + + + + + Save + + + + + E&xit + + + + + + cpPipelineEditor::Canvas + QWidget +
cpPipelineEditor/Canvas.h
+ 1 +
+ + cpExtensions::QT::SimpleMPRWidget + QWidget +
cpExtensions/QT/SimpleMPRWidget.h
+ 1 +
+
+ + + + ActionExit + triggered() + PipelineEditor + close() + + + -1 + -1 + + + 399 + 299 + + + + +
diff --git a/appli/PipelineEditor/main.cxx b/appli/PipelineEditor/main.cxx new file mode 100644 index 0000000..2013a69 --- /dev/null +++ b/appli/PipelineEditor/main.cxx @@ -0,0 +1,81 @@ +#include "PipelineEditor.h" +#include +#include + +// ------------------------------------------------------------------------- +int main( int argc, char* argv[] ) +{ + QApplication a( argc, argv ); + PipelineEditor w( argc, argv, NULL ); + w.show( ); + + return( a.exec( ) ); +} + +// ------------------------------------------------------------------------- +#ifdef _WIN32 + +#include +#include +#include +#include + +/** + */ +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 ); + } +}; + +int CALLBACK WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow + ) +{ + Win32CommandLineConverter cmd_line; + return( main( cmd_line.argc( ), cmd_line.argv( ) ) ); +} + +#endif + +// eof - $RCSfile$ diff --git a/appli/bash/CMakeLists.txt b/appli/bash/CMakeLists.txt new file mode 100644 index 0000000..2eac91c --- /dev/null +++ b/appli/bash/CMakeLists.txt @@ -0,0 +1,16 @@ +SET( + bash_SOURCES + cpPlugins_HostCreator + ) + +FOREACH(program ${bash_SOURCES}) + ADD_EXECUTABLE(${program} ${program}.cxx) + INSTALL( + TARGETS ${program} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + ) +ENDFOREACH(program) + +## eof - $RCSfile$ diff --git a/appli/bash/cpPlugins_HostCreator.cxx b/appli/bash/cpPlugins_HostCreator.cxx new file mode 100644 index 0000000..6721271 --- /dev/null +++ b/appli/bash/cpPlugins_HostCreator.cxx @@ -0,0 +1,169 @@ +#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( 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 < 3 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " output_file header_file_0.h header_file_0.h ..." + << std::endl; + return( 1 ); + + } // fi + + // Parse all header files + TInfo info; + for( int i = 2; 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[ 1 ] ); + + // Write include section + out_stream + << "#include " << std::endl + << "#include " << std::endl; + for( int i = 2; i < argc; ++i ) + out_stream << "#include \"" << argv[ i ] << "\"" < > " + << "LoadedFilters( )" << std::endl << "{" << std::endl + << " std::map< std::string, std::set< std::string > > classes;" + << std::endl; + int i = 0; + for( auto iIt = info.begin( ); iIt != info.end( ); ++iIt ) + { + for( auto jIt = iIt->second.begin( ); jIt != iIt->second.end( ); ++jIt ) + { + out_stream + << " auto f" << i << " = " + << jIt->second << "::" << jIt->first + << "::New( );" << std::endl + << " classes[ f" << i << "->GetClassCategory( ) ].insert( " + << "f" << i << "->GetClassName( ) );" << std::endl; + i++; + + } // rof + + } // rof + out_stream + << " return( classes );" << 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\" cpPlugins::ProcessObject::Pointer " + << iIt->first << "_" << jIt->first + << "( )" << std::endl << "{" << std::endl + << std::endl + << " cpPlugins::ProcessObject::Pointer p;" << std::endl + << " " << jIt->second << "::" << jIt->first << "::Pointer f = " + << jIt->second << "::" << jIt->first << "::New( );" << std::endl + << " p = f.GetPointer( );" << std::endl << " return( p );" + << 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..020c854 --- /dev/null +++ b/appli/examples/CMakeLists.txt @@ -0,0 +1,13 @@ +SET( + examples_SOURCES + example_LoadPluginsFile + example_ReadWriteImage + example_ReadWriteImageWithWorkspace + ) + +FOREACH(example ${examples_SOURCES}) + ADD_EXECUTABLE(${example} ${example}.cxx) + TARGET_LINK_LIBRARIES(${example} cpPlugins) +ENDFOREACH(example) + +## eof - $RCSfile$ diff --git a/appli/examples/example_LoadPluginsFile.cxx b/appli/examples/example_LoadPluginsFile.cxx new file mode 100644 index 0000000..e43f383 --- /dev/null +++ b/appli/examples/example_LoadPluginsFile.cxx @@ -0,0 +1,44 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 2 ) + { + std::cerr << "Usage: " << argv[ 0 ] << " plugins_library" << std::endl; + return( 1 ); + + } // fi + + // Load interface + cpPlugins::Interface interface; + try + { + interface.LoadPluginFile( argv[ 1 ] ); + } + catch( std::exception& err ) + { + std::cerr + << "Interface load failed on \"" << argv[ 1 ] << "\": " + << err.what( ) + << std::endl; + return( 1 ); + + } // fi + + // Show loaded filters + auto filters = interface.GetFilters( ); + for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) + { + std::cout << "Category: " << cIt->first << std::endl; + for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt ) + std::cout + << "\tFilter: " << nIt->first + << " (" << nIt->second << ")" + << std::endl; + + } // rof + return( 0 ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_ReadWriteImage.cxx b/appli/examples/example_ReadWriteImage.cxx new file mode 100644 index 0000000..50b8f43 --- /dev/null +++ b/appli/examples/example_ReadWriteImage.cxx @@ -0,0 +1,95 @@ +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " plugins_library input_image(s) output_image" << std::endl; + return( 1 ); + + } // fi + + // Load interface + int ret = 0; + cpPlugins::Interface interface; + try + { + interface.LoadPluginFile( argv[ 1 ] ); + } + catch( std::exception& err ) + { + std::cerr + << "Interface load failed on \"" << argv[ 1 ] << "\": " + << err.what( ) + << std::endl; + ret = 1; + + } // fi + + // Create filters + cpPlugins::ProcessObject::Pointer reader; + cpPlugins::ProcessObject::Pointer writer; + try + { + reader = interface.Create( "IO", "ImageReader" ); + if( reader.IsNull( ) ) + { + std::cerr + << "\"IO::ImageReader\" creation failed from \"" + << argv[ 1 ] << "\"" + << std::endl; + ret = 1; + + } // fi + writer = interface.Create( "IO", "ImageWriter" ); + if( writer.IsNull( ) ) + { + std::cerr + << "\"IO::ImageWriter\" creation failed from \"" + << argv[ 1 ] << "\"" + << std::endl; + ret = 1; + + } // fi + } + catch( std::exception& err ) + { + std::cerr + << "Filter creation failed on \"" << argv[ 1 ] << "\": " + << err.what( ) + << std::endl; + ret = 1; + + } // yrt + + if( ret == 0 ) + { + // Configure filters + auto reader_params = reader->GetParameters( ); + for( int i = 2; i < argc - 1; ++i ) + reader_params->AddToOpenFileNameList( "FileNames", argv[ i ] ); + auto writer_params = writer->GetParameters( ); + writer_params->SetOpenFileName( "FileName", argv[ argc - 1 ] ); + + // Connect filters + writer->SetInput( "Input", reader->GetOutput( "Output" ) ); + + // Execute filters + std::string err = writer->Update( ); + if( err != "" ) + { + std::cout << "Error caught: " << err << std::endl; + ret = 1; + + } // fi + + } // fi + + // Ok finish + return( ret ); +} + +// eof - $RCSfile$ diff --git a/appli/examples/example_ReadWriteImageWithWorkspace.cxx b/appli/examples/example_ReadWriteImageWithWorkspace.cxx new file mode 100644 index 0000000..9a82138 --- /dev/null +++ b/appli/examples/example_ReadWriteImageWithWorkspace.cxx @@ -0,0 +1,60 @@ +#include +#include +#include + +int main( int argc, char* argv[] ) +{ + if( argc < 4 ) + { + std::cerr + << "Usage: " << argv[ 0 ] + << " plugins_library input_image(s) output_image" << std::endl; + return( 1 ); + + } // fi + + // Load interface + int ret = 0; + cpPlugins::Interface interface; + try + { + interface.LoadPluginFile( argv[ 1 ] ); + } + catch( std::exception& err ) + { + std::cerr + << "Interface load failed on \"" << argv[ 1 ] << "\": " + << err.what( ) + << std::endl; + ret = 1; + + } // fi + + // Create filters + cpPlugins::Workspace workspace; + workspace.SetInterface( &interface ); + auto reader = workspace.CreateFilter( "IO", "ImageReader", "reader" ); + auto writer = workspace.CreateFilter( "IO", "ImageWriter", "writer" ); + workspace.Connect( "reader", "writer", "Output", "Input" ); + + // Configure filters + auto reader_params = reader->GetParameters( ); + for( int i = 2; i < argc - 1; ++i ) + reader_params->AddToOpenFileNameList( "FileNames", argv[ i ] ); + auto writer_params = writer->GetParameters( ); + writer_params->SetOpenFileName( "FileName", argv[ argc - 1 ] ); + + // Execute + std::string err = workspace.Execute( ); + if( err != "" ) + { + std::cout << "Error caught: " << err << std::endl; + ret = 1; + + } // fi + + // Ok finish + return( ret ); +} + +// eof - $RCSfile$ diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt new file mode 100644 index 0000000..4b26944 --- /dev/null +++ b/cmake/CMakeLists.txt @@ -0,0 +1 @@ +## eof - $RCSfile$ diff --git a/cmake/cpPlugins_KitwareTools.cmake b/cmake/cpPlugins_KitwareTools.cmake new file mode 100644 index 0000000..c920959 --- /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..44b4f8f --- /dev/null +++ b/cmake/cpPlugins_Options.cmake @@ -0,0 +1,48 @@ +# ============================================================================ +# = 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 to build shared libs (windows) +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 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..a26f448 --- /dev/null +++ b/cmake/cpPlugins_Policies.cmake @@ -0,0 +1,13 @@ +SET( + policies + CMP0015 + CMP0020 + CMP0042 + ) +FOREACH(policy ${policies}) + IF(POLICY ${policy}) + CMAKE_POLICY(SET ${policy} NEW) + ENDIF(POLICY ${policy}) +ENDFOREACH(policy) + +## eof - $RCSfile$ diff --git a/cmake/cpPlugins_Qt4Tools.cmake b/cmake/cpPlugins_Qt4Tools.cmake new file mode 100644 index 0000000..d046e6b --- /dev/null +++ b/cmake/cpPlugins_Qt4Tools.cmake @@ -0,0 +1,24 @@ +OPTION(USE_QT4 "Build Qt4-based code" ON) + +SET(QT4_FOUND "0") +IF(USE_QT4) + FIND_PACKAGE(Qt4 REQUIRED) + INCLUDE(${QT_USE_FILE}) + SET( + vtk_required_modules + vtkGUISupportQt + vtkGUISupportQtOpenGL + ) + FOREACH(vtk_module ${vtk_required_modules}) + IF(NOT ${vtk_module}_LOADED) + MESSAGE( + FATAL_ERROR + "${vtk_module} module is required but not available." + ) + SET(QT4_FOUND "0") + ENDIF(NOT ${vtk_module}_LOADED) + ENDFOREACH(vtk_module) + SET(QT4_FOUND "1") +ENDIF(USE_QT4) + +## eof - $RCSfile$ diff --git a/doc/third_party/Pluma/build/Doxyfile b/doc/third_party/Pluma/build/Doxyfile deleted file mode 100644 index b0d5dd6..0000000 --- a/doc/third_party/Pluma/build/Doxyfile +++ /dev/null @@ -1,1597 +0,0 @@ -# Doxyfile 1.6.3 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- - -# This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. - -DOXYFILE_ENCODING = UTF-8 - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = Pluma - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = .. - -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. - -CREATE_SUBDIRS = NO - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. - -OUTPUT_LANGUAGE = English - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" - -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = YES - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all -# inherited members of a class in the documentation of that class as if those -# members were ordinary class members. Constructors, destructors and assignment -# operators of the base classes will not be shown. - -INLINE_INHERITED_MEMB = YES - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. - -STRIP_FROM_PATH = - -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. - -STRIP_FROM_INC_PATH = - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) - -JAVADOC_AUTOBRIEF = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) - -QT_AUTOBRIEF = NO - -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. - -MULTILINE_CPP_IS_BRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. - -INHERIT_DOCS = YES - -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. - -SEPARATE_MEMBER_PAGES = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 4 - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. - -OPTIMIZE_OUTPUT_JAVA = NO - -# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. - -OPTIMIZE_FOR_FORTRAN = NO - -# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. - -OPTIMIZE_OUTPUT_VHDL = NO - -# Doxygen selects the parser to use depending on the extension of the files it parses. -# With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this tag. -# The format is ext=language, where ext is a file extension, and language is one of -# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, -# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat -# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), -# use: inc=Fortran f=C. Note that for custom extensions you also need to set -# FILE_PATTERNS otherwise the files are not read by doxygen. - -EXTENSION_MAPPING = - -# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. - -BUILTIN_STL_SUPPORT = NO - -# If you use Microsoft's C++/CLI language, you should set this option to YES to -# enable parsing support. - -CPP_CLI_SUPPORT = NO - -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. - -SIP_SUPPORT = NO - -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. - -IDL_PROPERTY_SUPPORT = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. - -SUBGROUPING = YES - -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So -# typedef struct TypeS {} TypeT, will appear in the documentation as a struct -# with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound -# types are typedef'ed and only the typedef is referenced, never the tag name. - -TYPEDEF_HIDES_STRUCT = NO - -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols - -SYMBOL_CACHE_SIZE = 0 - -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = NO - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. - -EXTRACT_LOCAL_METHODS = NO - -# If this flag is set to YES, the members of anonymous namespaces will be -# extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. - -EXTRACT_ANON_NSPACES = NO - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. - -HIDE_FRIEND_COMPOUNDS = NO - -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. - -HIDE_IN_BODY_DOCS = NO - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# and Mac users are advised to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. - -FORCE_LOCAL_INCLUDES = NO - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. - -SORT_BRIEF_DOCS = NO - -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. - -SORT_MEMBERS_CTORS_1ST = NO - -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. - -SORT_GROUP_NAMES = NO - -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. -# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. - -SORT_BY_SCOPE_NAME = NO - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. - -GENERATE_DEPRECATEDLIST= YES - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = NO - -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. - -SHOW_FILES = YES - -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. - -SHOW_NAMESPACES = YES - -# The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from -# the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. - -FILE_VERSION_FILTER = - -# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by -# doxygen. The layout file controls the global structure of the generated output files -# in an output format independent way. The create the layout file that represents -# doxygen's defaults, run doxygen with the -l option. You can optionally specify a -# file name after the option, if omitted DoxygenLayout.xml will be used as the name -# of the layout file. - -LAYOUT_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. - -WARN_IF_DOC_ERROR = YES - -# This WARN_NO_PARAMDOC option can be abled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. - -WARN_NO_PARAMDOC = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = ../../../Pluma/ \ - Doxygen.hpp - -# This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. - -INPUT_ENCODING = UTF-8 - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 - -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.dox \ - *.py - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded -# from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* - -EXCLUDE_PATTERNS = .svn \ - Linux \ - Unix \ - OSX* - -# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names -# (namespaces, classes, functions, etc.) that should be excluded from the -# output. The symbol name can be a fully qualified name, a word, or if the -# wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test - -EXCLUDE_SYMBOLS = priv - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = * - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be -# ignored. - -INPUT_FILTER = - -# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. - -FILTER_PATTERNS = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. - -SOURCE_BROWSER = YES - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = NO - -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = NO - -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentation. - -REFERENCES_LINK_SOURCE = NO - -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. - -USE_HTAGS = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = YES - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .htm - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = header.htm - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = footer.htm - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! - -HTML_STYLESHEET = doxygen.css - -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. - -HTML_TIMESTAMP = YES - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). - -HTML_DYNAMIC_SECTIONS = NO - -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. - -GENERATE_DOCSET = NO - -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. - -DOCSET_FEEDNAME = "Doxygen generated docs" - -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. - -DOCSET_BUNDLE_ID = org.doxygen.Project - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be -# written to the html output directory. - -CHM_FILE = ../Pluma.chm - -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. - -HHC_LOCATION = "C:/Program Files/HTML Help Workshop/hhc.exe" - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. - -CHM_INDEX_ENCODING = - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. - -TOC_EXPAND = NO - -# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER -# are set, an additional index file will be generated that can be used as input for -# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated -# HTML documentation. - -GENERATE_QHP = NO - -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. - -QCH_FILE = - -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace - -QHP_NAMESPACE = org.doxygen.Project - -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders - -QHP_VIRTUAL_FOLDER = doc - -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. -# For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters - -QHP_CUST_FILTER_NAME = - -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see -# Qt Help Project / Custom Filters. - -QHP_CUST_FILTER_ATTRS = - -# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's -# filter section matches. -# Qt Help Project / Filter Attributes. - -QHP_SECT_FILTER_ATTRS = - -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. - -QHG_LOCATION = - -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. - -GENERATE_ECLIPSEHELP = NO - -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. - -ECLIPSE_DOC_ID = org.doxygen.Project - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 1 - -# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = NO - -# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, -# and Class Hierarchy pages using a tree view instead of an ordered list. - -USE_INLINE_TREES = NO - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. - -FORMULA_FONTSIZE = 10 - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. - -SEARCHENGINE = NO - -# When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvances is that it is more difficult to setup -# and does not have live searching capabilities. - -SERVER_BASED_SEARCH = NO - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be -# invoked. If left blank `latex' will be used as the default command name. -# Note that when enabling USE_PDFLATEX this option is only used for -# generating bitmaps for formulas in the HTML output, but not in the -# Makefile that is written to the output directory. - -LATEX_CMD_NAME = latex - -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the -# default command name. - -MAKEINDEX_CMD_NAME = makeindex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -# If LATEX_HIDE_INDICES is set to YES then doxygen will not -# include the index chapters (such as File Index, Compound Index, etc.) -# in the output. - -LATEX_HIDE_INDICES = NO - -# If LATEX_SOURCE_CODE is set to YES then doxygen will include -# source code with syntax highlighting in the LaTeX output. -# Note that which sources are shown also depends on other settings -# such as SOURCE_BROWSER. - -LATEX_SOURCE_CODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimized for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assignments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. - -GENERATE_XML = NO - -# The XML_OUTPUT tag is used to specify where the XML pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `xml' will be used as the default path. - -XML_OUTPUT = xml - -# The XML_SCHEMA tag can be used to specify an XML schema, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify an XML DTD, -# which can be used by a validating XML parser to check the -# syntax of the XML files. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES Doxygen will -# dump the program listings (including syntax highlighting -# and cross-referencing information) to the XML output. Note that -# enabling this will significantly increase the size of the XML output. - -XML_PROGRAMLISTING = YES - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- - -# If the GENERATE_PERLMOD tag is set to YES Doxygen will -# generate a Perl module file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_PERLMOD = NO - -# If the PERLMOD_LATEX tag is set to YES Doxygen will generate -# the necessary Makefile rules, Perl scripts and LaTeX code to be able -# to generate PDF and DVI output from the Perl module output. - -PERLMOD_LATEX = NO - -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this -# tag is set to NO the size of the Perl module output will be much smaller -# and Perl will parse it just the same. - -PERLMOD_PRETTY = YES - -# The names of the make variables in the generated doxyrules.make file -# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. -# This is useful so different doxyrules.make files included by the same -# Makefile don't overwrite each other's variables. - -PERLMOD_MAKEVAR_PREFIX = - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = YES - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_DEFINED tags. - -EXPAND_ONLY_PREDEF = YES - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. To prevent a macro definition from being -# undefined via #undef or recursively expanded use the := operator -# instead of the = operator. - -PREDEFINED = - -# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... -# Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base -# or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. - -CLASS_DIAGRAMS = YES - -# You can define message sequence charts within doxygen comments using the \msc -# command. Doxygen will then run the mscgen tool (see -# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the -# documentation. The MSCGEN_PATH tag allows you to specify the directory where -# the mscgen tool resides. If left empty the tool is assumed to be found in the -# default search path. - -MSCGEN_PATH = D:/Programmes/mscgen - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. - -DOT_FONTNAME = FreeSans - -# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. -# The default size is 10pt. - -DOT_FONTSIZE = 10 - -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. - -DOT_FONTPATH = - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for groups, showing the direct groups dependencies - -GROUP_GRAPHS = YES - -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and -# collaboration diagrams in a style similar to the OMG's Unified Modeling -# Language. - -UML_LOOK = NO - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = NO - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the CALL_GRAPH and HAVE_DOT options are set to YES then -# doxygen will generate a call dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable call graphs -# for selected functions only using the \callgraph command. - -CALL_GRAPH = NO - -# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then -# doxygen will generate a caller dependency graph for every global function -# or class method. Note that enabling this option will significantly increase -# the time of a run. So in most cases it will be better to enable caller -# graphs for selected functions only using the \callergraph command. - -CALLER_GRAPH = NO - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES -# then doxygen will show the dependencies a directory has on other directories -# in a graphical way. The dependency relations are determined by the #include -# relations between the files in the directories. - -DIRECTORY_GRAPH = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. - -DOT_IMAGE_FORMAT = png - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found in the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of -# nodes that will be shown in the graph. If the number of nodes in a graph -# becomes larger than this value, doxygen will truncate the graph, which is -# visualized by representing a node as a red box. Note that doxygen if the -# number of direct children of the root node in a graph is already larger than -# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note -# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. - -DOT_GRAPH_MAX_NODES = 50 - -# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the -# graphs generated by dot. A depth value of 3 means that only nodes reachable -# from the root by following a path via at most 3 edges will be shown. Nodes -# that lay further from the root node will be omitted. Note that setting this -# option to 1 or 2 may greatly reduce the computation time needed for large -# code bases. Also note that the size of a graph can be further restricted by -# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. - -MAX_DOT_GRAPH_DEPTH = 0 - -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not -# seem to support this out of the box. Warning: Depending on the platform used, -# enabling this option may lead to badly anti-aliased labels on the edges of -# a graph (i.e. they become hard to read). - -DOT_TRANSPARENT = NO - -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output -# files in one run (i.e. multiple -o and -T options on the command line). This -# makes dot run faster, but since only newer versions of dot (>1.8.10) -# support this, this feature is disabled by default. - -DOT_MULTI_TARGETS = NO - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermediate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES diff --git a/doc/third_party/Pluma/build/Doxygen.hpp b/doc/third_party/Pluma/build/Doxygen.hpp deleted file mode 100644 index 9b307a1..0000000 --- a/doc/third_party/Pluma/build/Doxygen.hpp +++ /dev/null @@ -1,101 +0,0 @@ -//////////////////////////////////////////////////////////// -/// \mainpage -/// -/// \section welcome Welcome -/// Welcome to Pluma documentation. Here you will find a detailed -/// view of all Pluma classes.
-/// If you are looking for support, you can visit the official website -/// at http://pluma-framework.sourceforge.net/.

-/// -/// CSS based on SFML1.6 documentation
-/// -/// \section example Short Example -/// A short example to demonstrate Pluma usage:
-/// A host application define a Device interface. A certain plugin -/// defines a Keyboard, witch is a Device. -/// The host will use DeviceProviders to create objects of type Device. -/// The plugin will provide host specifically with a KeyboardProvider.
-/// -/// Device hpp (shared): -/// \code -/// #include -/// class Device{ -/// public: -/// virtual std::string getDescription() const = 0; -/// }; -/// // create DevicedProvider class -/// PLUMA_PROVIDER_HEADER(Device); -/// \endcode -/// -/// Device cpp (shared): -/// \code -/// #include "Device.hpp" -/// generate DevicedProvider with version 6, and compatible with at least v.3 -/// PLUMA_PROVIDER_SOURCE(Device, 6, 3); -/// \endcode -/// -/// -///
-/// Keyboard code on the plugin side: -/// \code -/// #include -/// #include "Device.hpp" -/// -/// class Keyboard: public Device{ -/// public: -/// std::string getDescription() const{ -/// return "keyboard"; -/// } -/// }; -/// -/// // create KeyboardProvider, it implements DeviceProvider -/// PLUMA_INHERIT_PROVIDER(Keyboard, Device); -/// \endcode -/// -/// plugin connector: -/// \code -/// #include -/// #include "Keyboard.hpp" -/// -/// PLUMA_CONNECTOR -/// bool connect(pluma::Host& host){ -/// // add a keyboard provider to host -/// host.add( new KeyboardProvider() ); -/// return true; -/// } -/// \endcode -/// -/// -/// Host application code: -/// \code -/// #include -/// -/// #include "Device.hpp" -/// #include -/// #include -/// -/// int main(){ -/// -/// pluma::Pluma plugins; -/// // Tell plugins manager to accept providers of the type DeviceProvider -/// plugins.acceptProviderType(); -/// // Load library "standard_devices" from folder "plugins" -/// plugins.load("plugins", "standard_devices"); -/// -/// // Get device providers into a vector -/// std::vector providers; -/// plugins.getProviders(providers); -/// -/// // create a Device from the first provider -/// if (!providers.empty()){ -/// Device* myDevice = providers.first()->create(); -/// // do something with myDevice -/// std::cout << device->getDescription() << std::endl; -/// // and delete it in the end -/// delete myDevice; -/// } -/// return 0; -/// } -/// \endcode -/// -//////////////////////////////////////////////////////////// diff --git a/doc/third_party/Pluma/build/doxygen.css b/doc/third_party/Pluma/build/doxygen.css deleted file mode 100644 index de219ac..0000000 --- a/doc/third_party/Pluma/build/doxygen.css +++ /dev/null @@ -1,384 +0,0 @@ -div#logo -{ - margin-bottom : 1em; - background : url("./logo-bg.jpg") repeat-x; -} - -div#logo a -{ - display : block; -} - -p#footer -{ - text-decoration : overline; - color : #606060; - padding-top : 1em; - text-align : center; - font-size : smaller; -} - -p#footer a -{ - color : #007298; - text-decoration : none; -} - -BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { - font-family: Geneva, Arial, Helvetica, sans-serif; -} -BODY,TD { - font-size: 90%; -} -H1 { - text-align : center; - margin-top : 0px; - color : #2090B0; - font-size : 160%; -} -H2 { - font-size: 120%; -} -H3 { - font-size: 100%; -} -CAPTION { font-weight: bold } -DIV.qindex { - width: 100%; - background-color: #E0FFE0; - border: 1px dotted #808080; - text-align: center; - margin: 2px; - padding: 2px; - line-height: 140%; -} -DIV.nav { - width: 100%; - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - padding: 2px; - line-height: 140%; -} -DIV.navtab { - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} -TD.navtab { - font-size: 70%; -} -A.qindex { - text-decoration: none; - font-weight: bold; -} -A.qindex:visited { - text-decoration: none; - font-weight: bold; -} -A.qindex:hover { - text-decoration: none; - background-color: #ddddff; -} -A.qindexHL { - text-decoration: none; - font-weight: bold; - background-color: #6666cc; - color: #ffffff; - border: 1px double #9295C2; -} -A.qindexHL:hover { - text-decoration: none; - background-color: #6666cc; - color: #ffffff; -} -A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } -A.el { text-decoration: none; font-weight: bold } -A.elRef { font-weight: bold } -A.code:link { text-decoration: none; font-weight: normal; border-bottom : 1px dotted #808080; color: black;} -A.code:visited { text-decoration: none; font-weight: normal; border-bottom : 1px dotted #808080; color: black;} -A.codeRef:link { font-weight: normal; color: #0000FF} -A.codeRef:visited { font-weight: normal; color: #0000FF} -/*A:hover { text-decoration: none; background-color: #f2f2ff }*/ -DL.el { margin-left: -1cm } -.fragment { - font-family: monospace, fixed; - font-size: 95%; -} -PRE.fragment { - border: 1px solid #CCCCCC; - background-color: #f5f5f5; - margin-top: 4px; - margin-bottom: 4px; - margin-left: 2px; - margin-right: 8px; - padding-left: 6px; - padding-right: 6px; - padding-top: 4px; - padding-bottom: 4px; -} -DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } - -DIV.groupHeader { - margin-left: 16px; - margin-top: 12px; - margin-bottom: 6px; - font-weight: bold; -} -DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } -BODY { - background: white; - color: black; - margin-right: 20px; - margin-left: 20px; -} -TD.indexkey { - background-color: #e8eef2; - font-weight: bold; - padding-right : 10px; - padding-top : 2px; - padding-left : 10px; - padding-bottom : 2px; - margin-left : 0px; - margin-right : 0px; - margin-top : 2px; - margin-bottom : 2px; - border: 1px solid #CCCCCC; -} -TD.indexvalue { - background-color: #e8eef2; - font-style: italic; - padding-right : 10px; - padding-top : 2px; - padding-left : 10px; - padding-bottom : 2px; - margin-left : 0px; - margin-right : 0px; - margin-top : 2px; - margin-bottom : 2px; - border: 1px solid #CCCCCC; -} -TR.memlist { - background-color: #f0f0f0; -} -P.formulaDsp { text-align: center; } -IMG.formulaDsp { } -IMG.formulaInl { vertical-align: middle; } -SPAN.keyword { color: #0000FF } -SPAN.keywordtype { color: #0000FF } -SPAN.keywordflow { color: #0000FF } -SPAN.comment { color: #008000 } -SPAN.preprocessor { color: #008080 } -SPAN.stringliteral { color: #008080 } -SPAN.charliteral { color: #008080 } -.mdescLeft { - padding: 0px 8px 4px 8px; - font-size: 80%; - font-style: italic; - background-color: #FAFAFA; - border-top: 1px none #E0E0E0; - border-right: 1px none #E0E0E0; - border-bottom: 1px none #E0E0E0; - border-left: 1px none #E0E0E0; - margin: 0px; -} -.mdescRight { - padding: 0px 8px 4px 8px; - font-size: 80%; - font-style: italic; - background-color: #FAFAFA; - border-top: 1px none #E0E0E0; - border-right: 1px none #E0E0E0; - border-bottom: 1px none #E0E0E0; - border-left: 1px none #E0E0E0; - margin: 0px; -} -.memItemLeft { - padding: 1px 0px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: solid; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memItemRight { - padding: 1px 8px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: solid; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memTemplItemLeft { - padding: 1px 0px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: none; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memTemplItemRight { - padding: 1px 8px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: none; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memTemplParams { - padding: 1px 0px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: solid; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - color: #606060; - background-color: #FAFAFA; - font-size: 80%; -} -.search { color: #003399; - font-weight: bold; -} -FORM.search { - margin-bottom: 0px; - margin-top: 0px; -} -INPUT.search { font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -TD.tiny { font-size: 75%; -} -a { - color: #2090B0; -} -a:visited { - color: #2090B0; -} -.dirtab { padding: 4px; - border-collapse: collapse; - border: 1px solid #84b0c7; -} -TH.dirtab { background: #e8eef2; - font-weight: bold; -} -HR { height: 1px; - border: none; - border-top: 1px solid black; -} - -/* Style for detailed member documentation */ -.memtemplate { - font-size: 80%; - color: #606060; - font-weight: normal; -} -.memnav { - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} -.memitem { - /*padding: 4px;*/ - background-color: #F0FFF0; - border-width: 1px; - border-style: solid; - border-color: #808080; - /*-moz-border-radius: 8px 8px 8px 8px;*/ -} -.memname { - white-space: nowrap; - font-weight: bold; -} -.memdoc{ - padding-left: 10px; -} -.memproto { - background-color: #D0FFD0; - width: 100%; - border-bottom-width: 1px; - border-bottom-style: dotted; - border-bottom-color: #808080; - font-weight: bold; - /*-moz-border-radius: 8px 8px 8px 8px;*/ -} -.paramkey { - text-align: right; -} -.paramtype { - white-space: nowrap; -} -.paramname { - color: #602020; - font-style: italic; - white-space: nowrap; -} -/* End Styling for detailed member documentation */ - -/* for the tree view */ -.ftvtree { - font-family: sans-serif; - margin:0.5em; -} -.directory { font-size: 9pt; font-weight: bold; } -.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } -.directory > h3 { margin-top: 0; } -.directory p { margin: 0px; white-space: nowrap; } -.directory div { display: none; margin: 0px; } -.directory img { vertical-align: -30%; } diff --git a/doc/third_party/Pluma/build/footer.htm b/doc/third_party/Pluma/build/footer.htm deleted file mode 100644 index 0681f33..0000000 --- a/doc/third_party/Pluma/build/footer.htm +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/doc/third_party/Pluma/build/header.htm b/doc/third_party/Pluma/build/header.htm deleted file mode 100644 index e7890bd..0000000 --- a/doc/third_party/Pluma/build/header.htm +++ /dev/null @@ -1,12 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - diff --git a/doc/third_party/Pluma/html/Config_8hpp_source.htm b/doc/third_party/Pluma/html/Config_8hpp_source.htm deleted file mode 100644 index fb54cd0..0000000 --- a/doc/third_party/Pluma/html/Config_8hpp_source.htm +++ /dev/null @@ -1,170 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Config.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 //
-
28 // Based on SFML configuration header
-
29 // SFML Config.hpp:
-
30 // http://www.sfml-dev.org/documentation/2.0/Config_8hpp-source.htm
-
31 //
-
32 // Acknowledgements to Simple and Fast Multimedia Library
-
33 // http://www.sfml-dev.org/
-
34 //
-
36 
-
37 
-
38 #ifndef PLUMA_CONFIG_HPP
-
39 #define PLUMA_CONFIG_HPP
-
40 
-
41 
-
43 // Identify the operating system
-
45 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
-
46 
-
47  // Windows
-
48  #define PLUMA_SYS_WINDOWS
-
49  #ifndef WIN32_LEAN_AND_MEAN
-
50  #define WIN32_LEAN_AND_MEAN
-
51  #endif
-
52  #ifndef NOMINMAX
-
53  #define NOMINMAX
-
54  #endif
-
55 
-
56 #elif defined(linux) || defined(__linux)
-
57 
-
58  // Linux
-
59  #define PLUMA_SYS_LINUX
-
60 
-
61 #elif defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)
-
62 
-
63  // MacOS
-
64  #define PLUMA_SYS_MACOS
-
65 
-
66 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
-
67 
-
68  // FreeBSD
-
69  #define PLUMA_SYS_FREEBSD
-
70 
-
71 #else
-
72 
-
73  // Unsupported system
-
74  #error This operating system is not supported by this library
-
75 
-
76 #endif
-
77 
-
78 
-
79 
-
81 // Define library file extension based on OS
-
83 #ifdef PLUMA_SYS_WINDOWS
-
84  #define PLUMA_LIB_EXTENSION "dll"
-
85 #elif defined(PLUMA_SYS_MACOS)
-
86  #define PLUMA_LIB_EXTENSION "dylib"
-
87 #elif defined(PLUMA_SYS_LINUX) || defined(PLUMA_SYS_FREEBSD)
-
88  #define PLUMA_LIB_EXTENSION "so"
-
89 #else
-
90  // unknown library file type
-
91  #error Unknown library file extension for this operating system
-
92 #endif
-
93 
-
94 
-
96 // Define portable import / export macros
-
98 #if defined(PLUMA_SYS_WINDOWS)
-
99 
-
100  #ifndef PLUMA_STATIC
-
101 
-
102  // Windows platforms
-
103  #ifdef PLUMA_EXPORTS
-
104 
-
105  // From DLL side, we must export
-
106  #define PLUMA_API __declspec(dllexport)
-
107 
-
108  #else
-
109 
-
110  // From client application side, we must import
-
111  #define PLUMA_API __declspec(dllimport)
-
112 
-
113  #endif
-
114 
-
115  // For Visual C++ compilers, we also need to turn off this annoying C4251 warning.
-
116  // You can read lots ot different things about it, but the point is the code will
-
117  // just work fine, and so the simplest way to get rid of this warning is to disable it
-
118  #ifdef _MSC_VER
-
119 
-
120  #pragma warning(disable : 4251)
-
121 
-
122  #endif
-
123 
-
124  #else
-
125 
-
126  // No specific directive needed for static build
-
127  #define PLUMA_API
-
128 
-
129  #endif
-
130 
-
131 #else
-
132 
-
133  // Other platforms don't need to define anything
-
134  #define PLUMA_API
-
135 
-
136 #endif
-
137 
-
138 
-
139 
-
140 
-
141 #endif // PLUMA_CONFIG_HPP
-
- - - - diff --git a/doc/third_party/Pluma/html/Connector_8hpp_source.htm b/doc/third_party/Pluma/html/Connector_8hpp_source.htm deleted file mode 100644 index 5a36cdf..0000000 --- a/doc/third_party/Pluma/html/Connector_8hpp_source.htm +++ /dev/null @@ -1,119 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Connector.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_CONNECTOR_HPP
-
26 #define PLUMA_CONNECTOR_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <Pluma/Pluma.hpp>
-
33 
-
34 
-
36 // Define portable import/export macros for Plugin registration
-
38 #if defined(PLUMA_SYS_WINDOWS)
-
39 
-
40  #ifndef PLUMA_STATIC_PLUGIN
-
41 
-
42  // Windows platforms
-
43  #ifndef PLUGIN_IMPORTS
-
44 
-
45  // From DLL side, we must export
-
46  #ifdef __cplusplus
-
47  #define PLUMA_CONNECTOR extern "C" __declspec(dllexport)
-
48  #else
-
49  #define PLUMA_CONNECTOR __declspec(dllexport)
-
50  #endif
-
51 
-
52  #else
-
53 
-
54  // From client application side, we must import
-
55  #ifdef __cplusplus
-
56  #define PLUMA_CONNECTOR extern "C" __declspec(dllimport)
-
57  #else
-
58  #define PLUMA_CONNECTOR __declspec(dllimport)
-
59  #endif
-
60 
-
61  #endif
-
62 
-
63  #else
-
64 
-
65  // Only define the extern "C" for static build
-
66  #ifdef __cplusplus
-
67  #define PLUMA_CONNECTOR extern "C"
-
68  #else
-
69  #define PLUMA_CONNECTOR
-
70  #endif
-
71 
-
72  #endif
-
73 
-
74 #else
-
75 
-
76  // Only define the extern "C" for other platforms
-
77  #ifdef __cplusplus
-
78  #define PLUMA_CONNECTOR extern "C"
-
79  #else
-
80  #define PLUMA_CONNECTOR
-
81  #endif
-
82 
-
83 #endif
-
84 
-
85 
-
86 #endif // PLUMA_CONNECTOR_HPP
-
- - - - diff --git a/doc/third_party/Pluma/html/DLibrary_8cpp_source.htm b/doc/third_party/Pluma/html/DLibrary_8cpp_source.htm deleted file mode 100644 index e4e4562..0000000 --- a/doc/third_party/Pluma/html/DLibrary_8cpp_source.htm +++ /dev/null @@ -1,141 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
DLibrary.cpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 // Headers
-
29 #include <Pluma/DLibrary.hpp>
-
30 #include <cstdio>
-
31 #include <string>
-
32 
-
33 
-
34 namespace pluma{
-
35 
-
37 DLibrary* DLibrary::load(const std::string& path){
-
38  if ( path.empty() ){
-
39  fprintf(stderr, "Failed to load library: Empty path\n");
-
40  return NULL;
-
41  }
-
42  void* handle = NULL;
-
43 
-
44  // load library - OS dependent operation
-
45  #ifdef PLUMA_SYS_WINDOWS
-
46  handle = ::LoadLibraryA(path.c_str());
-
47  if (!handle){
-
48  fprintf(stderr, "Failed to load library \"%s\".\n", path.c_str());
-
49  return NULL;
-
50  }
-
51  #else
-
52  handle = ::dlopen(path.c_str(), RTLD_NOW);
-
53  if (!handle){
-
54  const char* errorString = ::dlerror();
-
55  fprintf(stderr, "Failed to load library \"%s\".", path.c_str());
-
56  if(errorString) fprintf(stderr, " OS returned error: \"%s\".", errorString);
-
57  fprintf(stderr, "\n");
-
58  return NULL;
-
59  }
-
60  #endif
-
61  // return a DLibrary with the DLL handle
-
62  return new DLibrary(handle);
-
63 }
-
64 
-
65 
- -
68  if (handle){
-
69  #ifdef PLUMA_SYS_WINDOWS
-
70  ::FreeLibrary( (HMODULE)handle );
-
71  #else
-
72  ::dlclose(handle);
-
73  #endif
-
74  }
-
75 }
-
76 
-
77 
-
79 void* DLibrary::getSymbol(const std::string& symbol){
-
80  if (!handle){
-
81  fprintf(stderr, "Cannot inspect library symbols, library isn't loaded.\n");
-
82  return NULL;
-
83  }
-
84  void* res;
-
85  #ifdef PLUMA_SYS_WINDOWS
-
86  res = (void*)(::GetProcAddress((HMODULE)handle, symbol.c_str()));
-
87  #else
-
88  res = (void*)(::dlsym(handle, symbol.c_str()));
-
89  #endif
-
90  if (!res){
-
91  fprintf(stderr, "Library symbol \"%s\" not found.\n", symbol.c_str());
-
92  return NULL;
-
93  }
-
94  return res;
-
95 }
-
96 
-
97 
-
99 DLibrary::DLibrary(void* handle):
-
100  handle(handle)
-
101 {
-
102  // Nothing to do
-
103 }
-
104 
-
105 } // namespace pluma
-
106 
-
static DLibrary * load(const std::string &path)
Load a library.
Definition: DLibrary.cpp:37
-
Manages a Dynamic Linking Library.
Definition: DLibrary.hpp:49
-
void * getSymbol(const std::string &symbol)
Get a symbol from the library.
Definition: DLibrary.cpp:79
-
~DLibrary()
Destructor.
Definition: DLibrary.cpp:67
-
- - - - diff --git a/doc/third_party/Pluma/html/DLibrary_8hpp_source.htm b/doc/third_party/Pluma/html/DLibrary_8hpp_source.htm deleted file mode 100644 index 6030a7a..0000000 --- a/doc/third_party/Pluma/html/DLibrary_8hpp_source.htm +++ /dev/null @@ -1,117 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
DLibrary.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_DYNAMIC_LIBRARY_HPP
-
26 #define PLUMA_DYNAMIC_LIBRARY_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <string>
-
33 
-
34 // include OS dependent support for DLL
-
35 #ifdef PLUMA_SYS_WINDOWS
-
36  #include <Windows.h>
-
37 #else
-
38  #include <dlfcn.h>
-
39 #endif
-
40 
-
41 
-
42 
-
43 namespace pluma{
-
44 
-
49 class DLibrary{
-
50 
-
51 
-
52 public:
-
53 
-
62  static DLibrary* load(const std::string& path);
-
63 
-
70  ~DLibrary();
-
71 
-
81  void* getSymbol(const std::string& symbol);
-
82 
-
83 
-
84 private:
-
85 
-
94  DLibrary();
-
95 
-
104  DLibrary(void* handle);
-
105 
-
106 
-
107 
-
109 // Member data
-
111 
-
112 
-
113 private:
-
114 
-
115  void* handle;
-
116 
-
117 };
-
118 
-
119 
-
120 } // namespace pluma
-
121 
-
122 
-
123 #endif // PLUMA_DYNAMIC_LIBRARY_HPP
-
static DLibrary * load(const std::string &path)
Load a library.
Definition: DLibrary.cpp:37
-
Manages a Dynamic Linking Library.
Definition: DLibrary.hpp:49
-
void * getSymbol(const std::string &symbol)
Get a symbol from the library.
Definition: DLibrary.cpp:79
-
~DLibrary()
Destructor.
Definition: DLibrary.cpp:67
-
- - - - diff --git a/doc/third_party/Pluma/html/Dir_8cpp_source.htm b/doc/third_party/Pluma/html/Dir_8cpp_source.htm deleted file mode 100644 index 8c2d4c2..0000000 --- a/doc/third_party/Pluma/html/Dir_8cpp_source.htm +++ /dev/null @@ -1,137 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Dir.cpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 // Headers
-
29 #include <Pluma/Dir.hpp>
-
30 #include <Pluma/uce-dirent.h>
-
31 #include <cstdio>
-
32 #include <queue>
-
33 
-
34 
-
35 namespace pluma{
-
36 
-
37 namespace dir{
-
38 
-
39 
-
41 void listFiles(std::list<std::string>& list, const std::string& folder, const std::string& extension, bool recursive){
-
42  DIR* dir;
-
43  DIR* subDir;
-
44  struct dirent *ent;
-
45  // try to open top folder
-
46  dir = opendir(folder.c_str());
-
47  if (dir == NULL){
-
48  // could not open directory
-
49  fprintf(stderr, "Could not open \"%s\" directory.\n", folder.c_str());
-
50  return;
-
51  }else{
-
52  // close, we'll process it next
-
53  closedir(dir);
-
54  }
-
55  // enqueue top folder
-
56  std::queue<std::string> folders;
-
57  folders.push(folder);
-
58 
-
59  // run while has queued folders
-
60  while (!folders.empty()){
-
61  std::string currFolder = folders.front();
-
62  folders.pop();
-
63  dir = opendir(currFolder.c_str());
-
64  if (dir == NULL) continue;
-
65  // iterate through all the files and directories
-
66  while ((ent = readdir (dir)) != NULL) {
-
67  std::string name(ent->d_name);
-
68  // ignore "." and ".." directories
-
69  if ( name.compare(".") == 0 || name.compare("..") == 0) continue;
-
70  // add path to the file name
-
71  std::string path = currFolder;
-
72  path.append("/");
-
73  path.append(name);
-
74  // check if it's a folder by trying to open it
-
75  subDir = opendir(path.c_str());
-
76  if (subDir != NULL){
-
77  // it's a folder: close, we can process it later
-
78  closedir(subDir);
-
79  if (recursive) folders.push(path);
-
80  }else{
-
81  // it's a file
-
82  if (extension.empty()){
-
83  list.push_back(path);
-
84  }else{
-
85  // check file extension
-
86  size_t lastDot = name.find_last_of('.');
-
87  std::string ext = name.substr(lastDot+1);
-
88  if (ext.compare(extension) == 0){
-
89  // match
-
90  list.push_back(path);
-
91  }
-
92  } // endif (extension test)
-
93  } // endif (folder test)
-
94  } // endwhile (nextFile)
-
95  closedir(dir);
-
96  } // endwhile (queued folders)
-
97 
-
98 } // end listFiles
-
99 
-
100 
-
101 } // namespace dir
-
102 
-
103 } // namespace pluma
-
- - - - diff --git a/doc/third_party/Pluma/html/Dir_8hpp_source.htm b/doc/third_party/Pluma/html/Dir_8hpp_source.htm deleted file mode 100644 index 1b8b876..0000000 --- a/doc/third_party/Pluma/html/Dir_8hpp_source.htm +++ /dev/null @@ -1,88 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Dir.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_DIRECTORY_HPP
-
26 #define PLUMA_DIRECTORY_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <string>
-
33 #include <list>
-
34 
-
35 
-
36 namespace pluma{
-
37 
-
38 namespace dir{
-
39 
-
51 void listFiles(
-
52  std::list<std::string>& list,
-
53  const std::string& folder,
-
54  const std::string& extension = "",
-
55  bool recursive = false
-
56 );
-
57 
-
58 
-
59 } // namespace dir
-
60 
-
61 } // namespace pluma
-
62 
-
63 
-
64 #endif // PLUMA_DIRECTORY_HPP
-
- - - - diff --git a/doc/third_party/Pluma/html/Doxygen_8hpp_source.htm b/doc/third_party/Pluma/html/Doxygen_8hpp_source.htm deleted file mode 100644 index 0a8d6d5..0000000 --- a/doc/third_party/Pluma/html/Doxygen_8hpp_source.htm +++ /dev/null @@ -1,39 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Doxygen.hpp
-
-
-
1 
- - - - diff --git a/doc/third_party/Pluma/html/Host_8cpp_source.htm b/doc/third_party/Pluma/html/Host_8cpp_source.htm deleted file mode 100644 index b70cfb6..0000000 --- a/doc/third_party/Pluma/html/Host_8cpp_source.htm +++ /dev/null @@ -1,203 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - -
-
-
-
Host.cpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 // Headers
-
29 #include <Pluma/Host.hpp>
-
30 #include <cstdio>
-
31 
-
32 
-
33 namespace pluma{
-
34 
-
36 Host::Host(){
-
37  // Nothing to do
-
38 }
-
39 
-
40 
-
42 bool Host::add(Provider* provider){
-
43  if (provider == NULL){
-
44  fprintf(stderr, "Trying to add a null provider.\n");
-
45  return false;
-
46  }
-
47  if (!validateProvider(provider)){
-
48  delete provider;
-
49  return false;
-
50  }
-
51  addRequests[ provider->plumaGetType() ].push_back(provider);
-
52  return true;
-
53 }
-
54 
-
55 
-
57 Host::~Host(){
-
58  clearProviders();
-
59  // map frees itself
-
60 }
-
61 
-
62 
-
64 void Host::clearProviders(){
-
65  ProvidersMap::iterator it;
-
66  for (it = knownTypes.begin() ; it != knownTypes.end() ; ++it){
-
67  std::list<Provider*>& providers = it->second.providers;
-
68  std::list<Provider*>::iterator provIt;
-
69  for (provIt = providers.begin() ; provIt != providers.end() ; ++provIt){
-
70  delete *provIt;
-
71  }
-
72  std::list<Provider*>().swap(providers);
-
73  }
-
74 }
-
75 
-
76 
-
78 bool Host::knows(const std::string& type) const{
-
79  return knownTypes.find(type) != knownTypes.end();
-
80 }
-
81 
-
82 
-
84 unsigned int Host::getVersion(const std::string& type) const{
-
85  ProvidersMap::const_iterator it = knownTypes.find(type);
-
86  if (it != knownTypes.end())
-
87  return it->second.version;
-
88  return 0;
-
89 }
-
90 
-
91 
-
93 unsigned int Host::getLowestVersion(const std::string& type) const{
-
94  ProvidersMap::const_iterator it = knownTypes.find(type);
-
95  if (it != knownTypes.end())
-
96  return it->second.lowestVersion;
-
97  return 0;
-
98 }
-
99 
-
100 
-
102 void Host::registerType(const std::string& type, unsigned int version, unsigned int lowestVersion){
-
103  if (!knows(type)){
-
104  ProviderInfo pi;
-
105  pi.version = version;
-
106  pi.lowestVersion = lowestVersion;
-
107  knownTypes[type] = pi;
-
108  }
-
109 }
-
110 
-
111 
-
113 const std::list<Provider*>* Host::getProviders(const std::string& type) const{
-
114  ProvidersMap::const_iterator it = knownTypes.find(type);
-
115  if (it != knownTypes.end())
-
116  return &it->second.providers;
-
117  return NULL;
-
118 }
-
119 
-
120 
-
122 bool Host::validateProvider(Provider* provider) const{
-
123  const std::string& type = provider->plumaGetType();
-
124  if ( !knows(type) ){
-
125  fprintf(stderr, "%s provider type isn't registered.\n", type.c_str());
-
126  return false;
-
127  }
-
128  if (!provider->isCompatible(*this)){
-
129  fprintf(stderr, "Incompatible %s provider version.\n", type.c_str());
-
130  return false;
-
131  }
-
132  return true;
-
133 }
-
134 
-
135 
-
137 bool Host::registerProvider(Provider* provider){
-
138  if (!validateProvider(provider)){
-
139  delete provider;
-
140  return false;
-
141  }
-
142  knownTypes[ provider->plumaGetType() ].providers.push_back(provider);
-
143  return true;
-
144 }
-
145 
-
146 
-
148 void Host::cancelAddictions(){
-
149  TempProvidersMap::iterator it;
-
150  for( it = addRequests.begin() ; it != addRequests.end() ; ++it){
-
151  std::list<Provider*> lst = it->second;
-
152  std::list<Provider*>::iterator providerIt;
-
153  for (providerIt = lst.begin() ; providerIt != lst.end() ; ++providerIt){
-
154  delete *providerIt;
-
155  }
-
156  }
-
157  // clear map
-
158  TempProvidersMap().swap(addRequests);
-
159 }
-
160 
-
161 
-
163 bool Host::confirmAddictions(){
-
164  if (addRequests.empty()) return false;
-
165  TempProvidersMap::iterator it;
-
166  for( it = addRequests.begin() ; it != addRequests.end() ; ++it){
-
167  std::list<Provider*> lst = it->second;
-
168  std::list<Provider*>::iterator providerIt;
-
169  for (providerIt = lst.begin() ; providerIt != lst.end() ; ++providerIt){
-
170  knownTypes[it->first].providers.push_back(*providerIt);
-
171  }
-
172  }
-
173  // clear map
-
174  TempProvidersMap().swap(addRequests);
-
175  return true;
-
176 }
-
177 
-
178 
-
179 } //namespace pluma
-
Interface to provide applications with objects from plugins.
Definition: Provider.hpp:42
-
bool add(Provider *provider)
Add provider.
Definition: Host.cpp:42
-
- - - - diff --git a/doc/third_party/Pluma/html/Host_8hpp_source.htm b/doc/third_party/Pluma/html/Host_8hpp_source.htm deleted file mode 100644 index 8ca0182..0000000 --- a/doc/third_party/Pluma/html/Host_8hpp_source.htm +++ /dev/null @@ -1,136 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Host.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_HOST_HPP
-
26 #define PLUMA_HOST_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <Pluma/Provider.hpp>
-
33 
-
34 #include <vector>
-
35 #include <list>
-
36 #include <map>
-
37 
-
38 namespace pluma{
-
39 
-
44 class PLUMA_API Host{
-
45 friend class PluginManager;
-
46 friend class Provider;
-
47 
-
48 
-
49 public:
-
50 
-
62  bool add(Provider* provider);
-
63 
-
64 
-
65 private:
-
66 
-
73  Host();
-
74 
-
81  ~Host();
-
82 
-
91  bool knows(const std::string& type) const;
-
92 
-
101  unsigned int getVersion(const std::string& type) const;
-
102 
-
111  unsigned int getLowestVersion(const std::string& type) const;
-
112 
-
121  void registerType(const std::string& type, unsigned int version, unsigned int lowestVersion);
-
122 
-
132  const std::list<Provider*>* getProviders(const std::string& type) const;
-
133 
-
138  void clearProviders();
-
139 
-
146  bool validateProvider(Provider* provider) const;
-
147 
-
160  bool registerProvider(Provider* provider);
-
161 
-
170  void cancelAddictions();
-
171 
-
182  bool confirmAddictions();
-
183 
-
184 
-
185 
-
187 // Member data
-
189 
-
190 private:
-
191 
-
196  struct ProviderInfo{
-
197  unsigned int version;
-
198  unsigned int lowestVersion;
-
199  std::list<Provider*> providers;
-
200  };
-
201 
-
202  typedef std::map<std::string, ProviderInfo > ProvidersMap;
-
203  typedef std::map<std::string, std::list<Provider*> > TempProvidersMap;
-
204 
-
205  ProvidersMap knownTypes;
-
206  TempProvidersMap addRequests;
-
207 
-
208 };
-
209 
-
210 } // namespace pluma
-
211 
-
212 #endif // PLUMA_HOST_HPP
-
Manages loaded plugins.
-
Interface to provide applications with objects from plugins.
Definition: Provider.hpp:42
-
Manages providers.
Definition: Host.hpp:44
-
- - - - diff --git a/doc/third_party/Pluma/html/PluginManager_8cpp_source.htm b/doc/third_party/Pluma/html/PluginManager_8cpp_source.htm deleted file mode 100644 index 20f62fb..0000000 --- a/doc/third_party/Pluma/html/PluginManager_8cpp_source.htm +++ /dev/null @@ -1,237 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
PluginManager.cpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 // Headers
-
29 #include <Pluma/PluginManager.hpp>
-
30 #include <Pluma/DLibrary.hpp>
-
31 #include <Pluma/Dir.hpp>
-
32 #include <cstdio>
-
33 
-
34 namespace pluma{
-
35 
- -
38  // Nothing to do
-
39 }
-
40 
-
41 
- -
44  unloadAll();
-
45 }
-
46 
-
47 
-
49 bool PluginManager::load(const std::string& path){
-
50  std::string plugName = getPluginName(path);
-
51  std::string realPath = resolvePathExtension(path);
-
52  DLibrary* lib = DLibrary::load(realPath);
-
53  if (!lib) return false;
-
54 
-
55  fnRegisterPlugin* registerFunction;
-
56  registerFunction = reinterpret_cast<fnRegisterPlugin*>(lib->getSymbol("connect"));
-
57 
-
58  if(!registerFunction){
-
59  fprintf(stderr, "Failed to initialize plugin \"%s\": connect function not found\n", plugName.c_str());
-
60  delete lib;
-
61  return false;
-
62  }
-
63  // try to initialize plugin:
-
64  if (!registerFunction(host)){
-
65  // plugin decided to fail
-
66  fprintf(stderr, "Self registry failed on plugin \"%s\".\n", plugName.c_str());
-
67  host.cancelAddictions();
-
68  delete lib;
-
69  return false;
-
70  }
-
71  // Store the library if addictions are confirmed
-
72  if (host.confirmAddictions())
-
73  libraries[plugName] = lib;
-
74  else{
-
75  // otherwise nothing was registered
-
76  fprintf(stderr, "Nothing registered by plugin \"%s\".\n", plugName.c_str());
-
77  delete lib;
-
78  return false;
-
79  }
-
80  return true;
-
81 }
-
82 
-
83 
-
85 bool PluginManager::load(const std::string& folder, const std::string& pluginName){
-
86  if (folder.empty())
-
87  return load(pluginName);
-
88  else if (folder[folder.size()-1] == '/' || folder[folder.size()-1] == '\\')
-
89  return load(folder + pluginName);
-
90  return load(folder + '/' + pluginName);
-
91 }
-
92 
-
93 
-
95 int PluginManager::loadFromFolder(const std::string& folder, bool recursive){
-
96  std::list<std::string> files;
-
97  dir::listFiles(files, folder, PLUMA_LIB_EXTENSION, recursive);
-
98  // try to load every library
-
99  int res = 0;
-
100  std::list<std::string>::const_iterator it;
-
101  for (it = files.begin() ; it != files.end() ; ++it){
-
102  if ( load(*it) ) ++res;
-
103  }
-
104  return res;
-
105 }
-
106 
-
107 
-
109 bool PluginManager::unload(const std::string& pluginName){
-
110  std::string plugName = getPluginName(pluginName);
-
111  LibMap::iterator it = libraries.find(plugName);
-
112  if( it != libraries.end() ) {
-
113  delete it->second;
-
114  libraries.erase(it);
-
115  return true;
-
116  }
-
117  return false;
-
118 }
-
119 
-
120 
- -
123 
-
124  host.clearProviders();
-
125  LibMap::iterator it;
-
126  for (it = libraries.begin() ; it != libraries.end() ; ++it){
-
127  delete it->second;
-
128  }
-
129  libraries.clear();
-
130 }
-
131 
-
132 
-
134 std::string PluginManager::getPluginName(const std::string& path){
-
135  size_t lastDash = path.find_last_of("/\\");
-
136  size_t lastDot = path.find_last_of('.');
-
137  if (lastDash == std::string::npos) lastDash = 0;
-
138  else ++lastDash;
-
139  if (lastDot < lastDash || lastDot == std::string::npos){
-
140  // path without extension
-
141  lastDot = path.length();
-
142  }
-
143  return path.substr(lastDash, lastDot-lastDash);
-
144 }
-
145 
-
146 
-
148 std::string PluginManager::resolvePathExtension(const std::string& path){
-
149  size_t lastDash = path.find_last_of("/\\");
-
150  size_t lastDot = path.find_last_of('.');
-
151  if (lastDash == std::string::npos) lastDash = 0;
-
152  else ++lastDash;
-
153  if (lastDot < lastDash || lastDot == std::string::npos){
-
154  // path without extension, add it
-
155  return path + "." + PLUMA_LIB_EXTENSION;
-
156  }
-
157  return path;
-
158 }
-
159 
-
160 
-
162 void PluginManager::registerType(const std::string& type, unsigned int version, unsigned int lowestVersion){
-
163  host.registerType(type, version, lowestVersion);
-
164 }
-
165 
-
166 
- -
169  if (provider == NULL){
-
170  fprintf(stderr, "Trying to add null provider\n");
-
171  return false;
-
172  }
-
173  return host.registerProvider(provider);
-
174 }
-
175 
-
176 
-
178 void PluginManager::getLoadedPlugins(std::vector<const std::string*>& pluginNames) const{
-
179  pluginNames.reserve(pluginNames.size()+libraries.size());
-
180  LibMap::const_iterator it;
-
181  for(it = libraries.begin() ; it != libraries.end() ; ++it){
-
182  pluginNames.push_back(&(it->first));
-
183  }
-
184 }
-
185 
-
186 
-
188 bool PluginManager::isLoaded(const std::string& pluginName) const{
-
189  return libraries.find(getPluginName(pluginName)) != libraries.end();
-
190 }
-
191 
-
192 
-
194 const std::list<Provider*>* PluginManager::getProviders(const std::string& type) const{
-
195  return host.getProviders(type);
-
196 }
-
197 
-
198 
-
199 
-
200 } // namespace pluma
-
201 
-
bool unload(const std::string &pluginName)
Unload a plugin.
-
void registerType(const std::string &type, unsigned int version, unsigned int lowestVersion)
Register a provider type.
-
void unloadAll()
Unload all loaded plugins.
-
PluginManager()
Default constructor.
-
Interface to provide applications with objects from plugins.
Definition: Provider.hpp:42
-
const std::list< Provider * > * getProviders(const std::string &type) const
Get providers of a certain type.
-
static DLibrary * load(const std::string &path)
Load a library.
Definition: DLibrary.cpp:37
-
Manages a Dynamic Linking Library.
Definition: DLibrary.hpp:49
-
int loadFromFolder(const std::string &folder, bool recursive=false)
Load all plugins from a given folder.
-
void * getSymbol(const std::string &symbol)
Get a symbol from the library.
Definition: DLibrary.cpp:79
-
bool load(const std::string &path)
Load a plugin given it's path.
-
~PluginManager()
Destructor.
-
bool isLoaded(const std::string &pluginName) const
Check if a plug-in is loaded.
-
void getLoadedPlugins(std::vector< const std::string * > &pluginNames) const
Get the name of all loaded plugins.
-
bool addProvider(Provider *provider)
Directly add a new provider.
-
- - - - diff --git a/doc/third_party/Pluma/html/PluginManager_8hpp_source.htm b/doc/third_party/Pluma/html/PluginManager_8hpp_source.htm deleted file mode 100644 index ace857e..0000000 --- a/doc/third_party/Pluma/html/PluginManager_8hpp_source.htm +++ /dev/null @@ -1,131 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
PluginManager.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_PLUGIN_MANAGER_HPP
-
26 #define PLUMA_PLUGIN_MANAGER_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <Pluma/Host.hpp>
-
33 
-
34 #include <string>
-
35 #include <map>
-
36 
-
37 namespace pluma{
-
38 class DLibrary;
-
39 
-
44 class PLUMA_API PluginManager{
-
45 
-
46 
-
47 public:
-
48 
-
53  ~PluginManager();
-
54 
-
71  bool load(const std::string& path);
-
72 
-
73 
-
91  bool load(const std::string& folder, const std::string& pluginName);
-
92 
-
107  int loadFromFolder(const std::string& folder, bool recursive = false);
-
108 
-
123  bool unload(const std::string& pluginName);
-
124 
-
134  void unloadAll();
-
135 
-
142  bool addProvider(Provider* provider);
-
143 
-
150  void getLoadedPlugins(std::vector<const std::string*>& pluginNames) const;
-
151 
-
158  bool isLoaded(const std::string& pluginName) const;
-
159 
-
160 
-
161 protected:
-
162 
-
169  PluginManager();
-
170 
-
181  void registerType(const std::string& type, unsigned int version, unsigned int lowestVersion);
-
182 
-
194  const std::list<Provider*>* getProviders(const std::string& type) const;
-
195 
-
196 
-
197 private:
-
198 
-
212  static std::string getPluginName(const std::string& path);
-
213 
-
229  static std::string resolvePathExtension(const std::string& path);
-
230 
-
231 
-
232 private:
-
233 
-
235  typedef bool fnRegisterPlugin(Host&);
-
236  typedef std::map<std::string,DLibrary*> LibMap;
-
237 
-
238  LibMap libraries;
-
239  Host host;
-
240 
-
241 };
-
242 
-
243 } // namespace pluma
-
244 
-
245 #endif // PLUMA_PLUGIN_MANAGER_HPP
-
Manages loaded plugins.
-
Interface to provide applications with objects from plugins.
Definition: Provider.hpp:42
-
Manages providers.
Definition: Host.hpp:44
-
- - - - diff --git a/doc/third_party/Pluma/html/Pluma_8hpp_source.htm b/doc/third_party/Pluma/html/Pluma_8hpp_source.htm deleted file mode 100644 index 54cbe25..0000000 --- a/doc/third_party/Pluma/html/Pluma_8hpp_source.htm +++ /dev/null @@ -1,137 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Pluma.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_PLUMA_HPP
-
26 #define PLUMA_PLUMA_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <Pluma/Provider.hpp>
-
33 #include <Pluma/PluginManager.hpp>
-
34 
-
36 // Andy macro to convert parameter to string
-
38 #define PLUMA_2STRING(X) #X
-
39 
-
41 // Macro that helps host applications defining
-
42 // their provider classes
-
44 #define PLUMA_PROVIDER_HEADER(TYPE)\
-
45 PLUMA_PROVIDER_HEADER_BEGIN(TYPE)\
-
46 virtual TYPE* create() const = 0;\
-
47 PLUMA_PROVIDER_HEADER_END
-
48 
-
50 // Macro that generate first part of the provider definition
-
52 #define PLUMA_PROVIDER_HEADER_BEGIN(TYPE)\
-
53 class TYPE##Provider: public pluma::Provider{\
-
54 private:\
-
55  friend class pluma::Pluma;\
-
56  static const unsigned int PLUMA_INTERFACE_VERSION;\
-
57  static const unsigned int PLUMA_INTERFACE_LOWEST_VERSION;\
-
58  static const std::string PLUMA_PROVIDER_TYPE;\
-
59  std::string plumaGetType() const{ return PLUMA_PROVIDER_TYPE; }\
-
60 public:\
-
61  unsigned int getVersion() const{ return PLUMA_INTERFACE_VERSION; }
-
62 
-
64 // Macro that generate last part of the provider definition
-
66 #define PLUMA_PROVIDER_HEADER_END };
-
67 
-
69 // Macro that generate the provider declaration
-
71 #define PLUMA_PROVIDER_SOURCE(TYPE, Version, LowestVersion)\
-
72 const std::string TYPE##Provider::PLUMA_PROVIDER_TYPE = PLUMA_2STRING( TYPE );\
-
73 const unsigned int TYPE##Provider::PLUMA_INTERFACE_VERSION = Version;\
-
74 const unsigned int TYPE##Provider::PLUMA_INTERFACE_LOWEST_VERSION = LowestVersion;
-
75 
-
76 
-
78 // Macro that helps plugins generating their provider implementations
-
79 // PRE: SPECIALIZED_TYPE must inherit from BASE_TYPE
-
81 #define PLUMA_INHERIT_PROVIDER(SPECIALIZED_TYPE, BASE_TYPE)\
-
82 class SPECIALIZED_TYPE##Provider: public BASE_TYPE##Provider{\
-
83 public:\
-
84  BASE_TYPE * create() const{ return new SPECIALIZED_TYPE (); }\
-
85 };
-
86 
-
87 
-
88 namespace pluma{
-
89 
-
94 class Pluma: public PluginManager{
-
95 
-
96 public:
-
101  Pluma();
-
102 
-
114  template<typename ProviderType>
-
115  void acceptProviderType();
-
116 
-
127  template<typename ProviderType>
-
128  void getProviders(std::vector<ProviderType*>& providers);
-
129 };
-
130 
-
131 #include <Pluma/Pluma.inl>
-
132 
-
133 }
-
134 
-
135 
-
136 #endif // PLUMA_PLUMA_HPP
-
137 
-
138 
-
Manages loaded plugins.
-
Pluma plugins management.
Definition: Pluma.hpp:94
-
void getProviders(std::vector< ProviderType * > &providers)
Get the stored providers of a certain type.
-
void acceptProviderType()
Tell Pluma to accept a certain type of providers.
-
Pluma()
Default Constructor.
Definition: Pluma.inl:27
-
- - - - diff --git a/doc/third_party/Pluma/html/Pluma_8inl_source.htm b/doc/third_party/Pluma/html/Pluma_8inl_source.htm deleted file mode 100644 index 3955ab5..0000000 --- a/doc/third_party/Pluma/html/Pluma_8inl_source.htm +++ /dev/null @@ -1,86 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Pluma.inl
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 inline Pluma::Pluma(){
-
28  // Nothing to do
-
29 }
-
30 
-
31 
-
33 template<typename ProviderType>
-
34 void Pluma::acceptProviderType(){
-
35  PluginManager::registerType(
-
36  ProviderType::PLUMA_PROVIDER_TYPE,
-
37  ProviderType::PLUMA_INTERFACE_VERSION,
-
38  ProviderType::PLUMA_INTERFACE_LOWEST_VERSION
-
39  );
-
40 }
-
41 
-
42 
-
44 template<typename ProviderType>
-
45 void Pluma::getProviders(std::vector<ProviderType*>& providers){
-
46  const std::list<Provider*>* lst = PluginManager::getProviders(ProviderType::PLUMA_PROVIDER_TYPE);
-
47  if (!lst) return;
-
48  providers.reserve(providers.size() + lst->size());
-
49  std::list<Provider*>::const_iterator it;
-
50  for (it = lst->begin() ; it != lst->end() ; ++it)
-
51  providers.push_back(static_cast<ProviderType*>(*it));
-
52 }
-
- - - - diff --git a/doc/third_party/Pluma/html/Provider_8cpp_source.htm b/doc/third_party/Pluma/html/Provider_8cpp_source.htm deleted file mode 100644 index 64e9be5..0000000 --- a/doc/third_party/Pluma/html/Provider_8cpp_source.htm +++ /dev/null @@ -1,89 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Provider.cpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 
-
27 // Headers
-
29 #include <Pluma/Provider.hpp>
-
30 #include <Pluma/Host.hpp>
-
31 
-
32 
-
33 namespace pluma{
-
34 
- -
37  // Nothing to do
-
38 }
-
39 
-
40 
-
42 bool Provider::isCompatible(const Host& host) const{
-
43  // check compatibility with host
-
44  const std::string& type = this->plumaGetType();
-
45  if (!host.knows(type)) return false;
-
46  unsigned int lowest = host.getLowestVersion(type);
-
47  unsigned int current = host.getVersion(type);
-
48  unsigned int myVersion = this->getVersion();
-
49  return lowest <= myVersion && myVersion <= current;
-
50 }
-
51 
-
52 } // namespace pluma
-
virtual ~Provider()
Destructor.
Definition: Provider.cpp:36
-
virtual unsigned int getVersion() const =0
Get provider version.
-
Manages providers.
Definition: Host.hpp:44
-
bool isCompatible(const Host &host) const
Check compatibility with host.
Definition: Provider.cpp:42
-
- - - - diff --git a/doc/third_party/Pluma/html/Provider_8hpp_source.htm b/doc/third_party/Pluma/html/Provider_8hpp_source.htm deleted file mode 100644 index bba5d6a..0000000 --- a/doc/third_party/Pluma/html/Provider_8hpp_source.htm +++ /dev/null @@ -1,99 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Provider.hpp
-
-
-
1 //
-
3 // Pluma - Plug-in Management Framework
-
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
-
5 //
-
6 // This software is provided 'as-is', without any express or implied warranty.
-
7 // In no event will the authors be held liable for any damages arising from the use of this software.
-
8 //
-
9 // Permission is granted to anyone to use this software for any purpose,
-
10 // including commercial applications, and to alter it and redistribute it freely,
-
11 // subject to the following restrictions:
-
12 //
-
13 // 1. The origin of this software must not be misrepresented;
-
14 // you must not claim that you wrote the original software.
-
15 // If you use this software in a product, an acknowledgment
-
16 // in the product documentation would be appreciated but is not required.
-
17 //
-
18 // 2. Altered source versions must be plainly marked as such,
-
19 // and must not be misrepresented as being the original software.
-
20 //
-
21 // 3. This notice may not be removed or altered from any source distribution.
-
22 //
-
24 
-
25 #ifndef PLUMA_PROVIDER_HPP
-
26 #define PLUMA_PROVIDER_HPP
-
27 
-
29 // Headers
-
31 #include <Pluma/Config.hpp>
-
32 #include <string>
-
33 
-
34 
-
35 namespace pluma{
-
36 class Host;
-
37 
-
42 class PLUMA_API Provider{
-
43 friend class Host;
-
44 
-
45 
-
46 public:
-
47 
-
52  virtual ~Provider();
-
53 
-
60  virtual unsigned int getVersion() const = 0;
-
61 
-
75  bool isCompatible(const Host& host) const;
-
76 
-
77 
-
78 private:
-
79 
-
90  virtual std::string plumaGetType() const = 0;
-
91 
-
92 };
-
93 
-
94 } // namespace pluma
-
95 
-
96 
-
97 #endif // PLUMA_PROVIDER_HPP
-
98 
-
99 
-
Interface to provide applications with objects from plugins.
Definition: Provider.hpp:42
-
Manages providers.
Definition: Host.hpp:44
-
- - - - diff --git a/doc/third_party/Pluma/html/annotated.htm b/doc/third_party/Pluma/html/annotated.htm deleted file mode 100644 index b5d70dd..0000000 --- a/doc/third_party/Pluma/html/annotated.htm +++ /dev/null @@ -1,52 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Class List
-
-
-
Here are the classes, structs, unions and interfaces with brief descriptions:
-
[detail level 12]
- - - - - - -
\Npluma
 oCDLibraryManages a Dynamic Linking Library
 oCHostManages providers
 oCPluginManagerManages loaded plugins
 oCPlumaPluma plugins management
 \CProviderInterface to provide applications with objects from plugins
-
-
- - - - diff --git a/doc/third_party/Pluma/html/bc_s.png b/doc/third_party/Pluma/html/bc_s.png deleted file mode 100644 index 224b29aa9847d5a4b3902efd602b7ddf7d33e6c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 676 zcmV;V0$crwP)y__>=_9%My z{n931IS})GlGUF8K#6VIbs%684A^L3@%PlP2>_sk`UWPq@f;rU*V%rPy_ekbhXT&s z(GN{DxFv}*vZp`F>S!r||M`I*nOwwKX+BC~3P5N3-)Y{65c;ywYiAh-1*hZcToLHK ztpl1xomJ+Yb}K(cfbJr2=GNOnT!UFA7Vy~fBz8?J>XHsbZoDad^8PxfSa0GDgENZS zuLCEqzb*xWX2CG*b&5IiO#NzrW*;`VC9455M`o1NBh+(k8~`XCEEoC1Ybwf;vr4K3 zg|EB<07?SOqHp9DhLpS&bzgo70I+ghB_#)K7H%AMU3v}xuyQq9&Bm~++VYhF09a+U zl7>n7Jjm$K#b*FONz~fj;I->Bf;ule1prFN9FovcDGBkpg>)O*-}eLnC{6oZHZ$o% zXKW$;0_{8hxHQ>l;_*HATI(`7t#^{$(zLe}h*mqwOc*nRY9=?Sx4OOeVIfI|0V(V2 zBrW#G7Ss9wvzr@>H*`r>zE z+e8bOBgqIgldUJlG(YUDviMB`9+DH8n-s9SXRLyJHO1!=wY^79WYZMTa(wiZ!zP66 zA~!21vmF3H2{ngD;+`6j#~6j;$*f*G_2ZD1E;9(yaw7d-QnSCpK(cR1zU3qU0000< KMNUMnLSTYoA~SLT diff --git a/doc/third_party/Pluma/html/bdwn.png b/doc/third_party/Pluma/html/bdwn.png deleted file mode 100644 index 940a0b950443a0bb1b216ac03c45b8a16c955452..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147 zcmV;E0Brw>P)3^A{Hh@-| z>oc?m#Ror3b0;W$tUfCWo=fu__ocsM5oll+f(u^P8w7*ijcxz{002ovPDHLkV1f&@ BGwT2V diff --git a/doc/third_party/Pluma/html/classes.htm b/doc/third_party/Pluma/html/classes.htm deleted file mode 100644 index cb2c15c..0000000 --- a/doc/third_party/Pluma/html/classes.htm +++ /dev/null @@ -1,53 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Class Index
-
-
-
D | H | P
- - - - - -
  D  
-
  H  
-
  P  
-
Pluma (pluma)   
Provider (pluma)   
DLibrary (pluma)   Host (pluma)   PluginManager (pluma)   
-
D | H | P
-
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1DLibrary-members.htm b/doc/third_party/Pluma/html/classpluma_1_1DLibrary-members.htm deleted file mode 100644 index 0a21d3f..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1DLibrary-members.htm +++ /dev/null @@ -1,52 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
-
pluma::DLibrary Member List
-
-
- -

This is the complete list of members for pluma::DLibrary, including all inherited members.

- - - - -
getSymbol(const std::string &symbol)pluma::DLibrary
load(const std::string &path)pluma::DLibrarystatic
~DLibrary()pluma::DLibrary
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1DLibrary.htm b/doc/third_party/Pluma/html/classpluma_1_1DLibrary.htm deleted file mode 100644 index 3d34b08..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1DLibrary.htm +++ /dev/null @@ -1,163 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
- -
-
pluma::DLibrary Class Reference
-
-
- -

Manages a Dynamic Linking Library. - More...

- -

#include <DLibrary.hpp>

- - - - - - - - -

-Public Member Functions

 ~DLibrary ()
 Destructor. More...
 
void * getSymbol (const std::string &symbol)
 Get a symbol from the library. More...
 
- - - - -

-Static Public Member Functions

static DLibraryload (const std::string &path)
 Load a library. More...
 
-

Detailed Description

-

Manages a Dynamic Linking Library.

- -

Definition at line 49 of file DLibrary.hpp.

-

Constructor & Destructor Documentation

- -
-
- - - - - - - -
pluma::DLibrary::~DLibrary ()
-
- -

Destructor.

-

Close and free the opened library (if any).

- -

Definition at line 67 of file DLibrary.cpp.

- -
-
-

Member Function Documentation

- -
-
- - - - - - - - -
void * pluma::DLibrary::getSymbol (const std::string & symbol)
-
- -

Get a symbol from the library.

-
Parameters
- - -
symbolSymbol that we're looking for.
-
-
-
Returns
Pointer to what the symbol refers to, or NULL if the symbol is not found.
- -

Definition at line 79 of file DLibrary.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - -
DLibrary * pluma::DLibrary::load (const std::string & path)
-
-static
-
- -

Load a library.

-
Parameters
- - -
pathPath to the library.
-
-
-
Returns
Pointer to the loaded library, or NULL if failed.
- -

Definition at line 37 of file DLibrary.cpp.

- -
-
-
The documentation for this class was generated from the following files: -
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1Host-members.htm b/doc/third_party/Pluma/html/classpluma_1_1Host-members.htm deleted file mode 100644 index dae8f08..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1Host-members.htm +++ /dev/null @@ -1,52 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
-
pluma::Host Member List
-
-
- -

This is the complete list of members for pluma::Host, including all inherited members.

- - - - -
add(Provider *provider)pluma::Host
PluginManager (defined in pluma::Host)pluma::Hostfriend
Provider (defined in pluma::Host)pluma::Hostfriend
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1Host.htm b/doc/third_party/Pluma/html/classpluma_1_1Host.htm deleted file mode 100644 index b5b0096..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1Host.htm +++ /dev/null @@ -1,109 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
- -
-
pluma::Host Class Reference
-
-
- -

Manages providers. - More...

- -

#include <Host.hpp>

- - - - - -

-Public Member Functions

bool add (Provider *provider)
 Add provider. More...
 
- - - - - -

-Friends

-class PluginManager
 
-class Provider
 
-

Detailed Description

-

Manages providers.

- -

Definition at line 44 of file Host.hpp.

-

Member Function Documentation

- -
-
- - - - - - - - -
bool pluma::Host::add (Providerprovider)
-
- -

Add provider.

-

Provider type and version are checked. Only known and valid provider types are accepted.

-
Parameters
- - -
providerProvider to be added.
-
-
-
Returns
True if the provider is accepted.
- -

Definition at line 42 of file Host.cpp.

- -
-
-
The documentation for this class was generated from the following files: -
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1PluginManager-members.htm b/doc/third_party/Pluma/html/classpluma_1_1PluginManager-members.htm deleted file mode 100644 index 93bfd8a..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1PluginManager-members.htm +++ /dev/null @@ -1,61 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
-
pluma::PluginManager Member List
-
-
- -

This is the complete list of members for pluma::PluginManager, including all inherited members.

- - - - - - - - - - - - - -
addProvider(Provider *provider)pluma::PluginManager
getLoadedPlugins(std::vector< const std::string * > &pluginNames) const pluma::PluginManager
getProviders(const std::string &type) const pluma::PluginManagerprotected
isLoaded(const std::string &pluginName) const pluma::PluginManager
load(const std::string &path)pluma::PluginManager
load(const std::string &folder, const std::string &pluginName)pluma::PluginManager
loadFromFolder(const std::string &folder, bool recursive=false)pluma::PluginManager
PluginManager()pluma::PluginManagerprotected
registerType(const std::string &type, unsigned int version, unsigned int lowestVersion)pluma::PluginManagerprotected
unload(const std::string &pluginName)pluma::PluginManager
unloadAll()pluma::PluginManager
~PluginManager()pluma::PluginManager
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1PluginManager.htm b/doc/third_party/Pluma/html/classpluma_1_1PluginManager.htm deleted file mode 100644 index eec4670..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1PluginManager.htm +++ /dev/null @@ -1,515 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
- -
-
pluma::PluginManager Class Reference
-
-
- -

Manages loaded plugins. - More...

- -

#include <PluginManager.hpp>

-
-Inheritance diagram for pluma::PluginManager:
-
-
- - -pluma::Pluma - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Public Member Functions

 ~PluginManager ()
 Destructor. More...
 
bool load (const std::string &path)
 Load a plugin given it's path. More...
 
bool load (const std::string &folder, const std::string &pluginName)
 Load a plugin from a given folder. More...
 
int loadFromFolder (const std::string &folder, bool recursive=false)
 Load all plugins from a given folder. More...
 
bool unload (const std::string &pluginName)
 Unload a plugin. More...
 
void unloadAll ()
 Unload all loaded plugins. More...
 
bool addProvider (Provider *provider)
 Directly add a new provider. More...
 
void getLoadedPlugins (std::vector< const std::string * > &pluginNames) const
 Get the name of all loaded plugins. More...
 
bool isLoaded (const std::string &pluginName) const
 Check if a plug-in is loaded. More...
 
- - - - - - - - - - -

-Protected Member Functions

 PluginManager ()
 Default constructor. More...
 
void registerType (const std::string &type, unsigned int version, unsigned int lowestVersion)
 Register a provider type. More...
 
const std::list< Provider * > * getProviders (const std::string &type) const
 Get providers of a certain type. More...
 
-

Detailed Description

-

Manages loaded plugins.

- -

Definition at line 44 of file PluginManager.hpp.

-

Constructor & Destructor Documentation

- -
-
- - - - - - - -
pluma::PluginManager::~PluginManager ()
-
- -

Destructor.

- -

Definition at line 43 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - -
pluma::PluginManager::PluginManager ()
-
-protected
-
- -

Default constructor.

-

PluginManager cannot be publicly instantiated.

- -

Definition at line 37 of file PluginManager.cpp.

- -
-
-

Member Function Documentation

- -
-
- - - - - - - - -
bool pluma::PluginManager::addProvider (Providerprovider)
-
- -

Directly add a new provider.

-
Parameters
- - -
providerProvider.
-
-
- -

Definition at line 168 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - - -
void pluma::PluginManager::getLoadedPlugins (std::vector< const std::string * > & pluginNames) const
-
- -

Get the name of all loaded plugins.

-
Parameters
- - -
pluginNamesA vector to fill with the plugins names.
-
-
- -

Definition at line 178 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - -
const std::list< Provider * > * pluma::PluginManager::getProviders (const std::string & type) const
-
-protected
-
- -

Get providers of a certain type.

-
Parameters
- - -
typeProvider type.
-
-
-
Returns
Pointer to the list of providers of that type, or NULL if type is not registered.
-
See Also
Host::getProviders
- -

Definition at line 194 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - - -
bool pluma::PluginManager::isLoaded (const std::string & pluginName) const
-
- -

Check if a plug-in is loaded.

-
Parameters
- - -
pluginNamethe plug-in tname o check.
-
-
- -

Definition at line 188 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - - -
bool pluma::PluginManager::load (const std::string & path)
-
- -

Load a plugin given it's path.

-
Parameters
- - -
pathPath for the plugin, including plugin name. File extension may be included, but is discouraged for better cross platform code. If file extension isn't present on the path, Pluma will deduce it from the operating system.
-
-
-
Returns
True if the plugin is successfully loaded.
-
See Also
load(const std::string&, const std::string&)
-
-loadFromFolder
-
-unload
-
-unloadAll
- -

Definition at line 49 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
bool pluma::PluginManager::load (const std::string & folder,
const std::string & pluginName 
)
-
- -

Load a plugin from a given folder.

-
Parameters
- - - -
folderThe folder path.
pluginNameName of the plugin. File extension may be included, but is discouraged for better cross platform code. If file extension is omitted, Pluma will deduce it from the operating system.
-
-
-
Returns
True if the plugin is successfully loaded.
-
See Also
load(const std::string&)
-
-loadFromFolder
-
-unload
-
-unloadAll
- -

Definition at line 85 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - - - - - - - - - - - - -
int pluma::PluginManager::loadFromFolder (const std::string & folder,
bool recursive = false 
)
-
- -

Load all plugins from a given folder.

-
Parameters
- - - -
folderPath for the folder where the plug-ins are.
recursiveIf true it will search on sub-folders as well
-
-
-
Returns
Number of successfully loaded plug-ins.
-
See Also
load(const std::string&, const std::string&)
-
-load(const std::string&)
-
-unload
-
-unloadAll
- -

Definition at line 95 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
void pluma::PluginManager::registerType (const std::string & type,
unsigned int version,
unsigned int lowestVersion 
)
-
-protected
-
- -

Register a provider type.

-
Parameters
- - - - -
typeProvider type.
versionCurrent version of that provider type.
lowestVersionLowest compatible version of that provider type.
-
-
-
See Also
Host::registerType
- -

Definition at line 162 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - - -
bool pluma::PluginManager::unload (const std::string & pluginName)
-
- -

Unload a plugin.

-
Parameters
- - -
pluginNameName or path of the plugin.
-
-
-
Returns
True if the plugin is successfully unloaded, false if no such plugin exists on the manager.
-
See Also
load(const std::string&, const std::string&)
-
-load(const std::string&)
-
-loadFromFolder
-
-unloadAll
- -

Definition at line 109 of file PluginManager.cpp.

- -
-
- -
-
- - - - - - - -
void pluma::PluginManager::unloadAll ()
-
- -

Unload all loaded plugins.

-
See Also
load(const std::string&, const std::string&)
-
-load(const std::string&)
-
-loadFromFolder
-
-unload
- -

Definition at line 122 of file PluginManager.cpp.

- -
-
-
The documentation for this class was generated from the following files: -
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1PluginManager.png b/doc/third_party/Pluma/html/classpluma_1_1PluginManager.png deleted file mode 100644 index a5fc17ed1f769070ff7cfbfed6c8c6884821f79d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 609 zcmV-n0-pVeP)vTJkN^MxkN^Mxkifve1&Q1r00008bW%=J0RR90|NsC0)yh;d0005-NklO2V}Y2a{5o^-ZuwY|quC6mb1+ zn`nD=l&8(0nbhfv$r5kPnwmGRu~n!{+@|UVl!feT(#cSFp%%sT$>C;;=_WRfb%--< z_1R=gzHi5|i7Chu+Lmvg_Pu|>#2uA;CZp=vo8^AJ2EE*2)}) z+T?bXwS?sibSvOP&C}uRban^ezqlRT33zVOed7X*7zBKwCicY#@R5E%{1yXv!UVuG zl}Sn|%>ck-UI0@tjmhgZi^?=6Z;?q<<}r!01F$Dd06bv=;0Y4|PnZCB!UVt*CIFr= z0q}$gfG11_W|8`s8$+ zB=vY^vL$z^K8=&49*<01)lW>mwmV5`SCZ^CG8vDPq#n1 - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
-
pluma::Pluma Member List
-
-
- -

This is the complete list of members for pluma::Pluma, including all inherited members.

- - - - - - - - - - - - - - - - - - -
acceptProviderType()pluma::Pluma
acceptProviderType() (defined in pluma::Pluma)pluma::Pluma
addProvider(Provider *provider)pluma::PluginManager
getLoadedPlugins(std::vector< const std::string * > &pluginNames) const pluma::PluginManager
getProviders(std::vector< ProviderType * > &providers)pluma::Pluma
getProviders(std::vector< ProviderType * > &providers) (defined in pluma::Pluma)pluma::Pluma
pluma::PluginManager::getProviders(const std::string &type) const pluma::PluginManagerprotected
isLoaded(const std::string &pluginName) const pluma::PluginManager
load(const std::string &path)pluma::PluginManager
load(const std::string &folder, const std::string &pluginName)pluma::PluginManager
loadFromFolder(const std::string &folder, bool recursive=false)pluma::PluginManager
PluginManager()pluma::PluginManagerprotected
Pluma()pluma::Plumainline
registerType(const std::string &type, unsigned int version, unsigned int lowestVersion)pluma::PluginManagerprotected
unload(const std::string &pluginName)pluma::PluginManager
unloadAll()pluma::PluginManager
~PluginManager()pluma::PluginManager
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1Pluma.htm b/doc/third_party/Pluma/html/classpluma_1_1Pluma.htm deleted file mode 100644 index 95fc1bd..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1Pluma.htm +++ /dev/null @@ -1,650 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
- -
-
pluma::Pluma Class Reference
-
-
- -

Pluma plugins management. - More...

- -

#include <Pluma.hpp>

-
-Inheritance diagram for pluma::Pluma:
-
-
- - -pluma::PluginManager - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Public Member Functions

 Pluma ()
 Default Constructor. More...
 
template<typename ProviderType >
void acceptProviderType ()
 Tell Pluma to accept a certain type of providers. More...
 
template<typename ProviderType >
void getProviders (std::vector< ProviderType * > &providers)
 Get the stored providers of a certain type. More...
 
-template<typename ProviderType >
void acceptProviderType ()
 
-template<typename ProviderType >
void getProviders (std::vector< ProviderType * > &providers)
 
bool load (const std::string &path)
 Load a plugin given it's path. More...
 
bool load (const std::string &folder, const std::string &pluginName)
 Load a plugin from a given folder. More...
 
int loadFromFolder (const std::string &folder, bool recursive=false)
 Load all plugins from a given folder. More...
 
bool unload (const std::string &pluginName)
 Unload a plugin. More...
 
void unloadAll ()
 Unload all loaded plugins. More...
 
bool addProvider (Provider *provider)
 Directly add a new provider. More...
 
void getLoadedPlugins (std::vector< const std::string * > &pluginNames) const
 Get the name of all loaded plugins. More...
 
bool isLoaded (const std::string &pluginName) const
 Check if a plug-in is loaded. More...
 
- - - - - - - -

-Protected Member Functions

void registerType (const std::string &type, unsigned int version, unsigned int lowestVersion)
 Register a provider type. More...
 
const std::list< Provider * > * getProviders (const std::string &type) const
 Get providers of a certain type. More...
 
-

Detailed Description

-

Pluma plugins management.

-

Pluma is the main class of Pluma library. Allows hosting applications to load/unload dlls in runtime (plugins), and to get providers of shared interface objects.

-

Example:

-
-
// Tell it to accept providers of the type DeviceProvider
-
pluma.acceptProviderType<DeviceProvider>();
-
// Load some dll
-
pluma.load("plugins/standard_devices");
-
// Get device providers into a vector
-
std::vector<DeviceProvider*> providers;
-
pluma.getProviders(providers);
-
// create a Device from the first provider
-
if (!providers.empty()){
-
Device* myDevice = providers.first()->create();
-
// do something with myDevice
-
std::cout << device->getDescription() << std::endl;
-
// (...)
-
delete myDevice;
-
}
-

It is also possible to add local providers, providers that are defined directly on the host application. That can be useful to provide and use default implementations of certain interfaces, along with plugin implementations.

- -

Definition at line 94 of file Pluma.hpp.

-

Constructor & Destructor Documentation

- -
-
- - - - - -
- - - - - - - -
Pluma::Pluma ()
-
-inline
-
- -

Default Constructor.

- -

Definition at line 27 of file Pluma.inl.

- -
-
-

Member Function Documentation

- -
-
-
-template<typename ProviderType >
- - - - - - - -
void pluma::Pluma::acceptProviderType ()
-
- -

Tell Pluma to accept a certain type of providers.

-

A Pluma object is able to accept multiple types of providers. When a plugin is loaded, it tries to register it's providers implementations. Those are only accepted by the host application if it's accepting providers of that kind.

-
Template Parameters
- - -
ProviderTypetype of provider.
-
-
- -
-
- -
-
- - - - - -
- - - - - - - - -
bool pluma::PluginManager::addProvider (Providerprovider)
-
-inherited
-
- -

Directly add a new provider.

-
Parameters
- - -
providerProvider.
-
-
- -

Definition at line 168 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - -
void pluma::PluginManager::getLoadedPlugins (std::vector< const std::string * > & pluginNames) const
-
-inherited
-
- -

Get the name of all loaded plugins.

-
Parameters
- - -
pluginNamesA vector to fill with the plugins names.
-
-
- -

Definition at line 178 of file PluginManager.cpp.

- -
-
- -
-
-
-template<typename ProviderType >
- - - - - - - - -
void pluma::Pluma::getProviders (std::vector< ProviderType * > & providers)
-
- -

Get the stored providers of a certain type.

-

Providers are added at the end of the providers vector.

-
Template Parameters
- - -
ProviderTypetype of provider to be returned.
-
-
-
Parameters
- - -
[out]providersVector to fill with the existing providers.
-
-
- -
-
- -
-
- - - - - -
- - - - - - - - -
const std::list< Provider * > * pluma::PluginManager::getProviders (const std::string & type) const
-
-protectedinherited
-
- -

Get providers of a certain type.

-
Parameters
- - -
typeProvider type.
-
-
-
Returns
Pointer to the list of providers of that type, or NULL if type is not registered.
-
See Also
Host::getProviders
- -

Definition at line 194 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - -
bool pluma::PluginManager::isLoaded (const std::string & pluginName) const
-
-inherited
-
- -

Check if a plug-in is loaded.

-
Parameters
- - -
pluginNamethe plug-in tname o check.
-
-
- -

Definition at line 188 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - -
bool pluma::PluginManager::load (const std::string & path)
-
-inherited
-
- -

Load a plugin given it's path.

-
Parameters
- - -
pathPath for the plugin, including plugin name. File extension may be included, but is discouraged for better cross platform code. If file extension isn't present on the path, Pluma will deduce it from the operating system.
-
-
-
Returns
True if the plugin is successfully loaded.
-
See Also
load(const std::string&, const std::string&)
-
-loadFromFolder
-
-unload
-
-unloadAll
- -

Definition at line 49 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
bool pluma::PluginManager::load (const std::string & folder,
const std::string & pluginName 
)
-
-inherited
-
- -

Load a plugin from a given folder.

-
Parameters
- - - -
folderThe folder path.
pluginNameName of the plugin. File extension may be included, but is discouraged for better cross platform code. If file extension is omitted, Pluma will deduce it from the operating system.
-
-
-
Returns
True if the plugin is successfully loaded.
-
See Also
load(const std::string&)
-
-loadFromFolder
-
-unload
-
-unloadAll
- -

Definition at line 85 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
int pluma::PluginManager::loadFromFolder (const std::string & folder,
bool recursive = false 
)
-
-inherited
-
- -

Load all plugins from a given folder.

-
Parameters
- - - -
folderPath for the folder where the plug-ins are.
recursiveIf true it will search on sub-folders as well
-
-
-
Returns
Number of successfully loaded plug-ins.
-
See Also
load(const std::string&, const std::string&)
-
-load(const std::string&)
-
-unload
-
-unloadAll
- -

Definition at line 95 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
void pluma::PluginManager::registerType (const std::string & type,
unsigned int version,
unsigned int lowestVersion 
)
-
-protectedinherited
-
- -

Register a provider type.

-
Parameters
- - - - -
typeProvider type.
versionCurrent version of that provider type.
lowestVersionLowest compatible version of that provider type.
-
-
-
See Also
Host::registerType
- -

Definition at line 162 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - - -
bool pluma::PluginManager::unload (const std::string & pluginName)
-
-inherited
-
- -

Unload a plugin.

-
Parameters
- - -
pluginNameName or path of the plugin.
-
-
-
Returns
True if the plugin is successfully unloaded, false if no such plugin exists on the manager.
-
See Also
load(const std::string&, const std::string&)
-
-load(const std::string&)
-
-loadFromFolder
-
-unloadAll
- -

Definition at line 109 of file PluginManager.cpp.

- -
-
- -
-
- - - - - -
- - - - - - - -
void pluma::PluginManager::unloadAll ()
-
-inherited
-
- -

Unload all loaded plugins.

-
See Also
load(const std::string&, const std::string&)
-
-load(const std::string&)
-
-loadFromFolder
-
-unload
- -

Definition at line 122 of file PluginManager.cpp.

- -
-
-
The documentation for this class was generated from the following files: -
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1Pluma.png b/doc/third_party/Pluma/html/classpluma_1_1Pluma.png deleted file mode 100644 index 29983adc78779373c36014ed3e36d065895c7593..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 602 zcmV-g0;TvTJkN^MxkN^Mxkifve1&Q1r00008bW%=J0RR90|NsC0)yh;d0005$NklyGOn3D+mi&a6UgPXE1{KFnWoL!creiZCFh){fGkN95GIo32@^^3 z>`js+osj7n3F5nl&|VTyv{XDbR-MCX|Wnd(x>;SD`k=?32UIHnUFE zcCVLLhrVO772j{iv59HOlG>(kKJEAZ4HI`%o|%lgXZQTkBuVW`lD$SI`wg;h`*0o4 zSEu&M9EQ5d?JR2x%Ngi)z^9r|hqKdJ9ZC8x9w&DaJ~!!p<4V$qLBbb$V!!w#>5_gz z{1!`+Crl*CGnGlsInMyV$GiZhU>cLxYZjGhOx_}ssLW#$X9r+Um;iXf1i%v}0G==b z@Pr9~Crki5VFKU@697+`0C>U#z!N3_p1)?2Qc6=m0+@g>0q}$gfaku+RouG&uj2rE ze9>fk`9+g=$Trt{D+Sjs986B*0D9apsl%5Fi<_<3N}k05jJeg5!(7cO)O52?PU8T2 zd}gv0ccrf40D636;<|of^0n1T(5?jb8kvma0D3$+J8c8DuGbS{Oa^fPV{Wbvz%LUf o0G{|Q2JnOlfM+U`lv0|3A4Fapr`OccVE_OC07*qoM6N<$f`P{vQUCw| diff --git a/doc/third_party/Pluma/html/classpluma_1_1Provider-members.htm b/doc/third_party/Pluma/html/classpluma_1_1Provider-members.htm deleted file mode 100644 index 7dfdf91..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1Provider-members.htm +++ /dev/null @@ -1,53 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
-
pluma::Provider Member List
-
-
- -

This is the complete list of members for pluma::Provider, including all inherited members.

- - - - - -
getVersion() const =0pluma::Providerpure virtual
Host (defined in pluma::Provider)pluma::Providerfriend
isCompatible(const Host &host) const pluma::Provider
~Provider()pluma::Providervirtual
- - - - diff --git a/doc/third_party/Pluma/html/classpluma_1_1Provider.htm b/doc/third_party/Pluma/html/classpluma_1_1Provider.htm deleted file mode 100644 index ea7b0ee..0000000 --- a/doc/third_party/Pluma/html/classpluma_1_1Provider.htm +++ /dev/null @@ -1,233 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
- -
-
pluma::Provider Class Referenceabstract
-
-
- -

Interface to provide applications with objects from plugins. - More...

- -

#include <Provider.hpp>

- - - - - - - - - - - -

-Public Member Functions

virtual ~Provider ()
 Destructor. More...
 
virtual unsigned int getVersion () const =0
 Get provider version. More...
 
bool isCompatible (const Host &host) const
 Check compatibility with host. More...
 
- - - -

-Friends

-class Host
 
-

Detailed Description

-

Interface to provide applications with objects from plugins.

-

The plugin specific implementations are unknown at the host side, only their shared interfaces are known. Then, host app needs a generic way of create interface objects. That's what provider classes are for. It is the factory design pattern (http://www.oodesign.com/factory-pattern.html)

-

Shared interfaces define their provider types (by inheriting from pluma::Provider). Hosts then use those tipes to get objects from the plugins. Plugins derive the shared interface providers so that they can provide host with specific implementations of the shared interface. Those specific providers are given to the host through a connect function.

-

Example: A host app uses objects of type Device. A certain plugin defines a Keyboard, witch is a Device. The Host will use DeviceProviders to create objects of type Device. The plugin will provide host specifically with a KeyboardProvider. Other plugins may provide host with other derived DeviceProvider types.

-

Device hpp (shared):

-
#include <Pluma/Pluma.hpp>
-
class Device{
-
public:
-
virtual std::string getDescription() const = 0;
-
};
-
// create DevicedProvider class
-
PLUMA_PROVIDER_HEADER(Device);
-

Device cpp (shared):

-
#include "Device.hpp"
-
generate DevicedProvider with version 6, and compatible with at least v.3
-
PLUMA_PROVIDER_SOURCE(Device, 6, 3);
-


- Keyboard code on the plugin side:

-
#include <Pluma/Pluma.hpp>
-
#include "Device.hpp"
-
-
class Keyboard: public Device{
-
public:
-
std::string getDescription() const{
-
return "keyboard";
-
}
-
};
-
-
// create KeyboardProvider, it implements DeviceProvider
-
PLUMA_INHERIT_PROVIDER(Keyboard, Device);
-

plugin connector:

-
#include <Pluma/Connector.hpp>
-
#include "Keyboard.hpp"
-
-
PLUMA_CONNECTOR
-
bool connect(pluma::Host& host){
-
// add a keyboard provider to host
-
host.add( new KeyboardProvider() );
-
return true;
-
}
-

Host application code:

-
#include <Pluma/Pluma.hpp>
-
-
#include "Device.hpp"
-
#include <iostream>
-
#include <vector>
-
-
int main(){
-
-
pluma::Pluma plugins;
-
// Tell plugins manager to accept providers of the type DeviceProvider
-
plugins.acceptProviderType<DeviceProvider>();
-
// Load library "standard_devices" from folder "plugins"
-
plugins.load("plugins", "standard_devices");
-
-
// Get device providers into a vector
-
std::vector<DeviceProvider*> providers;
-
plugins.getProviders(providers);
-
-
// create a Device from the first provider
-
if (!providers.empty()){
-
Device* myDevice = providers.first()->create();
-
// do something with myDevice
-
std::cout << device->getDescription() << std::endl;
-
// and delete it in the end
-
delete myDevice;
-
}
-
return 0;
-
}
-
-

Definition at line 42 of file Provider.hpp.

-

Constructor & Destructor Documentation

- -
-
- - - - - -
- - - - - - - -
pluma::Provider::~Provider ()
-
-virtual
-
- -

Destructor.

- -

Definition at line 36 of file Provider.cpp.

- -
-
-

Member Function Documentation

- -
-
- - - - - -
- - - - - - - -
virtual unsigned int pluma::Provider::getVersion () const
-
-pure virtual
-
- -

Get provider version.

-
Returns
Version number.
- -
-
- -
-
- - - - - - - - -
bool pluma::Provider::isCompatible (const Hosthost) const
-
- -

Check compatibility with host.

-

The same provider may be compiled with different versions on host side and on plugins side. This function checks if a plugin provider is compatible with the current version of the same provider type on the host side.

-
Parameters
- - -
hostHost, proxy of host application.
-
-
-
Returns
True if it's compatible with host.
- -

Definition at line 42 of file Provider.cpp.

- -
-
-
The documentation for this class was generated from the following files: -
- - - - diff --git a/doc/third_party/Pluma/html/closed.png b/doc/third_party/Pluma/html/closed.png deleted file mode 100644 index 98cc2c909da37a6df914fbf67780eebd99c597f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmeAS@N?(olHy`uVBq!ia0y~yVBiE{4mJh`h6fYb1Q-|?yggkULn;{G-p%E8P~>R4 z=$<|EB$N38-2}DbmnFr_%O)K7`0vvPK}LtC*|iL-j2e1dIRjJ=#-IMT-)|GIo|S=1 k_R{V{v-v8NIIqptTqq(?amn;60|Nttr>mdKI;Vst0N5uiMgRZ+ diff --git a/doc/third_party/Pluma/html/doxygen.css b/doc/third_party/Pluma/html/doxygen.css deleted file mode 100644 index 3f2e69f..0000000 --- a/doc/third_party/Pluma/html/doxygen.css +++ /dev/null @@ -1,384 +0,0 @@ -div#logo -{ - margin-bottom : 1em; - background : url("./logo-bg.jpg") repeat-x; -} - -div#logo a -{ - display : block; -} - -p#footer -{ - text-decoration : overline; - color : #606060; - padding-top : 1em; - text-align : center; - font-size : smaller; -} - -p#footer a -{ - color : #007298; - text-decoration : none; -} - -BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { - font-family: Geneva, Arial, Helvetica, sans-serif; -} -BODY,TD { - font-size: 90%; -} -H1 { - text-align : center; - margin-top : 0px; - color : #2090B0; - font-size : 160%; -} -H2 { - font-size: 120%; -} -H3 { - font-size: 100%; -} -CAPTION { font-weight: bold } -DIV.qindex { - width: 100%; - background-color: #E0FFE0; - border: 1px dotted #808080; - text-align: center; - margin: 2px; - padding: 2px; - line-height: 140%; -} -DIV.nav { - width: 100%; - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - padding: 2px; - line-height: 140%; -} -DIV.navtab { - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} -TD.navtab { - font-size: 70%; -} -A.qindex { - text-decoration: none; - font-weight: bold; -} -A.qindex:visited { - text-decoration: none; - font-weight: bold; -} -A.qindex:hover { - text-decoration: none; - background-color: #ddddff; -} -A.qindexHL { - text-decoration: none; - font-weight: bold; - background-color: #6666cc; - color: #ffffff; - border: 1px double #9295C2; -} -A.qindexHL:hover { - text-decoration: none; - background-color: #6666cc; - color: #ffffff; -} -A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } -A.el { text-decoration: none; font-weight: bold } -A.elRef { font-weight: bold } -A.code:link { text-decoration: none; font-weight: normal; border-bottom : 1px dotted #808080; color: black;} -A.code:visited { text-decoration: none; font-weight: normal; border-bottom : 1px dotted #808080; color: black;} -A.codeRef:link { font-weight: normal; color: #0000FF} -A.codeRef:visited { font-weight: normal; color: #0000FF} -/*A:hover { text-decoration: none; background-color: #f2f2ff }*/ -DL.el { margin-left: -1cm } -.fragment { - font-family: monospace, fixed; - font-size: 95%; -} -PRE.fragment { - border: 1px solid #CCCCCC; - background-color: #f5f5f5; - margin-top: 4px; - margin-bottom: 4px; - margin-left: 2px; - margin-right: 8px; - padding-left: 6px; - padding-right: 6px; - padding-top: 4px; - padding-bottom: 4px; -} -DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } - -DIV.groupHeader { - margin-left: 16px; - margin-top: 12px; - margin-bottom: 6px; - font-weight: bold; -} -DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } -BODY { - background: white; - color: black; - margin-right: 20px; - margin-left: 20px; -} -TD.indexkey { - background-color: #e8eef2; - font-weight: bold; - padding-right : 10px; - padding-top : 2px; - padding-left : 10px; - padding-bottom : 2px; - margin-left : 0px; - margin-right : 0px; - margin-top : 2px; - margin-bottom : 2px; - border: 1px solid #CCCCCC; -} -TD.indexvalue { - background-color: #e8eef2; - font-style: italic; - padding-right : 10px; - padding-top : 2px; - padding-left : 10px; - padding-bottom : 2px; - margin-left : 0px; - margin-right : 0px; - margin-top : 2px; - margin-bottom : 2px; - border: 1px solid #CCCCCC; -} -TR.memlist { - background-color: #f0f0f0; -} -P.formulaDsp { text-align: center; } -IMG.formulaDsp { } -IMG.formulaInl { vertical-align: middle; } -SPAN.keyword { color: #0000FF } -SPAN.keywordtype { color: #0000FF } -SPAN.keywordflow { color: #0000FF } -SPAN.comment { color: #008000 } -SPAN.preprocessor { color: #008080 } -SPAN.stringliteral { color: #008080 } -SPAN.charliteral { color: #008080 } -.mdescLeft { - padding: 0px 8px 4px 8px; - font-size: 80%; - font-style: italic; - background-color: #FAFAFA; - border-top: 1px none #E0E0E0; - border-right: 1px none #E0E0E0; - border-bottom: 1px none #E0E0E0; - border-left: 1px none #E0E0E0; - margin: 0px; -} -.mdescRight { - padding: 0px 8px 4px 8px; - font-size: 80%; - font-style: italic; - background-color: #FAFAFA; - border-top: 1px none #E0E0E0; - border-right: 1px none #E0E0E0; - border-bottom: 1px none #E0E0E0; - border-left: 1px none #E0E0E0; - margin: 0px; -} -.memItemLeft { - padding: 1px 0px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: solid; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memItemRight { - padding: 1px 8px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: solid; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memTemplItemLeft { - padding: 1px 0px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: none; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memTemplItemRight { - padding: 1px 8px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: none; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - background-color: #FAFAFA; - font-size: 80%; -} -.memTemplParams { - padding: 1px 0px 0px 8px; - margin: 4px; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; - border-top-color: #E0E0E0; - border-right-color: #E0E0E0; - border-bottom-color: #E0E0E0; - border-left-color: #E0E0E0; - border-top-style: solid; - border-right-style: none; - border-bottom-style: none; - border-left-style: none; - color: #606060; - background-color: #FAFAFA; - font-size: 80%; -} -.search { color: #003399; - font-weight: bold; -} -FORM.search { - margin-bottom: 0px; - margin-top: 0px; -} -INPUT.search { font-size: 75%; - color: #000080; - font-weight: normal; - background-color: #e8eef2; -} -TD.tiny { font-size: 75%; -} -a { - color: #2090B0; -} -a:visited { - color: #2090B0; -} -.dirtab { padding: 4px; - border-collapse: collapse; - border: 1px solid #84b0c7; -} -TH.dirtab { background: #e8eef2; - font-weight: bold; -} -HR { height: 1px; - border: none; - border-top: 1px solid black; -} - -/* Style for detailed member documentation */ -.memtemplate { - font-size: 80%; - color: #606060; - font-weight: normal; -} -.memnav { - background-color: #e8eef2; - border: 1px solid #84b0c7; - text-align: center; - margin: 2px; - margin-right: 15px; - padding: 2px; -} -.memitem { - /*padding: 4px;*/ - background-color: #F0FFF0; - border-width: 1px; - border-style: solid; - border-color: #808080; - /*-moz-border-radius: 8px 8px 8px 8px;*/ -} -.memname { - white-space: nowrap; - font-weight: bold; -} -.memdoc{ - padding-left: 10px; -} -.memproto { - background-color: #D0FFD0; - width: 100%; - border-bottom-width: 1px; - border-bottom-style: dotted; - border-bottom-color: #808080; - font-weight: bold; - /*-moz-border-radius: 8px 8px 8px 8px;*/ -} -.paramkey { - text-align: right; -} -.paramtype { - white-space: nowrap; -} -.paramname { - color: #602020; - font-style: italic; - white-space: nowrap; -} -/* End Styling for detailed member documentation */ - -/* for the tree view */ -.ftvtree { - font-family: sans-serif; - margin:0.5em; -} -.directory { font-size: 9pt; font-weight: bold; } -.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } -.directory > h3 { margin-top: 0; } -.directory p { margin: 0px; white-space: nowrap; } -.directory div { display: none; margin: 0px; } -.directory img { vertical-align: -30%; } diff --git a/doc/third_party/Pluma/html/doxygen.png b/doc/third_party/Pluma/html/doxygen.png deleted file mode 100644 index 3ff17d807fd8aa003bed8bb2a69e8f0909592fd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3779 zcmV;!4m|ORP)tMIv#Q0*~7*`IBSO7_x;@a8#Zk6_PeKR_s92J&)(m+);m9Iz3blw)z#Gi zP!9lj4$%+*>Hz@HCmM9L9|8c+0u=!H$O3?R0Kgx|#WP<6fKfC8fM-CQZT|_r@`>VO zX^Hgb|9cJqpdJA5$MCEK`F_2@2Y@s>^+;pF`~jdI0Pvr|vl4`=C)EH@1IFe7pdJ8F zH(qGi004~QnF)Ggga~8v08kGAs2hKTATxr7pwfNk|4#_AaT>w8P6TV+R2kbS$v==} zAjf`s0g#V8lB+b3)5oEI*q+{Yt$MZDruD2^;$+(_%Qn+%v0X-bJO=;@kiJ^ygLBnC z?1OVv_%aex1M@jKU|Z~$eI?PoF4Vj>fDzyo zAiLfpXY*a^Sj-S5D0S3@#V$sRW)g)_1e#$%8xdM>Jm7?!h zu0P2X=xoN>^!4DoPRgph2(2va07yfpXF+WH7EOg1GY%Zn z7~1A<(z7Q$ktEXhW_?GMpHp9l_UL18F3KOsxu81pqoBiNbFSGsof-W z6~eloMoz=4?OOnl2J268x5rOY`dCk0us(uS#Ud4yqOr@?=Q57a}tit|BhY>}~frH1sP`ScHS_d)oqH^lYy zZ%VP`#10MlE~P?cE(%(#(AUSv_T{+;t@$U}El}(1ig`vZo`Rm;+5&(AYzJ^Ae=h2X z@Re%vHwZU>|f0NI&%$*4eJweC5OROQrpPMA@*w|o z()A==l}(@bv^&>H1Ob3C=<^|hob?0+xJ?QQ3-ueQC}zy&JQNib!OqSO@-=>XzxlSF zAZ^U*1l6EEmg3r};_HY>&Jo_{dOPEFTWPmt=U&F#+0(O59^UIlHbNX+eF8UzyDR*T z(=5X$VF3!gm@RooS-&iiUYGG^`hMR(07zr_xP`d!^BH?uD>Phl8Rdifx3Af^Zr`Ku ztL+~HkVeL#bJ)7;`=>;{KNRvjmc}1}c58Sr#Treq=4{xo!ATy|c>iRSp4`dzMMVd@ zL8?uwXDY}Wqgh4mH`|$BTXpUIu6A1-cSq%hJw;@^Zr8TP=GMh*p(m(tN7@!^D~sl$ zz^tf4II4|};+irE$Fnm4NTc5%p{PRA`%}Zk`CE5?#h3|xcyQsS#iONZ z6H(@^i9td!$z~bZiJLTax$o>r(p}3o@< zyD7%(>ZYvy=6$U3e!F{Z`uSaYy`xQyl?b{}eg|G3&fz*`QH@mDUn)1%#5u`0m$%D} z?;tZ0u(mWeMV0QtzjgN!lT*pNRj;6510Wwx?Yi_=tYw|J#7@(Xe7ifDzXuK;JB;QO z#bg~K$cgm$@{QiL_3yr}y&~wuv=P=#O&Tj=Sr)aCUlYmZMcw?)T?c%0rUe1cS+o!qs_ zQ6Gp)-{)V!;=q}llyK3|^WeLKyjf%y;xHku;9(vM!j|~<7w1c*Mk-;P{T&yG) z@C-8E?QPynNQ<8f01D`2qexcVEIOU?y}MG)TAE6&VT5`rK8s(4PE;uQ92LTXUQ<>^ ztyQ@=@kRdh@ebUG^Z6NWWIL;_IGJ2ST>$t!$m$qvtj0Qmw8moN6GUV^!QKNK zHBXCtUH8)RY9++gH_TUV4^=-j$t}dD3qsN7GclJ^Zc&(j6&a_!$jCf}%c5ey`pm~1)@{yI3 zTdWyB+*X{JFw#z;PwRr5evb2!ueWF;v`B0HoUu4-(~aL=z;OXUUEtG`_$)Oxw6FKg zEzY`CyKaSBK3xt#8gA|r_|Kehn_HYVBMpEwbn9-fI*!u*eTA1ef8Mkl1=!jV4oYwWYM}i`A>_F4nhmlCIC6WLa zY%;4&@AlnaG11ejl61Jev21|r*m+?Kru3;1tFDl}#!OzUp6c>go4{C|^erwpG*&h6bspUPJag}oOkN2912Y3I?(eRc@U9>z#HPBHC?nps7H5!zP``90!Q1n80jo+B3TWXp!8Pe zwuKuLLI6l3Gv@+QH*Y}2wPLPQ1^EZhT#+Ed8q8Wo z1pTmIBxv14-{l&QVKxAyQF#8Q@NeJwWdKk>?cpiJLkJr+aZ!Me+Cfp!?FWSRf^j2k z73BRR{WSKaMkJ>1Nbx5dan5hg^_}O{Tj6u%iV%#QGz0Q@j{R^Ik)Z*+(YvY2ziBG)?AmJa|JV%4UT$k`hcOg5r9R?5>?o~JzK zJCrj&{i#hG>N7!B4kNX(%igb%kDj0fOQThC-8mtfap82PNRXr1D>lbgg)dYTQ(kbx z`Ee5kXG~Bh+BHQBf|kJEy6(ga%WfhvdQNDuOfQoe377l#ht&DrMGeIsI5C<&ai zWG$|hop2@@q5YDa)_-A?B02W;#fH!%k`daQLEItaJJ8Yf1L%8x;kg?)k)00P-lH+w z)5$QNV6r2$YtnV(4o=0^3{kmaXn*Dm0F*fU(@o)yVVjk|ln8ea6BMy%vZAhW9|wvA z8RoDkVoMEz1d>|5(k0Nw>22ZT){V<3$^C-cN+|~hKt2)){+l-?3m@-$c?-dlzQ)q- zZ)j%n^gerV{|+t}9m1_&&Ly!9$rtG4XX|WQ8`xYzGC~U@nYh~g(z9)bdAl#xH)xd5a=@|qql z|FzEil{P5(@gy!4ek05i$>`E^G~{;pnf6ftpLh$h#W?^#4UkPfa;;?bsIe&kz!+40 zI|6`F2n020)-r`pFaZ38F!S-lJM-o&inOw|66=GMeP@xQU5ghQH{~5Uh~TMTd;I9` z>YhVB`e^EVj*S7JF39ZgNf}A-0DwOcTT63ydN$I3b?yBQtUI*_fae~kPvzoD$zjX3 zoqBe#>12im4WzZ=f^4+u=!lA|#r%1`WB0-6*3BL#at`47#ebPpR|D1b)3BjT34nYY z%Ds%d?5$|{LgOIaRO{{oC&RK`O91$fqwM0(C_TALcozu*fWHb%%q&p-q{_8*2Zsi^ zh1ZCnr^UYa;4vQEtHk{~zi>wwMC5o{S=$P0X681y`SXwFH?Ewn{x-MOZynmc)JT5v zuHLwh;tLfxRrr%|k370}GofLl7thg>ACWWY&msqaVu&ry+`7+Ss>NL^%T1|z{IGMA zW-SKl=V-^{(f!Kf^#3(|T2W47d(%JVCI4JgRrT1pNz>+ietmFToNv^`gzC@&O-)+i zPQ~RwK8%C_vf%;%e>NyTp~dM5;!C|N0Q^6|CEb7Bw=Vz~$1#FA;Z*?mKSC)Hl-20s t8QyHj(g6VK0RYbl8UjE)0O0w=e*@m04r>stuEhWV002ovPDHLkV1hl;dM*F} diff --git a/doc/third_party/Pluma/html/dynsections.js b/doc/third_party/Pluma/html/dynsections.js deleted file mode 100644 index 2f15470..0000000 --- a/doc/third_party/Pluma/html/dynsections.js +++ /dev/null @@ -1,104 +0,0 @@ -function toggleVisibility(linkObj) -{ - var base = $(linkObj).attr('id'); - var summary = $('#'+base+'-summary'); - var content = $('#'+base+'-content'); - var trigger = $('#'+base+'-trigger'); - var src=$(trigger).attr('src'); - if (content.is(':visible')===true) { - content.hide(); - summary.show(); - $(linkObj).addClass('closed').removeClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-8)+'closed.png'); - } else { - content.show(); - summary.hide(); - $(linkObj).removeClass('closed').addClass('opened'); - $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); - } - return false; -} - -function updateStripes() -{ - $('table.directory tr'). - removeClass('even').filter(':visible:even').addClass('even'); -} -function toggleLevel(level) -{ - $('table.directory tr').each(function(){ - var l = this.id.split('_').length-1; - var i = $('#img'+this.id.substring(3)); - var a = $('#arr'+this.id.substring(3)); - if (l - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
File List
-
-
-
Here is a list of all documented files with brief descriptions:
- - - - - - - - - - - - - - - - -
o*Config.hpp
o*Connector.hpp
o*Dir.cpp
o*Dir.hpp
o*DLibrary.cpp
o*DLibrary.hpp
o*Doxygen.hpp
o*Host.cpp
o*Host.hpp
o*PluginManager.cpp
o*PluginManager.hpp
o*Pluma.hpp
o*Pluma.inl
o*Provider.cpp
\*Provider.hpp
-
-
- - - - diff --git a/doc/third_party/Pluma/html/ftv2blank.png b/doc/third_party/Pluma/html/ftv2blank.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznU=ZVAV_;x7xk{#nfq_BR)5S5Qg7NL$jSLJ7 o42L)T2FVdQ&MBb@0Ppk@y8r+H diff --git a/doc/third_party/Pluma/html/ftv2cl.png b/doc/third_party/Pluma/html/ftv2cl.png deleted file mode 100644 index 132f6577bf7f085344904602815a260d29f55d9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 453 zcmV;$0XqJPP)VBF;ev;toEj8_OB0EQg5eYilIj#JZG_m^33l3^k4mtzx!TVD?g)Y$ zrvwRDSqT!wLIM$dWCIa$vtxE|mzbTzu-y&$FvF6WA2a{Wr1g}`WdPT-0JzEZ0IxAv z-Z+ejZc&H;I5-pb_SUB}04j0^V)3t{`z<7asDl2Tw3w3sP%)0^8$bhEg)IOTBcRXv zFfq~3&gvJ$F-U7mpBW8z1GY~HK&7h4^YI~Orv~wLnC0PP_dAkv;nzX{9Q|8Gv=2ca z@v)c9T;D#h`TZ2X&&$ff2wedmot995de~-s3I)yauahg;7qn*?1n?F$e+PwP37}~; z1NKUk7reVK^7A;$QRW7qAx40HHUZ<|k3U%nz(Ec`#i+q9K!dgcROAlCS?`L= v>#=f?wF5ZND!1uAfQsk;KN^4&*8~0npJiJ%2dj9(00000NkvXXu0mjfWVFf_ diff --git a/doc/third_party/Pluma/html/ftv2doc.png b/doc/third_party/Pluma/html/ftv2doc.png deleted file mode 100644 index 17edabff95f7b8da13c9516a04efe05493c29501..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t diff --git a/doc/third_party/Pluma/html/ftv2folderclosed.png b/doc/third_party/Pluma/html/ftv2folderclosed.png deleted file mode 100644 index bb8ab35edce8e97554e360005ee9fc5bffb36e66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 616 zcmV-u0+;=XP)a9#ETzayK)T~Jw&MMH>OIr#&;dC}is*2Mqdf&akCc=O@`qC+4i z5Iu3w#1M@KqXCz8TIZd1wli&kkl2HVcAiZ8PUn5z_kG@-y;?yK06=cA0U%H0PH+kU zl6dp}OR(|r8-RG+YLu`zbI}5TlOU6ToR41{9=uz^?dGTNL;wIMf|V3`d1Wj3y!#6` zBLZ?xpKR~^2x}?~zA(_NUu3IaDB$tKma*XUdOZN~c=dLt_h_k!dbxm_*ibDM zlFX`g{k$X}yIe%$N)cn1LNu=q9_CS)*>A zsX_mM4L@`(cSNQKMFc$RtYbx{79#j-J7hk*>*+ZZhM4Hw?I?rsXCi#mRWJ=-0LGV5a-WR0Qgt<|Nqf)C-@80`5gIz45^_20000IqP)X=#(TiCT&PiIIVc55T}TU}EUh*{q$|`3@{d>{Tc9Bo>e= zfmF3!f>fbI9#GoEHh0f`i5)wkLpva0ztf%HpZneK?w-7AK@b4Itw{y|Zd3k!fH?q2 zlhckHd_V2M_X7+)U&_Xcfvtw60l;--DgZmLSw-Y?S>)zIqMyJ1#FwLU*%bl38ok+! zh78H87n`ZTS;uhzAR$M`zZ`bVhq=+%u9^$5jDplgxd44}9;IRqUH1YHH|@6oFe%z( zo4)_>E$F&^P-f(#)>(TrnbE>Pefs9~@iN=|)Rz|V`sGfHNrJ)0gJb8xx+SBmRf@1l zvuzt=vGfI)<-F9!o&3l?>9~0QbUDT(wFdnQPv%xdD)m*g%!20>Bc9iYmGAp<9YAa( z0QgYgTWqf1qN++Gqp z8@AYPTB3E|6s=WLG?xw0tm|U!o=&zd+H0oRYE;Dbx+Na9s^STqX|Gnq%H8s(nGDGJ j8vwW|`Ts`)fSK|Kx=IK@RG@g200000NkvXXu0mjfauFEA diff --git a/doc/third_party/Pluma/html/ftv2lastnode.png b/doc/third_party/Pluma/html/ftv2lastnode.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznU=ZVAV_;x7xk{#nfq_BR)5S5Qg7NL$jSLJ7 o42L)T2FVdQ&MBb@0Ppk@y8r+H diff --git a/doc/third_party/Pluma/html/ftv2link.png b/doc/third_party/Pluma/html/ftv2link.png deleted file mode 100644 index 17edabff95f7b8da13c9516a04efe05493c29501..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 746 zcmV7=@pnbNXRFEm&G8P!&WHG=d)>K?YZ1bzou)2{$)) zumDct!>4SyxL;zgaG>wy`^Hv*+}0kUfCrz~BCOViSb$_*&;{TGGn2^x9K*!Sf0=lV zpP=7O;GA0*Jm*tTYj$IoXvimpnV4S1Z5f$p*f$Db2iq2zrVGQUz~yq`ahn7ck(|CE z7Gz;%OP~J6)tEZWDzjhL9h2hdfoU2)Nd%T<5Kt;Y0XLt&<@6pQx!nw*5`@bq#?l*?3z{Hlzoc=Pr>oB5(9i6~_&-}A(4{Q$>c>%rV&E|a(r&;?i5cQB=} zYSDU5nXG)NS4HEs0it2AHe2>shCyr7`6@4*6{r@8fXRbTA?=IFVWAQJL&H5H{)DpM#{W(GL+Idzf^)uRV@oB8u$ z8v{MfJbTiiRg4bza<41NAzrl{=3fl_D+$t+^!xlQ8S}{UtY`e z;;&9UhyZqQRN%2pot{*Ei0*4~hSF_3AH2@fKU!$NSflS>{@tZpDT4`M2WRTTVH+D? z)GFlEGGHe?koB}i|1w45!BF}N_q&^HJ&-tyR{(afC6H7|aml|tBBbv}55C5DNP8p3 z)~jLEO4Z&2hZmP^i-e%(@d!(E|KRafiU8Q5u(wU((j8un3OR*Hvj+t diff --git a/doc/third_party/Pluma/html/ftv2mlastnode.png b/doc/third_party/Pluma/html/ftv2mlastnode.png deleted file mode 100644 index 0b63f6d38c4b9ec907b820192ebe9724ed6eca22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 diff --git a/doc/third_party/Pluma/html/ftv2mnode.png b/doc/third_party/Pluma/html/ftv2mnode.png deleted file mode 100644 index 0b63f6d38c4b9ec907b820192ebe9724ed6eca22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 diff --git a/doc/third_party/Pluma/html/ftv2mo.png b/doc/third_party/Pluma/html/ftv2mo.png deleted file mode 100644 index 4bfb80f76e65815989a9350ad79d8ce45380e2b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 403 zcmV;E0c`$>P)${!fXv7NWJ%@%u4(KapRY>T6_x;E zxE7kt!}Tiw8@d9Sd`rTGum>z#Q14vIm`wm1#-byD1muMi02@YNO5LRF0o!Y{`a!Ya z{^&p0Su|s705&2QxmqdexG+-zNKL3f@8gTQSJrKByfo+oNJ^-{|Mn||Q5SDwjQVsS zr1}7o5-QMs>gYIMD>GRw@$lT`z4r-_m{5U#cR{urD_)TOeY)(UD|qZ^&y`IVijqk~ xs(9-kWFr7E^!lgi8GsFK5kOY_{Xbgf0^etEU%fLevs?fG002ovPDHLkV1nB&vX1}& diff --git a/doc/third_party/Pluma/html/ftv2node.png b/doc/third_party/Pluma/html/ftv2node.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznU=ZVAV_;x7xk{#nfq_BR)5S5Qg7NL$jSLJ7 o42L)T2FVdQ&MBb@0Ppk@y8r+H diff --git a/doc/third_party/Pluma/html/ftv2ns.png b/doc/third_party/Pluma/html/ftv2ns.png deleted file mode 100644 index 72e3d71c2892d6f00e259facebc88b45f6db2e35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 388 zcmV-~0ek+5P)f+++#cT|!CkD&4pnIkeMEUEM*>`*9>+Juji$!h-mW%M^8s9957{3nvbrz^&=u<~TAUrFROkmt%^F~Ez+-c53Lv%iH3d38!Rv?K zrb&MYAhp;Gf<}wS;9ZZq2@;!uYG;=Z>~GKE^{HD4keu}lnyqhc>kWX^tQn|warJ~h zT+rtMkdz6aHoN%z(o|&wpu@@OpJnF_z{PA)6(FHw02iHslz^(N{4*+K9)QJHR87wT iTyp>aXaF{u2lxRou|^4tux6eB0000^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K diff --git a/doc/third_party/Pluma/html/ftv2pnode.png b/doc/third_party/Pluma/html/ftv2pnode.png deleted file mode 100644 index c6ee22f937a07d1dbfc27c669d11f8ed13e2f152..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229 zcmV^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K diff --git a/doc/third_party/Pluma/html/ftv2splitbar.png b/doc/third_party/Pluma/html/ftv2splitbar.png deleted file mode 100644 index fe895f2c58179b471a22d8320b39a4bd7312ec8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 314 zcmeAS@N?(olHy`uVBq!ia0y~yU|?flU}4~3VqjqK-LYSgfq{|H)5S5Qg7NL$g3+rcW~p3*2k<8ET5+kt+??7VY)%8z5|0uNDQ@?BH>==GIK88=8LINZs-Am7NcFtb?^;v({ zq8ITc`sa7geZ2VM+sMGMuOD7LdHeYLmg_$w*WCKQb@{T)vd`K3;@>{~dwa2`g9;hw cuXA+R8{0q8EosLX7#J8lUHx3vIVCg!02F6;9RL6T diff --git a/doc/third_party/Pluma/html/ftv2vertline.png b/doc/third_party/Pluma/html/ftv2vertline.png deleted file mode 100644 index 63c605bb4c3d941c921a4b6cfa74951e946bcb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86 zcmeAS@N?(olHy`uVBq!ia0y~yU=UznU=ZVAV_;x7xk{#nfq_BR)5S5Qg7NL$jSLJ7 o42L)T2FVdQ&MBb@0Ppk@y8r+H diff --git a/doc/third_party/Pluma/html/functions.htm b/doc/third_party/Pluma/html/functions.htm deleted file mode 100644 index cdc44a7..0000000 --- a/doc/third_party/Pluma/html/functions.htm +++ /dev/null @@ -1,105 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
Here is a list of all documented class members with links to the class documentation for each member:
-
- - - - diff --git a/doc/third_party/Pluma/html/functions_func.htm b/doc/third_party/Pluma/html/functions_func.htm deleted file mode 100644 index 64622da..0000000 --- a/doc/third_party/Pluma/html/functions_func.htm +++ /dev/null @@ -1,105 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - - -
-
- - - - diff --git a/doc/third_party/Pluma/html/hierarchy.htm b/doc/third_party/Pluma/html/hierarchy.htm deleted file mode 100644 index 297a965..0000000 --- a/doc/third_party/Pluma/html/hierarchy.htm +++ /dev/null @@ -1,51 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - - -
-
-
Class Hierarchy
-
-
-
This inheritance list is sorted roughly, but not completely, alphabetically:
-
[detail level 12]
- - - - - -
oCpluma::DLibraryManages a Dynamic Linking Library
oCpluma::HostManages providers
oCpluma::PluginManagerManages loaded plugins
|\Cpluma::PlumaPluma plugins management
\Cpluma::ProviderInterface to provide applications with objects from plugins
-
-
- - - - diff --git a/doc/third_party/Pluma/html/index.htm b/doc/third_party/Pluma/html/index.htm deleted file mode 100644 index df4076e..0000000 --- a/doc/third_party/Pluma/html/index.htm +++ /dev/null @@ -1,112 +0,0 @@ - - - - Pluma - Plug-in Management Framework - - - - - - - - - -
-
-
Pluma Documentation
-
-
-

-Welcome

-

Welcome to Pluma documentation. Here you will find a detailed view of all Pluma classes.
- If you are looking for support, you can visit the official website at http://pluma-framework.sourceforge.net/.
-
-

-

CSS based on SFML1.6 documentation
-

-

-Short Example

-

A short example to demonstrate Pluma usage:
- A host application define a Device interface. A certain plugin defines a Keyboard, witch is a Device. The host will use DeviceProviders to create objects of type Device. The plugin will provide host specifically with a KeyboardProvider.
-

-

Device hpp (shared):

-
#include <Pluma/Pluma.hpp>
-
class Device{
-
public:
-
virtual std::string getDescription() const = 0;
-
};
-
// create DevicedProvider class
-
PLUMA_PROVIDER_HEADER(Device);
-

Device cpp (shared):

-
#include "Device.hpp"
-
generate DevicedProvider with version 6, and compatible with at least v.3
-
PLUMA_PROVIDER_SOURCE(Device, 6, 3);
-


- Keyboard code on the plugin side:

-
#include <Pluma/Pluma.hpp>
-
#include "Device.hpp"
-
-
class Keyboard: public Device{
-
public:
-
std::string getDescription() const{
-
return "keyboard";
-
}
-
};
-
-
// create KeyboardProvider, it implements DeviceProvider
-
PLUMA_INHERIT_PROVIDER(Keyboard, Device);
-

plugin connector:

-
#include <Pluma/Connector.hpp>
-
#include "Keyboard.hpp"
-
-
PLUMA_CONNECTOR
-
bool connect(pluma::Host& host){
-
// add a keyboard provider to host
-
host.add( new KeyboardProvider() );
-
return true;
-
}
-

Host application code:

-
#include <Pluma/Pluma.hpp>
-
-
#include "Device.hpp"
-
#include <iostream>
-
#include <vector>
-
-
int main(){
-
-
pluma::Pluma plugins;
-
// Tell plugins manager to accept providers of the type DeviceProvider
-
plugins.acceptProviderType<DeviceProvider>();
-
// Load library "standard_devices" from folder "plugins"
-
plugins.load("plugins", "standard_devices");
-
-
// Get device providers into a vector
-
std::vector<DeviceProvider*> providers;
-
plugins.getProviders(providers);
-
-
// create a Device from the first provider
-
if (!providers.empty()){
-
Device* myDevice = providers.first()->create();
-
// do something with myDevice
-
std::cout << device->getDescription() << std::endl;
-
// and delete it in the end
-
delete myDevice;
-
}
-
return 0;
-
}
-
- - - - diff --git a/doc/third_party/Pluma/html/logo.png b/doc/third_party/Pluma/html/logo.png deleted file mode 100644 index f3d74cd02e5f5989913d57000c2f12d4c074e185..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32867 zcmV(yKKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z004E4NkliAOa#t9@3ey}cVD_?m(0;i^5v7O zfj79C-M;64?4a?~3A)1x%j>YR5-`Ilqc@Jy-qB$36N{svAD#`I0PehW>n?%tlKk7H z0lY!1Ja+3VHj_MVgcUEWdP6@Lycc|72qKJKGtBtqLo9r9pUMncg_DHIl#U9a5n*FXGq#M>ElY1b z#ksegqIaT$Ye&r8GRBUV?_|?6CTU+e#N5Z{1*LK6cK+9&ESKcVFJBA1dH9BQyy<&) zu<9)Rro%KXwZt*rN?7^xlN|oF`|x=R-Hvo44Bfzt|XL>*0 zJ=5C`+y#8^B>-Lm;U)Rv<-Y^BHm+fp_stNlZ;KwTS?P93`+khPvXa~{Y034%C zh%bB@$MYH{3Y-Ym!{t(`AP)gIPjB=owdt0 zKYxV50a2xQ~!0&w-#x@E(FKS1o z{iHGas`#eE#!z!Yvf?@LJ4dO2|39mR;F4UDuQ(8n0Xs$>-R6oP+f6nf7`e91fnPbi zH($JmBXZ4>PTz=kO0e{njb#-wi}oobM`wZ zX=2~Rm&Q(+0KVNsCT=}$gd!4r(_&+x(J=Ts*O-0J48R9~|8;5FU6QY45N-e{R9T!a z=p_zup7{DPE_=gGB@<<;P7sT?mTrKeP>OZMujZhjqF8|>HngUiT=^R}629jXocpKg zucu5E{PLGDu15hkk3D__vmv3M7))J=Bc+uXj{fgs^cV90{4ub4Y1&cOie8dS@)ZTbt0>tg zF9G(~Hm5Wm)grobh;E@|nI{;FXux=|qKFtI2pRydNTJ|?5D*OrAkIL|;KkC(0?~$q z9k1NU-9LNx6!7c74*(~>z%gC{JZtExCef~xeq^BTNFzrr51f3*H2tN#5BxUeNG{1G z`HBGHQ-P-gUjytJxps*5V@9am&?f9kSy}UB-cShO1Bd}15LK*tqzIT?u^x;M7y%;z z1E7i&pg9;Hp%T;W8AhMCiA|qe;Ox83y#&}unQplE^NceBUTh+ns9)1WM;#%xxHzIY z6w&*adFDPe5AaUlLzkx8CHYDK;gc$@_qD*p*bT!>JZA&-$Bd#IW7fK!)wP^n>CB;KY3Opy>oRD78pfDEGOo(Ggyy`jo_cMdU{Orc67){yw+C7-WaNlnqxtTJO`8B}u zLyY^mz}2-qHSFdZSrTL8hyj3{B#&eej#j|?9%E&9ZK}r3|F(zP z4I}gu!%~3msweYG?v+9V!IY&R&O$AMCPK7Uklnt-><8vq`rI<1;|ZB&8nj2*$?SOb zI6}$Cyc_6iKRl^-s`tv7x11W0$(ZEoQTl~t^LOu{Sj{>1C#RmOL0=2}%!7>G0^b_7 zoon9MCYMSJMusF;WV}0cL^Iz-K6Pa<^50dnkDaFx5TM ze_8)r7r&{C9jjrCvgH+9nfu@ZtB2QL1pFNTn&EOK@VI1iLb|U-*F{L|NSr}tdz^gR zDS(dwpS(29F3BSegjWMU0=zUCi_L~-Y-GdNZpCk|GryM8?<=_xd{8v^n5;nZ0#(JM zXk>^JLoGJMvwhCK`4qk%4pOET{)Ms~#1|u(21R@zU(N8tF{|r=;q5gVd+MwnUcU<1 zLP-?AP+lOG`p~1>Ugqy^}pg zzIz*q5fW=?H67C*UBDNb{Tn9xc3@L78H2S13~0$ORg|K0KCO2#%jKECm5qH37)#N5 zjEgO4EUdhDj_!0%D|7hlr73nv9tj|P3GfTR?#<7eV&hAxH4T`V9&>L!#o2ew;=8_6`FYnjE^myx#NuKhtvgo# zd6xccAIkReU#i>y)Z*<&woR#-X zbNmmFldl#T@Hxur^QQw(uV3CIN+Vq2NK?zX+m^`J3V^@;62~_V+?sAkFe5SESu}AN zAdU_B;dSz*eBj$%7#Y18*fD%#8%-m$7UN<=y?;7=)YdOvMbBaQt{ zq!!^)i_Z4w9$AMn_jkvaIL2#%o9mZ1u@fnovq;@xMX0wdt9P!_pUVfDb^t;PJQg8M z_czg+!_*xv0<)O0@R50f>LJSF;!AQ#{?kA>0{pBX+oryL8)o+qs~zaoEk1G>fy64U zy3jJ7`9C?v@jp63zUJ3}-=Iu23^{jt4LrTRvxc2W(7MAWj(XFv`VVL5oajK= zwqp6x)Vd`9nIOCz_?nR$hiP0t!dge^rUoBbj1gk1v{IpMJjZ|jPR{<#S+q1ge~gmo zeDS$9*Dr5ih9XQYB90BScdXEx%b=u$eJPyGeZWf^dm1ErTXZncj4-0qn}+V4ORRi) zd7uR^tftrx>>j$VjSMAd5@8%9s!V@mo_xJnuQd22xg=k(n16?JJ{oAWA2UK0l&tRw z)*z7~5~Ud{Z5ufDvv+c)1mK@haxmZdAPdA3Oe{9uUPGD@HWpaUSifrp4V31m}cWtPI6)>}T%e>^sju8ODD#58kqH7x4JT z?mBKFDd}plkR4iO_0AQ5Pw=I&Q62-lytchY^X3uO0?>*OqtxpLJ-W`!-_1~g>Eqnr z?qUjfTJy37ZevP_EH*ZzHACm%3af|Lpllko_W#J-NvemTtES~b?Hb82FA6{VP&^o{yfuk23 zy9L;r?yO@cA~d#$6-=j~d)G3mbSm@pD`5wv3Cd#RZC~O-`}AtTIRVU9zWFy&ZvXwI z$PncYR_~*1K{-QdAwB-z@g6+3vUE;Y*E|FK6(telKXiMDFSjOC;5Og$nw{xNx;@2& z0%Me6ANYP9w>2>lQ*e0upsMaMrAcnxK)_{(YL ze<$!uHZ|?h8`{{KCGCV-!%9iqHQC7|T)|arzKVkwi2Y^#cA79wI>6#&2U9jq@ zwG8X;pQl$w5dZh*xv68olWW^j;w>qprRf*ud(3}e4nBW%#DmFB;QL(5xyhGorl(M} zB1nbE1e&q1^sX7!OP0)^Qzq#L(g2>GZc0eD*YVCGks*$R;&g}QgR6t6==2u=fFHSN zh5sle#qCdd_yXdKWj|#rjwe;)gEC$7my`{q9&ADQD&P;(iDbj3XHT;D>E$g;cdq<8 zC8_=$)#Ks7_;bLI4_`gR-XFM(u_uioPMH750%zZLhBNOx_kyD1UqDGw{K+o>*rUMj zn@FC$>A4%&`b}FIxn-2l@tk}6Sq}Zy(Z>4m&KoJC<-c12g{ZJ z(PnHbLe~QG@0;WJ8;{%hPcHr}C6VLDs%yWRl3n%D>K-k9IRW$Uu|MGwFqSXokFRg9 z5lzOpc0_YiO7{~B%zt2(YUO*l33n~;|rCM zYPEmj=9f(oT{lc8vV^w7#X>Vt(z!kdfAn5_KYSYaK_18#-3$C=IR+N=hkDaPB{)7p}u5D8+<*Xm?Jgz#& z$9d?!I%Aai;1_QEs!4YK&}HNsQx<0n)_PFCvdzd1Beb{G$QSdm{#^E~>RkU8hSYBY zKRR@IBii*NyQ$qe&is*TStkn9ztpn zi3lt2oM!&xi=9f79{3{7kJn5*c}#}CdK2rBA#cW*x{#W{*s$aH&m3aquGO5f#_@d@ z9sd#&$@ANfAI4oi1j8v&-IDY?=l=K@-7~#AfZur-^JNNnOVoCoFaL?XOulRj^&3WL zT|3O?Cy!I#QfL07iyJj)Ot~S<=ab*EiFx{tS8ie3_w1nd=niV3GpQjVEH#%j#%kF%d|w;Osl6seGQ> zzKF3r8ThgKwwjDQe6Pzh^gl|JyDq^J!mo%U|l72ohk24Sci^rQ3tw17Xgj_G8KUeRLs>LCywPg$A%U~&U+ zU9vqT+EqiH!59MzIcsIr#HTMZvmQ>a0Di}%W_-iTHltfoIu=6RA|}vmIO?mOQ*Szn z?}rZXOAitjPl3loBN6eA8o?RF3RVLvAD>6Pdf+1uGluJcm)ABWw4XN4(rRF}t8@zJ z7fQb7x#u?y6S9!=`FXGr@Jd&=>G<=SbNdBm@9S)0Htv1x9$MFq;F>Wq zpL6o(?_u`OPtm(=p5pWxML*ClV67W)BN1XSRnX;P`4-?ct;-s+^Luv^8WFA@5$8(p z12fG1;z7FaK1-PIk!MQB3#;o&yyg6c#p7S(TzoO`tF@`5zWoPxlaJTvV9>-8MbLDC zxXZ%iJ^7v5Z+l#B*Ye$ zJ~#&@JLY3w1OVS^oLsf}o3@ZVW`vajiiSg+Qi~14b<5e`Im*%I1Cx91293ZM$=KpDibN@I^6;XWC=lM?0 z0B#w&u8C}`(dj8!tK3^7k@ETU+s?3jU{!%%t2FEH#$!>k<5k~x1?zi}_ipI%xAx<(jhEhDUD zggB+B8ZXO(hew|P{AxTF)pxyi7j8=(+m6u1oKt^rl<9ZPl>SJ=65rTH>j_2d$~GtA zOUnE_9{8PjBuaLC-)`95qK`#WAxeaH+fsaVfn&dNgtbHKTKUn*%=>4j5F!+&zI`Vv zOBvoctTlwfv-#RlMjtiGnfILCU!{2tJrXtHK;8hnWBD^Hoc^nGs8O=HKB~$?gs>aH zE%9VTw4NO;2yN8oT<(oB!o-jbvZ>~qaoDaTFw=&^gIPt_Ww!Ul&Za6|#Gw%MW zyO{gfLccQG?+`$IfV?1xaz9q&!GdGIY+^IM=X-b1xNeAeEGG7WBR_X=0Kj(unT-VN z1KQ1@0`-@G!Og%MT*GeM`l@Z1y+d@dXu}c5j?v)=`ScP;e(GM<4y~^MuLYi81<-y5 zWzG#n#Cw|b)(iSQrSG8#N>M0lC)NSh`7#u4|3?({{(u&`X$X3<&eZ;BSZhbb=K}(2l!M4L_UxC_hx}Bw!LyI&9BE3 za%9dy-C=>&aKy?x&a!gH3c$N5DQ}-Ix%~X$>xVEq8g#A2H_H5JWT2TEX8zz5*>c{e zqyT;uuy^~nY+>T*qZBJSCx7=i>vyeEyS#zbfcgSsB3$gqr@LhH8P$SvEAW%GsZ@4< z_fDb>3G_S%e&HVGKC(ciW#10G(9{fKgh0vAP(n%4DA(8l66;mK>*g&l-N?vOCot^@ zS9tFGg?pKP-z=5;@&@23qFU~s6%UT}O9_`%_u+Grva0aU>vnAos>?+V>h9Vqw2Tz{ncgcr&| z;1#~>KXC3{Gu_@yHUoSgekEX?QY>VH`pLV2 zA9gj{-u+!WXkO7GiiBftJi@8JIZGA2{rM_*vnd*jAW~Emm4J~z=zBsLTOCmNz7=@Y z_|3yieZv;)P)rn*lfQe6Q-67$J@o^?xCpUr+H%_v3u+W2P%NI$nk;?+bMCdkONMVA zVfY0b>3AX39WF7nQbYL65_kW=-E`0NmaCxIg#g?D{D`ZYcJqcdS}%9>BC=S4THP`G z{_~Bz-uXyP)<2kh68P%Mr1B4u)V>0EQf(?F-qj!^5yo25#4!J%MO0a@R^PZvV{ESM zajEinF9vRoN22<|NKES$Y<84avHL{KKGqG#8%ZyCmJua#=HUY2szha8JAfIVu4o6GWW+P$;wUu|5OnT=0oo3&-Xa-mNT4t$1IflFN%rn zsIh`IWfyZ73He-~Y%w1M#vV2K^l>&mdy=SbIrq0`Ir^rPgRy>VWi>PaE4Bn67Eq5w z5#2LAE+7wF2mEY(TPoXLwT);~4QGXOZ#~VCKRiLTV7$6YW$YIxCK`=V1!99SilAg? z&KoM9&-{BX@Wb&$%*K~*p&L7jT7*drjl>Yob-C*&?xr`>Uje?mB4%7DHv!KWe#{7N zN0W}TXx(8%iL8(snEB^vg4abJ$f|n8gAhuJ*2C4=Jr$T5zNt+}T}jwZh3@SuWas(= zzinTYaJ{NZaToziY>XRnG&e;tesj8R4x(#9*yq?M$Dd7d-I9`u3XaeeEt>J7WFd3Wr{Qlwz&uRDR;} z1tzAG)IcPtly1IAK*RYIV+;6o6UpedZ{9-dhGAT4S^MMy_x;vULZOE$0L~0pKoS`f zjYoJC9Eg+~{S-?X)%Tizn0qw@{Dg^Qbla=8Pz=Wuu|-o$8VSu1xc8?H&^gh~f&an3 z?gO+9_{Dh0+2+l|^*0#Y5!l#ZtwJx#RPU>8fZrLdMGiq^E<0u45ueulVsjQMx6C%yam6kF#=cT`SFg zVf1($z>b!|F07U|NuiJ_Rnq@QfG2Nw)&v`#zY$w=6sNl!_@9T!my0#vM=QVTeh>(l zVMlJIT4GC0xORATz{WcCFn-{F18$sr);RWxCcVf)JtA??ZVKmq<1q7|SfmOn{lSBr z3gM62u6tnQY(y2M%a5-xcmDK zuzs}LsV2wgi?Ut;OxAbR@M6mTGfs$Op>xj~zT>qr&n^}L#?q-6Hy$zl&UxhKVO(Nx z25JpU@3TuReQsrtmRNe2G295eqOq&S&=W`Lcp-}nzGkqZq>-g=;OKkj$k+Tb|GM|; zpI=~Z8Q_|zWwApJ#9(8KwT5CbqkpCk(3*PjCPp7OigAY1e|4Hue{*hdo;O}#whJ(6 zVpDE2XD#9^)>(?hY+%+N1fJd4UNbwtYX_ztVe-ITzi=Nb_pDJ_A#b~Q(Q_?}n~dmL z0b2%TtSJ3zk$4z$^ijYM)pyoR`So`~PocRAvg7R75r})<$)gKRh zcYRNd){{rdt@mP!rVb}%-yxarvUblhRXpQ^|J6YFG+?5A(+JXvp%xLPhVC89tlhH? zWna+~!1U6mS2mpZi*vLe)xsM~KUi{Osz+%SIV)HPX#^vqG5Wb>4*cjn0|5R|WwPBL zJ5L_XYIcA^A5aQ-HLx+=mO|_xwulkZhULs{%lJG%Sx$Aac;Mr`Guf7-uRBS!tww8G z4J^b~NCZ}ob_P97|DJ~@IscMP%;eZJC-9>&y&UqI0V_mes5c$ioolS!xk{Bk{q)0} zYZ$m99*eQ@eb(+;A)buc{EbtXnx%7Sjf1~+bdc};X&y*F6JVo_4a62i z5Ni+-{F=v?4Y;OkYMOh0XgA5W22ss$^7oH1^Zt1%Gw^j6jc-3tOSUBBMIf}wNVFl~ ztgw9N^1!8eFrr2sc#Uz=9)H0&VMAOMY8#qE1`e%qJBxfcE$+3nT+14F7;h?HhtX|B(fCe`W*hfW8`H{_S>oj^})V#nrulatbs&I zW>N&%J!^x6W$SBq6K}3zJe>H;Gt87b7XQgZ^)2siRFhPaVH??ECI zhKxmy@DmSp_zvK?t;-uEdm3d&HVcsimJh7bo6ofhUi4D7BUR=SyT{|{qIiM^6pvg$tqSC%b`w*zmvXxM zXFI+2w!~8j)Eyd?*G+1|($RJDl>(64Mr+sVaN}yuF29H2+GU(u{RpZ7;93zjC0kR> zP=urr)(NItuw0s=XL#tMQ=IN&_9aBt5<5dp46Ao8(_hHW z-=oj-J3rdB9Bw?J@DM6ZsPh?i$TIxG4J0C*c=PE2JLwPj*Cky8*#flVO)=7RC?%sL z_e$r`I_)Qo(R}PEMuhb{S2+0FhX=Xhhsw!53fSG)TgQtnyVykrCqh~?oc-hy>a|y; zsV??&zbP4y8GYI~nT?>85=DlF6K4PN9P7t>1BTDV{_+^`b0#)ZyI#G6Xj`4!K=0#o zWOuF6x@iInL>3YU-J>gX=lTN>u0Ntcs1yV;!h6Hd}wiubLU*5!Q zOz|~~i$Lf5EPmj;-}JeXGV%%>BY>~2rPAh!I?G=z8j1dFT%P-9kfY)evCM^kV9Y!X z!8$crv(ROO$a2M`8mi2gq#8>Gtg9BC*o_o*xAjr0`F&}$xdyc|_+Uh^s&o#oqpG>! zKDcxAwq{AD61*6sW^oo=&$IA}{9vZ6m=9Mfd<-1Qj7a)C_;2_O=JP=Fb36n0nzxMxHcQrbK3YEdTX1@wIK@$jl~<#3zF0)l6Sf;E&v0-1VQ zW>Q|nm^_n$r6JF{^K|g6HOB2T2=p4B^$^I~AR|@eQmSCkwN(n>2FjA14Ipt5Iure3 z{?V>wkX99Rhz-^m^0R&V(;2|06#uQq7T@x^*|m?p$Vy69tgw0bacmyG1(2I<%Mx#{ z5v(muQKN*}jPB_^Rc@@adHgyq-|<3>iJ&Z*`Z3_DsTXggc106yIKpC1@52kk<1tQ6 z$=XOPtY*xYxyDaEgpYM`^lx`O5kuQj1jP%45HM{+j308smfD5eij`exUZ)QIf0L#MW@`ZKqi%yQ;s1hu=5yMiHWDORWT9>@dau+kkI&LypmBPLKt`G!r6cXvD(t-#UT@U8iixapt1y{Q&TtqmLeD z+qZ1Tv}0^)nSSF5`lox;uWTWiVvXROA*|%ge|(P041HAB1ZI>1OPxCVS$p8( z{}kZSwVgGRoeg@4#abouu=>drLLRy;uKU0cH)RQ%F}PF-1^A+5_Oczg#ma7QI!vhn6n~!vx+_ss3|&Qg+mzgvEaKV)1`f_sRY|_ z6t-NIjf3KBM!t{%>;nCj`OYUJ;9KkQrcsbL=DssJT;CPWEPeP!Q!}_N3H_*y8d_le z(`A#Yk>;*X@0xlF?V%}Z(Kz>=d>4WIslcm89@S?2t2W^47LzM$@0i6edg@mVK>!yU zB9z`et7OZ$Rwh~o;9SDfpY&avp1zCQ?|i_5{bUmf>GqVO2zciRj*^NM3(aQ4`X?8e zdG8!m{_C$l4=d%CcrqoLOz2mdFcbkh5fN`nNSu(}zRZz7Ix$#q{>Q_xf;Irx*0$G> zro%@i2tkNyj>S(clPwog*4{tOV%fa;?<-o| zh4LKW=bO9h_OkEajoVa1Rhj;qGc3Mup4w$~(rqchD;d*8k_^$3!MJTGk`gmFm*?ZM-Amn_Z7dR z3S$=#j)H6hy)_V?E2vQzLUe;MY*Offo;5~SRCE&(_F2Q2sw`miT?!vX*kD8pM7JqC zDL^oWI|+Uc!j5=TinJqi&;Y~ zm4dXB%_%`ZY6j!Lp-h)rVYX45ymQ0o)#SQLKVQMwq*eId4@GSkZTgyx*vT3}l;Xf5 zi+?xG&@(4-b%#pH_axJSd35f=V17Ni0hrnd8Lk%WP4+A;vT< zg_h1#$OEgNEji;8H&4{B_<<|A=eG_p{lV#1QdWk1MU*lDiXp`@M8r5fPV7b8f}R3B24skT8ln>dD@ZsY z!nDAi0J~JQ5Mc)7oT3Yej*95Z5MB)Yc~E(aH9Bd8rw6zO(JQ^KI{-J4mO%$&Pz5zY z?@W(;-Lvx*TiE;Boh;n8Oz%v=Xnk^TqdxhQ0e^QMx>tx3lTIaN=qEOaC{AJdzzVT# zcP2-!YxlF|$BAQ66{A7F4|w9_Q^y&3;y6VlxIA$BcaCEsL;dmw|G z8T0X4ZHSSPNnY@R@1-#m^H1-8E1&x0d28~?wq}VprxadMXUi5OD3J)Qk(i}-oMWzx zhCWnU;DPyAp_%TkqphespD_>%tDl-Do9%PO|J=*guinVXx1AmM?_UF4*}kz&XgIVM zVQZE~%d!0S6LgNPQ*mWKeUZQYHWQnv?ccJM(OV}lsl%V^a^J5VB3~&wCX#x(Jtbs; zkd_r$MK3V_!D&Ws8so;--$Zj$oqJz@aNrxuSBxgS-!NTfBVTX(oc@l!oEaUtd4xQw zHe)d$&T!_frva0#bMSeG`H5Ew_1*-}zNf`C_X&Ck^d1#13-C-NtOFm^lKOR{!1a{n zGoP)>j4rFphF(z4A{;d^4>~GFzd?krLHIDpKUm}+Rr}BA^iJI>DfM_PE?0RmC_>&1 zbdGmv?rX5)+qY8mJa_!`L5wE7(dJbv*2+E=-J0b~YdBRm=0u~CdgZL(r+f6LbH*B* z8Efx)ZV}e6thr`%Z028FzgT%f>+%L$zG*8VwbX_kM}PG=>-Vmgo1^Zi6Y_z!E6t+`%fmTpbSEqH67+DWROT9Wmm zoZQMX@Vmq9jos%z|Fw*ckI?J(@I}s(pZrp~YdHrGeheRq=SOWvvb{z(fX0F(6}Pf( zNtSa?{?!?Zt}m*^p`_1j--#~*^Rws3v;Kwo#;2r{33e=@P(yH4-qFCyzbr8J^l?U? zK2GOUk3+wE9N^9hh+Bqk9)U&#^$2SrDLg0MGfUA6y^HdjLshi*+HK#knay9n71NBc z{elC(bT2ChRslX_YUUZqR3b&D1Qb<8mvd~*vEzrXAla01;xCUg_sKaZTU?%bLSSSvxGX1_e#>O`P<@ML!ddG90 z{c4i9L0;U?%IbDkx%uX=BT1V(fvcnO7`wUD^dYr~6JiHLP0Qjt&av>ZMJi^}0f3vI z_)K2*%2)F>FaK^@tX`cLza~f&$9fvr9nXN_6vyJzXH5)<8vn1^3B^Y&4@_h-e0+oGw+_J ziUjYrH7jmoOi?J_L*bP?4@`XTK5ADDv3huw``&OL`D(seF^L`-fte-#nHoC*gFZ;^ zS&&50>w%jLX|}>Yy(nj4&-nGDghol9DkziLbN}}&?dNP_;u#y+c+&)R}!B~s4hJ^!bnBcTk-Gg>( z=wBovWLXyte2rM*#^p_NFC~Mg;jk7Ob%QzAW#;YY(9%!(?fq9jwm&*H!L>I$hULWt zvOKVB?+q+`^c{nR`3YiarMsGFBc{L-tPoT&Dm0%oPGf^*@dLA*eCrt~>-RnYysCBW zP|5sB%RWSjg@sQnkS*mo@cS1Kw0{x!j|!?#Y71;IO0Lbs>b$Bon6)6*yWwHd6Nd91nrB&dOZ*e_t3kGo-gq>&BWtStN$cD-y=->bYi5#72?0Uk z2(cDt4Eb!11}Tih_o&M7iL)QwI=_6F(VK_a_%&0ISklCD?Da>O|M)V^+NAVYlypZK z(JT-&1iV7Ak}>s)E1CP)94Fs?is9BKc5K`Gk~lFphfw4iWTZY6ZCYGD9d$aZ8`7;Y z+9)ggP0ivWp%x3-r?tf16IWL=fWdp#Y3oD`KO zm{h3kZ;^Q=v>YZjBu=S2q4TjtmP#`DZ(eu9lTKWF)6=k4>2}tMYX)EBY~H$`$2TKB z`u@Ldc<*17PLy5Eb6;xJU@b<4s1=c>O0<%5&+Cq%C1>=Pfg8lojJBs}!y+|HoIrNp z3d`ko1ov?NR^`72{P&R?+g$d;d$1FAtToKPdzyQH`_Q1K^uGaDi;+fsSDhk*5S8p7 z1Bg>1r}Pi4aQZJ#LRlU1Cy%IPJwT7+C^?1%ePASd4E%Ex|5QWGt#j{Kms9oO8;4*d zCO4K`OxZ~*SE5}_I>FGLD{x}zI|%3cZ2a1t9Q*UbtRKE-xW&m{%End5y8&&8=v9a= z0dv4XRT)QgN9Btwp>hIrTnxJ^=KFk5&KP0L2xGvoS5}OKUN1klis(qZDa8Z92x>}R zjTNC*v#fn$f%$)#r|Gsa-nyz5Lbjs9vZ`+O+S>^lxrRfvD(?|P99fnRtYFkK+}hcn zTez=#==l3XyvdsF-?kGwStA*WSoz32NB;N(BaQ9d%&*021JUM~PN5ViVxV_;mC>)6 z!n7=NAD<(eF2ZAPzST5`hxP`aZ}$ZUeJFAz?HxaP&*a+rl9{-6oPyF9G-+9l-%Nxf ze|nPGCgFw~Z{099G5K9t)@w9|qUl<&J!>UKq~~H>z1ciBGkstw_uVH)n-c7XxQs|P z9o7l;2%_bTqi;S1FmvlOpL^%ND{d}URyyrMyhf2Ypod7O-|Mk)^L9jJD{xCPRU_Wo zpr=BJ?D;klktnUUWBLupS-xWp;E$?w#}6lyWtmur1W6513caK2ESDuxZ>DU4@vFf1 zkK8cCzMs5|cxMY^481#7xbvs)AzRE(P&S1=4t$4LNs}!pJ}BNoaDp{uHGNEA=>z9j zJK3R%xSoB)fv}_!{5IS8ek@ItY!EoQLXoF}Oa=N2Yuw$(WcA_4Y{f?oZ!O*$Lbb}% z^LWY#U=YE0A@hOU7`DG;CwKkg-KM8UHl=221oE?#oxVqa-3l87jteX(M5>G%p$4*4 zYCDZowT+OJ8dSOhGm5r>QBaCvF*6Ccc7*q!&Y)4rq>pX6+MjvP4E=?IEfY7YG08S0 zYy}oWu*>WH`Ph@kwW%Q#L5x8tAHEkbl1APB;&lfO{WZb%%8MjNfw*bq>BwZm0BWNBSFO8?9{r`~ZEC$;r@ZSttk!k9|fh~*j+ znCYyo-h1NM!66mhSiiDK9t$)qHWq5B5bj-L`7mj>T7S<*X^xlAuyYyW?SM& zRS}hdfzTdp%F^mlQ}~Rr8z;#{%3xYza8{{Bu>Rh8R`2O>%dJoGPkhGHUa~N=ve!i_ z#)yj|lN!gO2zMFFQc!PO?U8R-TAGdOds`IF;MF2YnVN_Uw1y)5fo0DAmKFU;D(G~F({DXR8Svvne3^IN`m%vAXMq#EjxBt91;jv^ z2+v0hwOXGuo4XvMwXcTT-lT8K#H<9U`4SgP6LrMq;*3aE1RCWk-L8JF8Z8V zHMnkp?kHo#GAnR0pu@nU5c(h|P!6f;MloTVmag4A%8bAm!bX&ySJuVQ6~U-#t((mz z(U>C|kI6#`LK7PzfqF9{yL*L&kIa#p4Mii_>H`{!s!@?KkhX@hFPB7CFs3T+G4!YV zP=IqOhfn;Y>lO>_`u1InJar=^j#z}le{__k&#tj=$J0sEp-p+Q?iyPYyeeKPbB-FY z;|>=qy#s43eP)f_J045BHMO+5(w!DZW@9$j({yrn?)cc;{7I?piD9^`PN7zIdTTZ; zGk-gcUspCyU6%K<++sqcA+*=l{1V`!*whh?fo^{~OO716cSuc;#&vCa2535LEF=a} zg~NYzidJj5*t7qNVYU8S8e>r&Y;n$euf~eAku(}nw1)Ga4L+p4@Ha*yF|~ayvZ8Fn zMCyo)kjBum%IUYAX6<;l-y9kF%_qG0x&5`J>Cq3p?L9l(SPV^Dnv6!t7J7qzJ-1V~ z%Xs1NqlVc3vwN{qbzH-tXL}s@xqIlG>E#vk<_|Bxz*bW;n3f{|5|=GIA{$63SpV1@ z>!-U~9rHz3P}o|6ja@mL)zPu@loH^!rCtLY`3YH11AA;yUrMO{*Pm5=T zq3gGy?U>AzTWE*KfKhDKOC-@iQUq#sM@<8Atb^HFBlpGmRENN#K}So8JBoFxH6BkMy6cc%SzbunHw~nKW|HE05TK%)vKm8epj4@Bnv+NoGTQ3(k@4*^FwiH+|i@$dR*N#1QB-!_~`(QjJ zYC6K%9(TOwGu|J z*^R5Gs0YnrB$Q=Zy)$jJZyywdazWY97cChxO!Mai`i$`8t%37 zqJX+8Uu+d|piu}!BIIHaDgA6)a$i8slaeqBsv+Q6!q%EZ?Fe1=Wv@vQ;>2L)`mEkI zhmg=nwmH-RnNZbY2vGPwiel;x^$>C>RL~rJ<|+IN<4>Gm*AHJwNG*{SI(IB{*Uujy ziP~JY?U^L;C<{x+2}uU!Pfdn*u`$+Yic#mi zW_dUCf(CQq_vfih+q1Ws8yG4IBNo~s* zKaPfer?2bM3t6L`3?I4cuE<2f@GWCx0etMxMpU+fOby9;#>uxHr$3)_-L2P;)m!en zgYVCGmR4^CO3jujbd^vDz7dn`ZxM1GpM3Eqwtn+AWH`b)gDm9S@dJ0U@ad&c0r2M@ zq#~pqjYMUKH!btk&O+)Szjuw518W01-xstAQF?idsKuzIF*$-u9KN5Io6Z!b1feSG zb2NkpfKaN^knL6Y_;~f)dyqP;hm<~N=~sU12v78e+mg?OgN**BhK@x$|Ei=LQmtlzhSP-lckX@e_W2-%Pdb<_kTs46Omh>%n? zEd&FiR=`%f1}mjmXQ*1nYlR+_QlAa(f^{I?V+v1Xm3k@^$2-jZ%Ob64KTd`u_yP=w zlzlOSQ10%-p!;8-Sn4A~5oS|^+U0F(Tk1@`a#z`cPZgc-bN5f(NwHjT+0LiatWS|; zUHVzsW+NVs=m$Zv@`p;CrDmb?sU`fnFuHlWwYEk-Tf-Qvu`-%x-NvEAACuM2jBI$? z1ZKoh6qLEV$Pjk|OCMb%DjICvd8HJ2o~Ww&5Q0}xF)GHY6TyMFxw*5PK7Q0hla_c( zN+$$V6laB6Y6yqdSv|PUhN*2#Zrc`TMINiu+^Y}1TLkMg76~!p;~>VLI(9OgId;mr zk%-#97HdJ!M%BL2D$Tkf`_vL={{AeRcW)`ST(xO;u&bN2kV7tw%c_^6yuPkv`1wAJ zrHuaf%aHj#?Q4c8qH>!7*9#o{`GbSzPQM2H?9`1ra+^e~o?d0~*f}WMY7C`Q)h^w> zq!`8)l1Ny3{~TJ*|F=J^#@i*>Z6JL^JQZV#h$tkuA|kB$hfT>}2*S%LH|w~*0^Uj$ zWipfmHNkNFl^(s7Jz3 z!_fK18SZ)g5qhU{Qg*VDTd1)ePX{5wkc!|Gf~ew*2&%%s$PPgfsdQZFXriUDNCndJ zoPm6y zOQ<`-#s(XI;ws{nLz<3Icxs{?{M7?2-LcG;@mrW^UqO*)7>S5nxj9os3_K1I{lU8%*lhK+Z`j19VWMe@g5fftszVQQ%fx0 zvCR0y9*j-t_j3>xOfbeHDrL88V<1kVcz*6I%M0@iKfQ%(2qq6iMIgb`9*H>nJJa|T z&(saO=ybaTpM#MIln}gTUNGW8LgM0>;|K4fv$n>jXKyA8P(*^H7Hgpv3&~o>f&X<7 z@kTf8-xAb`=@*>_PIgB_vMPvQzjxiX9y5$HLNVPdyT(l>#8Wj2uOvpXs|9!d!~tgh zc}{`1Y`kjQPqep;W>Kruc#Y9<)Wg!rbHjjhjj}yTzX+IqL0uvmDIERK0@d7p$SRO% zyO7)@;1tt0XkXDn2_cl+U3qxBasa}~3V^SsY?{LbCaF~6{`D#W+O0}DOcknKsTlHe zlu7YH*~xmwtOw2t(R;h6yVuNrcvdD~xS1>tm?FmpLnDc3rm*xEr#Sk%$MEYZV?3Qv zo{V4#P5laol8JWWZL-P%PVS0BU2H)FQ`Qu5j8A)WRa;|4OEn3p@T}m zjihCDzLcx|soy)oslPkJaQ!kiPduJ1_f?0#oJO*tBtm>*iIHbblnsxvf|gZkKCt+y zMH=ZATJgiaZ0O zh^PpmRO98%BKHL@u2E|=SUs@D#FKJrqY<7!!z%TzXZbTrB(A~6ojd7tyNHx@FEOC% z1p{cAw#xE?v&T*$2@GA=rjvU@91x=<4w|X3_P%MBKD*4;Yq!bpuA!*2zOIE7s4JSZ zLw#)bn4kOXoUQLzp!MWYdfgnI>0mVAMkDGqOSG7A=MUV)!l#!R+S)$6@$wy?jT^OF zjAf}PiesS&OX@8fuG&NJ;o~c3W*2APJvXv-DyH6c81ET!f<4Q8rYaG>hjNRvtAWQkuLYi;=V{9xfYmi&zX%^;%MzrMQYnU=d;jgCQ#WtYZ-(ED`l+8=dSp%lAw} z*E2MgFuXM-5xDR74rAsg7_UDTD|HM8!C@q-(h!csP0%kESUP@^e5OY_Wwb1bM_KEhX5qkD=y)0vF|Ca;W7}#h|I0k* z-Z{sHk!u+p-cQhy95|CgJwMZy^LQ4!qbU)uaSVRRe;MWrH<&54`)qCCe zWiAwMRgX!~9n~*vRu8O_o$cd7AV1RK)SFH+`~C%ln22F==IL>qE{ExHy!!u1Jj)a; zk+V#ohtfmoBN$W)${LJ8v)HK8f)U`W$x-UYvNowGwX6oD(u_*LnL4T6N}37dF6z``UUqiqXR4brs^-mxKTIo)5zs&N9Sr$JwNB7dT*NLLvyTrW)X{!&t@F|(=!y) z!nRFM#MuTKJc`E`S+!$OpL%10BpqgLafXG@&XS$#BSm25eGAOIXP(WQuVi$52i|+~ zJi`|`K6r|vPf=8_`J5sz=x2S}V-xryXZge&^B-9tJJZ9jdCt9Kmd>F*JFd8jwArH2 zoIKA6LFsk71P$a_5AQunU}<)qbB9l0hYiEm3=y?0#z4JhnB1Cj?oW?#?jNSvdhHH2 zUb%^^pQA=m8&IQoABct=jm-^uOFfo8w@m+dm&gbFsUCBGH_eg%eS&=5GjUU!;j5ZK zC5XCS)2Hj3a?{&YkUcJo*Plb&y9RH^LSTo9ircXv>zwNBUAb)~rRyn{3QoTD9KEyI z67VCnv5DFC)=BDH>lD6Mx{tQv*BXD`8u?N{D8Ms;U+1AW?fefCbDr)el$8sE_83wb zpQRQPz~Ig|m~uFV5ge8TLxd;8NJ2peD=|Sc6tKpknpf}jOW=x@4}^fnNS#2Bwc;RI zm`AJjl2+=p+3ar545}UxSB7E5u$G;q?-wYF^?%iWCo)Zj8hfb6;}m`k zV`739)q>#g+Q-=zd03~@J42^4jX!@5p;@0|xV57U2!&9N+gL*AV{A+jGSaw7r?q@dvP|#=Y33M(NJKlMJuzhti&ky7!)a+b-Bo~yfn-D@-ju9oo7a+ zjRq4_+sb3DAY$=FhK(YMyiXKIs4s&###&~Mouaq4PWzf6npZTa?{6^iqzR%7KJhJ| zCZF|ex@wB38Dnb}8(B0`qK3tX0!a<7Vd$^)nEUKJi}x%M^85SvHh0!&?XOYa9^-Sb zL4znBOx2#>J3be0-sRN_q@6Ay@3aLK6^R{;Z)fS)zTy`mxu@vdoeBVBKO%;{;0u7 zL?EE*37TCn22-`OD6bc^z=$0*h=L0Mtr~DPA%qMc2EaF1o8o=HI9Yue*y^86;*jynC>oV7#i7+ZD**HHRj##K##P01%Uv0ze5G8$tOp}*QM zhiVmDGo(`v6GPtf-~w6{_@I=AazLewrK=)h3qkLV*9ma@3JGQ zj{klXZ~92q&DNqgx7uFlmmn1S$?}&Cgu|5GkYCOvxg=i+i>?uDYB90FrUqL#L?aH{ zFo;!5LoiLiDZ~Lu1Db`3JW=kI5kj>jYq>p~23rRAq5#45B~O<{WL2_gg|+lp)E)br zczbuKFCETp_jK+$)86J^HV{JDhW>T``6lUq$thE56jN#xOqs*bfJj8p93xQ`-7U3O zP+w|N^;ogzP2VzF95CVtT6UEi=r57doU}F~gi^a!(+*=SK6s3AC>~RtQ&kab(GW1s zqTVCMRGL+>#t}k+jV!@?L=1zXVPh*Z*16J56jOcIfQcNz7g*=;zNq3orh3f~ihywj z^;NG{V+bK&9fU%`==ng063SGPExW^^5VW9J5BPq81Yy8jGEPeE*)Z54!NwqU!3`<4 zX^*na(x3HGoeXR~Paa4`Nh&`)8r z{+9!Uu8NR;brtoTtl9yL{ztT+sp=GL=@aTjiA{5VW#ajK-i6%-ck$7oyzj!ayd zi|Vk(BI1FhtUfVOHNG;+dOw%~h%1|0o6;2Zgc3yJ%cv-WhC~$rDiC3$I;SF5N^?|7 z5L;U=3`(fX(}1y6N@uVWk`1MwsU>h!JtfVz+6>f|roFL(YEkY-A!Xc4A`4o+R|dZn z70}=@R?$#KPzeE*fSM9)rb=%FQ+0hKZcrc#vE?gWZZ5VC@zQ&4mZLeEpI7KCnf zd`Hn-%gALYIZ|#|Fm;f+Vp@W22vP%Sls~(~Ra&LQ9B3e1kZuS{37#wslEsC(VqHaV z2i}j(J`s%n1j53<1%zCXFT9#^1J28;#QoN)IytJoQm+DSubQ>_1qGD-3s^R;$}bL( z)h*W{)~a*mgJ^-^mSQ&SjM;FLz;Jn5Q%)dCEn#q#$7ZWbX!V+26ucQ6YtMt&;Hn|m z3Xq{XhVv`9R%a9`HO*i#kTS7Yr6WRFUnnJ=tzzX+QD@4}pZ70KnfH?_z$9g3rP4<; z3>1d~M#^t$WI!u8pMXTAS}068`9&1PV~wG}mwUOJP~J*0AUP^!1Q-Eh%D@d`OW)L# zxmS@&Axly2NuhbE)yOeYr5Q9UwOPn;t}NOX35YQSGK`A|zK@L!ArxQ~6FEE{lSG6( z!`MMIIv`FciX0aiye}}eTsRb8YC2zFoKR@lKUPtKltA>Fp+*Vf@#--VsCx1&FUQ*T zskR+kV4S_CIT}iNUE5cU`I1oV?Z?*kzgUW z9>pRG#-9l$yh&94P6~HKG@ALhfN-FC>;=HvU*!k~@6A^l@?6!sW3ZJ`QZZ?UDppOi z0;8wg_G+~v0<2Y^9e_6y++vGIZ5-ukUvFuC3;10iwggL5{fO?owxCMHmmu_24zNlS z3``bbYsiMl~O~>l}GWCiYQ{9_TjYZGj zS3%2jidKuq1^<_FVF>EaYuz9PL45hQdV(p_GT1U8qgsMkqd@SX+yg-r-zxzgdI7(x zgdXTB_$5XA5c(h)44TQA2G~|PTcrhdw3?|2m|C^YIut|IJy`^;Hnc}_yevpz-zg#f zQDhU4*ye7*Kk7k1B*A4Y2DgEyOeS(%ieh}7=UND*U0i1I^UuiLjk`6v~ z@#potsrkTb3?_%(e?BQ8rK0zrOD;TbHCfM}ui}$dTCD`|{hu~cvTX(wxBG8Ic^v0W z;6ZnS0YE%L*@GMjm3ipPC~WmFNErzWmZB?vYkqM{XDULrv&el69W_EG`S@IdemUMm;Eve8m7IYCNO zxBPAep7OO&-GdUe)%dG?orr=h7ZDu*HY(dgg`yl!(G|3#NDh9v>|86o@^7ukmm0t( zWwJsNFl{j7v!v)r} zJ^=FrUT7H@sOIV5@4;JI*_Y>;;nngG$_-P>TC%c*Vo<66Up}kK{htei1y;~t&?=Ir zLGTrw#Z+}^gG_^-KVLb7Frd9?IhlMY12G!PF>6qK^>X%vH;=1&R>xs%lU~2OH98 zS!_~K;Z4xNb<~%gH-ZF$K~+Q0pr*`A2i2efAIhtjaMY@s+4;qDu<1=W|9=%wsRAWh zX+;96mCsl$E;{IpcK%UnL=A!9RYOS$D(@A7SfeB=wo#g(Zd|aFf*k`l1#T1AAuyvL z5om`}i!MNM4E!AU)8Nk`p@+}~?SiC$Q%mHBX!t7-d#&pwH7Sxq!Ph!s3-Ini88eR< z5Z2f|V7Z*C3N-Hp*;2B4gfHNsgE->9-=hlWs9fNKir#NTURat@f$M_c(fRO^3_MOb zA9B*lgOv-mstIM(q5?VRHK>+EbX8Re)r(qw`{0A36`%Y90HF$A&mVk#G0{*WwR)>M zj$DIwODwA^BZgYq2tl(D=v6Rrs%nB#gdqKDg|G-Fi+m-cFln#}jgW_!Ud=kPr&~@;u!Kvh1i&p1K8|;Yo zhmINR=kfND4#GX>sb&>n_IAoW$_t=fwX*np`GCCoyoG-cb6Xzpj{&cw{EfY;m}&{H zf-u$R2HH;V2ejz@uMf21dEizL8B}5qqBsNKRLOKzt$67wmF5jvnFU&IS|$Sk-d`oE zmBt;suK1v34P;47H`Ql+P+3>iP6alnK}|J`LOp#{3zZNlYRke2=@96GH;Ov-6cuGi z%KuAOgY+>WQi7@0h=6#b1Lds}lprcW&M!ce{-9ujib#;6#CwQBW$MacfBOLlQR@*E z2`1oOE)pyz7zsux;y%H6G2Y@aWKk|Y>Jx%d)EHMeO0n~%g~*VK9RoW7ZUoE*Fe3)j zM5R&1_lnZw^|PS!Ad$kTAIfXpDwxM^#fn9ikR3b1y+z*I;r?NX3L$0~!ihQ8gVgS|g&ax%NY*OBg{7H4T~v zm7WqJP^;c_G)RGjSjCH~@dU{rh?L}DEqz%pB1TQHg{VsDV;W3|3N;?JzKlOt(KAt7 zCL&!Ci&}4d)WJwlTSTHJ7$0{~DR4!Ch)N!H#k-zb?^M;|1?f4}uFdcgRDvaxW~XTg zQg`YmB-qWt*zwYoHDh2?kb0?6r4A+yX&$XzZq@E~S>vb{_ORyQ*HiHFhzH?7Iv{s} z-dmSu?kYs1RvWl`P~eBB(g6tCuxZvsUJhLWG)iRq2Td2JudV%`~_S6D$TR!30&+ zV7xI{HR^m2FNMvFRaY2|GnGIv-jNQbJX-0U;noRqg*VkVBQGYgg$Lb5V_CQEAZ8Dn0UGQdFrF zx!^NWUHnu9z{Z1suvev7GtbhWhHT-n;UQXWd7Wh4t7 zlx!kY4WAN%J*VED)u3Xm))jSPG*%@-WktPPEXg~*iSa4kE^1~^Lr_x-8v&yoa|}<1 zNLvKysM=LyeFIa(8r%ZjEn`D0wrHWo6KogJGR+#|OhmP?eHTnHMy(e_yv?k5Q&@Gq zV7#a)j06#*#*3&*kt~baZisp5vk$BrTd2Jpg3s#*NjgTM`B$zx|lgzE7-XI#4fm@@ZE>~}hD%x%^P^9ZS9kwlN zqn`@BXql>@?kfd^gFm_;2Z8s29H}Pzh6(@|MnM)U|FH28=BrZfCD5;On-^-s6_CXW z;ORw!h$^6Us&m_m-mg{QUaNfA!Fi)fLoZk3Ngm=$_Nqs6;g{C)HSfBLa7KkVptUM} zV9O34tN_c3#^nR2<@nY?)<7GIrUD&7R;olx5~#8&qM|D6siwThr;*F1ciNOR{)K-w7>hf6C z<${I~Wpz`eYXsXR%G!eUNq6{OQPcBjXG1VPO}nEfqP#huCu^e`_eYF(-8gHX3KA?X zYvGDig5+s`?6C3iVz5~Q6VkF~$vg3GojhJadn?=&D-nbPtA8EjKFW6FcT|&hs+#O^m2&+M$k0R3@2U*A9ILeA;4`-Jqdr~@ zWa>f43~@zT=v4&x2UIFCXt7v6w=P&5k_v=N)p7PA>bVvxt=Sw9(n=-{R?$d=btC2+ zgu0@&ve!Ux0b&tdRdgLRMToR~&5G!XAZHX}6&(}NU__P#auH1tH32n1)*6AST4>-MSdjV6xcxWX*(Vt#JLw zyDX7lgTV%G^9TXw)71b$<8D*b6cSuFxUBAcI`6Xj2_N-ZgBq(9)R<7uJcT_a36tXdqlHmH0DWX*qqE&TyO@hlL zM61DNLrPGar?bIjqlN2?)w>%$6J@Q#d9t!4Pdb~Ue&bZ!Z`~VgHdLgYEkT2(z2W=B zyA|&`n?h6!1@UpxZ=Fi}WA_E|&PV-GG3wM7v3Tp_Z0M}Fh1EE3i3t%BtO@ao%bLg3 z6iuv8L)8CF7+QW;7@6;WrGxN7({h@!L-HqpW55x?ysOkqdecLhe}XJZsSRtDSvxrK zm|#C8Fb8_ogT!|RJlNxv7ELY!Qmyh0XDTwhyWlt}$0%#nd*-4qH=y+$sQ^EuGT{6u zRWFYO^tgzgQ_%?^t=KuSls9ovMVCdi0h%Brinc(PMdU=;ttU)We1c_!uA-@kIuW&E zGy%yCa$MCcit`&lEdnCJVZ%5Q5-^8?w?{GB5bN7wf)yLe6+gK7;LWlapPGhj6r-)s zH~0FkJtS$^?CN2!dYRFl+#?o;3GGls$HZtbQTK8&+VENJ03kl3wmYV_-xQ6zsAPr9 z>QQT|0vqiF! zyY=x9hZGx90 z%37rn-z&&0Fn@tIe2^fGOjh9iB*>F5cq0`!336}Qoez{EbfmS&f?`gMY6Ir?T&rQ_FG3Z zUAv}VTiz``nT>jllRjDBUevmq3n|hh8@@L#;*PidZNz!2Z`QZjerr0(hmT;2At`Jx zDr!sKy^8c+48$?uu%IUp-5AhXD5I4Fg7=W3k)n5t$ReUsrO&7YG*QvC z0`d|PTA-1XVBCOVRpCgPZU`Ghv@S4@$hwp!Y>ZJbVOS+dDBNd6<*bSP1V)g!^|kf>duurs*eY^s|~QtT!(_l2&#gGh&MtGHRf_@4ck ziF8z=Vj}dDBjm|Zmvk>D?p&os?Wh#ZBf)jrd9=FGg>=!XUG7IKqZmoje)FV4Cr?*5 z2~tGa(6L~%*vFkom!}JasOO{Zr1SBLD{9NV#>@?Bd@b!x++9R#`@GE>$=aq5+iqjt zH&(99-0J3ZZSx1Bym7MZ79)wv>POw`gsrCB|Mx=L)@W5`a=Qpd(TyTy4zL8FI^h3j z@7j9fI^O}b%T+B|l6A2zv~{th=w?z9MRJCmIp^D}59f?D7Sx9TMeD@e zzybL(oEe^3v-h|6T5I1V(Q&8+AQfexPZ@QSu)_vVB7Li%aT3=7E~?C=HBx~|F+=lN zC>)a8Sth=X=8b`EGJ_gSd`fO7Jx~7&h6zjZ*-C4iGC^ID*VVU=XvnOl=}?Q?)lW`) zr*_yv9Jglvn8-C>&0c1Lk&yMD@tEFJ%+7>#{ehTv9zef!EXnI# zx6jtQQ-@;Ood|jMu`jh>sD z9S{!Yg14(u^_A)@Hw|D5ff*t@MkITH_%%S2Ln7e@U>6D7FZk1dTK7Ef;0$-YI{!`H z1@RpqO%gWf!fqNm17-lW0erV)1YzzzbalL{aoD0D_T+1U&$% zeV6Ixjk27@jZ*50R%r*O1keoVIba6`O~T>~;4K#yAucd@n^X;eS?~!2Z!(4h@NmRJ z{B;B$yCbCxag<5^AU!O{B71}8GfaJ!fkeU@M=-;Pb*=L(QyXI~pSDK)9E;?(uO@FP z^^v5}d)9(B`C4rs6IfDT{jw{$Sgen}mL&PK*Kd3|E$Ww&ym__AIy-yW@@!U&E?BQM zpEqvq?$?$cY^+V470}Ha%e$<|mYQp`@5LmCd01{NZ`z;cua=P4Te67nw#|^ zLJ_6lG3!KI8Hbz*tsWE&O4s4H+E6fjmO(fS#ub#y9`}`}c!E+C&3k}Y18@;wUV(qOWSszb6yP$-r6&9&wMWyWuQ_z6 zVr1>)z`DQG=P^R#AeITd3;K-1+e4D9x`@=k%LIC&#z2J<%$fq#lk9B=>N4L3c$?&s zWamINY2Ks>G)*zYS$gu3iu52u{56I+eusDzVuNYiDur|CXFnj6GK+Ia%?Jc$7*)iA zmeaj5i_G#}ti>JjU+=+m#mpT%aCtok)B~FHYw{ojo#>i z&>K6c+R8&k=x0fH@<7sWov6prkJKH1C-mB{*L&^5yfJeSt7HF$_R0@KFWsAT$6t5V z-YAOnn7Vc%Bu|zFW&8Tie(c8-v@XN z&~w%7@7`!t8E(F6%51ua7%+yiQM6EjaF_%zQFTfWRDj(+{J?S$?=$83PW#NXyPPu) zYafw1eG0&N&@KbojIuL2&|=jqi;s^>5uC=#Jc`uevlOofCi`e=z>1wPZ$i8d5Az6W z(!34I5PSwfGb+MC&(pUVd@GY;cHl6;5F1R2?Q*;AYxUP5q&8CQMq)HW%Ea4n_Tp;T zZ^1%n^yaLQ?*vG!+Zn}VDb$MRnB-gIT6TgoCE40TF|Qv-xAAgdSX5!BV^RBA#`@dA z_|sygwclgy74@5Ms>8!VIH-QMFWzVzN2s0G^!01Z?W53Ze(Z)@F1v-k#ZdD;L(w7N z@_@J=N|*FTABqWt1nL7!N@a$x2cXyh;r}KGhd88MA=npkmD$L;xTF4MyUJD<0Q?ZZ zGbr5#?iZT@9w~vQ-PP?Iexdb}rNiq0cHZ*_X39*7cPfIwG;r5=qoj^$6M&Nd4v7A+ zpqB0^xC8=q!KVQnr=chKj%vVPl31a!(qRghK_p&|EC4EnX$Qfp5RQpH1B+YDGzsy# zWb*`C48;UUFvKZ@xP>vCl7~Y~itP-=rooBeunOU)Op;fo>ZP4?GorweA!ry(ASoso0u+DowX#|*jz z@~nHh*LygkZhFB+aEstA6u6Cm9?f&Dr9GwwO??dJhR|!mjio%SZwNI9Ls7}OHbD6Q z2}0a8h>`=m3UEKc<0$vu-v-bT^bru>0^)AMzH*Ny{vOr~=LvT1Q@S>)a`=3e3CD-t zL{@?LB*5bUpF&ALyQ}V}TA)THz5rlV@ZF^9gRw=~uGA>00PuYP!Qop6?9fu-?xPY` zAzmhxff%inc$pY?6P%~QaZ#HX;#Qh(fxSW=XM$NqiWxBc5jmXx_H8 z*jkE51WP>)&G-bOE_ko@78Mg%F{5?fP{BoJmgZNQ-|^ccFQXMZv~W5u)lbROw?d=; z8oIV;y;DELmX2p3KNN4(&N9)GHM|3AQLqjS@Z}L8NKC7Hm{*)93hJg{8a6=q%LPIo zOc46zj1Wgk`kD>`I%Y^0h%^E4IG`>6!}D(<>?B|(06krmruby(d8a|N^PVQoXmtYF zTNR@ZYA}1`fV!q>5@Q0t3m^ggN!;kaBYP0>AH_oRAZQ5Sw1bwd5_7My|F8Y+j3xr)mh`Y>Un;||S*@qsJ12nbE z>X8}SQ#Sp)!Db;N%n>=nWu6a2SO z?slB3096D03xZuF!iz%jWN8!hiP#Bn4!{e5K34&67^GhU^frKRJM?EReO~Z8&TbHD zr2lb1_|xd&Tai9Ti@S!M;Q-YHJp=Hy0DILD|A3$P?$WpcJ0ZU6;sKgH4a7vkO;XdM zW<4g~LlH9t+d_JSWDhZUF|IdWQqp@=s$I1tZc_{sh}kI{S$p3-yrjI*WXNxkT7j68 z-eV}rW?1E@_UW(~`*g$x2!HVq?n;u*m2@{u1Kb5*2Y^Qa{T{&uB0Uc9mXJ^1=To;E zz?%Sn4Ct%)q;m*(wFb5*7oJ|LgE4vC5e*x$lf%r?64(g-BwSs_0U3kwB zUKac*(sy`eiUbM{><0LjDg7I`Kjq|-q>G>zfG#=xLwGn95!$poresG5XQRBQ7>y(~Nll4R%Dc4j5!nFY|8-m`FC8mw7Bvg-c>yZ~uM+lG0)HQ+vZGOTLB{|+2;h$Z zeyi%XK0EX`LkVVlRj@sR9)s{Z10%Px5|l;8uZcKn;NKJWk3{@)0K+DZ2KsLcJR1x%zbogD zNc(G2k2w7c68a$5C3eg_0@@4@-<0eaiD2f}3}L_<=&vZENDh!blt#mvC~^ye@){^MdM*q#IH;S|CgP%@jL{L%FOK`0nH>>z`0?}JzczCNNEjg90RZ)R00000NkvXX Hu0mjf%11c! diff --git a/doc/third_party/Pluma/html/nav_g.png b/doc/third_party/Pluma/html/nav_g.png deleted file mode 100644 index 2093a237a94f6c83e19ec6e5fd42f7ddabdafa81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 95 zcmeAS@N?(olHy`uVBq!ia0y~yU|?imU|{25V_;xl68K`sz`&s9>Eakt!T9#BAuj_1 z2lGLH5An2?hw;3+c6B?R`YL3e_I+`nnVp?Km|^dqCL2};1_lOCS3j3^P6Eakt!T9#BBNu}M zhg0BMX7T`TmD+;uQ+m}s#*WMoza2lbLp9(I{Its b_As80;W@%@d2oT|#XixUYy%lpuf3i8{fX!o zUyDD0jOrAiT^tq>fLSOOABs-#u{dV^F$b{L9&!2=9&RmV;;8s^x&UqB$PCj4FdKbh zoB1WTskPUPu05XzFbA}=KZ-GP1fPpAfSs>6AHb12UlR%-i&uOlTpFNS7{jm@mkU1V zh`nrXr~+^lsV-s1dkZOaI|kYyVj3WBpPCY{n~yd%u%e+d=f%`N0FItMPtdgBb@py; zq@v6NVArhyTC7)ULw-Jy8y42S1~4n(3LkrW8mW(F-4oXUP3E`e#g**YyqI7h-J2zK zK{m9##m4ri!7N>CqQqCcnI3hqo1I;Yh&QLNY4T`*ptiQGozK>FF$!$+84Z`xwmeMh zJ0WT+OH$WYFALEaGj2_l+#DC3t7_S`vHpSivNeFbP6+r50cO8iu)`7i%Z4BTPh@_m3Tk!nAm^)5Bqnr%Ov|Baunj#&RPtRuK& z4RGz|D5HNrW83-#ydk}tVKJrNmyYt-sTxLGlJY5nc&Re zU4SgHNPx8~Yxwr$bsju?4q&%T1874xxzq+_%?h8_ofw~(bld=o3iC)LUNR*BY%c0y zWd_jX{Y8`l%z+ol1$@Qa?Cy!(0CVIEeYpKZ`(9{z>3$CIe;pJDQk$m3p}$>xBm4lb zKo{4S)`wdU9Ba9jJbVJ0C=SOefZe%d$8=2r={nu<_^a3~>c#t_U6dye5)JrR(_a^E f@}b6j1K9lwFJq@>o)+Ry00000NkvXXu0mjfWa5j* diff --git a/doc/third_party/Pluma/html/sync_on.png b/doc/third_party/Pluma/html/sync_on.png deleted file mode 100644 index e08320fb64e6fa33b573005ed6d8fe294e19db76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 845 zcmV-T1G4;yP)Y;xxyHF2B5Wzm| zOOGupOTn@c(JmBOl)e;XMNnZuiTJP>rM8<|Q`7I_))aP?*T)ow&n59{}X4$3Goat zgjs?*aasfbrokzG5cT4K=uG`E14xZl@z)F={P0Y^?$4t z>v!teRnNZym<6h{7sLyF1V0HsfEl+l6TrZpsfr1}luH~F7L}ktXu|*uVX^RG$L0`K zWs3j|0tIvVe(N%_?2{(iCPFGf#B6Hjy6o&}D$A%W%jfO8_W%ZO#-mh}EM$LMn7joJ z05dHr!5Y92g+31l<%i1(=L1a1pXX+OYnalY>31V4K}BjyRe3)9n#;-cCVRD_IG1fT zOKGeNY8q;TL@K{dj@D^scf&VCs*-Jb>8b>|`b*osv52-!A?BpbYtTQBns5EAU**$m zSnVSm(teh>tQi*S*A>#ySc=n;`BHz`DuG4&g4Kf8lLhca+zvZ7t7RflD6-i-mcK=M z!=^P$*u2)bkY5asG4gsss!Hn%u~>}kIW`vMs%lJLH+u*9<4PaV_c6U`KqWXQH%+Nu zTv41O(^ZVi@qhjQdG!fbZw&y+2o!iYymO^?ud3{P*HdoX83YV*Uu_HB=?U&W9%AU# z80}k1SS-CXTU7dcQlsm<^oYLxVSseqY6NO}dc`Nj?8vrhNuCdm@^{a3AQ_>6myOj+ z`1RsLUXF|dm|3k7s2jD(B{rzE>WI2scH8i1;=O5Cc9xB3^aJk%fQjqsu+kH#0=_5a z0nCE8@dbQa-|YIuUVvG0L_IwHMEhOj$Mj4Uq05 X8=0q~qBNan00000NkvXXu0mjfptF>5 diff --git a/doc/third_party/Pluma/html/tab_a.png b/doc/third_party/Pluma/html/tab_a.png deleted file mode 100644 index 3b725c41c5a527a3a3e40097077d0e206a681247..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 142 zcmV;90CE3`P)z100010Nkl|2#Ij`H`=#qC$x4-uPeScZ?U+O^uG+CbGeEz10001RNklz10001ZNklz10001gNklEq-#tja!`PimmJ#tZjoC)~tgX-LKHSiq%FbS-K?)r(kXu m%q%$(LZF$FsUgvfT>S++#UuRg?v)<^0000 +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/ItkVtkGlue/itkImageToVTKImageFilter.hxx b/lib/ItkVtkGlue/itkImageToVTKImageFilter.hxx new file mode 100644 index 0000000..e134b3f --- /dev/null +++ b/lib/ItkVtkGlue/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/ItkVtkGlue/itkVTKImageToImageFilter.h b/lib/ItkVtkGlue/itkVTKImageToImageFilter.h new file mode 100644 index 0000000..b4427c8 --- /dev/null +++ b/lib/ItkVtkGlue/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/ItkVtkGlue/itkVTKImageToImageFilter.hxx b/lib/ItkVtkGlue/itkVTKImageToImageFilter.hxx new file mode 100644 index 0000000..334b02b --- /dev/null +++ b/lib/ItkVtkGlue/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/cpExtensions/Algorithms/BezierCurveFunction.h b/lib/cpExtensions/Algorithms/BezierCurveFunction.h new file mode 100644 index 0000000..2deba45 --- /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; + 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/GradientFunctionBase.h b/lib/cpExtensions/Algorithms/GradientFunctionBase.h new file mode 100644 index 0000000..0472cc4 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GradientFunctionBase.h @@ -0,0 +1,84 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTFUNCTIONBASE__H__ +#define __CPEXTENSIONS__ALGORITHMS__GRADIENTFUNCTIONBASE__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class G > + class GradientFunctionBase + : public itk::ImageFunction< G, typename G::PixelType::ValueType, typename G::PixelType::ValueType > + { + public: + // Types from input arguments + typedef G TGradient; + typedef typename G::PixelType TVector; + typedef typename TVector::ValueType TScalar; + itkStaticConstMacro( Dimension, unsigned int, G::ImageDimension ); + + // Standard itk types + typedef GradientFunctionBase Self; + typedef itk::ImageFunction< G, 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; + + // Sparse buffer + typedef std::map< TIndex, TOutput, typename TIndex::LexicographicCompare > TBuffer; + + public: + itkTypeMacro( GradientFunctionBase, itkImageFunction ); + + itkBooleanMacro( BufferResults ); + itkGetConstMacro( BufferResults, bool ); + itkSetMacro( BufferResults, bool ); + + public: + virtual void ResetBuffer( ); + + virtual TOutput Evaluate( const TPoint& p ) const; + virtual TOutput EvaluateAtIndex( const TIndex& i ) const; + virtual TOutput EvaluateAtContinuousIndex( const TContIndex& i ) const; + + protected: + GradientFunctionBase( ); + virtual ~GradientFunctionBase( ); + + virtual TOutput _Evaluate( const TIndex& i ) const = 0; + + private: + // Purposely not implemented. + GradientFunctionBase( const Self& ); + void operator=( const Self& ); + + protected: + mutable TBuffer m_Buffer; + bool m_BufferResults; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__GRADIENTFUNCTIONBASE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GradientFunctionBase.hxx b/lib/cpExtensions/Algorithms/GradientFunctionBase.hxx new file mode 100644 index 0000000..cc0bac3 --- /dev/null +++ b/lib/cpExtensions/Algorithms/GradientFunctionBase.hxx @@ -0,0 +1,82 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__GRADIENTFUNCTIONBASE__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__GRADIENTFUNCTIONBASE__HXX__ + +// ------------------------------------------------------------------------- +template< class G > +void cpExtensions::Algorithms::GradientFunctionBase< G >:: +ResetBuffer( ) +{ + this->m_Buffer.clear( ); +} + +// ------------------------------------------------------------------------- +template< class G > +typename cpExtensions::Algorithms::GradientFunctionBase< G >:: +TOutput cpExtensions::Algorithms::GradientFunctionBase< G >:: +Evaluate( const TPoint& p ) const +{ + TIndex i; + this->GetInputImage( )->TransformPhysicalPointToIndex( p, i ); + return( this->EvaluateAtIndex( i ) ); +} + +// ------------------------------------------------------------------------- +template< class G > +typename cpExtensions::Algorithms::GradientFunctionBase< G >:: +TOutput cpExtensions::Algorithms::GradientFunctionBase< G >:: +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 ); +} + +// ------------------------------------------------------------------------- +template< class G > +typename cpExtensions::Algorithms::GradientFunctionBase< G >:: +TOutput cpExtensions::Algorithms::GradientFunctionBase< G >:: +EvaluateAtContinuousIndex( const TContIndex& i ) const +{ + TPoint p; + this->GetInputImage( )->TransformContinuousIndexToPhysicalPoint( i, p ); + return( this->Evaluate( p ) ); +} + +// ------------------------------------------------------------------------- +template< class G > +cpExtensions::Algorithms::GradientFunctionBase< G >:: +GradientFunctionBase( ) + : Superclass( ), + m_BufferResults( false ) +{ + this->m_Buffer.clear( ); +} + +// ------------------------------------------------------------------------- +template< class G > +cpExtensions::Algorithms::GradientFunctionBase< G >:: +~GradientFunctionBase( ) +{ + this->m_Buffer.clear( ); +} + +#endif // __CPEXTENSIONS__ALGORITHMS__GRADIENTFUNCTIONBASE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/GulsunTekMedialness.h b/lib/cpExtensions/Algorithms/GulsunTekMedialness.h new file mode 100644 index 0000000..2fdf61c --- /dev/null +++ b/lib/cpExtensions/Algorithms/GulsunTekMedialness.h @@ -0,0 +1,85 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ +#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class G > + class GulsunTekMedialness + : public GradientFunctionBase< G > + { + public: + // Standard itk types + typedef GulsunTekMedialness Self; + typedef GradientFunctionBase< G > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + // Types from superclass + typedef typename Superclass::TGradient TGradient; + typedef typename Superclass::TVector TVector; + typedef typename Superclass::TScalar TScalar; + typedef typename Superclass::TInput TInput; + typedef typename Superclass::TOutput TOutput; + typedef typename Superclass::TPoint TPoint; + typedef typename Superclass::TContIndex TContIndex; + typedef typename Superclass::TIndex TIndex; + typedef typename Superclass::TBuffer TBuffer; + + typedef typename TIndex::OffsetType TOffset; + typedef std::vector< double > TProfile; + typedef std::vector< TOffset > TOffsets; + + public: + itkNewMacro( Self ); + itkTypeMacro( GulsunTekMedialness, GradientFunctionBase ); + + 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; + + 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..01a278b --- /dev/null +++ b/lib/cpExtensions/Algorithms/GulsunTekMedialness.hxx @@ -0,0 +1,197 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__GULSUNTEKMEDIALNESS__HXX__ + +#include +#include + + +#include +#include +#include + + + + +// ------------------------------------------------------------------------- +template< class G > +cpExtensions::Algorithms::GulsunTekMedialness< G >:: +GulsunTekMedialness( ) + : Superclass( ), + m_MinRadius( double( 0 ) ), + m_MaxRadius( double( 1 ) ), + m_ProfileSampling( 4 ), + m_RadialSampling( 10 ) +{ +} + +// ------------------------------------------------------------------------- +template< class G > +cpExtensions::Algorithms::GulsunTekMedialness< G >:: +~GulsunTekMedialness( ) +{ +} + +// ------------------------------------------------------------------------- +template< class G > +typename cpExtensions::Algorithms::GulsunTekMedialness< G >:: +TOutput cpExtensions::Algorithms::GulsunTekMedialness< G >:: +_Evaluate( const TIndex& i ) const +{ + const G* gradient = this->GetInputImage( ); + typename G::RegionType region = gradient->GetRequestedRegion( ); + typename G::PointType i_P; + gradient->TransformIndexToPhysicalPoint( i, i_P ); + + std::queue< TIndex > q; + std::set< TIndex, typename TIndex::LexicographicCompare > m; + std::map< TOffset, std::vector< TIndex >, typename TOffset::LexicographicCompare > profiles; + q.push( i ); + + while( !q.empty( ) ) + { + // Get next node + TIndex node = q.front( ); + q.pop( ); + if( m.find( node ) != m.end( ) ) + continue; + m.insert( node ); + + // Get neighborhood + for( unsigned int d = 0; d < Self::Dimension; d++ ) + { + for( int off = -1; off <= 1; off += 2 ) + { + TIndex neighbor = node; + neighbor[ d ] += off; + if( region.IsInside( neighbor ) ) + { + typename G::PointType neighbor_P; + gradient->TransformIndexToPhysicalPoint( neighbor, neighbor_P ); + if( double( i_P.EuclideanDistanceTo( neighbor_P ) ) > this->m_MaxRadius ) + continue; + + // Normalize offset in terms of a l1 (manhattan) distance + TOffset offset = neighbor - i; + // std::cout << "Offset: " << offset << std::endl; + + /* + int max_off = 0; + for( unsigned int o = 0; o < Self::Dimension; ++o ) + max_off += std::abs( offset[ o ] ); + if( max_off == 0 ) + continue; + bool normalized = true; + TOffset normalized_offset; + for( unsigned int o = 0; o < Self::Dimension && normalized; ++o ) + { + if( offset[ o ] % max_off == 0 ) + normalized_offset[ o ] = offset[ o ] / max_off; + else + normalized = false; + + } // rof + if( !normalized ) + normalized_offset = offset; + std::cout << "offset: " << normalized_offset << std::endl; + + // Update profiles + profiles[ normalized_offset ].push_back( neighbor ); + */ + + // Update queue + q.push( neighbor ); + + } // fi + + } // rof + + } // rof + + } // elihw + // std::cout << "HOLA: " << profiles.size( ) << std::endl; + + + return( TOutput( 0 ) ); + /* TODO + const G* 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; + if( + in->TransformPhysicalPointToIndex( pnt + ( dir * 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..39007a5 --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctionFilter.h @@ -0,0 +1,106 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ +#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class I, class O, class F > + class ImageFunctionFilter + : public itk::ImageToImageFilter< I, O > + { + public: + typedef ImageFunctionFilter 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 TFunction; + + typedef typename O::RegionType TRegion; + + public: + itkNewMacro( Self ); + itkTypeMacro( ImageFunctionFilter, itkImageToImageFilter ); + + itkGetObjectMacro( Function, F ); + itkSetObjectMacro( Function, F ); + + protected: + ImageFunctionFilter( ) + : Superclass( ) + { + } + virtual ~ImageFunctionFilter( ) + { + } + + 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_Function->EvaluateAtIndex( inIt.GetIndex( ) ) ); + ++inIt; + ++outIt; + + } // elihw + inIt.NextLine( ); + outIt.NextLine( ); + progress.CompletedPixel( ); + + } // elihw + } + + private: + // Purposely not implemented. + ImageFunctionFilter( const Self& ); + void operator=( const Self& ); + + protected: + typename F::Pointer m_Function; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +// TODO: #include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTIONFILTER__H__ + +// 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..19410c3 --- /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; + + 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( ); // TODO { } + virtual void GenerateInputRequestedRegion( ); + virtual void GenerateData( ); + + 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..5cf7332 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.h @@ -0,0 +1,111 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ +#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class S, unsigned int D > + 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 S TScalar; + itkStaticConstMacro( Dimension, unsigned int, D ); + + // Begin concept checking +#ifdef ITK_USE_CONCEPT_CHECKING + itkConceptMacro( + ScalarTypeHasFloatResolution, + ( itk::Concept::IsFloatingPoint< S > ) + ); +#endif + // End concept checking + + typedef vnl_matrix< S > TMatrix; + typedef std::vector< TMatrix > TMatrices; + + public: + itkNewMacro( Self ); + itkTypeMacro( IterativeGaussianModelEstimator, itkObject ); + + public: + unsigned long GetNumberOfSamples( ) const + { return( ( unsigned long )( this->m_N ) ); } + const TMatrix& GetMu( ) const + { return( this->m_M ); } + const TMatrix& GetOmega( ) const + { return( this->m_O ); } + + void SetNumberOfSamples( unsigned long n ); + void SetMu( const TMatrix& m ); + void SetOmega( const TMatrix& O ); + + bool SaveModelToFile( const std::string& filename ) const; + bool LoadModelFromFile( const std::string& filename ); + + template< class V > + S Probability( const V& sample ) const; + + S Probability( const S& s_x, const S& s_y, ... ) const; + + template< class V, class M > + void GetModel( V& m, M& E ) const; + + void Clear( ); + + template< class V > + void AddSample( const V& sample ); + + void AddSample( const S& s_x, const S& s_y, ... ); + + protected: + IterativeGaussianModelEstimator( ); + virtual ~IterativeGaussianModelEstimator( ); + + protected: + void _UpdateModel( ) const; + + private: + // Purposely not implemented + IterativeGaussianModelEstimator( const Self& other ); + void operator=( const Self& other ); + + protected: + S m_N; + TMatrix m_M; + TMatrix m_O; + + mutable bool m_Updated; + mutable TMatrix m_Cov; + mutable TMatrix m_Inv; + mutable S m_Norm; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#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..c6e3cb8 --- /dev/null +++ b/lib/cpExtensions/Algorithms/IterativeGaussianModelEstimator.hxx @@ -0,0 +1,291 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ +#define __CPEXTENSIONS__ALGORITHMS__ITERATIVEGAUSSIANMODELESTIMATOR__HXX__ + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +SetNumberOfSamples( unsigned long n ) +{ + this->m_N = S( n ); + this->m_Updated = false; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +SetMu( const TMatrix& m ) +{ + if( m.rows( ) == D && m.columns( ) == 1 ) + { + this->m_M = m; + this->m_Updated = false; + this->Modified( ); + } + else + { + itkExceptionMacro( + << "Input Mu matrix is not a " << D << "x1 matrix" + ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +SetOmega( const TMatrix& O ) +{ + if( O.rows( ) == D && O.columns( ) == D ) + { + this->m_O = O; + this->m_Updated = false; + this->Modified( ); + } + else + { + itkExceptionMacro( + << "Input Omega matrix is not a " << D << "x" << D << " matrix" + ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +bool cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +SaveModelToFile( const std::string& filename ) const +{ + std::ofstream out( filename.c_str( ) ); + if( out ) + { + out << this->m_N << std::endl; + out << this->m_M << std::endl; + out << this->m_O << std::endl; + out.close( ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +bool cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +LoadModelFromFile( const std::string& filename ) +{ + std::ifstream in( filename.c_str( ) ); + if( in ) + { + this->Clear( ); + in >> this->m_N; + for( unsigned int i = 0; i < D; ++i ) + in >> this->m_M[ i ][ 0 ]; + for( unsigned int j = 0; j < D; ++j ) + for( unsigned int i = 0; i < D; ++i ) + in >> this->m_O[ i ][ j ]; + in.close( ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +template< class V > +S cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +Probability( const V& sample ) const +{ + if( !this->m_Updated ) + this->_UpdateModel( ); + + TMatrix c( D, 1 ); + for( unsigned int d = 0; d < D; ++d ) + c[ d ][ 0 ] = S( sample[ d ] ) - this->m_M[ d ][ 0 ]; + if( S( 0 ) < this->m_Norm ) + { + // Covariance is NOT null + double v = double( ( c.transpose( ) * ( this->m_Inv * c ) )[ 0 ][ 0 ] ); + v /= double( 2 ); + + return( S( std::exp( -v ) ) ); + } + else + { + // Covariance is null + S n = S( 0 ); + for( unsigned int d = 0; d < D; ++d ) + n += c[ d ][ 0 ] * c[ d ][ 0 ]; + bool equal = ( double( n ) < double( 1e-10 ) ); + return( ( equal )? S( 1 ): S( 0 ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +S cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +Probability( const S& s_x, const S& s_y, ... ) const +{ + static S sample[ D ]; + + std::va_list args_lst; + va_start( args_lst, s_y ); + sample[ 0 ] = s_x; + sample[ 1 ] = s_y; + for( unsigned int d = 2; d < D; ++d ) + sample[ d ] = S( va_arg( args_lst, double ) ); + va_end( args_lst ); + return( this->Probability( sample ) ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +template< class V, class M > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +GetModel( V& m, M& E ) const +{ + if( !this->m_Updated ) + this->_UpdateModel( ); + for( unsigned int i = 0; i < D; ++i ) + { + m[ i ] = double( this->m_M[ i ][ 0 ] ); + for( unsigned int j = 0; j < D; ++j ) + E[ i ][ j ] = double( this->m_Cov[ i ][ j ] ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +Clear( ) +{ + this->m_N = S( 0 ); + this->m_M.set_size( D, 1 ); + this->m_O.set_size( D, D ); + this->m_M.fill( S( 0 ) ); + this->m_O.fill( S( 0 ) ); + this->m_Updated = false; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +template< class V > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +AddSample( const V& sample ) +{ + TMatrix s( D, 1 ); + for( unsigned int d = 0; d < D; ++d ) + s[ d ][ 0 ] = S( sample[ d ] ); + + // Update mean + S coeff = this->m_N; + this->m_N += S( 1 ); + coeff /= this->m_N; + this->m_M = ( this->m_M * coeff ) + ( s / this->m_N ); + + // Update omega operand + if( this->m_N == 1 ) + this->m_O = s * s.transpose( ); + else if( this->m_N == 2 ) + this->m_O += s * s.transpose( ); + else + { + S inv = S( 1 ) / ( this->m_N - S( 1 ) ); + this->m_O = this->m_O * ( this->m_N - S( 2 ) ) * inv; + this->m_O += ( s * s.transpose( ) ) * inv; + + } // fi + + this->m_Updated = false; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +AddSample( const S& s_x, const S& s_y, ... ) +{ + static S sample[ D ]; + + std::va_list args_lst; + va_start( args_lst, s_y ); + sample[ 0 ] = s_x; + if( D > 1 ) + { + sample[ 1 ] = s_y; + for( unsigned int d = 2; d < D; ++d ) + sample[ d ] = S( va_arg( args_lst, double ) ); + va_end( args_lst ); + + } // fi + this->AddSample( sample ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +IterativeGaussianModelEstimator( ) + : Superclass( ) +{ + this->Clear( ); +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +~IterativeGaussianModelEstimator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class S, unsigned int D > +void cpExtensions::Algorithms::IterativeGaussianModelEstimator< S, D >:: +_UpdateModel( ) const +{ + static const double _2piD = + std::pow( double( 2 ) * double( vnl_math::pi ), D ); + + // Update covariance + this->m_Cov = + this->m_O - + ( + ( this->m_M * this->m_M.transpose( ) ) * + ( this->m_N / ( this->m_N - S( 1 ) ) ) + ); + + // Compute inverse and determinant + S det = vnl_determinant( this->m_Cov ); + if( !( det > S( 0 ) ) ) + { + this->m_Inv.set_size( D, D ); + this->m_Inv.fill( S( 0 ) ); + this->m_Norm = S( 0 ); + } + else + { + this->m_Inv = vnl_inverse( this->m_Cov ); + this->m_Norm = S( 1 ) / S( std::sqrt( _2piD * double( det ) ) ); + + } // fi + + // Object now is updated + this->m_Updated = true; +} + +#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..860a8f3 --- /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( ); + + 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..2055420 --- /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( ); + + 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/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..5dba45b --- /dev/null +++ b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.h @@ -0,0 +1,102 @@ +// ------------------------------------------------------------------------- +// @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; + + enum FilterId + { + Gradient = 0, + GradientMagnitude, + Hessian, + None + }; + + 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 SetFilterToGradient( ); + void SetFilterToGradientMagnitude( ); + void SetFilterToHessian( ); + + bool IsGradientFilter( ) const; + bool IsGradientMagnitudeFilter( ) const; + bool IsHessianFilter( ) const; + + void AddScale( const double& s ); + unsigned long GetNumberOfScales( ) const; + + protected: + MultiScaleGaussianImageFilter( ); + virtual ~MultiScaleGaussianImageFilter( ); + + virtual void GenerateData( ); + + template< class F > + void _GenerateData( ); + + private: + // Purposely not implemented. + MultiScaleGaussianImageFilter( const Self& ); + void operator=( const Self& ); + + protected: + TScalesContainer m_Scales; + FilterId m_FilterId; + }; + + } // 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..c2e7cff --- /dev/null +++ b/lib/cpExtensions/Algorithms/MultiScaleGaussianImageFilter.hxx @@ -0,0 +1,315 @@ +// ------------------------------------------------------------------------- +// @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 +#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 >:: +SetFilterToGradient( ) +{ + if( + itk::NumericTraits< typename O::PixelType >::GetLength( ) == + I::ImageDimension + ) + this->m_FilterId = Self::Gradient; + else + this->m_FilterId = Self::None; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +SetFilterToGradientMagnitude( ) +{ + if( itk::NumericTraits< typename O::PixelType >::GetLength( ) == 1 ) + this->m_FilterId = Self::GradientMagnitude; + else + this->m_FilterId = Self::None; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +void +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +SetFilterToHessian( ) +{ + itkExceptionMacro( << "Check for hessian definition." ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +bool +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +IsGradientFilter( ) const +{ + return( this->m_FilterId == Self::Gradient ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +bool +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +IsGradientMagnitudeFilter( ) const +{ + return( this->m_FilterId == Self::GradientMagnitude ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +bool +cpExtensions::Algorithms:: +MultiScaleGaussianImageFilter< I, O >:: +IsHessianFilter( ) const +{ + return( this->m_FilterId == Self::Hessian ); +} + +// ------------------------------------------------------------------------- +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( ) +{ + this->SetFilterToGradientMagnitude( ); + if( !this->IsGradientMagnitudeFilter( ) ) + { + this->SetFilterToGradient( ); + if( !this->IsGradientFilter( ) ) + this->SetFilterToHessian( ); + + } // fi +} + +// ------------------------------------------------------------------------- +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; + typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< I, O > _TGMF; + typedef itk::HessianRecursiveGaussianImageFilter< I, O > _THF; + + if( this->IsGradientFilter( ) ) + this->_GenerateData< _TGF >( ); + else if( this->IsGradientMagnitudeFilter( ) ) + this->_GenerateData< _TGMF >( ); + else if( this->IsHessianFilter( ) ) + this->_GenerateData< _THF >( ); +} + +// ------------------------------------------------------------------------- +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/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/CMakeLists.txt b/lib/cpExtensions/CMakeLists.txt new file mode 100644 index 0000000..c2abf2c --- /dev/null +++ b/lib/cpExtensions/CMakeLists.txt @@ -0,0 +1,133 @@ +SET(LIBRARY_NAME cpExtensions) + +CONFIGURE_FILE( + Config.h.in + ${PROJECT_BINARY_DIR}/lib/cpExtensions/Config.h + @ONLY + ) + +## =============== +## = Source code = +## =============== + +SET(LIB_HEADERS_H "") +SET(LIB_HEADERS_HPP "") +SET(LIB_HEADERS_HXX "") +SET(LIB_SOURCES_C "") +SET(LIB_SOURCES_CPP "") +SET(LIB_SOURCES_CXX "") + +SET( + lib_DIRECTORIES + . + DataStructures + Algorithms + IO + Interaction + Visualization + ) +FOREACH(dir ${lib_DIRECTORIES}) + FILE(GLOB dir_LIB_HEADERS_H "${dir}/*.h") + FILE(GLOB dir_LIB_HEADERS_HPP "${dir}/*.hpp") + FILE(GLOB dir_LIB_HEADERS_HXX "${dir}/*.hxx") + FILE(GLOB dir_LIB_SOURCES_C "${dir}/*.c") + FILE(GLOB dir_LIB_SOURCES_CPP "${dir}/*.cpp") + FILE(GLOB dir_LIB_SOURCES_CXX "${dir}/*.cxx") + + SET(LIB_HEADERS_H "${LIB_HEADERS_H};${dir_LIB_HEADERS_H}") + SET(LIB_HEADERS_HPP "${LIB_HEADERS_HPP};${dir_LIB_HEADERS_HPP}") + SET(LIB_HEADERS_HXX "${LIB_HEADERS_HXX};${dir_LIB_HEADERS_HXX}") + SET(LIB_SOURCES_C "${LIB_SOURCES_C};${dir_LIB_SOURCES_C}") + SET(LIB_SOURCES_CPP "${LIB_SOURCES_CPP};${dir_LIB_SOURCES_CPP}") + SET(LIB_SOURCES_CXX "${LIB_SOURCES_CXX};${dir_LIB_SOURCES_CXX}") + + INSTALL( + DIRECTORY ${dir} + DESTINATION include/cpExtensions + FILES_MATCHING PATTERN "*.h" + ) + INSTALL( + DIRECTORY ${dir} + DESTINATION include/cpExtensions + FILES_MATCHING PATTERN "*.hpp" + ) + INSTALL( + DIRECTORY ${dir} + DESTINATION include/cpExtensions + FILES_MATCHING PATTERN "*.hxx" + ) +ENDFOREACH(dir) + +IF(USE_QT4) + FILE(GLOB LIB_QT_UI "QT/*.ui") + FILE(GLOB LIB_QT_Headers "QT/*.h") + FILE(GLOB LIB_QT_Sources "QT/*.cxx") + FILE(GLOB LIB_QT_Resources "QT/*.rc") + + 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_SOURCES_CXX + ${LIB_SOURCES_CXX} + ${LIB_QT_Sources} + ${LIB_QT_Wrapped_Headers} + ${LIB_QT_Wrapped_MOC_Sources} + ${LIB_QT_Wrapped_Resources_Sources} + ) +ENDIF(USE_QT4) + + +## ===================== +## = Compilation rules = +## ===================== + +ADD_LIBRARY( + ${LIBRARY_NAME} + SHARED + ${LIB_SOURCES_C} + ${LIB_SOURCES_CPP} + ${LIB_SOURCES_CXX} + ) +SET_TARGET_PROPERTIES( + ${LIBRARY_NAME} PROPERTIES + VERSION "${prj_VER}" + SOVERSION "${prj_sVER}" + ) +GENERATE_EXPORT_HEADER( + ${LIBRARY_NAME} + BASE_NAME ${LIBRARY_NAME} + EXPORT_MACRO_NAME ${LIBRARY_NAME}_EXPORT + EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/cpExtensions/${LIBRARY_NAME}_Export.h + STATIC_DEFINE ${LIBRARY_NAME}_BUILT_AS_STATIC + ) +TARGET_LINK_LIBRARIES( + ${LIBRARY_NAME} + ${QT_LIBRARIES} + ${ITK_LIBRARIES} + ${VTK_LIBRARIES} + ) + +## ======================== +## -- Installation rules -- +## ======================== + +INSTALL( + TARGETS ${LIBRARY_NAME} + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib/static + ) +INSTALL( + FILES + ${PROJECT_BINARY_DIR}/lib/cpExtensions/${LIBRARY_NAME}_Export.h + DESTINATION include/cpExtensions + ) + +## eof - $RCSfile$ diff --git a/lib/cpExtensions/Config.h.in b/lib/cpExtensions/Config.h.in new file mode 100644 index 0000000..dbf80e9 --- /dev/null +++ b/lib/cpExtensions/Config.h.in @@ -0,0 +1,20 @@ +#ifndef __CPEXTENSIONS__CONFIG__H__ +#define __CPEXTENSIONS__CONFIG__H__ + +#include + +#define cpExtensions_MAJ_VER @prj_MAJ_VER@ +#define cpExtensions_MIN_VER @prj_MIN_VER@ +#define cpExtensions_REL_VER @prj_VER@ +#define cpExtensions_VER "@prj_sVER@" + +#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 + +#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/ITKAndVTKImage.h b/lib/cpExtensions/DataStructures/ITKAndVTKImage.h new file mode 100644 index 0000000..dfcad3f --- /dev/null +++ b/lib/cpExtensions/DataStructures/ITKAndVTKImage.h @@ -0,0 +1,107 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__ITKANDVTKIMAGE__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__ITKANDVTKIMAGE__H__ + +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< typename P, unsigned int D > + struct ITKAndVTKImage + { + typedef itk::Image< P, D > TImage; + typedef itk::ImageToVTKImageFilter< TImage > TItk2Vtk; + + typename TImage::Pointer ITK; + typename TItk2Vtk::Pointer VTK; + + void CopyInformation( const itk::ImageBase< D >* i ) + { + this->ITK = TImage::New( ); + this->ITK->SetLargestPossibleRegion( i->GetLargestPossibleRegion( ) ); + this->ITK->SetRequestedRegion( i->GetRequestedRegion( ) ); + this->ITK->SetBufferedRegion( i->GetBufferedRegion( ) ); + this->ITK->SetSpacing( i->GetSpacing( ) ); + this->ITK->SetOrigin( i->GetOrigin( ) ); + this->ITK->SetDirection( i->GetDirection( ) ); + this->ITK->Allocate( ); + } + + void SetItkImage( TImage* image ) + { + this->ITK = image; + this->_Synch( ); + } + + std::string ReadFromFile( const std::string& filename ) + { + typename itk::ImageFileReader< TImage >::Pointer r = + itk::ImageFileReader< TImage >::New( ); + r->SetFileName( filename ); + try + { + r->Update( ); + } + catch( itk::ExceptionObject& err ) + { + this->ITK = NULL; + return( err.GetDescription( ) ); + + } // fi + this->ITK = r->GetOutput( ); + this->ITK->DisconnectPipeline( ); + this->_Synch( ); + return( "" ); + } + + std::string WriteToFile( const std::string& filename ) const + { + typename itk::ImageFileWriter< TImage >::Pointer w = + itk::ImageFileWriter< TImage >::New( ); + w->SetFileName( filename ); + w->SetInput( this->ITK ); + try + { + w->Update( ); + } + catch( itk::ExceptionObject& err ) + { + return( err.GetDescription( ) ); + + } // fi + return( "" ); + } + + TImage* GetItkImage( ) + { return( this->ITK ); } + vtkImageData* GetVtkImage( ) + { return( this->VTK->GetOutput( ) ); } + const TImage* GetItkImage( ) const + { return( this->ITK ); } + const vtkImageData* GetVtkImage( ) const + { return( this->VTK->GetOutput( ) ); } + void DisconnectPipeline( ) + { this->ITK->DisconnectPipeline( ); } + + void _Synch( ) + { + this->VTK = TItk2Vtk::New( ); + this->VTK->SetInput( this->ITK ); + this->VTK->Update( ); + } + + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__DATASTRUCTURES__ITKANDVTKIMAGE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.h b/lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.h new file mode 100644 index 0000000..2f61766 --- /dev/null +++ b/lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.h @@ -0,0 +1,88 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__INFINITEPLANESPATIALOBJECT__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__INFINITEPLANESPATIALOBJECT__H__ + +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< unsigned int D > + class InfinitePlaneSpatialObject + : public itk::SpatialObject< D > + { + public: + typedef InfinitePlaneSpatialObject Self; + typedef itk::SpatialObject< D > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef double ScalarType; + typedef typename Superclass::PointType PointType; + typedef typename Superclass::TransformType TransformType; + typedef typename Superclass::BoundingBoxType BoundingBoxType; + typedef typename PointType::VectorType VectorType; + + itkStaticConstMacro( NumberOfDimension, unsigned int, D ); + + public: + itkNewMacro( Self ); + itkTypeMacro( InfinitePlaneSpatialObject, itk::SpatialObject ); + + itkGetConstMacro( Center, PointType ); + itkGetConstMacro( Normal, VectorType ); + + public: + template< class P > + void SetCenter( const P& p ); + + template< class N > + void SetNormal( const N& n ); + + virtual bool ValueAt( + const PointType& point, double& value, + unsigned int depth = 0, char* name = NULL + ) const; + + virtual bool IsEvaluableAt( + const PointType& point, + unsigned int depth = 0, char* name = NULL + ) const; + + virtual bool IsInside( + const PointType& point, + unsigned int depth, char* name + ) const; + + virtual bool IsInside( const PointType& point ) const; + + virtual bool ComputeLocalBoundingBox( ) const; + + protected: + InfinitePlaneSpatialObject( ); + virtual ~InfinitePlaneSpatialObject( ); + virtual void PrintSelf( std::ostream& os, itk::Indent indent ) const; + + private: + // Purposely not implemented. + InfinitePlaneSpatialObject( const Self& other ); + Self& operator=( const Self& other ); + + protected: + PointType m_Center; + VectorType m_Normal; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__DATASTRUCTURES__INFINITEPLANESPATIALOBJECT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.hxx b/lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.hxx new file mode 100644 index 0000000..fd68815 --- /dev/null +++ b/lib/cpExtensions/DataStructures/InfinitePlaneSpatialObject.hxx @@ -0,0 +1,109 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__INFINITEPLANESPATIALOBJECT__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__INFINITEPLANESPATIALOBJECT__HXX__ + +// ------------------------------------------------------------------------- +template< unsigned int D > +template< class P > +void cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +SetCenter( const P& p ) +{ + for( unsigned int d = 0; d < D; ++d ) + this->m_Center[ d ] = ScalarType( p[ d ] ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +template< class N > +void cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +SetNormal( const N& n ) +{ + for( unsigned int d = 0; d < D; ++d ) + this->m_Normal[ d ] = ScalarType( n[ d ] ); + ScalarType nn = this->m_Normal.GetNorm( ); + if( nn > ScalarType( 0 ) ) + this->m_Normal /= nn; + this->Modified( ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +ValueAt( + const PointType& point, double& value, unsigned int depth, char* name + ) const +{ + value = this->m_Normal * ( point - this->m_Center ); + return( value >= double( 0 ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +IsEvaluableAt( + const PointType& point, unsigned int depth, char* name + ) const +{ + double value; + return( this->ValueAt( point, value, depth, name ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +IsInside( + const PointType& point, unsigned int depth, char* name + ) const +{ + double value; + return( this->ValueAt( point, value, depth, name ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +IsInside( const PointType& point ) const +{ + double value; + return( this->ValueAt( point, value, 0, NULL ) ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +ComputeLocalBoundingBox( ) const +{ + return( false ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +InfinitePlaneSpatialObject( ) + : Superclass( ) +{ + this->m_Center.Fill( ScalarType( 0 ) ); + this->m_Normal.Fill( ScalarType( 0 ) ); + this->m_Normal[ 0 ] = ScalarType( 1 ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +~InfinitePlaneSpatialObject( ) +{ +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +void cpExtensions::DataStructures::InfinitePlaneSpatialObject< D >:: +PrintSelf( std::ostream& os, itk::Indent indent ) const +{ + this->Superclass::PrintSelf( os, indent ); + os << indent << "Center: " << this->m_Center << std::endl; + os << indent << "Normal: " << this->m_Normal << std::endl; +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__INFINITEPLANESPATIALOBJECT__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdge.h b/lib/cpExtensions/DataStructures/QuadEdge.h new file mode 100644 index 0000000..bcb1f88 --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdge.h @@ -0,0 +1,471 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGE__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGE__H__ + +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< typename P, typename D, bool IsPrimal = true > + class QuadEdge + : public itk::LightObject + { + public: + typedef QuadEdge Self; + typedef itk::LightObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /// Vertices and faces types + typedef P TPrimalGeometry; + typedef D TDualGeometry; + + /** + * Dual type, basically the same type with swapped template + * parameters. + */ + typedef QuadEdge< D, P, !IsPrimal > TDual; + typedef Self TPrimal; + typedef typename TDual::Pointer PtrDual; + friend TDual; + + /// Iterators + typedef QuadEdgeIterator< TPrimal > Iterator; + typedef QuadEdgeConstIterator< TPrimal > ConstIterator; + typedef QuadEdgePointIterator< TPrimal > PointIterator; + typedef QuadEdgePointConstIterator< TPrimal > PointConstIterator; + + public: + itkNewMacro( Self ); + itkTypeMacro( QuadEdge, itkLightObject ); + + cpPluginsExtensionsQEAllIteratorsMacro( Onext ); + cpPluginsExtensionsQEAllIteratorsMacro( Lnext ); + cpPluginsExtensionsQEAllIteratorsMacro( Rnext ); + cpPluginsExtensionsQEAllIteratorsMacro( Dnext ); + cpPluginsExtensionsQEAllIteratorsMacro( Oprev ); + cpPluginsExtensionsQEAllIteratorsMacro( Lprev ); + cpPluginsExtensionsQEAllIteratorsMacro( Rprev ); + cpPluginsExtensionsQEAllIteratorsMacro( Dprev ); + + public: + void CreateRings( ); + + /// First order access methods + inline TPrimal* GetOnext( ) + { return( this->m_Onext ); } + inline TDual* GetRot( ) + { return( this->m_Rot ); } + inline const TPrimal* GetOnext( ) const + { return( this->m_Onext ); } + inline const TDual* GetRot( ) const + { return( this->m_Rot ); } + + /// First order configuration methods + inline void SetOnext( TPrimal* e ) + { this->m_Onext = e; } + inline void SetRot( TDual* e ) + { this->m_Rot = e; } + + /// Second order accessors: around base rings + inline TPrimal* GetSym( ) + { return( this->m_Rot->m_Rot ); } + inline TDual* GetInvRot( ) + { return( this->m_Rot->m_Rot->m_Rot ); } + + /// Second order accessors: neighboring topology + inline TPrimal* GetLnext( ) + { return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot ); } + inline TPrimal* GetRnext( ) + { return( this->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); } + inline TPrimal* GetDnext( ) + { return( this->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot ); } + inline TPrimal* GetOprev( ) + { return( this->m_Rot->m_Onext->m_Rot ); } + inline TPrimal* GetLprev( ) + { return( this->m_Onext->m_Rot->m_Rot ); } + inline TPrimal* GetRprev( ) + { return( this->m_Rot->m_Rot->m_Onext ); } + inline TPrimal* GetDprev( ) + { + return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); + } + + /// Second order accessors: around base rings (const versions) + inline const TPrimal* GetSym( ) const + { return( this->m_Rot->m_Rot ); } + inline const TDual* GetInvRot( ) const + { return( this->m_Rot->m_Rot->m_Rot ); } + + /// Second order accessors: neighboring topology (const versions) + inline const TPrimal* GetLnext( ) const + { return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot ); } + inline const TPrimal* GetRnext( ) const + { return( this->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); } + inline const TPrimal* GetDnext( ) const + { return( this->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot ); } + inline const TPrimal* GetOprev( ) const + { return( this->m_Rot->m_Onext->m_Rot ); } + inline const TPrimal* GetLprev( ) const + { return( this->m_Onext->m_Rot->m_Rot ); } + inline const TPrimal* GetRprev( ) const + { return( this->m_Rot->m_Rot->m_Onext ); } + inline const TPrimal* GetDprev( ) const + { + return( this->m_Rot->m_Rot->m_Rot->m_Onext->m_Rot->m_Rot->m_Rot ); + } + + /// Get geometry methods + inline P& GetOrigin( ) + { return ( this->m_Origin ); } + inline P& GetDestination( ) + { return ( this->m_Rot->m_Rot->m_Origin ); } + inline D& GetRight( ) + { return ( this->m_Rot->m_Origin ); } + inline D& GetLeft( ) + { return ( this->m_Rot->m_Rot->m_Rot->m_Origin ); } + + /// Get geometry methods (const versions) + inline const P& GetOrigin( ) const + { return ( this->m_Origin ); } + inline const P& GetDestination( ) const + { return ( this->m_Rot->m_Rot->m_Origin ); } + inline const D& GetRight( ) const + { return ( this->m_Rot->m_Origin ); } + inline const D& GetLeft( ) const + { return ( this->m_Rot->m_Rot->m_Rot->m_Origin ); } + + /// Set geometry methods + inline void SetOrigin( const P& v ) + { this->m_Origin = v; } + inline void SetDestination( const P& v ) + { this->m_Rot->m_Rot->m_Origin = v; } + inline void SetRight( const D& v ) + { this->m_Rot->m_Origin = v; } + inline void SetLeft( const D& v ) + { this->m_Rot->m_Rot->m_Rot->m_Origin = v; } + inline void UnsetOrigin( ) + { this->m_Origin = TPrimal::NoGeometry; } + inline void UnsetDestination( ) + { this->m_Rot->m_Rot->m_Origin = TPrimal::NoGeometry; } + inline void UnsetRight( ) + { this->m_Rot->m_Origin = TDual::NoGeometry; } + inline void UnsetLeft( ) + { this->m_Rot->m_Rot->m_Rot->m_Origin = TDual::NoGeometry; } + + /** + * Set the Left( ) of all the edges in the Lnext( ) ring of "this" + * with the same given geometrical information. + * @param faceGeom Looks at most maxSize edges in the Lnext( ) ring. + * @return Returns true on success. False otherwise. + */ + void SetLnextRingGeometry( const D& v ); + void UnsetLnextRingGeometry( ); + + /// Topological queries + inline bool IsIsolated( ) const + { return( this == this->m_Onext ); } + bool IsEdgeInOnextRing( const TPrimal* e ) const; + bool IsEdgeInLnextRing( const TPrimal* e ) const; + unsigned int GetOnextRingSize( ) const; + unsigned int GetLnextRingSize( ) const; + + /** + * @return Returns true when "this" has no faces set on both sides. + * Return false otherwise. + */ + inline bool IsWire( ) + { return( !( this->IsLeftSet( ) ) && !( this->IsRightSet( ) ) ); } + + /** + * @return Returns true when "this" is on the boundary i.e. + * one and only one of the faces is set. Return false + * otherwise. + */ + inline bool IsAtBorder( ) const; + + /** + * @return Returns true when "this" has faces set on both sides. + * Return false otherwise. + */ + inline bool IsInternal( ) const + { return ( this->IsLeftSet( ) && this->IsRightSet( ) ); } + + /// Geometrical queries + inline bool IsOriginSet( ) const + { return ( this->m_Origin != Self::NoGeometry ); } + inline bool IsDestinationSet( ) const + { return ( this->m_Rot->m_Rot->IsOriginSet( ) ); } + inline bool IsRightSet( ) const + { return ( this->m_Rot->IsOriginSet( ) ); } + inline bool IsLeftSet( ) const + { return ( this->m_Rot->m_Rot->m_Rot->IsOriginSet( ) ); } + + /** + * \brief Check wether edge's Origin is internal to the mesh (as + * opposed to being on the boundary) by looking if all the edges + * in the Onext() ring have a face set on both their Left() and + * Right() side. + */ + bool IsOriginInternal( ) const; + + /** + * Definition: an edge is said to be a boundary edge when it is + * adjacent to i.e. when at least one of the faces edge->GetLeft() or + * edge->GetRight() is unset. Definition: an point is said to be a + * boundary point when at least one of the edges of it's Onext() ring + * is a boundary edge. + * + * Assume "this" edge belongs to a triangulation (i.e. it belongs to a + * QEMesh which represents a 2-manifold) which possesses a boundary. + * Assume "this" edge instance is a boundary edge. Let us denote by P + * the point which is the origin of "this" edge i.e. P is + * this->Origin(). By definition P is a boundary point. Then AT + * LEAST two [see the note below] edges of the Onext() ring of P + * [which all have the point P as Origin()] are themselves boundary + * edges. And among those boundary edges AT LEAST one has it's Left() + * face unset. By iterating over the Onext() ring (which defines a + * local ordering on edges) this method searches for the first edge + * whose Left() face is unset AND which is encountered AFTER edgeTest. + * + * @param edgeTest When present, this edge will be considered as + * the entry edge in the Onext() ring. When absent it shall + * be defaulted to "this" edge. (see the warning below). + * @return When "this" edge is a boundary edge, return the first + * edge in "this" Onext() ring whose Left() face is unset + * AND located after edgeTest. + * When "this" edge is NOT a boundary edge the 0 is + * returned. + * @warning When the Mesh possessing "this" edge is a 2-manifold + * then result of this method is unique in the sense that + * it is independent from the edgeTest parameter. + * But when the Mesh is not 2-manifold (this state can + * happen at intermediary stages of the building process, + * or during "surgical" operations on the Mesh, and + * even though the Mesh represents a triangulation) + * the result of this method is not unique in the sense + * that the result depends on the edgeTest parameter. + * Let us illusatre this dependence by considering a + * Mesh (which is a triangulation) which is not a 2-manifold. + * Assume the point P (the origin of "this" edge i.e. + * P = this->Originv()) is TWICE on the border i.e. it + * is adjacent twice to noface. We can consider the situation + * of the following diagram, which depicts some Onext() + * ring around point P: + * + * \ / // + * \ * / // + * i3 b2 counter-clockwise // + * * \ / NO FACE Onext() order. // + * \ / // + * ----b4-----P----b1------ // + * /|\ // + * NO FACE / | \ // + * / | \ * <------ a * indicates the // + * / | \ the presence of a face // + * / | \ // + * b5 i6 i7 // + * / * | * \ // + * / | \ // + * + * On this example, and if we assume the Onext() oder is + * represented counter-clockwise, the edges are ordered as + * follows: + * b1, b2, i3, b4, b5, i6, i7 + * (when arbitrarily starting at edge b1). + * We have four Boundary edges labeled b1, b2, b4, b5 and + * we have three internal edges (i.e. non boundary edges) + * labeled i3, i6 and i7. + * Depending on edgeTest, the result of this method + * will NOT return the same edge: + * - when edgeTest == b5 (or i6 or i7 or b1) then the edge + * b1 will be returned, + * - when edgeTest == b2 (or i3 or b4) then the edge + * b4 will be returned, + * Eventually, when edgeTest is absent, the result shall + * depend on the position of "this" in the Onext() ring(). + * + */ + TPrimal* GetNextBorderEdgeWithUnsetLeft( TPrimal* edge = NULL ) const; + + /** + * Assume "this->Originv()" is a boundary point P that is thrice + * adjacent to noface and consider the given situation is the one + * depicted by the following diagram where: + * - P is "this->Originv()" instance, + * - the * (star) indicates the presence of a face, + * - b1, b2, b3, b4, b5, b6 denote boundary edges, + * - p denotes some generic point, + * - A and B denote some specific points we want to discuss, + * - the Onext() ring order is represented counter-clockwise + * [which is coherent with the definition of edge->GetRigth()] + * i.e. the ordering of the edges is: + * b1, b2, b3, b4, b5, b6, b1... + * + * p N p + * / \ O / \ // + * / \ / \ // + * / \ F / \ counter-clockwise // + * / b3 A b2 \ Onext() ring order // + * / \ C / \ // + * / * \ E / * \ // + * / \ / \ // + * A------b4------P------b1-------B // + * / \ // + * / \ // + * NO FACE / \ NO FACE // + * / \ // + * b5 b6 // + * / * \ // + * / \ // + * p---------------p // + * + * At P this Mesh doesn't represent a 2-manifold (since we are thrice + * on the boundary). Nevertheless such a situation could arise in + * intermediary stages (e.g. when building the Mesh, or during + * surgical changes on the Mesh). + * Now, assume we are asked to build the triangle [P, A, B]. Note + * that this request is not absurd since the current situation at + * P isn't the one of a 2-manifold: hence when building the current + * Onext() ring of P, we had not enough information to decide + * wheter b4.Onext() should be b5 or b1. It is ONLY when we are + * required to build the triangle [P, A, B] that we have the + * additional information that b4.Onext() is indeed b1. + * When we are required to build triangle [P, A, B], we hence + * need to change the Onext() ring order at P, i.e. we need to deal + * with the triangle [P, b5, b6] which currently prevents + * b4.Onext() to be b1. In other terms, when considering the + * additional information that b4.Onext() is b1, and before + * building the triangle [P, A, B], we need to reorder + * the Onext() ring of P from it's current state + * b1, b2, b3, b4, b5, b6, b1... + * to an order coherent with the [P, A, B] request, i.e. + * b1, b2, b5, b6, b3, b4, b1... + * + * In order to establish the "proper" Onext() ring at P we use + * two Splice operations. The algorithm goes: + * - first disconnect the piece of the surface containing the edge + * [PB] (it would be the same process if we chose [PA]) from + * the Onext() ring at P. + * - second, re-integrate the disconnected piece at the desired + * location i.e. side by side with [PA] (respectively [PB] if + * we chose [PA] at first stage). + * By "piece of surface containing the edge [PB]" we mean [all] + * the triangle[s] starting at [PB] in the Onext() order and + * having a left face set. + * + * We can illustrate this process on bit more general diagram than + * the last case (where the "piece of surface containing the edge + * [PB]" is constituted by two triangles) and when using + * the arguments of this method (i.e. [PA] = this and [PB] = second). + * The initial stage is the following (we note first=this=[PA] and + * second=[PB]) where the Onext() ring order is: + * first, b2, b3, second, b5, bsplice, b7, first... + * + * p N A // + * / \ O / \ // + * / \ / \ // + * / \ F / \ counter-clockwise // + * / b2 A first \ Onext() ring order // + * / \ C / \ // + * / * \ E / * \ // + * / \ / \ // + * p-------b3------P------b7-------p // + * /|\ // + * / | \ // + * NO FACE / | \ NO FACE // + * / | \ // + * second b5 bsplice // + * / * | * \ // + * / | \ // + * B-------p-------p // + * + * The first stage, implemented as + * second->Oprev()->Splice( bsplice ), + * yields the following diagram: + * + * p N A // + * / \ O / \ // + * / \ F / \ // + * / \ A / \ counter-clockwise // + * / b2 C first \ Onext() ring order // + * / \ E / \ // + * / * \ / * \ // + * / \ / \ // + * p-------b3------P------b7-------p // + * // + * NO FACE // + * // + * /|\ // + * / | \ // + * / | \ // + * / | \ // + * second b5 bsplice // + * / * | * \ // + * / | \ // + * B-------p-------p // + * + * and the second stage, implemented as + * first->Splice( bsplice ), + * yields the following diagram: + * + * A // + * B__ NO FACE / \ // + * | \__ / \ // + * | \__ / \ counter- // + * | second first \ clockwise for all // + * | \__ / \ // + * | * \__ / * \ // + * | \ / \ // + * p-------b5---------P------b7-------p // + * | __/|\ // + * | * __/ | \ // + * | / | \ NO FACE // + * | bsplice | \ // + * | __/ b2 b3 // + * p__/ | * \ // + * NO FACE | \ // + * p-------p // + * + */ + inline static bool ReorderOnextRing( TPrimal* first, TPrimal* second ); + + /** + * \brief Basic quad-edge topological method. + * + * This method describes all possible topological operations on an + * edge since it is its own inverse. It works in two ways: + * + * 1. If this->m_Org != b->m_Org, it slice a face in two. + * 2. If this->m_Org == b->m_Org, it unifies two faces. + */ + inline static void Splice( TPrimal* a, TPrimal* b ); + + protected: + QuadEdge( ); + virtual ~QuadEdge( ); + + public: + static const TPrimalGeometry NoGeometry; + + protected: + Pointer m_Onext; /**< Onext ring */ + PtrDual m_Rot; /**< Rot ring */ + TPrimalGeometry m_Origin; /**< Geometry attached to edge's origin */ + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdge.hxx b/lib/cpExtensions/DataStructures/QuadEdge.hxx new file mode 100644 index 0000000..a0e0e25 --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdge.hxx @@ -0,0 +1,241 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGE__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGE__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +const typename cpExtensions::DataStructures:: +QuadEdge< P, D, IsPrimal >::TPrimalGeometry +cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +NoGeometry = std::numeric_limits< P >::max( ); + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +void cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +CreateRings( ) +{ + TPrimal* e = this; + PtrDual r = TDual::New( ); + Pointer s = Self::New( ); + PtrDual i = TDual::New( ); + + // Create Rot ring + e->m_Rot = r; + r->m_Rot = s; + s->m_Rot = i; + i->m_Rot = e; + + // Update Onext rings + r->m_Onext = i; + i->m_Onext = r; +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +void cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +SetLnextRingGeometry( const D& v ) +{ + for( Iterator i = this->BeginLnext( ); i != this->EndLnext( ); ++i ) + ( *i )->SetLeft( v ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +void cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +UnsetLnextRingGeometry( ) +{ + this->SetLnextRingGeometry( TDual::NoGeometry ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +bool cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +IsEdgeInOnextRing( const TPrimal* e ) const +{ + bool found = false; + for( + ConstIterator i = this->BeginOnext( ); + i != this->EndOnext( ) && !found; + ++i + ) + found |= ( *i == e ); + return( found ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +bool cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +IsEdgeInLnextRing( const TPrimal* e ) const +{ + bool found = false; + for( + ConstIterator i = this->BeginLnext( ); + i != this->EndLnext( ) && !found; + ++i + ) + found |= ( *i == e ); + return( found ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +unsigned int +cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +GetOnextRingSize( ) const +{ + unsigned int count = 0; + for( + ConstIterator i = this->BeginOnext( ); + i != this->EndOnext( ); + ++i + ) + count++; + return( count ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +unsigned int +cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +GetLnextRingSize( ) const +{ + unsigned int count = 0; + for( + ConstIterator i = this->BeginLnext( ); + i != this->EndLnext( ); + ++i + ) + count++; + return( count ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +bool cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +IsAtBorder( ) const +{ + return( + ( this->IsLeftSet( ) && !( this->IsRightSet( ) ) ) || + ( !( this->IsLeftSet( ) ) && this->IsRightSet( ) ) + ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +bool cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +IsOriginInternal( ) const +{ + bool internal = true; + for( + ConstIterator i = this->BeginOnext( ); + i != this->EndOnext( ) && internal; + ++i + ) + internal &= ( *i )->IsInternal( ); + return( internal ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +typename cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +TPrimal* cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +GetNextBorderEdgeWithUnsetLeft( TPrimal* edge ) const +{ + // Be sure the Onext ring isn't already full + if( this->IsOriginInternal( ) ) + return( NULL ); + + // Update reference + edge = ( edge == NULL )? const_cast< TPrimal* >( this ): edge; + + // On efficiency purposes + if( edge->IsIsolated( ) ) + return( edge ); + + // Ok, no more special cases + const TPrimal* cedge = const_cast< const TPrimal* >( edge ); + ConstIterator it = cedge->BeginOnext( ); + TPrimal* found = NULL; + for( ; it != cedge->EndOnext( ) && found == NULL; ++it ) + if( !( ( *it )->IsLeftSet( ) ) ) + found = const_cast< TPrimal* >( *it ); + return( found ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +bool cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +ReorderOnextRing( TPrimal* first, TPrimal* second ) +{ + // Making sure point adjacency is correct: + if( first->GetOrigin( ) != second->GetOrigin( ) ) + return( false ); + + if( first->GetOnext( ) == second ) + return( true ); + + if( first->IsLeftSet( ) ) + return( false ); + + // Second is an internal edge. + if( second->IsInternal( ) ) + return( false ); + + // Disconnect the triangles containing second: + TPrimal* bsplice; + if( second->IsLeftSet( ) ) + bsplice = second->GetNextBorderEdgeWithUnsetLeft( ); + else + bsplice = second; + TPrimal::Splice( second->GetOprev( ), bsplice ); + + // Reconnect second after first: + TPrimal::Splice( first, bsplice ); + return( true ); +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +void cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +Splice( TPrimal* a, TPrimal* b ) +{ + // Don't waste time splicing the same edge (or non-existent) + // remember: it is its own inverse! + if( a != b || a == NULL || b == NULL ) + { + TPrimal* aNext = a->m_Onext; + TPrimal* bNext = b->m_Onext; + TDual* al = aNext->m_Rot; + TDual* be = bNext->m_Rot; + TDual* alNext = al->m_Onext; + TDual* beNext = be->m_Onext; + + a->SetOnext( bNext ); + b->SetOnext( aNext ); + al->SetOnext( beNext ); + be->SetOnext( alNext ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +QuadEdge( ) + : m_Origin( Self::NoGeometry ) +{ + this->m_Onext = this; + this->m_Rot = NULL; +} + +// ------------------------------------------------------------------------- +template< typename P, typename D, bool IsPrimal > +cpExtensions::DataStructures::QuadEdge< P, D, IsPrimal >:: +~QuadEdge( ) +{ +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdgeCell.h b/lib/cpExtensions/DataStructures/QuadEdgeCell.h new file mode 100644 index 0000000..84ae92f --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdgeCell.h @@ -0,0 +1,126 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGECELL__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGECELL__H__ + +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< class I, class E > + class QuadEdgeCell + : public I + { + public: + // Base types + typedef QuadEdgeCell Self; + typedef I Superclass; + typedef itk::AutoPointer< Self > SelfAutoPointer; + typedef itk::AutoPointer< const Self > ConstSelfAutoPointer; + typedef Self* RawPointer; + typedef const Self* ConstRawPointer; + + // QuadEdge objects + typedef E TPrimalEdge; + typedef typename E::TDual TDualEdge; + + // Inherited types + typedef typename I::PixelType PixelType; + typedef typename I::CellType CellType; + typedef typename I::CellAutoPointer CellAutoPointer; + typedef typename I::CellConstAutoPointer CellConstAutoPointer; + typedef typename I::CellRawPointer CellRawPointer; + typedef typename I::CellConstRawPointer CellConstRawPointer; + typedef typename I::CellTraits CellTraits; + typedef typename I::CoordRepType CoordRepType; + typedef typename I::InterpolationWeightType InterpolationWeightType; + typedef typename I::PointIdentifier PointIdentifier; + typedef typename I::PointIdIterator PointIdIterator; + typedef typename I::PointIdConstIterator PointIdConstIterator; + typedef typename I::CellIdentifier CellIdentifier; + typedef typename I::CellFeatureIdentifier CellFeatureIdentifier; + typedef typename I::CellFeatureIdentifier CellFeatureCount; + typedef typename I::PointType PointType; + typedef typename I::VectorType VectorType; + typedef typename I::PointsContainer PointsContainer; + typedef typename I::UsingCellsContainer UsingCellsContainer; + typedef typename I::CellGeometry CellGeometry; + typedef typename I::ParametricCoordArrayType ParametricCoordArrayType; + typedef typename I::ShapeFunctionsArrayType ShapeFunctionsArrayType; + + itkStaticConstMacro( PointDimension, unsigned int, I::PointDimension ); + itkStaticConstMacro( CellDimension, unsigned int, 2 ); + + public: + itkTypeMacro( QuadEdgeCell, I ); + + public: + QuadEdgeCell( ); + QuadEdgeCell( E* entry ); + virtual ~QuadEdgeCell( ); + + /// Implement the standard CellInterface. + virtual CellGeometry GetType( ) const; + virtual void MakeCopy( CellAutoPointer& other ) const; + virtual unsigned int GetDimension( ) const; + virtual unsigned int GetNumberOfPoints( ) const; + virtual CellFeatureCount GetNumberOfBoundaryFeatures( + int dimension + ) const; + virtual bool GetBoundaryFeature( + int dimension, CellFeatureIdentifier fId, CellAutoPointer& ptr + ); + virtual void SetPointIds( PointIdConstIterator first ); + virtual void SetPointIds( + PointIdConstIterator first, PointIdConstIterator last + ); + virtual void AddPointId( PointIdentifier pId ); + virtual void RemovePointId( PointIdentifier pId ); + virtual void SetPointIds( + int dummy, int num, PointIdConstIterator first + ); + virtual void BuildEdges( ); + virtual void ClearPoints( ); + virtual void SetPointId( int localId, PointIdentifier pId ); + + // Visitor methods + static int GetTopologyId( ); + virtual void Accept( + CellIdentifier cellid, + typename itk::CellInterface< PixelType, CellTraits >:: + MultiVisitor* mv + ); + + // Iterators + virtual PointIdIterator PointIdsBegin( ); + virtual PointIdConstIterator PointIdsBegin( ) const; + virtual PointIdIterator PointIdsEnd( ); + virtual PointIdConstIterator PointIdsEnd( ) const; + + /// QuadEdgeCell-specific interface. + virtual E* GetEntryPrimalEdge( ); + virtual const E* GetEntryPrimalEdge( ) const; + virtual void SetEntryPrimalEdge( E* entry ); + + private: + /// Purposely not implemented. + QuadEdgeCell( const Self& ); + Self& operator=( const Self& ); + + protected: + E* m_EntryEdge; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGECELL__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdgeCell.hxx b/lib/cpExtensions/DataStructures/QuadEdgeCell.hxx new file mode 100644 index 0000000..7713b3e --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdgeCell.hxx @@ -0,0 +1,258 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGECELL__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGECELL__HXX__ + +// ------------------------------------------------------------------------- +template< class I, class E > +cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +QuadEdgeCell( ) + : Superclass( ), + m_EntryEdge( NULL ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class E > +cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +QuadEdgeCell( E* entry ) + : Superclass( ), + m_EntryEdge( entry ) +{ + this->SetEntryPrimalEdge( entry ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +~QuadEdgeCell( ) +{ +} + +// ------------------------------------------------------------------------- +template< class I, class E > +typename cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +CellGeometry cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetType( ) const +{ + std::cout << "QuadEdgeCell GetType" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +MakeCopy( CellAutoPointer& other ) const +{ + std::cout << "QuadEdgeCell MakeCopy" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +unsigned int cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetDimension( ) const +{ + std::cout << "QuadEdgeCell GetDimension" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +unsigned int cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetNumberOfPoints( ) const +{ + return( this->m_EntryEdge->GetLnextRingSize( ) ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +typename cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +CellFeatureCount cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetNumberOfBoundaryFeatures( int dimension ) const +{ + std::cout << "QuadEdgeCell GetNumberOfBoundaryFeatures" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +bool cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetBoundaryFeature( + int dimension, + CellFeatureIdentifier fId, + CellAutoPointer& ptr + ) +{ + std::cout << "QuadEdgeCell GetBoundaryFeature" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +SetPointIds( PointIdConstIterator first ) +{ + std::cout << "QuadEdgeCell SetPointIds" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +SetPointIds( + PointIdConstIterator first, + PointIdConstIterator last + ) +{ + std::cout << "QuadEdgeCell SetPointIds(first,last)" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +AddPointId( PointIdentifier pId ) +{ + std::cout << "QuadEdgeCell AddPointId" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +RemovePointId( PointIdentifier pId ) +{ + std::cout << "QuadEdgeCell RemovePointId" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +SetPointIds( + int dummy, + int num, + PointIdConstIterator first + ) +{ + std::cout << "QuadEdgeCell SetPointIds(dummy,num,first)" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +BuildEdges( ) +{ + std::cout << "QuadEdgeCell BuildEdges" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +ClearPoints( ) +{ + std::cout << "QuadEdgeCell ClearPoints" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +SetPointId( int localId, PointIdentifier pId ) +{ + std::cout << "QuadEdgeCell SetPointId(localId,pId)" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +int cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetTopologyId( ) +{ + // TODO: return( Superclass::POLYGON_CELL ); + std::cout << "QuadEdgeCell GetTopologyId" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +Accept( + CellIdentifier cellid, + typename itk::CellInterface< PixelType, CellTraits >::MultiVisitor* mv + ) +{ + std::cout << "QuadEdgeCell Accept" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +typename cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdIterator cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdsBegin( ) +{ + std::cout << "QuadEdgeCell PointIdsBegin" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +typename cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdConstIterator +cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdsBegin( ) const +{ + std::cout << "QuadEdgeCell PointIdsBegin (const)" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +typename cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdIterator cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdsEnd( ) +{ + std::cout << "QuadEdgeCell PointIdsEnd" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +typename cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdConstIterator +cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +PointIdsEnd( ) const +{ + std::cout << "QuadEdgeCell PointIdsEnd (const)" << std::endl; + std::exit( 1 ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +E* cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetEntryPrimalEdge( ) +{ + return( this->m_EntryEdge ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +const E* cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +GetEntryPrimalEdge( ) const +{ + return( this->m_EntryEdge ); +} + +// ------------------------------------------------------------------------- +template< class I, class E > +void cpExtensions::DataStructures::QuadEdgeCell< I, E >:: +SetEntryPrimalEdge( E* entry ) +{ + this->m_EntryEdge = entry; +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGECELL__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdgeIterators.h b/lib/cpExtensions/DataStructures/QuadEdgeIterators.h new file mode 100644 index 0000000..c82ac34 --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdgeIterators.h @@ -0,0 +1,173 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEITERATORS__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEITERATORS__H__ + +#include + +// ------------------------------------------------------------------------- +#define cpPluginsQEIteratorsMacro( op, it, cit ) \ + inline it Begin##op( ) \ + { return( it( this, it::Op##op, true ) ); } \ + inline it End##op( ) \ + { return( it( this, it::Op##op, false ) ); } \ + inline cit Begin##op( ) const \ + { return( cit( this, cit::Op##op, true ) ); } \ + inline cit End##op( ) const \ + { return( cit( this, cit::Op##op, false ) ); } + +// ------------------------------------------------------------------------- +#define cpPluginsExtensionsQEPointIteratorsMacro( op, it, cit ) \ + inline Point##it BeginPoint##op( ) \ + { return( Point##it( this, it::Op##op, true ) ); } \ + inline Point##it EndPoint##op( ) \ + { return( Point##it( this, it::Op##op, false ) ); } \ + inline Point##cit BeginPoint##op( ) const \ + { return( Point##cit( this, cit::Op##op, true ) ); } \ + inline Point##cit EndPoint ##op( ) const \ + { return( Point##cit( this, cit::Op##op, false ) ); } + +// ------------------------------------------------------------------------- +#define cpPluginsExtensionsQEAllIteratorsMacro( op ) \ + cpPluginsQEIteratorsMacro( op, Iterator, ConstIterator ); \ + cpPluginsExtensionsQEPointIteratorsMacro( op, Iterator, ConstIterator ); + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< class E > + class QuadEdgeBaseIterator + { + public: + typedef QuadEdgeBaseIterator Self; + typedef E TQuadEdge; + + // Different types of logical iterators + enum + { + OpOnext = 0, + OpLnext = 1, + OpRnext = 2, + OpDnext = 3, + OpOprev = 4, + OpLprev = 5, + OpRprev = 6, + OpDprev = 7 + }; + + public: + QuadEdgeBaseIterator( E* e, int op = OpOnext, bool start = true ); + virtual ~QuadEdgeBaseIterator( ); + Self& operator=( const Self& r ); + + E* GetStartEdge( ) const; + E* GetIterator( ) const; + int GetOpType( ) const; + bool GetStart( ) const; + + bool operator==( Self& r ); + bool operator==( const Self& r ) const; + bool operator!=( Self& r ); + bool operator!=( const Self& r ) const; + Self& operator++( ); + Self& operator++( int ); + + protected: + /// Method that should do all the iteration work + virtual void _GoToNext( ); + + protected: + E* m_StartEdge; /**< Start edge */ + E* m_Iterator; /**< Current iteration position */ + int m_OpType; /**< Operation type */ + bool m_Start; /**< Indicates iteration has just started */ + }; + + /** + */ + template< class E > + class QuadEdgeIterator + : public QuadEdgeBaseIterator< E > + { + public: + typedef QuadEdgeIterator Self; + typedef QuadEdgeBaseIterator< E > Superclass; + typedef E TQuadEdge; + + public: + QuadEdgeIterator( + E* e = NULL, int op = Superclass::OpOnext, bool start = true + ); + virtual ~QuadEdgeIterator( ); + E* operator*( ); + }; + + /** + */ + template< class E > + class QuadEdgeConstIterator + : public QuadEdgeBaseIterator< const E > + { + public: + typedef QuadEdgeConstIterator Self; + typedef QuadEdgeBaseIterator< const E > Superclass; + typedef E TQuadEdge; + + public: + QuadEdgeConstIterator( + const E* e = NULL, int op = Superclass::OpOnext, bool start = true + ); + virtual ~QuadEdgeConstIterator( ); + const E* operator*( ) const; + }; + + /** + */ + template< class E > + class QuadEdgePointIterator + : public QuadEdgeBaseIterator< const E > + { + public: + typedef QuadEdgePointIterator Self; + typedef QuadEdgeBaseIterator< const E > Superclass; + typedef E TQuadEdge; + + public: + QuadEdgePointIterator( + const E* e = NULL, int op = Superclass::OpOnext, bool start = true + ); + virtual ~QuadEdgePointIterator( ); + typename E::TPrimalGeometry& operator*( ); + }; + + /** + */ + template< class E > + class QuadEdgePointConstIterator + : public QuadEdgeBaseIterator< const E > + { + public: + typedef QuadEdgePointConstIterator Self; + typedef QuadEdgeBaseIterator< const E > Superclass; + typedef E TQuadEdge; + + public: + QuadEdgePointConstIterator( + const E* e = NULL, int op = Superclass::OpOnext, bool start = true + ); + virtual ~QuadEdgePointConstIterator( ); + const typename E::TPrimalGeometry& operator*( ) const; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEITERATORS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdgeIterators.hxx b/lib/cpExtensions/DataStructures/QuadEdgeIterators.hxx new file mode 100644 index 0000000..3255e0d --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdgeIterators.hxx @@ -0,0 +1,275 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEITERATORS__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEITERATORS__HXX__ + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +QuadEdgeBaseIterator( E* e, int op, bool start ) + : m_StartEdge( e ), + m_Iterator( e ), + m_OpType( op ), + m_Start( start ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +~QuadEdgeBaseIterator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +typename cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +Self& cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator=( const Self& r ) +{ + if( this != &r ) + { + this->m_StartEdge = r.m_StartEdge; + this->m_Iterator = r.m_Iterator; + this->m_OpType = r.m_OpType; + this->m_Start = r.m_Start; + + } // fi + return( *this ); +} + +// ------------------------------------------------------------------------- +template< class E > +E* cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +GetStartEdge( ) const +{ + return( this->m_StartEdge ); +} + +// ------------------------------------------------------------------------- +template< class E > +E* cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +GetIterator( ) const +{ + return( this->m_Iterator ); +} + +// ------------------------------------------------------------------------- +template< class E > +int cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +GetOpType( ) const +{ + return( this->m_OpType ); +} + +// ------------------------------------------------------------------------- +template< class E > +bool cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +GetStart( ) const +{ + return( this->m_Start ); +} + +// ------------------------------------------------------------------------- +template< class E > +bool cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator==( Self& r ) +{ + return( + ( this->m_StartEdge == r.m_StartEdge ) && + ( this->m_Iterator == r.m_Iterator ) && + ( this->m_OpType == r.m_OpType ) && + ( this->m_Start == r.m_Start ) + ); +} + +// ------------------------------------------------------------------------- +template< class E > +bool cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator==( const Self& r ) const +{ + return( + ( this->m_StartEdge == r.m_StartEdge ) && + ( this->m_Iterator == r.m_Iterator ) && + ( this->m_OpType == r.m_OpType ) && + ( this->m_Start == r.m_Start ) + ); +} + +// ------------------------------------------------------------------------- +template< class E > +bool cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator!=( Self& r ) +{ + return( !( this->operator==( r ) ) ); +} + +// ------------------------------------------------------------------------- +template< class E > +bool cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator!=( const Self& r ) const +{ + return( !( this->operator==( r ) ) ); +} + +// ------------------------------------------------------------------------- +template< class E > +typename cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +Self& cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator++( ) +{ + if( this->m_Start ) + { + this->_GoToNext( ); + this->m_Start = !( this->m_Iterator == this->m_StartEdge ); + + } // fi + return( *this ); +} + +// ------------------------------------------------------------------------- +template< class E > +typename cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +Self& cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +operator++( int ) +{ + if( this->m_Start ) + { + this->_GoToNext( ); + this->m_Start = !( this->m_Iterator == this->m_StartEdge ); + + } // fi + return( *this ); +} + +// ------------------------------------------------------------------------- +template< class E > +void cpExtensions::DataStructures::QuadEdgeBaseIterator< E >:: +_GoToNext( ) +{ + switch( this->m_OpType ) + { + case Self::OpOnext: + this->m_Iterator = this->m_Iterator->GetOnext( ); + break; + case Self::OpLnext: + this->m_Iterator = this->m_Iterator->GetLnext( ); + break; + case Self::OpRnext: + this->m_Iterator = this->m_Iterator->GetRnext( ); + break; + case Self::OpDnext: + this->m_Iterator = this->m_Iterator->GetDnext( ); + break; + case Self::OpOprev: + this->m_Iterator = this->m_Iterator->GetOprev( ); + break; + case Self::OpLprev: + this->m_Iterator = this->m_Iterator->GetLprev( ); + break; + case Self::OpRprev: + this->m_Iterator = this->m_Iterator->GetRprev( ); + break; + case Self::OpDprev: + this->m_Iterator = this->m_Iterator->GetDprev( ); + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgeIterator< E >:: +QuadEdgeIterator( E* e, int op, bool start ) + : Superclass( e, op, start ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgeIterator< E >:: +~QuadEdgeIterator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +E* cpExtensions::DataStructures::QuadEdgeIterator< E >:: +operator*( ) +{ + return( this->m_Iterator ); +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgeConstIterator< E >:: +QuadEdgeConstIterator( const E* e, int op, bool start ) + : Superclass( e, op, start ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgeConstIterator< E >:: +~QuadEdgeConstIterator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +const E* cpExtensions::DataStructures::QuadEdgeConstIterator< E >:: +operator*( ) const +{ + return( this->m_Iterator ); +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgePointIterator< E >:: +QuadEdgePointIterator( const E* e, int op, bool start ) + : Superclass( e, op, start ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgePointIterator< E >:: +~QuadEdgePointIterator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +typename E::TPrimalGeometry& +cpExtensions::DataStructures::QuadEdgePointIterator< E >:: +operator*( ) +{ + return( this->m_Iterator->GetOrigin( ) ); +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgePointConstIterator< E >:: +QuadEdgePointConstIterator( const E* e, int op, bool start ) + : Superclass( e, op, start ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +cpExtensions::DataStructures::QuadEdgePointConstIterator< E >:: +~QuadEdgePointConstIterator( ) +{ +} + +// ------------------------------------------------------------------------- +template< class E > +const typename E::TPrimalGeometry& +cpExtensions::DataStructures::QuadEdgePointConstIterator< E >:: +operator*( ) const +{ + return( this->m_Iterator->GetOrigin( ) ); +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEITERATORS__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdgeMesh.h b/lib/cpExtensions/DataStructures/QuadEdgeMesh.h new file mode 100644 index 0000000..40cdf1f --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdgeMesh.h @@ -0,0 +1,285 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEMESH__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEMESH__H__ + +#include +#include + +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< typename P, unsigned int D = 3, typename T = itk::DefaultStaticMeshTraits< P, D, D > > + class QuadEdgeMesh + : public itk::Mesh< P, D, T > + { + public: + typedef QuadEdgeMesh Self; + typedef itk::Mesh< P, D, T > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + /// Types from superclass + typedef typename + Superclass::BoundaryAssignmentsContainer + BoundaryAssignmentsContainer; + + typedef typename + Superclass::BoundaryAssignmentsContainerPointer + BoundaryAssignmentsContainerPointer; + + typedef typename Superclass::BoundingBoxType BoundingBoxType; + typedef typename Superclass::CellAutoPointer CellAutoPointer; + typedef typename Superclass::CellsContainer CellsContainer; + typedef typename Superclass::CellDataContainer CellDataContainer; + typedef typename Superclass::CellFeatureCount CellFeatureCount; + typedef typename Superclass::CellFeatureIdentifier CellFeatureIdentifier; + typedef typename Superclass::CellIdentifier CellIdentifier; + typedef typename Superclass::CellLinksContainer CellLinksContainer; + typedef typename Superclass::CellMultiVisitorType CellMultiVisitorType; + typedef typename Superclass::CellPixelType CellPixelType; + typedef typename Superclass::CellType CellType; + typedef typename Superclass::PointIdentifier PointIdentifier; + typedef typename Superclass::PointsContainer PointsContainer; + typedef typename Superclass::PointType PointType; + + /// QuadEdge types (primal and dual) + typedef QuadEdge< PointIdentifier, CellIdentifier > TPrimalEdge; + typedef typename TPrimalEdge::TDual TDualEdge; + typedef QuadEdgeCell< CellType, TPrimalEdge > TQuadEdgeCell; + + /// Memory management objects + typedef std::set< typename TPrimalEdge::Pointer > CntPrimalEdges; + typedef std::set< typename TDualEdge::Pointer > CntDualEdges; + typedef std::vector< TPrimalEdge* > CntOnextRings; + + /// More geometry types + typedef typename PointType::VectorType VectorType; + typedef typename VectorType::ValueType TScalar; + typedef std::vector< VectorType > CntNormals; + typedef typename CntNormals::const_iterator NormalsIterator; + + protected: + typedef std::vector< TPrimalEdge* > _TEdges; + + public: + itkNewMacro( Self ); + itkTypeMacro( QuadEdgeMesh, itkMesh ); + + public: + // Edge related methods + TPrimalEdge* FindEdge( const PointIdentifier& a ) const; + TPrimalEdge* FindEdge( + const PointIdentifier& a, const PointIdentifier& b + ) const; + TPrimalEdge* FindEntryEdge( const CellIdentifier& i ) const; + + /// New geometric methods + const CntNormals& GetPointNormalsContainer( ) const; + NormalsIterator BeginPointNormals( ) const; + NormalsIterator EndPointNormals( ) const; + const VectorType& GetPointNormal( const PointIdentifier& id ) const; + + /// itk::DataObject methods overloading + virtual bool RequestedRegionIsOutsideOfTheBufferedRegion( ); + + /// itk::PointSet methods overloading + virtual void SetPoints( PointsContainer* points ); + virtual void SetPoint( PointIdentifier id , PointType point ); + + /// itk::Mesh methods overloading + virtual void PassStructure( Self* inputMesh ) + { + std::cout << "PassStructure" << std::endl; + std::exit( 1 ); + } + + virtual void Initialize( ); + virtual void Graft( const itk::DataObject* data ); + + void SetCellLinks( CellLinksContainer* cellLinks ) + { + std::cout << "SetCellLinks" << std::endl; + std::exit( 1 ); + } + virtual CellLinksContainer* GetCellLinks( ) + { + std::cout << "GetCellLinks" << std::endl; + std::exit( 1 ); + } + virtual const CellLinksContainer* GetCellLinks( ) const + { + std::cout << "GetCellLinks (const)" << std::endl; + std::exit( 1 ); + } + virtual void SetCells( CellsContainer* cells ); + virtual void SetCellData( CellDataContainer* data ); + virtual CellDataContainer* GetCellData( ) + { + std::cout << "GetCellData" << std::endl; + std::exit( 1 ); + } + virtual const CellDataContainer* GetCellData( ) const + { + std::cout << "GetCellData (const)" << std::endl; + std::exit( 1 ); + } + +#if !defined( CABLE_CONFIGURATION ) + virtual void SetBoundaryAssignments( + int dimension, BoundaryAssignmentsContainer* container + ) + { + std::cout << "SetBoundaryAssignments" << std::endl; + std::exit( 1 ); + } + virtual BoundaryAssignmentsContainerPointer + GetBoundaryAssignments( int dimension ) + { + std::cout << "GetBoundaryAssignments" << std::endl; + std::exit( 1 ); + } + virtual const BoundaryAssignmentsContainerPointer + GetBoundaryAssignments( int dimension ) const + { + std::cout << "GetBoundaryAssignments (const)" << std::endl; + std::exit( 1 ); + } +#endif + + virtual void SetCell( CellIdentifier id, CellAutoPointer& ptr ); + virtual void SetCellData( CellIdentifier id, CellPixelType data ); + virtual bool GetCellData( CellIdentifier id, CellPixelType* data ) const + { + std::cout << "GetCellData" << std::endl; + std::exit( 1 ); + } + virtual void SetBoundaryAssignment( + int dimension, CellIdentifier cellId, + CellFeatureIdentifier featureId, + CellIdentifier boundaryId + ) + { + std::cout << "SetBoundaryAssignment" << std::endl; + std::exit( 1 ); + } + virtual bool GetBoundaryAssignment( + int dimension, CellIdentifier cellId, + CellFeatureIdentifier featureId, + CellIdentifier* boundaryId + ) const + { + std::cout << "GetBoundaryAssignment" << std::endl; + std::exit( 1 ); + } + virtual bool RemoveBoundaryAssignment( + int dimension, CellIdentifier cellId, + CellFeatureIdentifier featureId + ) + { + std::cout << "RemoveBoundaryAssignment" << std::endl; + std::exit( 1 ); + } + virtual CellFeatureCount GetNumberOfCellBoundaryFeatures( + int dimension, + CellIdentifier id + ) const + { + std::cout << "GetNumberOfCellBoundaryFeatures" << std::endl; + std::exit( 1 ); + } + virtual bool GetCellBoundaryFeature( + int dimension, CellIdentifier id, + CellFeatureIdentifier fid, + CellAutoPointer& ptr + ) const + { + std::cout << "GetCellBoundaryFeature" << std::endl; + std::exit( 1 ); + } + virtual CellIdentifier GetCellBoundaryFeatureNeighbors( + int dimension, + CellIdentifier id, + CellFeatureIdentifier fid, + std::set< CellIdentifier >* cellSet ) + { + std::cout << "GetCellBoundaryFeatureNeighbors" << std::endl; + std::exit( 1 ); + } + virtual CellIdentifier GetCellNeighbors( + CellIdentifier cellId, + std::set< CellIdentifier >* cellSet + ) + { + std::cout << "GetCellNeighbors" << std::endl; + std::exit( 1 ); + } + virtual bool GetAssignedCellBoundaryIfOneExists( + int dimension, CellIdentifier id, + CellFeatureIdentifier fid, + CellAutoPointer& ptr + ) const + { + std::cout << "GetAssignedCellBoundaryIfOneExists" << std::endl; + std::exit( 1 ); + } + virtual void BuildCellLinks( ) const; + + virtual void Accept( CellMultiVisitorType* mv ) const + { + std::cout << "Accept" << std::endl; + std::exit( 1 ); + } + + protected: + QuadEdgeMesh( ); + virtual ~QuadEdgeMesh( ); + + virtual void ReleaseCellsMemory( ) + { + std::cout << "ReleaseCellsMemory" << std::endl; + std::exit( 1 ); + } + + inline bool _CheckPoints( const CellAutoPointer& ptr ) const; + inline void _DeletePoint( const PointIdentifier& pId ); + inline TPrimalEdge* _CreateQuadEdge( + const PointIdentifier& a, const PointIdentifier& b + ); + inline void _DeleteEdge( TPrimalEdge* edge ); + inline void _DeleteFace( const CellIdentifier& f ); + inline void _ConstructEdges( + _TEdges& edges, const CellAutoPointer& ptr + ); + virtual VectorType _ComputePointNormal( const TPrimalEdge* e ) const; + inline void _ReleaseQuadEdgeObjects( ); + + private: + QuadEdgeMesh( const Self& ); // Not implemented + void operator=( const Self& ); // Not implemented + + protected: + CntPrimalEdges m_PrimalEdges; + CntDualEdges m_DualEdges; + + CntOnextRings m_OnextRings; + + CntNormals m_PointNormals; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEMESH__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/QuadEdgeMesh.hxx b/lib/cpExtensions/DataStructures/QuadEdgeMesh.hxx new file mode 100644 index 0000000..e4c5eff --- /dev/null +++ b/lib/cpExtensions/DataStructures/QuadEdgeMesh.hxx @@ -0,0 +1,527 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEMESH__HXX__ +#define __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEMESH__HXX__ + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +TPrimalEdge* cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +FindEdge( const PointIdentifier& a ) const +{ + if( a < this->m_OnextRings.size( ) ) + return( this->m_OnextRings[ a ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +TPrimalEdge* cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +FindEdge( const PointIdentifier& a, const PointIdentifier& b ) const +{ + TPrimalEdge* found = NULL; + TPrimalEdge* e = this->FindEdge( a ); + if( e != NULL ) + { + typename TPrimalEdge::Iterator eIt = e->BeginOnext( ); + for( ; eIt != e->EndOnext( ) && found == NULL; eIt++ ) + if( ( *eIt )->GetDestination( ) == b ) + found = *eIt; + + } // fi + return( found ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +TPrimalEdge* cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +FindEntryEdge( const CellIdentifier& i ) const +{ + if( i < this->GetNumberOfCells( ) ) + { + CellAutoPointer c; + this->GetCell( i, c ); + + TQuadEdgeCell* ec = dynamic_cast< TQuadEdgeCell* >( c.GetPointer( ) ); + if( ec != NULL ) + return( ec->GetEntryPrimalEdge( ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +const typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +CntNormals& cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +GetPointNormalsContainer( ) const +{ + return( this->m_PointNormals ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +NormalsIterator cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +BeginPointNormals( ) const +{ + return( this->m_PointNormals.begin( ) ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +NormalsIterator cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +EndPointNormals( ) const +{ + return( this->m_PointNormals.end( ) ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +const typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +VectorType& cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +GetPointNormal( const PointIdentifier& id ) const +{ + static const VectorType zero( TScalar( 0 ) ); + if( id < this->m_PointNormals.size( ) ) + return( this->m_PointNormals[ id ] ); + else + return( zero ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +bool cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +RequestedRegionIsOutsideOfTheBufferedRegion( ) +{ + // Mesh regions don't have meaning with QuadEdges, this is important + // in order to guarantee correct pipeline execution + return( false ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +SetPoints( PointsContainer* points ) +{ + this->_ReleaseQuadEdgeObjects( ); + this->m_OnextRings.resize( points->Size( ), NULL ); + this->m_PointNormals.resize( + points->Size( ), VectorType( TScalar( 0 ) ) + ); + this->Superclass::SetPoints( points ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +SetPoint( PointIdentifier id , PointType point ) +{ + // If the point is brand new, add some non-existent edges and normals + unsigned long N = this->GetNumberOfPoints( ); + N = ( N < id + 1 )? id + 1: N; + if( this->m_OnextRings.size( ) < N ) + { + this->m_OnextRings.resize( N, NULL ); + this->m_PointNormals.resize( N, VectorType( TScalar( 0 ) ) ); + + } // fi + + // Ok pass it to itk + this->Superclass::SetPoint( id, point ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +Initialize( ) +{ + this->Superclass::Initialize( ); + this->_ReleaseQuadEdgeObjects( ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +Graft( const itk::DataObject* data ) +{ + this->Superclass::Graft( data ); + const Self* mesh = dynamic_cast< const Self* >( data ); + if( mesh != NULL ) + { + this->_ReleaseQuadEdgeObjects( ); + this->m_PrimalEdges = mesh->m_PrimalEdges; + this->m_DualEdges = mesh->m_DualEdges; + this->m_OnextRings = mesh->m_OnextRings; + this->m_PointNormals = mesh->m_PointNormals; + + } // fi +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +SetCells( CellsContainer* cells ) +{ + // Clear cells + if( this->GetCells( ) != NULL ) + this->SetCells( CellsContainer::New( ) ); + this->_ReleaseQuadEdgeObjects( ); + this->m_OnextRings.resize( this->GetNumberOfPoints( ), NULL ); + + // Copy cells + if( cells != NULL ) + { + for( unsigned long cId = 0; cId < cells->Size( ); ++cId ) + { + CellAutoPointer cell( cells->GetElement( cId ), false ); + this->SetCell( cId, cell ); + + } // rof + + } // fi +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +SetCellData( CellDataContainer* data ) +{ + /* TODO + No need for CellData in initial application: + how should this be overridden? + */ +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +SetCell( CellIdentifier id, CellAutoPointer& ptr ) +{ + // Overwrite an existing cell? + if( id < this->GetNumberOfCells( ) ) + { + itkExceptionMacro( + << "TODO: What do I do here? Trying to overwrite a cell!" + ); + + } // fi + + // Do not allow to add vertices or edges as cells for the sake of + // correct mesh construction + if( ptr->GetNumberOfPoints( ) < 3 ) + { + itkExceptionMacro( + << "Face have less than 3 points (" + << ptr->GetNumberOfPoints( ) + << ")" + ); + + } // fi + + // Fill up geometrical prerrequisites + if( !( this->_CheckPoints( ptr ) ) ) + { + itkExceptionMacro( << "Points missing in the mesh" ); + + } // fi + + // Get (or create) individual edges + _TEdges edges; + this->_ConstructEdges( edges, ptr ); + + // Configure new face's geometry + edges[ 0 ]->SetLnextRingGeometry( id ); + + // Update normals + typename _TEdges::const_iterator eIt = edges.begin( ); + for( ; eIt != edges.end( ); ++eIt ) + this->m_PointNormals[ ( *eIt )->GetOrigin( ) ] = + this->_ComputePointNormal( *eIt ); + + // Save cell + TQuadEdgeCell* qcell = new TQuadEdgeCell( edges[ 0 ] ); + CellAutoPointer cell; + cell.TakeOwnership( qcell ); + this->Superclass::SetCell( id, cell ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +SetCellData( CellIdentifier id, CellPixelType data ) +{ + /* TODO + No need for CellData in initial application: + how should this be overridden? + */ +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +BuildCellLinks( ) const +{ + // This is no longer required when using QuadEdges +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +QuadEdgeMesh( ) + : Superclass( ) +{ + this->_ReleaseQuadEdgeObjects( ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +~QuadEdgeMesh( ) +{ + this->_ReleaseQuadEdgeObjects( ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +bool cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_CheckPoints( const CellAutoPointer& ptr ) const +{ + const typename Superclass::PointsContainer* pnts = this->GetPoints( ); + + bool all_exist = true; + typename CellType::PointIdConstIterator pIt = ptr->PointIdsBegin( ); + for( ; pIt != ptr->PointIdsEnd( ) && all_exist; ++pIt ) + all_exist &= pnts->IndexExists( *pIt ); + return( all_exist ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_DeletePoint( const PointIdentifier& pId ) +{ + PointIdentifier lastId = this->GetNumberOfPoints( ) - 1; + if( lastId < pId ) + return; + + // Modify point container + PointType to_delete = this->GetPoint( pId ); + PointType last = this->GetPoint( lastId ); + this->Superclass::SetPoint( pId, last ); + + // Modify Onext ring and normals containers + this->m_OnextRings[ pId ] = this->m_OnextRings[ lastId ]; + this->m_PointNormals[ pId ] = this->m_PointNormals[ lastId ]; + this->m_OnextRings.pop_back( ); + this->m_PointNormals.pop_back( ); + + // Update origins + typename TPrimalEdge::Iterator oIt = + this->m_OnextRings[ pId ]->BeginOnext( ); + for( ; oIt != this->m_OnextRings[ pId ]->EndOnext( ); ++oIt ) + ( *oIt )->SetOrigin( pId ); + + // Erase the point + this->GetPoints( )->CastToSTLContainer( ).pop_back( ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +TPrimalEdge* cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_CreateQuadEdge( const PointIdentifier& a, const PointIdentifier& b ) +{ + // Create brand new object + typename TPrimalEdge::Pointer edge = TPrimalEdge::New( ); + edge->CreateRings( ); + + // Configure geometry + edge->SetOrigin( a ); + edge->SetDestination( b ); + + // Keep trace of all reserved memory + this->m_PrimalEdges.insert( edge ); + this->m_PrimalEdges.insert( edge->GetSym( ) ); + this->m_DualEdges.insert( edge->GetRot( ) ); + this->m_DualEdges.insert( edge->GetInvRot( ) ); + + return( edge ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_DeleteEdge( TPrimalEdge* edge ) +{ + this->m_DualEdges.erase( edge->GetInvRot( ) ); + this->m_PrimalEdges.erase( edge->GetSym( ) ); + this->m_DualEdges.erase( edge->GetRot( ) ); + this->m_PrimalEdges.erase( edge ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_DeleteFace( const CellIdentifier& f ) +{ + unsigned long cellId = this->GetNumberOfCells( ) - 1; + if( cellId < f ) + return; + + // Exchange desired face with last one + CellAutoPointer to_delete, last; + this->GetCell( f, to_delete ); + this->GetCell( cellId, last ); + this->Superclass::SetCell( f, last ); + this->Superclass::SetCell( cellId, to_delete ); + + // This will delete cell's memory when to_delete is no longer used + to_delete.TakeOwnership( ); + + // Squeeze container + this->GetCells( )->CastToSTLContainer( ).pop_back( ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_ConstructEdges( _TEdges& edges, const CellAutoPointer& ptr ) +{ + edges.clear( ); + typename CellType::PointIdConstIterator pIt = ptr->PointIdsBegin( ); + for( pIt = ptr->PointIdsBegin( ); pIt != ptr->PointIdsEnd( ); ++pIt ) + { + typename CellType::PointIdConstIterator nIt = pIt; + ++nIt; + if( nIt == ptr->PointIdsEnd( ) ) + nIt = ptr->PointIdsBegin( ); + + TPrimalEdge* edge = this->FindEdge( *pIt, *nIt ); + if( edge == NULL ) + { + edge = this->_CreateQuadEdge( *pIt, *nIt ); + if( this->m_OnextRings[ *pIt ] != NULL ) + { + if( this->m_OnextRings[ *pIt ]->IsOriginInternal( ) ) + { + itkExceptionMacro( + << "Edge [" + << *pIt << ", " << *nIt << "] is already internal." + ); + + } // fi + + // Put edge in Onext ring + typename TPrimalEdge::Iterator eIt = + this->m_OnextRings[ *pIt ]->BeginOnext( ); + while( eIt != this->m_OnextRings[ *pIt ]->EndOnext( ) ) + { + if( !( ( *eIt )->IsLeftSet( ) ) ) + { + TPrimalEdge::Splice( *eIt, edge ); + eIt = this->m_OnextRings[ *pIt ]->EndOnext( ); + } + else + ++eIt; + + } // elihw + } + else + this->m_OnextRings[ *pIt ] = edge; + } + else + { + if( edge->IsLeftSet( ) ) + { + itkExceptionMacro( + << "Edge [" + << edge->GetOrigin( ) << ", " + << edge->GetDestination( ) << "] already have a left face (" + << edge->GetLeft( ) + << "). Face already exits (at least in part)." + ); + + } // fi + + } // fi + edges.push_back( edge ); + + } // rof + + // Reorder Onext rings + typename _TEdges::iterator ecIt; + for( ecIt = edges.begin( ); ecIt != edges.end( ); ++ecIt ) + { + TPrimalEdge* e = *ecIt; + TPrimalEdge* eOprev; + if( ecIt != edges.begin( ) ) + { + typename _TEdges::iterator eOprevIt = ecIt; + --eOprevIt; + eOprev = ( *eOprevIt )->GetSym( ); + } + else + eOprev = edges.back( )->GetSym( ); + TPrimalEdge::ReorderOnextRing( e, eOprev ); + + } // rof +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +typename cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +VectorType cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_ComputePointNormal( const TPrimalEdge* e ) const +{ + VectorType n( TScalar( 0 ) ); + if( Superclass::PointDimension == 3 ) + { + PointType p0 = this->GetPoint( e->GetOrigin( ) ); + typename TPrimalEdge::ConstIterator eIt = e->BeginOnext( ); + unsigned int count = 0; + for( ; eIt != e->EndOnext( ); eIt++ ) + { + if( ( *eIt )->IsLeftSet( ) ) + { + typename TPrimalEdge::ConstIterator nIt = eIt; + nIt++; + if( nIt == e->EndOnext( ) ) + nIt = e->BeginOnext( ); + + VectorType pe = this->GetPoint( ( *eIt )->GetDestination( ) ) - p0; + VectorType pn = this->GetPoint( ( *nIt )->GetDestination( ) ) - p0; + n[ 0 ] += ( pe[ 1 ] * pn[ 2 ] ) - ( pe[ 2 ] * pn[ 1 ] ); + n[ 1 ] += ( pe[ 2 ] * pn[ 0 ] ) - ( pe[ 0 ] * pn[ 2 ] ); + n[ 2 ] += ( pe[ 0 ] * pn[ 1 ] ) - ( pe[ 1 ] * pn[ 0 ] ); + count++; + + } // fi + + } // rof + TScalar nn = n.GetNorm( ); + if( nn > TScalar( 0 ) && count > 0 ) + n /= nn * TScalar( count ); + + } // fi + return( n ); +} + +// ------------------------------------------------------------------------- +template< typename P, unsigned int D, typename T > +void cpExtensions::DataStructures::QuadEdgeMesh< P, D, T >:: +_ReleaseQuadEdgeObjects( ) +{ + this->m_PrimalEdges.clear( ); + this->m_OnextRings.clear( ); + this->m_DualEdges.clear( ); + this->m_PointNormals.clear( ); +} + +#endif // __CPEXTENSIONS__DATASTRUCTURES__QUADEDGEMESH__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/DataStructures/VectorValuesContainer.h b/lib/cpExtensions/DataStructures/VectorValuesContainer.h new file mode 100644 index 0000000..eea4e40 --- /dev/null +++ b/lib/cpExtensions/DataStructures/VectorValuesContainer.h @@ -0,0 +1,66 @@ +#ifndef __CPEXTENSIONS__DATASTRUCTURES__VECTORVALUESCONTAINER__H__ +#define __CPEXTENSIONS__DATASTRUCTURES__VECTORVALUESCONTAINER__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace DataStructures + { + /** + */ + template< class T > + class VectorValuesContainer + : public itk::SimpleDataObjectDecorator< std::vector< T > > + { + public: + typedef std::vector< T > TDecorated; + typedef VectorValuesContainer Self; + typedef itk::SimpleDataObjectDecorator< TDecorated > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef T TValue; + typedef typename TDecorated::iterator Iterator; + typedef typename TDecorated::const_iterator ConstIterator; + + public: + itkNewMacro( Self ); + itkTypeMacro( VectorValuesContainer, itkSimpleDataObjectDecorator ); + + public: + void PushBack( const T& v ) + { this->Get( ).push_back( v ); this->Modified( ); } + void PopBack( const T& v ) + { this->Get( ).pop_back( ); this->Modified( ); } + Iterator Begin( ) + { return( this->Get( ).begin( ) ); } + Iterator End( ) + { return( this->Get( ).end( ) ); } + ConstIterator Begin( ) const + { return( this->Get( ).begin( ) ); } + ConstIterator End( ) const + { return( this->Get( ).end( ) ); } + + protected: + VectorValuesContainer( ) + : Superclass( ) + { } + virtual ~VectorValuesContainer( ) + { } + + private: + // Purposely not implemented + VectorValuesContainer( const Self& other ); + Self& operator=( const Self& other ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__DATASTRUCTURES__VECTORVALUESCONTAINER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/IO/MementoState.cxx b/lib/cpExtensions/IO/MementoState.cxx new file mode 100644 index 0000000..2af5abf --- /dev/null +++ b/lib/cpExtensions/IO/MementoState.cxx @@ -0,0 +1,148 @@ +/* +#include + + +#include +#include +#include + + + + + +// ------------------------------------------------------------------------- +cpExtensions::IO::MementoState::MementoState() +{ + m_maxId = m_Id = 0; + m_stateIt = m_stateReady.begin(); +}; + +// ------------------------------------------------------------------------- +bool +cpExtensions::IO::MementoState::SetToMemento(cpPlugins::Interface::Image* _img) +{ + char base[] = "state"; + std::ostringstream oss; + this->m_Id; + oss << this->m_Id; + std::string str = oss.str(); + auto complement = str.c_str(); + + std::string fileName(base); + fileName.append(complement); + fileName.append(".mhd"); + + std::string fileNameRaw(base); + fileNameRaw.append(complement); + fileNameRaw.append(".raw"); + //save(fileName, fileNameRaw, _img); + m_stateReady.insert(m_stateReady.begin() + m_Id, false); + std::async(std::launch::async, &MementoState::Save, this, fileName, fileNameRaw, _img); + + m_stateReady[m_Id] = true; + m_Id++; + + if (m_Id > m_maxId) + { + m_maxId = m_Id; + } + + return true; +} + + +// ------------------------------------------------------------------------- +vtkSmartPointer +cpExtensions::IO::MementoState::GetFromMemento(long id) +{ + if (id > m_maxId) + { + return nullptr; + } + + char base[] = "state"; + std::ostringstream oss; + oss << id; + std::string str = oss.str(); + auto complement = str.c_str(); + + std::string fileName(base); + fileName.append(complement); + fileName.append(".mhd"); + return Load(fileName); + //std::future> result(std::async(std::launch::async, &MementoState::Load, this, fileName)); + //return result.get(); +} + +// ------------------------------------------------------------------------- +vtkSmartPointer +cpExtensions::IO::MementoState::MementoUndo() +{ + char base[] = "state"; + std::ostringstream oss; + oss << --this->m_Id; + std::string str = oss.str(); + auto complement = str.c_str(); + + std::string fileName(base); + fileName.append(complement); + fileName.append(".mhd"); + + if (m_stateReady.at(this->m_Id)) + { + return Load(fileName); + } + + return nullptr; +} + + +vtkSmartPointer +cpExtensions::IO::MementoState::MementoRedo() +{ + char base[] = "state"; + std::ostringstream oss; + oss << ++this->m_Id; + std::string str = oss.str(); + auto complement = str.c_str(); + + std::string fileName(base); + fileName.append(complement); + fileName.append(".mhd"); + + if (m_stateReady.at(this->m_Id) && + this->m_Id <= this->m_maxId) + { + return Load(fileName); + } + return nullptr; +} + +// ------------------------------------------------------------------------- +void +cpExtensions::IO::MementoState:: +Save(const std::string& filename, const std::string& filenameRaw, cpPlugins::Interface::Image* img) { + + vtkSmartPointer writer = + vtkSmartPointer::New(); + writer->SetInputData(img->GetVTK< vtkImageData >()); + writer->SetFileName(filename.c_str()); + writer->SetRAWFileName(filenameRaw.c_str()); + writer->Write(); +} + +// ------------------------------------------------------------------------- +vtkSmartPointer +cpExtensions::IO::MementoState::Load(const std::string& filename) { + + vtkSmartPointer reader = + vtkSmartPointer::New(); + reader->SetFileName(filename.c_str()); + + reader->Update(); + return reader->GetOutput(); + +} +*/ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/IO/MementoState.h b/lib/cpExtensions/IO/MementoState.h new file mode 100644 index 0000000..d7430d3 --- /dev/null +++ b/lib/cpExtensions/IO/MementoState.h @@ -0,0 +1,63 @@ +#ifndef __CPEXTENSIONS__IO__MEMENTOSTATE__H__ +#define __CPEXTENSIONS__IO__MEMENTOSTATE__H__ + +/* +#include + + +#include + + +// vtk stuff +#include +#include + +// Plugins interface +#include +#include +#include +#include +#include + +#include +#include + +namespace cpExtensions +{ + namespace IO + { + class cpExtensions_EXPORT MementoState + { + private: + long m_Id; + long m_maxId; + std::vector m_stateReady; + std::vector::iterator m_stateIt; + public: + + MementoState(); + bool SetToMemento(cpPlugins::Interface::Image* _img); + vtkSmartPointer MementoUndo(); + vtkSmartPointer MementoRedo(); + vtkSmartPointer GetFromMemento(long id); + private: + void Save(const std::string& filename, const std::string& filenameRaw, cpPlugins::Interface::Image* img); + vtkSmartPointer Load(const std::string& filename); + + }; + } +} +*/ +//========================================================================== + +// ------------------------------------------------------------------------- +/** + */ + + + + + +#endif // __CPEXTENSIONS__IO__MEMENTOSTATE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/IO/MeshReader.h b/lib/cpExtensions/IO/MeshReader.h new file mode 100644 index 0000000..af16293 --- /dev/null +++ b/lib/cpExtensions/IO/MeshReader.h @@ -0,0 +1,64 @@ +#ifndef __CPEXTENSIONS__IO__MESHREADER__H__ +#define __CPEXTENSIONS__IO__MESHREADER__H__ + +#include +#include + +namespace cpExtensions +{ + namespace IO + { + /** + */ + template< typename M > + class MeshReader + : public itk::MeshSource< M > + { + public: + typedef MeshReader Self; + typedef itk::MeshSource< M > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef M MeshType; + + public: + itkNewMacro( Self ); + itkTypeMacro( MeshReader, itkMeshSource ); + + itkSetStringMacro( FileName ); + itkGetStringMacro( FileName ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const; + + protected: + MeshReader( ); + virtual ~MeshReader( ); + + virtual void GenerateData( ); + + template< class R > + void _Read( ); + + private: + // Purposely not implemented + MeshReader( const Self& ); + Self& operator=( const Self & ); + + protected: + typename Superclass::Pointer m_Reader; + std::string m_FileName; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__IO__MESHREADER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/IO/MeshReader.hxx b/lib/cpExtensions/IO/MeshReader.hxx new file mode 100644 index 0000000..8146e6e --- /dev/null +++ b/lib/cpExtensions/IO/MeshReader.hxx @@ -0,0 +1,92 @@ +#ifndef __CPEXTENSIONS__IO__MESHREADER__HXX__ +#define __CPEXTENSIONS__IO__MESHREADER__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< typename M > +itk::ModifiedTimeType cpExtensions::IO::MeshReader< M >:: +GetMTime( ) const +{ + itk::ModifiedTimeType mtime = this->Superclass::GetMTime( ); + if( this->m_Reader.IsNotNull( ) ) + { + itk::ModifiedTimeType rtime = this->m_Reader->GetMTime( ); + mtime = ( rtime < mtime )? rtime: mtime; + + } // fi + return( mtime ); +} + +// ------------------------------------------------------------------------- +template< typename M > +cpExtensions::IO::MeshReader< M >:: +MeshReader( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< typename M > +cpExtensions::IO::MeshReader< M >:: +~MeshReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< typename M > +void cpExtensions::IO::MeshReader< M >:: +GenerateData( ) +{ + std::string fn = this->m_FileName; + std::transform( fn.begin( ), fn.end( ), fn.begin( ), ::tolower ); + if( fn.rfind( ".vtk" ) != std::string::npos ) + this->_Read< itk::VTKPolyDataReader< M > >( ); + else if( fn.rfind( ".obj" ) != std::string::npos ) + this->_Read< cpExtensions::IO::WaveFrontOBJReader< M > >( ); +} + +// ------------------------------------------------------------------------- +template< typename M > +template< class R > +void cpExtensions::IO::MeshReader< M >:: +_Read( ) +{ + typename R::Pointer reader = NULL; + if( this->m_Reader.IsNotNull( ) ) + { + reader = dynamic_cast< R* >( this->m_Reader.GetPointer( ) ); + if( reader.IsNotNull( ) ) + { + if( reader->GetFileName( ) == this->m_FileName ) + reader = NULL; + } + else + { + reader = R::New( ); + this->m_Reader = reader; + + } // fi + } + else + { + reader = R::New( ); + this->m_Reader = reader; + + } // fi + + if( reader.IsNotNull( ) ) + { + reader->SetFileName( this->m_FileName ); + reader->GraftOutput( this->GetOutput( ) ); + reader->Update( ); + this->GraftOutput( reader->GetOutput( ) ); + + } // fi +} + +#endif // __CPEXTENSIONS__IO__MESHREADER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/IO/WaveFrontOBJReader.h b/lib/cpExtensions/IO/WaveFrontOBJReader.h new file mode 100644 index 0000000..4cd7446 --- /dev/null +++ b/lib/cpExtensions/IO/WaveFrontOBJReader.h @@ -0,0 +1,81 @@ +#ifndef __CPEXTENSIONS__IO__WAVEFRONTOBJREADER__H__ +#define __CPEXTENSIONS__IO__WAVEFRONTOBJREADER__H__ + +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace IO + { + /** + * \class WaveFrontOBJReader + * \brief + * Reads a wavefront OBJ file and create an itkMesh. + * + * Caveat1: itkWaveFrontOBJReader will read only vertices and faces. + * Normal, parameters and textures vectors are ignored. + * + */ + template< typename M > + class WaveFrontOBJReader + : public itk::MeshSource< M > + { + public: + typedef WaveFrontOBJReader Self; + typedef itk::MeshSource< M > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + typedef M MeshType; + typedef typename M::MeshTraits MeshTraits; + typedef typename M::PointType PointType; + typedef typename MeshTraits::PixelType PixelType; + typedef typename M::Pointer MeshPointer; + typedef typename M::CellTraits CellTraits; + typedef typename M::CellIdentifier CellIdentifier; + typedef typename M::CellType CellType; + typedef typename M::CellAutoPointer CellAutoPointer; + typedef typename M::PointIdentifier PointIdentifier; + typedef typename CellTraits::PointIdIterator PointIdIterator; + typedef typename M::PointsContainerPointer PointsContainerPointer; + typedef typename M::PointsContainer PointsContainer; + + typedef itk::PolygonCell< CellType > TPolygonCell; + + public: + itkNewMacro( Self ); + itkTypeMacro( WaveFrontOBJReader, itkMeshSource ); + + itkSetStringMacro( FileName ); + itkGetStringMacro( FileName ); + + protected: + WaveFrontOBJReader( ); + virtual ~WaveFrontOBJReader( ); + + virtual void GenerateData( ); + + private: + // Purposely not implemented + WaveFrontOBJReader( const Self& ); + Self& operator=( const Self & ); + + protected: + std::string m_FileName; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__IO__WAVEFRONTOBJREADER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/IO/WaveFrontOBJReader.hxx b/lib/cpExtensions/IO/WaveFrontOBJReader.hxx new file mode 100644 index 0000000..355f779 --- /dev/null +++ b/lib/cpExtensions/IO/WaveFrontOBJReader.hxx @@ -0,0 +1,123 @@ +#ifndef __CPEXTENSIONS__IO__WAVEFRONTOBJREADER__HXX__ +#define __CPEXTENSIONS__IO__WAVEFRONTOBJREADER__HXX__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< typename M > +cpExtensions::IO::WaveFrontOBJReader< M >:: +WaveFrontOBJReader( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< typename M > +cpExtensions::IO::WaveFrontOBJReader< M >:: +~WaveFrontOBJReader( ) +{ +} + +// ------------------------------------------------------------------------- +template< typename M > +void cpExtensions::IO::WaveFrontOBJReader< M >:: +GenerateData( ) +{ + typedef typename PointType::ValueType TScalar; + typename M::Pointer out = this->GetOutput( ); + + out->SetCellsAllocationMethod( M::CellsAllocatedDynamicallyCellByCell ); + if( this->m_FileName == "" ) + { + itkExceptionMacro( << "No input FileName" ); + + } // fi + + std::ifstream in( this->m_FileName.c_str( ) ); + if( !in.is_open( ) ) + { + itkExceptionMacro( + << "Unable to open file" << std::endl + << "\"" << m_FileName << "\"" + ); + + } // fi + + in.imbue( std::locale::classic( ) ); + std::string buffer; + + while( !in.eof( ) ) + { + std::getline( in, buffer, '\n' ); + + // Tokenize + std::stringstream ss( buffer ); + std::istream_iterator< std::string > it( ss ); + std::istream_iterator< std::string > end; + std::vector< std::string > line( it, end ); + if( line.size( ) == 0 ) + continue; + + // Now, we are talking... + if( line[ 0 ] == "v" || line[ 0 ] == "V" ) + { + // Add points + PointType pnt; + pnt.Fill( TScalar( 0 ) ); + + if( line.size( ) > 1 && M::PointDimension >= 1 ) + pnt[ 0 ] = TScalar( std::atof( line[ 1 ].c_str( ) ) ); + if( line.size( ) > 2 && M::PointDimension >= 2 ) + pnt[ 1 ] = TScalar( std::atof( line[ 2 ].c_str( ) ) ); + if( line.size( ) > 3 && M::PointDimension >= 3 ) + pnt[ 2 ] = TScalar( std::atof( line[ 3 ].c_str( ) ) ); + if( M::PointDimension >= 4 ) + { + if( line.size( ) > 4 ) + pnt[ 3 ] = TScalar( std::atof( line[ 4 ].c_str( ) ) ); + else + pnt[ 4 ] = TScalar( 1 ); + + } // fi + out->SetPoint( out->GetNumberOfPoints( ), pnt ); + } + else if( line[ 0 ] == "f" || line[ 0 ] == "F" ) + { + if( line.size( ) > 3 ) + { + // Add a face + CellAutoPointer cell; + TPolygonCell* face = new TPolygonCell( ); + + for( unsigned int k = 1; k < line.size( ); ++k ) + { + PointIdentifier pId = + PointIdentifier( + std::atoi( + line[ k ]. + substr( 0, line[ k ].find_first_of( "/" ) ).c_str( ) + ) + ); + + // In OBJ files, vertices are numbered from 1 + face->AddPointId( pId - 1 ); + + } // rof + cell.TakeOwnership( face ); + out->SetCell( out->GetNumberOfCells( ), cell ); + + } // fi + + } // fi + + } // elihw + + // Finish the job + in.close( ); +} + +#endif // __CPEXTENSIONS__IO__WAVEFRONTOBJREADER__HXX__ + +// 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..30c3ba3 --- /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..c037193 --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageInteractorStyle.cxx @@ -0,0 +1,168 @@ +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +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:: +AssociateImageActor( vtkImageActor* actor ) +{ + if( actor != NULL ) + { + this->m_PropPicker->AddPickList( actor ); + 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 +{ + /* TODO + if( this->m_SeedWidget != NULL ) + this->m_SeedWidget->Representation->GetSeedWorldPosition( id, pos ); + */ +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::ImageInteractorStyle:: +ImageInteractorStyle( ) + : Superclass( ), + 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; +} + +// ------------------------------------------------------------------------- +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..ec54f5e --- /dev/null +++ b/lib/cpExtensions/Interaction/ImageInteractorStyle.h @@ -0,0 +1,97 @@ +#ifndef __CPEXTENSIONS__INTERACTION__IMAGEINTERACTORSTYLE__H__ +#define __CPEXTENSIONS__INTERACTION__IMAGEINTERACTORSTYLE__H__ + +#include + +#include + +#include +#include +#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 + 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( ); + + // Data for local picker + virtual void AssociateImageActor( vtkImageActor* actor ); + + // Widgets + 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( ); + + virtual bool _PickPosition( int idx[ 2 ], double pos[ 3 ] ); + + private: + // Purposely not implemented + ImageInteractorStyle( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkPropPicker > m_PropPicker; + + 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..526ac7e --- /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/Interaction/SphereWidget.cxx b/lib/cpExtensions/Interaction/SphereWidget.cxx new file mode 100644 index 0000000..882c3ca --- /dev/null +++ b/lib/cpExtensions/Interaction/SphereWidget.cxx @@ -0,0 +1,263 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SphereWidget:: +Self* cpExtensions::Interaction::SphereWidget:: +New() +{ + return(new Self); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SphereWidget:: +SetInteractor(vtkRenderWindowInteractor* rwi) +{ + this->Superclass::SetInteractor(rwi); + TBaseStyle* s = dynamic_cast(rwi->GetInteractorStyle()); + if (s != NULL) + { + s->AddKeyCommand(Self::_KeyPress, this); + s->AddMouseMoveCommand(Self::_MouseMove, this); + + } // fi +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SphereWidget:: +SphereWidget() +: Superclass() +{ + //this->SetAxis(0); + + this->SetTranslation(0); + this->SetRadius(7); + + this->SetPhiResolution(10); + this->SetThetaResolution(20); + + this->SetRepresentationToWireframe(); +} + +// ------------------------------------------------------------------------- +cpExtensions::Interaction::SphereWidget:: +~SphereWidget() +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SphereWidget:: +_Click( +void* data, const TBaseStyle::ButtonID& button, +int* idx, double* pos, bool alt, bool ctr, bool sft +) +{ + SphereWidget* self = reinterpret_cast(data); + self->Superclass::EndInteraction(); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SphereWidget:: +_DoubleClick( +void* data, const TBaseStyle::ButtonID& button, +int* idx, double* pos, bool alt, bool ctr, bool sft +) +{ + +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SphereWidget:: +_MouseMove( +void* data, const TBaseStyle::ButtonID& button, +int* idx, double* pos, bool alt, bool ctr, bool sft +) +{ + /*SphereWidget* self = reinterpret_cast(data); + self->Superclass::StartInteraction();*/ +} + +void cpExtensions::Interaction::SphereWidget::SetAxis(int axis) +{ + this->m_axis = axis; +} + + +void cpExtensions::Interaction::SphereWidget::SetAxis(void* data, int axis) +{ + SphereWidget* self = reinterpret_cast(data); + self->SetAxis(axis); +} + +int cpExtensions::Interaction::SphereWidget::GetAxis() +{ + return this->m_axis; +} + +int cpExtensions::Interaction::SphereWidget::GetAxis(void* data) +{ + SphereWidget* self = reinterpret_cast(data); + return self->GetAxis(); +} + +double* cpExtensions::Interaction::SphereWidget::GetPosition() +{ + return this->SphereActor->GetPosition(); +} + +double* cpExtensions::Interaction::SphereWidget::GetPosition(void* data) +{ + SphereWidget* self = reinterpret_cast(data); + return self->GetPosition(); +} + +void cpExtensions::Interaction::SphereWidget::SetCenter(double * center) +{ + //this->Superclass::SetCenter(center); + this->SphereActor->SetPosition(center); + this->SphereActor->Modified(); + this->Modified(); + this->GetInteractor()->Render(); +} + +void cpExtensions::Interaction::SphereWidget::SetCenter(void* data, double * center) +{ + SphereWidget* self = reinterpret_cast(data); + + //self->Superclass::SetCenter(center); + self->SphereActor->SetPosition(center); + self->SphereActor->Modified(); + self->Modified(); + self->GetInteractor()->Render(); + + std::cout << "sphere: {" << center[0] << " , " << center[1] << " , " << center[2] << "} " << std::endl; +} + +// ------------------------------------------------------------------------- +void cpExtensions::Interaction::SphereWidget::_KeyPress(void* data, const char& key) +{ + SphereWidget* self = reinterpret_cast(data); + self->Superclass::StartInteraction(); + + double * center = self->SphereActor->GetPosition(); + + auto radius = self->GetRadius(); + + auto axis = self->GetAxis(); + + switch (key) + { + case 122: // Z & z + case 90: + radius += 0.1; + + break; + case 88: // X & x + case 120: + radius -= 0.1; + + break; + case 119: // W & w + case 87: + if (axis == 0) + { + center[2] += 1; + } else if (axis == 1) + { + center[2] += 1; + } else + { + center[1] -= 1; + } + + + break; + case 83: // S & s + case 115: + if (axis == 0) + { + center[2] -= 1; + } + else if (axis == 1) + { + center[2] -= 1; + } + else + { + center[1] += 1; + } + + break; + case 65: // A & a + case 97: + if (axis == 0) + { + center[1] -= 1; + } + else if (axis == 1) + { + center[0] -= 1; + } + else + { + center[0] += 1; + } + + break; + case 100: // D & d + case 68: + if (axis == 0) + { + center[1] += 1; + } + else if (axis == 1) + { + center[0] += 1; + } + else + { + center[0] -= 1; + } + + break; + //case 81: // Q & q + //case 113: + // center[2] += 1; + // + // break; + //case 69: // E & e + //case 101: + // center[2] -= 1; + // + // break; + + default: + break; + } + + + self->SetRadius(radius); + self->SetCenter(data, center); + self->Modified(); + self->GetInteractor()->Render(); + self->EndInteraction(); +} + + + + + + + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Interaction/SphereWidget.h b/lib/cpExtensions/Interaction/SphereWidget.h new file mode 100644 index 0000000..9afae7c --- /dev/null +++ b/lib/cpExtensions/Interaction/SphereWidget.h @@ -0,0 +1,71 @@ +#ifndef __CPEXTENSIONS__INTERACTION__SphereWidget__H__ +#define __CPEXTENSIONS__INTERACTION__SphereWidget__H__ + +#include +#include +#include + +namespace cpExtensions +{ + namespace Interaction + { + /** + */ + class cpExtensions_EXPORT SphereWidget + : public vtkSphereWidget + { + public: + typedef SphereWidget Self; + vtkTypeMacro( SphereWidget, vtkSphereWidget ); + + typedef cpExtensions::Interaction::BaseInteractorStyle TBaseStyle; + typedef TBaseStyle::TMouseCommand TMouseCommand; + typedef TBaseStyle::TKeyCommand TKeyCommand; + + public: + static Self* New( ); + + virtual void SetInteractor( vtkRenderWindowInteractor* rwi ); + void SetCenter(double* center); + void SetAxis(int axis); + int GetAxis(); + double * GetPosition(); + protected: + SphereWidget( ); + virtual ~SphereWidget( ); + + 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 + ); + static void _MouseMove( + void* data, const TBaseStyle::ButtonID& button, + int* idx, double* pos, bool alt, bool ctr, bool sft + ); + + static void _KeyPress(void* data, const char& key); + + static void SetCenter(void* data, double* center); + + static void SetAxis(void* data, int axis); + static int GetAxis(void* data); + static double * GetPosition(void* data); + private: + int m_axis; + + // Purposely not implemented + SphereWidget( const Self& ); + Self& operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__INTERACTION__SphereWidget__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/QT/SimpleMPRWidget.cxx b/lib/cpExtensions/QT/SimpleMPRWidget.cxx new file mode 100644 index 0000000..62b9296 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.cxx @@ -0,0 +1,622 @@ +#include + +#ifdef cpExtensions_QT4 + +#include + +#include +#include + +double cpExtensions::QT::SimpleMPRWidget:: +cm_Colors[ 8 ][ 3 ] = +{ + { 1.0, 0.0, 0.0 }, + { 0.0, 1.0, 0.0 }, + { 0.0, 0.0, 1.0 }, + { 0.0, 1.0, 1.0 }, + { 1.0, 0.0, 1.0 }, + { 1.0, 1.0, 0.0 }, + { 1.0, 0.5, 0.0 }, + { 1.0, 0.0, 0.5 } +}; + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +SimpleMPRWidget( QWidget* parent ) + : QWidget( parent ), + m_UI( new Ui::SimpleMPRWidget ), + m_MainImage( "" ) +{ + this->m_UI->setupUi( this ); + + // Configure VTK widgets + this->m_VTK[ 0 ] = this->m_UI->VTK01; + this->m_VTK[ 1 ] = this->m_UI->VTK00; + this->m_VTK[ 2 ] = this->m_UI->VTK10; + this->m_VTK[ 3 ] = this->m_UI->VTK11; + + this->m_MPRObjects = vtkSmartPointer< TMPRObjects >::New( ); + this->m_MPRObjects->SetRenderWindows( + this->m_VTK[ 0 ]->GetRenderWindow( ), + this->m_VTK[ 1 ]->GetRenderWindow( ), + this->m_VTK[ 2 ]->GetRenderWindow( ), + this->m_VTK[ 3 ]->GetRenderWindow( ) + ); + + // 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( ) +{ + delete this->m_UI; +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::QT::SimpleMPRWidget:: +GetNumberOfData( ) const +{ + return( this->m_Data.size( ) ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +AddData( + vtkImageData* data, const std::string& name, + const std::string& parent + ) +{ + if( name == "" ) + return( false ); + + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + { + if( parent != "" ) + { + auto pIt = this->m_Data.find( parent ); + if( pIt == this->m_Data.end( ) ) + return( false ); + + } // fi + + // Add new data + this->m_Data[ name ].SetImageData( data ); + + // Set color + auto iIt = this->m_Data.find( name ); + if( iIt != this->m_Data.end( ) ) + { + vtkActor* actor = + dynamic_cast< vtkActor* >( iIt->second.GetMeshActor( ) ); + if( actor != NULL ) + { + unsigned int idx = this->m_Data.size( ) % 8; + actor->GetProperty( )->SetColor( + Self::cm_Colors[ idx ][ 0 ], + Self::cm_Colors[ idx ][ 1 ], + Self::cm_Colors[ idx ][ 2 ] + ); + + } // fi + + } // fi + + // Add to tree view + // TODO: this->_UpdateTreeItem( name, parent ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +AddData( vtkPolyData* data, const std::string& name ) +{ + if( name == "" ) + return( false ); + + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + { + // Add new data + this->m_Data[ name ].SetPolyData( data ); + + // Set color + auto iIt = this->m_Data.find( name ); + if( iIt != this->m_Data.end( ) ) + { + vtkActor* actor = + dynamic_cast< vtkActor* >( iIt->second.GetMeshActor( ) ); + if( actor != NULL ) + { + unsigned int idx = this->m_Data.size( ) % 8; + actor->GetProperty( )->SetColor( + Self::cm_Colors[ idx ][ 0 ], + Self::cm_Colors[ idx ][ 1 ], + Self::cm_Colors[ idx ][ 2 ] + ); + + } // fi + + } // fi + + // Add to tree view + // TODO: this->_UpdateTreeItem( name, parent ); + return( true ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +const std::string& cpExtensions::QT::SimpleMPRWidget:: +GetMainImage( ) const +{ + return( this->m_MainImage ); +} + +// ------------------------------------------------------------------------- +bool cpExtensions::QT::SimpleMPRWidget:: +SetMainImage( const std::string& name ) +{ + auto iIt = this->m_Data.find( name ); + if( iIt != this->m_Data.end( ) ) + { + if( iIt->second.Tag == Data::IMAGE ) + { + this->m_MainImage = name; + return( true ); + } + else + return( false ); + } + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +DeleteData( const std::string& name ) +{ + auto iIt = this->m_Data.find( name ); + if( iIt != this->m_Data.end( ) ) + { + this->m_Data.erase( iIt ); + + // Get children + std::vector< std::string > to_erase; + auto tIt = this->m_Tree.begin( ); + for( ; tIt != this->m_Tree.end( ); ++tIt ) + if( tIt->second == name ) + to_erase.push_back( tIt->first ); + + // Delete from tree + tIt = this->m_Tree.find( name ); + if( tIt != this->m_Tree.end( ) ) + this->m_Tree.erase( tIt ); + + // Recursive erase + auto dIt = to_erase.begin( ); + for( ; dIt != to_erase.end( ); ++dIt ) + this->DeleteData( *dIt ); + + // Delete from tree widget + /* TODO + QTreeWidgetItem* item = this->_FindItemInTree( name ); + if( item != NULL ) + this->m_UI->LoadedData->removeItemWidget( item, 0 ); + */ + + // Reset main image, just in case + if( this->m_Data.size( ) == 0 ) + this->m_MainImage = ""; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +DeleteAllData( ) +{ + this->m_MPRObjects->Clear( ); + this->m_Data.clear( ); + this->m_Tree.clear( ); + // TODO: this->m_UI->LoadedData->clear( ); + this->m_MainImage = ""; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +SetDataColor( + const std::string& name, const double& r, const double& g, const double& b + ) +{ + /* + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + return; + + if( iIt->second.Tag == Data::IMAGE ) + { + } + else if( iIt->second.Tag == Data::MESH ) + { + } // fi + */ +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +ShowData( const std::string& name ) +{ + auto iIt = this->m_Data.find( name ); + if( iIt == this->m_Data.end( ) ) + return; + + if( iIt->second.Tag == Data::IMAGE ) + { + if( name == this->m_MainImage ) + this->m_MPRObjects->SetInputImage( iIt->second.Image ); + else + { + unsigned int i = ( this->m_MPRObjects->GetNumberOfImages( ) - 1 ) % 8; + this->m_MPRObjects->AddBinaryImage( + iIt->second.Image, + Self::cm_Colors[ i ][ 0 ], + Self::cm_Colors[ i ][ 1 ], + Self::cm_Colors[ i ][ 2 ] + ); + } + this->m_MPRObjects->Show( ); + } + else if( iIt->second.Tag == Data::MESH ) + { + vtkRenderer* ren = + this->m_VTK[ 3 ]->GetRenderWindow( )-> + GetRenderers( )->GetFirstRenderer( ); + if( ren == NULL ) + return; + ren->AddActor( iIt->second.GetMeshActor( ) ); + this->m_VTK[ 3 ]->GetRenderWindow( )->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget:: +HideData( const std::string& name ) +{ +} + +// ------------------------------------------------------------------------- +vtkRenderWindowInteractor* cpExtensions::QT::SimpleMPRWidget:: +GetInteractor( unsigned int i ) +{ + if( i < 4 ) + { + if( this->m_VTK[ i ] != NULL ) + return( this->m_VTK[ i ]->GetInteractor( ) ); + else + return( NULL ); + } + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +/* + bool cpExtensions::QT::SimpleMPRWidget:: + ShowImage( + vtkImageData* image, + const std::string& name, + const std::string& parent + ) + { + // Update tree view + QTreeWidgetItem* new_item = this->_UpdateTreeItem( name, parent ); + if( new_item == NULL ) + return( false ); + + // Associate new data + this->m_Images[ name ] = image; + this->m_Tree[ name ] = parent; + + // Show image and return + this->m_MPRObjects->AddImage( image ); + return( true ); + } + + // ------------------------------------------------------------------------- + bool cpExtensions::QT::SimpleMPRWidget:: + ShowImage( + vtkImageData* image, + const std::string& name, + const std::string& parent, + const double& r, const double& g, const double& b + ) + { + // Update tree view + QTreeWidgetItem* new_item = this->_UpdateTreeItem( name, parent ); + if( new_item == NULL ) + return( false ); + + // Associate new data + this->m_Images[ name ] = image; + this->m_Tree[ name ] = parent; + + // Show image and return + this->m_MPRObjects->AddImage( image ); + return( true ); + } + + // ------------------------------------------------------------------------- + bool cpExtensions::QT::SimpleMPRWidget:: + ShowMesh( + vtkPolyData* mesh, + const std::string& name, + const std::string& parent + ) + { + // Update tree view + QTreeWidgetItem* new_item = this->_UpdateTreeItem( name, parent ); + if( new_item == NULL ) + return( false ); + + // Associate new data + PolyDataActor* actor = new PolyDataActor( mesh ); + this->m_Meshes[ name ] = actor; + this->m_Tree[ name ] = parent; + + // Show mesh + this->_Add3DActor( actor->Actor ); + return( true ); + } + + // ------------------------------------------------------------------------- + bool cpExtensions::QT::SimpleMPRWidget:: + ShowMesh( + vtkPolyData* mesh, + const std::string& name, + const std::string& parent, + const double& r, const double& g, const double& b + ) + { + return false; + } + + // ------------------------------------------------------------------------- + void cpExtensions::QT::SimpleMPRWidget:: + ClearAll( ) + { + this->m_MPRObjects->ClearAll( ); + this->m_Images.clear( ); + this->m_Meshes.clear( ); + } +*/ + +// ------------------------------------------------------------------------- +std::string cpExtensions::QT::SimpleMPRWidget:: +GetSelectedData( ) const +{ + /* TODO + QTreeWidgetItem* item = this->m_UI->LoadedData->currentItem( ); + if( item != NULL ) + return( item->text( 0 ).toStdString( ) ); + else + */ + return( "" ); +} + +// ------------------------------------------------------------------------- +/* TODO +QTreeWidgetItem* cpExtensions::QT::SimpleMPRWidget:: +_FindItemInTree( const std::string& name ) const +{ + QList< QTreeWidgetItem* > items = + this->m_UI->LoadedData->findItems( + name.c_str( ), Qt::MatchExactly | Qt::MatchRecursive + ); + if( items.size( ) > 0 ) + return( items[ 0 ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +QTreeWidgetItem* cpExtensions::QT::SimpleMPRWidget:: +_UpdateTreeItem( const std::string& name, const std::string& parent ) +{ + // Update tree view + QTreeWidgetItem* new_item = NULL; + if( parent != "" ) + { + QTreeWidgetItem* parent_item = this->_FindItemInTree( parent ); + if( parent_item != NULL ) + { + QTreeWidgetItem* old_item = this->_FindItemInTree( name ); + if( old_item == NULL ) + { + new_item = + new QTreeWidgetItem( parent_item, QStringList( name.c_str( ) ) ); + parent_item->setExpanded( true ); + + } // fi + + } // fi + } + else + { + new_item = new QTreeWidgetItem( + ( QTreeWidgetItem* )( NULL ), QStringList( name.c_str( ) ) + ); + this->m_UI->LoadedData->addTopLevelItem( new_item ); + + } // fi + return( new_item ); +} +*/ + +// ------------------------------------------------------------------------- +/* + void cpExtensions::QT::SimpleMPRWidget:: + _Add3DActor( vtkProp3D* prop ) + { + vtkRenderer* ren = + this->m_VTK[ 3 ]->GetRenderWindow( )->GetRenderers( )->GetFirstRenderer( ); + if( ren == NULL ) + return; + ren->AddActor( prop ); + 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( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget::PolyDataActor:: +PolyDataActor( ) + : Mesh( NULL ), + Normals( NULL ), + Stripper( NULL ), + Mapper( NULL ), + Actor( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget::PolyDataActor:: +~PolyDataActor( ) +{ + if( this->Actor != NULL ) this->Actor->Delete( ); + if( this->Mapper != NULL ) this->Mapper->Delete( ); + if( this->Stripper != NULL ) this->Stripper->Delete( ); + if( this->Normals != NULL ) this->Normals->Delete( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget::PolyDataActor:: +Configure( vtkPolyData* pd ) +{ + if( pd == NULL ) + return; + + double range[ 2 ]; + pd->GetScalarRange( range ); + + this->Normals = vtkPolyDataNormals::New( ); + this->Stripper = vtkStripper::New( ); + this->Mapper = vtkPolyDataMapper::New( ); + this->Actor = vtkQuadricLODActor::New( ); + + this->Mesh = pd; + this->Normals->SetInputData( pd ); + this->Normals->SetFeatureAngle( 60.0 ); + this->Stripper->SetInputConnection( this->Normals->GetOutputPort( ) ); + this->Mapper->SetInputConnection( this->Stripper->GetOutputPort( ) ); + this->Mapper->UseLookupTableScalarRangeOff( ); + this->Mapper->SetScalarRange( + range[ 0 ], ( ( range[ 1 ] - range[ 0 ] ) * 0.75 ) + range[ 0 ] + ); + this->Actor->SetMapper( this->Mapper ); + this->Actor->DeferLODConstructionOff( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget::Data:: +Data( ) +{ + this->Tag = Data::IMAGE; + this->Image = NULL; +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget::Data:: +~Data( ) +{ +} + +// ------------------------------------------------------------------------- +cpExtensions::QT::SimpleMPRWidget:: +Data& cpExtensions::QT::SimpleMPRWidget::Data:: +operator=( const Data& data ) +{ + this->Tag = data.Tag; + if( this->Tag == Data::IMAGE ) + this->Image = data.Image; + else if( this->Tag == Data::MESH ) + this->Mesh = data.Mesh; + return( *this ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget::Data:: +SetImageData( vtkImageData* data ) +{ + this->Tag = Data::IMAGE; + this->Image = data; +} + +// ------------------------------------------------------------------------- +void cpExtensions::QT::SimpleMPRWidget::Data:: +SetPolyData( vtkPolyData* data ) +{ + this->Tag = Data::MESH; + this->Mesh.Configure( data ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::QT::SimpleMPRWidget::Data:: +GetImage( ) +{ + if( this->Tag == Data::IMAGE ) + return( this->Image ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkPolyData* cpExtensions::QT::SimpleMPRWidget::Data:: +GetMesh( ) +{ + if( this->Tag == Data::MESH ) + return( this->Mesh.Mesh ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +vtkProp* cpExtensions::QT::SimpleMPRWidget::Data:: +GetMeshActor( ) +{ + if( this->Tag == Data::MESH ) + return( this->Mesh.Actor ); + else + return( NULL ); +} + +#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..c4d5ec5 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.h @@ -0,0 +1,147 @@ +#ifndef __CPEXTENSIONS__QT__SIMPLEMPRWIDGET__H__ +#define __CPEXTENSIONS__QT__SIMPLEMPRWIDGET__H__ + +#include + +#ifdef cpExtensions_QT4 + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +// ------------------------------------------------------------------------- +class QTreeWidgetItem; +class QVTKWidget; + +namespace Ui +{ + class SimpleMPRWidget; +} + +// ------------------------------------------------------------------------- +namespace cpExtensions +{ + namespace QT + { + /** + */ + class cpExtensions_EXPORT SimpleMPRWidget + : public QWidget + { + Q_OBJECT; + + public: + typedef SimpleMPRWidget Self; + + typedef cpExtensions::Visualization::MPRObjects TMPRObjects; + typedef TMPRObjects::TStyle TStyle; + typedef TMPRObjects::TMouseCommand TMouseCommand; + typedef TMPRObjects::TMouseWheelCommand TMouseWheelCommand; + typedef TMPRObjects::TKeyCommand TKeyCommand; + typedef TMPRObjects::TVoidCommand TVoidCommand; + typedef TMPRObjects::TMouseMoveCommand TMouseMoveCommand; + typedef TMPRObjects::TMouseClickCommand TMouseClickCommand; + typedef TMPRObjects::TMouseDoubleClickCommand TMouseDoubleClickCommand; + typedef TMPRObjects::TExposeCommand TExposeCommand; + typedef TMPRObjects::TConfigureCommand TConfigureCommand; + typedef TMPRObjects::TEnterCommand TEnterCommand; + typedef TMPRObjects::TLeaveCommand TLeaveCommand; + + public: + explicit SimpleMPRWidget( QWidget* parent = 0 ); + virtual ~SimpleMPRWidget( ); + + // Data management + unsigned int GetNumberOfData( ) const; + bool AddData( + vtkImageData* data, const std::string& name, + const std::string& parent + ); + bool AddData( + vtkPolyData* data, const std::string& name + ); + const std::string& GetMainImage( ) const; + bool SetMainImage( const std::string& name ); + void DeleteData( const std::string& name ); + void DeleteAllData( ); + + // Some qt accessors + void SetDataColor( + const std::string& name, + const double& r, const double& g, const double& b + ); + void ShowData( const std::string& name ); + void HideData( const std::string& name ); + + vtkRenderWindowInteractor* GetInteractor( unsigned int i ); + + // Visual objects accessors + std::string GetSelectedData( ) const; + + private slots: + void _SyncBottom( int a, int b ); + void _SyncTop( int a, int b ); + + protected: + static double cm_Colors[ 8 ][ 3 ]; + + Ui::SimpleMPRWidget* m_UI; + vtkSmartPointer< TMPRObjects > m_MPRObjects; + QVTKWidget* m_VTK[ 4 ]; + + struct PolyDataActor + { + vtkPolyData* Mesh; + vtkPolyDataNormals* Normals; + vtkStripper* Stripper; + vtkPolyDataMapper* Mapper; + vtkQuadricLODActor* Actor; + + PolyDataActor( ); + virtual ~PolyDataActor( ); + void Configure( vtkPolyData* pd ); + }; + + struct Data + { + enum { IMAGE, MESH } Tag; + vtkImageData* Image; + PolyDataActor Mesh; + + Data( ); + virtual ~Data( ); + + Data& operator=( const Data& data ); + + void SetImageData( vtkImageData* data ); + void SetPolyData( vtkPolyData* data ); + + vtkImageData* GetImage( ); + vtkPolyData* GetMesh( ); + vtkProp* GetMeshActor( ); + }; + + std::string m_MainImage; + std::map< std::string, Data > m_Data; + std::map< std::string, std::string > m_Tree; + }; + + } // 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..e468e92 --- /dev/null +++ b/lib/cpExtensions/QT/SimpleMPRWidget.ui @@ -0,0 +1,96 @@ + + + SimpleMPRWidget + + + + 0 + 0 + 424 + 424 + + + + Form + + + + + + + 406 + 406 + + + + Qt::Vertical + + + + + 406 + 200 + + + + Qt::Horizontal + + + + + 200 + 200 + + + + + + + 200 + 200 + + + + + + + + 406 + 200 + + + + Qt::Horizontal + + + + + 200 + 200 + + + + + + + 200 + 200 + + + + + + + + + + + QVTKWidget + QWidget +
QVTKWidget.h
+ 1 +
+
+ + +
\ No newline at end of file diff --git a/lib/cpExtensions/Visualization/Image3DMPR.cxx b/lib/cpExtensions/Visualization/Image3DMPR.cxx new file mode 100644 index 0000000..7812300 --- /dev/null +++ b/lib/cpExtensions/Visualization/Image3DMPR.cxx @@ -0,0 +1,364 @@ +#include + +#include +#include + +#include + +/** + */ +class cpPlugins_Extensions_Visualization_InteractionModeCallback + : public vtkCommand +{ +public: + static cpPlugins_Extensions_Visualization_InteractionModeCallback* New( ) + { + return( new cpPlugins_Extensions_Visualization_InteractionModeCallback ); + } + virtual void Execute( + vtkObject* caller, unsigned long eventId, void* arguments ) + { + if( eventId == vtkCommand::KeyPressEvent ) + { + vtkRenderWindowInteractor* iren = + static_cast< vtkRenderWindowInteractor* >( caller ); + if( caller == NULL ) + return; + + switch( iren->GetKeyCode( ) ) + { + case 'x': + case 'X': + { + bool eSeed = ( this->SeedWidget->GetProcessEvents( ) == 1 ); + if( eSeed ) + { + this->SeedWidget->ProcessEventsOff( ); + this->WidgetX->InteractionOn( ); + this->WidgetY->InteractionOn( ); + this->WidgetZ->InteractionOn( ); + } + else + { + this->SeedWidget->ProcessEventsOn( ); + this->WidgetX->InteractionOff( ); + this->WidgetY->InteractionOff( ); + this->WidgetZ->InteractionOff( ); + + } // fi + } + break; + case 'z': + case 'Z': + { + this->SeedWidget->ProcessEventsOff( ); + this->WidgetX->InteractionOff( ); + this->WidgetY->InteractionOff( ); + this->WidgetZ->InteractionOff( ); + } + break; + default: + break; + + } // hctiws + + } // fi + } + +public: + vtkImagePlaneWidget* WidgetX; + vtkImagePlaneWidget* WidgetY; + vtkImagePlaneWidget* WidgetZ; + vtkSeedWidget* SeedWidget; +}; + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::Image3DMPR:: +Image3DMPR( ) +{ + this->m_Outline = vtkSmartPointer< vtkOutlineSource >::New( ); + this->m_OutlineMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_OutlineActor = vtkSmartPointer< vtkActor >::New( ); + this->m_Picker = vtkSmartPointer< vtkCellPicker >::New( ); + this->m_WidgetX = vtkSmartPointer< vtkImagePlaneWidget >::New( ); + this->m_WidgetY = vtkSmartPointer< vtkImagePlaneWidget >::New( ); + this->m_WidgetZ = vtkSmartPointer< vtkImagePlaneWidget >::New( ); + this->m_Renderer = vtkSmartPointer< vtkRenderer >::New( ); + this->m_Window = vtkSmartPointer< vtkRenderWindow >::New( ); + this->m_Interactor = vtkSmartPointer< vtkRenderWindowInteractor >::New( ); + this->m_SeedHandleRepresentation = + vtkSmartPointer< vtkPointHandleRepresentation3D >::New( ); + this->m_SeedRepresentation = + vtkSmartPointer< vtkSeedRepresentation >::New( ); + this->m_SeedWidget = vtkSmartPointer::New(); + + this->m_SeedHandleRepresentation->GetProperty()->SetColor( 1, 0, 1 ); + this->m_SeedRepresentation-> + SetHandleRepresentation( this->m_SeedHandleRepresentation ); + this->m_SeedWidget->SetRepresentation( this->m_SeedRepresentation ); + + this->m_WidgetX->KeyPressActivationOff( ); + this->m_WidgetY->KeyPressActivationOff( ); + this->m_WidgetZ->KeyPressActivationOff( ); + this->m_SeedWidget->KeyPressActivationOff( ); + + typedef + cpPlugins_Extensions_Visualization_InteractionModeCallback + _TInteractionCB; + vtkSmartPointer< _TInteractionCB > int_cb = + vtkSmartPointer< _TInteractionCB >::New( ); + int_cb->WidgetX = this->m_WidgetX; + int_cb->WidgetY = this->m_WidgetY; + int_cb->WidgetZ = this->m_WidgetZ; + int_cb->SeedWidget = this->m_SeedWidget; + this->m_Interactor->AddObserver( vtkCommand::KeyPressEvent, int_cb ); + + typedef + cpExtensions::Visualization::SeedWidgetCorrector + _TCorrector; + vtkSmartPointer< _TCorrector > corr_cb = + vtkSmartPointer< _TCorrector >::New( ); + corr_cb->Configure( this->m_Picker ); + this->m_SeedWidget->AddObserver( vtkCommand::PlacePointEvent, corr_cb ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::Image3DMPR:: +~Image3DMPR( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +SetImage( vtkImageData* image ) +{ + this->m_Image = image; + + // Outline + this->m_Outline->SetBounds( this->m_Image->GetBounds( ) ); + this->m_OutlineMapper-> + SetInputConnection( this->m_Outline->GetOutputPort( ) ); + this->m_OutlineActor->SetMapper( this->m_OutlineMapper ); + this->m_OutlineActor->GetProperty( )->SetColor( 1, 1, 1 ); + + // Local picker + this->m_Picker->SetTolerance( 0.005 ); + + // Image planes + this->m_WidgetX->DisplayTextOn( ); + this->m_WidgetX->SetInputData( this->m_Image ); + this->m_WidgetX->SetPlaneOrientationToXAxes( ); + this->m_WidgetX->SetSliceIndex( this->m_Image->GetExtent( )[ 0 ] ); + this->m_WidgetX->SetPicker( this->m_Picker ); + this->m_WidgetX->SetKeyPressActivationValue( 'x' ); + this->m_WidgetX->GetPlaneProperty( )->SetLineWidth( 3 ); + this->m_WidgetX->GetPlaneProperty( )->SetColor( 0, 1, 1 ); + + this->m_WidgetY->DisplayTextOn( ); + this->m_WidgetY->SetInputData( this->m_Image ); + this->m_WidgetY->SetPlaneOrientationToYAxes( ); + this->m_WidgetY->SetSliceIndex( this->m_Image->GetExtent( )[ 2 ] ); + this->m_WidgetY->SetPicker( this->m_Picker ); + this->m_WidgetY->SetKeyPressActivationValue( 'y' ); + this->m_WidgetY->GetPlaneProperty( )->SetColor( 1, 0, 1 ); + this->m_WidgetY->GetPlaneProperty( )->SetLineWidth( 3 ); + this->m_WidgetY->SetLookupTable( this->m_WidgetX->GetLookupTable( ) ); + + this->m_WidgetZ->DisplayTextOn( ); + this->m_WidgetZ->SetInputData( this->m_Image ); + this->m_WidgetZ->SetPlaneOrientationToZAxes( ); + this->m_WidgetZ->SetSliceIndex( this->m_Image->GetExtent( )[ 4 ] ); + this->m_WidgetZ->SetPicker( this->m_Picker ); + this->m_WidgetZ->SetKeyPressActivationValue( 'z' ); + this->m_WidgetZ->GetPlaneProperty( )->SetColor( 1, 1, 0 ); + this->m_WidgetZ->GetPlaneProperty( )->SetLineWidth( 3 ); + this->m_WidgetZ->SetLookupTable( this->m_WidgetX->GetLookupTable( ) ); + + // Rendering stuff + this->m_Window->AddRenderer( this->m_Renderer ); + this->m_Interactor->SetRenderWindow( this->m_Window ); + + // Command + double spac[ 3 ]; + this->m_Image->GetSpacing( spac ); + double min_spacing = spac[ 0 ]; + for( unsigned int d = 1; d < 3; d++ ) + min_spacing = ( spac[ d ] < min_spacing )? spac[ d ]: min_spacing; + + vtkInteractorStyleSwitch* iswitch = + dynamic_cast< vtkInteractorStyleSwitch* >( + this->m_Interactor->GetInteractorStyle( ) + ); + if( iswitch != NULL ) + iswitch->SetCurrentStyleToTrackballCamera( ); + + // Add actors + this->m_Renderer->AddActor( this->m_OutlineActor ); + + // Prepare widgets + this->m_WidgetX->SetInteractor( this->m_Interactor ); + this->m_WidgetY->SetInteractor( this->m_Interactor ); + this->m_WidgetZ->SetInteractor( this->m_Interactor ); + this->m_SeedWidget->SetInteractor( this->m_Interactor ); + + this->m_WidgetX->On( ); + this->m_WidgetY->On( ); + this->m_WidgetZ->On( ); + this->m_SeedWidget->On( ); + this->m_SeedWidget->ProcessEventsOff( ); + this->m_Interactor->SetPicker( this->m_Picker ); + /* + this->m_Interactor->GetPickingManager( )->AddPicker( this->m_Picker ); + this->m_Interactor->GetPickingManager( )->EnabledOn( ); + */ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +SetBackground( double r, double g, double b ) +{ + this->m_Renderer->SetBackground( r, g, b ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +SetSize( unsigned int w, unsigned int h ) +{ + this->m_Window->SetSize( w, h ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +SetWindowLevel( double w, double l ) +{ + this->m_WidgetX->SetWindowLevel( w, l ); + this->m_WidgetY->SetWindowLevel( w, l ); + this->m_WidgetZ->SetWindowLevel( w, l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +AddPolyData( vtkPolyData* pd, double opacity ) +{ + unsigned int i = this->m_PolyDatas.size( ); + + this->m_PolyDatas.push_back( pd ); + this->m_Mappers.push_back( vtkSmartPointer< vtkPolyDataMapper >::New( ) ); + this->m_Actors.push_back( vtkSmartPointer< vtkActor >::New( ) ); + + this->m_Mappers[ i ]->SetInputData( pd ); + this->m_Actors[ i ]->SetMapper( this->m_Mappers[ i ] ); + this->m_Actors[ i ]->GetProperty( )->SetOpacity( opacity ); + this->m_Actors[ i ]->GetProperty( )->SetLineWidth( 3 ); + this->m_Actors[ i ]->GetProperty( )->SetPointSize( 5 ); + this->m_Renderer->AddActor( this->m_Actors[ i ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +AddPolyData( vtkPolyData* pd, double r, double g, double b, double opacity ) +{ + unsigned int i = this->m_PolyDatas.size( ); + + this->m_PolyDatas.push_back( pd ); + this->m_Mappers.push_back( vtkSmartPointer< vtkPolyDataMapper >::New( ) ); + this->m_Actors.push_back( vtkSmartPointer< vtkActor >::New( ) ); + + this->m_Mappers[ i ]->SetInputData( pd ); + this->m_Mappers[ i ]->ScalarVisibilityOff( ); + this->m_Actors[ i ]->SetMapper( this->m_Mappers[ i ] ); + this->m_Actors[ i ]->GetProperty( )->SetColor( r, g, b ); + this->m_Actors[ i ]->GetProperty( )->SetOpacity( opacity ); + this->m_Actors[ i ]->GetProperty( )->SetLineWidth( 3 ); + this->m_Actors[ i ]->GetProperty( )->SetPointSize( 5 ); + this->m_Renderer->AddActor( this->m_Actors[ i ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +AddPolyData( vtkPolyData* pd, vtkLookupTable* lut, double opacity ) +{ + unsigned int i = this->m_PolyDatas.size( ); + + this->m_PolyDatas.push_back( pd ); + this->m_Mappers.push_back( vtkSmartPointer< vtkPolyDataMapper >::New( ) ); + this->m_Actors.push_back( vtkSmartPointer< vtkActor >::New( ) ); + + this->m_Mappers[ i ]->SetInputData( pd ); + this->m_Mappers[ i ]->SetLookupTable( lut ); + this->m_Actors[ i ]->SetMapper( this->m_Mappers[ i ] ); + this->m_Actors[ i ]->GetProperty( )->SetOpacity( opacity ); + this->m_Renderer->AddActor( this->m_Actors[ i ] ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::Image3DMPR:: +GetNumberOfSeeds( ) const +{ + return( this->m_SeedRepresentation->GetNumberOfSeeds( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +GetSeed( int n, double* s ) const +{ + vtkHandleWidget* hWdg = this->m_SeedWidget->GetSeed( n ); + if( hWdg == NULL ) + return; + vtkHandleRepresentation* hRep = + dynamic_cast< vtkHandleRepresentation* >( hWdg->GetRepresentation( ) ); + if( hRep == NULL ) + return; + hRep->GetWorldPosition( s ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::Image3DMPR:: +AddSeed( const double& x, const double& y, const double& z ) const +{ + double pos[ 3 ] = { x, y, z }; + + int hnd_id = this->m_SeedRepresentation->CreateHandle( pos ); + vtkHandleWidget* hnd = this->m_SeedWidget->CreateNewHandle( ); + this->m_SeedRepresentation->GetHandleRepresentation( hnd_id )-> + SetWorldPosition( pos ); + hnd->SetEnabled( 1 ); + + return( this->GetNumberOfSeeds( ) - 1 ); +} + +// ------------------------------------------------------------------------- +vtkRenderWindow* cpExtensions::Visualization::Image3DMPR:: +GetWindow( ) const +{ + return( this->m_Window ); +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::Visualization::Image3DMPR:: +GetRenderer( ) const +{ + return( this->m_Renderer ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +Start( ) +{ + this->m_WidgetX->On( ); + this->m_WidgetY->On( ); + this->m_WidgetZ->On( ); + + this->m_Renderer->ResetCamera( ); + this->m_Interactor->Initialize( ); + this->m_Interactor->Start( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::Image3DMPR:: +Render( ) +{ + this->m_Window->Render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/Image3DMPR.h b/lib/cpExtensions/Visualization/Image3DMPR.h new file mode 100644 index 0000000..2cbb9b7 --- /dev/null +++ b/lib/cpExtensions/Visualization/Image3DMPR.h @@ -0,0 +1,95 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGE3DMPR__H__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGE3DMPR__H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT Image3DMPR + { + public: + Image3DMPR( ); + virtual ~Image3DMPR( ); + + void SetImage( vtkImageData* image ); + void SetBackground( double r, double g, double b ); + void SetSize( unsigned int w, unsigned int h ); + void SetWindowLevel( double w, double l ); + + void AddPolyData( vtkPolyData* pd, double opacity = double( 1 ) ); + void AddPolyData( + vtkPolyData* pd, + double r, double g, double b, double opacity = double( 1 ) + ); + void AddPolyData( + vtkPolyData* pd, + vtkLookupTable* lut, + double opacity = double( 1 ) + ); + + unsigned int GetNumberOfSeeds( ) const; + void GetSeed( int n, double* s ) const; + unsigned int AddSeed( + const double& x, const double& y, const double& z + ) const; + + vtkRenderWindow* GetWindow( ) const; + vtkRenderer* GetRenderer( ) const; + + void Start( ); + void Render( ); + + protected: + vtkSmartPointer< vtkImageData > m_Image; + vtkSmartPointer< vtkOutlineSource > m_Outline; + vtkSmartPointer< vtkPolyDataMapper > m_OutlineMapper; + vtkSmartPointer< vtkActor > m_OutlineActor; + vtkSmartPointer< vtkCellPicker > m_Picker; + vtkSmartPointer< vtkImagePlaneWidget > m_WidgetX; + vtkSmartPointer< vtkImagePlaneWidget > m_WidgetY; + vtkSmartPointer< vtkImagePlaneWidget > m_WidgetZ; + vtkSmartPointer< vtkRenderer > m_Renderer; + vtkSmartPointer< vtkRenderWindow > m_Window; + vtkSmartPointer< vtkRenderWindowInteractor > m_Interactor; + + std::vector< vtkSmartPointer< vtkPolyData > > m_PolyDatas; + std::vector< vtkSmartPointer< vtkPolyDataMapper > > m_Mappers; + std::vector< vtkSmartPointer< vtkActor > > m_Actors; + + // Create the widget and its representation + vtkSmartPointer< vtkPointHandleRepresentation3D > + m_SeedHandleRepresentation; + vtkSmartPointer< vtkSeedRepresentation > m_SeedRepresentation; + vtkSmartPointer< vtkSeedWidget > m_SeedWidget; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__VISUALIZATION__IMAGE3DMPR__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..e4bf27c --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageBlender.h @@ -0,0 +1,67 @@ +#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/ImageSliceActors.cxx b/lib/cpExtensions/Visualization/ImageSliceActors.cxx new file mode 100644 index 0000000..024fbe0 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceActors.cxx @@ -0,0 +1,1323 @@ +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +m_PlaneColors[ 3 ][ 3 ] = +{ + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 } +}; + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors* +cpExtensions::Visualization::ImageSliceActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetAxis( int axis ) +{ + this->m_ImageMapper->SetOrientation( axis ); + this->m_BlenderMapper->SetOrientation( axis ); + this->m_ImageMapper->Update( ); + this->m_BlenderMapper->Update( ); + this->SetSliceNumber( this->GetSliceNumberMinValue( ) ); + this->m_ImageActor->Modified( ); + this->m_BlenderActor->Modified( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetInputConnection( vtkAlgorithmOutput* aout ) +{ + // Get input vtkImageData + if( aout == NULL ) + return; + + // Create mapper and actors + this->m_ImageMapper->SetInputConnection( aout ); + this->_ConfigureInputImage( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetInputImage( vtkImageData* data ) +{ + // Get input vtkImageData + if( data == NULL ) + return; + + // Create mapper and actors + this->m_ImageMapper->SetInputData( data ); + this->_ConfigureInputImage( ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ) +{ + if( aout == NULL ) + return( -1 ); + this->m_Blender->AddInputConnection( aout ); + this->_ConfigureBinaryImage( r, g, b ); + return( this->m_Blender->GetNumberOfInputs( ) - 1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ) +{ + if( data == NULL ) + return( -1 ); + this->m_Blender->AddInputData( data ); + this->_ConfigureBinaryImage( r, g, b ); + return( this->m_Blender->GetNumberOfInputs( ) - 1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +Clear( ) +{ + // Unbind from container + this->RemoveAllItems( ); + + // Filters and mappers + this->m_ImageMapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); + this->m_ImageActor = vtkSmartPointer< vtkImageActor >::New( ); + this->m_Blender = vtkSmartPointer< TBlender >::New( ); + this->m_BlenderMapper = vtkSmartPointer< vtkImageSliceMapper >::New( ); + this->m_BlenderLUT = vtkSmartPointer< vtkLookupTable >::New( ); + this->m_BlenderActor = vtkSmartPointer< vtkImageActor >::New( ); + + this->m_ImageActor->SetMapper( this->m_ImageMapper ); + this->m_BlenderMapper-> + SetInputConnection( this->m_Blender->GetOutputPort( ) ); + + this->m_BlenderLUT->SetNumberOfTableValues( 1 ); + this->m_BlenderLUT->SetTableRange( 0, 1 ); + this->m_BlenderLUT->SetTableValue( 0, 0, 0, 0, 0 ); + this->m_BlenderLUT->Build( ); + + this->m_BlenderActor->SetMapper( this->m_BlenderMapper ); + this->m_BlenderActor->GetProperty( )->SetLookupTable( this->m_BlenderLUT ); + this->m_BlenderActor->GetProperty( )->UseLookupTableScalarRangeOn( ); + + // White cursor + vtkSmartPointer< vtkPoints > cursor_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > cursor_lines = + vtkSmartPointer< vtkCellArray >::New( ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_points->InsertNextPoint( 0, 0, 0 ); + cursor_lines->InsertNextCell( 2 ); + cursor_lines->InsertCellPoint( 0 ); + cursor_lines->InsertCellPoint( 1 ); + cursor_lines->InsertNextCell( 2 ); + cursor_lines->InsertCellPoint( 2 ); + cursor_lines->InsertCellPoint( 3 ); + + this->m_Cursor = vtkSmartPointer< vtkPolyData >::New( ); + this->m_CursorMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_CursorActor = vtkSmartPointer< vtkActor >::New( ); + + this->m_Cursor->SetPoints( cursor_points ); + this->m_Cursor->SetLines( cursor_lines ); + this->m_CursorMapper->SetInputData( this->m_Cursor ); + this->m_CursorActor->SetMapper( this->m_CursorMapper ); + this->m_CursorActor->GetProperty( )->SetColor( 1, 1, 0 ); + this->m_CursorActor->GetProperty( )->SetLineWidth( 2 ); + + // Plane intersections + this->m_Axis1 = vtkSmartPointer< vtkPolyData >::New( ); + this->m_Axis1Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_Axis1Actor = vtkSmartPointer< vtkActor >::New( ); + + vtkSmartPointer< vtkPoints > h_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > h_lines = + vtkSmartPointer< vtkCellArray >::New( ); + h_points->InsertNextPoint( 0, 0, 0 ); + h_points->InsertNextPoint( 0, 0, 0 ); + h_lines->InsertNextCell( 2 ); + h_lines->InsertCellPoint( 0 ); + h_lines->InsertCellPoint( 1 ); + this->m_Axis1->SetPoints( h_points ); + this->m_Axis1->SetLines( h_lines ); + this->m_Axis1Mapper->SetInputData( this->m_Axis1 ); + this->m_Axis1Actor->SetMapper( this->m_Axis1Mapper ); + + this->m_Axis2 = vtkSmartPointer< vtkPolyData >::New( ); + this->m_Axis2Mapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_Axis2Actor = vtkSmartPointer< vtkActor >::New( ); + + vtkSmartPointer< vtkPoints > v_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > v_lines = + vtkSmartPointer< vtkCellArray >::New( ); + v_points->InsertNextPoint( 0, 0, 0 ); + v_points->InsertNextPoint( 0, 0, 0 ); + v_lines->InsertNextCell( 2 ); + v_lines->InsertCellPoint( 0 ); + v_lines->InsertCellPoint( 1 ); + this->m_Axis2->SetPoints( v_points ); + this->m_Axis2->SetLines( v_lines ); + this->m_Axis2Mapper->SetInputData( this->m_Axis2 ); + this->m_Axis2Actor->SetMapper( this->m_Axis2Mapper ); + + // Plane + this->m_Plane = vtkSmartPointer< vtkPolyData >::New( ); + this->m_PlaneMapper = vtkSmartPointer< vtkPolyDataMapper >::New( ); + this->m_PlaneActor = vtkSmartPointer< vtkActor >::New( ); + + vtkSmartPointer< vtkPoints > plane_points = + vtkSmartPointer< vtkPoints >::New( ); + vtkSmartPointer< vtkCellArray > plane_lines = + vtkSmartPointer< vtkCellArray >::New( ); + plane_points->InsertNextPoint( 0, 0, 0 ); + plane_points->InsertNextPoint( 0, 1, 0 ); + plane_points->InsertNextPoint( 1, 1, 0 ); + plane_points->InsertNextPoint( 1, 0, 0 ); + plane_lines->InsertNextCell( 5 ); + plane_lines->InsertCellPoint( 0 ); + plane_lines->InsertCellPoint( 1 ); + plane_lines->InsertCellPoint( 2 ); + plane_lines->InsertCellPoint( 3 ); + plane_lines->InsertCellPoint( 0 ); + this->m_Plane->SetPoints( plane_points ); + this->m_Plane->SetLines( plane_lines ); + + this->m_PlaneMapper->SetInputData( this->m_Plane ); + this->m_PlaneActor->SetMapper( this->m_PlaneMapper ); + + // Text actor + this->m_TextActor = vtkSmartPointer< vtkTextActor >::New( ); + this->m_TextBuffer[ 0 ] = '\0'; + 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.01 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +AssociateSlice( Self* slice ) +{ + this->m_AssociatedSlices.push_back( slice ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors:: +GetStyle( ) +{ + return( this->m_Style.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +const vtkInteractorStyle* cpExtensions::Visualization::ImageSliceActors:: +GetStyle( ) const +{ + return( this->m_Style.GetPointer( ) ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::ImageSliceActors:: +GetInputImage( ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetInput( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::ImageSliceActors:: +GetInputImage( ) const +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetInput( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +PushActorsInto( vtkRenderWindow* window, bool force_style ) +{ + this->m_Window = window; + if( window == NULL ) + return; + vtkRenderWindowInteractor* rwi = window->GetInteractor( ); + vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( ); + if( rwi == NULL || renderer == NULL ) + return; + + // Update style + if( this->m_Style.GetPointer( ) != NULL && force_style ) + rwi->SetInteractorStyle( this->m_Style ); + + // Update actors + renderer->AddViewProp( this->m_ImageActor ); + renderer->AddViewProp( this->m_BlenderActor ); + if( force_style ) + { + renderer->AddViewProp( this->m_CursorActor ); + renderer->AddViewProp( this->m_PlaneActor ); + renderer->AddViewProp( this->m_TextActor ); + renderer->AddViewProp( this->m_Axis1Actor ); + renderer->AddViewProp( this->m_Axis2Actor ); + + } // fi + + // Configure camera + vtkCamera* camera = renderer->GetActiveCamera( ); + if( camera != NULL && force_style ) + { + // Parallel projections are better when displaying 2D images + int axis = this->GetAxis( ); + camera->ParallelProjectionOn( ); + camera->SetFocalPoint( double( 0 ), double( 0 ), double( 0 ) ); + if( axis == 0 ) + { + camera->SetPosition( double( 1 ), double( 0 ), double( 0 ) ); + camera->SetViewUp ( double( 0 ), double( 0 ), double( 1 ) ); + } + else if( axis == 1 ) + { + camera->SetPosition( double( 0 ), double( -1 ), double( 0 ) ); + camera->SetViewUp ( double( 0 ), double( 0 ), double( 1 ) ); + } + else // if( axis == 2 ) + { + camera->SetPosition( double( 0 ), double( 0 ), double( -1 ) ); + camera->SetViewUp ( double( 0 ), double( -1 ), double( 0 ) ); + + } // fi + + } // fi + renderer->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +PopActorsFrom( vtkRenderWindow* window ) +{ + vtkRenderWindowInteractor* rwi = window->GetInteractor( ); + vtkRenderer* renderer = window->GetRenderers( )->GetFirstRenderer( ); + if( renderer != NULL ) + { + renderer->RemoveViewProp( this->m_ImageActor ); + renderer->RemoveViewProp( this->m_BlenderActor ); + renderer->RemoveViewProp( this->m_CursorActor ); + renderer->RemoveViewProp( this->m_PlaneActor ); + renderer->RemoveViewProp( this->m_TextActor ); + renderer->RemoveViewProp( this->m_Axis1Actor ); + renderer->RemoveViewProp( this->m_Axis2Actor ); + + } // fi +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::ImageSliceActors:: +GetNumberOfImages( ) const +{ + return( this->m_Blender->GetNumberOfInputs( ) ); +} + +// ------------------------------------------------------------------------- +vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetImageActor( ) +{ + return( this->m_ImageActor ); +} + +// ------------------------------------------------------------------------- +const vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetImageActor( ) const +{ + return( this->m_ImageActor ); +} + +// ------------------------------------------------------------------------- +vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetBinaryActor( ) +{ + return( this->m_BlenderActor ); +} + +// ------------------------------------------------------------------------- +const vtkImageActor* cpExtensions::Visualization::ImageSliceActors:: +GetBinaryActor( ) const +{ + return( this->m_BlenderActor ); +} + +// ------------------------------------------------------------------------- +vtkTextActor* cpExtensions::Visualization::ImageSliceActors:: +GetTextActor( ) +{ + return( this->m_TextActor ); +} + +// ------------------------------------------------------------------------- +const vtkTextActor* cpExtensions::Visualization::ImageSliceActors:: +GetTextActor( ) const +{ + return( this->m_TextActor ); +} + +// ------------------------------------------------------------------------- +vtkActor* cpExtensions::Visualization::ImageSliceActors:: +GetPlaneActor( ) +{ + return( this->m_PlaneActor ); +} + +// ------------------------------------------------------------------------- +const vtkActor* cpExtensions::Visualization::ImageSliceActors:: +GetPlaneActor( ) const +{ + return( this->m_PlaneActor ); +} + +// ------------------------------------------------------------------------- +vtkPlane* cpExtensions::Visualization::ImageSliceActors:: +GetPlaneFunction( ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetSlicePlane( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const vtkPlane* cpExtensions::Visualization::ImageSliceActors:: +GetPlaneFunction( ) const +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetSlicePlane( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetInterpolate( bool v ) +{ + if( this->m_Interpolate != v ) + { + this->m_ImageActor->SetInterpolate( v ); + this->m_BlenderActor->SetInterpolate( v ); + this->m_Interpolate = v; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +InterpolateOn( ) +{ + this->SetInterpolate( true ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +InterpolateOff( ) +{ + this->SetInterpolate( false ); +} + +// ------------------------------------------------------------------------- +double* cpExtensions::Visualization::ImageSliceActors:: +GetDisplayBounds( ) const +{ + if( this->m_ImageActor.GetPointer( ) != NULL ) + return( this->m_ImageActor->GetDisplayBounds( ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +GetDisplayBounds( double bounds[ 6 ] ) const +{ + if( this->m_ImageActor.GetPointer( ) == NULL ) + { + bounds[ 0 ] = bounds[ 2 ] = bounds[ 4 ] = double( 0 ); + bounds[ 1 ] = bounds[ 3 ] = bounds[ 5 ] = double( -1 ); + } + else + this->m_ImageActor->GetDisplayBounds( bounds ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +ResetCursor( ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + { + double pos[] = + { + this->m_VisibleBounds[ 0 ], + this->m_VisibleBounds[ 2 ], + this->m_VisibleBounds[ 4 ] + }; + this->SetCursor( pos ); + } + else + { + vtkPoints* points = this->m_Cursor->GetPoints( ); + points->SetPoint( 0, 0, 0, 0 ); + points->SetPoint( 1, 0, 0, 0 ); + points->SetPoint( 2, 0, 0, 0 ); + points->SetPoint( 3, 0, 0, 0 ); + this->m_Cursor->Modified( ); + this->m_CursorMapper->Modified( ); + this->m_CursorActor->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetCursor( double pos[ 3 ] ) +{ + if( this->m_ImageMapper.GetPointer( ) == NULL ) + return; + + // Get ordered axes + int a0 = this->GetAxis( ); + int a1 = ( a0 + 1 ) % 3; + int a2 = ( a0 + 2 ) % 3; + int ma0 = a0 << 1; + int ma1 = a1 << 1; + int ma2 = a2 << 1; + + // Update cross + double* bounds = this->m_VisibleBounds; + double p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ]; + + p0[ a2 ] = p1[ a2 ] = pos[ a2 ]; + p2[ a1 ] = p3[ a1 ] = pos[ a1 ]; + p0[ a0 ] = p1[ a0 ] = p2[ a0 ] = p3[ a0 ] = bounds[ ma0 ]; + p0[ a1 ] = bounds[ ma1 ]; + p1[ a1 ] = bounds[ ma1 + 1 ]; + p2[ a2 ] = bounds[ ma2 ]; + p3[ a2 ] = bounds[ ma2 + 1 ]; + + vtkPoints* points = this->m_Cursor->GetPoints( ); + points->SetPoint( 0, p0 ); + points->SetPoint( 1, p1 ); + points->SetPoint( 2, p2 ); + points->SetPoint( 3, p3 ); + this->m_Cursor->Modified( ); + this->m_CursorMapper->Modified( ); + this->m_CursorActor->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +ResetAxesCursor( ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + { + double pos[] = + { + this->m_VisibleBounds[ 0 ], + this->m_VisibleBounds[ 2 ], + this->m_VisibleBounds[ 4 ] + }; + this->SetAxesCursor( pos ); + } + else + { + vtkPoints* points = this->m_Axis1->GetPoints( ); + points->SetPoint( 0, 0, 0, 0 ); + points->SetPoint( 1, 0, 0, 0 ); + this->m_Axis1->Modified( ); + this->m_Axis1Mapper->Modified( ); + this->m_Axis1Actor->Modified( ); + + points = this->m_Axis2->GetPoints( ); + points->SetPoint( 0, 0, 0, 0 ); + points->SetPoint( 1, 0, 0, 0 ); + this->m_Axis2->Modified( ); + this->m_Axis2Mapper->Modified( ); + this->m_Axis2Actor->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetAxesCursor( double pos[ 3 ] ) +{ + if( this->m_ImageMapper.GetPointer( ) == NULL ) + return; + + // Get ordered axes + int a0 = this->GetAxis( ); + int a1 = ( a0 + 1 ) % 3; + int a2 = ( a0 + 2 ) % 3; + int ma0 = a0 << 1; + int ma1 = a1 << 1; + int ma2 = a2 << 1; + + // Update cross + double* bounds = this->m_VisibleBounds; + double p0[ 3 ], p1[ 3 ], p2[ 3 ], p3[ 3 ]; + + p0[ a2 ] = p1[ a2 ] = pos[ a2 ]; + p2[ a1 ] = p3[ a1 ] = pos[ a1 ]; + p0[ a0 ] = p1[ a0 ] = p2[ a0 ] = p3[ a0 ] = bounds[ ma0 ]; + p0[ a1 ] = bounds[ ma1 ]; + p1[ a1 ] = bounds[ ma1 + 1 ]; + p2[ a2 ] = bounds[ ma2 ]; + p3[ a2 ] = bounds[ ma2 + 1 ]; + + vtkPoints* points1 = this->m_Axis1->GetPoints( ); + points1->SetPoint( 0, p2 ); + points1->SetPoint( 1, p3 ); + + vtkPoints* points2 = this->m_Axis2->GetPoints( ); + points2->SetPoint( 0, p0 ); + points2->SetPoint( 1, p1 ); + + this->m_Axis1->Modified( ); + this->m_Axis1Mapper->Modified( ); + this->m_Axis1Actor->Modified( ); + + this->m_Axis2->Modified( ); + this->m_Axis2Mapper->Modified( ); + this->m_Axis2Actor->Modified( ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetMinWindow( ) const +{ + return( this->m_WLRange[ 0 ] ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetMaxWindow( ) const +{ + return( this->m_WLRange[ 1 ] ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetMinLevel( ) const +{ + return( this->m_WLRange[ 2 ] ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetMaxLevel( ) const +{ + return( this->m_WLRange[ 3 ] ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetWindow( ) const +{ + if( this->m_ImageActor.GetPointer( ) != NULL ) + return( this->m_ImageActor->GetProperty( )->GetColorWindow( ) ); + else + return( double( 0 ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::ImageSliceActors:: +GetLevel( ) const +{ + if( this->m_ImageActor.GetPointer( ) != NULL ) + return( this->m_ImageActor->GetProperty( )->GetColorLevel( ) ); + else + return( double( 0 ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetWindow( double w ) +{ + if( this->m_ImageActor.GetPointer( ) == NULL ) + return; + double v = ( w < this->m_WLRange[ 0 ] )? this->m_WLRange[ 0 ]: w; + v = ( v > this->m_WLRange[ 1 ] )? this->m_WLRange[ 1 ]: v; + this->m_ImageActor->GetProperty( )->SetColorWindow( v ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetLevel( double l ) +{ + if( this->m_ImageActor.GetPointer( ) == NULL ) + return; + double v = ( l < this->m_WLRange[ 2 ] )? this->m_WLRange[ 2 ]: l; + v = ( v > this->m_WLRange[ 3 ] )? this->m_WLRange[ 3 ]: v; + this->m_ImageActor->GetProperty( )->SetColorLevel( v ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetWindowLevel( double w, double l ) +{ + if( this->m_ImageActor.GetPointer( ) == NULL ) + return; + double a = ( w < this->m_WLRange[ 0 ] )? this->m_WLRange[ 0 ]: w; + a = ( a > this->m_WLRange[ 1 ] )? this->m_WLRange[ 1 ]: a; + double b = ( l < this->m_WLRange[ 2 ] )? this->m_WLRange[ 2 ]: l; + b = ( b > this->m_WLRange[ 3 ] )? this->m_WLRange[ 3 ]: b; + this->m_ImageActor->GetProperty( )->SetColorWindow( a ); + this->m_ImageActor->GetProperty( )->SetColorLevel( b ); + this->UpdateText( a, b ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +ResetWindowLevel( ) +{ + this->SetWindowLevel( + this->m_WLRange[ 1 ] * double( 0.5 ), + ( this->m_WLRange[ 3 ] + this->m_WLRange[ 2 ] ) * double( 0.5 ) + ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +GetAxis( ) const +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetOrientation( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +GetSliceNumber( ) const +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetSliceNumber( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +GetSliceNumberMinValue( ) const +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetSliceNumberMinValue( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::ImageSliceActors:: +GetSliceNumberMaxValue( ) const +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + return( this->m_ImageMapper->GetSliceNumberMaxValue( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetSliceNumber( const int& slice ) +{ + if( this->m_ImageMapper.GetPointer( ) == NULL ) + return; + + int axis = this->GetAxis( ); + double prev_pos = this->m_VisibleBounds[ axis << 1 ]; + + // Update mappers and display bounds + this->m_ImageMapper->SetSliceNumber( slice ); + this->m_BlenderMapper->SetSliceNumber( slice ); + this->m_ImageMapper->Modified( ); + this->m_BlenderMapper->Modified( ); + this->m_ImageActor->Modified( ); + this->m_BlenderActor->Modified( ); + + // Update display extent (this isn't done automatically) + this->m_ImageMapper->GetInput( )->GetExtent( this->m_VisibleExtent ); + this->m_VisibleExtent[ axis << 1 ] = slice; + this->m_VisibleExtent[ ( axis << 1 ) + 1 ] = slice; + this->m_ImageActor->SetDisplayExtent( this->m_VisibleExtent ); + + // Prepare plane data + this->m_ImageMapper->GetBounds( this->m_VisibleBounds ); + double x0[][ 3 ] = + { + { + this->m_VisibleBounds[ 0 ], + this->m_VisibleBounds[ 2 ], + this->m_VisibleBounds[ 4 ] + }, + { + this->m_VisibleBounds[ 1 ], + this->m_VisibleBounds[ 3 ], + this->m_VisibleBounds[ 5 ] + } + }; + double p0[ 2 ][ 3 ]; + + vtkPlane* plane = this->m_ImageMapper->GetSlicePlane( ); + plane->GeneralizedProjectPoint( x0[ 0 ], p0[ 0 ] ); + plane->GeneralizedProjectPoint( x0[ 1 ], p0[ 1 ] ); + + this->m_VisibleBounds[ 0 ] = p0[ 0 ][ 0 ]; + this->m_VisibleBounds[ 1 ] = p0[ 1 ][ 0 ]; + this->m_VisibleBounds[ 2 ] = p0[ 0 ][ 1 ]; + this->m_VisibleBounds[ 3 ] = p0[ 1 ][ 1 ]; + this->m_VisibleBounds[ 4 ] = p0[ 0 ][ 2 ]; + this->m_VisibleBounds[ 5 ] = p0[ 1 ][ 2 ]; + double* bnds = this->m_VisibleBounds; + + // Configure visualization and implicit plane orientation + this->m_PlaneActor->GetProperty( )->SetRepresentationToWireframe( ); + this->m_PlaneActor->GetProperty( )->SetLineWidth( 3 ); + vtkPoints* plane_points = this->m_Plane->GetPoints( ); + plane_points->SetPoint( 0, bnds[ 0 ], bnds[ 2 ], bnds[ 4 ] ); + plane_points->SetPoint( 2, bnds[ 1 ], bnds[ 3 ], bnds[ 5 ] ); + if( axis == 0 || axis == 2 ) // YZ, x-normal + { + plane_points->SetPoint( 1, bnds[ 1 ], bnds[ 2 ], bnds[ 5 ] ); + plane_points->SetPoint( 3, bnds[ 0 ], bnds[ 3 ], bnds[ 4 ] ); + } + else if( axis == 1 ) // ZX, y-normal + { + plane_points->SetPoint( 1, bnds[ 0 ], bnds[ 2 ], bnds[ 5 ] ); + plane_points->SetPoint( 3, bnds[ 1 ], bnds[ 3 ], bnds[ 4 ] ); + + } // fi + + // Set plane colors + this->m_PlaneActor->GetProperty( )-> + SetColor( this->m_PlaneColors[ axis ] ); + this->m_Axis1Actor->GetProperty( )-> + SetColor( this->m_PlaneColors[ ( axis + 1 ) % 3 ] ); + this->m_Axis2Actor->GetProperty( )-> + SetColor( this->m_PlaneColors[ ( axis + 2 ) % 3 ] ); + + this->m_Plane->Modified( ); + this->m_PlaneMapper->Modified( ); + this->m_PlaneActor->Modified( ); + + this->m_Axis1->Modified( ); + this->m_Axis1Mapper->Modified( ); + this->m_Axis1Actor->Modified( ); + + this->m_Axis2->Modified( ); + this->m_Axis2Mapper->Modified( ); + this->m_Axis2Actor->Modified( ); + + // Update text + this->UpdateText( ); + + // Update camera position + if( this->m_Window == NULL ) + return; + vtkRenderer* renderer = + this->m_Window->GetRenderers( )->GetFirstRenderer( ); + if( renderer == NULL ) + return; + vtkCamera* camera = renderer->GetActiveCamera( ); + if( camera == NULL ) + return; + double cam_pos[ 3 ]; + camera->GetPosition( cam_pos ); + cam_pos[ axis ] += this->m_VisibleBounds[ axis << 1 ] - prev_pos; + camera->SetPosition( cam_pos ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +SetSlice( double* pos ) +{ + vtkImageData* image = this->GetInputImage( ); + if( image == NULL ) + return; + + int ijk[ 3 ]; + double pcoords[ 3 ]; + image->ComputeStructuredCoordinates( pos, ijk, pcoords ); + this->SetSliceNumber( ijk[ this->GetAxis( ) ] ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +UpdateText( ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + { + char axis; + int axId = this->m_ImageMapper->GetOrientation( ); + if ( axId == 0 ) axis = 'X'; + else if( axId == 1 ) axis = 'Y'; + else if( axId == 2 ) axis = 'Z'; + +#if defined(WIN32) + sprintf_s( + this->m_TextBuffer, 1024, "Axis: %c (%d)", + axis, this->m_ImageMapper->GetSliceNumber( ) + ); +#else // defined(WIN32) + std::sprintf( + this->m_TextBuffer, "Axis: %c (%d)", + axis, this->m_ImageMapper->GetSliceNumber( ) + ); +#endif // defined(WIN32) + } + else + this->m_TextBuffer[ 0 ] = '\0'; + this->m_TextActor->SetInput( this->m_TextBuffer ); + this->m_TextActor->Modified( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +UpdateText( double pos[ 3 ] ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + { + char axis; + int axId = this->m_ImageMapper->GetOrientation( ); + if ( axId == 0 ) axis = 'X'; + else if( axId == 1 ) axis = 'Y'; + else if( axId == 2 ) axis = 'Z'; + int slice = this->GetSliceNumber( ); + + vtkImageData* image = this->GetInputImage( ); + 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, 1024, "Axis: %c (%d)\nPixel %s", + axis, slice, str.str( ).c_str( ) + ); +#else // defined(WIN32) + std::sprintf( + this->m_TextBuffer, "Axis: %c (%d)\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:: +UpdateText( const double& w, const double& l ) +{ + if( this->m_ImageMapper.GetPointer( ) != NULL ) + { + char axis; + int axId = this->m_ImageMapper->GetOrientation( ); + if ( axId == 0 ) axis = 'X'; + else if( axId == 1 ) axis = 'Y'; + else if( axId == 2 ) axis = 'Z'; + +#if defined(WIN32) + sprintf_s( + this->m_TextBuffer, 1024, "Axis: %c (%d)\nW/L (%.2f/%.2f)", + axis, this->m_ImageMapper->GetSliceNumber( ), w, l + ); +#else // defined(WIN32) + std::sprintf( + this->m_TextBuffer, "Axis: %c (%d)\nW/L (%.2f/%.2f)", + axis, this->m_ImageMapper->GetSliceNumber( ), w, l + ); +#endif // defined(WIN32) + } + else + this->m_TextBuffer[ 0 ] = '\0'; + this->m_TextActor->SetInput( this->m_TextBuffer ); + this->m_TextActor->Modified( ); + this->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +Render( ) +{ + if( this->m_Window == NULL ) + return; + vtkRenderer* renderer = + this->m_Window->GetRenderers( )->GetFirstRenderer( ); + if( renderer == NULL ) + return; + renderer->SetAllocatedRenderTime( 1e-3 ); + this->m_Window->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +ResetCamera( ) +{ + if( this->m_Window == NULL ) + return; + vtkRenderer* renderer = + this->m_Window->GetRenderers( )->GetFirstRenderer( ); + if( renderer == NULL ) + return; + renderer->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +ImageSliceActors( ) + : Superclass( ), + m_Window( NULL ), + m_Interpolate( false ) +{ + this->Clear( ); + this->_ConfigureStyle( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::ImageSliceActors:: +~ImageSliceActors( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_ConfigureStyle( ) +{ + // Connect this view with a controller + this->m_Style = vtkSmartPointer< TStyle >::New( ); + this->m_Style->SetAssociatedObject( this ); + this->m_Style->AddMouseMoveCommand( Self::_MouseMoveCommand, this ); + this->m_Style->AddMouseClickCommand( Self::_MouseClickCommand, this ); + this->m_Style->AddMouseWheelCommand( Self::_MouseWheelCommand, this ); + this->m_Style->AddKeyCommand( Self::_KeyCommand, this ); + this->m_Style->AddEnterCommand( Self::_EnterCommand, this ); + this->m_Style->AddLeaveCommand( Self::_LeaveCommand, this ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_ConfigureInputImage( ) +{ + this->m_ImageMapper->SetOrientation( 0 ); + this->m_ImageMapper->Update( ); + + // Create actor + this->m_ImageActor->SetInterpolate( this->m_Interpolate ); + this->m_ImageActor->Modified( ); + + if( this->m_Style.GetPointer( ) != NULL ) + this->m_Style->AssociateImageActor( this->m_ImageActor ); + this->AddItem( this->m_ImageActor ); + + 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:: +_ConfigureBinaryImage( const double& r, const double& g, const double& b ) +{ + unsigned int nValues = this->m_BlenderLUT->GetNumberOfTableValues( ); + this->m_BlenderLUT->SetNumberOfTableValues( nValues + 1 ); + this->m_BlenderLUT->SetTableRange( 0, nValues ); + this->m_BlenderLUT->SetTableValue( nValues, r, g, b, 0.5 ); + this->m_BlenderLUT->Build( ); + + this->m_BlenderLUT->Modified( ); + this->m_Blender->Modified( ); + this->m_Blender->Update( ); + + this->m_BlenderMapper->Modified( ); + this->m_BlenderActor->Modified( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_MouseMoveCommand( + void* data, const TStyle::ButtonID& btn, int* idx, double* pos, + bool alt, bool ctr, bool sft + ) +{ + ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data ); + if( actors == NULL ) + return; + + if( btn == TStyle::ButtonID_None ) + { + // Just show the pixel information + actors->SetCursor( pos ); + actors->UpdateText( pos ); + actors->Render( ); + } + else if( btn == TStyle::ButtonID_Left ) + { + if( !alt && ctr && !sft ) + { + // Show axes in current renderer + actors->SetAxesCursor( pos ); + actors->Render( ); + + // Interactively move slices + auto i = actors->m_SlicesCommands.begin( ); + for( ; i != actors->m_SlicesCommands.end( ); ++i ) + i->first( pos, actors->GetAxis( ), i->second ); + + } // fi + } + else if( btn == TStyle::ButtonID_Right ) + { + if( !alt && !ctr && sft ) + { + // Change image window level + double bounds[ 6 ]; + actors->m_ImageMapper->GetBounds( bounds ); + + int a0 = actors->GetAxis( ); + int a1 = ( a0 + 1 ) % 3; + int a2 = ( a0 + 2 ) % 3; + double dx = pos[ a1 ] - actors->m_StartWindowLevelPos[ a1 ]; + double dy = pos[ a2 ] - actors->m_StartWindowLevelPos[ a2 ]; + dx /= bounds[ ( a1 << 1 ) + 1 ] - bounds[ a1 << 1 ]; + dy /= bounds[ ( a2 << 1 ) + 1 ] - bounds[ a2 << 1 ]; + + dx *= actors->m_StartWindowLevel[ 0 ]; + dy *= actors->m_StartWindowLevel[ 1 ]; + dx += actors->m_StartWindowLevel[ 0 ]; + dy += actors->m_StartWindowLevel[ 1 ]; + actors->SetWindowLevel( dx, dy ); + actors->Render( ); + + // Associate objects + auto i = actors->m_WindowLevelCommands.begin( ); + for( ; i != actors->m_WindowLevelCommands.end( ); ++i ) + i->first( dx, dy, i->second ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_MouseClickCommand( + void* data, const TStyle::ButtonID& btn, int* idx, double* pos, + bool alt, bool ctr, bool sft + ) +{ + ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data ); + if( actors == NULL ) + return; + + actors->m_StartWindowLevelPos[ 0 ] = pos[ 0 ]; + actors->m_StartWindowLevelPos[ 1 ] = pos[ 1 ]; + actors->m_StartWindowLevelPos[ 2 ] = pos[ 2 ]; + actors->m_StartWindowLevel[ 0 ] = actors->GetWindow( ); + actors->m_StartWindowLevel[ 1 ] = actors->GetLevel( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_MouseWheelCommand( + void* data, const int& dir, + bool alt, bool ctr, bool sft + ) +{ + ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data ); + if( actors == NULL ) + return; + + if( !alt && !ctr ) + { + int slice = actors->GetSliceNumber( ) + ( dir * ( ( sft )? 10: 1 ) ); + if( slice < actors->GetSliceNumberMinValue( ) ) + slice = actors->GetSliceNumberMinValue( ); + if( slice > actors->GetSliceNumberMaxValue( ) ) + slice = actors->GetSliceNumberMaxValue( ); + actors->SetSliceNumber( slice ); + actors->Render( ); + + auto a = actors->m_AssociatedSlices.begin( ); + for( ; a != actors->m_AssociatedSlices.end( ); ++a ) + ( *a )->SetSliceNumber( slice ); + + // Associate objects + auto i = actors->m_RenderCommands.begin( ); + for( ; i != actors->m_RenderCommands.end( ); ++i ) + i->first( i->second ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_KeyCommand( void* data, const char& key ) +{ + ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data ); + if( actors == NULL ) + return; + + switch( key ) + { + case 'r': case 'R': + { + actors->ResetCamera( ); + actors->Render( ); + + // Associate objects + auto i = actors->m_RenderCommands.begin( ); + for( ; i != actors->m_RenderCommands.end( ); ++i ) + i->first( i->second ); + } + break; + case 'w': case 'W': + { + actors->ResetWindowLevel( ); + actors->Render( ); + + // Associate objects + auto i = actors->m_RenderCommands.begin( ); + for( ; i != actors->m_RenderCommands.end( ); ++i ) + i->first( i->second ); + } + break; + default: + break; + } // hctiws +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_EnterCommand( void* data ) +{ + ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data ); + if( actors == NULL ) + return; + + actors->ResetCursor( ); + actors->m_CursorActor->VisibilityOn( ); + actors->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::ImageSliceActors:: +_LeaveCommand( void* data ) +{ + ImageSliceActors* actors = reinterpret_cast< ImageSliceActors* >( data ); + if( actors == NULL ) + return; + + actors->ResetCursor( ); + actors->m_CursorActor->VisibilityOff( ); + actors->Render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/ImageSliceActors.h b/lib/cpExtensions/Visualization/ImageSliceActors.h new file mode 100644 index 0000000..b4cec90 --- /dev/null +++ b/lib/cpExtensions/Visualization/ImageSliceActors.h @@ -0,0 +1,236 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__IMAGESLICEACTORS__H__ +#define __CPEXTENSIONS__VISUALIZATION__IMAGESLICEACTORS__H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// ------------------------------------------------------------------------- +class vtkAlgorithmOutput; +class vtkImageData; +class vtkLookupTable; +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; + + typedef cpExtensions::Visualization::ImageBlender TBlender; + + public: + vtkTypeMacro( ImageSliceActors, vtkPropCollection ); + + cpExtensions_BaseInteractorStyle_Commands( Slices ); + cpExtensions_BaseInteractorStyle_Commands( WindowLevel ); + cpExtensions_BaseInteractorStyle_Commands( Render ); + + public: + // Creation + static ImageSliceActors* New( ); + + void SetAxis( int axis ); + void SetInputConnection( vtkAlgorithmOutput* aout ); + void SetInputImage( vtkImageData* data ); + int AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ); + int AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ); + void Clear( ); + + void AssociateSlice( Self* slice ); + + vtkImageData* GetInputImage( ); + const vtkImageData* GetInputImage( ) const; + + vtkInteractorStyle* GetStyle( ); + const vtkInteractorStyle* GetStyle( ) const; + + void PushActorsInto( vtkRenderWindow* window, bool force_style = true ); + void PopActorsFrom( vtkRenderWindow* window ); + unsigned int GetNumberOfImages( ) const; + + vtkImageActor* GetImageActor( ); + const vtkImageActor* GetImageActor( ) const; + vtkImageActor* GetBinaryActor( ); + const vtkImageActor* GetBinaryActor( ) const; + vtkTextActor* GetTextActor( ); + const vtkTextActor* GetTextActor( ) const; + vtkActor* GetPlaneActor( ); + const vtkActor* GetPlaneActor( ) const; + vtkPlane* GetPlaneFunction( ); + const vtkPlane* GetPlaneFunction( ) const; + + void SetInterpolate( bool v ); + void InterpolateOn( ); + void InterpolateOff( ); + + double* GetDisplayBounds( ) const; + void GetDisplayBounds( double bounds[ 6 ] ) const; + + void ResetCursor( ); + void SetCursor( double pos[ 3 ] ); + + void ResetAxesCursor( ); + void SetAxesCursor( double pos[ 3 ] ); + + double GetMinWindow( ) const; + double GetMaxWindow( ) const; + double GetMinLevel( ) const; + double GetMaxLevel( ) const; + double GetWindow( ) const; + double GetLevel( ) const; + void SetWindow( double w ); + void SetLevel( double l ); + void SetWindowLevel( double w, double l ); + void ResetWindowLevel( ); + + int GetAxis( ) const; + int GetSliceNumber( ) const; + int GetSliceNumberMinValue( ) const; + int GetSliceNumberMaxValue( ) const; + void SetSliceNumber( const int& slice ); + void SetSlice( double* pos ); + void UpdateText( ); + void UpdateText( double pos[ 3 ] ); + void UpdateText( const double& w, const double& l ); + + void Render( ); + void ResetCamera( ); + + protected: + ImageSliceActors( ); + virtual ~ImageSliceActors( ); + + void _ConfigureStyle( ); + void _ConfigureInputImage( ); + void _ConfigureBinaryImage( + const double& r, const double& g, const double& b + ); + + // 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: + static double m_PlaneColors[ 3 ][ 3 ]; + + vtkSmartPointer< TStyle > m_Style; + vtkRenderWindow* m_Window; + + // Multiple actors + vtkSmartPointer< vtkImageSliceMapper > m_ImageMapper; + vtkSmartPointer< vtkImageActor > m_ImageActor; + + vtkSmartPointer< vtkImageData > m_BlenderBase; + vtkSmartPointer< TBlender > m_Blender; + vtkSmartPointer< vtkImageSliceMapper > m_BlenderMapper; + vtkSmartPointer< vtkLookupTable > m_BlenderLUT; + vtkSmartPointer< vtkImageActor > m_BlenderActor; + + bool m_Interpolate; + + double m_WLRange[ 4 ]; + + int m_VisibleExtent[ 6 ]; + double m_VisibleBounds[ 6 ]; + + // Associated slices + std::vector< Self* > m_AssociatedSlices; + + // Unique objects + vtkSmartPointer< vtkPolyData > m_Cursor; + vtkSmartPointer< vtkPolyDataMapper > m_CursorMapper; + vtkSmartPointer< vtkActor > m_CursorActor; + + vtkSmartPointer< vtkPolyData > m_Axis1; + vtkSmartPointer< vtkPolyDataMapper > m_Axis1Mapper; + vtkSmartPointer< vtkActor > m_Axis1Actor; + + vtkSmartPointer< vtkPolyData > m_Axis2; + vtkSmartPointer< vtkPolyDataMapper > m_Axis2Mapper; + vtkSmartPointer< vtkActor > m_Axis2Actor; + + vtkSmartPointer< vtkPolyData > m_Plane; + vtkSmartPointer< vtkPolyDataMapper > m_PlaneMapper; + vtkSmartPointer< vtkActor > m_PlaneActor; + + char m_TextBuffer[ 1024 ]; + vtkSmartPointer< vtkTextActor > m_TextActor; + + double m_StartWindowLevelPos[ 3 ]; + double m_StartWindowLevel[ 2 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__VISUALIZATION__IMAGESLICEACTORS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MPRActors.cxx b/lib/cpExtensions/Visualization/MPRActors.cxx new file mode 100644 index 0000000..e26651b --- /dev/null +++ b/lib/cpExtensions/Visualization/MPRActors.cxx @@ -0,0 +1,500 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRActors* +cpExtensions::Visualization::MPRActors:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +ImageSliceActors* cpExtensions::Visualization::MPRActors:: +GetSliceActors( const int& i ) const +{ + if( i < 3 ) + return( this->Slices[ 0 ][ i ] ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetInputConnection( vtkAlgorithmOutput* aout ) +{ + for( int i = 0; i < 2; ++i ) + { + for( int j = 0; j < 3; ++j ) + { + this->Slices[ i ][ j ]->SetInputConnection( aout ); + this->Slices[ i ][ j ]->SetAxis( j ); + + } // rof + + } // rof + this->_CreateBoundingBox( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetInputImage( vtkImageData* data ) +{ + for( int i = 0; i < 2; ++i ) + { + for( int j = 0; j < 3; ++j ) + { + this->Slices[ i ][ j ]->SetInputImage( data ); + this->Slices[ i ][ j ]->SetAxis( j ); + + } // rof + + } // rof + this->_CreateBoundingBox( ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRActors:: +AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ) +{ + this->Slices[ 0 ][ 0 ]->AddBinaryConnection( aout, r, g, b ); + this->Slices[ 0 ][ 1 ]->AddBinaryConnection( aout, r, g, b ); + this->Slices[ 0 ][ 2 ]->AddBinaryConnection( aout, r, g, b ); + this->Slices[ 1 ][ 0 ]->AddBinaryConnection( aout, r, g, b ); + this->Slices[ 1 ][ 1 ]->AddBinaryConnection( aout, r, g, b ); + return( this->Slices[ 1 ][ 2 ]->AddBinaryConnection( aout, r, g, b ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRActors:: +AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ) +{ + this->Slices[ 0 ][ 0 ]->AddBinaryImage( data, r, g, b ); + this->Slices[ 0 ][ 1 ]->AddBinaryImage( data, r, g, b ); + this->Slices[ 0 ][ 2 ]->AddBinaryImage( data, r, g, b ); + this->Slices[ 1 ][ 0 ]->AddBinaryImage( data, r, g, b ); + this->Slices[ 1 ][ 1 ]->AddBinaryImage( data, r, g, b ); + return( this->Slices[ 1 ][ 2 ]->AddBinaryImage( data, r, g, b ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +Clear( ) +{ + this->Slices[ 0 ][ 0 ]->Clear( ); + this->Slices[ 0 ][ 1 ]->Clear( ); + this->Slices[ 0 ][ 2 ]->Clear( ); + this->Slices[ 1 ][ 0 ]->Clear( ); + this->Slices[ 1 ][ 1 ]->Clear( ); + this->Slices[ 1 ][ 2 ]->Clear( ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::MPRActors:: +GetInputImage( ) +{ + return( this->Slices[ 0 ][ 0 ]->GetInputImage( ) ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::MPRActors:: +GetInputImage( ) const +{ + return( this->Slices[ 0 ][ 0 ]->GetInputImage( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::MPRActors:: +GetNumberOfImages( ) const +{ + return( this->Slices[ 0 ][ 0 ]->GetNumberOfImages( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetInterpolate( bool v ) +{ + this->Slices[ 0 ][ 0 ]->SetInterpolate( v ); + this->Slices[ 0 ][ 1 ]->SetInterpolate( v ); + this->Slices[ 0 ][ 2 ]->SetInterpolate( v ); + this->Slices[ 1 ][ 0 ]->SetInterpolate( v ); + this->Slices[ 1 ][ 1 ]->SetInterpolate( v ); + this->Slices[ 1 ][ 2 ]->SetInterpolate( v ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +InterpolateOn( ) +{ + this->SetInterpolate( true ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +InterpolateOff( ) +{ + this->SetInterpolate( false ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +PushActorsInto( + vtkRenderWindow* x, + vtkRenderWindow* y, + vtkRenderWindow* z, + vtkRenderWindow* w + ) +{ + this->Slices[ 0 ][ 0 ]->PushActorsInto( x, true ); + this->Slices[ 0 ][ 1 ]->PushActorsInto( y, true ); + this->Slices[ 0 ][ 2 ]->PushActorsInto( z, true ); + this->Slices[ 1 ][ 0 ]->PushActorsInto( w, false ); + this->Slices[ 1 ][ 1 ]->PushActorsInto( w, false ); + this->Slices[ 1 ][ 2 ]->PushActorsInto( w, false ); + + vtkRenderer* wren = + ( w != NULL )? w->GetRenderers( )->GetFirstRenderer( ): NULL; + if( wren != NULL ) + { + wren->AddViewProp( this->ImageOutlineActor ); + wren->AddViewProp( this->Slices[ 1 ][ 0 ]->GetPlaneActor( ) ); + wren->AddViewProp( this->Slices[ 1 ][ 1 ]->GetPlaneActor( ) ); + wren->AddViewProp( this->Slices[ 1 ][ 2 ]->GetPlaneActor( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +PopActorsFrom( + vtkRenderWindow* x, + vtkRenderWindow* y, + vtkRenderWindow* z, + vtkRenderWindow* w + ) +{ + this->Slices[ 0 ][ 0 ]->PopActorsFrom( x ); + this->Slices[ 0 ][ 1 ]->PopActorsFrom( y ); + this->Slices[ 0 ][ 2 ]->PopActorsFrom( z ); + this->Slices[ 1 ][ 0 ]->PopActorsFrom( w ); + this->Slices[ 1 ][ 1 ]->PopActorsFrom( w ); + this->Slices[ 1 ][ 2 ]->PopActorsFrom( w ); + + vtkRenderer* wren = + ( w != NULL )? w->GetRenderers( )->GetFirstRenderer( ): NULL; + if( wren != NULL ) + { + wren->RemoveViewProp( this->ImageOutlineActor ); + wren->RemoveViewProp( this->Slices[ 1 ][ 0 ]->GetPlaneActor( ) ); + wren->RemoveViewProp( this->Slices[ 1 ][ 1 ]->GetPlaneActor( ) ); + wren->RemoveViewProp( this->Slices[ 1 ][ 2 ]->GetPlaneActor( ) ); + + } // fi +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRActors:: +GetMinWindow( ) const +{ + return( this->Slices[ 0 ][ 0 ]->GetMinWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRActors:: +GetMaxWindow( ) const +{ + return( this->Slices[ 0 ][ 0 ]->GetMaxWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRActors:: +GetMinLevel( ) const +{ + return( this->Slices[ 0 ][ 0 ]->GetMinLevel( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRActors:: +GetMaxLevel( ) const +{ + return( this->Slices[ 0 ][ 0 ]->GetMaxLevel( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRActors:: +GetWindow( ) +{ + return( this->Slices[ 0 ][ 0 ]->GetWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRActors:: +GetLevel( ) +{ + return( this->Slices[ 0 ][ 0 ]->GetLevel( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetWindow( double w ) +{ + this->Slices[ 0 ][ 0 ]->SetWindow( w ); + this->Slices[ 0 ][ 1 ]->SetWindow( w ); + this->Slices[ 0 ][ 2 ]->SetWindow( w ); + this->Slices[ 1 ][ 0 ]->SetWindow( w ); + this->Slices[ 1 ][ 1 ]->SetWindow( w ); + this->Slices[ 1 ][ 2 ]->SetWindow( w ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetLevel( double l ) +{ + this->Slices[ 0 ][ 0 ]->SetLevel( l ); + this->Slices[ 0 ][ 1 ]->SetLevel( l ); + this->Slices[ 0 ][ 2 ]->SetLevel( l ); + this->Slices[ 1 ][ 0 ]->SetLevel( l ); + this->Slices[ 1 ][ 1 ]->SetLevel( l ); + this->Slices[ 1 ][ 2 ]->SetLevel( l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetWindowLevel( double w, double l ) +{ + this->Slices[ 0 ][ 0 ]->SetWindowLevel( w, l ); + this->Slices[ 0 ][ 1 ]->SetWindowLevel( w, l ); + this->Slices[ 0 ][ 2 ]->SetWindowLevel( w, l ); + this->Slices[ 1 ][ 0 ]->SetWindowLevel( w, l ); + this->Slices[ 1 ][ 1 ]->SetWindowLevel( w, l ); + this->Slices[ 1 ][ 2 ]->SetWindowLevel( w, l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +ResetWindowLevel( ) +{ + this->Slices[ 0 ][ 0 ]->ResetWindowLevel( ); + this->Slices[ 0 ][ 1 ]->ResetWindowLevel( ); + this->Slices[ 0 ][ 2 ]->ResetWindowLevel( ); + this->Slices[ 1 ][ 0 ]->ResetWindowLevel( ); + this->Slices[ 1 ][ 1 ]->ResetWindowLevel( ); + this->Slices[ 1 ][ 2 ]->ResetWindowLevel( ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRActors:: +GetSliceNumber( const int& axis ) const +{ + if( axis < 3 ) + return( this->Slices[ 0 ][ axis ]->GetSliceNumber( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRActors:: +GetSliceNumberMinValue( const int& axis ) const +{ + if( axis < 3 ) + return( this->Slices[ 0 ][ axis ]->GetSliceNumberMinValue( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRActors:: +GetSliceNumberMaxValue( const int& axis ) const +{ + if( axis < 3 ) + return( this->Slices[ 0 ][ axis ]->GetSliceNumberMaxValue( ) ); + else + return( -1 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetSliceNumber( const int& axis, const int& slice ) +{ + if( axis < 3 ) + { + this->Slices[ 0 ][ axis ]->SetSliceNumber( slice ); + this->Slices[ 1 ][ axis ]->SetSliceNumber( slice ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetSlice( const int& axis, double* pos ) +{ + if( axis < 3 ) + { + this->Slices[ 0 ][ axis ]->SetSlice( pos ); + this->Slices[ 1 ][ axis ]->SetSlice( pos ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +SetAxesCursor( const int& axis, double* pos ) +{ + if( axis < 3 ) + this->Slices[ 0 ][ axis ]->SetAxesCursor( pos ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +Render( const int& axis ) +{ + if( axis < 3 ) + { + this->Slices[ 0 ][ axis ]->Render( ); + this->Slices[ 1 ][ axis ]->Render( ); + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +Render( ) +{ + this->Render( 0 ); + this->Render( 1 ); + this->Render( 2 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +ResetCamera( const int& axis ) +{ + if( axis < 3 ) + this->Slices[ 0 ][ axis ]->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +ResetCameras( ) +{ + this->ResetCamera( 0 ); + this->ResetCamera( 1 ); + this->ResetCamera( 2 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRActors:: +MPRActors( ) + : Superclass( ) +{ + this->ImageOutlineActor = vtkSmartPointer< vtkActor >::New( ); + for( unsigned int i = 0; i < 2; ++i ) + for( unsigned int j = 0; j < 3; ++j ) + this->Slices[ i ][ j ] = vtkSmartPointer< ImageSliceActors >::New( ); + + this->Slices[ 0 ][ 0 ]->AssociateSlice( this->Slices[ 1 ][ 0 ] ); + this->Slices[ 0 ][ 1 ]->AssociateSlice( this->Slices[ 1 ][ 1 ] ); + this->Slices[ 0 ][ 2 ]->AssociateSlice( this->Slices[ 1 ][ 2 ] ); + + for( unsigned int i = 0; i < 3; ++ i ) + { + this->Slices[ 0 ][ i ]->AddRenderCommand( + Self::_RenderCommand, this + ); + this->Slices[ 0 ][ i ]->AddWindowLevelCommand( + Self::_WindowLevelCommand, this + ); + this->Slices[ 0 ][ i ]->AddSlicesCommand( Self::_SlicesCommand, this ); + + } // rof +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRActors:: +~MPRActors( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +_CreateBoundingBox( ) +{ + vtkImageData* image = + dynamic_cast< vtkImageData* >( this->Slices[ 0 ][ 0 ]->GetInputImage( ) ); + if( image == NULL ) + return; + + // Create 3D outline + double bb[ 6 ]; + image->GetBounds( bb ); + + vtkSmartPointer< vtkOutlineSource > img_ol = + vtkSmartPointer< vtkOutlineSource >::New( ); + img_ol->SetBounds( bb ); + + vtkSmartPointer< vtkPolyDataMapper > img_ol_mapper = + vtkSmartPointer< vtkPolyDataMapper >::New( ); + img_ol_mapper->SetInputConnection( img_ol->GetOutputPort( ) ); + this->ImageOutlineActor->SetMapper( img_ol_mapper ); + this->ImageOutlineActor->GetProperty( )->SetColor( 1, 1, 1 ); + this->ImageOutlineActor->GetProperty( )->SetLineWidth( 1 ); + + this->AddItem( this->ImageOutlineActor ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +_SlicesCommand( double* pos, int axis, void* data ) +{ + MPRActors* actors = reinterpret_cast< MPRActors* >( data ); + if( actors == NULL ) + return; + for( unsigned int j = 0; j < 3; ++j ) + { + if( actors->Slices[ 0 ][ j ]->GetAxis( ) != axis ) + { + actors->SetSlice( j, pos ); + actors->SetAxesCursor( j, pos ); + actors->Render( j ); + + } // fi + + } // rof +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +_WindowLevelCommand( double window, double level, void* data ) +{ + MPRActors* actors = reinterpret_cast< MPRActors* >( data ); + if( actors == NULL ) + return; + actors->SetWindowLevel( window, level ); + actors->Render( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRActors:: +_RenderCommand( void* data ) +{ + MPRActors* actors = reinterpret_cast< MPRActors* >( data ); + if( actors == NULL ) + return; + actors->Render( ); +} + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MPRActors.h b/lib/cpExtensions/Visualization/MPRActors.h new file mode 100644 index 0000000..91c0b50 --- /dev/null +++ b/lib/cpExtensions/Visualization/MPRActors.h @@ -0,0 +1,128 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__MPRACTORS__H__ +#define __CPEXTENSIONS__VISUALIZATION__MPRACTORS__H__ + +#include +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT MPRActors + : public vtkPropCollection + { + public: + typedef MPRActors Self; + + typedef ImageSliceActors::TStyle TStyle; + typedef ImageSliceActors::TMouseCommand TMouseCommand; + typedef ImageSliceActors::TMouseWheelCommand TMouseWheelCommand; + typedef ImageSliceActors::TKeyCommand TKeyCommand; + typedef ImageSliceActors::TVoidCommand TVoidCommand; + typedef ImageSliceActors::TMouseMoveCommand TMouseMoveCommand; + typedef ImageSliceActors::TMouseClickCommand TMouseClickCommand; + typedef ImageSliceActors::TMouseDoubleClickCommand TMouseDoubleClickCommand; + typedef ImageSliceActors::TExposeCommand TExposeCommand; + typedef ImageSliceActors::TConfigureCommand TConfigureCommand; + typedef ImageSliceActors::TEnterCommand TEnterCommand; + typedef ImageSliceActors::TLeaveCommand TLeaveCommand; + + public: + vtkTypeMacro( MPRActors, vtkPropCollection ); + + public: + // Creation + static MPRActors* New( ); + + ImageSliceActors* GetSliceActors( const int& i ) const; + + void SetInputConnection( vtkAlgorithmOutput* aout ); + void SetInputImage( vtkImageData* data ); + int AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ); + int AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ); + void Clear( ); + + vtkImageData* GetInputImage( ); + const vtkImageData* GetInputImage( ) const; + + unsigned int GetNumberOfImages( ) const; + + void SetInterpolate( bool v ); + void InterpolateOn( ); + void InterpolateOff( ); + + void PushActorsInto( + vtkRenderWindow* x, + vtkRenderWindow* y, + vtkRenderWindow* z, + vtkRenderWindow* w + ); + void PopActorsFrom( + vtkRenderWindow* x, + vtkRenderWindow* y, + vtkRenderWindow* z, + vtkRenderWindow* w + ); + + double GetMinWindow( ) const; + double GetMaxWindow( ) const; + double GetMinLevel( ) const; + double GetMaxLevel( ) const; + double GetWindow( ); + double GetLevel( ); + void SetWindow( double w ); + void SetLevel( double l ); + void SetWindowLevel( double w, double l ); + void ResetWindowLevel( ); + + // Slice access + int GetSliceNumber( const int& axis ) const; + int GetSliceNumberMinValue( const int& axis ) const; + int GetSliceNumberMaxValue( const int& axis ) const; + void SetSliceNumber( const int& axis, const int& slice ); + void SetSlice( const int& axis, double* pos ); + void SetAxesCursor( const int& axis, double* pos ); + + // Rendering controls + void Render( const int& axis ); + void Render( ); + void ResetCamera( const int& axis ); + void ResetCameras( ); + + protected: + MPRActors( ); + virtual ~MPRActors( ); + + void _CreateBoundingBox( ); + + static void _SlicesCommand( double* pos, int axis, void* data ); + static void _WindowLevelCommand( + double window, double level, void* data + ); + static void _RenderCommand( void* data ); + + private: + // Purposely not implemented + MPRActors( const Self& ); + Self& operator=( const Self& ); + + protected: + vtkSmartPointer< vtkActor > ImageOutlineActor; + vtkSmartPointer< ImageSliceActors > Slices[ 2 ][ 3 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__VISUALIZATION__MPRACTORS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MPRObjects.cxx b/lib/cpExtensions/Visualization/MPRObjects.cxx new file mode 100644 index 0000000..0727f22 --- /dev/null +++ b/lib/cpExtensions/Visualization/MPRObjects.cxx @@ -0,0 +1,519 @@ +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRObjects* +cpExtensions::Visualization::MPRObjects:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetRenderWindows( + vtkRenderWindow* x, vtkRenderWindow* y, + vtkRenderWindow* z, vtkRenderWindow* w + ) +{ + this->m_Windows[ 0 ] = x; + this->m_Windows[ 1 ] = y; + this->m_Windows[ 2 ] = z; + this->m_Windows[ 3 ] = w; + + // Prepare 2D renderers + for( int i = 0; i < 4; ++i ) + { + // Create renderer, if render window exists + if( this->m_Windows[ i ] != NULL ) + { + this->m_Renderers[ i ] = vtkSmartPointer< vtkRenderer >::New( ); + this->m_Renderers[ i ]->SetBackground( 0.3, 0.3, 0.3 ); + this->m_Windows[ i ]->AddRenderer( this->m_Renderers[ i ] ); + } + else + this->m_Renderers[ i ] = NULL; + + } // rof +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetInputConnection( vtkAlgorithmOutput* aout ) +{ + this->m_MPRActors->SetInputConnection( aout ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetInputImage( vtkImageData* data ) +{ + this->m_MPRActors->SetInputImage( data ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRObjects:: +AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ) +{ + return( this->m_MPRActors->AddBinaryConnection( aout, r, g, b ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRObjects:: +AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ) +{ + return( this->m_MPRActors->AddBinaryImage( data, r, g, b ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +Show( ) +{ + this->m_MPRActors->PushActorsInto( + this->m_Windows[ 0 ], + this->m_Windows[ 1 ], + this->m_Windows[ 2 ], + this->m_Windows[ 3 ] + ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +Hide( ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +Clear( ) +{ + this->m_MPRActors->Clear( ); +} + +// ------------------------------------------------------------------------- +vtkImageData* cpExtensions::Visualization::MPRObjects:: +GetInputImage( ) +{ + return( this->m_MPRActors->GetInputImage( ) ); +} + +// ------------------------------------------------------------------------- +const vtkImageData* cpExtensions::Visualization::MPRObjects:: +GetInputImage( ) const +{ + return( this->m_MPRActors->GetInputImage( ) ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::MPRObjects:: +GetNumberOfImages( ) const +{ + return( this->m_MPRActors->GetNumberOfImages( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetInterpolate( bool v ) +{ + this->m_MPRActors->SetInterpolate( v ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +InterpolateOn( ) +{ + this->m_MPRActors->InterpolateOn( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +InterpolateOff( ) +{ + this->m_MPRActors->InterpolateOff( ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetMinWindow( ) const +{ + return( this->m_MPRActors->GetMinWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetMaxWindow( ) const +{ + return( this->m_MPRActors->GetMaxWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetMinLevel( ) const +{ + return( this->m_MPRActors->GetMinLevel( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetMaxLevel( ) const +{ + return( this->m_MPRActors->GetMaxLevel( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetWindow( ) const +{ + return( this->m_MPRActors->GetWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetLevel( ) const +{ + return( this->m_MPRActors->GetLevel( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetWindow( double w ) +{ + this->m_MPRActors->SetWindow( w ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetLevel( double l ) +{ + this->m_MPRActors->SetLevel( l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetWindowLevel( double w, double l ) +{ + this->m_MPRActors->SetWindowLevel( w, l ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +ResetWindowLevel( ) +{ + this->m_MPRActors->ResetWindowLevel( ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRObjects:: +GetSliceNumber( const int& axis ) const +{ + return( this->m_MPRActors->GetSliceNumber( axis ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRObjects:: +GetSliceNumberMinValue( const int& axis ) const +{ + return( this->m_MPRActors->GetSliceNumberMinValue( axis ) ); +} + +// ------------------------------------------------------------------------- +int cpExtensions::Visualization::MPRObjects:: +GetSliceNumberMaxValue( const int& axis ) const +{ + return( this->m_MPRActors->GetSliceNumberMaxValue( axis ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetSliceNumber( const int& axis, const int& slice ) +{ + this->m_MPRActors->SetSliceNumber( axis, slice ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetSlice( const int& axis, double* pos ) +{ + this->m_MPRActors->SetSlice( axis, pos ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +Render( const double& t ) +{ + this->Render( 0, t ); + this->Render( 1, t ); + this->Render( 2, t ); + this->Render( 3, t ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +Render( const int& axis, const double& t ) +{ + if( axis < 4 ) + { + if( this->m_Windows[ axis ].GetPointer( ) != NULL ) + { + if( this->m_Renderers[ axis ].GetPointer( ) != NULL ) + this->m_Renderers[ axis ]->SetAllocatedRenderTime( t ); + this->m_Windows[ axis ]->Render( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +ResetCamera( const int& axis ) +{ + if( axis < 4 ) + if( this->m_Renderers[ axis ].GetPointer( ) != NULL ) + this->m_Renderers[ axis ]->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +ResetCameras( ) +{ + this->ResetCamera( 0 ); + this->ResetCamera( 1 ); + this->ResetCamera( 2 ); + this->ResetCamera( 3 ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRObjects:: +MPRObjects( ) + : vtkObject( ) +{ + this->m_MPRActors = vtkSmartPointer< MPRActors >::New( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRObjects:: +~MPRObjects( ) +{ +} + + + + +/* +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +SetRenderWindows( + vtkRenderWindow* wx, vtkRenderWindow* wy, + vtkRenderWindow* wz, vtkRenderWindow* w3D + ) +{ +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +AddImage( vtkImageData* image ) +{ + this->m_MPRActors->AddInputData( image ); + this->m_MPRActors->PushActorsInto( + this->m_Windows[ 0 ], + this->m_Windows[ 1 ], + this->m_Windows[ 2 ], + this->m_Windows[ 3 ] + ); + + // First rendering + if( this->m_MPRActors->GetNumberOfImages( ) == 1 ) + { + this->m_MPRActors->ResetSlices( ); + this->ResetCameras( ); + + } // fi + this->RenderAll( 1e-3 ); +} + +// ------------------------------------------------------------------------- +unsigned int cpExtensions::Visualization::MPRObjects:: +GetNumberOfImages( ) const +{ + return( this->m_MPRActors->GetNumberOfImages( ) ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +ClearAll( ) +{ + this->m_MPRActors->PopActorsFrom( + this->m_Windows[ 0 ], + this->m_Windows[ 1 ], + this->m_Windows[ 2 ], + this->m_Windows[ 3 ] + ); + this->ResetCameras( ); + this->RenderAll( 1e-3 ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +ResetCamera( const int& id ) +{ + if( id < 4 ) + if( this->m_Windows[ id ] != NULL ) + this->m_Renderers[ id ]->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +ResetCameras( ) +{ + for( int i = 0; i < 4; ++i ) + if( this->m_Windows[ i ] != NULL ) + this->m_Renderers[ i ]->ResetCamera( ); +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +Render( const int& id, const double& t ) +{ + if( id < 4 ) + { + if( this->m_Windows[ id ] != NULL ) + { + if( this->m_Renderers[ id ] != NULL ) + this->m_Renderers[ id ]->SetAllocatedRenderTime( t ); + this->m_Windows[ id ]->Render( ); + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpExtensions::Visualization::MPRObjects:: +RenderAll( const double& t ) +{ + for( int i = 0; i < 4; ++i ) + { + if( this->m_Windows[ i ] != NULL ) + { + if( this->m_Renderers[ i ] != NULL ) + this->m_Renderers[ i ]->SetAllocatedRenderTime( t ); + this->m_Windows[ i ]->Render( ); + + } // fi + + } // rof +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::Visualization::MPRObjects:: +GetXRenderer( ) +{ + return( this->m_Renderers[ 0 ] ); +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::Visualization::MPRObjects:: +GetYRenderer( ) +{ + return( this->m_Renderers[ 1 ] ); +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::Visualization::MPRObjects:: +GetZRenderer( ) +{ + return( this->m_Renderers[ 2 ] ); +} + +// ------------------------------------------------------------------------- +vtkRenderer* cpExtensions::Visualization::MPRObjects:: +Get3DRenderer( ) +{ + return( this->m_Renderers[ 3 ] ); +} + +// ------------------------------------------------------------------------- +const vtkRenderer* cpExtensions::Visualization::MPRObjects:: +GetXRenderer( ) const +{ + return( this->m_Renderers[ 0 ] ); +} + +// ------------------------------------------------------------------------- +const vtkRenderer* cpExtensions::Visualization::MPRObjects:: +GetYRenderer( ) const +{ + return( this->m_Renderers[ 1 ] ); +} + +// ------------------------------------------------------------------------- +const vtkRenderer* cpExtensions::Visualization::MPRObjects:: +GetZRenderer( ) const +{ + return( this->m_Renderers[ 2 ] ); +} + +// ------------------------------------------------------------------------- +const vtkRenderer* cpExtensions::Visualization::MPRObjects:: +Get3DRenderer( ) const +{ + return( this->m_Renderers[ 3 ] ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization:: +MPRActors* cpExtensions::Visualization::MPRObjects:: +GetMPRActors( ) +{ + return( this->m_MPRActors ); +} + +// ------------------------------------------------------------------------- +const cpExtensions::Visualization:: +MPRActors* cpExtensions::Visualization::MPRObjects:: +GetMPRActors( ) const +{ + return( this->m_MPRActors ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetWindow( ) const +{ + return( this->m_MPRActors->GetWindow( ) ); +} + +// ------------------------------------------------------------------------- +double cpExtensions::Visualization::MPRObjects:: +GetLevel( ) const +{ + return( this->m_MPRActors->GetLevel( ) ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRObjects:: +MPRObjects( ) + : vtkObject( ) +{ + // Prepare actors + this->m_MPRActors = vtkSmartPointer< MPRActors >::New( ); +} + +// ------------------------------------------------------------------------- +cpExtensions::Visualization::MPRObjects:: +~MPRObjects( ) +{ +} +*/ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MPRObjects.h b/lib/cpExtensions/Visualization/MPRObjects.h new file mode 100644 index 0000000..c800fc1 --- /dev/null +++ b/lib/cpExtensions/Visualization/MPRObjects.h @@ -0,0 +1,137 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__MPROBJECTS__H__ +#define __CPEXTENSIONS__VISUALIZATION__MPROBJECTS__H__ + +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +#define cpExtensions_MPRObjects_Renderer( DIR ) \ + inline vtkRenderer* Get##DIR##Renderer( ) \ + { return( this->m_Renderers[ Self::MPRDirections_##DIR ] ); } \ + inline const vtkRenderer* Get##DIR##Renderer( ) const \ + { return( this->m_Renderers[ Self::MPRDirections_##DIR ] ); } + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + class cpExtensions_EXPORT MPRObjects + : public vtkObject + { + public: + typedef MPRObjects Self; + + typedef MPRActors::TStyle TStyle; + typedef MPRActors::TMouseCommand TMouseCommand; + typedef MPRActors::TMouseWheelCommand TMouseWheelCommand; + typedef MPRActors::TKeyCommand TKeyCommand; + typedef MPRActors::TVoidCommand TVoidCommand; + typedef MPRActors::TMouseMoveCommand TMouseMoveCommand; + typedef MPRActors::TMouseClickCommand TMouseClickCommand; + typedef MPRActors::TMouseDoubleClickCommand TMouseDoubleClickCommand; + typedef MPRActors::TExposeCommand TExposeCommand; + typedef MPRActors::TConfigureCommand TConfigureCommand; + typedef MPRActors::TEnterCommand TEnterCommand; + typedef MPRActors::TLeaveCommand TLeaveCommand; + + enum MPRDirections + { + MPRDirections_X = 0, + MPRDirections_Y = 1, + MPRDirections_Z = 2, + MPRDirections_W = 3 + }; + + public: + vtkTypeMacro( MPRObjects, vtkObject ); + + cpExtensions_MPRObjects_Renderer( X ); + cpExtensions_MPRObjects_Renderer( Y ); + cpExtensions_MPRObjects_Renderer( Z ); + cpExtensions_MPRObjects_Renderer( W ); + + public: + // Creation + static MPRObjects* New( ); + + // Association + void SetRenderWindows( + vtkRenderWindow* x, vtkRenderWindow* y, + vtkRenderWindow* z, vtkRenderWindow* w + ); + + void SetInputConnection( vtkAlgorithmOutput* aout ); + void SetInputImage( vtkImageData* data ); + int AddBinaryConnection( + vtkAlgorithmOutput* aout, + const double& r, const double& g, const double& b + ); + int AddBinaryImage( + vtkImageData* data, + const double& r, const double& g, const double& b + ); + void Show( ); + void Hide( ); + void Clear( ); + + vtkImageData* GetInputImage( ); + const vtkImageData* GetInputImage( ) const; + unsigned int GetNumberOfImages( ) const; + + void SetInterpolate( bool v ); + void InterpolateOn( ); + void InterpolateOff( ); + + double GetMinWindow( ) const; + double GetMaxWindow( ) const; + double GetMinLevel( ) const; + double GetMaxLevel( ) const; + double GetWindow( ) const; + double GetLevel( ) const; + void SetWindow( double w ); + void SetLevel( double l ); + void SetWindowLevel( double w, double l ); + void ResetWindowLevel( ); + + int GetSliceNumber( const int& axis ) const; + int GetSliceNumberMinValue( const int& axis ) const; + int GetSliceNumberMaxValue( const int& axis ) const; + void SetSliceNumber( const int& axis, const int& slice ); + void SetSlice( const int& axis, double* pos ); + + void Render( const double& t ); + void Render( const int& axis, const double& t ); + void ResetCamera( const int& axis ); + void ResetCameras( ); + + protected: + MPRObjects( ); + virtual ~MPRObjects( ); + + private: + // Purposely not implemented + MPRObjects( const Self& ); + Self& operator=( const Self& ); + + protected: + // Inputs + vtkSmartPointer< vtkRenderWindow > m_Windows[ 4 ]; + + // Internal pipelines + vtkSmartPointer< MPRActors > m_MPRActors; + vtkSmartPointer< vtkRenderer > m_Renderers[ 4 ]; + }; + + } // ecapseman + +} // ecapseman + +#endif // __CPEXTENSIONS__VISUALIZATION__MPROBJECTS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MeshMapper.h b/lib/cpExtensions/Visualization/MeshMapper.h new file mode 100644 index 0000000..c6aee51 --- /dev/null +++ b/lib/cpExtensions/Visualization/MeshMapper.h @@ -0,0 +1,105 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__MESHMAPPER__H__ +#define __CPEXTENSIONS__VISUALIZATION__MESHMAPPER__H__ + +#include +#include + +class vtkActor; +class vtkInformation; +class vtkRenderer; + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class M > + class MeshMapper + : public vtkMapper + { + public: + typedef MeshMapper Self; + vtkTypeMacro( MeshMapper, vtkMapper ); + + typedef M TMesh; + typedef typename M::PointType TPoint; + typedef typename TPoint::VectorType TVector; + typedef typename TPoint::CoordRepType TScalar; + itkStaticConstMacro( Dimension, unsigned int, M::PointDimension ); + + // Begin concept checking +#ifdef ITK_USE_CONCEPT_CHECKING + /* TODO + itkConceptMacro( + InputMeshIsTwoOrThreeimensionalCheck, + ( itk::Concept::SameDimensionOrMinusOne< Self::Dimension, 3 > ) + ); + itkConceptMacro( + ScalarTypeHasFloatResolution, + ( itk::Concept::IsFloatingPoint< TScalar > ) + ); + */ +#endif + // End concept checking + + public: + // TODO: static Self* New( ); + virtual void ShallowCopy( vtkAbstractMapper* m ); + + virtual void SetInputData( M* in ); + virtual M* GetInput( ); + virtual const M* GetInput( ) const; + + virtual double* GetBounds( ); + virtual void GetBounds( double bounds[ 6 ] ); + + virtual void RenderPiece( vtkRenderer* aren, vtkActor* act ) = 0; + virtual void Render( vtkRenderer* aren, vtkActor* act ); + virtual void Update( ); + virtual void Update( int port ); + + virtual void MapDataArrayToVertexAttribute( + const char* vertexAttributeName, + const char* dataArrayName, + int fieldAssociation, + int componentno = -1 + ); + virtual void MapDataArrayToMultiTextureAttribute( + int unit, + const char* dataArrayName, + int fieldAssociation, + int componentno = -1 + ); + virtual void RemoveVertexAttributeMapping( + const char* vertexAttributeName + ); + virtual void RemoveAllVertexAttributeMappings( ); + + protected: + MeshMapper( ); + virtual ~MeshMapper( ); + + virtual void ComputeBounds( ); + virtual int FillInputPortInformation( int port, vtkInformation* info ); + + private: + // These methods aren't supposed to be implemented + MeshMapper( const Self& other ); + Self& operator=( const Self& other ); + + protected: + typename M::Pointer Mesh; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__VISUALIZATION__MESHMAPPER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/MeshMapper.hxx b/lib/cpExtensions/Visualization/MeshMapper.hxx new file mode 100644 index 0000000..4374ffe --- /dev/null +++ b/lib/cpExtensions/Visualization/MeshMapper.hxx @@ -0,0 +1,224 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__MESHMAPPER__HXX__ +#define __CPEXTENSIONS__VISUALIZATION__MESHMAPPER__HXX__ + +#include +#include + +// TODO: #include + +// ------------------------------------------------------------------------- +/* TODO + template< class M > + typename cpExtensions::Visualization::MeshMapper< M >:: + Self* cpExtensions::Visualization::MeshMapper< M >:: + New( ) + { + return( + cpExtensions::Visualization::OpenGLMeshMapper< M >::New( ) + ); + } +*/ + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +ShallowCopy( vtkAbstractMapper* m ) +{ + Self* mapper = Self::SafeDownCast( m ); + if( m != NULL ) + this->SetInputData( mapper->GetInput( ) ); + this->vtkMapper::ShallowCopy( m ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +SetInputData( M* in ) +{ + if( this->Mesh != in ) + { + this->Mesh = in; + this->Modified( ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class M > +M* cpExtensions::Visualization::MeshMapper< M >:: +GetInput( ) +{ + return( this->Mesh ); +} + +// ------------------------------------------------------------------------- +template< class M > +const M* cpExtensions::Visualization::MeshMapper< M >:: +GetInput( ) const +{ + return( this->Mesh ); +} + +// ------------------------------------------------------------------------- +template< class M > +double* cpExtensions::Visualization::MeshMapper< M >:: +GetBounds( ) +{ + // do we have an input + if( this->Mesh.IsNull( ) ) + { + vtkMath::UninitializeBounds( this->Bounds ); + return( this->Bounds ); + } + else + { + this->Mesh->Update( ); + this->ComputeBounds( ); + + if( !vtkMath::AreBoundsInitialized( this->Bounds ) ) + return( NULL ); + return( this->Bounds ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +GetBounds( double bounds[ 6 ] ) +{ + this->Superclass::GetBounds( bounds ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +Render( vtkRenderer* aren, vtkActor* act ) +{ + if( this->Mesh.IsNull( ) ) + { + vtkErrorMacro( "Mapper has no input." ); + return; + + } // fi + this->RenderPiece( aren, act ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +Update( ) +{ + // TODO: + std::cout << "Update( )" << std::endl; +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +Update( int port ) +{ + // TODO: + std::cout << "Update( port = " << port << " ) "<< std::endl; +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +MapDataArrayToVertexAttribute( + const char* vertexAttributeName, + const char* dataArrayName, + int fieldAssociation, + int componentno + ) +{ + vtkErrorMacro( "Not implemented at this level..." ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +MapDataArrayToMultiTextureAttribute( + int unit, + const char* dataArrayName, + int fieldAssociation, + int componentno + ) +{ + vtkErrorMacro( "Not implemented at this level..." ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +RemoveVertexAttributeMapping( const char* vertexAttributeName ) +{ + vtkErrorMacro( "Not implemented at this level..." ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +RemoveAllVertexAttributeMappings( ) +{ + vtkErrorMacro( "Not implemented at this level..." ); +} + +// ------------------------------------------------------------------------- +template< class M > +cpExtensions::Visualization::MeshMapper< M >:: +MeshMapper( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class M > +cpExtensions::Visualization::MeshMapper< M >:: +~MeshMapper( ) +{ +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::MeshMapper< M >:: +ComputeBounds( ) +{ + static const TScalar _0 = TScalar( 0 ); + if( this->Mesh.IsNotNull( ) ) + { + const typename M::BoundingBoxType* bb = this->Mesh->GetBoundingBox( ); + TPoint minP = bb->GetMinimum( ); + TPoint maxP = bb->GetMaximum( ); + this->Bounds[ 0 ] = double( ( Self::Dimension >= 1 )? minP[ 0 ]: _0 ); + this->Bounds[ 1 ] = double( ( Self::Dimension >= 1 )? maxP[ 0 ]: _0 ); + this->Bounds[ 2 ] = double( ( Self::Dimension >= 2 )? minP[ 1 ]: _0 ); + this->Bounds[ 3 ] = double( ( Self::Dimension >= 2 )? maxP[ 1 ]: _0 ); + this->Bounds[ 4 ] = double( ( Self::Dimension >= 3 )? minP[ 2 ]: _0 ); + this->Bounds[ 5 ] = double( ( Self::Dimension >= 3 )? maxP[ 2 ]: _0 ); + } + else + { + this->Bounds[ 0 ] = + this->Bounds[ 1 ] = + this->Bounds[ 2 ] = + this->Bounds[ 3 ] = + this->Bounds[ 4 ] = + this->Bounds[ 5 ] = + double( 0 ); + + } // fi +} + +// ------------------------------------------------------------------------- +template< class M > +int cpExtensions::Visualization::MeshMapper< M >:: +FillInputPortInformation( int port, vtkInformation* info ) +{ + info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE( ), "itk::Mesh" ); + return( 1 ); +} + +#endif // __CPEXTENSIONS__VISUALIZATION__MESHMAPPER__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/OpenGLMeshMapper.h b/lib/cpExtensions/Visualization/OpenGLMeshMapper.h new file mode 100644 index 0000000..ff80ce3 --- /dev/null +++ b/lib/cpExtensions/Visualization/OpenGLMeshMapper.h @@ -0,0 +1,78 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__H__ +#define __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__H__ + +#include + +#include + +namespace cpExtensions +{ + namespace Visualization + { + /** + */ + template< class M > + class OpenGLMeshMapper + : public MeshMapper< M > + { + public: + typedef OpenGLMeshMapper Self; + vtkTypeMacro( OpenGLMeshMapper, MeshMapper< M > ); + + typedef typename Superclass::TMesh TMesh; + typedef typename Superclass::TPoint TPoint; + typedef typename Superclass::TVector TVector; + typedef typename Superclass::TScalar TScalar; + + protected: + typedef unsigned int TIndex; + typedef typename M::CellType TCell; + typedef typename M::CellsContainer TCellsContainer; + typedef typename TCellsContainer::ConstIterator TCellIt; + + public: + virtual const char* GetNameOfClass( ) const + { return( "cpExtensions::OpenGLMeshMapper" ); } + static Self* New( ); + + virtual void RenderPiece( vtkRenderer* aren, vtkActor* act ); + virtual void ReleaseGraphicsResources( vtkWindow* win ); + virtual int Draw( vtkRenderer* aren, vtkActor* act ); + + protected: + OpenGLMeshMapper( ); + virtual ~OpenGLMeshMapper( ); + + bool _ConfigureOpenGL( ); + + private: + // Purposely not implemented + OpenGLMeshMapper( const Self& other ); + Self& operator=( const Self& other ); + + protected: + vtkIdType TotalCells; + // TODO: vtkSmartPointer< vtkOpenGLTexture > InternalColorTexture; + + bool FirstRendering; + + bool VBOSupported; + unsigned int VBOID1, VBOID2; + + std::vector< unsigned int > Sizes; + std::vector< TIndex > Indices; + long IndexElementType; + long ElementValueType; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +#include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__H__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Visualization/OpenGLMeshMapper.hxx b/lib/cpExtensions/Visualization/OpenGLMeshMapper.hxx new file mode 100644 index 0000000..ab2fc60 --- /dev/null +++ b/lib/cpExtensions/Visualization/OpenGLMeshMapper.hxx @@ -0,0 +1,672 @@ +#ifndef __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__ +#define __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__HXX__ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define GL_GLEXT_PROTOTYPES +#include + +#ifdef _WIN32 + +PFNGLGENBUFFERSARBPROC pglGenBuffers = 0; +PFNGLBINDBUFFERARBPROC pglBindBuffer = 0; +PFNGLBUFFERDATAARBPROC pglBufferData = 0; +PFNGLBUFFERSUBDATAARBPROC pglBufferSubData = 0; +PFNGLDELETEBUFFERSARBPROC pglDeleteBuffers = 0; +PFNGLGETBUFFERPARAMETERIVARBPROC pglGetBufferParameteriv = 0; +PFNGLMAPBUFFERARBPROC pglMapBuffer = 0; +PFNGLUNMAPBUFFERARBPROC pglUnmapBuffer = 0; + +#define glGenBuffers pglGenBuffers +#define glBindBuffer pglBindBuffer +#define glBufferData pglBufferData +#define glBufferSubData pglBufferSubData +#define glDeleteBuffers pglDeleteBuffers +#define glGetBufferParameteriv pglGetBufferParameteriv +#define glMapBuffer pglMapBuffer +#define glUnmapBuffer pglUnmapBuffer + +#endif // _WIN32 + +// some definitions for what the polydata has in it +#define CPPLUGINS_VTK_PDM_NORMALS 0x0001 +#define CPPLUGINS_VTK_PDM_COLORS 0x0002 +#define CPPLUGINS_VTK_PDM_TCOORDS 0x0004 +#define CPPLUGINS_VTK_PDM_CELL_COLORS 0x0008 +#define CPPLUGINS_VTK_PDM_CELL_NORMALS 0x0010 +#define CPPLUGINS_VTK_PDM_POINT_TYPE_FLOAT 0x0020 +#define CPPLUGINS_VTK_PDM_POINT_TYPE_DOUBLE 0x0040 +#define CPPLUGINS_VTK_PDM_NORMAL_TYPE_FLOAT 0x0080 +#define CPPLUGINS_VTK_PDM_NORMAL_TYPE_DOUBLE 0x0100 +#define CPPLUGINS_VTK_PDM_TCOORD_TYPE_FLOAT 0x0200 +#define CPPLUGINS_VTK_PDM_TCOORD_TYPE_DOUBLE 0x0400 +#define CPPLUGINS_VTK_PDM_TCOORD_1D 0x0800 +#define CPPLUGINS_VTK_PDM_OPAQUE_COLORS 0x1000 +#define CPPLUGINS_VTK_PDM_USE_FIELD_DATA 0x2000 + +// ------------------------------------------------------------------------- +template< class M > +typename cpExtensions::Visualization::OpenGLMeshMapper< M >:: +Self* cpExtensions::Visualization::OpenGLMeshMapper< M >:: +New( ) +{ + return( new Self( ) ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::OpenGLMeshMapper< M >:: +RenderPiece( vtkRenderer* aren, vtkActor* act ) +{ + vtkOpenGLClearErrorMacro( ); + + // Is the renderer correctly initialized? + if( aren->GetRenderWindow( )->CheckAbortStatus( ) ) + return; + + // Get input mesh ( and check it ) + M* in = this->GetInput( ); + if( !in ) + { + vtkErrorMacro( << "No input!" ); + return; + + } // fi + unsigned long numPts = in->GetNumberOfPoints( ); + if( numPts == 0 ) + { + vtkDebugMacro( << "No points!" ); + return; + + } // fi + + // Update input, if needed + this->InvokeEvent( vtkCommand::StartEvent, NULL ); + if( !this->Static ) + in->Update( ); + this->InvokeEvent( vtkCommand::EndEvent, NULL ); + + // Update some visualization objects + if( !this->LookupTable ) + this->CreateDefaultLookupTable( ); + aren->GetRenderWindow( )->MakeCurrent( ); + + // Check clipping planes + int numClipPlanes = this->GetNumberOfClippingPlanes( ); + if( numClipPlanes > 6 ) + { + vtkErrorMacro( << "OpenGL has a limit of 6 clipping planes" ); + numClipPlanes = 6; + + } // fi + + // Add all the clipping planes + double eq[ 4 ]; + GLenum clipPlaneId; + for( int i = 0; i < numClipPlanes; i++ ) + { + this->GetClippingPlaneInDataCoords( act->GetMatrix( ), i, eq ); + + clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + i ); + glEnable( clipPlaneId ); + glClipPlane( clipPlaneId, eq ); + + } // rof + + // Configure opacity + this->MapScalars( act->GetProperty( )->GetOpacity( ) ); + + // Configure textures + if( this->ColorTextureMap ) + { + /* TODO + if( !this->InternalColorTexture ) + { + this->InternalColorTexture = + vtkSmartPointer< vtkOpenGLTexture >::New( ); + this->InternalColorTexture->RepeatOff( ); + + } // fi + this->InternalColorTexture->SetInputData( this->ColorTextureMap ); + */ + + // Keep color from interacting with texture. + float info[ 4 ] = { float( 1 ), float( 1 ), float( 1 ), float( 1 ) }; + glMaterialfv( GL_FRONT_AND_BACK, GL_DIFFUSE, info ); + + } // fi + + int noAbort = 1; + bool renderNeeded = !this->ImmediateModeRendering; + renderNeeded &= !this->GetGlobalImmediateModeRendering( ); + + // Something has changed in the pipeline? + if( + this->GetMTime( ) > this->BuildTime || + in->GetMTime( ) > this->BuildTime || + act->GetProperty( )->GetMTime( ) > this->BuildTime || + aren->GetRenderWindow( ) != this->LastWindow + ) + { + // Update visualization objects + this->ReleaseGraphicsResources( aren->GetRenderWindow( ) ); + this->LastWindow = aren->GetRenderWindow( ); + + if( renderNeeded ) + { + // Load textures + /* TODO + if( this->ColorTextureMap ) + this->InternalColorTexture->Load( aren ); + */ + + // Time the actual drawing + this->Timer->StartTimer( ); + noAbort = this->Draw( aren, act ); + this->Timer->StopTimer( ); + + } // fi + + if( noAbort ) + this->BuildTime.Modified( ); + } + else + { + // If nothing changed, just draw the mapped mesh + if( renderNeeded ) + { + // Load textures + /* TODO + if( this->ColorTextureMap ) + this->InternalColorTexture->Load( aren ); + */ + + // Time the actual drawing + this->Timer->StartTimer( ); + this->Draw( aren, act ); + this->Timer->StopTimer( ); + + } // fi + + } // fi + + // if we are in immediate mode rendering we always + // want to draw the primitives here + if( !renderNeeded ) + { + // Load textures + /* TODO + if( this->ColorTextureMap ) + this->InternalColorTexture->Load( aren ); + */ + + // Time the actual drawing + this->Timer->StartTimer( ); + this->Draw( aren, act ); + this->Timer->StopTimer( ); + + } // fi + this->TimeToDraw = this->Timer->GetElapsedTime( ); + + // If the timer is not accurate enough, set it to a small + // time so that it is not zero + if( this->TimeToDraw == double( 0 ) ) + this->TimeToDraw = double( 1e-3 ); + + for( int c = 0; c < numClipPlanes; c++ ) + { + GLenum clipPlaneId = static_cast< GLenum >( GL_CLIP_PLANE0 + c ); + glDisable( clipPlaneId ); + + } // rof + vtkOpenGLCheckErrorMacro( "failed after RenderPiece\n" ); +} + +// ------------------------------------------------------------------------- +template< class M > +void cpExtensions::Visualization::OpenGLMeshMapper< M >:: +ReleaseGraphicsResources( vtkWindow* win ) +{ + if( win && win->GetMapped( ) ) + { + win->MakeCurrent( ); + vtkOpenGLCheckErrorMacro( "failed after ReleaseGraphicsResources" ); + + } // fi + this->LastWindow = NULL; + + // TAKEN FROM BASIC vtkOpenGLPolyDataMapper: + // We may not want to do this here. + /* TODO + if( this->InternalColorTexture ) + this->InternalColorTexture->ReleaseGraphicsResources( win ); + */ +} + +// ------------------------------------------------------------------------- +template< class M > +int cpExtensions::Visualization::OpenGLMeshMapper< M >:: +Draw( vtkRenderer* aren, vtkActor* act ) +{ + vtkOpenGLClearErrorMacro( ); + + // First and second initialization check + if( this->FirstRendering ) + this->FirstRendering = !( this->_ConfigureOpenGL( ) ); + if( this->FirstRendering ) + return( 0 ); + + vtkOpenGLRenderer* ren = static_cast< vtkOpenGLRenderer* >( aren ); + int rep, interpolation; + float tran; + vtkProperty* prop; + vtkUnsignedCharArray* c = NULL; + int tDim; + int noAbort = 1; + M* input = this->GetInput( ); + int cellScalars = 0; + vtkIdType cellNum = 0; + int cellNormals; + int resolve = 0, zResolve = 0; + double zRes = 0.0; + + // get the property + prop = act->GetProperty( ); + + // get the transparency + tran = prop->GetOpacity( ); + + // if the primitives are invisable then get out of here + if( tran <= 0.0 ) + return( noAbort ); + + // get the representation ( e.g., surface / wireframe / points ) + rep = prop->GetRepresentation( ); + + // get the shading interpolation + interpolation = prop->GetInterpolation( ); + + // are they cell or point scalars + if( this->Colors ) + { + c = this->Colors; + if( + ( + this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA || + this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA || + !input->GetPointData( ) + ) && + this->ScalarMode != VTK_SCALAR_MODE_USE_POINT_FIELD_DATA + ) + cellScalars = 1; + + } // fi + + cellNormals = 1; + + // if we are doing vertex colors then set lmcolor to adjust + // the current materials ambient and diffuse values using + // vertex color commands otherwise tell it not to. + glDisable( GL_COLOR_MATERIAL ); + if( c ) + { + GLenum lmcolorMode; + if( this->ScalarMaterialMode == VTK_MATERIALMODE_DEFAULT ) + { + if( prop->GetAmbient( ) > prop->GetDiffuse( ) ) + lmcolorMode = GL_AMBIENT; + else + lmcolorMode = GL_DIFFUSE; + } + else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT_AND_DIFFUSE ) + lmcolorMode = GL_AMBIENT_AND_DIFFUSE; + else if( this->ScalarMaterialMode == VTK_MATERIALMODE_AMBIENT ) + lmcolorMode = GL_AMBIENT; + else // if( this->ScalarMaterialMode == VTK_MATERIALMODE_DIFFUSE ) + lmcolorMode = GL_DIFFUSE; + glColorMaterial( GL_FRONT_AND_BACK, lmcolorMode ); + glEnable( GL_COLOR_MATERIAL ); + + } // fi + + unsigned long idx = 0; + if( c ) + { + idx |= CPPLUGINS_VTK_PDM_COLORS; + if( c->GetName( ) ) + idx |= CPPLUGINS_VTK_PDM_OPAQUE_COLORS; + } // fi + if( cellScalars ) + idx |= CPPLUGINS_VTK_PDM_CELL_COLORS; + if( cellNormals ) + idx |= CPPLUGINS_VTK_PDM_CELL_NORMALS; + if( this->ScalarMode == VTK_SCALAR_MODE_USE_FIELD_DATA ) + idx |= CPPLUGINS_VTK_PDM_USE_FIELD_DATA; + + // store the types in the index + if( typeid( typename M::CoordRepType ) == typeid( float ) ) + idx |= CPPLUGINS_VTK_PDM_POINT_TYPE_FLOAT; + else if( typeid( typename M::CoordRepType ) == typeid( double ) ) + idx |= CPPLUGINS_VTK_PDM_POINT_TYPE_DOUBLE; + + if( typeid( typename M::CoordRepType ) == typeid( float ) ) + idx |= CPPLUGINS_VTK_PDM_NORMAL_TYPE_FLOAT; + else if( typeid( typename M::CoordRepType ) == typeid( double ) ) + idx |= CPPLUGINS_VTK_PDM_NORMAL_TYPE_DOUBLE; + + if( this->GetResolveCoincidentTopology( ) ) + { + resolve = 1; + if( this->GetResolveCoincidentTopology( ) == VTK_RESOLVE_SHIFT_ZBUFFER ) + { + zResolve = 1; + zRes = this->GetResolveCoincidentTopologyZShift( ); + } + else + { +#ifdef GL_VERSION_1_1 + double f, u; + glEnable( GL_POLYGON_OFFSET_FILL ); + this->GetResolveCoincidentTopologyPolygonOffsetParameters( f, u ); + glPolygonOffset( f, u ); +#endif + } // fi + + } // fi + + // we need to know the total number of cells so that we can + // report progress + this->TotalCells = input->GetNumberOfCells( ); + + // Actual render + if( this->VBOSupported ) + { + glBindBuffer( GL_ARRAY_BUFFER, GLuint( this->VBOID1 ) ); + + void* ptr = glMapBuffer( GL_ARRAY_BUFFER, GL_READ_WRITE ); + if( ptr != NULL ) + { + // Copy source points to OpenGL buffer + const TPoint* src = + input->GetPoints( )->CastToSTLContainer( ).data( ); + TPoint* dest = reinterpret_cast< TPoint* >( ptr ); + if( dest != NULL ) + std::copy( src, src + input->GetNumberOfPoints( ), dest ); + glUnmapBuffer( GL_ARRAY_BUFFER ); + + } // fi + + std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint ); + + // Bind vertices, normals and indices + glNormalPointer( this->ElementValueType, 0, ( void* )( pSize ) ); + glVertexPointer( 3, this->ElementValueType, 0, 0 ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, GLuint( this->VBOID2 ) ); + + // Prepare to render polygons + glEnableClientState( GL_NORMAL_ARRAY ); + glEnableClientState( GL_VERTEX_ARRAY ); + + // Iterate over all input cells + unsigned int accum = 0; + const TCellsContainer* cells = input->GetCells( ); + TCellIt cIt = cells->Begin( ); + for( unsigned int nCell = 0; cIt != cells->End( ); nCell++, cIt++ ) + { + const TCell* cell = cIt.Value( ); + unsigned int nPoints = this->Sizes[ nCell ]; + + // Infere rendering mode + GLenum mode; + switch( prop->GetRepresentation( ) ) + { + case VTK_SURFACE: + { + switch( nPoints ) + { + case 1: mode = GL_POINTS; break; + case 2: mode = GL_LINES; break; + case 3: mode = GL_TRIANGLES; break; + case 4: mode = GL_QUADS; break; + default: mode = GL_POLYGON; break; + } // hctiws + // TODO: GL_LINE_STRIP, + // TODO: GL_LINE_LOOP, + // TODO: GL_TRIANGLE_STRIP, + // TODO: GL_TRIANGLE_FAN, + // TODO: GL_QUAD_STRIP, + } + break; + case VTK_WIREFRAME: mode = GL_LINE_LOOP; break; + case VTK_POINTS: default: mode = GL_POINTS; break; + } // hctiws + + // Actual draw all elements + if( nPoints < 3 ) + glDisable( GL_LIGHTING ); + + if( nPoints == 2 && zResolve ) + glDepthRange( zRes, 1. ); + + glDrawElements( + mode, nPoints, this->IndexElementType, ( GLuint* )( 0 ) + accum + ); + accum += nPoints; + + if( nPoints < 3 ) + glEnable( GL_LIGHTING ); + + } // rof + + glDisableClientState( GL_VERTEX_ARRAY ); + glDisableClientState( GL_NORMAL_ARRAY ); + + glBindBuffer( GL_ARRAY_BUFFER, 0 ); + glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); + } + else + { + std::cout << "Not VBO rendering!!!" << std::endl; + + } // fi + + if( resolve ) + { + if( zResolve ) + glDepthRange( 0., 1. ); + else + { +#ifdef GL_VERSION_1_1 + glDisable( GL_POLYGON_OFFSET_FILL ); +#endif + } // fi + + } // fi + vtkOpenGLCheckErrorMacro( "failed after Draw" ); + this->UpdateProgress( 1.0 ); + return( noAbort ); +} + +// ------------------------------------------------------------------------- +template< class M > +cpExtensions::Visualization::OpenGLMeshMapper< M >:: +OpenGLMeshMapper( ) + : Superclass( ), + TotalCells( 0 ), + FirstRendering( true ), + VBOID1( 0 ), + VBOID2( 0 ) +{ + // Infere index element type + switch( sizeof( TIndex ) ) + { + case 1 : this->IndexElementType = GL_UNSIGNED_BYTE; break; + case 2 : this->IndexElementType = GL_UNSIGNED_SHORT; break; + case 4 : this->IndexElementType = GL_UNSIGNED_INT; break; + default: this->IndexElementType = GL_UNSIGNED_BYTE; break; + } // hctiws + + // Infere point value type + if( typeid( TScalar ) == typeid( float ) ) + this->ElementValueType = GL_FLOAT; + else + this->ElementValueType = GL_DOUBLE; +} + +// ------------------------------------------------------------------------- +template< class M > +cpExtensions::Visualization::OpenGLMeshMapper< M >:: +~OpenGLMeshMapper( ) +{ + if( this->LastWindow ) + this->ReleaseGraphicsResources( this->LastWindow ); + if( this->VBOSupported ) + { + GLuint id1 = GLuint( this->VBOID1 ); + GLuint id2 = GLuint( this->VBOID2 ); + if( id1 != GLuint( 0 ) ) glDeleteBuffers( 1, &id1 ); + if( id2 != GLuint( 0 ) ) glDeleteBuffers( 1, &id2 ); + this->VBOID1 = this->VBOID2 = 0; + + } // fi +} + +// ------------------------------------------------------------------------- +template< class M > +bool cpExtensions::Visualization::OpenGLMeshMapper< M >:: +_ConfigureOpenGL( ) +{ + M* input = this->GetInput( ); + if( input == NULL ) + return( false ); + +#ifdef _WIN32 + // Get pointers to GL functions + glGenBuffers = reinterpret_cast< PFNGLGENBUFFERSARBPROC > + ( wglGetProcAddress( "glGenBuffers" ) ); + glBindBuffer = reinterpret_cast< PFNGLBINDBUFFERARBPROC > + ( wglGetProcAddress( "glBindBuffer" ) ); + glBufferData = reinterpret_cast< PFNGLBUFFERDATAARBPROC > + ( wglGetProcAddress( "glBufferData" ) ); + glBufferSubData = reinterpret_cast< PFNGLBUFFERSUBDATAARBPROC > + ( wglGetProcAddress( "glBufferSubData" ) ); + glDeleteBuffers = reinterpret_cast< PFNGLDELETEBUFFERSARBPROC > + ( wglGetProcAddress( "glDeleteBuffers" ) ); + glGetBufferParameteriv = + reinterpret_cast< PFNGLGETBUFFERPARAMETERIVARBPROC > + ( wglGetProcAddress( "glGetBufferParameteriv" ) ); + glMapBuffer = reinterpret_cast< PFNGLMAPBUFFERARBPROC > + ( wglGetProcAddress( "glMapBuffer" ) ); + glUnmapBuffer = reinterpret_cast< PFNGLUNMAPBUFFERARBPROC > + ( wglGetProcAddress( "glUnmapBuffer" ) ); + + // Check once again VBO extension + if( + glGenBuffers != NULL && + glBindBuffer != NULL && + glBufferData != NULL && + glBufferSubData != NULL && + glMapBuffer != NULL && + glUnmapBuffer != NULL && + glDeleteBuffers != NULL && + glGetBufferParameteriv != NULL + ) + this->VBOSupported = true; + else + this->VBOSupported = false; +#else // _WIN32 + // Check if VBO ( Vertex Buffer Object ) is supported + std::string str = ( const char* )( glGetString( GL_EXTENSIONS ) ); + this->VBOSupported = + ( str.find( "GL_ARB_vertex_buffer_object" ) != std::string::npos ); +#endif // _WIN32 + + if( this->VBOSupported ) + { + // Create points and normals buffers + GLuint id1; + std::size_t pSize = input->GetNumberOfPoints( ) * sizeof( TPoint ); + std::size_t nSize = + input->GetPointNormalsContainer( ).size( ) * sizeof( TVector ); + const TPoint* verts = + input->GetPoints( )->CastToSTLContainer( ).data( ); + const TVector* norms = input->GetPointNormalsContainer( ).data( ); + glGenBuffers( 1, &id1 ); + glBindBuffer( GL_ARRAY_BUFFER, id1 ); + glBufferData( GL_ARRAY_BUFFER, pSize + nSize, 0, GL_STREAM_DRAW ); + glBufferSubData( GL_ARRAY_BUFFER, 0, pSize, verts ); + glBufferSubData( GL_ARRAY_BUFFER, pSize, nSize, norms ); + this->VBOID1 = ( unsigned int )( id1 ); + + // Create indices buffer + const TCellsContainer* cells = input->GetCells( ); + if( cells == NULL ) + { + itkExceptionMacro( + << "This QuadEdgeMesh does not have any cells!" + ); + + } // fi + + TCellIt cIt; + unsigned int cellPointsCount = 0; + this->Sizes.clear( ); + for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ ) + { + this->Sizes.push_back( cIt.Value( )->GetNumberOfPoints( ) ); + cellPointsCount += this->Sizes.back( ); + + } // rof + this->Indices.resize( cellPointsCount ); + unsigned int indId = 0; + for( cIt = cells->Begin( ); cIt != cells->End( ); cIt++ ) + { + const typename M::TQuadEdgeCell* cell = + dynamic_cast< const typename M::TQuadEdgeCell* >( cIt.Value( ) ); + const typename M::TPrimalEdge* edge = + cell->GetEntryPrimalEdge( ); + typename M::TPrimalEdge::ConstIterator iIt = edge->BeginLnext( ); + for( ; iIt != edge->EndLnext( ); ++iIt ) + this->Indices[ indId++ ] = ( *iIt )->GetOrigin( ); + + } // fi + + // Attach index buffer to VBO + std::size_t iSize = std::size_t( this->Indices.size( ) ); + iSize *= sizeof( TIndex ); + const unsigned int* indices = this->Indices.data( ); + GLuint id2; + glGenBuffers( 1, &id2 ); + glBindBuffer( GL_ARRAY_BUFFER, id2 ); + glBufferData( GL_ARRAY_BUFFER, iSize, indices, GL_STATIC_DRAW ); + + int bSize; + glGetBufferParameteriv( GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bSize ); + if( iSize != bSize ) + { + glDeleteBuffers( 1, &id2 ); + id2 = 0; + vtkErrorMacro( << "Data size mismatch with input array" ); + + } // fi + this->VBOID2 = ( unsigned int )( id2 ); + + } // fi + return( true ); +} + +#endif // __CPEXTENSIONS__VISUALIZATION__OPENGLMESHMAPPER__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..541d60c --- /dev/null +++ b/lib/cpExtensions/Visualization/SeedWidgetCorrector.h @@ -0,0 +1,45 @@ +#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/cpPipelineEditor/Block.cxx b/lib/cpPipelineEditor/Block.cxx new file mode 100644 index 0000000..cd32453 --- /dev/null +++ b/lib/cpPipelineEditor/Block.cxx @@ -0,0 +1,301 @@ +#include "Block.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "Port.h" +#include "Connection.h" +#include "Editor.h" + +// ------------------------------------------------------------------------- +cpPipelineEditor::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( ) ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Block:: +~Block( ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Editor* cpPipelineEditor::Block:: +editor( ) +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +const cpPipelineEditor::Editor* cpPipelineEditor::Block:: +editor( ) const +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Block:: +setEditor( cpPipelineEditor::Editor* editor ) +{ + this->m_Editor = editor; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::InputPort* cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::OutputPort* cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::InputPort* cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::OutputPort* cpPipelineEditor::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 cpPipelineEditor::Block:: +namePort( ) const +{ + return( this->m_NamePort->name( ) ); +} + +// ------------------------------------------------------------------------- +const cpPipelineEditor::InputPort* cpPipelineEditor::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 cpPipelineEditor::OutputPort* cpPipelineEditor::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 cpPipelineEditor::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 cpPipelineEditor::Block:: +itemChange( GraphicsItemChange change, const QVariant& value ) +{ + return( value ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Block:: +_setTypeInfo( const QString& txt ) +{ + this->setToolTip( txt ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::Block:: +mouseReleaseEvent( QGraphicsSceneMouseEvent* evt ) +{ + if( this->m_Filter != NULL ) + this->m_Filter->SetViewCoords( + this->scenePos( ).x( ), this->scenePos( ).y( ) + ); + this->Superclass::mouseReleaseEvent( evt ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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->CreateQtDialog( ); + dlg->exec( ); + } + else if( selectedAction == updateAction ) + this->m_Editor->updateFilter( this->namePort( ).toStdString( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Block.h b/lib/cpPipelineEditor/Block.h new file mode 100644 index 0000000..2ace7b7 --- /dev/null +++ b/lib/cpPipelineEditor/Block.h @@ -0,0 +1,85 @@ +#ifndef __CPPIPELINEEDITOR__BLOCK__H__ +#define __CPPIPELINEEDITOR__BLOCK__H__ + +#include +#include +#include + +namespace cpPipelineEditor +{ + class Editor; + class Port; + class NamePort; + class InputPort; + class OutputPort; + + /** + */ + class cpPipelineEditor_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( ); + + 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 // __CPPIPELINEEDITOR__BLOCK__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/CMakeLists.txt b/lib/cpPipelineEditor/CMakeLists.txt new file mode 100644 index 0000000..7943a91 --- /dev/null +++ b/lib/cpPipelineEditor/CMakeLists.txt @@ -0,0 +1,55 @@ +SET(lib_NAME cpPipelineEditor) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_HEADERS_H "*.h") +FILE(GLOB lib_HEADERS_HPP "*.hpp") +FILE(GLOB lib_HEADERS_HXX "*.hxx") +FILE(GLOB lib_SOURCES_C "*.c") +FILE(GLOB lib_SOURCES_CPP "*.cpp") +FILE(GLOB lib_SOURCES_CXX "*.cxx") +SET( + lib_QT_Headers + Canvas.h + Editor.h + ) + +## ===================== +## = Compilation rules = +## ===================== + +QT4_WRAP_CPP(lib_QT_Wrapped_MOC_Sources ${lib_QT_Headers}) + +ADD_LIBRARY( + ${lib_NAME} + SHARED + ${lib_SOURCES_C} + ${lib_SOURCES_CPP} + ${lib_SOURCES_CXX} + ${lib_QT_Wrapped_MOC_Sources} + ) +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_NAME}/${lib_NAME}_Export.h + STATIC_DEFINE ${lib_NAME}_BUILT_AS_STATIC + ) +TARGET_LINK_LIBRARIES( + ${lib_NAME} + ${QT_LIBRARIES} + cpPlugins + ) + +## ======================== +## -- Installation rules -- +## ======================== + +## eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Canvas.cxx b/lib/cpPipelineEditor/Canvas.cxx new file mode 100644 index 0000000..90f1285 --- /dev/null +++ b/lib/cpPipelineEditor/Canvas.cxx @@ -0,0 +1,160 @@ +#include "Canvas.h" +#include "Editor.h" +#include "Block.h" +#include "Connection.h" +#include "Port.h" + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Canvas:: +~Canvas( ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor:: +Editor* cpPipelineEditor::Canvas:: +editor( ) +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +const cpPipelineEditor:: +Editor* cpPipelineEditor::Canvas:: +editor( ) const +{ + return( this->m_Editor ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::Canvas:: +wheelEvent( QWheelEvent* event ) +{ + this->_scaleView( + std::pow( double( 2 ), event->delta( ) / double( 240 ) ) + ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Canvas:: +dragEnterEvent( QDragEnterEvent* event ) +{ + const QMimeData* mime = event->mimeData( ); + if( mime->hasFormat( "application/x-qabstractitemmodeldatalist" ) ) + event->acceptProposedAction( ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Canvas:: +dragLeaveEvent( QDragLeaveEvent* event ) +{ +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Canvas:: +dragMoveEvent( QDragMoveEvent* event ) +{ +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::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/cpPipelineEditor/Canvas.h b/lib/cpPipelineEditor/Canvas.h new file mode 100644 index 0000000..eb57a23 --- /dev/null +++ b/lib/cpPipelineEditor/Canvas.h @@ -0,0 +1,50 @@ +#ifndef __CPPIPELINEEDITOR__CANVAS__H__ +#define __CPPIPELINEEDITOR__CANVAS__H__ + +#include +#include + +namespace cpPipelineEditor +{ + // Some other forward declarations + class Block; + class Connection; + class Editor; + + /** + */ + class cpPipelineEditor_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 // __CPPIPELINEEDITOR__CANVAS__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Connection.cxx b/lib/cpPipelineEditor/Connection.cxx new file mode 100644 index 0000000..0d5eea2 --- /dev/null +++ b/lib/cpPipelineEditor/Connection.cxx @@ -0,0 +1,140 @@ +#include "Connection.h" +#include "Port.h" + +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::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 cpPipelineEditor::Connection:: +setPos1( const QPointF& p ) +{ + this->m_Pos1 = p; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Connection:: +setPos2( const QPointF& p ) +{ + this->m_Pos2 = p; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Connection:: +setPort1( OutputPort* p ) +{ + if( p != NULL ) + { + p->connections( ).append( this ); + this->m_Port1 = p; + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Connection:: +setPort2( InputPort* p ) +{ + if( p != NULL ) + { + if( p->connection( ) == NULL ) + { + p->setConnection( this ); + this->m_Port2 = p; + + } // fi + + } // fi +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::OutputPort* cpPipelineEditor::Connection:: +port1( ) const +{ + return( this->m_Port1 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::InputPort* cpPipelineEditor::Connection:: +port2( ) const +{ + return( this->m_Port2 ); +} + +#include + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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/cpPipelineEditor/Connection.h b/lib/cpPipelineEditor/Connection.h new file mode 100644 index 0000000..94b8676 --- /dev/null +++ b/lib/cpPipelineEditor/Connection.h @@ -0,0 +1,56 @@ +#ifndef __CPPIPELINEEDITOR__CONNECTION__H__ +#define __CPPIPELINEEDITOR__CONNECTION__H__ + +#include +#include + +namespace cpPipelineEditor +{ + class InputPort; + class OutputPort; + + /** + */ + class cpPipelineEditor_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 // __CPPIPELINEEDITOR__CONNECTION__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Editor.cxx b/lib/cpPipelineEditor/Editor.cxx new file mode 100644 index 0000000..319edb5 --- /dev/null +++ b/lib/cpPipelineEditor/Editor.cxx @@ -0,0 +1,598 @@ +#include "Editor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Port.h" +#include "Connection.h" +#include "Block.h" + +// ------------------------------------------------------------------------- +#define cpPipelineEditor_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 cpPipelineEditor_Editor_Callback_CODE( E ) \ + void cpPipelineEditor::Editor::_##E##_cbk( QGraphicsScene##E##Event* evt ) + +// ------------------------------------------------------------------------- +cpPipelineEditor::Editor:: +Editor( QObject* parent ) + : Superclass( parent ), + m_ActualConnection( NULL ), + m_Workspace( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Editor:: +~Editor( ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Editor:: +TWorkspace* cpPipelineEditor::Editor:: +workspace( ) +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +const cpPipelineEditor::Editor:: +TWorkspace* cpPipelineEditor::Editor:: +workspace( ) const +{ + return( this->m_Workspace ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::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 cpPipelineEditor::Editor:: +deleteFilter( const std::string& name ) +{ + std::cout << name << std::endl; + return( false ); +} + +// ------------------------------------------------------------------------- +bool cpPipelineEditor::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 cpPipelineEditor::Editor:: +install( QGraphicsScene* s ) +{ + s->installEventFilter( this ); + this->m_Scene = s; +} + +// ------------------------------------------------------------------------- +QGraphicsItem* cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Block* cpPipelineEditor::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 cpPipelineEditor::Editor:: +eventFilter( QObject* o, QEvent* e ) +{ + // Event type + switch( int( e->type( ) ) ) + { + cpPipelineEditor_Editor_Callback_SWITCH( ContextMenu, e ); + cpPipelineEditor_Editor_Callback_SWITCH( DragEnter, e ); + cpPipelineEditor_Editor_Callback_SWITCH( DragLeave, e ); + cpPipelineEditor_Editor_Callback_SWITCH( DragMove, e ); + cpPipelineEditor_Editor_Callback_SWITCH( Drop, e ); + cpPipelineEditor_Editor_Callback_SWITCH( Help, e ); + cpPipelineEditor_Editor_Callback_SWITCH( HoverEnter, e ); + cpPipelineEditor_Editor_Callback_SWITCH( HoverLeave, e ); + cpPipelineEditor_Editor_Callback_SWITCH( HoverMove, e ); + cpPipelineEditor_Editor_Callback_SWITCH( MouseDoubleClick, e ); + cpPipelineEditor_Editor_Callback_SWITCH( MouseMove, e ); + cpPipelineEditor_Editor_Callback_SWITCH( MousePress, e ); + cpPipelineEditor_Editor_Callback_SWITCH( MouseRelease, e ); + cpPipelineEditor_Editor_Callback_SWITCH( Move, e ); + cpPipelineEditor_Editor_Callback_SWITCH( Resize, e ); + cpPipelineEditor_Editor_Callback_SWITCH( Wheel, e ); + default: + break; + } // hctiws + return( this->Superclass::eventFilter( o, e ) ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Editor:: +updateFilter( const std::string& filter_name ) +{ + emit execFilter( filter_name ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Editor:: +showOutputData( + const std::string& filter_name, const std::string& output_name + ) +{ + emit showFilterOutput( filter_name, output_name ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( ContextMenu ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( DragEnter ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( DragLeave ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( DragMove ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( Drop ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( Help ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( HoverEnter ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( HoverLeave ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( HoverMove ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_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 +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_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 +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_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 +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_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 +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( Move ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( Resize ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor_Editor_Callback_CODE( Wheel ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Editor.h b/lib/cpPipelineEditor/Editor.h new file mode 100644 index 0000000..3429477 --- /dev/null +++ b/lib/cpPipelineEditor/Editor.h @@ -0,0 +1,131 @@ +#ifndef __CPPIPELINEEDITOR__EDITOR__H__ +#define __CPPIPELINEEDITOR__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 cpPipelineEditor_Editor_Callback_DCL( E ) \ + void _##E##_cbk( QGraphicsScene##E##Event* e ); + +namespace cpPipelineEditor +{ + class Connection; + class Block; + + /** + */ + class cpPipelineEditor_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 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 + ); + + signals: + void execFilter( const std::string& filter_name ); + void showFilterOutput( + 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; + + cpPipelineEditor_Editor_Callback_DCL( ContextMenu ); + cpPipelineEditor_Editor_Callback_DCL( DragEnter ); + cpPipelineEditor_Editor_Callback_DCL( DragLeave ); + cpPipelineEditor_Editor_Callback_DCL( DragMove ); + cpPipelineEditor_Editor_Callback_DCL( Drop ); + cpPipelineEditor_Editor_Callback_DCL( Help ); + cpPipelineEditor_Editor_Callback_DCL( HoverEnter ); + cpPipelineEditor_Editor_Callback_DCL( HoverLeave ); + cpPipelineEditor_Editor_Callback_DCL( HoverMove ); + cpPipelineEditor_Editor_Callback_DCL( MouseDoubleClick ); + cpPipelineEditor_Editor_Callback_DCL( MouseMove ); + cpPipelineEditor_Editor_Callback_DCL( MousePress ); + cpPipelineEditor_Editor_Callback_DCL( MouseRelease ); + cpPipelineEditor_Editor_Callback_DCL( Move ); + cpPipelineEditor_Editor_Callback_DCL( Resize ); + cpPipelineEditor_Editor_Callback_DCL( Wheel ); + + private: + QGraphicsScene* m_Scene; + Connection* m_ActualConnection; + + TWorkspace* m_Workspace; + TGraph::Pointer m_Graph; + }; + +} // ecapseman + +#endif // __CPPIPELINEEDITOR__EDITOR__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Port.cxx b/lib/cpPipelineEditor/Port.cxx new file mode 100644 index 0000000..b447b0a --- /dev/null +++ b/lib/cpPipelineEditor/Port.cxx @@ -0,0 +1,292 @@ +#include "Port.h" +#include "Connection.h" +#include "Block.h" +#include "Editor.h" + +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::Port:: +~Port( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Port:: +setBlock( Block* b ) +{ + this->m_Block = b; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Port:: +setName( const QString& n ) +{ + this->m_Label->setPlainText( n ); + this->_updateLabels( ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Port:: +setExtendedName( const QString& n ) +{ + this->m_ExtendedLabel->setPlainText( n ); + this->_updateLabels( ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::Port:: +setExtend( bool extend ) +{ + // Do nothing! + this->m_IsExtended = false; + this->m_ExtendedLabel->setVisible( false ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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( ) ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::NamePort:: +NamePort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::NamePort:: +~NamePort( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::NamePort:: +_updateLabels( ) +{ + QFont font( this->scene( )->font( ) ); + font.setBold( true ); + this->m_Label->setFont( font ); + this->m_ExtendedLabel->setFont( font ); + this->setPath( QPainterPath( ) ); +} + +// ------------------------------------------------------------------------- +bool cpPipelineEditor::NamePort:: +isConnected( Port* other ) +{ + return( false ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::InputPort:: +InputPort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ), + m_Connection( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::InputPort:: +~InputPort( ) +{ + if( this->m_Connection != NULL ) + delete this->m_Connection; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::InputPort:: +setExtend( bool extend ) +{ + if( this->m_Connection == NULL ) + { + this->m_IsExtended = extend; + this->m_ExtendedLabel->setVisible( extend ); + } + else + this->Superclass::setExtend( false ); +} + +// ------------------------------------------------------------------------- +bool cpPipelineEditor::InputPort:: +isConnected( Port* other ) +{ + if( this->m_Connection != NULL ) + return( + this->m_Connection->port1( ) == other && + this->m_Connection->port2( ) == this + ); + else + return( false ); +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::InputPort:: +setConnection( Connection* c ) +{ + this->m_Connection = c; +} + +// ------------------------------------------------------------------------- +QVariant cpPipelineEditor::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 ); +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::OutputPort:: +OutputPort( QGraphicsItem* parent, QGraphicsScene* scene ) + : Superclass( parent, scene ) +{ +} + +// ------------------------------------------------------------------------- +cpPipelineEditor::OutputPort:: +~OutputPort( ) +{ + foreach( Connection* conn, this->m_Connections ) + delete conn; +} + +// ------------------------------------------------------------------------- +void cpPipelineEditor::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 cpPipelineEditor::OutputPort:: +setExtend( bool extend ) +{ + this->m_IsExtended = extend; + this->m_ExtendedLabel->setVisible( extend ); +} + +// ------------------------------------------------------------------------- +bool cpPipelineEditor::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 cpPipelineEditor::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 cpPipelineEditor::OutputPort:: +contextMenuEvent( QGraphicsSceneContextMenuEvent* evt ) +{ + if( this->m_Block == NULL ) + return; + + QMenu menu; + QAction* showAction = menu.addAction( "Show" ); + QAction* hideAction = menu.addAction( "Hide" ); + 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 ) + { + } // fi +} + +// eof - $RCSfile$ diff --git a/lib/cpPipelineEditor/Port.h b/lib/cpPipelineEditor/Port.h new file mode 100644 index 0000000..4daafd0 --- /dev/null +++ b/lib/cpPipelineEditor/Port.h @@ -0,0 +1,169 @@ +#ifndef __CPPIPELINEEDITOR__PORT__H__ +#define __CPPIPELINEEDITOR__PORT__H__ + +#include +#include + +namespace cpPipelineEditor +{ + class Block; + class Connection; + + /** + */ + class cpPipelineEditor_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 // __CPPIPELINEEDITOR__PORT__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/BaseWidget.cxx b/lib/cpPlugins/BaseWidget.cxx new file mode 100644 index 0000000..35915d2 --- /dev/null +++ b/lib/cpPlugins/BaseWidget.cxx @@ -0,0 +1,59 @@ +#include + +// ------------------------------------------------------------------------- +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 +} + +// ------------------------------------------------------------------------- +cpPlugins::BaseWidget:: +BaseWidget( ) + : Superclass( ), + m_MPRViewer( NULL ), + m_SingleInteractor( NULL ) +{ +} + +// ------------------------------------------------------------------------- +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..04de85a --- /dev/null +++ b/lib/cpPlugins/BaseWidget.h @@ -0,0 +1,60 @@ +#ifndef __CPPLUGINS__BASEWIDGET__H__ +#define __CPPLUGINS__BASEWIDGET__H__ + +#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: + const TMPRWidget* GetMPRViewer( ) const; + const vtkRenderWindowInteractor* GetSingleInteractor( ) const; + + void SetMPRViewer( TMPRWidget* v ); + void SetSingleInteractor( vtkRenderWindowInteractor* i ); + + 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/CMakeLists.txt b/lib/cpPlugins/CMakeLists.txt new file mode 100644 index 0000000..8efbc6c --- /dev/null +++ b/lib/cpPlugins/CMakeLists.txt @@ -0,0 +1,133 @@ +## ============================= +## = Set names and directories = +## ============================= + +SET(lib_NAME cpPlugins) +SET(lib_DIR cpPlugins) + +## ========================= +## = Configure local files = +## ========================= + +CONFIGURE_FILE( + Config.h.in + ${PROJECT_BINARY_DIR}/lib/${lib_DIR}/Config.h + @ONLY + ) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_HEADERS_H "*.h") +FILE(GLOB lib_HEADERS_HPP "*.hpp") +FILE(GLOB lib_HEADERS_HXX "*.hxx") +FILE(GLOB lib_SOURCES_C "*.c") +FILE(GLOB lib_SOURCES_CPP "*.cpp") +FILE(GLOB lib_SOURCES_CXX "*.cxx") + +IF(USE_QT4) + SET( + lib_QT_UI + ) + SET( + lib_QT_Headers + ParametersQtDialog.h + ) + SET( + lib_QT_Sources + 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_SOURCES_CXX + ${lib_SOURCES_CXX} + ${lib_QT_Sources} + ${lib_QT_Wrapped_Headers} + ${lib_QT_Wrapped_MOC_Sources} + ${lib_QT_Wrapped_Resources_Sources} + ) + +ENDIF(USE_QT4) + +# =================================== +# = Integrate all source file names = +# =================================== + +SET( + lib_HEADERS + ${lib_HEADERS_H} + ${lib_HEADERS_HPP} + ${lib_HEADERS_HXX} + ) + +SET( + lib_SOURCES + ${lib_SOURCES_C} + ${lib_SOURCES_CPP} + ${lib_SOURCES_CXX} + ) + +SET( + target_LIBRARIES + cpPlugins_ITKInstances + ${VTK_LIBRARIES} + ) +IF(NOT WIN32) + SET( + target_LIBRARIES + ${target_LIBRARIES} + cpPlugins_tinyxml2 + dl + ) +ENDIF(NOT WIN32) + +## ===================== +## = Compilation rules = +## ===================== + +ADD_LIBRARY(${lib_NAME} SHARED ${lib_SOURCES}) +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 + ) +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..75ae331 --- /dev/null +++ b/lib/cpPlugins/Config.h.in @@ -0,0 +1,112 @@ +#ifndef __CPPLUGINS__CONFIG__H__ +#define __CPPLUGINS__CONFIG__H__ + +#include +#include + +/* + * ========================================================================= + * Version numbers and strings + * ========================================================================= + */ +#define cpPlugins_MAJ_VER @prj_MAJ_VER@ +#define cpPlugins_MIN_VER @prj_MIN_VER@ +#define cpPlugins_REL_VER @prj_REL_VER@ +#define cpPlugins_VER "@prj_VER@" +#define cpPlugins_sVER "@prj_sVER@" + +/* + * ========================================================================= + * Some useful constants and values + * ========================================================================= + */ + +#define ITK_MANUAL_INSTANTIATION +#define cpPlugins_CONFIG_FILE "plugins.cfg" + +#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 + +/* + * ========================================================================= + * Identify OS + * ========================================================================= + */ +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) +# define cpPlugins_SYS_WINDOWS +# define cpPlugins_PLUGIN_PREFIX "" +# define cpPlugins_PLUGIN_EXT "dll" +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef NOMINMAX +# define NOMINMAX +# endif +#elif defined( linux ) || defined( __linux ) +# define cpPlugins_SYS_LINUX +# define cpPlugins_PLUGIN_PREFIX "lib" +# define cpPlugins_PLUGIN_EXT "so" +#elif defined( __APPLE__ ) || defined( MACOSX ) || defined( macintosh ) || defined( Macintosh ) +# define cpPlugins_SYS_MACOS +# define cpPlugins_PLUGIN_PREFIX "lib" +# define cpPlugins_PLUGIN_EXT "dylib" +#elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ ) +# define cpPlugins_SYS_FREEBSD +# define cpPlugins_PLUGIN_PREFIX "lib" +# define cpPlugins_PLUGIN_EXT "so" +#else +# error "This operating system is not supported by cpPlugins" +#endif + +/* + * ========================================================================= + * Some macros + * ========================================================================= + */ +#define cpPlugins_Id_Macro( N, C ) \ + public: \ + virtual const char* GetClassName( ) override { return( #N ); } \ + virtual const char* GetClassCategory( ) override { return( #C ); } + +/* + * ========================================================================= + * Some functions + * ========================================================================= + */ +namespace cpPlugins +{ + struct PathHelper + { + // --------------------------------------------------------------------- + inline bool operator()( char c ) const + { +#ifdef cpPlugins_SYS_WINDOWS + return( c == '\\' || c == '/' ); +#else // cpPlugins_SYS_WINDOWS + return( c == '/' ); +#endif // cpPlugins_SYS_WINDOWS + } + + // --------------------------------------------------------------------- + inline static std::string CanonicalPath( const std::string& path ) + { +#ifdef cpPlugins_SYS_WINDOWS + TCHAR buffer[ 4096 ] = TEXT( "" ); + TCHAR** lppPart = { NULL }; + GetFullPathName( path.c_str( ), 4096, buffer, lppPart ); + return( std::string( buffer ) ); +#else // cpPlugins_SYS_WINDOWS + return( std::string( realpath( path.c_str( ), NULL ) ) ); +#endif // cpPlugins_SYS_WINDOWS + } + }; + +} // ecapseman + +#endif // __CPPLUGINS__CONFIG__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/DataObject.cxx b/lib/cpPlugins/DataObject.cxx new file mode 100644 index 0000000..06c10df --- /dev/null +++ b/lib/cpPlugins/DataObject.cxx @@ -0,0 +1,81 @@ +#include + +#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( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject:: +DataObject( ) + : Superclass( ), + m_Source( NULL ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::DataObject:: +~DataObject( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/DataObject.h b/lib/cpPlugins/DataObject.h new file mode 100644 index 0000000..279fe76 --- /dev/null +++ b/lib/cpPlugins/DataObject.h @@ -0,0 +1,51 @@ +#ifndef __CPPLUGINS__DATAOBJECT__H__ +#define __CPPLUGINS__DATAOBJECT__H__ + +#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( ); + + protected: + DataObject( ); + virtual ~DataObject( ); + + private: + // Purposely not implemented + DataObject( const Self& ); + Self& operator=( const Self& ); + + protected: + ProcessObject* m_Source; + }; + +} // 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..ba3ff29 --- /dev/null +++ b/lib/cpPlugins/Image.cxx @@ -0,0 +1,41 @@ +#include + +// ------------------------------------------------------------------------- +void cpPlugins::Image:: +SetITK( itk::LightObject* o ) +{ + this->Superclass::SetITK( o ); + bool s = this->_ITK_2_VTK_0< 2 >( o ); + if( !s ) s = this->_ITK_2_VTK_0< 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( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Image.h b/lib/cpPlugins/Image.h new file mode 100644 index 0000000..fa7c7c3 --- /dev/null +++ b/lib/cpPlugins/Image.h @@ -0,0 +1,55 @@ +#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; + + public: + cpPlugins_Id_Macro( Image, Object ); + + public: + Image( ); + virtual ~Image( ); + + virtual void SetITK( itk::LightObject* o ) override; + virtual void SetVTK( vtkObjectBase* o ) override; + + protected: + + template< unsigned int D > + inline bool _ITK_2_VTK_0( itk::LightObject* o ); + + template< class P, unsigned int D > + inline bool _ITK_2_VTK_1( itk::LightObject* o ); + + template< class I > + 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..dd6ef10 --- /dev/null +++ b/lib/cpPlugins/Image.hxx @@ -0,0 +1,149 @@ +#ifndef __CPPLUGINS__IMAGE__HXX__ +#define __CPPLUGINS__IMAGE__HXX__ + +#include + +// ------------------------------------------------------------------------- +template< unsigned int D > +bool cpPlugins::Image:: +_ITK_2_VTK_0( itk::LightObject* o ) +{ + bool s = false; + if( dynamic_cast< itk::ImageBase< D >* >( o ) != NULL ) + { + s |= this->_ITK_2_VTK_1< char, D >( o ); + s |= this->_ITK_2_VTK_1< short, D >( o ); + s |= this->_ITK_2_VTK_1< int, D >( o ); + s |= this->_ITK_2_VTK_1< long, D >( o ); + s |= this->_ITK_2_VTK_1< float, D >( o ); + s |= this->_ITK_2_VTK_1< double, D >( o ); + s |= this->_ITK_2_VTK_1< unsigned char, D >( o ); + s |= this->_ITK_2_VTK_1< unsigned short, D >( o ); + s |= this->_ITK_2_VTK_1< unsigned int, D >( o ); + s |= this->_ITK_2_VTK_1< unsigned long, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< char >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< short >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< int >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< long >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< float >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< double >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned char >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned short >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned int >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBPixel< unsigned long >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< char >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< short >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< int >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< long >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< float >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< double >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned char >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned short >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned int >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::RGBAPixel< unsigned long >, D >( o ); + /* TODO + s |= this->_ITK_2_VTK_1< itk::DiffusionTensor3D< float >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::DiffusionTensor3D< double >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::Vector< float, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::Vector< double, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::CovariantVector< float, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::CovariantVector< double, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::Point< float, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::Point< double, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::SymmetricSecondRankTensor< float, D >, D >( o ); + s |= this->_ITK_2_VTK_1< itk::SymmetricSecondRankTensor< double, D >, 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 I > +bool cpPlugins::Image:: +_ITK_2_VTK_2( itk::LightObject* o ) +{ + typedef itk::ImageToVTKImageFilter< I > _I2V; + + I* image = dynamic_cast< I* >( 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 cpPlugin_Image_Demangle_Dim( FUNC, INPUT, D ) \ + this->FUNC( INPUT->GetITK< itk::ImageBase< D > >( ) ) + +#define cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, PIXEL, D ) \ + this->FUNC( dynamic_cast< itk::Image< PIXEL, D >* >( INPUT ) ) + +#define cpPlugin_Image_Demangle_Pixel_AllScalars( r, FUNC, INPUT, D ) \ + r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, char, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, short, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, int, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, long, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, float, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, double, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, unsigned char, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, unsigned short, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, unsigned int, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, unsigned long, D ) + +#define cpPlugin_Image_Demangle_Pixel_AllColor( r, FUNC, INPUT, D ) \ + r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< char >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< short >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< int >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< long >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< float >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< double >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< unsigned char >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< unsigned short >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< unsigned int >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBPixel< unsigned long >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< char >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< short >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< int >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< long >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< float >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< double >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< unsigned char >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< unsigned short >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< unsigned int >, D ); \ + if( r != "" ) r = cpPlugin_Image_Demangle_Pixel_Dim( FUNC, INPUT, itk::RGBAPixel< unsigned long >, D ) + +#endif // __CPPLUGINS__IMAGE__HXX__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface.cxx b/lib/cpPlugins/Interface.cxx new file mode 100644 index 0000000..de6d631 --- /dev/null +++ b/lib/cpPlugins/Interface.cxx @@ -0,0 +1,157 @@ +#include + +#include +#include +#include + +#ifdef cpPlugins_SYS_WINDOWS +#else // cpPlugins_SYS_WINDOWS +# include +#endif // cpPlugins_SYS_WINDOWS + + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +Interface( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Interface:: +~Interface( ) +{ + this->UnloadAll( ); +} + +// ------------------------------------------------------------------------- +const cpPlugins::Interface:: +TFilters& cpPlugins::Interface:: +GetFilters( ) +{ + return( this->m_Filters ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +LoadPluginFile( const std::string& filename ) +{ + auto canonical_fn = cpPlugins::PathHelper::CanonicalPath( filename ); + void* hnd = NULL; + std::map< std::string, std::set< std::string > > filters; +#ifdef cpPlugins_SYS_WINDOWS + // TODO: +#else // cpPlugins_SYS_WINDOWS + + // Try to load canonical filename and clean error messages + hnd = dlopen( canonical_fn.c_str( ), RTLD_NOW | RTLD_GLOBAL ); + if( hnd == NULL ) + throw std::runtime_error( + std::string( "cpPlugins::Interface: Could not load library \"" ) + + canonical_fn + + std::string( "\"" ) + ); + dlerror( ); + + // Init plugins + typedef const std::map< std::string, std::set< std::string > > ( *func_t )( ); + auto func = ( func_t ) dlsym( hnd, "LoadedFilters" ); + const char* func_error = dlerror( ); + if( func_error != NULL ) + { + dlclose( hnd ); + throw std::runtime_error( + std::string( "cpPlugins::Interface: Library \"" ) + + canonical_fn + + std::string( "\" not recognized as a cpPlugins library." ) + ); + + } // fi + filters = func( ); +#endif // cpPlugins_SYS_WINDOWS + if( hnd != NULL ) + { + // Save the loaded filters names + for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt ) + { + auto colIt = this->m_Filters.find( cIt->first ); + for( auto fIt = cIt->second.begin( ); fIt != cIt->second.end( ); ++fIt ) + { + bool found = false; + if( colIt != this->m_Filters.end( ) ) + { + auto rowIt = colIt->second.find( *fIt ); + if( rowIt != colIt->second.end( ) ) + found = true; + + } // fi + if( !found ) + this->m_Filters[ cIt->first ][ *fIt ] = canonical_fn; + + } // rof + + } // rof + + // Save the hnd + this->m_Plugins[ canonical_fn ] = hnd; + } + else + throw std::runtime_error( + "cpPlugins::Interface: Operative system not yet supported." + ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::Interface:: +UnloadAll( ) +{ + auto pIt = this->m_Plugins.begin( ); + for( ; pIt != this->m_Plugins.end( ); ++pIt ) + { +#ifdef cpPlugins_SYS_WINDOWS +#else // cpPlugins_SYS_WINDOWS + dlclose( pIt->second ); +#endif // cpPlugins_SYS_WINDOWS + } // rof + this->m_Plugins.clear( ); + this->m_Filters.clear( ); +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject::Pointer cpPlugins::Interface:: +Create( const std::string& category, const std::string& name ) +{ + cpPlugins::ProcessObject::Pointer filter; + auto cIt = this->m_Filters.find( category ); + if( cIt != this->m_Filters.end( ) ) + { + auto nIt = cIt->second.find( name ); + if( nIt != cIt->second.end( ) ) + { + auto pIt = this->m_Plugins.find( nIt->second ); + if( pIt != this->m_Plugins.end( ) ) + { +#ifdef cpPlugins_SYS_WINDOWS +#else // cpPlugins_SYS_WINDOWS + std::string func_name = category + "_" + name; + typedef cpPlugins::ProcessObject::Pointer ( *func_t )( ); + auto func = ( func_t ) dlsym( pIt->second, func_name.c_str( ) ); + if( func == NULL ) + { + throw std::runtime_error( + std::string( "cpPlugins::Interface: Class \"" ) + + category + std::string( ":" ) + name + + std::string( "\" does not have a valid creator function." ) + ); + + } // fi + filter = func( ); +#endif // cpPlugins_SYS_WINDOWS + } // fi + + } // fi + + } // fi + return( filter ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Interface.h b/lib/cpPlugins/Interface.h new file mode 100644 index 0000000..7c860db --- /dev/null +++ b/lib/cpPlugins/Interface.h @@ -0,0 +1,41 @@ +#ifndef __CPPLUGINS__INTERFACE__H__ +#define __CPPLUGINS__INTERFACE__H__ + +#include +#include +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT Interface + { + public: + typedef std::map< std::string, std::string > TStringRow; + typedef std::map< std::string, TStringRow > TFilters; + + public: + Interface( ); + virtual ~Interface( ); + + const TFilters& GetFilters( ); + + void LoadPluginFile( const std::string& filename ); + void UnloadAll( ); + + cpPlugins::ProcessObject::Pointer Create( + const std::string& category, const std::string& name + ); + + protected: + std::map< std::string, void* > m_Plugins; + TFilters m_Filters; + }; + +} // ecapseman + +#endif // __CPPLUGINS__INTERFACE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Object.cxx b/lib/cpPlugins/Object.cxx new file mode 100644 index 0000000..a6615b4 --- /dev/null +++ b/lib/cpPlugins/Object.cxx @@ -0,0 +1,116 @@ +#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 +} + +#ifdef cpPlugins_QT4 +// ------------------------------------------------------------------------- +void cpPlugins::Object:: +SetViewCoords( const QPointF& coords ) +{ + this->SetViewCoords( coords.x( ), coords.y( ) ); +} + +// ------------------------------------------------------------------------- +QPointF cpPlugins::Object:: +GetViewCoords( ) const +{ + return( QPointF( this->m_ViewX, this->m_ViewY ) ); +} +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +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( ); +} + +// ------------------------------------------------------------------------- +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..881edde --- /dev/null +++ b/lib/cpPlugins/Object.h @@ -0,0 +1,86 @@ +#ifndef __CPPLUGINS__OBJECT__H__ +#define __CPPLUGINS__OBJECT__H__ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef cpPlugins_QT4 +# include +#endif // cpPlugins_QT4 + +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( ) = 0; + virtual const char* GetClassCategory( ) = 0; + + const float& GetViewX( ) const; + const float& GetViewY( ) const; + void SetViewCoords( float x, float y ); + +#ifdef cpPlugins_QT4 + void SetViewCoords( const QPointF& coords ); + QPointF GetViewCoords( ) const; +#endif // cpPlugins_QT4 + + virtual void Modified( ) const override; + virtual itk::ModifiedTimeType GetMTime( ) const 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/Parameters.cxx b/lib/cpPlugins/Parameters.cxx new file mode 100644 index 0000000..c805327 --- /dev/null +++ b/lib/cpPlugins/Parameters.cxx @@ -0,0 +1,348 @@ +#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 ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Parameters.h b/lib/cpPlugins/Parameters.h new file mode 100644 index 0000000..5393d03 --- /dev/null +++ b/lib/cpPlugins/Parameters.h @@ -0,0 +1,308 @@ +#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 ) \ + { \ + this->m_Parameters[ name ] = TParameter( Self::Y, "" ); \ + this->Modified( ); \ + } \ + bool Has##Y( const std::string& name ) const \ + { \ + auto i = this->m_Parameters.find( name ); \ + if( i != this->m_Parameters.end( ) ) \ + return( i->second.first == Self::Y ); \ + else \ + return( false ); \ + } + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_GetSet( Y ) \ + T##Y Get##Y( const std::string& name ) const \ + { \ + auto i = this->m_Parameters.find( name ); \ + if( i != this->m_Parameters.end( ) ) \ + { \ + if( i->second.first == Self::Y ) \ + { \ + if( typeid( T##Y ) != typeid( std::string ) ) \ + { \ + std::istringstream tok_str( i->second.second ); \ + T##Y v; \ + tok_str >> v; \ + return( v ); \ + } \ + else \ + { \ + const T##Y* ptr = \ + reinterpret_cast< const T##Y* >( \ + &( i->second.second ) \ + ); \ + return( *ptr ); \ + } \ + } \ + } \ + return( T##Y( 0 ) ); \ + } \ + void Set##Y( const std::string& name, const T##Y& v ) \ + { \ + auto i = this->m_Parameters.find( name ); \ + if( i != this->m_Parameters.end( ) ) \ + { \ + if( i->second.first == Self::Y ) \ + { \ + if( typeid( T##Y ) != typeid( std::string ) ) \ + { \ + std::stringstream str; \ + str << v; \ + if( i->second.second != str.str( ) ) \ + { \ + i->second.second = str.str( ); \ + this->Modified( ); \ + } \ + } \ + else \ + { \ + const std::string* str = \ + reinterpret_cast< const std::string* >( &v ); \ + if( i->second.second != *str ) \ + { \ + i->second.second = *str; \ + this->Modified( ); \ + } \ + } \ + } \ + } \ + } + +// ------------------------------------------------------------------------- +#define cpPlugins_Parameters_GetSetList( Y ) \ + std::vector< T##Y > Get##Y##List( const std::string& name ) const \ + { \ + std::vector< T##Y > 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::Y##List ) \ + { \ + std::istringstream str( i->second.second ); \ + std::string token; \ + while( std::getline( str, token, '#' ) ) \ + { \ + if( typeid( T##Y ) != typeid( std::string ) ) \ + { \ + std::istringstream tok_str( token ); \ + T##Y v; \ + tok_str >> v; \ + lst.push_back( v ); \ + } \ + else \ + slst->push_back( token ); \ + } \ + } \ + } \ + return( lst ); \ + } \ + void AddTo##Y##List( const std::string& name, const T##Y& v ) \ + { \ + auto i = this->m_Parameters.find( name ); \ + if( i != this->m_Parameters.end( ) ) \ + { \ + if( i->second.first == Self::Y##List ) \ + { \ + std::stringstream str; \ + if( i->second.second != "" ) \ + str << i->second.second << "#"; \ + str << v; \ + i->second.second = str.str( ); \ + this->Modified( ); \ + } \ + } \ + } \ + void Clear##Y##List( const std::string& name ) \ + { \ + auto i = this->m_Parameters.find( name ); \ + if( i != this->m_Parameters.end( ) ) \ + { \ + if( i->second.first == Self::Y##List ) \ + { \ + if( i->second.second != "" ) \ + { \ + i->second.second = ""; \ + this->Modified( ); \ + } \ + } \ + } \ + } + +namespace cpPlugins +{ + // Forward declaration to improve Qt dialog execution + class ParametersQtDialog; + + /** + */ + class cpPlugins_EXPORT Parameters + { + // Frienship with forward declaration to improve Qt dialog execution + friend class ParametersQtDialog; + 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; + + 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/ParametersQtDialog.cxx b/lib/cpPlugins/ParametersQtDialog.cxx new file mode 100644 index 0000000..09e30fe --- /dev/null +++ b/lib/cpPlugins/ParametersQtDialog.cxx @@ -0,0 +1,858 @@ +#include + +#ifdef cpPlugins_QT4 + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::ParametersQtDialog:: +ParametersQtDialog( QWidget* parent, Qt::WindowFlags f ) + : QDialog( parent, f ), + m_ProcessObject( NULL ), + m_WidgetsUpdated( false ) +{ + 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 ); +} + +// ------------------------------------------------------------------------- +cpPlugins::ParametersQtDialog:: +~ParametersQtDialog( ) +{ + delete this->m_Title; + delete this->m_ToolsLayout; + delete this->m_MainLayout; +} + +// ------------------------------------------------------------------------- +cpPlugins:: +ProcessObject* cpPlugins::ParametersQtDialog:: +getProcessObject( ) const +{ + return( this->m_ProcessObject ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::ParametersQtDialog:: +setProcessObject( ProcessObject* obj ) +{ + if( this->m_ProcessObject != NULL || obj == NULL ) + return( false ); + this->m_ProcessObject = obj; + this->m_WidgetsUpdated = false; + return( true ); +} + +// ------------------------------------------------------------------------- +int cpPlugins::ParametersQtDialog:: +exec( ) +{ + this->_updateWidgets( ); + this->updateView( ); + + int ret = this->QDialog::exec( ); + if( ret == 1 ) + this->updateParameters( ); + else + this->updateView( ); + return( ret ); +} + +// ------------------------------------------------------------------------- +void cpPlugins::ParametersQtDialog:: +updateParameters( ) +{ + if( this->m_ProcessObject == NULL ) + return; + + // 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::ParametersQtDialog:: +updateView( ) +{ + if( this->m_ProcessObject == NULL ) + return; + + // 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::ParametersQtDialog:: +_addButtons( ) +{ + // 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::ParametersQtDialog:: +_updateWidgets( ) +{ + if( this->m_WidgetsUpdated || this->m_ProcessObject == NULL ) + 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( ) ); + + // 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::ParametersQtDialog:: +_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::ParametersQtDialog:: +_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::ParametersQtDialog:: +_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::ParametersQtDialog:: +_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::ParametersQtDialog:: +_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::ParametersQtDialog:: +_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::ParametersQtDialog:: +_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/ParametersQtDialog.h b/lib/cpPlugins/ParametersQtDialog.h new file mode 100644 index 0000000..b82f401 --- /dev/null +++ b/lib/cpPlugins/ParametersQtDialog.h @@ -0,0 +1,68 @@ +#ifndef __CPPLUGINS__PARAMETERSQTDIALOG__H__ +#define __CPPLUGINS__PARAMETERSQTDIALOG__H__ + +#include + +#ifdef cpPlugins_QT4 + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + /** + */ + class cpPlugins_EXPORT ParametersQtDialog + : public QDialog + { + Q_OBJECT; + + public: + ParametersQtDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + virtual ~ParametersQtDialog( ); + + ProcessObject* getProcessObject( ) const; + bool setProcessObject( ProcessObject* obj ); + + virtual int exec( ); + + 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: + ProcessObject* m_ProcessObject; + bool m_WidgetsUpdated; + QLabel* m_Title; + QGridLayout* m_MainLayout; + QVBoxLayout* m_ToolsLayout; + QDialogButtonBox* m_Buttons; + }; + +} // ecapseman + +#endif // cpPlugins_QT4 + +#endif // __CPPLUGINS__PARAMETERSQTDIALOG__H__ + +// 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..52b4ac4 --- /dev/null +++ b/lib/cpPlugins/ProcessObject.cxx @@ -0,0 +1,294 @@ +#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:: +GetOutput( 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:: +GetOutput( 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 ); +} + +// ------------------------------------------------------------------------- +cpPlugins:: +DataObject* cpPlugins::ProcessObject:: +GetInputData( const std::string& id ) +{ + auto i = this->m_Inputs.find( id ); + if( i != this->m_Inputs.end( ) ) + return( dynamic_cast< DataObject* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins:: +DataObject* cpPlugins::ProcessObject:: +GetInputData( const std::string& id ) const +{ + auto i = this->m_Inputs.find( id ); + if( i != this->m_Inputs.end( ) ) + return( dynamic_cast< const DataObject* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +cpPlugins:: +DataObject* cpPlugins::ProcessObject:: +GetOutputData( const std::string& id ) +{ + auto i = this->m_Outputs.find( id ); + if( i != this->m_Outputs.end( ) ) + return( dynamic_cast< DataObject* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +const cpPlugins:: +DataObject* cpPlugins::ProcessObject:: +GetOutputData( const std::string& id ) const +{ + auto i = this->m_Outputs.find( id ); + if( i != this->m_Outputs.end( ) ) + return( dynamic_cast< const DataObject* >( i->second.GetPointer( ) ) ); + else + return( NULL ); +} + +// ------------------------------------------------------------------------- +bool cpPlugins::ProcessObject:: +SetInput( 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( ); +} + +// ------------------------------------------------------------------------- +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 ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::ProcessObject:: +Update( ) +{ + std::string r = ""; + + // Force upstream updates + auto i = this->m_Inputs.begin( ); + bool need_to_update = false; + for( ; i != this->m_Inputs.end( ) && r == ""; ++i ) + { + bool iv = i->second.IsValid( ); + bool ir = i->second.IsRequired( ); + if( !iv && ir ) + r = + "ProcessObject: Required input \"" + + i->first + "@" + this->GetClassName( ) + + "\" is not valid (=NULL)."; + if( iv && r == "" ) + { + Self* src = dynamic_cast< Self* >( i->second->GetSource( ) ); + if( src != NULL ) + { + need_to_update |= ( this->m_LastExecutionTime < src->GetMTime( ) ); + r = src->Update( ); + + } // fi + + } // fi + + } // rof + + // Current update + if( r == "" ) + { + if( this->m_LastExecutionTime < this->GetMTime( ) || need_to_update ) + { + r = this->_GenerateData( ); + this->m_LastExecutionTime = this->GetMTime( ); + + } // fi + + } // fi + + // Return error description, if any + return( r ); +} + +// ------------------------------------------------------------------------- +cpPlugins::ParametersQtDialog* cpPlugins::ProcessObject:: +CreateQtDialog( ) +{ +#ifdef cpPlugins_QT4 + ParametersQtDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new ParametersQtDialog( ); + dlg->setProcessObject( this ); + + } // fi + return( dlg ); +#else // cpPlugins_QT4 + return( NULL ); +#endif // cpPlugins_QT4 +} + +// ------------------------------------------------------------------------- +cpPlugins::ProcessObject:: +ProcessObject( ) + : Superclass( ), + m_LastExecutionTime( 0 ) +{ +} + +// ------------------------------------------------------------------------- +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 +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/ProcessObject.h b/lib/cpPlugins/ProcessObject.h new file mode 100644 index 0000000..3979ac5 --- /dev/null +++ b/lib/cpPlugins/ProcessObject.h @@ -0,0 +1,104 @@ +#ifndef __CPPLUGINS__PROCESSOBJECT__H__ +#define __CPPLUGINS__PROCESSOBJECT__H__ + +#include +#include +#include +#include +#include + +namespace cpPlugins +{ + // Forward declaration + /* TODO + class ParametersQtDialog; + */ + + /** + */ + 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 ); + + 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& GetOutput( const std::string& id ); + const OutputPort& GetOutput( const std::string& id ) const; + + DataObject* GetInputData( const std::string& id ); + const DataObject* GetInputData( const std::string& id ) const; + DataObject* GetOutputData( const std::string& id ); + const DataObject* GetOutputData( const std::string& id ) const; + + bool SetInput( const std::string& id, const OutputPort& port ); + + void DisconnectInputs( ); + void DisconnectOutputs( ); + void Disconnect( ); + + // Pipeline execution + virtual itk::ModifiedTimeType GetMTime( ) const; + virtual std::string Update( ); + + // Qt dialog creation + virtual ParametersQtDialog* CreateQtDialog( ); + + protected: + ProcessObject( ); + virtual ~ProcessObject( ); + + void _AddInput( const std::string& name, bool required = true ); + + template< class O > + inline void _AddOutput( const std::string& name ); + + template< class F > + inline F* _CreateITK( ); + template< class F > + inline F* _CreateVTK( ); + + virtual std::string _GenerateData( ) = 0; + + private: + // Purposely not implemented + ProcessObject( const Self& ); + Self& operator=( const Self& ); + + protected: + Parameters m_Parameters; + + typedef std::map< std::string, InputPort > _TInputs; + typedef std::map< std::string, OutputPort > _TOutputs; + _TInputs m_Inputs; + _TOutputs m_Outputs; + + itk::ModifiedTimeType m_LastExecutionTime; + }; + +} // 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..73e8743 --- /dev/null +++ b/lib/cpPlugins/ProcessObject.hxx @@ -0,0 +1,58 @@ +#ifndef __CPPLUGINS__PROCESSOBJECT__HXX__ +#define __CPPLUGINS__PROCESSOBJECT__HXX__ + +// ------------------------------------------------------------------------- +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/Workspace.cxx b/lib/cpPlugins/Workspace.cxx new file mode 100644 index 0000000..f6491ca --- /dev/null +++ b/lib/cpPlugins/Workspace.cxx @@ -0,0 +1,415 @@ +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPlugins::Workspace:: +Workspace( ) + : m_Interface( NULL ), + 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 ); +} + +// ------------------------------------------------------------------------- +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->Create( category, filter ); + if( f.IsNotNull( ) ) + { + BaseWidget* bw = dynamic_cast< BaseWidget* >( f.GetPointer( ) ); + if( bw != NULL ) + { + bw->SetSingleInteractor( this->m_SingleInteractor ); + bw->SetMPRViewer( this->m_MPRViewer ); + + } // fi + Object::Pointer o = f.GetPointer( ); + this->m_Graph->SetVertex( name, o ); + + } // 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 ) +{ +} + +// ------------------------------------------------------------------------- +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->SetInput( input_name, orig->GetOutput( 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->SetInput( 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->GetOutput( 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->GetOutput( i->second.second ) ); + + } // fi + return( null_port ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::Workspace:: +Execute( ) +{ + // Find sinks + std::set< std::string > sinks = this->m_Graph->GetSinks( ); + + // Update sinks + std::string err = ""; + for( auto sIt = sinks.begin( ); sIt != sinks.end( ); ++sIt ) + { + std::string lerr = this->Execute( *sIt ); + if( lerr != "" ) + err += lerr + std::string( "\n" ); + + } // rof + return( err ); +} + +// ------------------------------------------------------------------------- +std::string cpPlugins::Workspace:: +Execute( const std::string& name ) +{ + // Get filter + ProcessObject* f = this->GetFilter( name ); + if( f == NULL ) + return( + std::string( "cpPlugins::Workspace: Vertex \"" ) + + name + std::string( "\" is not a filter." ) + ); + + // Execute and return + return( f->Update( ) ); +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Workspace.h b/lib/cpPlugins/Workspace.h new file mode 100644 index 0000000..c450063 --- /dev/null +++ b/lib/cpPlugins/Workspace.h @@ -0,0 +1,152 @@ +#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 + { +#ifdef cpPlugins_QT4 + class SimpleMPRWidget; +#else // cpPlugins_QT4 + typedef char SimpleMPRWidget; +#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; + 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 ); + + // 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 + std::string Execute( ); + std::string Execute( const std::string& name ); + + protected: + // Plugins interface + Interface* m_Interface; + + // 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..c23852a --- /dev/null +++ b/lib/cpPlugins/WorkspaceIO.cxx @@ -0,0 +1,195 @@ +#include +#include + +// ------------------------------------------------------------------------- +std::string cpPlugins::Workspace:: +LoadWorkspace( const std::string& fname ) +{ + 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; + + // 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 ); + 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 ); + + // 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" ); + + // 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 ) + { + 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( ) ); + + auto params = filter->GetParameters( ); + params->ToXML( doc, e ); + root->LinkEndChild( e ); + } + else if( data != NULL ) + { + // TODO + } // fi + + } // rof + + // 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_ITKInstances/Base.cxx b/lib/cpPlugins_ITKInstances/Base.cxx new file mode 100644 index 0000000..0ecd951 --- /dev/null +++ b/lib/cpPlugins_ITKInstances/Base.cxx @@ -0,0 +1,6 @@ + +#include + +// ...aaand that's all folks! + +// eof - $RCSfile$ diff --git a/lib/cpPlugins_ITKInstances/Base.h b/lib/cpPlugins_ITKInstances/Base.h new file mode 100644 index 0000000..9c767d9 --- /dev/null +++ b/lib/cpPlugins_ITKInstances/Base.h @@ -0,0 +1,89 @@ +#ifndef __CPPLUGINS_ITKINSTANCES__BASE__H__ +#define __CPPLUGINS_ITKINSTANCES__BASE__H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * ========================================================================= + * Define scalar FixedArray's + * ========================================================================= + */ +#define cpPlugins_ITKInstances_FixedArrays( T, D ) \ + cpPlugins_ITKInstances_PREFIX itk::FixedArray< T, D >; \ + cpPlugins_ITKInstances_PREFIX itk::Vector< T, D >; \ + cpPlugins_ITKInstances_PREFIX itk::Point< T, D > + +cpPlugins_ITKInstances_FixedArrays( float, 1 ); +cpPlugins_ITKInstances_FixedArrays( float, 2 ); +cpPlugins_ITKInstances_FixedArrays( float, 3 ); +cpPlugins_ITKInstances_FixedArrays( float, 4 ); + +cpPlugins_ITKInstances_FixedArrays( double, 1 ); +cpPlugins_ITKInstances_FixedArrays( double, 2 ); +cpPlugins_ITKInstances_FixedArrays( double, 3 ); +cpPlugins_ITKInstances_FixedArrays( double, 4 ); + +/* + * ========================================================================= + * Define scalar Array's + * ========================================================================= + */ +#define cpPlugins_ITKInstances_Array( T ) \ + cpPlugins_ITKInstances_PREFIX itk::Array< T > + +cpPlugins_ITKInstances_Array( char ); +cpPlugins_ITKInstances_Array( short ); +cpPlugins_ITKInstances_Array( int ); +cpPlugins_ITKInstances_Array( long ); +cpPlugins_ITKInstances_Array( float ); +cpPlugins_ITKInstances_Array( double ); +cpPlugins_ITKInstances_Array( unsigned char ); +cpPlugins_ITKInstances_Array( unsigned short ); +cpPlugins_ITKInstances_Array( unsigned int ); +cpPlugins_ITKInstances_Array( unsigned long ); + +/* + * ========================================================================= + * Define scalar SimpleDataObjectDecorator's + * ========================================================================= + */ +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< bool >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< char >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< short >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< int >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< long >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< float >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< double >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< unsigned char >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< unsigned short >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< unsigned int >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< unsigned long >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::string >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< char > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< short > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< int > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< long > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< float > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< double > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< unsigned char > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< unsigned short > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< unsigned int > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< itk::Array< unsigned long > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::vector< itk::Index< 2 > > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::vector< itk::Index< 3 > > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::vector< itk::Point< float, 2 > > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::vector< itk::Point< double, 2 > > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::vector< itk::Point< float, 3 > > >; +cpPlugins_ITKInstances_PREFIX itk::SimpleDataObjectDecorator< std::vector< itk::Point< double, 3 > > >; + +#endif // __CPPLUGINS_ITKINSTANCES__BASE__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins_ITKInstances/CMakeLists.txt b/lib/cpPlugins_ITKInstances/CMakeLists.txt new file mode 100644 index 0000000..f246d90 --- /dev/null +++ b/lib/cpPlugins_ITKInstances/CMakeLists.txt @@ -0,0 +1,78 @@ +## ============================= +## = Set names and directories = +## ============================= + +SET(lib_NAME cpPlugins_ITKInstances) +SET(lib_DIR cpPlugins_ITKInstances) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_HEADERS_H "*.h") +FILE(GLOB lib_HEADERS_HPP "*.hpp") +FILE(GLOB lib_HEADERS_HXX "*.hxx") +FILE(GLOB lib_SOURCES_C "*.c") +FILE(GLOB lib_SOURCES_CPP "*.cpp") +FILE(GLOB lib_SOURCES_CXX "*.cxx") + +# =================================== +# = Integrate all source file names = +# =================================== + +SET( + lib_HEADERS + ${lib_HEADERS_H} + ${lib_HEADERS_HPP} + ${lib_HEADERS_HXX} + ) + +SET( + lib_SOURCES + ${lib_SOURCES_C} + ${lib_SOURCES_CPP} + ${lib_SOURCES_CXX} + ) + +SET( + target_LIBRARIES + ${ITK_LIBRARIES} + ${VTK_LIBRARIES} + ) + +## ===================== +## = Compilation rules = +## ===================== + +ADD_LIBRARY(${lib_NAME} SHARED ${lib_SOURCES}) +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 + ) +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_ITKInstances/Config.h b/lib/cpPlugins_ITKInstances/Config.h new file mode 100644 index 0000000..5e4b1b1 --- /dev/null +++ b/lib/cpPlugins_ITKInstances/Config.h @@ -0,0 +1,21 @@ +#ifndef __CPPLUGINS_ITKINSTANCES__CONFIG__H__ +#define __CPPLUGINS_ITKINSTANCES__CONFIG__H__ + +#include + +/* + * ========================================================================= + * Discover what we are doing: building or using + * ========================================================================= + */ +#ifdef cpPlugins_ITKInstances_EXPORTS +# undef ITK_MANUAL_INSTANTIATION +# define cpPlugins_ITKInstances_PREFIX template class cpPlugins_ITKInstances_EXPORT +#else // cpPlugins_ITKInstances_EXPORTS +# define ITK_MANUAL_INSTANTIATION +# define cpPlugins_ITKInstances_PREFIX extern template class +#endif // cpPlugins_ITKInstances_EXPORTS + +#endif // __CPPLUGINS_ITKINSTANCES__CONFIG__H__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins_ITKInstances/Image.cxx b/lib/cpPlugins_ITKInstances/Image.cxx new file mode 100644 index 0000000..4fcf5ea --- /dev/null +++ b/lib/cpPlugins_ITKInstances/Image.cxx @@ -0,0 +1,19 @@ + +#include + +// ------------------------------------------------------------------------- +#define cpPlugins_ITKInstances_ostream( D ) \ + template cpPlugins_ITKInstances_EXPORT std::ostream& operator<< < D > \ + ( std::ostream& o, const ImageRegion< D >& r ) + +namespace itk +{ + cpPlugins_ITKInstances_ostream( 1 ); + cpPlugins_ITKInstances_ostream( 2 ); + cpPlugins_ITKInstances_ostream( 3 ); + cpPlugins_ITKInstances_ostream( 4 ); +} + +// ...aaand that's all folks! + +// eof - $RCSfile$ diff --git a/lib/cpPlugins_ITKInstances/Image.h b/lib/cpPlugins_ITKInstances/Image.h new file mode 100644 index 0000000..3069e31 --- /dev/null +++ b/lib/cpPlugins_ITKInstances/Image.h @@ -0,0 +1,251 @@ +#ifndef __CPPLUGINS_ITKINSTANCES__IMAGE__H__ +#define __CPPLUGINS_ITKINSTANCES__IMAGE__H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * ========================================================================= + * Define scalar ImageBase's + * ========================================================================= + */ +#define cpPlugins_ITKInstances_ImageBase( D ) \ + cpPlugins_ITKInstances_PREFIX itk::ImageBase< D > + +cpPlugins_ITKInstances_ImageBase( 1 ); +cpPlugins_ITKInstances_ImageBase( 2 ); +cpPlugins_ITKInstances_ImageBase( 3 ); +cpPlugins_ITKInstances_ImageBase( 4 ); + +/* + * ========================================================================= + * Define pixel-based objects + * ========================================================================= + */ +#define cpPlugins_ITKInstances_ConvertPixelBuffer( T, U, V ) \ + cpPlugins_ITKInstances_PREFIX itk::ConvertPixelBuffer< T, U, itk::DefaultConvertPixelTraits< V > > + +#define cpPlugins_ITKInstances_ColorPixel( T ) \ + cpPlugins_ITKInstances_PREFIX itk::RGBPixel< T >; \ + cpPlugins_ITKInstances_PREFIX itk::RGBAPixel< T > + +#define cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( U ) \ + cpPlugins_ITKInstances_PREFIX itk::ImportImageContainer< unsigned long, U >; \ + cpPlugins_ITKInstances_ConvertPixelBuffer( char, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( short, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( int, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( long, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( float, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( double, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( unsigned char, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( unsigned short, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( unsigned int, U, U ); \ + cpPlugins_ITKInstances_ConvertPixelBuffer( unsigned long, U, U ) + +cpPlugins_ITKInstances_ColorPixel( char ); +cpPlugins_ITKInstances_ColorPixel( short ); +cpPlugins_ITKInstances_ColorPixel( int ); +cpPlugins_ITKInstances_ColorPixel( long ); +cpPlugins_ITKInstances_ColorPixel( float ); +cpPlugins_ITKInstances_ColorPixel( double ); +cpPlugins_ITKInstances_ColorPixel( unsigned char ); +cpPlugins_ITKInstances_ColorPixel( unsigned short ); +cpPlugins_ITKInstances_ColorPixel( unsigned int ); +cpPlugins_ITKInstances_ColorPixel( unsigned long ); + +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( char ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( short ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( int ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( long ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( float ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( double ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( unsigned char ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( unsigned short ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( unsigned int ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( unsigned long ); + +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< char > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< short > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< int > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< long > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< float > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< double > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< unsigned char > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< unsigned short > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< unsigned int > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBPixel< unsigned long > ); + +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< char > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< short > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< int > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< long > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< float > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< double > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< unsigned char > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< unsigned short > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< unsigned int > ); +cpPlugins_ITKInstances_ConvertPixelBuffer_AllTypes( itk::RGBAPixel< unsigned long > ); + +/* + * ========================================================================= + * Define scalar Image's + * ========================================================================= + */ +#define cpPlugins_ITKInstances_ScalarImage( P, D ) \ + cpPlugins_ITKInstances_PREFIX itk::Image< P, D >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageTransformer< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageSource< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageConstIteratorWithIndex< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageIteratorWithIndex< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageRegionConstIterator< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageRegionIterator< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageScanlineConstIterator< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageScanlineIterator< itk::Image< P, D > > + +#define cpPlugins_ITKInstances_ScalarImage_AllDims( P ) \ + cpPlugins_ITKInstances_ScalarImage( P, 1 ); \ + cpPlugins_ITKInstances_ScalarImage( P, 2 ); \ + cpPlugins_ITKInstances_ScalarImage( P, 3 ); \ + cpPlugins_ITKInstances_ScalarImage( P, 4 ) + +cpPlugins_ITKInstances_ScalarImage_AllDims( char ); +cpPlugins_ITKInstances_ScalarImage_AllDims( short ); +cpPlugins_ITKInstances_ScalarImage_AllDims( int ); +cpPlugins_ITKInstances_ScalarImage_AllDims( long ); +cpPlugins_ITKInstances_ScalarImage_AllDims( float ); +cpPlugins_ITKInstances_ScalarImage_AllDims( double ); +cpPlugins_ITKInstances_ScalarImage_AllDims( unsigned char ); +cpPlugins_ITKInstances_ScalarImage_AllDims( unsigned short ); +cpPlugins_ITKInstances_ScalarImage_AllDims( unsigned int ); +cpPlugins_ITKInstances_ScalarImage_AllDims( unsigned long ); + +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< char > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< short > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< int > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< long > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< float > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< double > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< unsigned char > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< unsigned short > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< unsigned int > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBPixel< unsigned long > ); + +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< char > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< short > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< int > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< long > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< float > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< double > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< unsigned char > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< unsigned short > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< unsigned int > ); +cpPlugins_ITKInstances_ScalarImage_AllDims( itk::RGBAPixel< unsigned long > ); + +/* + * ========================================================================= + * Define scalar ItkVtkGlue + * ========================================================================= + */ +#define cpPlugins_ITKInstances_ItkVtkGlueScalarImage( P, D ) \ + cpPlugins_ITKInstances_PREFIX itk::ImageToVTKImageFilter< itk::Image< P, D > > + +#define cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( P ) \ + cpPlugins_ITKInstances_ItkVtkGlueScalarImage( P, 2 ); \ + cpPlugins_ITKInstances_ItkVtkGlueScalarImage( P, 3 ) + +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( char ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( short ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( int ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( long ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( float ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( double ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( unsigned char ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( unsigned short ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( unsigned int ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( unsigned long ); + +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< char > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< short > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< int > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< long > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< float > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< double > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< unsigned char > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< unsigned short > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< unsigned int > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBPixel< unsigned long > ); + +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< char > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< short > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< int > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< long > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< float > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< double > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< unsigned char > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< unsigned short > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< unsigned int > ); +cpPlugins_ITKInstances_ItkVtkGlueScalarImage_AllDims( itk::RGBAPixel< unsigned long > ); + +/* + * ========================================================================= + * Define scalar shaped iterators + * ========================================================================= + */ +#define cpPlugins_ITKInstances_ScalarImage_ShapedIterators( P, D ) \ + cpPlugins_ITKInstances_PREFIX itk::ImageLinearConstIteratorWithIndex< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ImageLinearIteratorWithIndex< itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ConstantBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::PeriodicBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ZeroFluxNeumannBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > >; \ + cpPlugins_ITKInstances_PREFIX itk::ConstNeighborhoodIterator< itk::Image< P, D >, itk::ConstantBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::NeighborhoodIterator< itk::Image< P, D >, itk::ConstantBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::ConstNeighborhoodIterator< itk::Image< P, D >, itk::PeriodicBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::NeighborhoodIterator< itk::Image< P, D >, itk::PeriodicBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::ConstNeighborhoodIterator< itk::Image< P, D >, itk::ZeroFluxNeumannBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::NeighborhoodIterator< itk::Image< P, D >, itk::ZeroFluxNeumannBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::ConstShapedNeighborhoodIterator< itk::Image< P, D >, itk::ZeroFluxNeumannBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > >; \ + cpPlugins_ITKInstances_PREFIX itk::ShapedNeighborhoodIterator< itk::Image< P, D >, itk::ZeroFluxNeumannBoundaryCondition< itk::Image< P, D >, itk::Image< P, D > > > + +#define cpPlugins_ITKInstances_ScalarImage_ShapedIterators_AllTypes( D ) \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( char, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( short, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( int, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( long, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( float, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( double, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( unsigned char, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( unsigned short, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( unsigned int, D ); \ + cpPlugins_ITKInstances_ScalarImage_ShapedIterators( unsigned long, D ) + +cpPlugins_ITKInstances_ScalarImage_ShapedIterators_AllTypes( 1 ); +cpPlugins_ITKInstances_ScalarImage_ShapedIterators_AllTypes( 2 ); +cpPlugins_ITKInstances_ScalarImage_ShapedIterators_AllTypes( 3 ); +cpPlugins_ITKInstances_ScalarImage_ShapedIterators_AllTypes( 4 ); + +#endif // __CPPLUGINS_ITKINSTANCES__IMAGE__H__ + +// eof - $RCSfile$ diff --git a/lib/third_party/CMakeLists.txt b/lib/third_party/CMakeLists.txt new file mode 100644 index 0000000..bab952a --- /dev/null +++ b/lib/third_party/CMakeLists.txt @@ -0,0 +1,5 @@ +SUBDIRS( + tinyxml + ) + +## eof - $RCSfile$ diff --git a/lib/third_party/tinyxml/CMakeLists.txt b/lib/third_party/tinyxml/CMakeLists.txt new file mode 100644 index 0000000..a66769f --- /dev/null +++ b/lib/third_party/tinyxml/CMakeLists.txt @@ -0,0 +1,25 @@ +SET(lib_NAME cpPlugins_tinyxml2) + +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}" + ) + +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/third_party/tinyxml/readme.md b/lib/third_party/tinyxml/readme.md new file mode 100644 index 0000000..30424c3 --- /dev/null +++ b/lib/third_party/tinyxml/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/third_party/tinyxml/tinyxml2.cpp b/lib/third_party/tinyxml/tinyxml2.cpp new file mode 100644 index 0000000..df49d0d --- /dev/null +++ b/lib/third_party/tinyxml/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/third_party/tinyxml/tinyxml2.h b/lib/third_party/tinyxml/tinyxml2.h new file mode 100644 index 0000000..fb7464a --- /dev/null +++ b/lib/third_party/tinyxml/tinyxml2.h @@ -0,0 +1,2102 @@ +/* +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; + +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..0d25544 --- /dev/null +++ b/plugins/CMakeLists.txt @@ -0,0 +1,7 @@ +SUBDIRS( + cpPluginsIO + cpPluginsImageFilters + cpPluginsWidgets + ) + +## eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/CMakeLists.txt b/plugins/cpPluginsIO/CMakeLists.txt new file mode 100644 index 0000000..1a8c84d --- /dev/null +++ b/plugins/cpPluginsIO/CMakeLists.txt @@ -0,0 +1,73 @@ +SET(lib_NAME cpPluginsIO) +SET(lib_DIR cpPluginsIO) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_HEADERS_H "*.h") +FILE(GLOB lib_HEADERS_HPP "*.hpp") +FILE(GLOB lib_HEADERS_HXX "*.hxx") +FILE(GLOB lib_SOURCES_C "*.c") +FILE(GLOB lib_SOURCES_CPP "*.cpp") +FILE(GLOB lib_SOURCES_CXX "*.cxx") + +# =================================== +# = Integrate all source file names = +# =================================== + +SET( + lib_HEADERS + ${lib_HEADERS_H} + ${lib_HEADERS_HPP} + ${lib_HEADERS_HXX} + ) + +SET( + lib_SOURCES + ${lib_SOURCES_C} + ${lib_SOURCES_CPP} + ${lib_SOURCES_CXX} + ) + +SET( + target_LIBRARIES + cpPlugins + ) + +## ===================== +## = Compilation rules = +## ===================== + +ADD_CUSTOM_COMMAND( + OUTPUT ${lib_NAME}_Host.cxx + DEPENDS cpPlugins_HostCreator ${LIB_HEADERS_H} + COMMAND cpPlugins_HostCreator ${lib_NAME}_Host.cxx ${lib_HEADERS_H} + ) +ADD_LIBRARY(${lib_NAME} SHARED ${lib_NAME}_Host.cxx ${lib_SOURCES}) +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}/plugins/${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 + ) + +## eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/DataReproducer.cxx b/plugins/cpPluginsIO/DataReproducer.cxx new file mode 100644 index 0000000..27f9ea5 --- /dev/null +++ b/plugins/cpPluginsIO/DataReproducer.cxx @@ -0,0 +1,32 @@ +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsIO::DataReproducer:: +DataReproducer( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::DataObject >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginsIO::DataReproducer:: +~DataReproducer( ) +{ +} + +// ------------------------------------------------------------------------- +std::string 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( ) ) + return( "IO::DataReproducer: No input/output ports." ); + o->second->SetITK( i->second->GetITK< itk::LightObject >( ) ); + o->second->SetVTK( i->second->GetVTK< vtkObjectBase >( ) ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/DataReproducer.h b/plugins/cpPluginsIO/DataReproducer.h new file mode 100644 index 0000000..ba43876 --- /dev/null +++ b/plugins/cpPluginsIO/DataReproducer.h @@ -0,0 +1,41 @@ +#ifndef __CPPLUGINSIO__DATAREPRODUCER__H__ +#define __CPPLUGINSIO__DATAREPRODUCER__H__ + +#include +#include + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT DataReproducer + : public cpPlugins::ProcessObject + { + 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 std::string _GenerateData( ); + + private: + // Purposely not implemented + DataReproducer( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIO__DATAREPRODUCER__H__ + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/DicomSeriesReader.cxx b/plugins/cpPluginsIO/DicomSeriesReader.cxx new file mode 100644 index 0000000..e53e249 --- /dev/null +++ b/plugins/cpPluginsIO/DicomSeriesReader.cxx @@ -0,0 +1,233 @@ +#include + +#ifdef cpPlugins_QT4 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/** + */ +class cpPluginsIO_DicomSeriesReader_ParametersQtDialog + : public cpPlugins::ParametersQtDialog +{ +public: + cpPluginsIO_DicomSeriesReader_ParametersQtDialog( + QWidget* parent = 0, Qt::WindowFlags f = 0 + ) + : cpPlugins::ParametersQtDialog( parent, f ) + { + } + virtual ~cpPluginsIO_DicomSeriesReader_ParametersQtDialog( ) + { + } + +protected: + virtual void _dlg_OpenMultipleFiles( ) + { + // DICOM series analyzer + itk::GDCMSeriesFileNames::GlobalWarningDisplayOff( ); + itk::GDCMSeriesFileNames::Pointer series = + itk::GDCMSeriesFileNames::New( ); + + // Show dialog and check if it was accepted + QWidget* parent = dynamic_cast< QWidget* >( this->parent( ) ); + QFileDialog dialog( parent ); + dialog.setFileMode( QFileDialog::DirectoryOnly ); + dialog.setDirectory( QFileDialog::tr( "." ) ); + if( !dialog.exec( ) ) + return; + + // Prepare dialog + QApplication::setOverrideCursor( Qt::WaitCursor ); + if( parent != NULL ) + parent->setEnabled( false ); + + QDialog* tree_dialog = new QDialog( parent ); + QTreeWidget* tree_widget = new QTreeWidget( tree_dialog ); + QList< QTreeWidgetItem* > tree_items; + std::map< + std::string, + std::map< std::string, std::vector< std::string > > + > found_files; + + std::string main_dir_name = + dialog.selectedFiles( ).begin( )->toStdString( ); + std::queue< std::string > q; + q.push( main_dir_name ); + while( !( q.empty( ) ) ) + { + std::string dir_name = q.front( ); + q.pop( ); + + // Get DICOM information + series->SetUseSeriesDetails( true ); + series->AddSeriesRestriction( "0008|0021" ); + series->SetDirectory( dir_name ); + const std::vector< std::string >& seriesUID = series->GetSeriesUIDs( ); + if( seriesUID.size( ) > 0 ) + { + QTreeWidgetItem* new_item = new QTreeWidgetItem( + ( QTreeWidgetItem* )( NULL ), + QStringList( dir_name.c_str( ) ) + ); + QTreeWidgetItem* new_leaf = NULL; + std::vector< std::string >::const_iterator sIt = seriesUID.begin( ); + for( ; sIt != seriesUID.end( ); ++sIt ) + { + std::vector< std::string > filenames = series->GetFileNames( *sIt ); + if( filenames.size( ) > 0 ) + { + std::stringstream ss; + ss << "(" << filenames.size( ) << "): " << *sIt; + new_leaf = + new QTreeWidgetItem( + new_item, QStringList( ss.str( ).c_str( ) ) + ); + new_item->addChild( new_leaf ); + found_files[ dir_name ][ *sIt ] = filenames; + + } // fi + + } // rof + + if( new_leaf != NULL ) + tree_items.append( new_item ); + else + delete new_item; + + } // fi + + // 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 + + // Show second dialog + if( tree_items.size( ) == 0 ) + { + delete tree_widget; + delete tree_dialog; + return; + + } // fi + + QLabel* title = new QLabel( tree_dialog ); + title->setText( "Choose a DICOM series" ); + QGridLayout* mainLayout = new QGridLayout( tree_dialog ); + QVBoxLayout* toolsLayout = new QVBoxLayout( ); + toolsLayout->addWidget( title ); + mainLayout->addLayout( toolsLayout, 0, 0, 1, 1 ); + + tree_widget->insertTopLevelItems( 0, tree_items ); + toolsLayout->addWidget( tree_widget ); + + QDialogButtonBox* bb = new QDialogButtonBox( + QDialogButtonBox::Ok | QDialogButtonBox::Cancel + ); + tree_dialog->connect( + bb, SIGNAL( accepted( ) ), tree_dialog, SLOT( accept( ) ) + ); + tree_dialog->connect( + bb, SIGNAL( rejected( ) ), tree_dialog, SLOT( reject( ) ) + ); + toolsLayout->addWidget( bb ); + + QApplication::restoreOverrideCursor( ); + if( parent != NULL ) + parent->setEnabled( true ); + + if( tree_dialog->exec( ) == 0 ) + return; + + QTreeWidgetItem* item = tree_widget->currentItem( ); + if( item != NULL ) + { + QTreeWidgetItem* item_parent = item->parent( ); + if( item_parent != NULL ) + { + QApplication::setOverrideCursor( Qt::WaitCursor ); + if( parent != NULL ) + parent->setEnabled( false ); + + auto parameters = this->m_ProcessObject->GetParameters( ); + std::string serie_dir = item_parent->text( 0 ).toStdString( ); + std::string serie_id = item->text( 0 ).toStdString( ); + serie_id = serie_id.substr( serie_id.find_first_of( " " ) + 1 ); + parameters->ClearOpenFileNameList( "FileNames" ); + const std::vector< std::string >& names = + found_files[ serie_dir ][ serie_id ]; + for( unsigned int f = 0; f < names.size( ); ++f ) + parameters->AddToOpenFileNameList( "FileNames", names[ f ] ); + this->updateView( ); + + QApplication::restoreOverrideCursor( ); + if( parent != NULL ) + parent->setEnabled( true ); + + } // fi + + } // fi + itk::GDCMSeriesFileNames::GlobalWarningDisplayOn( ); + } +}; + +#endif // cpPlugins_QT4 + +// ------------------------------------------------------------------------- +cpPlugins::ParametersQtDialog* cpPluginsIO::DicomSeriesReader:: +CreateQtDialog( ) +{ +#ifdef cpPlugins_QT4 + cpPluginsIO_DicomSeriesReader_ParametersQtDialog* dlg = NULL; + if( QApplication::instance( ) != NULL ) + { + dlg = new cpPluginsIO_DicomSeriesReader_ParametersQtDialog( ); + 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/cpPluginsIO/DicomSeriesReader.h b/plugins/cpPluginsIO/DicomSeriesReader.h new file mode 100644 index 0000000..1533cd7 --- /dev/null +++ b/plugins/cpPluginsIO/DicomSeriesReader.h @@ -0,0 +1,42 @@ +#ifndef __CPPLUGINSIO__DICOMSERIESREADER__H__ +#define __CPPLUGINSIO__DICOMSERIESREADER__H__ + +#include + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT DicomSeriesReader + : public ImageReader + { + 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 cpPlugins::ParametersQtDialog* CreateQtDialog( ) 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/cpPluginsIO/ImageReader.cxx b/plugins/cpPluginsIO/ImageReader.cxx new file mode 100644 index 0000000..c515c9e --- /dev/null +++ b/plugins/cpPluginsIO/ImageReader.cxx @@ -0,0 +1,220 @@ +#include +#include + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +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( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPluginsIO::ImageReader:: +_GenerateData( ) +{ + // Get filenames + auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" ); + std::string r = ""; + 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: r = this->_GD0< 1 >( io ); break; + case 2: r = this->_GD0< 2 >( io ); break; + case 3: r = this->_GD0< 3 >( io ); break; + case 4: r = this->_GD0< 4 >( io ); break; + default: + r = "IO::ImageReader: Image dimension not supported."; + break; + } // hctiws + + } // fi + } + else + r = + "IO::ImageReader: Could not CreateImageIO for \"" + + fnames[ 0 ] + + "\""; + } + else + r = "IO::ImageReader: No image(s) given"; + return( r ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +std::string cpPluginsIO::ImageReader:: +_GD0( itk::ImageIOBase* io ) +{ + itk::ImageIOBase::IOComponentType ct = io->GetComponentType( ); + itk::ImageIOBase::IOPixelType pt = io->GetPixelType( ); + + std::string r = ""; + if( pt == itk::ImageIOBase::SCALAR ) + { + switch( ct ) + { + case itk::ImageIOBase::CHAR : r = this->_GD1< char, D >( io ); break; + case itk::ImageIOBase::SHORT : r = this->_GD1< short, D >( io ); break; + case itk::ImageIOBase::INT : r = this->_GD1< int, D >( io ); break; + case itk::ImageIOBase::LONG : r = this->_GD1< long, D >( io ); break; + case itk::ImageIOBase::FLOAT : r = this->_GD1< float, D >( io ); break; + case itk::ImageIOBase::DOUBLE : r = this->_GD1< double, D >( io ); break; + case itk::ImageIOBase::UCHAR : r = this->_GD1< unsigned char, D >( io ); break; + case itk::ImageIOBase::USHORT : r = this->_GD1< unsigned short, D >( io ); break; + case itk::ImageIOBase::UINT : r = this->_GD1< unsigned int, D >( io ); break; + case itk::ImageIOBase::ULONG : r = this->_GD1< unsigned long, D >( io ); break; + default: + r = "IO::ImageReader: Scalar pixel type not supported."; + break; + } // hctiws + } + else if( pt == itk::ImageIOBase::RGB ) + { + switch( ct ) + { + case itk::ImageIOBase::CHAR : r = this->_GD1< itk::RGBPixel< char >, D >( io ); break; + case itk::ImageIOBase::SHORT : r = this->_GD1< itk::RGBPixel< short >, D >( io ); break; + case itk::ImageIOBase::INT : r = this->_GD1< itk::RGBPixel< int >, D >( io ); break; + case itk::ImageIOBase::LONG : r = this->_GD1< itk::RGBPixel< long >, D >( io ); break; + case itk::ImageIOBase::FLOAT : r = this->_GD1< itk::RGBPixel< float >, D >( io ); break; + case itk::ImageIOBase::DOUBLE : r = this->_GD1< itk::RGBPixel< double >, D >( io ); break; + case itk::ImageIOBase::UCHAR : r = this->_GD1< itk::RGBPixel< unsigned char >, D >( io ); break; + case itk::ImageIOBase::USHORT : r = this->_GD1< itk::RGBPixel< unsigned short >, D >( io ); break; + case itk::ImageIOBase::UINT : r = this->_GD1< itk::RGBPixel< unsigned int >, D >( io ); break; + case itk::ImageIOBase::ULONG : r = this->_GD1< itk::RGBPixel< unsigned long >, D >( io ); break; + default: + r = "IO::ImageReader: RGB pixel type not supported."; + break; + } // hctiws + } + else if( pt == itk::ImageIOBase::RGBA ) + { + switch( ct ) + { + case itk::ImageIOBase::CHAR : r = this->_GD1< itk::RGBAPixel< char >, D >( io ); break; + case itk::ImageIOBase::SHORT : r = this->_GD1< itk::RGBAPixel< short >, D >( io ); break; + case itk::ImageIOBase::INT : r = this->_GD1< itk::RGBAPixel< int >, D >( io ); break; + case itk::ImageIOBase::LONG : r = this->_GD1< itk::RGBAPixel< long >, D >( io ); break; + case itk::ImageIOBase::FLOAT : r = this->_GD1< itk::RGBAPixel< float >, D >( io ); break; + case itk::ImageIOBase::DOUBLE : r = this->_GD1< itk::RGBAPixel< double >, D >( io ); break; + case itk::ImageIOBase::UCHAR : r = this->_GD1< itk::RGBAPixel< unsigned char >, D >( io ); break; + case itk::ImageIOBase::USHORT : r = this->_GD1< itk::RGBAPixel< unsigned short >, D >( io ); break; + case itk::ImageIOBase::UINT : r = this->_GD1< itk::RGBAPixel< unsigned int >, D >( io ); break; + case itk::ImageIOBase::ULONG : r = this->_GD1< itk::RGBAPixel< unsigned long >, D >( io ); break; + default: + r = "IO::ImageReader: RGBA pixel type not supported."; + break; + } // hctiws + } + /* TODO + else if( pt == itk::ImageIOBase::VECTOR ) + { + } + else if( pt == itk::ImageIOBase::POINT ) + { + } + else if( pt == itk::ImageIOBase::COVARIANTVECTOR ) + { + } + else if( pt == itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR ) + { + } + else if( pt == itk::ImageIOBase::DIFFUSIONTENSOR3D ) + { + } + else if( pt == itk::ImageIOBase::COMPLEX ) + { + } + else if( pt == itk::ImageIOBase::OFFSET ) + { + } + else if( pt == itk::ImageIOBase::FIXEDARRAY ) + { + } + else if( pt == itk::ImageIOBase::MATRIX ) + { + } + */ + else + r = "IO::ImageReader: Image pixel type not yet supported."; + return( r ); +} + +// ------------------------------------------------------------------------- +template< class P, unsigned int D > +std::string cpPluginsIO::ImageReader:: +_GD1( itk::ImageIOBase* io ) +{ + typedef itk::Image< P, D > _I; + + // Get filenames + std::string r = ""; + auto fnames = this->m_Parameters.GetOpenFileNameList( "FileNames" ); + if( fnames.size( ) == 1 ) + { + auto f = this->_CreateITK< itk::ImageFileReader< _I > >( ); + f->SetFileName( fnames[ 0 ] ); + f->SetImageIO( io ); + try + { + f->Update( ); + this->GetOutput( "Output" )->SetITK( f->GetOutput( ) ); + } + catch( itk::ExceptionObject& err ) + { + r = "IO::ImageReader: " + std::string( err.GetDescription( ) ); + } + } + else // if( fnames.size( ) > 1 ) + { + auto f = this->_CreateITK< itk::ImageSeriesReader< _I > >( ); + 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 ) + { + r = "IO::ImageReader: " + std::string( err.GetDescription( ) ); + } + + } // fi + return( r ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/ImageReader.h b/plugins/cpPluginsIO/ImageReader.h new file mode 100644 index 0000000..a0b5c19 --- /dev/null +++ b/plugins/cpPluginsIO/ImageReader.h @@ -0,0 +1,52 @@ +#ifndef __CPPLUGINSIO__IMAGEREADER__H__ +#define __CPPLUGINSIO__IMAGEREADER__H__ + +#include +#include + +namespace itk +{ + class ImageIOBase; +} + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT ImageReader + : public cpPlugins::ProcessObject + { + 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 ); + + protected: + ImageReader( ); + virtual ~ImageReader( ); + + virtual std::string _GenerateData( ) override; + + template< unsigned int D > + inline std::string _GD0( itk::ImageIOBase* io ); + + template< class P, unsigned int D > + inline std::string _GD1( itk::ImageIOBase* io ); + + private: + // Purposely not implemented + ImageReader( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIO__IMAGEREADER__H__ + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/ImageWriter.cxx b/plugins/cpPluginsIO/ImageWriter.cxx new file mode 100644 index 0000000..4418c66 --- /dev/null +++ b/plugins/cpPluginsIO/ImageWriter.cxx @@ -0,0 +1,75 @@ +#include +#include + +#include +#include +#include + +// ------------------------------------------------------------------------- +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( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPluginsIO::ImageWriter:: +_GenerateData( ) +{ + auto input = this->GetInputData( "Input" ); + try + { + std::string r = cpPlugin_Image_Demangle_Dim( _GD0, input, 3 ); + if( r != "" ) r = cpPlugin_Image_Demangle_Dim( _GD0, input, 2 ); + if( r != "" ) r = cpPlugin_Image_Demangle_Dim( _GD0, input, 4 ); + if( r != "" ) r = cpPlugin_Image_Demangle_Dim( _GD0, input, 1 ); + return( r ); + } + catch( itk::ExceptionObject& err ) + { + return( "IO::ImageWriter: " + std::string( err.GetDescription( ) ) ); + } +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsIO::ImageWriter:: +_GD0( I* image ) +{ + static const unsigned int D = I::ImageDimension; + if( image == NULL ) + return( "IO::ImageWriter: Invalid image dimension." ); + + std::string cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD1, image, D ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllColor( r, _GD1, image, D ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsIO::ImageWriter:: +_GD1( I* image ) +{ + if( image == NULL ) + return( "IO::ImageWriter: Invalid pixel type." ); + auto f = this->_CreateITK< itk::ImageFileWriter< I > >( ); + f->SetFileName( this->m_Parameters.GetOpenFileName( "FileName" ) ); + f->SetInput( image ); + f->Update( ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsIO/ImageWriter.h b/plugins/cpPluginsIO/ImageWriter.h new file mode 100644 index 0000000..a6c9b79 --- /dev/null +++ b/plugins/cpPluginsIO/ImageWriter.h @@ -0,0 +1,47 @@ +#ifndef __CPPLUGINSIO__IMAGEWRITER__H__ +#define __CPPLUGINSIO__IMAGEWRITER__H__ + +#include +#include + +namespace cpPluginsIO +{ + /** + */ + class cpPluginsIO_EXPORT ImageWriter + : public cpPlugins::ProcessObject + { + 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 ); + + protected: + ImageWriter( ); + virtual ~ImageWriter( ); + + virtual std::string _GenerateData( ) override; + + template< class I > + inline std::string _GD0( I* image ); + + template< class I > + inline std::string _GD1( I* image ); + + private: + // Purposely not implemented + ImageWriter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIO__IMAGEWRITER__H__ + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.cxx b/plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.cxx new file mode 100644 index 0000000..5915829 --- /dev/null +++ b/plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.cxx @@ -0,0 +1,93 @@ +#include +#include + +#include +#include +#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.SetUint( "InsideValue", 1 ); + this->m_Parameters.SetUint( "OutsideValue", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::BinaryThresholdImageFilter:: +~BinaryThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPluginsImageFilters::BinaryThresholdImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData( "Input" )->GetITK< itk::DataObject >( ); + std::string cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 1 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 2 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 3 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 4 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsImageFilters::BinaryThresholdImageFilter:: +_GD0( I* image ) +{ + if( image != NULL ) + return( + this->_GD1< I, itk::Image< unsigned char, I::ImageDimension > >( + image + ) + ); + else + return( + "ImageFilters::BinaryThresholdImageFilter: No valid input image." + ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +std::string cpPluginsImageFilters::BinaryThresholdImageFilter:: +_GD1( I* image ) +{ + typedef itk::BinaryThresholdImageFilter< I, O > _F; + typedef typename I::PixelType _IP; + typedef typename O::PixelType _OP; + + // Get parameters + _IP lower_val = _IP( this->m_Parameters.GetReal( "LowerThresholdValue" ) ); + _IP upper_val = _IP( this->m_Parameters.GetReal( "UpperThresholdValue" ) ); + _OP in_val = _OP( this->m_Parameters.GetUint( "InsideValue" ) ); + _OP out_val = _OP( this->m_Parameters.GetUint( "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->GetOutputData( "Output" )->SetITK( filter->GetOutput( ) ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.h b/plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.h new file mode 100644 index 0000000..1d80104 --- /dev/null +++ b/plugins/cpPluginsImageFilters/BinaryThresholdImageFilter.h @@ -0,0 +1,47 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__BINARYTHRESHOLDIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__BINARYTHRESHOLDIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT BinaryThresholdImageFilter + : public cpPlugins::ProcessObject + { + 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 std::string _GenerateData( ); + + template< class I > + inline std::string _GD0( I* image ); + + template< class I, class O > + inline std::string _GD1( I* image ); + + private: + // Purposely not implemented + BinaryThresholdImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__BINARYTHRESHOLDIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/CMakeLists.txt b/plugins/cpPluginsImageFilters/CMakeLists.txt new file mode 100644 index 0000000..94af7c5 --- /dev/null +++ b/plugins/cpPluginsImageFilters/CMakeLists.txt @@ -0,0 +1,74 @@ +SET(lib_NAME cpPluginsImageFilters) +SET(lib_DIR cpPluginsImageFilters) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_HEADERS_H "*.h") +FILE(GLOB lib_HEADERS_HPP "*.hpp") +FILE(GLOB lib_HEADERS_HXX "*.hxx") +FILE(GLOB lib_SOURCES_C "*.c") +FILE(GLOB lib_SOURCES_CPP "*.cpp") +FILE(GLOB lib_SOURCES_CXX "*.cxx") + +# =================================== +# = Integrate all source file names = +# =================================== + +SET( + lib_HEADERS + ${lib_HEADERS_H} + ${lib_HEADERS_HPP} + ${lib_HEADERS_HXX} + ) + +SET( + lib_SOURCES + ${lib_SOURCES_C} + ${lib_SOURCES_CPP} + ${lib_SOURCES_CXX} + ) + +SET( + target_LIBRARIES + cpExtensions + cpPlugins + ) + +## ===================== +## = Compilation rules = +## ===================== + +ADD_CUSTOM_COMMAND( + OUTPUT ${lib_NAME}_Host.cxx + DEPENDS cpPlugins_HostCreator ${LIB_HEADERS_H} + COMMAND cpPlugins_HostCreator ${lib_NAME}_Host.cxx ${lib_HEADERS_H} + ) +ADD_LIBRARY(${lib_NAME} SHARED ${lib_NAME}_Host.cxx ${lib_SOURCES}) +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}/plugins/${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 + ) + +## eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.cxx b/plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.cxx new file mode 100644 index 0000000..c08eb20 --- /dev/null +++ b/plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.cxx @@ -0,0 +1,88 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::OtsuThresholdImageFilter:: +OtsuThresholdImageFilter( ) + : Superclass( ) +{ + this->_AddInput( "Input" ); + this->_AddOutput< cpPlugins::Image >( "Output" ); + + this->m_Parameters.ConfigureAsUint( "NumberOfHistogramBins" ); + this->m_Parameters.ConfigureAsUint( "InsideValue" ); + this->m_Parameters.ConfigureAsUint( "OutsideValue" ); + + this->m_Parameters.SetUint( "NumberOfHistogramBins", 100 ); + this->m_Parameters.SetUint( "InsideValue", 255 ); + this->m_Parameters.SetUint( "OutsideValue", 0 ); +} + +// ------------------------------------------------------------------------- +cpPluginsImageFilters::OtsuThresholdImageFilter:: +~OtsuThresholdImageFilter( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPluginsImageFilters::OtsuThresholdImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData( "Input" )->GetITK< itk::DataObject >( ); + std::string cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 1 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 2 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 3 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 4 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsImageFilters::OtsuThresholdImageFilter:: +_GD0( I* image ) +{ + if( image != NULL ) + return( + this->_GD1< I, itk::Image< unsigned char, I::ImageDimension > >( image ) + ); + else + return( "ImageFilters::OtsuThresholdImageFilter: No valid input image." ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +std::string cpPluginsImageFilters::OtsuThresholdImageFilter:: +_GD1( I* image ) +{ + typedef itk::OtsuThresholdImageFilter< I, O > _F; + typedef typename O::PixelType _OP; + + // Get parameters + unsigned int bins = this->m_Parameters.GetUint( "NumberOfHistogramBins" ); + _OP in_val = _OP( this->m_Parameters.GetUint( "InsideValue" ) ); + _OP out_val = _OP( this->m_Parameters.GetUint( "OutsideValue" ) ); + + // Configure filter + _F* filter = this->_CreateITK< _F >( ); + filter->SetInput( dynamic_cast< I* >( image ) ); + filter->SetNumberOfHistogramBins( bins ); + filter->SetInsideValue( out_val ); // WARNING: these are inverted + filter->SetOutsideValue( in_val ); + filter->Update( ); + + // Connect output + this->GetOutputData( "Output" )->SetITK( filter->GetOutput( ) ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.h b/plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.h new file mode 100644 index 0000000..6c20f50 --- /dev/null +++ b/plugins/cpPluginsImageFilters/OtsuThresholdImageFilter.h @@ -0,0 +1,47 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__OTSUTHRESHOLDIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__OTSUTHRESHOLDIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT OtsuThresholdImageFilter + : public cpPlugins::ProcessObject + { + public: + typedef OtsuThresholdImageFilter Self; + typedef cpPlugins::ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkNewMacro( Self ); + itkTypeMacro( OtsuThresholdImageFilter, cpPlugins::ProcessObject ); + cpPlugins_Id_Macro( OtsuThresholdImageFilter, ImageFilters ); + + protected: + OtsuThresholdImageFilter( ); + virtual ~OtsuThresholdImageFilter( ); + + virtual std::string _GenerateData( ); + + template< class I > + inline std::string _GD0( I* image ); + + template< class I, class O > + inline std::string _GD1( I* image ); + + private: + // Purposely not implemented + OtsuThresholdImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__OTSUTHRESHOLDIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.cxx b/plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.cxx new file mode 100644 index 0000000..fcb03cd --- /dev/null +++ b/plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.cxx @@ -0,0 +1,106 @@ +#include +#include + +#include +#include +#include +#include +#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( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +_GenerateData( ) +{ + auto image = this->GetInputData( "Input" )->GetITK< itk::DataObject >( ); + std::string cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 2 ); + if( r != "" ) cpPlugin_Image_Demangle_Pixel_AllScalars( r, _GD0, image, 3 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +_GD0( I* image ) +{ + if( image != NULL ) + { + std::string out_res = + this->m_Parameters.GetSelectedChoice( "OutputResolution" ); + if( out_res == "float" ) + return( + this->_GD1< I, itk::Image< float, I::ImageDimension > >( image ) + ); + else if( out_res == "double" ) + return( + this->_GD1< I, itk::Image< double, I::ImageDimension > >( image ) + ); + else + return( "ImageFilters::SignedMaurerDistanceMapImageFilter: Output resolution not supported." ); + } + else + return( + "ImageFilters::SignedMaurerDistanceMapImageFilter: No valid input image." + ); +} + +// ------------------------------------------------------------------------- +template< class I, class O > +std::string cpPluginsImageFilters::SignedMaurerDistanceMapImageFilter:: +_GD1( I* image ) +{ + typedef itk::SignedMaurerDistanceMapImageFilter< I, O > _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 I::PixelType )( back_value ) ); + filter->SetInsideIsPositive( pos_inside ); + filter->SetSquaredDistance( sqr_dist ); + filter->SetUseImageSpacing( use_spac ); + filter->Update( ); + + // Connect output + this->GetOutputData( "Output" )->SetITK( filter->GetOutput( ) ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.h b/plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.h new file mode 100644 index 0000000..745193d --- /dev/null +++ b/plugins/cpPluginsImageFilters/SignedMaurerDistanceMapImageFilter.h @@ -0,0 +1,52 @@ +#ifndef __CPPLUGINSIMAGEFILTERS__SIGNEDMAURERDISTANCEMAPIMAGEFILTER__H__ +#define __CPPLUGINSIMAGEFILTERS__SIGNEDMAURERDISTANCEMAPIMAGEFILTER__H__ + +#include +#include + +namespace cpPluginsImageFilters +{ + /** + */ + class cpPluginsImageFilters_EXPORT SignedMaurerDistanceMapImageFilter + : public cpPlugins::ProcessObject + { + 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 std::string _GenerateData( ); + + template< class I > + inline std::string _GD0( I* image ); + + template< class I, class O > + inline std::string _GD1( I* image ); + + private: + // Purposely not implemented + SignedMaurerDistanceMapImageFilter( const Self& ); + Self& operator=( const Self& ); + }; + +} // ecapseman + +#endif // __CPPLUGINSIMAGEFILTERS__SIGNEDMAURERDISTANCEMAPIMAGEFILTER__H__ + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsWidgets/CMakeLists.txt b/plugins/cpPluginsWidgets/CMakeLists.txt new file mode 100644 index 0000000..a01eca9 --- /dev/null +++ b/plugins/cpPluginsWidgets/CMakeLists.txt @@ -0,0 +1,74 @@ +SET(lib_NAME cpPluginsWidgets) +SET(lib_DIR cpPluginsWidgets) + +## =============== +## = Source code = +## =============== + +FILE(GLOB lib_HEADERS_H "*.h") +FILE(GLOB lib_HEADERS_HPP "*.hpp") +FILE(GLOB lib_HEADERS_HXX "*.hxx") +FILE(GLOB lib_SOURCES_C "*.c") +FILE(GLOB lib_SOURCES_CPP "*.cpp") +FILE(GLOB lib_SOURCES_CXX "*.cxx") + +# =================================== +# = Integrate all source file names = +# =================================== + +SET( + lib_HEADERS + ${lib_HEADERS_H} + ${lib_HEADERS_HPP} + ${lib_HEADERS_HXX} + ) + +SET( + lib_SOURCES + ${lib_SOURCES_C} + ${lib_SOURCES_CPP} + ${lib_SOURCES_CXX} + ) + +SET( + target_LIBRARIES + cpExtensions + cpPlugins + ) + +## ===================== +## = Compilation rules = +## ===================== + +ADD_CUSTOM_COMMAND( + OUTPUT ${lib_NAME}_Host.cxx + DEPENDS cpPlugins_HostCreator ${LIB_HEADERS_H} + COMMAND cpPlugins_HostCreator ${lib_NAME}_Host.cxx ${lib_HEADERS_H} + ) +ADD_LIBRARY(${lib_NAME} SHARED ${lib_NAME}_Host.cxx ${lib_SOURCES}) +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}/plugins/${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 + ) + +## eof - $RCSfile$ diff --git a/plugins/cpPluginsWidgets/SeedWidget.cxx b/plugins/cpPluginsWidgets/SeedWidget.cxx new file mode 100644 index 0000000..c5c014e --- /dev/null +++ b/plugins/cpPluginsWidgets/SeedWidget.cxx @@ -0,0 +1,214 @@ +#include "SeedWidget.h" + +#include +#include +#include +#include +#include + +// ------------------------------------------------------------------------- +itk::ModifiedTimeType cpPluginsWidgets::SeedWidget:: +GetMTime( ) const +{ + // std::cout << "Seed GetMTime" << std::endl; + return( 0 /*this->Superclass::GetMTime( )*/ ); +} + +// ------------------------------------------------------------------------- +cpPluginsWidgets::SeedWidget:: +SeedWidget( ) + : Superclass( ), + m_Configured( false ) +{ + this->_AddInput( "ReferenceImage" ); + this->_AddOutput< cpPlugins::DataObject >( "Output" ); + + this->m_Parameters.ConfigureAsBool( "SeedsAreInRealSpace" ); + this->m_Parameters.SetBool( "SeedsAreInRealSpace", false ); +} + +// ------------------------------------------------------------------------- +cpPluginsWidgets::SeedWidget:: +~SeedWidget( ) +{ +} + +// ------------------------------------------------------------------------- +std::string cpPluginsWidgets::SeedWidget:: +_GenerateData( ) +{ + auto image = this->GetInputData( "ReferenceImage" ); + std::string r = cpPlugin_Image_Demangle_Dim( _GD0, image, 3 ); + if( r != "" ) r = cpPlugin_Image_Demangle_Dim( _GD0, image, 2 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsWidgets::SeedWidget:: +_GD0( I* image ) +{ + if( image != NULL ) + { + if( this->m_Parameters.GetBool( "SeedsAreInRealSpace" ) ) + return( this->_GD1_Points< I >( image ) ); + else + return( this->_GD1_Vertices< I >( image ) ); + } + else + return( "Widgets::SeedWidget: Input image dimension not supported." ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsWidgets::SeedWidget:: +_GD1_Points( I* image ) +{ + typedef cpExtensions::Interaction::ImageInteractorStyle _S; + typedef itk::Point< double, I::ImageDimension > _P; + typedef itk::SimpleDataObjectDecorator< std::vector< _P > > _Container; + + auto container = this->_CreateITK< _Container >( ); + + double aux_pnt[ 3 ]; + unsigned int dim = ( I::ImageDimension < 3 )? I::ImageDimension: 3; + + container->Get( ).clear( ); + + // MPR + if( this->m_MPRViewer != NULL ) + { + for( unsigned int i = 0; i < 4; ++i ) + { + _S* s = + dynamic_cast< _S* >( + this->m_MPRViewer->GetInteractor( i )->GetInteractorStyle( ) + ); + if( s != NULL ) + { + if( this->m_Configured ) + { + for( unsigned int i = 0; i < s->GetNumberOfSeeds( ); ++i ) + { + s->GetSeedAsPoint( i, aux_pnt ); + _P seed; + for( unsigned int d = 0; d < dim; ++d ) + seed[ d ] = aux_pnt[ d ]; + container->Get( ).push_back( seed ); + + } // rof + } + else + s->SeedWidgetOn( ); + + } // fi + + } // rof + + } // fi + + // Single interactor + _S* s = dynamic_cast< _S* >( this->m_SingleInteractor ); + if( s != NULL ) + { + if( this->m_Configured ) + { + for( unsigned int i = 0; i < s->GetNumberOfSeeds( ); ++i ) + { + s->GetSeedAsPoint( i, aux_pnt ); + _P seed; + for( unsigned int d = 0; d < dim; ++d ) + seed[ d ] = aux_pnt[ d ]; + container->Get( ).push_back( seed ); + + } // rof + } + else + s->SeedWidgetOn( ); + + } // fi + this->m_Configured = true; + + this->GetOutputData( "Output" )->SetITK( container ); + return( "" ); +} + +// ------------------------------------------------------------------------- +template< class I > +std::string cpPluginsWidgets::SeedWidget:: +_GD1_Vertices( I* image ) +{ + typedef cpExtensions::Interaction::ImageInteractorStyle _S; + typedef + itk::SimpleDataObjectDecorator< std::vector< typename I::IndexType > > + _Container; + auto container = this->_CreateITK< _Container >( ); + + double aux_pnt[ 3 ]; + unsigned int dim = ( I::ImageDimension < 3 )? I::ImageDimension: 3; + + container->Get( ).clear( ); + + // MPR + if( this->m_MPRViewer != NULL ) + { + for( unsigned int i = 0; i < 4; ++i ) + { + _S* s = + dynamic_cast< _S* >( + this->m_MPRViewer->GetInteractor( i )->GetInteractorStyle( ) + ); + if( s != NULL ) + { + if( this->m_Configured ) + { + for( unsigned int i = 0; i < s->GetNumberOfSeeds( ); ++i ) + { + s->GetSeedAsPoint( i, aux_pnt ); + typename I::PointType seed; + for( unsigned int d = 0; d < dim; ++d ) + seed[ d ] = aux_pnt[ d ]; + typename I::IndexType idx; + if( image->TransformPhysicalPointToIndex( seed, idx ) ) + container->Get( ).push_back( idx ); + + } // rof + } + else + s->SeedWidgetOn( ); + + } // fi + + } // rof + + } // fi + + // Single interactor + _S* s = dynamic_cast< _S* >( this->m_SingleInteractor ); + if( s != NULL ) + { + if( this->m_Configured ) + { + for( unsigned int i = 0; i < s->GetNumberOfSeeds( ); ++i ) + { + s->GetSeedAsPoint( i, aux_pnt ); + typename I::PointType seed; + for( unsigned int d = 0; d < dim; ++d ) + seed[ d ] = aux_pnt[ d ]; + typename I::IndexType idx; + if( image->TransformPhysicalPointToIndex( seed, idx ) ) + container->Get( ).push_back( idx ); + + } // rof + } + else + s->SeedWidgetOn( ); + + } // fi + this->m_Configured = true; + + this->GetOutputData( "Output" )->SetITK( container ); + return( "" ); +} + +// eof - $RCSfile$ diff --git a/plugins/cpPluginsWidgets/SeedWidget.h b/plugins/cpPluginsWidgets/SeedWidget.h new file mode 100644 index 0000000..7b02d94 --- /dev/null +++ b/plugins/cpPluginsWidgets/SeedWidget.h @@ -0,0 +1,56 @@ +#ifndef __CPPLUGINSWIDGETS__SEEDWIDGET__H__ +#define __CPPLUGINSWIDGETS__SEEDWIDGET__H__ + +#include +#include + +namespace cpPluginsWidgets +{ + /** + */ + class cpPluginsWidgets_EXPORT SeedWidget + : public cpPlugins::BaseWidget + { + 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 ); + + public: + virtual itk::ModifiedTimeType GetMTime( ) const; + + protected: + SeedWidget( ); + virtual ~SeedWidget( ); + + virtual std::string _GenerateData( ); + + template< class I > + inline std::string _GD0( I* image ); + + template< class I > + inline std::string _GD1_Points( I* image ); + + template< class I > + inline std::string _GD1_Vertices( I* image ); + + private: + // Purposely not implemented + SeedWidget( const Self& ); + Self& operator=( const Self& ); + + protected: + bool m_Configured; + }; + +} // ecapseman + +#endif // __CPPLUGINSWIDGETS__SEEDWIDGET__H__ + +// eof - $RCSfile$ -- 2.47.1