diff --git a/README.md b/README.md index 02a681b301805b0b88775feedd4fea2953d9b0cf..7ece0c65d39ebaa41838e480e3e7f02213c61c22 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,40 @@ # Extraction d’information dans les formes 3D à partir de graphes de Reeb et d’un indice de forme spécifique, avec la librairie TTK + ## Table des matières + [[_TOC_]] + ## Sujet -TTK (Topological Toolkit) est une librairie très puissante en ce qui concerne l’analyse de données topologiques. Il est par exemple aisé de calculer des graphes de Reeb d’une forme, en utilisant tous types de fonctions scalaires qui va “traverser” l’objet. -Dans ce projet, il sera question de poursuivre des travaux élaborés dans l’équipe G-Mod concernant l’analyse d’objets 3D par graphes de Reeb. La librairie TTK sera utilisée pour le calcul des graphes de Reeb, et nous utiliserons la fonction Shape Index [Koenderink et al. 1992]. Cet indice de forme fournit une représentation intrinsèque des caractéristiques géométriques locales de la surface 3D (forme convexe, concave, ornière, crête, selle, etc.) à partir des courbures principales. De plus, il est invariant à l’échelle, à la rotation et aux translations. Ce descripteur propose un bon score pour retrouver des surfaces similaires. +TTK (Topological Toolkit) est une librairie très puissante en ce qui concerne l’analyse de données topologiques. Il est par exemple aisé de calculer des graphes de Reeb d’une forme, en utilisant tous types de fonctions scalaires qui va “traverser” l’objet. + +Dans ce projet, il sera question de poursuivre des travaux élaborés dans l’équipe G-Mod concernant l’analyse d’objets 3D par graphes de Reeb. La librairie TTK sera utilisée pour le calcul des graphes de Reeb, et nous utiliserons la fonction Shape Index [Koenderink et al. 1992]. Cet indice de forme fournit une représentation intrinsèque des caractéristiques géométriques locales de la surface 3D (forme convexe, concave, ornière, crête, selle, etc.) à partir des courbures principales. De plus, il est invariant à l’échelle, à la rotation et aux translations. Ce descripteur propose un bon score pour retrouver des surfaces similaires. Sur la base des graphes de Reeb produits, le projet pourra se poursuivre par : + - La détection de similarité et de symétries au sein d’un maillage ; - La segmentation d’objets ; - La classification d’objets ; - La simplification de formes. ## Environnements + - TTK : Topological Toolkit https://topology-tool-kit.github.io/ - Paraview ## Installer la librairie TTK + Avec Ubuntu : [Récupérer ici](https://topology-tool-kit.github.io/downloads.html) la librairie TTK. Ce projet est sous la version Ubuntu **Linux 22.04**. ```bash -$ sudo apt install ./ttk-paraview-v5.10.1-ubuntu-22.04.deb -$ sudo apt install ./ttk-1.1.0-ubuntu-22.04.deb +$ sudo apt install ./ttk-paraview-v5.10.1-ubuntu-22.04.deb +$ sudo apt install ./ttk-1.1.0-ubuntu-22.04.deb ``` ## Modifications à apporter à la librairie -Ces modifications doivent être faites sur les fichiers situés dans `usr/include/ttk/vtk/`. +Ces modifications doivent être faites sur les fichiers situés dans `usr/include/ttk/vtk/`. ### Modifications d'en-têtes @@ -39,7 +46,7 @@ Dans le fichier d'en-tête **ttkContourForests.h**, modifier les lignes 54 à 56 #include <DeprecatedDataTypes.h> ``` -Se rendre ensuite dans le fichier d'en-tête **ttkFTRGraph.h** et modifier les lignes 52 à 56 pour remplacer les guillemets par des chevrons : +Se rendre ensuite dans le fichier d'en-tête **ttkFTRGraph.h** et modifier les lignes 52 à 56 pour remplacer les guillemets par des chevrons : ``` // ttk code includes @@ -54,356 +61,358 @@ Se rendre ensuite dans le fichier d'en-tête **ttkFTRGraph.h** et modifier les l <details> <summary markdown="span">Créer le fichier <b>ttkFTRGraphStructures.h</b> :</summary> - ```c++ - #pragma once - - #include <vtkCellData.h> - #include <vtkCharArray.h> - #include <vtkDataSet.h> - #include <vtkDoubleArray.h> - #include <vtkIntArray.h> - #include <vtkNew.h> - #include <vtkPointData.h> - #include <vtkUnsignedCharArray.h> - #include <vtkUnstructuredGrid.h> - - #include <FTRCommon.h> - #include <FTRDataTypes.h> - #include <Graph.h> - - namespace ttk { - namespace ftr { - - /// Vertex / Node / Arc data inherit from this - /// master structure. - struct ObjectData { - inline void allocArray(vtkDataArray *const arr, - const char *fieldName, - size_t nbElmnt) { - arr->SetName(fieldName); - arr->SetNumberOfComponents(1); - arr->SetNumberOfTuples(nbElmnt); - - #ifndef TTK_ENABLE_KAMIKAZE - if(!arr) { - Debug dbg{}; - dbg.setDebugMsgPrefix("FTRGraph"); - dbg.printErr("unable to allocate " + std::string{fieldName} - + " the program will likely crash"); - } - #endif - } - }; - - struct NodeData : public ObjectData { - vtkNew<vtkIntArray> ids{}; - vtkNew<vtkIntArray> types{}; - vtkNew<vtkDoubleArray> scalars{}; - - explicit NodeData(const ttk::ftr::idVertex nbNodes) { - allocArray(ids, "VertexId", nbNodes); - allocArray(types, "CriticalType", nbNodes); - allocArray(scalars, "Scalar", nbNodes); - } - - void addNode(const ttk::ftr::Graph &graph, - const ttk::ftr::idNode n, - const double scalar) { - ids->SetTuple1(n, graph.getNode(n).getVertexIdentifier()); - types->SetTuple1(n, (double)graph.getNode(n).getType()); - scalars->SetTuple1(n, scalar); - } - - void addArrays(vtkPointData *pointData, - ttk::ftr::Params ttkNotUsed(params)) { - pointData->AddArray(ids); - pointData->SetScalars(types); - pointData->AddArray(scalars); - } - }; - - struct ArcData : public ObjectData { - vtkNew<vtkIntArray> ids{}; - vtkNew<vtkCharArray> reg{}; - #ifndef NDEBUG - vtkNew<vtkUnsignedCharArray> fromUp{}; - #endif - std::map<ttk::ftr::idVertex, vtkIdType> points; - - ArcData(const ttk::ftr::idSuperArc nbArcs) { - allocArray(ids, "ArcId", nbArcs); - allocArray(reg, ttk::MaskScalarFieldName, nbArcs * 2); - #ifndef NDEBUG - allocArray(fromUp, "growUp", nbArcs); - #endif - } - - void setPointInfo(const ttk::ftr::Graph &ttkNotUsed(graph), - const ttk::ftr::idSuperArc ttkNotUsed(a), - const vtkIdType skeletonVert, - bool r = false) { - reg->SetTuple1(skeletonVert, r); - } - - void setArcInfo(const ttk::ftr::Graph &graph, - const ttk::ftr::idSuperArc a, - const vtkIdType skeletonCell) { - ids->SetTuple1(skeletonCell, a); - #ifndef NDEBUG - fromUp->SetTuple1(skeletonCell, graph.getArc(a).getFromUp()); - #else - TTK_FORCE_USE(graph); - #endif - } +```c++ +#pragma once + +#include <vtkCellData.h> +#include <vtkCharArray.h> +#include <vtkDataSet.h> +#include <vtkDoubleArray.h> +#include <vtkIntArray.h> +#include <vtkNew.h> +#include <vtkPointData.h> +#include <vtkUnsignedCharArray.h> +#include <vtkUnstructuredGrid.h> + +#include <FTRCommon.h> +#include <FTRDataTypes.h> +#include <Graph.h> - void addArrays(vtkUnstructuredGrid *arcs, - ttk::ftr::Params ttkNotUsed(params)) { - // original size may be too large - ids->SetNumberOfTuples(arcs->GetNumberOfCells()); - arcs->GetCellData()->SetScalars(ids); - reg->SetNumberOfTuples(arcs->GetNumberOfPoints()); - arcs->GetPointData()->AddArray(reg); - #ifndef NDEBUG - fromUp->SetNumberOfTuples(arcs->GetNumberOfCells()); - arcs->GetCellData()->AddArray(fromUp); - #endif - } - }; - - struct VertData : public ObjectData { - vtkNew<vtkIntArray> ids{}; - vtkNew<vtkIntArray> regionType{}; - #ifdef TTK_ENABLE_FTR_VERT_STATS - vtkNew<vtkIntArray> touch{}; - vtkNew<vtkIntArray> arcActif{}; - vtkNew<vtkIntArray> taskActif{}; - #endif - - explicit VertData(const ttk::ftr::idVertex nbVertices) { - allocArray(ids, "ArcId", nbVertices); - allocArray(regionType, "RegionType", nbVertices); - #ifdef TTK_ENABLE_FTR_VERT_STATS - allocArray(touch, "Visit", nbVertices); - allocArray(arcActif, "Arc active", nbVertices); - #endif +namespace ttk { + namespace ftr { + + /// Vertex / Node / Arc data inherit from this + /// master structure. + struct ObjectData { + inline void allocArray(vtkDataArray *const arr, + const char *fieldName, + size_t nbElmnt) { + arr->SetName(fieldName); + arr->SetNumberOfComponents(1); + arr->SetNumberOfTuples(nbElmnt); + +#ifndef TTK_ENABLE_KAMIKAZE + if(!arr) { + Debug dbg{}; + dbg.setDebugMsgPrefix("FTRGraph"); + dbg.printErr("unable to allocate " + std::string{fieldName} + + " the program will likely crash"); } - - void setVertexInfo(const ttk::ftr::Graph &graph, - const ttk::ftr::idVertex v) { - - if(!graph.isVisited(v)) { - // Problem, we should have visited all vertices - // return to avoid crash - return; - } - - const ttk::ftr::idSuperArc curArcId = graph.getArcId(v); - ids->SetTuple1(v, curArcId); - - int downNodeType - = (int)graph.getNode(graph.getArc(curArcId).getDownNodeId()) - .getType(); - regionType->SetTuple1(v, downNodeType); - - #ifdef TTK_ENABLE_FTR_VERT_STATS - touch->SetTuple1(v, graph.getNbTouch(v)); - arcActif->SetTuple1(v, graph.getNbArcActive(v)); - #endif +#endif + } + }; + + struct NodeData : public ObjectData { + vtkNew<vtkIntArray> ids{}; + vtkNew<vtkIntArray> types{}; + vtkNew<vtkDoubleArray> scalars{}; + + explicit NodeData(const ttk::ftr::idVertex nbNodes) { + allocArray(ids, "VertexId", nbNodes); + allocArray(types, "CriticalType", nbNodes); + allocArray(scalars, "Scalar", nbNodes); + } + + void addNode(const ttk::ftr::Graph &graph, + const ttk::ftr::idNode n, + const double scalar) { + ids->SetTuple1(n, graph.getNode(n).getVertexIdentifier()); + types->SetTuple1(n, (double)graph.getNode(n).getType()); + scalars->SetTuple1(n, scalar); + } + + void addArrays(vtkPointData *pointData, + ttk::ftr::Params ttkNotUsed(params)) { + pointData->AddArray(ids); + pointData->SetScalars(types); + pointData->AddArray(scalars); + } + }; + + struct ArcData : public ObjectData { + vtkNew<vtkIntArray> ids{}; + vtkNew<vtkCharArray> reg{}; +#ifndef NDEBUG + vtkNew<vtkUnsignedCharArray> fromUp{}; +#endif + std::map<ttk::ftr::idVertex, vtkIdType> points; + + ArcData(const ttk::ftr::idSuperArc nbArcs) { + allocArray(ids, "ArcId", nbArcs); + allocArray(reg, ttk::MaskScalarFieldName, nbArcs * 2); +#ifndef NDEBUG + allocArray(fromUp, "growUp", nbArcs); +#endif + } + + void setPointInfo(const ttk::ftr::Graph &ttkNotUsed(graph), + const ttk::ftr::idSuperArc ttkNotUsed(a), + const vtkIdType skeletonVert, + bool r = false) { + reg->SetTuple1(skeletonVert, r); + } + + void setArcInfo(const ttk::ftr::Graph &graph, + const ttk::ftr::idSuperArc a, + const vtkIdType skeletonCell) { + ids->SetTuple1(skeletonCell, a); +#ifndef NDEBUG + fromUp->SetTuple1(skeletonCell, graph.getArc(a).getFromUp()); +#else + TTK_FORCE_USE(graph); +#endif + } + + void addArrays(vtkUnstructuredGrid *arcs, + ttk::ftr::Params ttkNotUsed(params)) { + // original size may be too large + ids->SetNumberOfTuples(arcs->GetNumberOfCells()); + arcs->GetCellData()->SetScalars(ids); + reg->SetNumberOfTuples(arcs->GetNumberOfPoints()); + arcs->GetPointData()->AddArray(reg); +#ifndef NDEBUG + fromUp->SetNumberOfTuples(arcs->GetNumberOfCells()); + arcs->GetCellData()->AddArray(fromUp); +#endif + } + }; + + struct VertData : public ObjectData { + vtkNew<vtkIntArray> ids{}; + vtkNew<vtkIntArray> regionType{}; +#ifdef TTK_ENABLE_FTR_VERT_STATS + vtkNew<vtkIntArray> touch{}; + vtkNew<vtkIntArray> arcActif{}; + vtkNew<vtkIntArray> taskActif{}; +#endif + + explicit VertData(const ttk::ftr::idVertex nbVertices) { + allocArray(ids, "ArcId", nbVertices); + allocArray(regionType, "RegionType", nbVertices); +#ifdef TTK_ENABLE_FTR_VERT_STATS + allocArray(touch, "Visit", nbVertices); + allocArray(arcActif, "Arc active", nbVertices); +#endif + } + + void setVertexInfo(const ttk::ftr::Graph &graph, + const ttk::ftr::idVertex v) { + + if(!graph.isVisited(v)) { + // Problem, we should have visited all vertices + // return to avoid crash + return; } - void addArrays(vtkDataSet *segmentation, - ttk::ftr::Params ttkNotUsed(params)) { - segmentation->GetPointData()->AddArray(ids); - segmentation->GetPointData()->SetActiveScalars(ids->GetName()); - segmentation->GetPointData()->AddArray(regionType); - #ifdef TTK_ENABLE_FTR_VERT_STATS - segmentation->GetPointData()->AddArray(touch); - segmentation->GetPointData()->AddArray(arcActif); - #endif - } - }; - }; // namespace ftr - }; // namespace ttk - ``` + const ttk::ftr::idSuperArc curArcId = graph.getArcId(v); + ids->SetTuple1(v, curArcId); + + int downNodeType + = (int)graph.getNode(graph.getArc(curArcId).getDownNodeId()) + .getType(); + regionType->SetTuple1(v, downNodeType); + +#ifdef TTK_ENABLE_FTR_VERT_STATS + touch->SetTuple1(v, graph.getNbTouch(v)); + arcActif->SetTuple1(v, graph.getNbArcActive(v)); +#endif + } + + void addArrays(vtkDataSet *segmentation, + ttk::ftr::Params ttkNotUsed(params)) { + segmentation->GetPointData()->AddArray(ids); + segmentation->GetPointData()->SetActiveScalars(ids->GetName()); + segmentation->GetPointData()->AddArray(regionType); +#ifdef TTK_ENABLE_FTR_VERT_STATS + segmentation->GetPointData()->AddArray(touch); + segmentation->GetPointData()->AddArray(arcActif); +#endif + } + }; + }; // namespace ftr +}; // namespace ttk +``` </details> <details> <summary markdown="span">Enfin, créer le fichier <b>ttkFTRGraph.h</b> :</summary> - ```c++ - /// \ingroup vtk - /// \class ttkFTRGraph - /// \author Charles Gueunet <charles.gueunet@kitware.com> - /// \date June 2017. - /// - /// \sa ttk::ftm::FTRGraph - /// - /// \brief TTK VTK-filter for the computation of Reeb Graphs - /// - /// The computation of the Reeb graph done by this package is done in - /// parallel if TTK_ENABLE_OPENMP is set to ON, using a task based approch - /// described in the article mention below. - /// - /// \param Input Input scalar field, either 2D or 3D, regular - /// grid or triangulation (vtkDataSet) - /// \param SingleSweep control if the computation should start from both minima - /// and maxima simultaneously. If you encouter troubled with FTR, you should try - /// to use the single sweep. It is slower but may be more robust. - /// \param Segmentation control wethear or not the output should be augmented - /// with the segmentation. - /// \param SuperArcSamplingLevel control the number of subdivision - /// of each superarc. Intermediate point will be located on the barycenter of - /// the corresponding portion of vertex. - /// \param Output the output of this filter - /// is composed of:\n - /// 1. The nodes of the tree - /// 2. The arcs of the tree - /// 3. The semgentation of the initial dataset - /// The structure of the tree (Nodes+Arcs) have a concept of nodeId, wich is - /// an id that is consistent between execution if SetWithNormalize is set to - /// True. The downNodeId of an arc is its starting node (directed towards the - /// leaves as the computation starts here) and the upNodeId it the ending node, - /// in direction of the Root of the tree. - /// The segmentation also contains some basics metrics like the size of each - /// region (RegionSpan) or its number of vertex (RegionSize) - /// - /// This filter can be used as any other VTK filter (for instance, by using the - /// sequence of calls SetInputData(), Update(), GetOutput()). - /// - /// \b Related \b publication \n - /// "Task-based Augmented Reeb Graphs with Dynamic ST-Trees" \n - /// Charles Gueunet, Pierre Fortin, Julien Jomier, Julien Tierny \n - /// EGPGV19: Eurographics Symposium on Parallel Graphics and Visualization - /// - /// \b Online \b examples: \n - /// - <a - /// href="https://topology-tool-kit.github.io/examples/harmonicSkeleton/"> - /// Harmonic Skeleton example</a> \n - - #pragma once - - // ttk code includes - #include <FTRGraph.h> - #include <Graph.h> - #include <ttkAlgorithm.h> - #include <ttkFTRGraphStructures.h> - - // VTK includes - #include <vtkDataArray.h> - - // VTK Module - #include <ttkFTRGraphModule.h> - - class TTKFTRGRAPH_EXPORT ttkFTRGraph : public ttkAlgorithm { - public: - static ttkFTRGraph *New(); - vtkTypeMacro(ttkFTRGraph, ttkAlgorithm); - - vtkSetMacro(ForceInputOffsetScalarField, bool); - vtkGetMacro(ForceInputOffsetScalarField, bool); - - /// @brief control whether the computation should start from min and max - /// (default) or use a single sweep starting only from the min (may be more - /// robust) - /// @{ - void SetSingleSweep(const bool ss) { - params_.singleSweep = ss; - Modified(); - } - bool GetSingleSweep() const { - return params_.singleSweep; - } - /// @} - - /// @brief control if the output should contains the segmentation information - /// @{ - void SetWithSegmentation(const bool segm) { - params_.segm = segm; - Modified(); - } - bool GetWithSegmentation() const { - return params_.segm; - } - /// @} - - /// @brief if set to true, a post processing pass will be used to enforce - /// consistend node ids between executions - /// @{ - void SetWithNormalize(const bool norm) { - params_.normalize = norm; - Modified(); - } - bool GetWithNormalize() const { - return params_.normalize; - } - /// @} - - /// @brief control the sampling level of the superarcs - /// @{ - void SetSampling(int lvl) { - params_.samplingLvl = lvl; - Modified(); - } - int GetSuperArcSamplingLevel() const { - return params_.samplingLvl; - } - /// @} - - int getSkeletonNodes(const ttk::ftr::Graph &graph, - vtkUnstructuredGrid *outputSkeletonNodes); - - int addDirectSkeletonArc(const ttk::ftr::Graph &graph, +```c++ +/// \ingroup vtk +/// \class ttkFTRGraph +/// \author Charles Gueunet <charles.gueunet@kitware.com> +/// \date June 2017. +/// +/// \sa ttk::ftm::FTRGraph +/// +/// \brief TTK VTK-filter for the computation of Reeb Graphs +/// +/// The computation of the Reeb graph done by this package is done in +/// parallel if TTK_ENABLE_OPENMP is set to ON, using a task based approch +/// described in the article mention below. +/// +/// \param Input Input scalar field, either 2D or 3D, regular +/// grid or triangulation (vtkDataSet) +/// \param SingleSweep control if the computation should start from both minima +/// and maxima simultaneously. If you encouter troubled with FTR, you should try +/// to use the single sweep. It is slower but may be more robust. +/// \param Segmentation control wethear or not the output should be augmented +/// with the segmentation. +/// \param SuperArcSamplingLevel control the number of subdivision +/// of each superarc. Intermediate point will be located on the barycenter of +/// the corresponding portion of vertex. +/// \param Output the output of this filter +/// is composed of:\n +/// 1. The nodes of the tree +/// 2. The arcs of the tree +/// 3. The semgentation of the initial dataset +/// The structure of the tree (Nodes+Arcs) have a concept of nodeId, wich is +/// an id that is consistent between execution if SetWithNormalize is set to +/// True. The downNodeId of an arc is its starting node (directed towards the +/// leaves as the computation starts here) and the upNodeId it the ending node, +/// in direction of the Root of the tree. +/// The segmentation also contains some basics metrics like the size of each +/// region (RegionSpan) or its number of vertex (RegionSize) +/// +/// This filter can be used as any other VTK filter (for instance, by using the +/// sequence of calls SetInputData(), Update(), GetOutput()). +/// +/// \b Related \b publication \n +/// "Task-based Augmented Reeb Graphs with Dynamic ST-Trees" \n +/// Charles Gueunet, Pierre Fortin, Julien Jomier, Julien Tierny \n +/// EGPGV19: Eurographics Symposium on Parallel Graphics and Visualization +/// +/// \b Online \b examples: \n +/// - <a +/// href="https://topology-tool-kit.github.io/examples/harmonicSkeleton/"> +/// Harmonic Skeleton example</a> \n + +#pragma once + +// ttk code includes +#include <FTRGraph.h> +#include <Graph.h> +#include <ttkAlgorithm.h> +#include <ttkFTRGraphStructures.h> + +// VTK includes +#include <vtkDataArray.h> + +// VTK Module +#include <ttkFTRGraphModule.h> + +class TTKFTRGRAPH_EXPORT ttkFTRGraph : public ttkAlgorithm { +public: + static ttkFTRGraph *New(); + vtkTypeMacro(ttkFTRGraph, ttkAlgorithm); + + vtkSetMacro(ForceInputOffsetScalarField, bool); + vtkGetMacro(ForceInputOffsetScalarField, bool); + + /// @brief control whether the computation should start from min and max + /// (default) or use a single sweep starting only from the min (may be more + /// robust) + /// @{ + void SetSingleSweep(const bool ss) { + params_.singleSweep = ss; + Modified(); + } + bool GetSingleSweep() const { + return params_.singleSweep; + } + /// @} + + /// @brief control if the output should contains the segmentation information + /// @{ + void SetWithSegmentation(const bool segm) { + params_.segm = segm; + Modified(); + } + bool GetWithSegmentation() const { + return params_.segm; + } + /// @} + + /// @brief if set to true, a post processing pass will be used to enforce + /// consistend node ids between executions + /// @{ + void SetWithNormalize(const bool norm) { + params_.normalize = norm; + Modified(); + } + bool GetWithNormalize() const { + return params_.normalize; + } + /// @} + + /// @brief control the sampling level of the superarcs + /// @{ + void SetSampling(int lvl) { + params_.samplingLvl = lvl; + Modified(); + } + int GetSuperArcSamplingLevel() const { + return params_.samplingLvl; + } + /// @} + + int getSkeletonNodes(const ttk::ftr::Graph &graph, + vtkUnstructuredGrid *outputSkeletonNodes); + + int addDirectSkeletonArc(const ttk::ftr::Graph &graph, + const ttk::ftr::idSuperArc arcId, + vtkPoints *points, + vtkUnstructuredGrid *skeletonArcs, + ttk::ftr::ArcData &arcData); + + int addSampledSkeletonArc(const ttk::ftr::Graph &graph, const ttk::ftr::idSuperArc arcId, vtkPoints *points, vtkUnstructuredGrid *skeletonArcs, ttk::ftr::ArcData &arcData); - int addSampledSkeletonArc(const ttk::ftr::Graph &graph, - const ttk::ftr::idSuperArc arcId, - vtkPoints *points, - vtkUnstructuredGrid *skeletonArcs, - ttk::ftr::ArcData &arcData); + int addCompleteSkeletonArc(const ttk::ftr::Graph &graph, + const ttk::ftr::idSuperArc arcId, + vtkPoints *points, + vtkUnstructuredGrid *skeletonArcs, + ttk::ftr::ArcData &arcData); - int addCompleteSkeletonArc(const ttk::ftr::Graph &graph, - const ttk::ftr::idSuperArc arcId, - vtkPoints *points, - vtkUnstructuredGrid *skeletonArcs, - ttk::ftr::ArcData &arcData); + int getSkeletonArcs(const ttk::ftr::Graph &graph, + vtkUnstructuredGrid *outputSkeletonArcs); - int getSkeletonArcs(const ttk::ftr::Graph &graph, - vtkUnstructuredGrid *outputSkeletonArcs); + int getSegmentation(const ttk::ftr::Graph &graph, + vtkDataSet *outputSegmentation); - int getSegmentation(const ttk::ftr::Graph &graph, - vtkDataSet *outputSegmentation); + template <typename VTK_TT, typename TTK_TT> + int dispatch(ttk::ftr::Graph &graph); - template <typename VTK_TT, typename TTK_TT> - int dispatch(ttk::ftr::Graph &graph); +protected: + ttkFTRGraph(); - protected: - ttkFTRGraph(); + void identify(vtkDataSet *ds) const; - void identify(vtkDataSet *ds) const; + int FillInputPortInformation(int port, vtkInformation *info) override; + int FillOutputPortInformation(int port, vtkInformation *info) override; + int RequestData(vtkInformation *request, + vtkInformationVector **inputVector, + vtkInformationVector *outputVector) override; - int FillInputPortInformation(int port, vtkInformation *info) override; - int FillOutputPortInformation(int port, vtkInformation *info) override; - int RequestData(vtkInformation *request, - vtkInformationVector **inputVector, - vtkInformationVector *outputVector) override; +private: + bool ForceInputOffsetScalarField{}; + ttk::ftr::Params params_{}; - private: - bool ForceInputOffsetScalarField{}; - ttk::ftr::Params params_{}; + vtkDataSet *mesh_{}; + ttk::Triangulation *triangulation_{}; + vtkDataArray *inputScalars_{}; + vtkDataArray *offsets_{}; +}; +``` - vtkDataSet *mesh_{}; - ttk::Triangulation *triangulation_{}; - vtkDataArray *inputScalars_{}; - vtkDataArray *offsets_{}; - }; - ``` </details> ## Comment tester le projet + ### Création du répertoire build ```bash @@ -413,6 +422,7 @@ cmake ../ ``` ### Génération du projet + Attention à bien être situé dans le répertoire `/build`. Cette étape est à répéter en cas de modification du script. ```bash @@ -420,6 +430,7 @@ make ``` ### Lancement du projet avec un objet + Attention à bien être situé dans le répertoire `/build`. ```bash @@ -427,9 +438,9 @@ Attention à bien être situé dans le répertoire `/build`. paraview ShapeIndexMap.vtp ``` -Où `nom_projet` correspond au nom donné dans le fichier [CMakeLists.txt](CMakeLists.txt), aux lignes 4, 10, 12 et 20. +Où `nom_projet` correspond au nom donné dans le fichier [CMakeLists.txt](CMakeLists.txt), aux lignes 4, 10, 12 et 20. -Cette dernière commande va lancer le programme ParaView avec l'objet donné. +Cette dernière commande va lancer le programme ParaView avec l'objet donné. Une fois dans le logiciel, penser à check l'icône avec l'œil fermé à côté de ShapeIndexMap.vtp dans la fenêtre Pipeline Browser afin d'afficher le résultat. Modifier dans la fenêtre Properties la valeur du menu déroulant sous Coloring par Shape_Index (indice de forme). Enfin, dans le menu Color Map Editor à droite (faire View/check Color Map Editor si la fenêtre n'est pas visible), cliquer sous Mapping Data pour sélectionner la color map nommée Turbo. @@ -440,11 +451,12 @@ L'exemple précédent montre comment ouvrir l'affichage avec `ShapeIndexMap.vtp` > **ReebGraphNodes.vtp** : contient les noeuds du graphe de Reeb d’indice de forme au format vtp, notons que ces noeuds sont colorés suivant leur valeur d’indice de forme. > **ShapeIndexMap.vtp** : permet l’affichage de notre maillage coloré selon l’indice de forme sur sa surface. - Pour ouvrir les 3 .vtp en même temps, on en ouvre un avec la commande `paraview` puis, une fois dans le logiciel, faire ctrl+O pour ouvrir des fichiers. De là, on peut ouvrir les autres .vtp du répertoire `build`. ### En cas de lecture de main.cpp sur un IDE + Penser à renseigner les chemins suivants pour les `#include` (sous Ubuntu) : + ``` /usr/include/ttk/vtk /usr/include/paraview-5.10 @@ -452,6 +464,7 @@ Penser à renseigner les chemins suivants pour les `#include` (sous Ubuntu) : ``` ## Fonctionnalités + - Lecture de fichier `.obj` passé en entrée et traduction du maillage en "VTKPolyData", le modèle de donnée de VTK. - Calcul des courbures principales du modèle, courbure minimale et courbure maximale. - Récupération des courbures afin de calculer l'indice de forme en chaque point du maillage. Ajout de l'indice de forme au modèle de données comme caractéristique du modèle. @@ -460,15 +473,25 @@ Penser à renseigner les chemins suivants pour les `#include` (sous Ubuntu) : - Récupération des informations du graphe et écriture dans le format `.vtp`. ## A modifier -- [ ] Généraliser le format d'entrée - - [ ] Rendre tous les OBJ lisibles par le programme. - - [ ] Pouvoir lire les fichiers OFF afin de généraliser le format d'entrée. + +- [x] Généraliser le format d'entrée + - [x] Rendre les OBJ lisibles par le programme (si pas lisibles, msg d'erreur) + - [x] Pouvoir lire les fichiers OFF afin de généraliser le format d'entrée. - [ ] Améliorer l'outil de filtrage. + - [ ] Transformer les .vtp en dot pour visualiser le graphe de Reeb sous graphviz + - [ ] Filtrer selon des paramètres spécifiques le graphe obtenu +- [ ] Créer une interface + - [ ] Un affichage du maillage d'un côté, affichage du graphe de Reeb de ce maillage de l'autre + - [ ] Possibilité d'agir sur le filtrage avec un slider + - [ ] Possibilité de cliquer sur un élément du graphe de Reeb et visualiser à quoi ça correspond sur le maillage + ## Références + - Florian Beguet. Modélisation et description par graphes pour des formes géométriques complexes. Thèse de doctorat, Aix-Marseille Université, 2021. - Jan J. Koenderink et Andrea J. Van Doorn. « Surface shape and curvature scales ». Image and vision computing, 10.8, p. 557-564, 1992. ### Auteurs + Un sujet proposé par Jean-Luc MARI Lucie CLERAND et Eve REGA (PFE Master 2 Informatique) Astrid BEYER (avril 2023 - juin 2023)