From 59aa3fdceb46b4d8236dfa2f061a5efb596c3383 Mon Sep 17 00:00:00 2001 From: Karsten Rink <karsten.rink@ufz.de> Date: Mon, 14 Apr 2014 16:43:03 +0200 Subject: [PATCH] integrated first version into GUI --- Gui/DataView/MeshLayerEditDialog.cpp | 214 ++++++++++++--------- Gui/DataView/MeshLayerEditDialog.h | 5 + MeshLib/MeshGenerators/MeshLayerMapper.cpp | 10 +- MeshLib/MeshGenerators/MeshLayerMapper.h | 4 +- MeshLib/Node.h | 4 +- 5 files changed, 139 insertions(+), 98 deletions(-) diff --git a/Gui/DataView/MeshLayerEditDialog.cpp b/Gui/DataView/MeshLayerEditDialog.cpp index 5692a07ce32..2902352bf92 100644 --- a/Gui/DataView/MeshLayerEditDialog.cpp +++ b/Gui/DataView/MeshLayerEditDialog.cpp @@ -12,7 +12,7 @@ * */ - +#include "MeshGenerators/LayerVolumes.h" #include "MeshLayerEditDialog.h" // ThirdParty/logog @@ -30,21 +30,24 @@ #include <QLineEdit> #include <QGroupBox> #include <QRadioButton> +#include <QHBoxLayout> #include <QVBoxLayout> MeshLayerEditDialog::MeshLayerEditDialog(const MeshLib::Mesh* mesh, QDialog* parent) : QDialog(parent), _msh(mesh), _n_layers(0), - _nLayerExplanation (new QLabel("(select \"0\" for surface mapping)")), - _layerEdit (new QLineEdit("0")), + _nLayerExplanation (new QLabel(this)), + _layerEdit (new QLineEdit("0", this)), _noDataReplacementEdit(nullptr), - _nextButton (new QPushButton("Next")), + _nextButton (new QPushButton("Next", this)), _layerBox (nullptr), _radioButtonBox (nullptr), - _layerSelectionLayout (new QGridLayout), + _ogsMeshButton (nullptr), + _layerSelectionLayout (new QGridLayout(_layerBox)), _use_rasters(true) { setupUi(this); + _nLayerExplanation->setText("(select \"0\" for surface mapping)"); this->gridLayoutLayerMapping->addWidget(new QLabel("Please specify the number of layers to add:", this), 0, 0); this->gridLayoutLayerMapping->addWidget(_nLayerExplanation, 1, 0); this->gridLayoutLayerMapping->addWidget(_layerEdit, 0, 1); @@ -53,7 +56,6 @@ MeshLayerEditDialog::MeshLayerEditDialog(const MeshLib::Mesh* mesh, QDialog* par connect(_nextButton, SIGNAL(pressed()), this, SLOT(nextButtonPressed())); // configure group box + layout - _layerBox = new QGroupBox; this->_layerSelectionLayout->setMargin(10); this->_layerSelectionLayout->setColumnMinimumWidth(2,10); this->_layerSelectionLayout->setColumnStretch(0, 80); @@ -63,16 +65,6 @@ MeshLayerEditDialog::MeshLayerEditDialog(const MeshLib::Mesh* mesh, QDialog* par MeshLayerEditDialog::~MeshLayerEditDialog() { - for (int i = 0; i < _edits.size(); ++i) - delete _edits[i]; - - delete _nLayerExplanation; - delete _layerEdit; - delete _noDataReplacementEdit; - delete _nextButton; - delete _radioButtonBox; - delete _layerSelectionLayout; - delete _layerBox; } void MeshLayerEditDialog::nextButtonPressed() @@ -82,12 +74,14 @@ void MeshLayerEditDialog::nextButtonPressed() _nLayerExplanation->setText(""); _n_layers = static_cast<unsigned>(_layerEdit->text().toInt()); - if (_n_layers > 0) + if (_n_layers == 0) + this->createWithRasters(); + else { QVBoxLayout* _radiobuttonLayout (new QVBoxLayout(_radioButtonBox)); QRadioButton* selectButton1 (new QRadioButton("Add layers based on raster files", _radioButtonBox)); QRadioButton* selectButton2 (new QRadioButton("Add layers with static thickness", _radioButtonBox)); - _radioButtonBox = new QGroupBox; + _radioButtonBox = new QGroupBox(this); _radiobuttonLayout->addWidget(selectButton1); _radiobuttonLayout->addWidget(selectButton2); _radioButtonBox->setLayout(_radiobuttonLayout); @@ -97,10 +91,6 @@ void MeshLayerEditDialog::nextButtonPressed() connect(selectButton1, SIGNAL(pressed()), this, SLOT(createWithRasters())); connect(selectButton2, SIGNAL(pressed()), this, SLOT(createStatic())); } - else - this->createWithRasters(); - - } void MeshLayerEditDialog::createWithRasters() @@ -110,7 +100,8 @@ void MeshLayerEditDialog::createWithRasters() this->_radioButtonBox->setEnabled(false); const QString selectText = (_n_layers>0) ? "Please specify a raster file for mapping each layer:" : - "Please specify rasterfile for surface mapping:"; + "Please specify raster file for surface mapping:"; + this->_layerBox = new QGroupBox(this); this->_layerBox->setTitle(selectText); for (unsigned i = 0; i <= _n_layers+1; ++i) @@ -119,7 +110,7 @@ void MeshLayerEditDialog::createWithRasters() if (i==0) text = "Surface"; else if (i>_n_layers) text = "Layer" + QString::number(_n_layers) + "-Bottom"; else text="Layer" + QString::number(i) + "-Top"; - QLineEdit* edit (new QLineEdit()); + QLineEdit* edit (new QLineEdit(this)); QPushButton* button (new QPushButton("...", _layerBox)); this->_edits.push_back(edit); @@ -144,103 +135,148 @@ void MeshLayerEditDialog::createWithRasters() } this->_layerBox->setLayout(this->_layerSelectionLayout); this->gridLayoutLayerMapping->addWidget(_layerBox, 4, 0, 1, 3); + if (this->_n_layers > 0) + this->createMeshToolSelection(); } void MeshLayerEditDialog::createStatic() { this->_use_rasters = false; this->_radioButtonBox->setEnabled(false); + this->_layerBox = new QGroupBox(this); this->_layerBox->setTitle("Please specify a thickness or each layer"); for (unsigned i = 0; i < this->_n_layers; ++i) { QString text("Layer" + QString::number(i) + "-Thickness"); - QLineEdit* staticLayerEdit = new QLineEdit("10"); + QLineEdit* staticLayerEdit = new QLineEdit("10", this); staticLayerEdit->setValidator(new QDoubleValidator(staticLayerEdit)); _edits.push_back(staticLayerEdit); this->_layerSelectionLayout->addWidget(new QLabel(text, _layerBox), i, 0); this->_layerSelectionLayout->addWidget(_edits[i], i, 1); } this->_layerBox->setLayout(this->_layerSelectionLayout); - this->gridLayoutLayerMapping->addWidget(_layerBox, 5, 0, 1, 3); + this->gridLayoutLayerMapping->addWidget(_layerBox, 4, 0, 1, 3); + this->createMeshToolSelection(); } -void MeshLayerEditDialog::accept() +void MeshLayerEditDialog::createMeshToolSelection() { - if (this->_edits.size()>0) + QGroupBox* meshToolSelectionBox (new QGroupBox(this)); + meshToolSelectionBox->setTitle("Select output element type"); + QHBoxLayout* meshToolSelectionLayout (new QHBoxLayout(meshToolSelectionBox)); + _ogsMeshButton = new QRadioButton("Prisms", meshToolSelectionBox); + QRadioButton* tetgenMeshButton = new QRadioButton("Tetrahedra", meshToolSelectionBox); + meshToolSelectionLayout->addWidget(_ogsMeshButton); + meshToolSelectionLayout->addWidget(tetgenMeshButton); + meshToolSelectionBox->setLayout(meshToolSelectionLayout); + _ogsMeshButton->setChecked(true); + gridLayoutLayerMapping->addWidget(meshToolSelectionBox, 5, 0, 1, 3); +} + +MeshLib::Mesh* MeshLayerEditDialog::createPrismMesh() +{ + const unsigned nLayers = _layerEdit->text().toInt(); + std::vector<float> layer_thickness; + for (unsigned i=0; i<nLayers; ++i) { - bool all_paths_set (true); - if ((_n_layers==0) && _use_rasters && (_edits[0]->text().length()==0)) - all_paths_set = false; - else - { - int start_idx = (_use_rasters) ? 1:0; - for (int i=start_idx; i<_edits.size(); ++i) - if (_edits[i]->text().length()==0) - all_paths_set = false; - } + // "100" is just a default size to have any value for extruding 2D elements. + // The actual mapping based on a raster file will be performed later. + const float thickness = (_use_rasters) ? 100 : (this->_edits[i]->text().toFloat()); + layer_thickness.push_back(thickness); + } - if (all_paths_set) - { - int result(1); - const unsigned nLayers = _layerEdit->text().toInt(); - MeshLib::Mesh* new_mesh (NULL); + MeshLib::Mesh* new_mesh = MeshLayerMapper::CreateLayers(*_msh, layer_thickness); - if (nLayers==0) - { - new_mesh = new MeshLib::Mesh(*_msh); - const std::string imgPath ( this->_edits[0]->text().toStdString() ); - const double noDataReplacementValue = this->_noDataReplacementEdit->text().toDouble(); - if (!imgPath.empty()) - result = MeshLayerMapper::LayerMapping(*new_mesh, imgPath, nLayers, 0, noDataReplacementValue); - } - else + if (_use_rasters) + { + for (unsigned i=0; i<=nLayers; ++i) + { + const std::string imgPath ( this->_edits[i+1]->text().toStdString() ); + const double noDataReplacement = (i==0) ? 0.0 : -9999.0; + if (!MeshLayerMapper::LayerMapping(*new_mesh, imgPath, nLayers, i, noDataReplacement)) { - std::vector<float> layer_thickness; - for (unsigned i=0; i<nLayers; ++i) - { - // "100" is just a default size to have any value for extruding 2D elements. - // The actual mapping based on a raster file will be performed later. - const float thickness = (_use_rasters) ? 100 : (this->_edits[i]->text().toFloat()); - layer_thickness.push_back(thickness); - } - - new_mesh = MeshLayerMapper::CreateLayers(*_msh, layer_thickness); - - if (_use_rasters) - { - for (unsigned i=0; i<=nLayers; ++i) - { - const std::string imgPath ( this->_edits[i+1]->text().toStdString() ); - const double noDataReplacement = (i==0) ? 0.0 : -9999.0; - if (!imgPath.empty()) - { - result = MeshLayerMapper::LayerMapping(*new_mesh, imgPath, nLayers, i, noDataReplacement); - if (result==0) break; - } - } - if (this->_edits[0]->text().length()>0) - { - MeshLib::Mesh* final_mesh = MeshLayerMapper::blendLayersWithSurface(*new_mesh, nLayers, this->_edits[0]->text().toStdString()); - delete new_mesh; - new_mesh = final_mesh; - } - } + delete new_mesh; + return nullptr; } + } + if (this->_edits[0]->text().length()>0) + { + MeshLib::Mesh* final_mesh = MeshLayerMapper::blendLayersWithSurface(*new_mesh, nLayers, this->_edits[0]->text().toStdString()); + delete new_mesh; + new_mesh = final_mesh; + } + } + return new_mesh; +} - if (new_mesh) - emit mshEditFinished(new_mesh); +MeshLib::Mesh* MeshLayerEditDialog::createTetMesh() +{ + const unsigned nLayers = _layerEdit->text().toInt(); + std::vector<std::string> raster_paths(nLayers+1); + for (unsigned i=0; i<=nLayers; ++i) + raster_paths[i] = this->_edits[i+1]->text().toStdString(); + LayerVolumes lv; + lv.createGeoVolumes(*_msh, raster_paths); + return lv.getMesh(); +} + +void MeshLayerEditDialog::accept() +{ + if (this->_edits.isEmpty()) + { + OGSError::box("Please specifiy the number and\n type of layers and press \"Next\""); + return; + } + + bool all_paths_set (true); + if (_n_layers==0) + { + if (_edits[0]->text().isEmpty()) + all_paths_set = false; + } + else + { + int start_idx = (_use_rasters) ? 1:0; + for (int i=start_idx; i<_edits.size(); ++i) + if (_edits[i]->text().isEmpty()) + all_paths_set = false; + } - if (!new_mesh || result==0) - OGSError::box("Error creating mesh"); + if (!all_paths_set) + { + OGSError::box("Please specifiy raster files for all layers."); + return; + } - this->done(QDialog::Accepted); + const unsigned nLayers = _layerEdit->text().toInt(); + MeshLib::Mesh* new_mesh (NULL); + + if (nLayers==0) + { + new_mesh = new MeshLib::Mesh(*_msh); + const std::string imgPath ( this->_edits[0]->text().toStdString() ); + const double noDataReplacementValue = this->_noDataReplacementEdit->text().toDouble(); + if (!MeshLayerMapper::LayerMapping(*new_mesh, imgPath, nLayers, 0, noDataReplacementValue)) + { + delete new_mesh; + return; } + } + else + { + if (_ogsMeshButton->isChecked()) + new_mesh = this->createPrismMesh(); else - OGSError::box("Please specifiy raster files for all layers."); + new_mesh = this->createTetMesh(); } + + if (new_mesh) + emit mshEditFinished(new_mesh); else - OGSError::box("Please specifiy the number and\n type of layers and press \"Next\""); + OGSError::box("Error creating mesh"); + + this->done(QDialog::Accepted); } void MeshLayerEditDialog::reject() diff --git a/Gui/DataView/MeshLayerEditDialog.h b/Gui/DataView/MeshLayerEditDialog.h index 89fabac9236..a4dcde19d5c 100644 --- a/Gui/DataView/MeshLayerEditDialog.h +++ b/Gui/DataView/MeshLayerEditDialog.h @@ -44,6 +44,10 @@ public: ~MeshLayerEditDialog(void); private: + void createMeshToolSelection(); + MeshLib::Mesh* createPrismMesh(); + MeshLib::Mesh* createTetMesh(); + const MeshLib::Mesh* _msh; unsigned _n_layers; QMap<QPushButton*, QLineEdit*> _fileButtonMap; @@ -55,6 +59,7 @@ private: QPushButton* _nextButton; QGroupBox* _layerBox; QGroupBox* _radioButtonBox; + QRadioButton* _ogsMeshButton; QGridLayout* _layerSelectionLayout; bool _use_rasters; diff --git a/MeshLib/MeshGenerators/MeshLayerMapper.cpp b/MeshLib/MeshGenerators/MeshLayerMapper.cpp index 59c600ef287..c6b76916b3c 100644 --- a/MeshLib/MeshGenerators/MeshLayerMapper.cpp +++ b/MeshLib/MeshGenerators/MeshLayerMapper.cpp @@ -109,19 +109,19 @@ MeshLib::Mesh* MeshLayerMapper::CreateLayers(const MeshLib::Mesh &mesh, const st return new MeshLib::Mesh("SubsurfaceMesh", new_nodes, new_elems); } -int MeshLayerMapper::LayerMapping(MeshLib::Mesh &new_mesh, const std::string &rasterfile, - const unsigned nLayers, const unsigned layer_id, double noDataReplacementValue = 0.0) +bool MeshLayerMapper::LayerMapping(MeshLib::Mesh &new_mesh, const std::string &rasterfile, + const unsigned nLayers, const unsigned layer_id, double noDataReplacementValue = 0.0) { if (nLayers < layer_id) { ERR("MshLayerMapper::LayerMapping() - Mesh has only %d Layers, cannot assign layer %d.", nLayers, layer_id); - return 0; + return false; } const GeoLib::Raster *raster(GeoLib::Raster::getRasterFromASCFile(rasterfile)); if (! raster) { ERR("MshLayerMapper::LayerMapping - could not read raster file %s", rasterfile.c_str()); - return 0; + return false; } const double x0(raster->getOrigin()[0]); const double y0(raster->getOrigin()[1]); @@ -202,7 +202,7 @@ int MeshLayerMapper::LayerMapping(MeshLib::Mesh &new_mesh, const std::string &ra } delete raster; - return 1; + return true; } bool MeshLayerMapper::isNodeOnRaster(const MeshLib::Node &node, diff --git a/MeshLib/MeshGenerators/MeshLayerMapper.h b/MeshLib/MeshGenerators/MeshLayerMapper.h index bcbd9a7da94..5121757a6d8 100644 --- a/MeshLib/MeshGenerators/MeshLayerMapper.h +++ b/MeshLib/MeshGenerators/MeshLayerMapper.h @@ -46,8 +46,8 @@ public: * Maps the z-values of nodes in the designated layer of the given mesh according to the given raster. * Note: This only results in a valid mesh if the layers don't intersect each other. */ - static int LayerMapping(MeshLib::Mesh &mesh, const std::string &rasterfile, - const unsigned nLayers, const unsigned layer_id, double noDataReplacementValue); + static bool LayerMapping(MeshLib::Mesh &mesh, const std::string &rasterfile, + const unsigned nLayers, const unsigned layer_id, double noDataReplacementValue); /** * Blends a mesh with the surface given by dem_raster. Nodes and elements above the surface are either removed or adapted to fit the surface. diff --git a/MeshLib/Node.h b/MeshLib/Node.h index 8bdb813c934..a47defee0df 100644 --- a/MeshLib/Node.h +++ b/MeshLib/Node.h @@ -36,8 +36,8 @@ class Element; class Node : public GeoLib::PointWithID { /* friend functions: */ - friend int MeshLayerMapper::LayerMapping(MeshLib::Mesh &mesh, const std::string &rasterfile, const unsigned nLayers, - const unsigned layer_id, double noDataReplacementValue); + friend bool MeshLayerMapper::LayerMapping(MeshLib::Mesh &mesh, const std::string &rasterfile, const unsigned nLayers, + const unsigned layer_id, double noDataReplacementValue); friend MeshLib::Mesh* MeshLayerMapper::blendLayersWithSurface(MeshLib::Mesh &mesh, const unsigned nLayers, const std::string &dem_raster); /* friend classes: */ -- GitLab