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 "operation.h"
23 #include "guimainwindow.h"
24 #include "egvtkobject.h"
25 #include "setboundarycode.h"
27 #include <vtkTriangleFilter.h>
28 #include <vtkInformation.h>
29 #include <vtkInformationVector.h>
30 #include <vtkObjectFactory.h>
31 #include <vtkPointData.h>
32 #include <vtkPolyData.h>
33 #include <vtkPolygon.h>
34 #include <vtkStreamingDemandDrivenPipeline.h>
35 #include <vtkCellArray.h>
36 #include <vtkCellData.h>
37 #include <vtkCellLocator.h>
38 #include <vtkFloatArray.h>
40 #include <vtkCharArray.h>
42 #include <QApplication>
45 #include "geometrytools.h"
47 using namespace GeometryTools
;
49 QSet
<Operation
*> Operation::garbage_operations
;
51 QVector
<vtkIdType
> m_static_DummyCells
;
52 QVector
<int> m_static_DummyRCells
;
53 QVector
<vtkIdType
> m_static_DummyNodes
;
54 QVector
<int> m_static_DummyRNodes
;
55 QVector
<QVector
<int> > m_static_DummyN2N
;
56 QVector
<QVector
<int> > m_static_DummyN2C
;
57 QVector
<QVector
<int> > m_static_DummyC2C
;
59 void Operation::collectGarbage()
61 QSet
<Operation
*> delete_operations
;
63 foreach (Operation
*op
, garbage_operations
)
65 if (!op
->getThread().isRunning()) {
66 delete_operations
.insert(op
);
67 cout
<< "deleting Operation " << op
<< endl
;
72 foreach (Operation
*op
, delete_operations
)
74 garbage_operations
.remove(op
);
78 Operation::Operation()
83 m_resetoperationcounter
= false;
86 m_TypeName
= "undefined";
87 m_MenuText
= "undefined";
91 Operation::~Operation()
101 garbage_operations
.insert(this);
104 void OperationThread::run()
107 GuiMainWindow::lock();
108 GuiMainWindow::pointer()->setBusy();
110 cout
<< "secs. for " << qPrintable(op
->getTypeName()) << ": " << op
->elapsedTime() << endl
;
111 } catch (Error err
) {
112 op
->err
= new Error();
115 GuiMainWindow::unlock();
116 GuiMainWindow::pointer()->setIdle();
119 void Operation::setTypeName(QString name
)
122 while ((i
< name
.size()) && (name
[i
].isDigit())) {
125 m_TypeName
= name
.right(name
.size() - i
);
128 void Operation::operator()()
132 if (GuiMainWindow::tryLock()) {
134 thread
.setOperation(this);
135 GuiMainWindow::unlock();
136 thread
.start(QThread::LowPriority
);
138 QMessageBox::warning(NULL
, "not permitted", "Operation is not permitted while background process is running!");
142 const bool gui_thread
= QThread::currentThread() == QCoreApplication::instance()->thread();
145 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor
));
147 QApplication::restoreOverrideCursor();
148 cout
<< "secs. for " << qPrintable(getTypeName()) << ": " << elapsedTime() << endl
;
149 } catch (Error err
) {
155 if(m_resetoperationcounter
) GuiMainWindow::pointer()->resetOperationCounter();
156 if(m_quicksave
) GuiMainWindow::pointer()->quickSave();
160 void Operation::setAllCells()
162 QVector
<vtkIdType
> all_cells
;
163 getAllCells(all_cells
, m_Grid
);
167 void Operation::setAllVolumeCells()
169 QVector
<vtkIdType
> cells
;
170 getAllVolumeCells(cells
, m_Grid
);
174 void Operation::setAllSurfaceCells()
176 QVector
<vtkIdType
> cells
;
177 getAllSurfaceCells(cells
, m_Grid
);
181 void Operation::setVolume(QString volume_name
)
183 m_Part
.setGrid(m_Grid
);
184 m_Part
.setVolume(volume_name
);
187 void Operation::setMeshPartition(const MeshPartition
&part
)
189 m_Part
.setGrid(part
.getGrid());
190 m_Part
.setCells(part
.getCells());
191 m_Grid
= m_Part
.getGrid();
194 void Operation::checkGrid()
196 if (m_Grid
== NULL
) {
197 m_Grid
= GuiMainWindow::pointer()->getGrid();
199 l2g_t cells
= getPartCells();
200 if ((cells
.size() == 0) && autoset
) {
205 void Operation::updateActors()
207 mainWindow()->updateActors();
210 GuiMainWindow
* Operation::mainWindow()
212 return GuiMainWindow::pointer();
215 void Operation::populateBoundaryCodes(QListWidget
*lw
)
218 mainWindow()->getAllBoundaryCodes(bcs
);
219 foreach(int bc
, bcs
) {
220 QListWidgetItem
*lwi
= new QListWidgetItem(lw
);
221 lwi
->setCheckState(Qt::Unchecked
);
223 QTextStream
ts(&text
);
224 ts
<< bc
<< " : " << GuiMainWindow::pointer()->getBC(bc
).getName();
226 lwi
->setFlags(Qt::ItemIsUserCheckable
| Qt::ItemIsEnabled
);
230 void Operation::populateVolumes(QListWidget
*lw
)
232 QList
<VolumeDefinition
> vols
= mainWindow()->getAllVols();
233 foreach (VolumeDefinition V
, vols
) {
234 QListWidgetItem
*lwi
= new QListWidgetItem(lw
);
235 lwi
->setText(V
.getName());
239 void Operation::eliminateDuplicateCells(bool surf_only
)
241 QVector
<QVector
<vtkIdType
> > cell_nodes(m_Grid
->GetNumberOfCells());
243 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
244 if (!surf_only
|| isSurface(id_cell
, m_Grid
)) {
245 EG_GET_CELL(id_cell
, m_Grid
);
246 QVector
<vtkIdType
> nodes(num_pts
);
247 for (int i
= 0; i
< num_pts
; ++i
) {
251 cell_nodes
[id_cell
] = nodes
;
254 QList
<vtkIdType
> new_cells
;
255 for (vtkIdType id_cell1
= 0; id_cell1
< m_Grid
->GetNumberOfCells(); ++id_cell1
) {
256 bool duplicate_cell
= false;
257 if (!surf_only
|| isSurface(id_cell1
, m_Grid
)) {
258 EG_GET_CELL(id_cell1
, m_Grid
);
259 for (int i
= 0; i
< num_pts
; ++i
) {
260 for (int j
= 0; j
< m_Part
.n2cGSize(pts
[i
]); ++j
) {
261 vtkIdType id_cell2
= m_Part
.n2cGG(pts
[i
], j
);
262 if (id_cell1
!= id_cell2
) {
263 if (!surf_only
|| isSurface(id_cell2
, m_Grid
)) {
264 if (cell_nodes
[id_cell1
] == cell_nodes
[id_cell2
]) {
265 duplicate_cell
= true;
273 if (!duplicate_cell
) {
274 new_cells
.append(id_cell1
);
277 EG_VTKSP(vtkUnstructuredGrid
, new_grid
);
278 makeCopy(m_Grid
, new_grid
, new_cells
);
279 makeCopy(new_grid
, m_Grid
);
282 void Operation::createFeatureBcs(double feature_angle
)
285 SetBoundaryCode set_bc
;
286 set_bc
.setGrid(m_Grid
);
287 set_bc
.setAllSurfaceCells();
288 QSet
<int> all_bcs
= GuiMainWindow::pointer()->getAllBoundaryCodes();
289 foreach (int bc
, all_bcs
) {
290 m_New2OldBc
[bc
] = bc
;
293 QMap
<int, QList
<vtkIdType
> > oldbc2cells
;
295 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
296 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
297 int bc
= cell_code
->GetValue(id_cell
);
298 max_bc
= max(max_bc
, bc
+ 1);
299 if (all_bcs
.contains(bc
)) {
300 oldbc2cells
[bc
] << id_cell
;
304 int old_max_bc
= max_bc
;
306 vtkIdType id_start
= -1;
307 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
308 if (cell_code
->GetValue(id_cell
) < old_max_bc
&& isSurface(id_cell
, m_Grid
)) {
310 set_bc
.setOLdBC(cell_code
->GetValue(id_cell
));
314 if (id_start
== -1) {
317 set_bc
.setFeatureAngle(feature_angle
);
318 set_bc
.setNewBC(max_bc
);
319 set_bc
.setProcessAll(true);
320 set_bc
.setSelectAllVisible(false);
321 set_bc
.setOnlyPickedCell(false);
322 set_bc
.setOnlyPickedCellAndNeighbours(false);
323 set_bc
.setStart(id_start
);
329 foreach (int bc
, oldbc2cells
.keys()) {
330 foreach (vtkIdType id_cell
, oldbc2cells
[bc
]) {
331 m_New2OldBc
[cell_code
->GetValue(id_cell
)] = bc
;
336 void Operation::restoreNormalBcs()
338 EG_VTKDCC(vtkIntArray
, cell_code
, m_Grid
, "cell_code");
339 for (vtkIdType id_cell
= 0; id_cell
< m_Grid
->GetNumberOfCells(); ++id_cell
) {
340 int bc
= cell_code
->GetValue(id_cell
);
341 cell_code
->SetValue(id_cell
, m_New2OldBc
[bc
]);