updated to modern VTK
[engrid-github.git] / src / libengrid / guicreatesurfacemesh.cpp
blobf6da3cea17dceadcd718d31f1a7f2a2fa6a897c7
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").trimmed());
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);
208 in >> iv; m_Ui.m_SpinBoxBufferLayers->setValue(iv);
211 return(0);
214 int GuiCreateSurfaceMesh::writeSettings()
216 QString buffer = "";
218 QTextStream out(&buffer, QIODevice::WriteOnly);
219 out << "\n";
220 out << m_Ui.lineEditMaximalEdgeLength->text() << "\n";
221 out << m_Ui.lineEditMinimalEdgeLength->text() << "\n";
222 out << m_Ui.lineEditGrowthFactor->text() << "\n";
223 out << m_Ui.doubleSpinBoxCurvature->value() << "\n";
224 out << m_Ui.listWidget->count() << "\n";
225 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
226 if (m_Ui.listWidget->item(i)->checkState() == Qt::Checked) {
227 out << "1 \n";
228 } else {
229 out << "0 \n";
232 out << m_Ui.doubleSpinBox2DFeature->value() << "\n";
233 out << m_Ui.m_DoubleSpinBox3DFeature->value() << "\n";
235 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer);
237 buffer = "";
239 QTextStream out(&buffer, QIODevice::WriteOnly);
240 out << "\n";
241 out << m_Ui.m_ListWidgetPrismaticLayers->count() << "\n";
242 for (int i = 0; i < m_Ui.m_ListWidgetPrismaticLayers->count(); ++i) {
243 if (m_Ui.m_ListWidgetPrismaticLayers->item(i)->checkState() == Qt::Checked) {
244 out << "1 \n";
245 } else {
246 out << "0 \n";
249 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFeatureAngle->value() << "\n";
250 out << m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value() << "\n";
251 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFarfieldRatio->value() << "\n";
252 out << m_Ui.m_SpinBoxNormalRelaxationIterations->value() << "\n";
253 out << m_Ui.m_SpinBoxHeightRelaxationIterations->value() << "\n";
254 out << 1e-3*m_Ui.m_PassBandSlider->value() << "\n";
255 out << m_Ui.m_DoubleSpinBoxBoundaryLayerLowerFaceLimit->value() << "\n";
256 out << m_Ui.m_DoubleSpinBoxBoundaryLayerUpperFaceLimit->value() << "\n";
257 out << m_Ui.m_DoubleSpinBoxBoundaryLayerFaceAngle->value() << "\n";
258 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGapHeight->value() << "\n";
259 out << m_Ui.m_DoubleSpinBoxBoundaryLayerRadarAngle->value() << "\n";
260 if (m_Ui.m_CheckBoxBoundaryLayerNormalVectorGrouping->checkState() == Qt::Checked) out << "1\n";
261 else out << "0\n";
262 out << m_Ui.m_DoubleSpinBoxBoundaryLayerGroupingAngle->value() << "\n";
263 out << m_Ui.m_SpinBoxBufferLayers->value() << "\n";
265 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/settings", buffer);
267 m_ELSManager.write();
269 GuiMainWindow::pointer()->setXmlSection("engrid/surface/rules", m_Ui.textEdit->toPlainText());
270 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
272 return(0);
275 ///////////////////////////////////////////
277 void GuiCreateSurfaceMesh::SelectAll_BC()
279 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
280 m_Ui.listWidget->item(i)->setCheckState(Qt::Checked);
284 void GuiCreateSurfaceMesh::ClearAll_BC()
286 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
287 m_Ui.listWidget->item(i)->setCheckState(Qt::Unchecked);
291 void GuiCreateSurfaceMesh::setTextFromTable()
293 //EG_STOPDATE("2015-06-01");
294 m_Ui.textEdit->setText(GuiMainWindow::pointer()->getXmlSection("engrid/surface/rules").trimmed());
295 m_Ui.m_TextEditPrismaticLayers->setText(GuiMainWindow::pointer()->getXmlSection("engrid/blayer/rules").trimmed());
296 return;
298 QString text = "";
299 QSet<QString> values;
300 for (int i = 0; i < m_NumRows; ++i) {
301 values.insert(m_Table[i][m_NumCols-1]);
303 foreach (QString value, values) {
304 int Ni = 0;
305 for (int i = 0; i < m_NumRows; ++i) {
306 if (m_Table[i][m_NumCols-1] == value) {
307 ++Ni;
310 int ni = 0;
311 for (int i = 0; i < m_NumRows; ++i) {
312 if (m_Table[i][m_NumCols-1] == value) {
313 int Nj = 0;
314 for (int j = 0; j < m_NumCols-3; ++j) {
315 if (m_Table[i][j] == "2") {
316 ++Nj;
319 int nj = 0;
320 for (int j = 0; j < m_NumCols-3; ++j) {
321 if (m_Table[i][j] == "2") {
322 QString bc = m_Ui.listWidget->item(j)->text().split(":")[1].trimmed();
323 text += bc;
324 ++nj;
325 if (nj < Nj) {
326 text += " <AND> ";
330 ++ni;
331 if (ni < Ni) {
332 text += " <OR>\n";
336 text += " = " + value + ";\n\n";
338 m_Ui.textEdit->setText(text);
341 void GuiCreateSurfaceMesh::getTableFromText()
343 QMap<QString, int> bc_map;
344 for (int i = 0; i < m_Ui.listWidget->count(); ++i) {
345 bc_map[m_Ui.listWidget->item(i)->text().split(":")[1].trimmed()] = i;
347 m_NumCols = bc_map.size() + 3;
348 QStringList rules = m_Ui.textEdit->toPlainText().split(";", QString::SkipEmptyParts);
349 m_Table.clear();
350 foreach (QString rule, rules) {
351 rule = rule.trimmed();
352 QStringList parts = rule.split("=");
353 if (parts.count() > 1) {
354 QString left = parts[0].trimmed();
355 QString right = parts[1].trimmed();
356 QStringList rows = left.split("<OR>");
357 foreach (QString row, rows) {
358 row = row.trimmed();
359 m_Table.append(QVector<QString>(m_NumCols, "1"));
360 int r = m_Table.count() - 1;
361 m_Table[r][m_NumCols - 3] = "any";
362 m_Table[r][m_NumCols - 2] = "";
363 m_Table[r][m_NumCols - 1] = right;
364 QStringList cols = row.split("<AND>");
365 foreach (QString col, cols) {
366 col = col.trimmed();
367 m_Table[r][bc_map[col]] = "2";
372 m_NumRows = m_Table.size();
375 void GuiCreateSurfaceMesh::operate()
377 writeSettings();
378 getTableFromText();
379 QString buffer = "";
381 QTextStream out(&buffer, QIODevice::WriteOnly);
382 out << "\n";
383 out << m_NumRows << " " << m_NumCols << "\n";
384 for (int row = 0; row < m_NumRows; ++row) {
385 for (int column = 0; column < m_NumCols; ++column) {
386 QString str = m_Table[row][column];
387 if (str.isEmpty()) {
388 str = "{{{empty}}}";
390 out << row << " " << column << " " << str << "\n";
394 GuiMainWindow::pointer()->setXmlSection("engrid/surface/table", buffer);
395 GuiMainWindow::pointer()->setXmlSection("engrid/blayer/rules", m_Ui.m_TextEditPrismaticLayers->toPlainText());
398 void GuiCreateSurfaceMesh::calc1()
400 // from number of layers
401 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
402 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
403 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
404 double h1 = h0*pow(s, double(N));
405 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
406 QString num;
407 num.setNum(H);
408 m_Ui.m_LineEditCalcTotalH->setText(num);
409 num.setNum(h1);
410 m_Ui.m_LineEditCalcH1->setText(num);
413 void GuiCreateSurfaceMesh::calc2()
415 double h0 = m_Ui.m_LineEditCalcH0->text().toDouble();
416 double h1 = m_Ui.m_LineEditCalcH1->text().toDouble();
417 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
418 int N = max(1, int(logarithm(s, h1/h0)));
419 double H = h0*(1.0 - pow(s, double(N)))/(1.0 - s);
420 QString num;
421 num.setNum(H);
422 m_Ui.m_LineEditCalcTotalH->setText(num);
423 m_Ui.m_SpinBoxCalcNumLayers->setValue(N);
426 void GuiCreateSurfaceMesh::calc3()
428 double H = m_Ui.m_LineEditCalcTotalH->text().toDouble();
429 int N = m_Ui.m_SpinBoxCalcNumLayers->value();
430 double s = m_Ui.m_DoubleSpinBoxBoundaryLayerStretchingRatio->value();
431 double h0 = H*(1.0 - s)/(1.0 - pow(s, double(N)));
432 double h1 = h0*pow(s, double(N));
433 QString num;
434 num.setNum(h0);
435 m_Ui.m_LineEditCalcH0->setText(num);
436 num.setNum(h1);
437 m_Ui.m_LineEditCalcH1->setText(num);