Merge branch 'master' of github.com:enGits/engrid
[engrid-github.git] / src / libengrid / guicreatesurfacemesh.cpp
blobf24f6bf9cb447dc2e3e00bb29f07e42f11a76d5d
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 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->setValue(dv);
180 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->setValue(dv);
181 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->setValue(dv);
182 in >> iv; m_Ui.m_SpinBoxNormalRelaxationIterations->setValue(iv);
183 in >> iv; m_Ui.m_SpinBoxHeightRelaxationIterations->setValue(iv);
184 in >> iv; m_Ui.m_SpinBoxShellRelaxationIterations->setValue(iv);
185 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->setValue(dv);
186 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->setValue(dv);
187 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->setValue(dv);
188 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->setValue(dv);
189 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->setValue(dv);
190 in >> iv; m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->setChecked(iv);
191 in >> dv; m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->setValue(dv);
194 return(0);
197 int GuiCreateSurfaceMesh::writeSettings()
199 QString buffer = "";
201 QTextStream out(&buffer, QIODevice::WriteOnly);
202 out << "\n";
203 out << m_Ui.lineEditMaximalEdgeLength->text() << "\n";
204 out << m_Ui.lineEditMinimalEdgeLength->text() << "\n";
205 out << m_Ui.lineEditGrowthFactor->text() << "\n";
206 out << m_Ui.doubleSpinBoxCurvature->value() << "\n";
207 out << m_Ui.listWidget->count() << "\n";
208 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
209 if (m_Ui.listWidget->item(i)->checkState() == Qt::Checked) {
210 out << "1 \n";
211 } else {
212 out << "0 \n";
215 out << m_Ui.doubleSpinBox2DFeature->value() << "\n";
216 out << m_Ui.m_DoubleSpinBox3DFeature->value() << "\n";
218 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer);
220 buffer = "";
222 QTextStream out(&buffer, QIODevice::WriteOnly);
223 out << "\n";
224 out << m_Ui.m_ListWidgetPrismaticLayers->count() << "\n";
225 for (int i = 0; i < m_Ui.m_ListWidgetPrismaticLayers->count(); ++i) {
226 if (m_Ui.m_ListWidgetPrismaticLayers->item(i)->checkState() == Qt::Checked) {
227 out << "1 \n";
228 } else {
229 out << "0 \n";
232 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->value() << "\n";
233 out << m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value() << "\n";
234 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->value() << "\n";
235 out << m_Ui.m_SpinBoxNormalRelaxationIterations->value() << "\n";
236 out << m_Ui.m_SpinBoxHeightRelaxationIterations->value() << "\n";
237 out << m_Ui.m_SpinBoxShellRelaxationIterations->value() << "\n";
238 out << m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->value() << "\n";
239 out << m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->value() << "\n";
240 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->value() << "\n";
241 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->value() << "\n";
242 out << m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->value() << "\n";
243 if (m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->checkState() == Qt::Checked) out << "1\n";
244 else out << "0\n";
245 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->value() << "\n";
247 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/settings", buffer);
249 m_ELSManager.write();
251 GuiMainWindow::pointer()->setXmlSection("engrid/surface/rules", m_Ui.textEdit->toPlainText());
252 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
254 return(0);
257 ///////////////////////////////////////////
259 void GuiCreateSurfaceMesh::SelectAll_BC()
261 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
262 m_Ui.listWidget->item(i)->setCheckState(Qt::Checked);
266 void GuiCreateSurfaceMesh::ClearAll_BC()
268 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
269 m_Ui.listWidget->item(i)->setCheckState(Qt::Unchecked);
273 void GuiCreateSurfaceMesh::setTextFromTable()
275 EG_STOPDATE("2014-11-01");
276 m_Ui.textEdit->setText(GuiMainWindow::pointer()->getXmlSection("engrid/surface/rules"));
277 m_Ui.m_TextEditPrismaticLayers->setText(GuiMainWindow::pointer()->getXmlSection("engrid/blayer/rules"));
278 return;
280 QString text = "";
281 QSet<QString> values;
282 for (int i = 0; i < m_NumRows; ++i) {
283 values.insert(m_Table[i][m_NumCols-1]);
285 foreach (QString value, values) {
286 int Ni = 0;
287 for (int i = 0; i < m_NumRows; ++i) {
288 if (m_Table[i][m_NumCols-1] == value) {
289 ++Ni;
292 int ni = 0;
293 for (int i = 0; i < m_NumRows; ++i) {
294 if (m_Table[i][m_NumCols-1] == value) {
295 int Nj = 0;
296 for (int j = 0; j < m_NumCols-3; ++j) {
297 if (m_Table[i][j] == "2") {
298 ++Nj;
301 int nj = 0;
302 for (int j = 0; j < m_NumCols-3; ++j) {
303 if (m_Table[i][j] == "2") {
304 QString bc = m_Ui.listWidget->item(j)->text().split(":")[1].trimmed();
305 text += bc;
306 ++nj;
307 if (nj < Nj) {
308 text += " <AND> ";
312 ++ni;
313 if (ni < Ni) {
314 text += " <OR>\n";
318 text += " = " + value + ";\n\n";
320 m_Ui.textEdit->setText(text);
323 void GuiCreateSurfaceMesh::getTableFromText()
325 QMap<QString, int> bc_map;
326 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
327 bc_map[m_Ui.listWidget->item(i)->text().split(":")[1].trimmed()] = i;
329 m_NumCols = bc_map.size() + 3;
330 QStringList rules = m_Ui.textEdit->toPlainText().split(";", QString::SkipEmptyParts);
331 m_Table.clear();
332 foreach (QString rule, rules) {
333 rule = rule.trimmed();
334 QStringList parts = rule.split("=");
335 if (parts.count() > 1) {
336 QString left = parts[0].trimmed();
337 QString right = parts[1].trimmed();
338 QStringList rows = left.split("<OR>");
339 foreach (QString row, rows) {
340 row = row.trimmed();
341 m_Table.append(QVector<QString>(m_NumCols, "1"));
342 int r = m_Table.count() - 1;
343 m_Table[r][m_NumCols - 3] = "any";
344 m_Table[r][m_NumCols - 2] = "";
345 m_Table[r][m_NumCols - 1] = right;
346 QStringList cols = row.split("<AND>");
347 foreach (QString col, cols) {
348 col = col.trimmed();
349 m_Table[r][bc_map[col]] = "2";
354 m_NumRows = m_Table.size();
357 void GuiCreateSurfaceMesh::operate()
359 writeSettings();
360 getTableFromText();
361 QString buffer = "";
363 QTextStream out(&buffer, QIODevice::WriteOnly);
364 out << "\n";
365 out << m_NumRows << " " << m_NumCols << "\n";
366 for (int row = 0; row < m_NumRows; ++row) {
367 for (int column = 0; column < m_NumCols; ++column) {
368 QString str = m_Table[row][column];
369 if (str.isEmpty()) {
370 str = "{{{empty}}}";
372 out << row << " " << column << " " << str << "\n";
376 GuiMainWindow::pointer()->setXmlSection("engrid/surface/table", buffer);
377 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
380 void GuiCreateSurfaceMesh::calc1()
382 // from number of layers
383 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
384 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
385 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
386 double h1 = h0*pow(s, double(N));
387 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
388 QString num;
389 num.setNum(H);
390 m_Ui.m_LineEditCalcTotalH->setText(num);
391 num.setNum(h1);
392 m_Ui.m_LineEditCalcH1->setText(num);
395 void GuiCreateSurfaceMesh::calc2()
397 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
398 double h1 = m_Ui.m_LineEditCalcH1->text().toDouble();
399 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
400 int N = max(1, int(logarithm(s, h1/h0)));
401 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
402 QString num;
403 num.setNum(H);
404 m_Ui.m_LineEditCalcTotalH->setText(num);
405 m_Ui.m_SpinBoxCalcNumLayers->setValue(N);
408 void GuiCreateSurfaceMesh::calc3()
410 double H = m_Ui.m_LineEditCalcTotalH->text().toDouble();
411 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
412 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
413 double h0 = H*(1.0 - s)/(1.0 - pow(s, double(N)));
414 double h1 = h0*pow(s, double(N));
415 QString num;
416 num.setNum(h0);
417 m_Ui.m_LineEditCalcH0->setText(num);
418 num.setNum(h1);
419 m_Ui.m_LineEditCalcH1->setText(num);