Skip to content

Commit 32540f7

Browse files
committed
Fem: Use mixed cell types in pipeline unstructured grid - fixes FreeCAD#12581
1 parent 0420f72 commit 32540f7

File tree

1 file changed

+60
-68
lines changed

1 file changed

+60
-68
lines changed

src/Mod/Fem/App/FemVTKTools.cpp

+60-68
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include <vtkQuadraticWedge.h>
5252
#include <vtkTetra.h>
5353
#include <vtkTriangle.h>
54+
#include <vtkUnsignedCharArray.h>
5455
#include <vtkUnstructuredGrid.h>
5556
#include <vtkWedge.h>
5657
#include <vtkXMLPUnstructuredGridReader.h>
@@ -309,10 +310,8 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
309310
{
310311
Base::Console().Log(" Start: VTK mesh builder faces.\n");
311312

312-
vtkSmartPointer<vtkCellArray> triangleArray = vtkSmartPointer<vtkCellArray>::New();
313-
vtkSmartPointer<vtkCellArray> quadTriangleArray = vtkSmartPointer<vtkCellArray>::New();
314-
vtkSmartPointer<vtkCellArray> quadArray = vtkSmartPointer<vtkCellArray>::New();
315-
vtkSmartPointer<vtkCellArray> quadQuadArray = vtkSmartPointer<vtkCellArray>::New();
313+
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
314+
std::vector<VTKCellType> types;
316315

317316
for (; aFaceIter->more();) {
318317
const SMDS_MeshFace* aFace = aFaceIter->next();
@@ -324,7 +323,8 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
324323
tria->GetPointIds()->SetId(1, aFace->GetNode(1)->GetID() - 1);
325324
tria->GetPointIds()->SetId(2, aFace->GetNode(2)->GetID() - 1);
326325

327-
triangleArray->InsertNextCell(tria);
326+
elemArray->InsertNextCell(tria);
327+
types.push_back(VTK_TRIANGLE);
328328
}
329329
// quad
330330
else if (aFace->NbNodes() == 4) {
@@ -334,7 +334,8 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
334334
quad->GetPointIds()->SetId(2, aFace->GetNode(2)->GetID() - 1);
335335
quad->GetPointIds()->SetId(3, aFace->GetNode(3)->GetID() - 1);
336336

337-
quadArray->InsertNextCell(quad);
337+
elemArray->InsertNextCell(quad);
338+
types.push_back(VTK_QUAD);
338339
}
339340
// quadratic triangle
340341
else if (aFace->NbNodes() == 6) {
@@ -346,7 +347,9 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
346347
tria->GetPointIds()->SetId(3, aFace->GetNode(3)->GetID() - 1);
347348
tria->GetPointIds()->SetId(4, aFace->GetNode(4)->GetID() - 1);
348349
tria->GetPointIds()->SetId(5, aFace->GetNode(5)->GetID() - 1);
349-
quadTriangleArray->InsertNextCell(tria);
350+
351+
elemArray->InsertNextCell(tria);
352+
types.push_back(VTK_QUADRATIC_TRIANGLE);
350353
}
351354
// quadratic quad
352355
else if (aFace->NbNodes() == 8) {
@@ -360,26 +363,25 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
360363
quad->GetPointIds()->SetId(6, aFace->GetNode(6)->GetID() - 1);
361364
quad->GetPointIds()->SetId(7, aFace->GetNode(7)->GetID() - 1);
362365

363-
quadQuadArray->InsertNextCell(quad);
366+
elemArray->InsertNextCell(quad);
367+
types.push_back(VTK_QUADRATIC_QUAD);
364368
}
365369
else {
366-
throw std::runtime_error("Face not yet supported by FreeCAD's VTK mesh builder\n");
370+
throw Base::TypeError("Face not yet supported by FreeCAD's VTK mesh builder\n");
367371
}
368372
}
369-
if (triangleArray->GetNumberOfCells() > 0) {
370-
grid->SetCells(VTK_TRIANGLE, triangleArray);
371-
}
372373

373-
if (quadArray->GetNumberOfCells() > 0) {
374-
grid->SetCells(VTK_QUAD, quadArray);
375-
}
374+
vtkIdType nCells = elemArray->GetNumberOfCells();
376375

