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
);
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
);
197 int GuiCreateSurfaceMesh::writeSettings()
201 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
215 out
<< m_Ui
.doubleSpinBox2DFeature
->value() << "\n";
216 out
<< m_Ui
.m_DoubleSpinBox3DFeature
->value() << "\n";
218 GuiMainWindow::pointer()->setXmlSection("engrid/surface/settings", buffer
);
222 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
) {
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";
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());
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"));
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
) {
287 for (int i
= 0; i
< m_NumRows
; ++i
) {
288 if (m_Table
[i
][m_NumCols
-1] == value
) {
293 for (int i
= 0; i
< m_NumRows
; ++i
) {
294 if (m_Table
[i
][m_NumCols
-1] == value
) {
296 for (int j
= 0; j
< m_NumCols
-3; ++j
) {
297 if (m_Table
[i
][j
] == "2") {
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();
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
);
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
) {
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
) {
349 m_Table
[r
][bc_map
[col
]] = "2";
354 m_NumRows
= m_Table
.size();
357 void GuiCreateSurfaceMesh::operate()
363 QTextStream
out(&buffer
, QIODevice::WriteOnly
);
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
];
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
);
390 m_Ui
.m_LineEditCalcTotalH
->setText(num
);
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
);
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
));
417 m_Ui
.m_LineEditCalcH0
->setText(num
);
419 m_Ui
.m_LineEditCalcH1
->setText(num
);