fixed edge display for volume cells
[engrid-github.git] / src / libengrid / guicreatehexshell.cpp
blob85f68d1d909d96a206e326a0666c04091ec81b74
1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 // + +
3 // + This file is part of enGrid. +
4 // + +
5 // + Copyright 2008-2014 enGits GmbH +
6 // + +
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. +
11 // + +
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. +
16 // + +
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/>. +
19 // + +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #include "guicreatehexshell.h"
23 #include "guimainwindow.h"
25 GuiCreateHexShell::GuiCreateHexShell()
27 connect(m_Ui.spinBoxNx, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
28 connect(m_Ui.spinBoxNy, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
29 connect(m_Ui.spinBoxNz, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
30 connect(m_Ui.spinBoxLx1, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
31 connect(m_Ui.spinBoxLx2, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
32 connect(m_Ui.spinBoxLy1, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
33 connect(m_Ui.spinBoxLy2, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
34 connect(m_Ui.spinBoxLz1, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
35 connect(m_Ui.spinBoxLz2, SIGNAL(valueChanged(int)), this, SLOT(updateNumberOfCells(int)));
38 void GuiCreateHexShell::ijkCell(int idx, int &i, int &j, int &k)
40 i = idx/(m_NumJCells*m_NumKCells);
41 int rest = idx - i*(m_NumJCells*m_NumKCells);
42 j = rest/m_NumKCells;
43 k = rest - j*m_NumKCells;
46 void GuiCreateHexShell::ijkNode(int idx, int &i, int &j, int &k)
48 i = idx/(m_NumJNodes*m_NumKNodes);
49 int rest = idx - i*(m_NumJNodes*m_NumKNodes);
50 j = rest/m_NumKNodes;
51 k = rest - j*m_NumKNodes;
54 void GuiCreateHexShell::updateNumberOfCells(int)
56 int num_i1 = m_Ui.spinBoxNx->value();
57 int num_i2 = num_i1 + m_Ui.spinBoxLx1->value() + m_Ui.spinBoxLx2->value();
58 int num_j1 = m_Ui.spinBoxNy->value();
59 int num_j2 = num_j1 + m_Ui.spinBoxLy1->value() + m_Ui.spinBoxLy2->value();
60 int num_k1 = m_Ui.spinBoxNz->value();
61 int num_k2 = num_k1 + m_Ui.spinBoxLz1->value() + m_Ui.spinBoxLz2->value();
62 m_TotalNumberOfCells = num_i2*num_j2*num_k2 - num_i1*num_j1*num_k1;
63 int num_cells = m_TotalNumberOfCells;
64 QList<int> numbers;
65 while (num_cells > 0) {
66 numbers << num_cells % 1000;
67 num_cells /= 1000;
69 QString txt;
70 txt.setNum(numbers.last());
71 numbers.pop_back();
72 while (numbers.size() > 0) {
73 QString num;
74 num.setNum(numbers.last());
75 while (num.size() < 3) {
76 num = "0" + num;
78 txt += "," + num;
79 numbers.pop_back();
81 m_Ui.labelTotalNumberOfCells->setText(txt);
84 void GuiCreateHexShell::before()
86 EG_VTKDCN(vtkDoubleArray, cl, m_Grid, "node_meshdensity_desired");
87 m_H = 1e99;
88 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
89 m_H = min(m_H, cl->GetValue(id_node));
91 vec3_t x1( 1e99, 1e99, 1e99);
92 vec3_t x2(-1e99, -1e99, -1e99);
93 for (vtkIdType id_node = 0; id_node < m_Grid->GetNumberOfPoints(); ++id_node) {
94 vec3_t x;
95 m_Grid->GetPoint(id_node, x.data());
96 for (int i = 0; i < 3; ++i) {
97 x1[i] = min(x1[i], x[i]);
98 x2[i] = max(x2[i], x[i]);
101 x1 -= 5*vec3_t(m_H, m_H, m_H);
102 x2 += 5*vec3_t(m_H, m_H, m_H);
103 m_Ui.spinBoxNx->setValue(int((x2[0] - x1[0])/m_H));
104 m_Ui.spinBoxNy->setValue(int((x2[1] - x1[1])/m_H));
105 m_Ui.spinBoxNz->setValue(int((x2[2] - x1[2])/m_H));
106 setDouble(x1[0], m_Ui.lineEditX1);
107 setDouble(x1[1], m_Ui.lineEditY1);
108 setDouble(x1[2], m_Ui.lineEditZ1);
109 setDouble(x2[0], m_Ui.lineEditX2);
110 setDouble(x2[1], m_Ui.lineEditY2);
111 setDouble(x2[2], m_Ui.lineEditZ2);
112 updateNumberOfCells();
115 void GuiCreateHexShell::createGridWithNodes(vtkUnstructuredGrid *grid)
117 int num_nodes = 0;
118 m_NodeIDs.fill(-1, m_NumINodes*m_NumJNodes*m_NumKNodes);
119 vtkIdType id_node = 0;
120 for (int i = 0; i < m_NumINodes; ++i) {
121 for (int j = 0; j < m_NumJNodes; ++j) {
122 for (int k = 0; k < m_NumKNodes; ++k) {
123 bool in_core = true;
124 in_core = in_core && i > m_Ui.spinBoxLx1->value();
125 in_core = in_core && i < m_NumINodes - m_Ui.spinBoxLx2->value() - 1;
126 in_core = in_core && j > m_Ui.spinBoxLy1->value();
127 in_core = in_core && j < m_NumJNodes - m_Ui.spinBoxLy2->value() - 1;
128 in_core = in_core && k > m_Ui.spinBoxLz1->value();
129 in_core = in_core && k < m_NumKNodes - m_Ui.spinBoxLz2->value() - 1;
130 if (!in_core) {
131 ++num_nodes;
136 allocateGrid(grid, m_TotalNumberOfCells, num_nodes);
137 for (int i = 0; i < m_NumINodes; ++i) {
138 for (int j = 0; j < m_NumJNodes; ++j) {
139 for (int k = 0; k < m_NumKNodes; ++k) {
140 bool in_core = true;
141 in_core = in_core && i > m_Ui.spinBoxLx1->value();
142 in_core = in_core && i < m_NumINodes - m_Ui.spinBoxLx2->value() - 1;
143 in_core = in_core && j > m_Ui.spinBoxLy1->value();
144 in_core = in_core && j < m_NumJNodes - m_Ui.spinBoxLy2->value() - 1;
145 in_core = in_core && k > m_Ui.spinBoxLz1->value();
146 in_core = in_core && k < m_NumKNodes - m_Ui.spinBoxLz2->value() - 1;
147 if (!in_core) {
148 m_NodeIDs[indexNode(i,j,k)] = id_node;
149 grid->GetPoints()->SetPoint(id_node, x(i), y(j), z(k));
150 ++id_node;
157 void GuiCreateHexShell::createHexCells(vtkUnstructuredGrid *grid)
159 EG_VTKDCC(vtkIntArray, cell_code, grid, "cell_code");
160 m_CellIDs.fill(-1, m_NumICells*m_NumJCells*m_NumKCells);
161 for (int i = 0; i < m_NumICells; ++i) {
162 for (int j = 0; j < m_NumJCells; ++j) {
163 for (int k = 0; k < m_NumKCells; ++k) {
164 bool in_core = true;
165 in_core = in_core && i >= m_Ui.spinBoxLx1->value();
166 in_core = in_core && i < m_NumICells - m_Ui.spinBoxLx2->value();
167 in_core = in_core && j >= m_Ui.spinBoxLy1->value();
168 in_core = in_core && j < m_NumJCells - m_Ui.spinBoxLy2->value();
169 in_core = in_core && k >= m_Ui.spinBoxLz1->value();
170 in_core = in_core && k < m_NumKCells - m_Ui.spinBoxLz2->value();
171 if (!in_core) {
172 EG_VTKSP(vtkIdList, pts);
173 pts->SetNumberOfIds(8);
174 pts->SetId(0, m_NodeIDs[indexNode(i ,j ,k )]);
175 pts->SetId(1, m_NodeIDs[indexNode(i+1,j ,k )]);
176 pts->SetId(2, m_NodeIDs[indexNode(i+1,j+1,k )]);
177 pts->SetId(3, m_NodeIDs[indexNode(i ,j+1,k )]);
178 pts->SetId(4, m_NodeIDs[indexNode(i ,j ,k+1)]);
179 pts->SetId(5, m_NodeIDs[indexNode(i+1,j ,k+1)]);
180 pts->SetId(6, m_NodeIDs[indexNode(i+1,j+1,k+1)]);
181 pts->SetId(7, m_NodeIDs[indexNode(i ,j+1,k+1)]);
182 for (int i_pts = 0; i_pts < 8; ++i_pts) {
183 if (pts->GetId(i_pts) == -1) {
184 EG_BUG;
187 m_CellIDs[indexCell(i,j,k)] = grid->InsertNextCell(VTK_HEXAHEDRON, pts);
188 if (m_CellIDs[indexCell(i,j,k)] >= m_TotalNumberOfCells) {
189 EG_BUG;
191 cell_code->SetValue(m_CellIDs[indexCell(i,j,k)], 0);
198 void GuiCreateHexShell::defineBoundaryCodes()
200 QSet<int> bcs = mainWindow()->getAllBoundaryCodes();
201 m_InnerBC = 1;
202 foreach (int bc, bcs) {
203 m_InnerBC = max(bc, m_InnerBC);
205 ++m_InnerBC;
206 m_OuterBC = m_InnerBC + 1;
207 mainWindow()->addBC(m_InnerBC, BoundaryCondition("HexShellInside", "patch"));
208 mainWindow()->addBC(m_OuterBC, BoundaryCondition("HexShellOutside", "patch"));
211 void GuiCreateHexShell::createOuterBoundary(vtkUnstructuredGrid *grid)
213 EG_VTKSP(vtkUnstructuredGrid, new_grid);
214 allocateGrid(new_grid, grid->GetNumberOfCells() + 2*(m_NumICells*m_NumJCells + m_NumICells*m_NumKCells + m_NumJCells*m_NumKCells), grid->GetNumberOfPoints());
215 makeCopyNoAlloc(grid, new_grid);
216 EG_VTKDCC(vtkIntArray, cell_code, new_grid, "cell_code");
218 // left boundary
220 int i = 0;
221 for (int j = 0; j < m_NumJCells; ++j) {
222 for (int k = 0; k < m_NumKCells; ++k) {
223 vtkIdType id_cell = m_CellIDs[indexCell(i,j,k)];
224 if (id_cell == -1) {
225 EG_BUG;
227 QVector<vtkIdType> pts;
228 getFaceOfCell(new_grid, id_cell, 4, pts);
229 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_QUAD, 4, pts.data());
230 cell_code->SetValue(id_new_cell, m_OuterBC);
235 // right boundary
237 int i = m_NumICells - 1;
238 for (int j = 0; j < m_NumJCells; ++j) {
239 for (int k = 0; k < m_NumKCells; ++k) {
240 vtkIdType id_cell = m_CellIDs[indexCell(i,j,k)];
241 if (id_cell == -1) {
242 EG_BUG;
244 QVector<vtkIdType> pts;
245 getFaceOfCell(new_grid, id_cell, 5, pts);
246 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_QUAD, 4, pts.data());
247 cell_code->SetValue(id_new_cell, m_OuterBC);
252 // front boundary
254 for (int i = 0; i < m_NumICells; ++i) {
255 int j = 0;
256 for (int k = 0; k < m_NumKCells; ++k) {
257 vtkIdType id_cell = m_CellIDs[indexCell(i,j,k)];
258 if (id_cell == -1) {
259 EG_BUG;
261 QVector<vtkIdType> pts;
262 getFaceOfCell(new_grid, id_cell, 2, pts);
263 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_QUAD, 4, pts.data());
264 cell_code->SetValue(id_new_cell, m_OuterBC);
269 // back boundary
271 for (int i = 0; i < m_NumICells; ++i) {
272 int j = m_NumJCells - 1;
273 for (int k = 0; k < m_NumKCells; ++k) {
274 vtkIdType id_cell = m_CellIDs[indexCell(i,j,k)];
275 if (id_cell == -1) {
276 EG_BUG;
278 QVector<vtkIdType> pts;
279 getFaceOfCell(new_grid, id_cell, 3, pts);
280 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_QUAD, 4, pts.data());
281 cell_code->SetValue(id_new_cell, m_OuterBC);
286 // bottom boundary
288 for (int i = 0; i < m_NumICells; ++i) {
289 for (int j = 0; j < m_NumJCells; ++j) {
290 int k = 0;
291 vtkIdType id_cell = m_CellIDs[indexCell(i,j,k)];
292 if (id_cell == -1) {
293 EG_BUG;
295 QVector<vtkIdType> pts;
296 getFaceOfCell(new_grid, id_cell, 0, pts);
297 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_QUAD, 4, pts.data());
298 cell_code->SetValue(id_new_cell, m_OuterBC);
303 // top boundary
305 for (int i = 0; i < m_NumICells; ++i) {
306 for (int j = 0; j < m_NumJCells; ++j) {
307 int k = m_NumKCells - 1;
308 vtkIdType id_cell = m_CellIDs[indexCell(i,j,k)];
309 if (id_cell == -1) {
310 EG_BUG;
312 QVector<vtkIdType> pts;
313 getFaceOfCell(new_grid, id_cell, 1, pts);
314 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_QUAD, 4, pts.data());
315 cell_code->SetValue(id_new_cell, m_OuterBC);
320 makeCopy(new_grid, grid);
323 void GuiCreateHexShell::createInnerBoundary(vtkUnstructuredGrid *grid)
325 int num_new_nodes = 0;
326 int num_new_faces = 0;
327 MeshPartition part(grid, true);
328 QVector<bool> copy_cell(grid->GetNumberOfCells(), true);
329 for (vtkIdType id_cell = 0; id_cell < grid->GetNumberOfCells(); ++id_cell) {
330 if (isVolume(id_cell, grid)) {
331 bool face_found = false;
332 for (int i = 0; i < part.c2cGSize(id_cell); ++i) {
333 vtkIdType id_neigh = part.c2cGG(id_cell, i);
334 if (id_neigh == -1) {
335 if (face_found) {
336 EG_BUG;
337 } else {
338 num_new_faces += 4;
339 num_new_nodes += 1;
340 face_found = true;
341 copy_cell[id_cell] = false;
347 EG_VTKSP(vtkUnstructuredGrid, new_grid);
348 allocateGrid(new_grid, grid->GetNumberOfCells() + num_new_faces, grid->GetNumberOfPoints() + num_new_nodes);
349 for (vtkIdType id_node = 0; id_node < grid->GetNumberOfPoints(); ++id_node) {
350 vec3_t x;
351 grid->GetPoint(id_node, x.data());
352 new_grid->GetPoints()->SetPoint(id_node, x.data());
354 for (vtkIdType id_cell = 0; id_cell < grid->GetNumberOfCells(); ++id_cell) {
355 if (copy_cell[id_cell]) {
356 vtkIdType id_new_cell = copyCell(grid, id_cell, new_grid);
357 copyCellData(grid, id_cell, new_grid, id_new_cell);
360 EG_VTKDCC(vtkIntArray, cell_code, new_grid, "cell_code");
361 vtkIdType id_new_node = grid->GetNumberOfPoints();
362 for (vtkIdType id_cell = 0; id_cell < grid->GetNumberOfCells(); ++id_cell) {
363 if (isVolume(id_cell, grid)) {
364 int i_replace_face = -1;
365 QVector<QVector<vtkIdType> > triangles;
366 for (int i = 0; i < part.c2cGSize(id_cell); ++i) {
367 vtkIdType id_neigh = part.c2cGG(id_cell, i);
368 if (id_neigh == -1) {
369 i_replace_face = i;
370 QVector<vtkIdType> pts;
371 getFaceOfCell(grid, id_cell, i, pts);
372 if (pts.size() != 4) {
373 EG_BUG;
375 vec3_t xc(0,0,0);
376 foreach (vtkIdType id_node, pts) {
377 vec3_t x;
378 grid->GetPoint(id_node, x.data());
379 xc += x;
381 xc *= 0.25;
382 new_grid->GetPoints()->SetPoint(id_new_node, xc.data());
383 pts.append(pts.first());
384 for (int j = 0; j < 4; ++j) {
385 QVector<vtkIdType> triangle(3);
386 triangle[0] = pts[j];
387 triangle[1] = pts[j+1];
388 triangle[2] = id_new_node;
389 vtkIdType id_new_face = new_grid->InsertNextCell(VTK_TRIANGLE, 3, triangle.data());
390 cell_code->SetValue(id_new_face, m_InnerBC);
391 triangles.push_back(triangle);
393 ++id_new_node;
396 if (i_replace_face != -1) {
397 EG_VTKSP(vtkIdList, stream);
398 stream->SetNumberOfIds(42);
399 vtkIdType id = 0;
400 stream->SetId(id++, 9);
401 for (int i = 0; i < 6; ++i) {
402 if (i != i_replace_face) {
403 stream->SetId(id++, 4);
404 QVector<vtkIdType> pts;
405 getFaceOfCell(grid, id_cell, i, pts);
406 if (pts.size() != 4) {
407 EG_BUG;
409 foreach (vtkIdType id_node, pts) {
410 stream->SetId(id++, id_node);
414 foreach (QVector<vtkIdType> triangle, triangles) {
415 stream->SetId(id++, 3);
416 foreach (vtkIdType id_node, triangle) {
417 stream->SetId(id++, id_node);
420 vtkIdType id_new_cell = new_grid->InsertNextCell(VTK_POLYHEDRON, stream);
421 copyCellData(grid, id_cell, new_grid, id_new_cell);
425 makeCopy(new_grid, grid);
428 void GuiCreateHexShell::createSourceBox()
430 QString xml_text = mainWindow()->getXmlSection("engrid/sources");
432 QTextStream s(&xml_text);
433 s << "box: HexShell; " << m_X0 << "; " << m_Y0 << "; " << m_Z0 << "; ";
434 s << m_X0 + m_NumICells*m_Dx << "; ";
435 s << m_Y0 + m_NumJCells*m_Dy << "; ";
436 s << m_Z0 + m_NumKCells*m_Dz << "; ";
437 s << 1.5*min(m_Dx, min(m_Dy, m_Dz)) << ";\n";
439 mainWindow()->setXmlSection("engrid/sources", xml_text);
442 void GuiCreateHexShell::operate()
444 m_NumICells = m_Ui.spinBoxNx->value() + m_Ui.spinBoxLx1->value() + m_Ui.spinBoxLx2->value();
445 m_NumJCells = m_Ui.spinBoxNy->value() + m_Ui.spinBoxLy1->value() + m_Ui.spinBoxLy2->value();
446 m_NumKCells = m_Ui.spinBoxNz->value() + m_Ui.spinBoxLz1->value() + m_Ui.spinBoxLz2->value();
447 m_NumINodes = m_NumICells + 1;
448 m_NumJNodes = m_NumJCells + 1;
449 m_NumKNodes = m_NumKCells + 1;
450 double x1 = m_Ui.lineEditX1->text().toDouble();
451 double x2 = m_Ui.lineEditX2->text().toDouble();
452 double y1 = m_Ui.lineEditY1->text().toDouble();
453 double y2 = m_Ui.lineEditY2->text().toDouble();
454 double z1 = m_Ui.lineEditZ1->text().toDouble();
455 double z2 = m_Ui.lineEditZ2->text().toDouble();
456 m_Dx = (x2 - x1)/m_Ui.spinBoxNx->value();
457 m_Dy = (y2 - y1)/m_Ui.spinBoxNy->value();
458 m_Dz = (z2 - z1)/m_Ui.spinBoxNz->value();
459 m_X0 = x1 - m_Ui.spinBoxLx1->value()*m_Dx;
460 m_Y0 = y1 - m_Ui.spinBoxLy1->value()*m_Dy;
461 m_Z0 = z1 - m_Ui.spinBoxLz1->value()*m_Dz;
462 EG_VTKSP(vtkUnstructuredGrid, shell_grid);
463 createGridWithNodes(shell_grid);
464 createHexCells(shell_grid);
465 defineBoundaryCodes();
466 createOuterBoundary(shell_grid);
467 createInnerBoundary(shell_grid);
468 MeshPartition shell_part(shell_grid, true);
469 m_Part.addPartition(shell_part);
470 createSourceBox();
471 mainWindow()->updateBoundaryCodes(true);