377-
if (quadTriangleArray->GetNumberOfCells() > 0) {
378-
grid->SetCells(VTK_QUADRATIC_TRIANGLE, quadTriangleArray);
379-
}
376+
if (nCells > 0) {
377+
auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
378+
cellTypes->SetNumberOfTuples(nCells);
379+
auto typeRange = vtk::DataArrayValueRange<1>(cellTypes);
380+
std::transform(types.cbegin(), types.cend(), typeRange.begin(), [](int t) -> unsigned char {
381+
return static_cast<unsigned char>(t);
382+
});
380383

381-
if (quadQuadArray->GetNumberOfCells() > 0) {
382-
grid->SetCells(VTK_QUADRATIC_QUAD, quadQuadArray);
384+
grid->SetCells(cellTypes, elemArray);
383385
}
384386

385387
Base::Console().Log(" End: VTK mesh builder faces.\n");
@@ -390,14 +392,8 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
390392
{
391393
Base::Console().Log(" Start: VTK mesh builder volumes.\n");
392394

393-
vtkSmartPointer<vtkCellArray> tetraArray = vtkSmartPointer<vtkCellArray>::New();
394-
vtkSmartPointer<vtkCellArray> pyramidArray = vtkSmartPointer<vtkCellArray>::New();
395-
vtkSmartPointer<vtkCellArray> wedgeArray = vtkSmartPointer<vtkCellArray>::New();
396-
vtkSmartPointer<vtkCellArray> hexaArray = vtkSmartPointer<vtkCellArray>::New();
397-
vtkSmartPointer<vtkCellArray> quadTetraArray = vtkSmartPointer<vtkCellArray>::New();
398-
vtkSmartPointer<vtkCellArray> quadPyramidArray = vtkSmartPointer<vtkCellArray>::New();
399-
vtkSmartPointer<vtkCellArray> quadWedgeArray = vtkSmartPointer<vtkCellArray>::New();
400-
vtkSmartPointer<vtkCellArray> quadHexaArray = vtkSmartPointer<vtkCellArray>::New();
395+
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
396+
std::vector<VTKCellType> types;
401397

402398
for (; aVolIter->more();) {
403399
const SMDS_MeshVolume* aVol = aVolIter->next();
@@ -409,7 +405,9 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
409405
cell->GetPointIds()->SetId(1, aVol->GetNode(1)->GetID() - 1);
410406
cell->GetPointIds()->SetId(2, aVol->GetNode(2)->GetID() - 1);
411407
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID() - 1);
412-
tetraArray->InsertNextCell(cell);
408+
409+
elemArray->InsertNextCell(cell);
410+
types.push_back(VTK_TETRA);
413411
}
414412
else if (aVol->NbNodes() == 5) { // pyra5
415413
Base::Console().Log(" Volume pyra5\n");
@@ -419,7 +417,9 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
419417
cell->GetPointIds()->SetId(2, aVol->GetNode(2)->GetID() - 1);
420418
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID() - 1);
421419
cell->GetPointIds()->SetId(4, aVol->GetNode(4)->GetID() - 1);
422-
pyramidArray->InsertNextCell(cell);
420+
421+
elemArray->InsertNextCell(cell);
422+
types.push_back(VTK_PYRAMID);
423423
}
424424
else if (aVol->NbNodes() == 6) { // penta6
425425
Base::Console().Log(" Volume penta6\n");
@@ -430,7 +430,9 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
430430
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID() - 1);
431431
cell->GetPointIds()->SetId(4, aVol->GetNode(4)->GetID() - 1);
432432
cell->GetPointIds()->SetId(5, aVol->GetNode(5)->GetID() - 1);
433-
wedgeArray->InsertNextCell(cell);
433+
434+
elemArray->InsertNextCell(cell);
435+
types.push_back(VTK_WEDGE);
434436
}
435437
else if (aVol->NbNodes() == 8) { // hexa8
436438
Base::Console().Log(" Volume hexa8\n");
@@ -443,33 +445,40 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
443445
cell->GetPointIds()->SetId(5, aVol->GetNode(5)->GetID() - 1);
444446
cell->GetPointIds()->SetId(6, aVol->GetNode(6)->GetID() - 1);
445447
cell->GetPointIds()->SetId(7, aVol->GetNode(7)->GetID() - 1);
446-
hexaArray->InsertNextCell(cell);
448+
449+
elemArray->InsertNextCell(cell);
450+
types.push_back(VTK_HEXAHEDRON);
447451
}
448452
else if (aVol->NbNodes() == 10) { // tetra10
449453
Base::Console().Log(" Volume tetra10\n");
450-
vtkSmartPointer<vtkQuadraticTetra> tetra = vtkSmartPointer<vtkQuadraticTetra>::New();
454+
vtkSmartPointer<vtkQuadraticTetra> cell = vtkSmartPointer<vtkQuadraticTetra>::New();
451455
for (int i = 0; i < 10; i++) {
452-
tetra->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
456+
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
453457
}
454-
quadTetraArray->InsertNextCell(tetra);
458+
459+
elemArray->InsertNextCell(cell);
460+
types.push_back(VTK_QUADRATIC_TETRA);
455461
}
456462

