slider for smoothing
[engrid-github.git] / src / libengrid / guicreatesurfacemesh.cpp
blob757f04d8325c4c8f18f78a0f9cba9473c0ec9a63
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()));
122 ///////////////////////////////////////////
124 int GuiCreateSurfaceMesh::readSettings()
126 QString buffer = GuiMainWindow::pointer()->getXmlSection("engrid/surface/settings");
127 if(!buffer.isEmpty()) {
128 QTextStream in(&buffer, QIODevice::ReadOnly);
129 QString str;
130 in >> str;
131 m_Ui.lineEditMaximalEdgeLength->setText(str);
132 in >> str;
133 m_Ui.lineEditMinimalEdgeLength->setText(str);
134 in >> str;
135 m_Ui.lineEditGrowthFactor->setText(str);
136 double nodes_per_quarter_circle;
137 in >> nodes_per_quarter_circle;
138 m_Ui.doubleSpinBoxCurvature->setValue(nodes_per_quarter_circle);
139 int num_bcs;
140 in >> num_bcs;
141 if (num_bcs == m_Ui.listWidget->count()) {
142 int check_state;
143 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
144 in >> check_state;
145 if (check_state == 1) {
146 m_Ui.listWidget->item(i)->setCheckState(Qt::Checked);
147 } else {
148 m_Ui.listWidget->item(i)->setCheckState(Qt::Unchecked);
152 double v;
153 in >> v;
154 m_Ui.doubleSpinBox2DFeature->setValue(v);
155 in >> v;
156 m_Ui.m_DoubleSpinBox3DFeature->setValue(v);
159 m_ELSManager.read();
161 buffer = GuiMainWindow::pointer()->getXmlSection("engrid/blayer/settings");
162 if(!buffer.isEmpty()) {
163 QTextStream in(&buffer, QIODevice::ReadOnly);
164 int num_bcs;
165 in >> num_bcs;
166 if (num_bcs == m_Ui.m_ListWidgetPrismaticLayers->count()) {
167 int check_state;
168 for (int i = 0; i < m_Ui.m_ListWidgetPrismaticLayers->count(); ++i) {
169 in >> check_state;
170 if (check_state == 1) {
171 m_Ui.m_ListWidgetPrismaticLayers->item(i)->setCheckState(Qt::Checked);
172 } else {
173 m_Ui.m_ListWidgetPrismaticLayers->item(i)->setCheckState(Qt::Unchecked);
177 double dv;
178 int iv;
179 QString num;
180 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->setValue(dv);
181 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->setValue(dv);
182 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->setValue(dv);
183 in >> iv; m_Ui.m_SpinBoxNormalRelaxationIterations->setValue(iv);
184 in >> iv; m_Ui.m_SpinBoxHeightRelaxationIterations->setValue(iv);
186 in >> dv; num.setNum(dv); m_Ui.m_PassBandSlider->setValue(int(1000*dv));
188 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->setValue(dv);
189 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->setValue(dv);
190 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->setValue(dv);
191 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->setValue(dv);
192 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->setValue(dv);
193 in >> iv; m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->setChecked(iv);
194 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->setValue(dv);
197 return(0);
200 int GuiCreateSurfaceMesh::writeSettings()
202 QString buffer = "";
204 QTextStream out(&buffer, QIODevice::WriteOnly);
205 out << "\n";
206 out << m_Ui.lineEditMaximalEdgeLength->text() << "\n";
207 out << m_Ui.lineEditMinimalEdgeLength->text() << "\n";
208 out << m_Ui.lineEditGrowthFactor->text() << "\n";
209 out << m_Ui.doubleSpinBoxCurvature->value() << "\n";
210 out << m_Ui.listWidget->count() << "\n";
211 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
212 if (m_Ui.listWidget->item(i)->checkState() == Qt::Checked) {
213 out << "1 \n";
214 } else {
215 out << "0 \n";
218 out << m_Ui.doubleSpinBox2DFeature->value() << "\n";
219 out << m_Ui.m_DoubleSpinBox3DFeature->value() << "\n";
221 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer);
223 buffer = "";
225 QTextStream out(&buffer, QIODevice::WriteOnly);
226 out << "\n";
227 out << m_Ui.m_ListWidgetPrismaticLayers->count() << "\n";
228 for (int i = 0; i < m_Ui.m_ListWidgetPrismaticLayers->count(); ++i) {
229 if (m_Ui.m_ListWidgetPrismaticLayers->item(i)->checkState() == Qt::Checked) {
230 out << "1 \n";
231 } else {
232 out << "0 \n";
235 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->value() << "\n";
236 out << m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value() << "\n";
237 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->value() << "\n";
238 out << m_Ui.m_SpinBoxNormalRelaxationIterations->value() << "\n";
239 out << m_Ui.m_SpinBoxHeightRelaxationIterations->value() << "\n";
240 out << 1e-3*m_Ui.m_PassBandSlider->value() << "\n";
241 out << m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->value() << "\n";
242 out << m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->value() << "\n";
243 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->value() << "\n";
244 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->value() << "\n";
245 out << m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->value() << "\n";
246 if (m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->checkState() == Qt::Checked) out << "1\n";
247 else out << "0\n";
248 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->value() << "\n";
250 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/settings", buffer);
252 m_ELSManager.write();
254 GuiMainWindow::pointer()->setXmlSection("engrid/surface/rules", m_Ui.textEdit->toPlainText());
255 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
257 return(0);
260 ///////////////////////////////////////////
262 void GuiCreateSurfaceMesh::SelectAll_BC()
264 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
265 m_Ui.listWidget->item(i)->setCheckState(Qt::Checked);
269 void GuiCreateSurfaceMesh::ClearAll_BC()
271 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
272 m_Ui.listWidget->item(i)->setCheckState(Qt::Unchecked);
276 void GuiCreateSurfaceMesh::setTextFromTable()
278 EG_STOPDATE("2015-06-01");
279 m_Ui.textEdit->setText(GuiMainWindow::pointer()->getXmlSection("engrid/surface/rules"));
280 m_Ui.m_TextEditPrismaticLayers->setText(GuiMainWindow::pointer()->getXmlSection("engrid/blayer/rules"));
281 return;
283 QString text = "";
284 QSet<QString> values;
285 for (int i = 0; i < m_NumRows; ++i) {
286 values.insert(m_Table[i][m_NumCols-1]);
288 foreach (QString value, values) {
289 int Ni = 0;
290 for (int i = 0; i < m_NumRows; ++i) {
291 if (m_Table[i][m_NumCols-1] == value) {
292 ++Ni;
295 int ni = 0;
296 for (int i = 0; i < m_NumRows; ++i) {
297 if (m_Table[i][m_NumCols-1] == value) {
298 int Nj = 0;
299 for (int j = 0; j < m_NumCols-3; ++j) {
300 if (m_Table[i][j] == "2") {
301 ++Nj;
304 int nj = 0;
305 for (int j = 0; j < m_NumCols-3; ++j) {
306 if (m_Table[i][j] == "2") {
307 QString bc = m_Ui.listWidget->item(j)->text().split(":")[1].trimmed();
308 text += bc;
309 ++nj;
310 if (nj < Nj) {
311 text += " <AND> ";
315 ++ni;
316 if (ni < Ni) {
317 text += " <OR>\n";
321 text += " = " + value + ";\n\n";
323 m_Ui.textEdit->setText(text);
326 void GuiCreateSurfaceMesh::getTableFromText()
328 QMap<QString, int> bc_map;
329 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
330 bc_map[m_Ui.listWidget->item(i)->text().split(":")[1].trimmed()] = i;
332 m_NumCols = bc_map.size() + 3;
333 QStringList rules = m_Ui.textEdit->toPlainText().split(";", QString::SkipEmptyParts);
334 m_Table.clear();
335 foreach (QString rule, rules) {
336 rule = rule.trimmed();
337 QStringList parts = rule.split("=");
338 if (parts.count() > 1) {
339 QString left = parts[0].trimmed();
340 QString right = parts[1].trimmed();
341 QStringList rows = left.split("<OR>");
342 foreach (QString row, rows) {
343 row = row.trimmed();
344 m_Table.append(QVector<QString>(m_NumCols, "1"));
345 int r = m_Table.count() - 1;
346 m_Table[r][m_NumCols - 3] = "any";
347 m_Table[r][m_NumCols - 2] = "";
348 m_Table[r][m_NumCols - 1] = right;
349 QStringList cols = row.split("<AND>");
350 foreach (QString col, cols) {
351 col = col.trimmed();
352 m_Table[r][bc_map[col]] = "2";
357 m_NumRows = m_Table.size();
360 void GuiCreateSurfaceMesh::operate()
362 writeSettings();
363 getTableFromText();
364 QString buffer = "";
366 QTextStream out(&buffer, QIODevice::WriteOnly);
367 out << "\n";
368 out << m_NumRows << " " << m_NumCols << "\n";
369 for (int row = 0; row < m_NumRows; ++row) {
370 for (int column = 0; column < m_NumCols; ++column) {
371 QString str = m_Table[row][column];
372 if (str.isEmpty()) {
373 str = "{{{empty}}}";
375 out << row << " " << column << " " << str << "\n";
379 GuiMainWindow::pointer()->setXmlSection("engrid/surface/table", buffer);
380 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
383 void GuiCreateSurfaceMesh::calc1()
385 // from number of layers
386 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
387 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
388 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
389 double h1 = h0*pow(s, double(N));
390 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
391 QString num;
392 num.setNum(H);
393 m_Ui.m_LineEditCalcTotalH->setText(num);
394 num.setNum(h1);
395 m_Ui.m_LineEditCalcH1->setText(num);
398 void GuiCreateSurfaceMesh::calc2()
400 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
401 double h1 = m_Ui.m_LineEditCalcH1->text().toDouble();
402 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
403 int N = max(1, int(logarithm(s, h1/h0)));
404 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
405 QString num;
406 num.setNum(H);
407 m_Ui.m_LineEditCalcTotalH->setText(num);
408 m_Ui.m_SpinBoxCalcNumLayers->setValue(N);
411 void GuiCreateSurfaceMesh::calc3()
413 double H = m_Ui.m_LineEditCalcTotalH->text().toDouble();
414 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
415 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
416 double h0 = H*(1.0 - s)/(1.0 - pow(s, double(N)));
417 double h1 = h0*pow(s, double(N));
418 QString num;
419 num.setNum(h0);
420 m_Ui.m_LineEditCalcH0->setText(num);
421 num.setNum(h1);
422 m_Ui.m_LineEditCalcH1->setText(num);