improved pass-band editing
[engrid-github.git] / src / libengrid / guicreatesurfacemesh.cpp
blob2444c347133cd25f7b66b5a0afb0d40c6a3f82ff
1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 // + +
3 // + This file is part of enGrid. +
4 // + +
5 // + Copyright 2008-2014 enGits GmbH +
6 // + +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
11 // + +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
16 // + +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
19 // + +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "guicreatesurfacemesh.h"
23 #include "swaptriangles.h"
24 #include "surfacemesher.h"
25 #include "vertexdelegate.h"
26 #include "laplacesmoother.h"
27 #include "guimainwindow.h"
28 #include "containertricks.h"
29 #include "updatedesiredmeshdensity.h"
30 #include "utilities.h"
32 #include <vtkSmoothPolyDataFilter.h>
33 #include <vtkWindowedSincPolyDataFilter.h>
34 #include <vtkLongArray.h>
35 #include <vtkEgNormalExtrusion.h>
36 #include <vtkIdList.h>
37 #include <vtkCell.h>
38 #include <vtkCellLocator.h>
39 #include <vtkFloatArray.h>
40 #include <vtkCellArray.h>
42 #include <QtGui>
43 #include <QTextStream>
45 #include <iostream>
46 #include <fstream>
47 #include <cmath>
49 #include <cstdio>
51 GuiCreateSurfaceMesh::GuiCreateSurfaceMesh()
53 EG_TYPENAME;
55 setQuickSave(true);
57 populateBoundaryCodes(m_Ui.listWidget);
58 populateBoundaryCodes(m_Ui.m_ListWidgetPrismaticLayers);
59 m_Ui.lineEditMaximalEdgeLength->setText("1000");
61 //Load settings
62 readSettings();
64 Nbc = m_Ui.listWidget-> count ();
66 current_filename= GuiMainWindow::pointer()->getFilename();
69 QString buffer = GuiMainWindow::pointer()->getXmlSection("engrid/surface/table");
70 QTextStream in(&buffer, QIODevice::ReadOnly);
72 m_NumRows = 0;
73 m_NumCols = 0;
74 in >> m_NumRows >> m_NumCols;
76 if (m_NumRows == 0) {
77 m_NumCols = Nbc + 3;
79 if(m_NumCols != Nbc + 3) {
80 //m_NumCols = Nbc + 3;
83 int row, column;
84 QString str;
86 m_Table.clear();
87 m_Table.fill(QVector<QString>(m_NumCols), m_NumRows);
89 for (int i = 0; i < m_NumRows; ++i) {
90 for (int j = 0; j < m_NumCols; ++j) {
91 in >> row >> column >> str;
92 if (str == "{{{empty}}}") {
93 str = "";
95 m_Table[row][column] = str;
99 setTextFromTable();
100 m_Ui.m_TextEditPrismaticLayers->setText(GuiMainWindow::pointer()->getXmlSection("engrid/blayer/rules"));
102 connect(m_Ui.pushButton_SelectAll_BC, SIGNAL(clicked()), this, SLOT(SelectAll_BC()));
103 connect(m_Ui.pushButton_ClearAll_BC, SIGNAL(clicked()), this, SLOT(ClearAll_BC()));
105 m_ELSManager.setListWidget(m_Ui.listWidgetSources);
106 m_ELSManager.read();
107 m_ELSManager.populateListWidget();
109 connect(m_Ui.pushButtonAddSphere, SIGNAL(clicked()), this, SLOT(addSphere()));
110 connect(m_Ui.pushButtonAddCone, SIGNAL(clicked()), this, SLOT(addCone()));
111 connect(m_Ui.pushButtonAddBox, SIGNAL(clicked()), this, SLOT(addBox()));
112 connect(m_Ui.pushButtonAddPipe, SIGNAL(clicked()), this, SLOT(addPipe()));
113 connect(m_Ui.pushButtonEditSource, SIGNAL(clicked()), this, SLOT(edit()));
114 connect(m_Ui.pushButtonDeleteSource, SIGNAL(clicked()), this, SLOT(remove()));
116 connect(m_Ui.m_PushButtonCalc1, SIGNAL(clicked()), this, SLOT(calc1()));
117 connect(m_Ui.m_PushButtonCalc2, SIGNAL(clicked()), this, SLOT(calc2()));
118 connect(m_Ui.m_PushButtonCalc3, SIGNAL(clicked()), this, SLOT(calc3()));
120 connect(m_Ui.m_PassBandSlider, SIGNAL(valueChanged(int)), this, SLOT(displayPb(int)));
125 void GuiCreateSurfaceMesh::displayPb(int v)
127 double dv = 1e-3*v;
128 QString num;
129 num.setNum(2*pow(10.0, -3*dv));
130 m_Ui.m_LabelPassBand->setText(num);
133 ///////////////////////////////////////////
135 int GuiCreateSurfaceMesh::readSettings()
137 QString buffer = GuiMainWindow::pointer()->getXmlSection("engrid/surface/settings");
138 if(!buffer.isEmpty()) {
139 QTextStream in(&buffer, QIODevice::ReadOnly);
140 QString str;
141 in >> str;
142 m_Ui.lineEditMaximalEdgeLength->setText(str);
143 in >> str;
144 m_Ui.lineEditMinimalEdgeLength->setText(str);
145 in >> str;
146 m_Ui.lineEditGrowthFactor->setText(str);
147 double nodes_per_quarter_circle;
148 in >> nodes_per_quarter_circle;
149 m_Ui.doubleSpinBoxCurvature->setValue(nodes_per_quarter_circle);
150 int num_bcs;
151 in >> num_bcs;
152 if (num_bcs == m_Ui.listWidget->count()) {
153 int check_state;
154 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
155 in >> check_state;
156 if (check_state == 1) {
157 m_Ui.listWidget->item(i)->setCheckState(Qt::Checked);
158 } else {
159 m_Ui.listWidget->item(i)->setCheckState(Qt::Unchecked);
163 double v;
164 in >> v;
165 m_Ui.doubleSpinBox2DFeature->setValue(v);
166 in >> v;
167 m_Ui.m_DoubleSpinBox3DFeature->setValue(v);
170 m_ELSManager.read();
172 buffer = GuiMainWindow::pointer()->getXmlSection("engrid/blayer/settings");
173 if(!buffer.isEmpty()) {
174 QTextStream in(&buffer, QIODevice::ReadOnly);
175 int num_bcs;
176 in >> num_bcs;
177 if (num_bcs == m_Ui.m_ListWidgetPrismaticLayers->count()) {
178 int check_state;
179 for (int i = 0; i < m_Ui.m_ListWidgetPrismaticLayers->count(); ++i) {
180 in >> check_state;
181 if (check_state == 1) {
182 m_Ui.m_ListWidgetPrismaticLayers->item(i)->setCheckState(Qt::Checked);
183 } else {
184 m_Ui.m_ListWidgetPrismaticLayers->item(i)->setCheckState(Qt::Unchecked);
188 double dv;
189 int iv;
190 QString num;
191 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->setValue(dv);
192 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->setValue(dv);
193 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->setValue(dv);
194 in >> iv; m_Ui.m_SpinBoxNormalRelaxationIterations->setValue(iv);
195 in >> iv; m_Ui.m_SpinBoxHeightRelaxationIterations->setValue(iv);
197 in >> dv; m_Ui.m_PassBandSlider->setValue(int(1000*dv));
198 num.setNum(2*pow(10.0, -3*dv));
199 m_Ui.m_LabelPassBand->setText(num);
201 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->setValue(dv);
202 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->setValue(dv);
203 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->setValue(dv);
204 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->setValue(dv);
205 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->setValue(dv);
206 in >> iv; m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->setChecked(iv);
207 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->setValue(dv);
210 return(0);
213 int GuiCreateSurfaceMesh::writeSettings()
215 QString buffer = "";
217 QTextStream out(&buffer, QIODevice::WriteOnly);
218 out << "\n";
219 out << m_Ui.lineEditMaximalEdgeLength->text() << "\n";
220 out << m_Ui.lineEditMinimalEdgeLength->text() << "\n";
221 out << m_Ui.lineEditGrowthFactor->text() << "\n";
222 out << m_Ui.doubleSpinBoxCurvature->value() << "\n";
223 out << m_Ui.listWidget->count() << "\n";
224 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
225 if (m_Ui.listWidget->item(i)->checkState() == Qt::Checked) {
226 out << "1 \n";
227 } else {
228 out << "0 \n";
231 out << m_Ui.doubleSpinBox2DFeature->value() << "\n";
232 out << m_Ui.m_DoubleSpinBox3DFeature->value() << "\n";
234 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer);
236 buffer = "";
238 QTextStream out(&buffer, QIODevice::WriteOnly);
239 out << "\n";
240 out << m_Ui.m_ListWidgetPrismaticLayers->count() << "\n";
241 for (int i = 0; i < m_Ui.m_ListWidgetPrismaticLayers->count(); ++i) {
242 if (m_Ui.m_ListWidgetPrismaticLayers->item(i)->checkState() == Qt::Checked) {
243 out << "1 \n";
244 } else {
245 out << "0 \n";
248 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->value() << "\n";
249 out << m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value() << "\n";
250 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->value() << "\n";
251 out << m_Ui.m_SpinBoxNormalRelaxationIterations->value() << "\n";
252 out << m_Ui.m_SpinBoxHeightRelaxationIterations->value() << "\n";
253 out << 1e-3*m_Ui.m_PassBandSlider->value() << "\n";
254 out << m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->value() << "\n";
255 out << m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->value() << "\n";
256 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->value() << "\n";
257 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->value() << "\n";
258 out << m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->value() << "\n";
259 if (m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->checkState() == Qt::Checked) out << "1\n";
260 else out << "0\n";
261 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->value() << "\n";
263 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/settings", buffer);
265 m_ELSManager.write();
267 GuiMainWindow::pointer()->setXmlSection("engrid/surface/rules", m_Ui.textEdit->toPlainText());
268 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
270 return(0);
273 ///////////////////////////////////////////
275 void GuiCreateSurfaceMesh::SelectAll_BC()
277 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
278 m_Ui.listWidget->item(i)->setCheckState(Qt::Checked);
282 void GuiCreateSurfaceMesh::ClearAll_BC()
284 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
285 m_Ui.listWidget->item(i)->setCheckState(Qt::Unchecked);
289 void GuiCreateSurfaceMesh::setTextFromTable()
291 EG_STOPDATE("2015-06-01");
292 m_Ui.textEdit->setText(GuiMainWindow::pointer()->getXmlSection("engrid/surface/rules"));
293 m_Ui.m_TextEditPrismaticLayers->setText(GuiMainWindow::pointer()->getXmlSection("engrid/blayer/rules"));
294 return;
296 QString text = "";
297 QSet<QString> values;
298 for (int i = 0; i < m_NumRows; ++i) {
299 values.insert(m_Table[i][m_NumCols-1]);
301 foreach (QString value, values) {
302 int Ni = 0;
303 for (int i = 0; i < m_NumRows; ++i) {
304 if (m_Table[i][m_NumCols-1] == value) {
305 ++Ni;
308 int ni = 0;
309 for (int i = 0; i < m_NumRows; ++i) {
310 if (m_Table[i][m_NumCols-1] == value) {
311 int Nj = 0;
312 for (int j = 0; j < m_NumCols-3; ++j) {
313 if (m_Table[i][j] == "2") {
314 ++Nj;
317 int nj = 0;
318 for (int j = 0; j < m_NumCols-3; ++j) {
319 if (m_Table[i][j] == "2") {
320 QString bc = m_Ui.listWidget->item(j)->text().split(":")[1].trimmed();
321 text += bc;
322 ++nj;
323 if (nj < Nj) {
324 text += " <AND> ";
328 ++ni;
329 if (ni < Ni) {
330 text += " <OR>\n";
334 text += " = " + value + ";\n\n";
336 m_Ui.textEdit->setText(text);
339 void GuiCreateSurfaceMesh::getTableFromText()
341 QMap<QString, int> bc_map;
342 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
343 bc_map[m_Ui.listWidget->item(i)->text().split(":")[1].trimmed()] = i;
345 m_NumCols = bc_map.size() + 3;
346 QStringList rules = m_Ui.textEdit->toPlainText().split(";", QString::SkipEmptyParts);
347 m_Table.clear();
348 foreach (QString rule, rules) {
349 rule = rule.trimmed();
350 QStringList parts = rule.split("=");
351 if (parts.count() > 1) {
352 QString left = parts[0].trimmed();
353 QString right = parts[1].trimmed();
354 QStringList rows = left.split("<OR>");
355 foreach (QString row, rows) {
356 row = row.trimmed();
357 m_Table.append(QVector<QString>(m_NumCols, "1"));
358 int r = m_Table.count() - 1;
359 m_Table[r][m_NumCols - 3] = "any";
360 m_Table[r][m_NumCols - 2] = "";
361 m_Table[r][m_NumCols - 1] = right;
362 QStringList cols = row.split("<AND>");
363 foreach (QString col, cols) {
364 col = col.trimmed();
365 m_Table[r][bc_map[col]] = "2";
370 m_NumRows = m_Table.size();
373 void GuiCreateSurfaceMesh::operate()
375 writeSettings();
376 getTableFromText();
377 QString buffer = "";
379 QTextStream out(&buffer, QIODevice::WriteOnly);
380 out << "\n";
381 out << m_NumRows << " " << m_NumCols << "\n";
382 for (int row = 0; row < m_NumRows; ++row) {
383 for (int column = 0; column < m_NumCols; ++column) {
384 QString str = m_Table[row][column];
385 if (str.isEmpty()) {
386 str = "{{{empty}}}";
388 out << row << " " << column << " " << str << "\n";
392 GuiMainWindow::pointer()->setXmlSection("engrid/surface/table", buffer);
393 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
396 void GuiCreateSurfaceMesh::calc1()
398 // from number of layers
399 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
400 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
401 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
402 double h1 = h0*pow(s, double(N));
403 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
404 QString num;
405 num.setNum(H);
406 m_Ui.m_LineEditCalcTotalH->setText(num);
407 num.setNum(h1);
408 m_Ui.m_LineEditCalcH1->setText(num);
411 void GuiCreateSurfaceMesh::calc2()
413 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
414 double h1 = m_Ui.m_LineEditCalcH1->text().toDouble();
415 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
416 int N = max(1, int(logarithm(s, h1/h0)));
417 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
418 QString num;
419 num.setNum(H);
420 m_Ui.m_LineEditCalcTotalH->setText(num);
421 m_Ui.m_SpinBoxCalcNumLayers->setValue(N);
424 void GuiCreateSurfaceMesh::calc3()
426 double H = m_Ui.m_LineEditCalcTotalH->text().toDouble();
427 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
428 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
429 double h0 = H*(1.0 - s)/(1.0 - pow(s, double(N)));
430 double h1 = h0*pow(s, double(N));
431 QString num;
432 num.setNum(h0);
433 m_Ui.m_LineEditCalcH0->setText(num);
434 num.setNum(h1);
435 m_Ui.m_LineEditCalcH1->setText(num);