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").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
);
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
);
208 in
>> iv
; m_Ui
.m_SpinBoxBufferLayers
->setValue(iv
);
214 int GuiCreateSurfaceMesh::writeSettings()
218 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
232 out
<< m_Ui
.doubleSpinBox2DFeature
->value() << "\n";
233 out
<< m_Ui
.m_DoubleSpinBox3DFeature
->value() << "\n";
235 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer
);
239 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
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";
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());
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());
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
) {
305 for (int i
= 0; i
< m_NumRows
; ++i
) {
306 if (m_Table
[i
][m_NumCols
-1] == value
) {
311 for (int i
= 0; i
< m_NumRows
; ++i
) {
312 if (m_Table
[i
][m_NumCols
-1] == value
) {
314 for (int j
= 0; j
< m_NumCols
-3; ++j
) {
315 if (m_Table
[i
][j
] == "2") {
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();
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
);
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
) {
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
) {
367 m_Table
[r
][bc_map
[col
]] = "2";
372 m_NumRows
= m_Table
.size();
375 void GuiCreateSurfaceMesh::operate()
381 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
];
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
);
408 m_Ui
.m_LineEditCalcTotalH
->setText(num
);
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
);
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
));
435 m_Ui
.m_LineEditCalcH0
->setText(num
);
437 m_Ui
.m_LineEditCalcH1
->setText(num
);