From fe98a605d6b03e7a734c48e5a08fe2ff7ab449a1 Mon Sep 17 00:00:00 2001
From: BEYER Astrid <astrid.beyer@etu.univ-amu.fr>
Date: Wed, 19 Apr 2023 17:17:29 +0200
Subject: [PATCH] =?UTF-8?q?wip:=20script=20v=C3=A9rification=20de=20mailla?=
 =?UTF-8?q?ge?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .gitignore        |   1 +
 CMakeLists.txt    |   2 +-
 isTriangulate.cpp |  35 +++++++++++
 isTriangulate.h   |   9 +++
 main.cpp          | 155 +++++++++++++++++++++++-----------------------
 5 files changed, 123 insertions(+), 79 deletions(-)
 create mode 100644 isTriangulate.cpp
 create mode 100644 isTriangulate.h

diff --git a/.gitignore b/.gitignore
index 6f31401..e2cada2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 build/
 .vscode/
+obj/
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f1e0001..b02cc5f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 11)
 
 find_package(TTKVTK REQUIRED)
 
-add_executable(projet-stage main.cpp)
+add_executable(projet-stage main.cpp isTriangulate.cpp)
 
 target_link_libraries(projet-stage
   PUBLIC
diff --git a/isTriangulate.cpp b/isTriangulate.cpp
new file mode 100644
index 0000000..9e0a153
--- /dev/null
+++ b/isTriangulate.cpp
@@ -0,0 +1,35 @@
+#include <vtkTriangleFilter.h>
+#include "isTriangulate.h"
+
+// Fonction pour construire une triangulation valide à partir d'un vtkPolyData contenant des quadrilatères
+vtkSmartPointer<vtkPolyData> triangulate::buildValidTriangulation(vtkSmartPointer<vtkPolyData> polyData)
+{
+    vtkSmartPointer<vtkPolyData> triPolyData = vtkSmartPointer<vtkPolyData>::New();
+
+    // Si le maillage en entrée est composé de quadrilatères, on construit une triangulation valide
+    if (polyData->GetMaxCellSize() > 3)
+    {
+        std::cout << "maillage composé de quads";
+        // On utilise un filtre vtkQuadToTriangle pour convertir les quadrilatères en triangles
+        vtkSmartPointer<vtkTriangleFilter> quadToTri = vtkSmartPointer<vtkTriangleFilter>::New();
+        quadToTri->SetInputData(polyData);
+        quadToTri->Update();
+
+        triPolyData = quadToTri->GetOutput();
+    }
+    else if (polyData->GetMaxCellSize() == 3) // Si le maillage en entrée est déjà triangulé, on renvoie le vtkPolyData d'origine
+    {
+        triPolyData = polyData;
+    }
+    else
+    {
+        std::cout << "Ce maillage n'est pas géré par ce programme, sont acceptés les maillages triangulés et quadrilatérisés";
+    }
+
+    // On ajoute un filtre vtkTriangleFilter pour garantir que la sortie est bien un maillage triangulé
+    vtkSmartPointer<vtkTriangleFilter> triangleFilter = vtkSmartPointer<vtkTriangleFilter>::New();
+    triangleFilter->SetInputData(triPolyData);
+    triangleFilter->Update();
+
+    return triangleFilter->GetOutput();
+}
\ No newline at end of file
diff --git a/isTriangulate.h b/isTriangulate.h
new file mode 100644
index 0000000..0c25de8
--- /dev/null
+++ b/isTriangulate.h
@@ -0,0 +1,9 @@
+#ifndef IS_TRIANGULATE_H // Vérification d'inclusion multiple
+#define IS_TRIANGULATE_H
+
+namespace triangulate
+{
+    vtkSmartPointer<vtkPolyData> buildValidTriangulation(vtkSmartPointer<vtkPolyData> polyData); // Prototype de la fonction
+}
+
+#endif // Fin de vérification d'inclusion multiple
diff --git a/main.cpp b/main.cpp
index 889dd4c..057a537 100644
--- a/main.cpp
+++ b/main.cpp
@@ -32,13 +32,16 @@
 #include <vtkExtractSurface.h>
 #include <ttkGeometrySmoother.h>
 
-
 #include <vtkDataSetSurfaceFilter.h>
 #include <ttkUtils.h>
 #include <vtkThresholdPoints.h>
 #include <vtkAppendPolyData.h>
 #include <vtkSortDataArray.h>
-int main(int argc, char* argv[]) {
+
+#include "isTriangulate.h"
+
+int main(int argc, char *argv[])
+{
   if (argc != 2)
   {
     std::cout << "Required arguments: Filename(.obj)" << std::endl;
@@ -48,128 +51,127 @@ int main(int argc, char* argv[]) {
   // Read the input file
   std::string filename = argv[1];
   vtkSmartPointer<vtkPolyData> source;
-  
+
   std::string extension = vtksys::SystemTools::GetFilenameLastExtension(filename);
   std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
-  
-  if(extension == ".obj")
+
+  if (extension == ".obj")
   {
     vtkNew<vtkOBJReader> reader;
     reader->SetFileName(filename.c_str());
     reader->Update();
-    source = reader->GetOutput();
+
+    source = triangulate::buildValidTriangulation(reader->GetOutput());
   }
   else
   {
     std::cout << "Required arguments: Filename(.obj)" << std::endl;
     return EXIT_FAILURE;
   }
- 
-  // Compute Max and Min curvature 
+
+  // Compute Max and Min curvature
   vtkSmartPointer<vtkCurvatures> maxCurvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();
   maxCurvaturesFilter->SetInputData(source);
   maxCurvaturesFilter->SetCurvatureTypeToMaximum(); // Set curvature type to maximum (k1)
   maxCurvaturesFilter->Update();
-  auto k1 = maxCurvaturesFilter->GetOutput();  
-  
+  auto k1 = maxCurvaturesFilter->GetOutput();
+
   vtkSmartPointer<vtkCurvatures> minCurvaturesFilter = vtkSmartPointer<vtkCurvatures>::New();
   minCurvaturesFilter->SetInputData(source);
   minCurvaturesFilter->SetCurvatureTypeToMinimum(); // Set curvature type to minimum (k2)
   minCurvaturesFilter->Update();
   auto k2 = minCurvaturesFilter->GetOutput();
-  
-  
-  // Shape Index computation 
+
+  // Shape Index computation
   k1->GetPointData()->SetActiveScalars("Maximum_Curvature");
-  auto k1Array = k1->GetPointData()->GetAbstractArray("Maximum_Curvature");  
+  auto k1Array = k1->GetPointData()->GetAbstractArray("Maximum_Curvature");
   k2->GetPointData()->SetActiveScalars("Minimum_Curvature");
-  auto k2Array = k2->GetPointData()->GetAbstractArray("Minimum_Curvature"); 
-  
+  auto k2Array = k2->GetPointData()->GetAbstractArray("Minimum_Curvature");
+
   vtkNew<vtkDoubleArray> shapeIndex;
   shapeIndex->SetName("Shape_Index");
-  
+
   for (vtkIdType i = 0; i < k1->GetNumberOfPoints(); ++i)
-  {  	
+  {
     double kmax = k1Array->GetVariantValue(i).ToDouble();
     double kmin = k2Array->GetVariantValue(i).ToDouble();
-    
-    if( kmax == kmin)
+
+    if (kmax == kmin)
     {
-      shapeIndex->InsertNextTuple1(0.5);    
+      shapeIndex->InsertNextTuple1(0.5);
     }
     else
     {
-      //double si = (2/M_PI)*atan((kmin+kmax)/(kmin-kmax)); //KOENDERIK ET VAN DOORN [-1,1]
-      double si = 0.5 - (1/M_PI)*atan((kmax+kmin)/(kmin-kmax)); // [0, 1]
-        
+      // double si = (2/M_PI)*atan((kmin+kmax)/(kmin-kmax)); //KOENDERIK ET VAN DOORN [-1,1]
+      double si = 0.5 - (1 / M_PI) * atan((kmax + kmin) / (kmin - kmax)); // [0, 1]
+
       shapeIndex->InsertNextTuple1(si);
     }
   }
   source->GetPointData()->AddArray(shapeIndex);
   source->GetPointData()->SetActiveScalars("Shape_Index");
-  
-/*  
-  double pourcent = 0.8;
-
-  // Create a vtkThresholdPoints filter for each threshold value
-  vtkNew<vtkThresholdPoints> threshold1;
-  threshold1->SetInputData(source);
-  threshold1->ThresholdBetween(0.0, 0.0 + pourcent*0.25); // Scalar values near 0
-  threshold1->Update();
-
-  vtkNew<vtkThresholdPoints> threshold2;
-  threshold2->SetInputData(source);
-  threshold2->ThresholdBetween(0.5 - pourcent*0.25, 0.5 + pourcent*0.25); // Scalar values near 1
-  threshold2->Update();
-
-  vtkNew<vtkThresholdPoints> threshold3;
-  threshold3->SetInputData(source);
-  threshold3->ThresholdBetween(1.0 - pourcent*0.25, 1.0); // Scalar values near 1
-  threshold3->Update();
-
-  // Create a vtkFTRGraph for each thresholded dataset
-  vtkNew<ttkFTRGraph> graph1;
-  graph1->SetInputData(threshold1->GetOutput());
-  graph1->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
-  graph1->Update();
-
-  vtkNew<ttkFTRGraph> graph2;
-  graph2->SetInputData(threshold2->GetOutput());
-  graph2->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
-  graph2->Update();
-
-  vtkNew<ttkFTRGraph> graph3;
-  graph3->SetInputData(threshold3->GetOutput());
-  graph3->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
-  graph3->Update();
-
-  // Merge the thresholded datasets together into a single polydata
-  vtkNew<vtkAppendPolyData> appendFilter;
-  appendFilter->AddInputData(threshold1->GetOutput());
-  appendFilter->AddInputData(threshold2->GetOutput());
-  appendFilter->AddInputData(threshold3->GetOutput());
-  appendFilter->Update();
-*/  
+
+  /*
+    double pourcent = 0.8;
+
+    // Create a vtkThresholdPoints filter for each threshold value
+    vtkNew<vtkThresholdPoints> threshold1;
+    threshold1->SetInputData(source);
+    threshold1->ThresholdBetween(0.0, 0.0 + pourcent*0.25); // Scalar values near 0
+    threshold1->Update();
+
+    vtkNew<vtkThresholdPoints> threshold2;
+    threshold2->SetInputData(source);
+    threshold2->ThresholdBetween(0.5 - pourcent*0.25, 0.5 + pourcent*0.25); // Scalar values near 1
+    threshold2->Update();
+
+    vtkNew<vtkThresholdPoints> threshold3;
+    threshold3->SetInputData(source);
+    threshold3->ThresholdBetween(1.0 - pourcent*0.25, 1.0); // Scalar values near 1
+    threshold3->Update();
+
+    // Create a vtkFTRGraph for each thresholded dataset
+    vtkNew<ttkFTRGraph> graph1;
+    graph1->SetInputData(threshold1->GetOutput());
+    graph1->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
+    graph1->Update();
+
+    vtkNew<ttkFTRGraph> graph2;
+    graph2->SetInputData(threshold2->GetOutput());
+    graph2->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
+    graph2->Update();
+
+    vtkNew<ttkFTRGraph> graph3;
+    graph3->SetInputData(threshold3->GetOutput());
+    graph3->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
+    graph3->Update();
+
+    // Merge the thresholded datasets together into a single polydata
+    vtkNew<vtkAppendPolyData> appendFilter;
+    appendFilter->AddInputData(threshold1->GetOutput());
+    appendFilter->AddInputData(threshold2->GetOutput());
+    appendFilter->AddInputData(threshold3->GetOutput());
+    appendFilter->Update();
+  */
 
   // Compute the Reeb Graph of the input dataset
   vtkNew<ttkFTRGraph> reebGraph;
-  //reebGraph->SetInputData(appendFilter->GetOutput()); // ttkFTRGraph for the merged polydata
+  // reebGraph->SetInputData(appendFilter->GetOutput()); // ttkFTRGraph for the merged polydata
   reebGraph->SetInputData(source);
   reebGraph->SetInputArrayToProcess(0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Shape_Index");
   reebGraph->Update();
 
-
   // Create Icospheres to represent nodes in the Reeb Graph
   vtkNew<ttkIcospheresFromPoints> ttkIcospheresFromPoints{};
   ttkIcospheresFromPoints->SetInputData(0, reebGraph->GetOutput());
   ttkIcospheresFromPoints->SetRadius(0.008);
-  ttkIcospheresFromPoints->SetNumberOfSubdivisions(1); 
+  ttkIcospheresFromPoints->SetNumberOfSubdivisions(1);
   ttkIcospheresFromPoints->Update();
 
   // Filters dependencies with Tubes : applies smooth to the geometry of the Reeb Graph
   vtkNew<ttkGeometrySmoother> ttkGeometrySmoother{};
   ttkGeometrySmoother->SetInputConnection(reebGraph->GetOutputPort(1));
-  ttkGeometrySmoother->Update(); 
+  ttkGeometrySmoother->Update();
 
   vtkNew<vtkGeometryFilter> geometryFilter{};
   geometryFilter->SetInputConnection(ttkGeometrySmoother->GetOutputPort());
@@ -180,12 +182,11 @@ int main(int argc, char* argv[]) {
 
   // Create Tubes to represent edges in the Reeb Graph
   vtkNew<vtkTubeFilter> tube{};
-  tube->SetInputData(polyData); //smoothed geometry of the Reeb graph
+  tube->SetInputData(polyData); // smoothed geometry of the Reeb graph
   tube->SetRadius(0.004);
-  //tube->SetNumberOfSides(1);
+  // tube->SetNumberOfSides(1);
   tube->Update();
 
-
   // Save the graph nodes with IcospheresFromPoints
   vtkNew<vtkXMLPolyDataWriter> writerNodes{};
   writerNodes->SetFileName("ReebGraphNodes.vtp");
@@ -210,20 +211,18 @@ int main(int argc, char* argv[]) {
   sWriter->SetInputConnection(reebGraph->GetOutputPort(0));
   sWriter->SetFileName("outputNodes.vtp");
   sWriter->Write();
-  
+
   // Save the graph edges
   vtkNew<vtkXMLUnstructuredGridWriter> sepWriter{};
   sepWriter->SetInputConnection(reebGraph->GetOutputPort(1));
   sepWriter->SetFileName("outputEdges.vtp");
   sepWriter->Write();
-  
+
   // Save the graph coloration
   vtkNew<vtkXMLPolyDataWriter> segWriter{};
   segWriter->SetInputConnection(reebGraph->GetOutputPort(2));
   segWriter->SetFileName("outputColor.vtp");
   segWriter->Write();*/
 
-  
   return EXIT_SUCCESS;
 }
-
-- 
GitLab