From 0bd6ea3d03c6c1d8d73c88748f1263a9da3f061a Mon Sep 17 00:00:00 2001
From: Julian Heinze <julian.heinze@ufz.de>
Date: Thu, 11 May 2023 09:37:06 +0200
Subject: [PATCH] Extract functions to create voxelgrid from mesh

Allowing to make the functions from Vtu2Grid visible
for accessing them in the DataExplorer.
---
 Applications/Utils/MeshEdit/Vtu2Grid.cpp      | 128 +-----------------
 .../MeshGenerators/VoxelGridFromMesh.cpp      | 117 ++++++++++++++++
 .../MeshGenerators/VoxelGridFromMesh.h        |  51 +++++++
 3 files changed, 175 insertions(+), 121 deletions(-)
 create mode 100644 MeshToolsLib/MeshGenerators/VoxelGridFromMesh.cpp
 create mode 100644 MeshToolsLib/MeshGenerators/VoxelGridFromMesh.h

diff --git a/Applications/Utils/MeshEdit/Vtu2Grid.cpp b/Applications/Utils/MeshEdit/Vtu2Grid.cpp
index e25412b662a..15ef9f3ce36 100644
--- a/Applications/Utils/MeshEdit/Vtu2Grid.cpp
+++ b/Applications/Utils/MeshEdit/Vtu2Grid.cpp
@@ -8,132 +8,17 @@
  */
 
 #include <tclap/CmdLine.h>
-#include <vtkAbstractArray.h>
-#include <vtkCellData.h>
-#include <vtkCellLocator.h>
-#include <vtkDataArray.h>
-#include <vtkDoubleArray.h>
-#include <vtkIntArray.h>
-#include <vtkSmartPointer.h>
-#include <vtkUnstructuredGrid.h>
-#include <vtkXMLUnstructuredGridReader.h>
-
-#include "InfoLib/GitInfo.h"
+
 #include "MeshLib/IO/writeMeshToFile.h"
 #include "MeshLib/Mesh.h"
 #include "MeshLib/MeshSearch/ElementSearch.h"
 #include "MeshToolsLib/MeshEditing/RemoveMeshComponents.h"
 #include "MeshToolsLib/MeshGenerators/MeshGenerator.h"
+#include "MeshToolsLib/MeshGenerators/VoxelGridFromMesh.h"
 
 #ifdef USE_PETSC
 #include <mpi.h>
 #endif
