OGS
MeshView.cpp
Go to the documentation of this file.
1
15#include "MeshView.h"
16
17#include <QContextMenuEvent>
18#include <QFileDialog>
19#include <QHeaderView>
20#include <QMenu>
21#include <QObject>
22#include <QSettings>
23#include <memory>
24
31#include "Base/OGSError.h"
32#include "MeshItem.h"
33#include "MeshLayerEditDialog.h"
34#include "MeshLib/Mesh.h"
38#include "MeshLib/Node.h"
39#include "MeshMapping2DDialog.h"
40#include "MeshModel.h"
41#include "MeshValueEditDialog.h"
43#include "SaveMeshDialog.h"
45
46MeshView::MeshView(QWidget* parent /*= 0*/) : QTreeView(parent)
47{
48 setUniformRowHeights(true);
49 // resizeColumnsToContents();
50 // resizeRowsToContents();
51}
52
53MeshView::~MeshView() = default;
54
56{
57 setAlternatingRowColors(true);
58 setColumnWidth(0, 150);
59 std::size_t nColumns =
60 (this->model() != nullptr) ? this->model()->columnCount() : 0;
61 for (std::size_t i = 1; i < nColumns; i++)
62 {
63 resizeColumnToContents(i);
64 }
65}
66
67void MeshView::selectionChanged(const QItemSelection& selected,
68 const QItemSelection& deselected)
69{
70 Q_UNUSED(deselected);
71 if (!selected.isEmpty())
72 {
74 const QModelIndex idx = *(selected.indexes().begin());
75 const TreeItem* tree_item =
76 static_cast<TreeModel*>(this->model())->getItem(idx);
77
78 const auto* list_item = dynamic_cast<const MeshItem*>(tree_item);
79 if (list_item)
80 {
81 emit enableSaveButton(true);
82 emit enableRemoveButton(true);
83 emit meshSelected(*list_item->getMesh());
84 }
85 else
86 {
87 emit enableSaveButton(false);
88 emit enableRemoveButton(false);
89 emit elementSelected(
90 dynamic_cast<const MeshItem*>(tree_item->parentItem())
91 ->vtkSource(),
92 static_cast<unsigned>(tree_item->row()), true);
93 }
94 }
95}
96
98{
100}
101
103{
104 QModelIndex index(this->selectionModel()->currentIndex());
105 if (!index.isValid())
106 {
107 OGSError::box("No mesh selected.");
108 }
109 else
110 {
111 emit requestMeshRemoval(index);
112 emit enableSaveButton(false);
113 emit enableRemoveButton(false);
114 }
115}
116
117void MeshView::contextMenuEvent(QContextMenuEvent* event)
118{
119 QModelIndex const& index = this->selectionModel()->currentIndex();
120 MeshItem const* const item = dynamic_cast<MeshItem*>(
121 static_cast<TreeItem*>(index.internalPointer()));
122
123 if (item == nullptr)
124 {
125 return;
126 }
127
128 unsigned const mesh_dim(item->getMesh()->getDimension());
129
130 std::vector<MeshAction> actions;
131 actions.push_back({new QAction("Map mesh...", this), 1, 2});
132 connect(actions.back().action, SIGNAL(triggered()), this,
133 SLOT(openMap2dMeshDialog()));
134 actions.push_back(
135 {new QAction("Assign raster data to mesh...", this), 1, 2});
136 connect(actions.back().action, SIGNAL(triggered()), this,
138 actions.push_back({new QAction("Edit mesh...", this), 2, 3});
139 connect(actions.back().action, SIGNAL(triggered()), this,
140 SLOT(openMeshEditDialog()));
141 actions.push_back({new QAction("Add layer...", this), 1, 3});
142 connect(actions.back().action, SIGNAL(triggered()), this,
143 SLOT(openAddLayerDialog()));
144 actions.push_back({new QAction("Edit material groups...", this), 1, 3});
145 connect(actions.back().action, SIGNAL(triggered()), this,
146 SLOT(openValuesEditDialog()));
147 actions.push_back({new QAction("Extract surface...", this), 3, 3});
148 connect(actions.back().action, SIGNAL(triggered()), this,
149 SLOT(extractSurfaceMesh()));
150 actions.push_back(
151 {new QAction("Calculate element quality...", this), 2, 3});
152 connect(actions.back().action, SIGNAL(triggered()), this,
153 SLOT(checkMeshQuality()));
154 actions.push_back({new QAction("Convert to geometry", this), 1, 2});
155 connect(actions.back().action, SIGNAL(triggered()), this,
156 SLOT(convertMeshToGeometry()));
157 actions.push_back({new QAction("Export to Shapefile...", this), 2, 2});
158 connect(actions.back().action, SIGNAL(triggered()), this,
159 SLOT(exportToShapefile()));
160 actions.push_back({new QAction("Export to TetGen...", this), 3, 3});
161 connect(actions.back().action, SIGNAL(triggered()), this,
162 SLOT(exportToTetGen()));
163
164 QMenu menu(this);
165 for (MeshAction a : actions)
166 {
167 if (mesh_dim >= a.min_dim && mesh_dim <= a.max_dim)
168 {
169 menu.addAction(a.action);
170 }
171 }
172 menu.exec(event->globalPos());
173}
174
176{
177 MeshModel const* const model = static_cast<MeshModel*>(this->model());
178 QModelIndex const index = this->selectionModel()->currentIndex();
179 MeshLib::Mesh const* const mesh = model->getMesh(index);
180 if (mesh == nullptr)
181 {
182 return;
183 }
184
186 if (dlg.exec() != QDialog::Accepted)
187 {
188 return;
189 }
190
191 auto result = std::make_unique<MeshLib::Mesh>(*mesh);
192 result->setName(dlg.getNewMeshName());
193 if (dlg.useRasterMapping())
194 {
195 std::unique_ptr<GeoLib::Raster> raster{
197 if (!raster)
198 {
199 OGSError::box(QString::fromStdString(
200 "Error mapping mesh. Could not read raster file " +
201 dlg.getRasterPath()));
202 return;
203 }
204 if (!MeshLib::MeshLayerMapper::layerMapping(*result, *raster,
206 dlg.getIgnoreNoData()))
207 {
208 OGSError::box("Error mapping mesh.");
209 return;
210 }
211 }
212 else
213 {
215 dlg.getStaticValue());
216 }
217 static_cast<MeshModel*>(this->model())->addMesh(std::move(result));
218}
219
221{
222 MeshModel const* const model = static_cast<MeshModel*>(this->model());
223 QModelIndex const index = this->selectionModel()->currentIndex();
224 MeshLib::Mesh const* mesh = model->getMesh(index);
225 if (mesh == nullptr)
226 {
227 return;
228 }
229
230 RasterDataToMeshDialog dlg(mesh->getName());
231 if (dlg.exec() != QDialog::Accepted)
232 {
233 return;
234 }
235
236 auto result = std::make_unique<MeshLib::Mesh>(*mesh);
237 result->setName(dlg.getMeshName());
238 std::unique_ptr<GeoLib::Raster> raster{
240 if (!raster)
241 {
242 OGSError::box(QString::fromStdString("Could not read raster file " +
243 dlg.getRasterPath()));
244 return;
245 }
246 if (dlg.createNodeArray())
247 {
249 *result, *raster, dlg.getNoDataReplacement(), dlg.getArrayName());
250 }
251 else
252 {
254 *result, *raster, dlg.getNoDataReplacement(), dlg.getArrayName());
255 }
256 static_cast<MeshModel*>(this->model())->addMesh(std::move(result));
257}
258
260{
261 MeshModel const* const model = static_cast<MeshModel*>(this->model());
262 QModelIndex const index = this->selectionModel()->currentIndex();
263 MeshLib::Mesh const* const mesh = model->getMesh(index);
264
265 MeshLayerEditDialog meshLayerEdit(mesh);
266 connect(&meshLayerEdit, SIGNAL(mshEditFinished(MeshLib::Mesh*)), model,
267 SLOT(addMesh(MeshLib::Mesh*)));
268 meshLayerEdit.exec();
269}
270
272{
273 MeshModel const* const model = static_cast<MeshModel*>(this->model());
274 QModelIndex const index = this->selectionModel()->currentIndex();
275 auto* mesh = const_cast<MeshLib::Mesh*>(model->getMesh(index));
276
277 MeshValueEditDialog valueEdit(mesh);
278 connect(&valueEdit, SIGNAL(valueEditFinished(MeshLib::Mesh*)), model,
279 SLOT(updateMesh(MeshLib::Mesh*)));
280 valueEdit.exec();
281}
282
284{
285 QModelIndex const index = this->selectionModel()->currentIndex();
286 if (!index.isValid())
287 {
288 return;
289 }
290
291 MeshLib::Mesh const* const mesh =
292 static_cast<MeshModel*>(this->model())->getMesh(index);
293 if (mesh == nullptr)
294 {
295 return;
296 }
297
299 if (dlg.exec() != QDialog::Accepted)
300 {
301 return;
302 }
303
304 bool const copy_material_ids = false;
305 double const thickness(dlg.getThickness());
306 std::unique_ptr<MeshLib::Mesh> result(MeshLib::addLayerToMesh(
307 *mesh, thickness, dlg.getName(), dlg.isTopLayer(), copy_material_ids));
308
309 if (result)
310 {
311 static_cast<MeshModel*>(model())->addMesh(std::move(result));
312 }
313 else
314 {
315 OGSError::box("Error adding layer to mesh.");
316 }
317}
318
320{
321 QModelIndex const index = this->selectionModel()->currentIndex();
322 if (!index.isValid())
323 {
324 return;
325 }
326
327 MeshLib::Mesh const* const mesh =
328 static_cast<MeshModel*>(this->model())->getMesh(index);
330 if (dlg.exec() != QDialog::Accepted)
331 {
332 return;
333 }
334
335 Eigen::Vector3d const& dir(dlg.getNormal());
336 int const tolerance(dlg.getTolerance());
337 std::unique_ptr<MeshLib::Mesh> sfc_mesh(
339 *mesh, dir, tolerance, "Bulk Mesh Node IDs",
340 "Bulk Mesh Element IDs", "Bulk Mesh Face IDs"));
341 if (sfc_mesh)
342 {
343 static_cast<MeshModel*>(model())->addMesh(std::move(sfc_mesh));
344 }
345 else
346 {
348 " No surfaces found to extract\n using the specified parameters.");
349 }
350}
351
353{
354 QModelIndex const index = this->selectionModel()->currentIndex();
355 MeshLib::Mesh const* const mesh =
356 static_cast<MeshModel*>(this->model())->getMesh(index);
358}
359
361{
362 QModelIndex const index = this->selectionModel()->currentIndex();
363 if (!index.isValid())
364 {
365 return;
366 }
367
368 QSettings const settings;
369 QFileInfo const fi(
370 settings.value("lastOpenedMeshFileDirectory").toString());
371 MeshLib::Mesh const* const mesh =
372 static_cast<MeshModel*>(this->model())->getMesh(index);
373 QString const fileName = QFileDialog::getSaveFileName(
374 nullptr, "Convert mesh to shapefile...",
376 QString::fromStdString(mesh->getName()),
377 "ESRI Shapefile (*.shp)");
378 if (!fileName.isEmpty())
379 {
381 if (!FileIO::SHPInterface::write2dMeshToSHP(fileName.toStdString(),
382 *mesh))
383 {
384 OGSError::box("Error exporting mesh\n to shapefile");
385 }
386 }
387}
388
390{
391 QModelIndex const index = this->selectionModel()->currentIndex();
392 if (!index.isValid())
393 {
394 return;
395 }
396
397 MeshLib::Mesh const* const mesh =
398 static_cast<MeshModel*>(this->model())->getMesh(index);
399 QSettings const settings;
400 QString const filename = QFileDialog::getSaveFileName(
401 this, "Write TetGen input file to",
402 settings.value("lastOpenedTetgenFileDirectory").toString(),
403 "TetGen Geometry (*.smesh)");
404 if (!filename.isEmpty())
405 {
407 std::vector<MeshLib::Node> attr;
408 tg.writeTetGenSmesh(filename.toStdString(), *mesh, attr);
409 }
410}
411
413{
414 QModelIndex const index = this->selectionModel()->currentIndex();
415 if (!index.isValid())
416 {
417 OGSError::box("No mesh selected.");
418 return;
419 }
420
421 MeshLib::Mesh const* const mesh =
422 static_cast<MeshModel*>(this->model())->getMesh(index);
423 if (mesh == nullptr)
424 {
425 OGSError::box("No mesh selected.");
426 return;
427 }
428
429 SaveMeshDialog dlg(*mesh);
430 dlg.exec();
431}
432
434{
435 // QModelIndex const index = this->selectionModel()->currentIndex();
436 // MeshLib::Mesh const*const grid =
437 // static_cast<MeshModel*>(this->model())->getMesh(index);
438}
439
441{
442 QModelIndex const index = this->selectionModel()->currentIndex();
443 emit loadFEMCondFileRequested(index.data(0).toString().toStdString());
444}
445
447{
448 QModelIndex const index = this->selectionModel()->currentIndex();
449 MeshItem const* const item = static_cast<MeshItem*>(
450 static_cast<MeshModel*>(this->model())->getItem(index));
451 emit qualityCheckRequested(item->vtkSource());
452}
Definition of the AddLayerToMeshDialog class.
Definition of AddLayerToMesh class.
Definition of the AsciiRasterInterface class.
Definition of the ImportFileTypes enumeration.
Manages the last directory used for saving a file.
Definition of the MeshItem class.
Definition of the MeshLayerEditDialog class.
Definition of the MeshModel class.
Definition of the MeshSurfaceExtraction class.
Definition of the MeshValueEditDialog class.
Definition of the MeshView class.
Definition of the Mesh class.
Definition of the Node class.
Definition of the OGSError class.
Implementation of the SHPInterface class.
Definition of the SaveMeshDialog class.
Definition of the SurfaceExtractionDialog class.
Definition of the TetGenInterface class.
A dialog window for adding a layer to the top or bottom of a mesh.
std::string getName() const
Returns the name of the new mesh.
bool isTopLayer() const
Returns if the top layer button is selected (if false, bottom is selected).
double getThickness() const
Returns the thickness of the new layer.
static GeoLib::Raster * readRaster(std::string const &fname)
Reads raster file by detecting type based on extension and then calling the appropriate method.
static bool write2dMeshToSHP(const std::string &file_name, const MeshLib::Mesh &mesh)
static bool writeTetGenSmesh(const std::string &file_name, const GeoLib::GEOObjects &geo_objects, const std::string &geo_name, const std::vector< GeoLib::Point > &attribute_points)
static void setDir(const QString &path)
Sets the directory last used for saving a file.
static const QString getDir()
Returns the directory last used for saving a file.
A TreeItem containing a mesh and the associated vtk object used in the Mesh Model.
Definition: MeshItem.h:30
MeshLib::Mesh const * getMesh() const
Returns the mesh.
Definition: MeshItem.h:42
MeshLib::VtkMappedMeshSource * vtkSource() const
Returns the VTK object.
Definition: MeshItem.h:44
A dialog window for editing meshes in various ways.
static bool layerMapping(MeshLib::Mesh const &mesh, const GeoLib::Raster &raster, double nodata_replacement=0.0, bool const ignore_nodata=false)
static bool mapToStaticValue(MeshLib::Mesh const &mesh, double value)
Maps the elevation of all mesh nodes to the specified static value.
static MeshLib::Mesh * getMeshSurface(const MeshLib::Mesh &subsfc_mesh, Eigen::Vector3d const &dir, double angle, std::string const &subsfc_node_id_prop_name="", std::string const &subsfc_element_id_prop_name="", std::string const &face_id_prop_name="")
unsigned getDimension() const
Returns the dimension of the mesh (determined by the maximum dimension over all elements).
Definition: Mesh.h:76
const std::string getName() const
Get name of the mesh.
Definition: Mesh.h:97
A dialog window for mapping a 2d mesh based on a raster file.
std::string getNewMeshName() const
bool getIgnoreNoData() const
bool useRasterMapping() const
std::string getRasterPath() const
double getNoDataReplacement() const
double getStaticValue() const
const MeshLib::Mesh * getMesh(const QModelIndex &idx) const
Returns the mesh with the given index.
Definition: MeshModel.cpp:96
A dialog window for changing the MaterialID for mesh elements.
void enableSaveButton(bool)
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override
Is called when the selection of this view changes.
Definition: MeshView.cpp:67
~MeshView() override
void checkMeshQuality()
Calls the dialog for calculating an element quality metric.
Definition: MeshView.cpp:446
void extractSurfaceMesh()
Definition: MeshView.cpp:319
void meshSelected(MeshLib::Mesh const &)
void qualityCheckRequested(MeshLib::VtkMappedMeshSource *)
void contextMenuEvent(QContextMenuEvent *event) override
Definition: MeshView.cpp:117
void openValuesEditDialog()
Opens a dialog for editing material groups.
Definition: MeshView.cpp:271
MeshView(QWidget *parent=nullptr)
Definition: MeshView.cpp:46
void openMap2dMeshDialog()
Opens a dialog for mapping 2d meshes.
Definition: MeshView.cpp:175
void openMeshEditDialog()
Opens a dialog for editing meshes.
Definition: MeshView.cpp:259
void writeToFile() const
Calls the FileDialog to save a mesh to a file.
Definition: MeshView.cpp:412
void requestMeshToGeometryConversion(const MeshLib::Mesh *)
void addMesh()
Adds a new mesh.
Definition: MeshView.cpp:97
void exportToTetGen()
Definition: MeshView.cpp:389
void removeSelectedMeshComponent()
void openRasterDataToMeshDialog()
Opens a dialog for assigning raster data to the mesh.
Definition: MeshView.cpp:220
void convertMeshToGeometry()
Definition: MeshView.cpp:352
void openMeshFile(int)
void loadDIRECTSourceTerms()
Definition: MeshView.cpp:440
void openAddLayerDialog()
Opens a dialog for adding a layer to the mesh.
Definition: MeshView.cpp:283
void elementSelected(vtkUnstructuredGridAlgorithm const *const, unsigned, bool)
void requestMeshRemoval(const QModelIndex &)
void loadFEMCondFileRequested(const std::string)
void addDIRECTSourceTerms()
Definition: MeshView.cpp:433
void removeMesh()
Remove the currently selected mesh.
Definition: MeshView.cpp:102
void updateView()
Definition: MeshView.cpp:55
void exportToShapefile() const
Definition: MeshView.cpp:360
void enableRemoveButton(bool)
static void box(const QString &e)
Definition: OGSError.cpp:23
A dialog window for transferring raster data onto a mesh.
std::string getArrayName() const
std::string getMeshName() const
std::string getRasterPath() const
A dialog window for managing properties for writing meshes to files.
A dialog window for managing properties for writing meshes to files.
Eigen::Vector3d const & getNormal() const
Objects nodes for the TreeModel.
Definition: TreeItem.h:28
TreeItem * parentItem() const
Definition: TreeItem.cpp:115
int row() const
Definition: TreeItem.cpp:73
A hierarchical model for a tree implemented as a double-linked list.
Definition: TreeModel.h:30
bool projectToElements(MeshLib::Mesh &mesh, GeoLib::Raster const &raster, double const default_replacement, std::string const &array_name)
bool projectToNodes(MeshLib::Mesh &mesh, GeoLib::Raster const &raster, double const default_replacement, std::string const &array_name)
MeshLib::Mesh * addLayerToMesh(MeshLib::Mesh const &mesh, double thickness, std::string const &name, bool on_top, bool copy_material_ids)
static double const tolerance