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()));
120 connect(m_Ui
.m_PassBandSlider
, SIGNAL(valueChanged(int)), this, SLOT(displayPb(int)));
125 void GuiCreateSurfaceMesh::displayPb(int v
)
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
);
142 m_Ui
.lineEditMaximalEdgeLength
->setText(str
);
144 m_Ui
.lineEditMinimalEdgeLength
->setText(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
);
152 if (num_bcs
== m_Ui
.listWidget
->count()) {
154 for (int i
= 0; i
< m_Ui
.listWidget
->count(); ++i
) {
156 if (check_state
== 1) {
157 m_Ui
.listWidget
->item(i
)->setCheckState(Qt::Checked
);
159 m_Ui
.listWidget
->item(i
)->setCheckState(Qt::Unchecked
);
165 m_Ui
.doubleSpinBox2DFeature
->setValue(v
);
167 m_Ui
.m_DoubleSpinBox3DFeature
->setValue(v
);
172 buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/blayer/settings");
173 if(!buffer
.isEmpty()) {
174 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
177 if (num_bcs
== m_Ui
.m_ListWidgetPrismaticLayers
->count()) {
179 for (int i
= 0; i
< m_Ui
.m_ListWidgetPrismaticLayers
->count(); ++i
) {
181 if (check_state
== 1) {
182 m_Ui
.m_ListWidgetPrismaticLayers
->item(i
)->setCheckState(Qt::Checked
);
184 m_Ui
.m_ListWidgetPrismaticLayers
->item(i
)->setCheckState(Qt::Unchecked
);
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
);
213 int GuiCreateSurfaceMesh::writeSettings()
217 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
231 out
<< m_Ui
.doubleSpinBox2DFeature
->value() << "\n";
232 out
<< m_Ui
.m_DoubleSpinBox3DFeature
->value() << "\n";
234 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer
);
238 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
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";
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());
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"));
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
) {
303 for (int i
= 0; i
< m_NumRows
; ++i
) {
304 if (m_Table
[i
][m_NumCols
-1] == value
) {
309 for (int i
= 0; i
< m_NumRows
; ++i
) {
310 if (m_Table
[i
][m_NumCols
-1] == value
) {
312 for (int j
= 0; j
< m_NumCols
-3; ++j
) {
313 if (m_Table
[i
][j
] == "2") {
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();
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
);
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
) {
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
) {
365 m_Table
[r
][bc_map
[col
]] = "2";
370 m_NumRows
= m_Table
.size();
373 void GuiCreateSurfaceMesh::operate()
379 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
];
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
);
406 m_Ui
.m_LineEditCalcTotalH
->setText(num
);
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
);
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
));
433 m_Ui
.m_LineEditCalcH0
->setText(num
);
435 m_Ui
.m_LineEditCalcH1
->setText(num
);