1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
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. +
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. +
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/>. +
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>
38 #include <vtkCellLocator.h>
39 #include <vtkFloatArray.h>
40 #include <vtkCellArray.h>
43 #include <QTextStream>
51 GuiCreateSurfaceMesh::GuiCreateSurfaceMesh()
57 populateBoundaryCodes(m_Ui
.listWidget
);
58 populateBoundaryCodes(m_Ui
.m_ListWidgetPrismaticLayers
);
59 m_Ui
.lineEditMaximalEdgeLength
->setText("1000");
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
);
74 in
>> m_NumRows
>> m_NumCols
;
79 if(m_NumCols
!= Nbc
+ 3) {
80 //m_NumCols = Nbc + 3;
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}}}") {
95 m_Table
[row
][column
] = str
;
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
);
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
);
131 m_Ui
.lineEditMaximalEdgeLength
->setText(str
);
133 m_Ui
.lineEditMinimalEdgeLength
->setText(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
);
141 if (num_bcs
== m_Ui
.listWidget
->count()) {
143 for (int i
= 0; i
< m_Ui
.listWidget
->count(); ++i
) {
145 if (check_state
== 1) {
146 m_Ui
.listWidget
->item(i
)->setCheckState(Qt::Checked
);
148 m_Ui
.listWidget
->item(i
)->setCheckState(Qt::Unchecked
);
154 m_Ui
.doubleSpinBox2DFeature
->setValue(v
);
156 m_Ui
.m_DoubleSpinBox3DFeature
->setValue(v
);
161 buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/blayer/settings");
162 if(!buffer
.isEmpty()) {
163 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
166 if (num_bcs
== m_Ui
.m_ListWidgetPrismaticLayers
->count()) {
168 for (int i
= 0; i
< m_Ui
.m_ListWidgetPrismaticLayers
->count(); ++i
) {
170 if (check_state
== 1) {
171 m_Ui
.m_ListWidgetPrismaticLayers
->item(i
)->setCheckState(Qt::Checked
);
173 m_Ui
.m_ListWidgetPrismaticLayers
->item(i
)->setCheckState(Qt::Unchecked
);
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
);
200 int GuiCreateSurfaceMesh::writeSettings()
204 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
218 out
<< m_Ui
.doubleSpinBox2DFeature
->value() << "\n";
219 out
<< m_Ui
.m_DoubleSpinBox3DFeature
->value() << "\n";
221 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer
);
225 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
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";
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());
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"));
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
) {
290 for (int i
= 0; i
< m_NumRows
; ++i
) {
291 if (m_Table
[i
][m_NumCols
-1] == value
) {
296 for (int i
= 0; i
< m_NumRows
; ++i
) {
297 if (m_Table
[i
][m_NumCols
-1] == value
) {
299 for (int j
= 0; j
< m_NumCols
-3; ++j
) {
300 if (m_Table
[i
][j
] == "2") {
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();
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
);
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
) {
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
) {
352 m_Table
[r
][bc_map
[col
]] = "2";
357 m_NumRows
= m_Table
.size();
360 void GuiCreateSurfaceMesh::operate()
366 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
];
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
);
393 m_Ui
.m_LineEditCalcTotalH
->setText(num
);
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
);
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
));
420 m_Ui
.m_LineEditCalcH0
->setText(num
);
422 m_Ui
.m_LineEditCalcH1
->setText(num
);