Skip to content

Commit 1841bab

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

File tree

1 file changed

+59
-68
lines changed

1 file changed

+59
-68
lines changed

src/Mod/Fem/App/FemVTKTools.cpp

+59-68
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,8 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
309309
{
310310
Base::Console().Log(" Start: VTK mesh builder faces.\n");
311311

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();
312+
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
313+
std::vector<VTKCellType> types;
316314

317315
for (; aFaceIter->more();) {
318316
const SMDS_MeshFace* aFace = aFaceIter->next();
@@ -324,7 +322,8 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
324322
tria->GetPointIds()->SetId(1, aFace->GetNode(1)->GetID() - 1);
325323
tria->GetPointIds()->SetId(2, aFace->GetNode(2)->GetID() - 1);
326324

327-
triangleArray->InsertNextCell(tria);
325+
elemArray->InsertNextCell(tria);
326+
types.push_back(VTK_TRIANGLE);
328327
}
329328
// quad
330329
else if (aFace->NbNodes() == 4) {
@@ -334,7 +333,8 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
334333
quad->GetPointIds()->SetId(2, aFace->GetNode(2)->GetID() - 1);
335334
quad->GetPointIds()->SetId(3, aFace->GetNode(3)->GetID() - 1);
336335

337-
quadArray->InsertNextCell(quad);
336+
elemArray->InsertNextCell(quad);
337+
types.push_back(VTK_QUAD);
338338
}
339339
// quadratic triangle
340340
else if (aFace->NbNodes() == 6) {
@@ -346,7 +346,9 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
346346
tria->GetPointIds()->SetId(3, aFace->GetNode(3)->GetID() - 1);
347347
tria->GetPointIds()->SetId(4, aFace->GetNode(4)->GetID() - 1);
348348
tria->GetPointIds()->SetId(5, aFace->GetNode(5)->GetID() - 1);
349-
quadTriangleArray->InsertNextCell(tria);
349+
350+
elemArray->InsertNextCell(tria);
351+
types.push_back(VTK_QUADRATIC_TRIANGLE);
350352
}
351353
// quadratic quad
352354
else if (aFace->NbNodes() == 8) {
@@ -360,26 +362,25 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
360362
quad->GetPointIds()->SetId(6, aFace->GetNode(6)->GetID() - 1);
361363
quad->GetPointIds()->SetId(7, aFace->GetNode(7)->GetID() - 1);
362364

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

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

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

381-
if (quadQuadArray->GetNumberOfCells() > 0) {
382-
grid->SetCells(VTK_QUADRATIC_QUAD, quadQuadArray);
383+
grid->SetCells(cellTypes, elemArray);
383384
}
384385

385386
Base::Console().Log(" End: VTK mesh builder faces.\n");
@@ -390,14 +391,8 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
390391
{
391392
Base::Console().Log(" Start: VTK mesh builder volumes.\n");
392393

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();
394+
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
395+
std::vector<VTKCellType> types;
401396

402397
for (; aVolIter->more();) {
403398
const SMDS_MeshVolume* aVol = aVolIter->next();
@@ -409,7 +404,9 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
409404
cell->GetPointIds()->SetId(1, aVol->GetNode(1)->GetID() - 1);
410405
cell->GetPointIds()->SetId(2, aVol->GetNode(2)->GetID() - 1);
411406
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID() - 1);
412-
tetraArray->InsertNextCell(cell);
407+
408+
elemArray->InsertNextCell(cell);
409+
types.push_back(VTK_TETRA);
413410
}
414411
else if (aVol->NbNodes() == 5) { // pyra5
415412
Base::Console().Log(" Volume pyra5\n");
@@ -419,7 +416,9 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
419416
cell->GetPointIds()->SetId(2, aVol->GetNode(2)->GetID() - 1);
420417
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID() - 1);
421418
cell->GetPointIds()->SetId(4, aVol->GetNode(4)->GetID() - 1);
422-
pyramidArray->InsertNextCell(cell);
419+
420+
elemArray->InsertNextCell(cell);
421+
types.push_back(VTK_PYRAMID);
423422
}
424423
else if (aVol->NbNodes() == 6) { // penta6
425424
Base::Console().Log(" Volume penta6\n");
@@ -430,7 +429,9 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
430429
cell->GetPointIds()->SetId(3, aVol->GetNode(3)->GetID() - 1);
431430
cell->GetPointIds()->SetId(4, aVol->GetNode(4)->GetID() - 1);
432431
cell->GetPointIds()->SetId(5, aVol->GetNode(5)->GetID() - 1);
433-
wedgeArray->InsertNextCell(cell);
432+
433+
elemArray->InsertNextCell(cell);
434+
types.push_back(VTK_WEDGE);
434435
}
435436
else if (aVol->NbNodes() == 8) { // hexa8
436437
Base::Console().Log(" Volume hexa8\n");
@@ -443,33 +444,40 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
443444
cell->GetPointIds()->SetId(5, aVol->GetNode(5)->GetID() - 1);
444445
cell->GetPointIds()->SetId(6, aVol->GetNode(6)->GetID() - 1);
445446
cell->GetPointIds()->SetId(7, aVol->GetNode(7)->GetID() - 1);
446-
hexaArray->InsertNextCell(cell);
447+
448+
elemArray->InsertNextCell(cell);
449+
types.push_back(VTK_HEXAHEDRON);
447450
}
448451
else if (aVol->NbNodes() == 10) { // tetra10
449452
Base::Console().Log(" Volume tetra10\n");
450-
vtkSmartPointer<vtkQuadraticTetra> tetra = vtkSmartPointer<vtkQuadraticTetra>::New();
453+
vtkSmartPointer<vtkQuadraticTetra> cell = vtkSmartPointer<vtkQuadraticTetra>::New();
451454
for (int i = 0; i < 10; i++) {
452-
tetra->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
455+
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
453456
}
454-
quadTetraArray->InsertNextCell(tetra);
457+
458+
elemArray->InsertNextCell(cell);
459+
types.push_back(VTK_QUADRATIC_TETRA);
455460
}
456461

457462
else if (aVol->NbNodes() == 13) { // pyra13
458463
Base::Console().Log(" Volume pyra13\n");
459464
vtkSmartPointer<vtkQuadraticPyramid> cell = vtkSmartPointer<vtkQuadraticPyramid>::New();
460465
for (int i = 0; i < 13; i++) {
461466
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
462-
// Base::Console().Log("node ids: %i\n", aVol->GetNode(i)->GetID()-1);
463467
}
464-
quadPyramidArray->InsertNextCell(cell);
468+
469+
elemArray->InsertNextCell(cell);
470+
types.push_back(VTK_QUADRATIC_PYRAMID);
465471
}
466472
else if (aVol->NbNodes() == 15) { // penta15
467473
Base::Console().Log(" Volume penta15\n");
468474
vtkSmartPointer<vtkQuadraticWedge> cell = vtkSmartPointer<vtkQuadraticWedge>::New();
469475
for (int i = 0; i < 15; i++) {
470476
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
471477
}
472-
quadWedgeArray->InsertNextCell(cell);
478+
479+
elemArray->InsertNextCell(cell);
480+
types.push_back(VTK_QUADRATIC_WEDGE);
473481
}
474482
else if (aVol->NbNodes() == 20) { // hexa20
475483
Base::Console().Log(" Volume hexa20\n");
@@ -478,43 +486,26 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
478486
for (int i = 0; i < 20; i++) {
479487
cell->GetPointIds()->SetId(i, aVol->GetNode(i)->GetID() - 1);
480488
}
481-
quadHexaArray->InsertNextCell(cell);
489+
490+
elemArray->InsertNextCell(cell);
491+
types.push_back(VTK_QUADRATIC_HEXAHEDRON);
482492
}
483493
else {
484-
throw std::runtime_error("Volume not yet supported by FreeCAD's VTK mesh builder\n");
494+
throw Base::TypeError("Volume not yet supported by FreeCAD's VTK mesh builder\n");
485495
}
486496
}
487497

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-
}
498+
vtkIdType nCells = elemArray->GetNumberOfCells();
507499

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-
}
500+
if (nCells > 0) {
501+
auto cellTypes = vtkSmartPointer<vtkUnsignedCharArray>::New();
502+
cellTypes->SetNumberOfTuples(nCells);
503+
auto typeRange = vtk::DataArrayValueRange<1>(cellTypes);
504+
std::transform(types.cbegin(), types.cend(), typeRange.begin(), [](int t) -> unsigned char {
505+
return static_cast<unsigned char>(t);
506+
});
515507

516-
if (quadHexaArray->GetNumberOfCells() > 0) {
517-
grid->SetCells(VTK_QUADRATIC_HEXAHEDRON, quadHexaArray);
508+
grid->SetCells(cellTypes, elemArray);
518509
}
519510

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

0 commit comments

Comments
 (0)