-
-std::string const cell_id_name = "CellIds";
-
-std::array<std::size_t, 3> getDimensions(MathLib::Point3d const& min,
-                                         MathLib::Point3d const& max,
-                                         std::array<double, 3> const& cellsize)
-{
-    return {
-        static_cast<std::size_t>(std::ceil((max[0] - min[0]) / cellsize[0])),
-        static_cast<std::size_t>(std::ceil((max[1] - min[1]) / cellsize[1])),
-        static_cast<std::size_t>(std::ceil((max[2] - min[2]) / cellsize[2]))};
-}
-
-std::vector<int> assignCellIds(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
-                               MathLib::Point3d const& min,
-                               std::array<std::size_t, 3> const& dims,
-                               std::array<double, 3> const& cellsize)
-{
-    vtkSmartPointer<vtkCellLocator> locator =
-        vtkSmartPointer<vtkCellLocator>::New();
-    locator->SetDataSet(mesh);
-    locator->Update();
-
-    std::vector<int> cell_ids;
-    cell_ids.reserve(dims[0] * dims[1] * dims[2]);
-    std::array<double, 3> const grid_max = {min[0] + dims[0] * cellsize[0],
-                                            min[1] + dims[1] * cellsize[1],
-                                            min[2] + dims[2] * cellsize[2]};
-    for (double k = min[2] + (cellsize[2] / 2.0); k < grid_max[2];
-         k += cellsize[2])
-    {
-        for (double j = min[1] + (cellsize[1] / 2.0); j < grid_max[1];
-             j += cellsize[1])
-        {
-            for (double i = min[0] + (cellsize[0] / 2.0); i < grid_max[0];
-                 i += cellsize[0])
-            {
-                double pnt[3] = {i, j, k};
-                cell_ids.push_back(static_cast<int>(locator->FindCell(pnt)));
-            }
-        }
-    }
-    return cell_ids;
-}
-
-bool removeUnusedGridCells(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
-                           std::unique_ptr<MeshLib::Mesh>& grid)
-{
-    MeshLib::ElementSearch search(*grid);
-    std::size_t const n_elems_marked = search.searchByPropertyValueRange<int>(
-        cell_id_name, 0, static_cast<int>(mesh->GetNumberOfCells()), true);
-
-    if (n_elems_marked == grid->getNumberOfElements())
-    {
-        ERR("No valid elements found. Aborting...");
-        return false;
-    }
-
-    if (n_elems_marked)
-    {
-        grid.reset(MeshToolsLib::removeElements(
-            *grid, search.getSearchedElementIDs(), "trimmed_grid"));
-    }
-    return true;
-}
-
-template <typename T, typename VTK_TYPE>
-void mapArray(MeshLib::Mesh& grid, VTK_TYPE vtk_arr, std::string const& name)
-{
-    MeshLib::PropertyVector<int> const& cell_ids =
-        *grid.getProperties().getPropertyVector<int>(
-            cell_id_name, MeshLib::MeshItemType::Cell, 1);
-    std::vector<T>& arr = *grid.getProperties().createNewPropertyVector<T>(
-        name, MeshLib::MeshItemType::Cell, vtk_arr->GetNumberOfComponents());
-    std::size_t const n_elems = cell_ids.size();
-    arr.resize(n_elems);
-    for (std::size_t j = 0; j < n_elems; ++j)
-        arr[j] = vtk_arr->GetValue(cell_ids[j]);
-}
-
-void mapMeshArraysOntoGrid(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
-                           std::unique_ptr<MeshLib::Mesh>& grid)
-{
-    vtkSmartPointer<vtkCellData> const cell_data = mesh->GetCellData();
-    for (int i = 0; i < cell_data->GetNumberOfArrays(); ++i)
-    {
-        std::string const& name = cell_data->GetArrayName(i);
-        vtkSmartPointer<vtkDoubleArray> const dbl_arr =
-            dynamic_cast<vtkDoubleArray*>(cell_data->GetArray(name.c_str()));
-        if (dbl_arr)
-        {
-            mapArray<double, vtkSmartPointer<vtkDoubleArray>>(*grid, dbl_arr,
-                                                              name);
-            continue;
-        }
-        vtkSmartPointer<vtkIntArray> const int_arr =
-            dynamic_cast<vtkIntArray*>(cell_data->GetArray(name.c_str()));
-        if (int_arr)
-        {
-            mapArray<int, vtkSmartPointer<vtkIntArray>>(*grid, int_arr, name);
-            continue;
-        }
-        WARN("Ignoring array '{:s}', array type not implemented...", name);
-    }
-}
-
 int main(int argc, char* argv[])
 {
     TCLAP::CmdLine cmd(
@@ -191,6 +76,7 @@ int main(int argc, char* argv[])
 #endif
         return -1;
     }
+    using namespace MeshLib::MeshGenerator;
 
     double const x_size = x_arg.getValue();
     double const y_size = (y_arg.isSet()) ? y_arg.getValue() : x_arg.getValue();
@@ -208,19 +94,19 @@ int main(int argc, char* argv[])
         std::array<double, 3>{bounds[0], bounds[2], bounds[4]});
     MathLib::Point3d const max(
         std::array<double, 3>{bounds[1], bounds[3], bounds[5]});
-    std::array<std::size_t, 3> const dims = getDimensions(min, max, cellsize);
+    std::array<std::size_t, 3> const dims = VoxelGridFromMesh::getDimensions(min, max, cellsize);
     std::unique_ptr<MeshLib::Mesh> grid(
         MeshToolsLib::MeshGenerator::generateRegularHexMesh(
             dims[0], dims[1], dims[2], cellsize[0], cellsize[1], cellsize[2],
             min, "grid"));
 