457463
else if (aVol->NbNodes() == 13) { // pyra13
458464
Base::Console().Log(" Volume pyra13\n");
459465
vtkSmartPointer<vtkQuadraticPyramid> cell = vtkSmartPointer<vtkQuadraticPyramid>::New();
460466
for (int i = 0; i < 13; i++) {
461467
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
462-
// Base::Console().Log("node ids: %i\n", aVol->GetNode(i)->GetID()-1);
463468
}
464-
quadPyramidArray->InsertNextCell(cell);
469+
470+
elemArray->InsertNextCell(cell);
471+
types.push_back(VTK_QUADRATIC_PYRAMID);
465472
}
466473
else if (aVol->NbNodes() == 15) { // penta15
467474
Base::Console().Log(" Volume penta15\n");
468475
vtkSmartPointer<vtkQuadraticWedge> cell = vtkSmartPointer<vtkQuadraticWedge>::New();
469476
for (int i = 0; i < 15; i++) {
470477
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
471478
}
472-
quadWedgeArray->InsertNextCell(cell);
479+
480+
elemArray->InsertNextCell(cell);
481+
types.push_back(VTK_QUADRATIC_WEDGE);
473482
}
474483
else if (aVol->NbNodes() == 20) { // hexa20
475484
Base::Console().Log(" Volume hexa20\n");
@@ -478,43 +487,26 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
478487
for (int i = 0; i < 20; i++) {
479488
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
480489
}
481-
quadHexaArray->InsertNextCell(cell);
490+
491+
elemArray->InsertNextCell(cell);
492+
types.push_back(VTK_QUADRATIC_HEXAHEDRON);
482493
}
483494
else {
484-
throw std::runtime_error("Volume not yet supported by FreeCAD's VTK mesh builder\n");
495+
throw Base::TypeError("Volume not yet supported by FreeCAD's VTK mesh builder\n");
485496
}
486497
}
487498

488-
if (tetraArray->GetNumberOfCells() > 0) {
489-
grid->SetCells(VTK_TETRA, tetraArray);
490-
}
491-
492-
if (pyramidArray->GetNumberOfCells() > 0) {
493-
grid->SetCells(VTK_PYRAMID, pyramidArray);
494-
}
495-
496-
if (wedgeArray->GetNumberOfCells() > 0) {
497-
grid->SetCells(VTK_WEDGE, wedgeArray);
498-
}
499-
500-
if (hexaArray->GetNumberOfCells() > 0) {
501-
grid->SetCells(VTK_HEXAHEDRON, hexaArray);
502-
}
503-
504-
if (quadTetraArray->GetNumberOfCells() > 0) {
505-
grid->SetCells(VTK_QUADRATIC_TETRA, quadTetraArray);
506-
}
499+
vtkIdType nCells = elemArray->GetNumberOfCells();
507500

508-
if (quadPyramidArray->GetNumberOfCells() > 0) {
509-
grid->SetCells(VTK_QUADRATIC_PYRAMID, quadPyramidArray);
510-
}
511-
512-
if (quadWedgeArray->GetNumberOfCells() > 0) {
513-
grid->SetCells(VTK_QUADRATIC_WEDGE, quadWedgeArray);
514-
}
501+
if (nCells > 0) {
502+
auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
503+
cellTypes->SetNumberOfTuples(nCells);
504+
auto typeRange = vtk::DataArrayValueRange<1>(cellTypes);
505+
std::transform(types.cbegin(), types.cend(), typeRange.begin(), [](int t) -> unsigned char {
506+
return static_cast<unsigned char>(t);
507+
});
515508

516-
if (quadHexaArray->GetNumberOfCells() > 0) {
517-
grid->SetCells(VTK_QUADRATIC_HEXAHEDRON, quadHexaArray);
509+
grid->SetCells(cellTypes, elemArray);
518510
}
519511

520512
Base::Console().Log(" End: VTK mesh builder volumes.\n");

0 commit comments

Comments
 (0)