OGS
VoxelGridFromMesh.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "VoxelGridFromMesh.h"
5
6#include <vtkAbstractArray.h>
7#include <vtkCellData.h>
8#include <vtkCellLocator.h>
9#include <vtkDataArray.h>
10#include <vtkDoubleArray.h>
11#include <vtkIntArray.h>
12#include <vtkLongLongArray.h>
13
14#include <cassert>
15#include <cmath>
16
17#include "InfoLib/GitInfo.h"
18#include "MathLib/Point3d.h"
23
25{
26std::array<std::size_t, 3> getNumberOfVoxelPerDimension(
27 std::array<double, 3> const& ranges, std::array<double, 3> const& cellsize)
28{
29 if (cellsize[0] <= 0 || cellsize[1] <= 0 || cellsize[2] <= 0)
30 {
31 OGS_FATAL("A cellsize ({},{},{}) is not allowed to be <= 0",
32 cellsize[0], cellsize[1], cellsize[2]);
33 }
34 std::array<double, 3> numberOfVoxel = {ranges[0] / cellsize[0],
35 ranges[1] / cellsize[1],
36 ranges[2] / cellsize[2]};
37
38 if (ranges[0] < 0 || ranges[1] < 0 || ranges[2] < 0)
39 {
41 "The difference of max-min ({},{},{}) is not allowed to be < 0",
42 ranges[0], ranges[1], ranges[2]);
43 }
44 std::replace(numberOfVoxel.begin(), numberOfVoxel.end(), 0, 1);
45
46 return {static_cast<std::size_t>(std::lround(numberOfVoxel[0])),
47 static_cast<std::size_t>(std::lround(numberOfVoxel[1])),
48 static_cast<std::size_t>(std::lround(numberOfVoxel[2]))};
49}
50
51std::vector<int> assignCellIds(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
52 MathLib::Point3d const& min,
53 std::array<std::size_t, 3> const& dims,
54 std::array<double, 3> const& cellsize)
55{
56 vtkSmartPointer<vtkCellLocator> locator =
57 vtkSmartPointer<vtkCellLocator>::New();
58 locator->SetDataSet(mesh);
59 locator->Update();
60
61 std::vector<int> cell_ids;
62 cell_ids.reserve(dims[0] * dims[1] * dims[2]);
63 std::array<double, 3> const grid_max = {min[0] + dims[0] * cellsize[0],
64 min[1] + dims[1] * cellsize[1],
65 min[2] + dims[2] * cellsize[2]};
66
67 double const start[3] = {min[0] + cellsize[0] / 2.,
68 min[1] + cellsize[1] / 2.,
69 min[2] + cellsize[2] / 2.};
70 double pnt[3];
71 for (pnt[2] = start[2]; pnt[2] < grid_max[2]; pnt[2] += cellsize[2])
72 {
73 for (pnt[1] = start[1]; pnt[1] < grid_max[1]; pnt[1] += cellsize[1])
74 {
75 for (pnt[0] = start[0]; pnt[0] < grid_max[0]; pnt[0] += cellsize[0])
76 {
77 cell_ids.push_back(static_cast<int>(locator->FindCell(pnt)));
78 }
79 }
80 }
81 return cell_ids;
82}
83
84bool removeUnusedGridCells(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
85 std::unique_ptr<MeshLib::Mesh>& grid)
86{
87 MeshLib::ElementSearch search(*grid);
88 std::size_t const n_elems_marked = search.searchByPropertyValueRange<int>(
89 cell_id_name, 0, static_cast<int>(mesh->GetNumberOfCells()), true);
90
91 if (n_elems_marked == grid->getNumberOfElements())
92 {
93 ERR("No valid elements found. Aborting...");
94 return false;
95 }
96
97 if (n_elems_marked)
98 {
100 *grid, search.getSearchedElementIDs(), "trimmed_grid"));
101 }
102 return true;
103}
104
105// PropertyVector is required to contain parameter cell_id_name
106template <typename T, typename VTK_TYPE>
107void mapArray(MeshLib::Mesh& grid, VTK_TYPE vtk_arr, std::string const& name)
108{
109 auto const* cell_ids = grid.getProperties().getPropertyVector<int>(
111 if (cell_ids == nullptr)
112 {
113 // Error message
114 return;
115 }
116 std::size_t const n_elems = cell_ids->size();
117 auto& arr = *grid.getProperties().createNewPropertyVector<T>(
118 name, MeshLib::MeshItemType::Cell, n_elems,
119 vtk_arr->GetNumberOfComponents());
120 for (std::size_t j = 0; j < n_elems; ++j)
121 {
122 arr[j] = vtk_arr->GetValue((*cell_ids)[j]);
123 }
124}
125
126template <typename T>
127// check whether dynamic_cast of cell data is possible the type of cell data to
128// map them on voxelgrid
130 vtkSmartPointer<vtkCellData> const cell_data,
131 char const* const name)
132{
133 using DataArrayType = vtkAOSDataArrayTemplate<T>;
134 vtkSmartPointer<DataArrayType> const arr =
135 dynamic_cast<DataArrayType*>(cell_data->GetArray(name));
136 if (!arr)
137 {
138 return false;
139 }
141 return true;
142}
143
144void mapMeshArraysOntoGrid(vtkSmartPointer<vtkUnstructuredGrid> const& mesh,
145 std::unique_ptr<MeshLib::Mesh> const& grid)
146{
147 assert(mesh != nullptr);
148 assert(grid != nullptr);
149 vtkSmartPointer<vtkCellData> const cell_data = mesh->GetCellData();
150 for (int i = 0; i < cell_data->GetNumberOfArrays(); ++i)
151 {
152 auto const name = cell_data->GetArrayName(i);
153
154 if (!(checkDyncast<double>(*grid, cell_data, name) ||
155 checkDyncast<long>(*grid, cell_data, name) ||
156 checkDyncast<long long>(*grid, cell_data, name) ||
157 checkDyncast<int>(*grid, cell_data, name)))
158 {
159 WARN("Ignoring array '{:s}', array type {:s} not implemented...",
160 name,
161 cell_data->GetArray(name)->GetDataTypeAsString());
162 }
163 }
164}
165} // namespace MeshToolsLib::MeshGenerator::VoxelGridFromMesh
#define OGS_FATAL(...)
Definition Error.h:19
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:34
Element search class.
const std::vector< std::size_t > & getSearchedElementIDs() const
return marked elements
std::size_t searchByPropertyValueRange(std::string const &property_name, PROPERTY_TYPE const min_property_value, PROPERTY_TYPE const max_property_value, bool outside_of)
Properties & getProperties()
Definition Mesh.h:125
PropertyVector< T > * createNewPropertyVector(std::string_view name, MeshItemType mesh_item_type, std::size_t n_components=1)
PropertyVector< T > const * getPropertyVector(std::string_view name) const
constexpr std::size_t size() const
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)
void mapArray(MeshLib::Mesh &grid, VTK_TYPE vtk_arr, std::string const &name)
void mapMeshArraysOntoGrid(vtkSmartPointer< vtkUnstructuredGrid > const &mesh, std::unique_ptr< MeshLib::Mesh > const &grid)
bool removeUnusedGridCells(vtkSmartPointer< vtkUnstructuredGrid > const &mesh, std::unique_ptr< MeshLib::Mesh > &grid)
bool checkDyncast(MeshLib::Mesh &mesh, vtkSmartPointer< vtkCellData > const cell_data, char const *const name)
std::array< std::size_t, 3 > getNumberOfVoxelPerDimension(std::array< double, 3 > const &ranges, std::array< double, 3 > const &cellsize)
MeshLib::Mesh * removeElements(const MeshLib::Mesh &mesh, const std::vector< std::size_t > &removed_element_ids, const std::string &new_mesh_name)