-    std::vector<int> const tmp_ids = assignCellIds(mesh, min, dims, cellsize);
+    std::vector<int> const tmp_ids = VoxelGridFromMesh::assignCellIds(mesh, min, dims, cellsize);
     std::vector<int>& cell_ids =
         *grid->getProperties().createNewPropertyVector<int>(
             cell_id_name, MeshLib::MeshItemType::Cell, 1);
     std::copy(tmp_ids.cbegin(), tmp_ids.cend(), std::back_inserter(cell_ids));
 
-    if (!removeUnusedGridCells(mesh, grid))
+    if (!VoxelGridFromMesh::removeUnusedGridCells(mesh, grid))
     {
 #ifdef USE_PETSC
         MPI_Finalize();
@@ -228,7 +114,7 @@ int main(int argc, char* argv[])
         return EXIT_FAILURE;
     }
 
-    mapMeshArraysOntoGrid(mesh, grid);
+    VoxelGridFromMesh::mapMeshArraysOntoGrid(mesh, grid);
 
     if (MeshLib::IO::writeMeshToFile(*grid, output_arg.getValue()) != 0)
     {
diff --git a/MeshToolsLib/MeshGenerators/VoxelGridFromMesh.cpp b/MeshToolsLib/MeshGenerators/VoxelGridFromMesh.cpp
new file mode 100644
index 00000000000..c2c9946edc8
--- /dev/null
+++ b/MeshToolsLib/MeshGenerators/VoxelGridFromMesh.cpp
@@ -0,0 +1,117 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "VoxelGridFromMesh.h"
+
+namespace MeshLib::MeshGenerator::VoxelGridFromMesh
+{
+
+std::array<std::size_t, 3> getDimensions(MathLib::Point3d const& min,
+                                         MathLib::Point3d const& max,
+                                         std::array<double, 3> const& cellsize)
+{
+    return {
+        static_cast<std::size_t>(std::ceil((max[0] - min[0]) / cellsize[0])),
+        static_cast<std::size_t>(std::ceil((max[1] - min[1]) / cellsize[1])),
+        static_cast<std::size_t>(std::ceil((max[2] - min[2]) / cellsize[2]))};
+}
+
+std::vector<int> assignCellIds(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
+                               MathLib::Point3d const& min,
+                               std::array<std::size_t, 3> const& dims,
+                               std::array<double, 3> const& cellsize)
+{
+    vtkSmartPointer<vtkCellLocator> locator =
+        vtkSmartPointer<vtkCellLocator>::New();
+    locator->SetDataSet(mesh);
+    locator->Update();
+
+    std::vector<int> cell_ids;
+    cell_ids.reserve(dims[0] * dims[1] * dims[2]);
+    std::array<double, 3> const grid_max = {min[0] + dims[0] * cellsize[0],
+                                            min[1] + dims[1] * cellsize[1],
+                                            min[2] + dims[2] * cellsize[2]};
+    for (double k = min[2] + (cellsize[2] / 2.0); k < grid_max[2];
+         k += cellsize[2])
+    {
+        for (double j = min[1] + (cellsize[1] / 2.0); j < grid_max[1];
+             j += cellsize[1])
+        {
+            for (double i = min[0] + (cellsize[0] / 2.0); i < grid_max[0];
+                 i += cellsize[0])
+            {
+                double pnt[3] = {i, j, k};
+                cell_ids.push_back(static_cast<int>(locator->FindCell(pnt)));
+            }
+        }
+    }
+    return cell_ids;
+}
+
+bool removeUnusedGridCells(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
+                           std::unique_ptr<MeshLib::Mesh>& grid)
+{
+    MeshLib::ElementSearch search(*grid);
+    std::size_t const n_elems_marked = search.searchByPropertyValueRange<int>(
+        cell_id_name, 0, static_cast<int>(mesh->GetNumberOfCells()), true);
+
+    if (n_elems_marked == grid->getNumberOfElements())
+    {
+        ERR("No valid elements found. Aborting...");
+        return false;
+    }
+
+    if (n_elems_marked)
+    {
+        grid.reset(MeshLib::removeElements(
+            *grid, search.getSearchedElementIDs(), "trimmed_grid"));
+    }
+    return true;
+}
+
+template <typename T, typename VTK_TYPE>
+void mapArray(MeshLib::Mesh& grid, VTK_TYPE vtk_arr, std::string const& name)
+{
+    MeshLib::PropertyVector<int> const& cell_ids =
+        *grid.getProperties().getPropertyVector<int>(
+            cell_id_name, MeshLib::MeshItemType::Cell, 1);
+    std::vector<T>& arr = *grid.getProperties().createNewPropertyVector<T>(
+        name, MeshLib::MeshItemType::Cell, vtk_arr->GetNumberOfComponents());
+    std::size_t const n_elems = cell_ids.size();
+    arr.resize(n_elems);
+    for (std::size_t j = 0; j < n_elems; ++j)
+        arr[j] = vtk_arr->GetValue(cell_ids[j]);
+}
+
+void mapMeshArraysOntoGrid(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
+                           std::unique_ptr<MeshLib::Mesh>& grid)
+{
+    vtkSmartPointer<vtkCellData> const cell_data = mesh->GetCellData();
+    for (int i = 0; i < cell_data->GetNumberOfArrays(); ++i)
+    {
+        std::string const& name = cell_data->GetArrayName(i);
+        vtkSmartPointer<vtkDoubleArray> const dbl_arr =
+            dynamic_cast<vtkDoubleArray*>(cell_data->GetArray(name.c_str()));
+        if (dbl_arr)
+        {
+            mapArray<double, vtkSmartPointer<vtkDoubleArray>>(*grid, dbl_arr,
+                                                              name);
+            continue;
+        }
+        vtkSmartPointer<vtkIntArray> const int_arr =
+            dynamic_cast<vtkIntArray*>(cell_data->GetArray(name.c_str()));
+        if (int_arr)
+        {
+            mapArray<int, vtkSmartPointer<vtkIntArray>>(*grid, int_arr, name);
+            continue;
+        }
+        WARN("Ignoring array '{:s}', array type not implemented...", name);
+    }
+}
+}  // namespace MeshLib::MeshGenerator::VoxelGridFromMesh
\ No newline at end of file
diff --git a/MeshToolsLib/MeshGenerators/VoxelGridFromMesh.h b/MeshToolsLib/MeshGenerators/VoxelGridFromMesh.h
new file mode 100644
index 00000000000..f62acdc37f1
--- /dev/null
+++ b/MeshToolsLib/MeshGenerators/VoxelGridFromMesh.h
@@ -0,0 +1,51 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include <vtkAbstractArray.h>
+#include <vtkCellData.h>
+#include <vtkCellLocator.h>
+#include <vtkDataArray.h>
+#include <vtkDoubleArray.h>
+#include <vtkIntArray.h>
+#include <vtkSmartPointer.h>
+#include <vtkUnstructuredGrid.h>
+#include <vtkXMLUnstructuredGridReader.h>
+
+#include "InfoLib/GitInfo.h"
+#include "MeshLib/Mesh.h"
+#include "MeshLib/MeshEditing/RemoveMeshComponents.h"
+#include "MeshLib/MeshGenerators/MeshGenerator.h"
+#include "MeshLib/MeshSearch/ElementSearch.h"
+#include "MeshLib/MeshSearch/MeshElementGrid.h"
+
+static constexpr std::string const cell_id_name = "CellIds";
+
+namespace MeshLib::MeshGenerator::VoxelGridFromMesh
+{
+
+    std::array<std::size_t, 3> getDimensions(
+        MathLib::Point3d const& min,
+        MathLib::Point3d const& max,
+        std::array<double, 3> const& cellsize);
+
+    std::vector<int> assignCellIds(
+        vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
+        MathLib::Point3d const& min,
+        std::array<std::size_t, 3> const& dims,
+        std::array<double, 3> const& cellsize);
+
+    bool removeUnusedGridCells(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
+                               std::unique_ptr<MeshLib::Mesh>& grid);
+
+    void mapMeshArraysOntoGrid(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
+                               std::unique_ptr<MeshLib::Mesh>& grid);
+};
\ No newline at end of file
-- 
GitLab