OGS
Vtu2GridDialog.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 "Vtu2GridDialog.h"
5
6#include <vtkXMLUnstructuredGridWriter.h>
7
8#include <QStringList>
9#include <QStringListModel>
10#include <optional>
11#include <string>
12
13#include "Base/OGSError.h"
15#include "GeoLib/AABB.h"
17#include "MeshLib/Mesh.h"
18#include "MeshLib/Node.h"
20#include "MeshModel.h"
23
24Vtu2GridDialog::Vtu2GridDialog(MeshModel& mesh_model, QDialog* parent)
25 : QDialog(parent), _mesh_model(mesh_model)
26{
27 setupUi(this);
28 QStringList MeshList;
29
30 for (int model_index = 0; model_index < mesh_model.rowCount();
31 ++model_index)
32 {
33 auto const* mesh = mesh_model.getMesh(mesh_model.index(model_index, 0));
34 MeshList.append(QString::fromStdString(mesh->getName()));
35 }
36
37 if (MeshList.empty())
38 {
39 MeshList.append("[No Mesh available.]");
40 this->expectedVoxelLabel->setText(
41 "Expected number of voxels: undefined");
42 }
43
44 _allMeshes.setStringList(MeshList);
45 this->meshListBox->addItems(_allMeshes.stringList());
46 this->xlineEdit->setFocus();
47}
48
49std::optional<std::array<double, 3>> fillXYZ(QString xin, QString yin,
50 QString zin)
51{
52 bool ok;
53 if (!xin.toDouble(&ok))
54 {
55 return std::nullopt;
56 }
57 double const xinput = xin.toDouble();
58 double const yinput = (yin.toDouble(&ok)) ? yin.toDouble() : xinput;
59 double const zinput = (zin.toDouble(&ok)) ? zin.toDouble() : xinput;
60
61 if (xinput <= 0 || yinput <= 0 || zinput <= 0)
62 {
63 return std::nullopt;
64 }
65
66 return std::optional<std::array<double, 3>>{{xinput, yinput, zinput}};
67}
68
69Eigen::Vector3d getMeshExtent(MeshLib::Mesh const* _mesh)
70{
71 auto const& nodes = _mesh->getNodes();
72 GeoLib::AABB const aabb(nodes.cbegin(), nodes.cend());
73 auto const& min = aabb.getMinPoint();
74 auto const& max = aabb.getMaxPoint();
75 return max - min;
76}
77
79{
80 if (_allMeshes.stringList()[0] == "[No Mesh available.]")
81 {
82 this->expectedVoxelLabel->setText("approximated Voxel: undefined");
83 return;
84 }
85
86 auto const opt_xyz =
87 fillXYZ(this->xlineEdit->text(), this->ylineEdit->text(),
88 this->zlineEdit->text());
89
90 if (!opt_xyz)
91 {
92 this->expectedVoxelLabel->setText("approximated Voxel: undefined");
93 return;
94 }
95
96 auto const delta = getMeshExtent(
97 _mesh_model.getMesh(this->meshListBox->currentText().toStdString()));
98 double const expected_voxel = (delta[0]) * (delta[1]) * (delta[2]) /
99 (*opt_xyz)[0] / (*opt_xyz)[1] / (*opt_xyz)[2];
100
101 int const exponent = std::floor(std::log10(std::abs(expected_voxel)));
102 this->expectedVoxelLabel->setText(
103 "approximated Voxel = " +
104 QString::number(std::round(expected_voxel / std::pow(10, exponent))) +
105 " x 10^" + QString::number(exponent));
106}
107
112
117
122
124{
125 using namespace MeshToolsLib::MeshGenerator;
126 if (this->meshListBox->currentText().toStdString() ==
127 "[No Mesh available.]")
128 {
130 "Please specify the input meshes. It has to be a 3D mesh.");
131 return;
132 }
133
134 auto cellsize = fillXYZ(this->xlineEdit->text(), this->ylineEdit->text(),
135 this->zlineEdit->text());
136
137 if (!cellsize)
138 {
140 "At least the x-length of a voxel must be specified and > 0.\n If "
141 "y-/z-input "
142 "are not specified, equal to 0, or not a real number, they are "
143 "treated as "
144 "the x-input.");
145 }
146 auto _mesh(
147 _mesh_model.getMesh(this->meshListBox->currentText().toStdString()));
148
149 if (_mesh->MeshLib::Mesh::getDimension() < 3)
150 {
151 OGSError::box("The dimension of the mesh has to be 3.");
152 return;
153 }
154
155 vtkNew<MeshLib::VtkMappedMeshSource> vtkSource;
156 vtkSource->SetMesh(_mesh);
157 vtkSource->Update();
158 vtkSmartPointer<vtkUnstructuredGrid> mesh = vtkSource->GetOutput();
159
160 double* const bounds = mesh->GetBounds();
161 MathLib::Point3d const min(
162 std::array<double, 3>{bounds[0], bounds[2], bounds[4]});
163 MathLib::Point3d const max(
164 std::array<double, 3>{bounds[1], bounds[3], bounds[5]});
165 std::array<double, 3> ranges = {max[0] - min[0], max[1] - min[1],
166 max[2] - min[2]};
167 if (ranges[0] < 0 || ranges[1] < 0 || ranges[2] < 0)
168 {
170 "The range (max-min of the bounding box) is not allowed to be < 0");
171 }
172 std::array<std::size_t, 3> const dims =
174 std::unique_ptr<MeshLib::Mesh> grid(
175 generateRegularHexMesh(dims[0], dims[1], dims[2], (*cellsize)[0],
176 (*cellsize)[1], (*cellsize)[2], min, "grid"));
177 if (grid == nullptr)
178 {
179 OGSError::box(QString::fromStdString(
180 fmt::format("Could not generate regular hex mesh. With "
181 "parameters dims={} {} {}, cellsize={} {} {}",
182 dims[0], dims[1], dims[2], (*cellsize)[0],
183 (*cellsize)[1], (*cellsize)[2])));
184 }
185
187 grid->getProperties().createNewPropertyVector<int>(
189 if (cell_ids == nullptr)
190 {
191 OGSError::box("Could not create cell ids.");
192 }
193 cell_ids->assign(
194 VoxelGridFromMesh::assignCellIds(mesh, min, dims, *cellsize));
196 {
197 return;
198 }
199
201
202 if (grid == nullptr)
203 {
204 OGSError::box("No voxelgrid could be created from the mesh.");
205 return;
206 }
207
208 _mesh_model.addMesh(grid.release());
209 this->done(QDialog::Accepted);
210}
std::optional< std::array< double, 3 > > fillXYZ(QString xin, QString yin, QString zin)
Eigen::Vector3d getMeshExtent(MeshLib::Mesh const *_mesh)
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
Definition AABB.h:45
Eigen::Vector3d const & getMaxPoint() const
Definition AABB.h:176
Eigen::Vector3d const & getMinPoint() const
Definition AABB.h:169
std::vector< Node * > const & getNodes() const
Get the nodes-vector for the mesh.
Definition Mesh.h:97
constexpr void assign(R &&r)
const MeshLib::Mesh * getMesh(const QModelIndex &idx) const
Returns the mesh with the given index.
Definition MeshModel.cpp:85
static void box(const QString &e)
Definition OGSError.cpp:13
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition TreeModel.cpp:93
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition TreeModel.cpp:39
void on_xlineEdit_textChanged()
Vtu2GridDialog(MeshModel &mesh_model, QDialog *parent=nullptr)
void on_zlineEdit_textChanged()
void updateExpectedVoxel()
As the x/y/z input changes an estimation of the expected Voxel is given.
MeshModel & _mesh_model
void on_ylineEdit_textChanged()
void accept() override
Instructions if the OK-Button has been pressed.
QStringListModel _allMeshes
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 mapMeshArraysOntoGrid(vtkSmartPointer< vtkUnstructuredGrid > const &mesh, std::unique_ptr< MeshLib::Mesh > const &grid)
bool removeUnusedGridCells(vtkSmartPointer< vtkUnstructuredGrid > const &mesh, std::unique_ptr< MeshLib::Mesh > &grid)
std::array< std::size_t, 3 > getNumberOfVoxelPerDimension(std::array< double, 3 > const &ranges, std::array< double, 3 > const &cellsize)
MeshLib::Mesh * generateRegularHexMesh(const BaseLib::ISubdivision &div_x, const BaseLib::ISubdivision &div_y, const BaseLib::ISubdivision &div_z, MathLib::Point3d const &origin=MathLib::ORIGIN, std::string const &mesh_name="mesh")