diff --git a/src/Mod/Fem/App/AppFemPy.cpp b/src/Mod/Fem/App/AppFemPy.cpp index b39da210cd..8ea2d2e254 100644 --- a/src/Mod/Fem/App/AppFemPy.cpp +++ b/src/Mod/Fem/App/AppFemPy.cpp @@ -196,9 +196,12 @@ private: throw Py::Exception(); } - std::string EncodedName = std::string(Name); + Base::FileInfo file(Name); PyMem_Free(Name); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Fem"); + Py::Sequence list(object); Base::Type meshId = Base::Type::fromName("Fem::FemMeshObject"); for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { @@ -207,7 +210,25 @@ private: App::DocumentObject* obj = static_cast(item)->getDocumentObjectPtr(); if (obj->getTypeId().isDerivedFrom(meshId)) { - static_cast(obj)->FemMesh.getValue().write(EncodedName.c_str()); + auto femMesh = static_cast(obj)->FemMesh.getValue(); + if (file.hasExtension({"vtk", "vtu"})) { + // get VTK prefs + ParameterGrp::handle g = hGrp->GetGroup("InOutVtk"); + std::string level = g->GetASCII("MeshExportLevel", "Highest"); + femMesh.writeVTK(file.filePath().c_str(), + level == "Highest" ? true : false); + } + else if (file.hasExtension("inp")) { + // get Abaqus inp prefs + ParameterGrp::handle g = hGrp->GetGroup("Abaqus"); + int elemParam = g->GetInt("AbaqusElementChoice", 1); + bool groupParam = g->GetBool("AbaqusWriteGroups", false); + // write ABAQUS Output + femMesh.writeABAQUS(file.filePath(), elemParam, groupParam); + } + else { + femMesh.write(file.filePath().c_str()); + } return Py::None(); } } diff --git a/src/Mod/Fem/App/FemMesh.cpp b/src/Mod/Fem/App/FemMesh.cpp index 2f1f8b0cc3..05eed1749f 100644 --- a/src/Mod/Fem/App/FemMesh.cpp +++ b/src/Mod/Fem/App/FemMesh.cpp @@ -1647,6 +1647,11 @@ void FemMesh::read(const char* FileName) } } +void FemMesh::writeVTK(const std::string& fileName, bool highest) const +{ + FemVTKTools::writeVTKMesh(fileName.c_str(), this, highest); +} + void FemMesh::writeABAQUS(const std::string& Filename, int elemParam, bool groupParam, @@ -2272,19 +2277,14 @@ void FemMesh::write(const char* FileName) const } else if (File.hasExtension("inp")) { Base::Console().Log("FEM mesh object will be exported to inp format.\n"); - // get Abaqus inp prefs - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Fem/Abaqus"); - int elemParam = hGrp->GetInt("AbaqusElementChoice", 1); - bool groupParam = hGrp->GetBool("AbaqusWriteGroups", false); // write ABAQUS Output - writeABAQUS(File.filePath(), elemParam, groupParam); + writeABAQUS(File.filePath(), 1, false); } #ifdef FC_USE_VTK else if (File.hasExtension({"vtk", "vtu"})) { Base::Console().Log("FEM mesh object will be exported to either vtk or vtu format.\n"); // write unstructure mesh to VTK format *.vtk and *.vtu - FemVTKTools::writeVTKMesh(File.filePath().c_str(), this); + writeVTK(File.filePath().c_str()); } #endif else if (File.hasExtension("z88")) { diff --git a/src/Mod/Fem/App/FemMesh.h b/src/Mod/Fem/App/FemMesh.h index 5008e25252..09b7070fb8 100644 --- a/src/Mod/Fem/App/FemMesh.h +++ b/src/Mod/Fem/App/FemMesh.h @@ -210,6 +210,7 @@ public: ABAQUS_VolumeVariant volVariant = ABAQUS_VolumeVariant::Standard, ABAQUS_FaceVariant faceVariant = ABAQUS_FaceVariant::Shell, ABAQUS_EdgeVariant edgeVariant = ABAQUS_EdgeVariant::Beam) const; + void writeVTK(const std::string& FileName, bool highest = true) const; void writeZ88(const std::string& FileName) const; private: diff --git a/src/Mod/Fem/App/FemVTKTools.cpp b/src/Mod/Fem/App/FemVTKTools.cpp index 4c952e33e6..1040c22625 100644 --- a/src/Mod/Fem/App/FemVTKTools.cpp +++ b/src/Mod/Fem/App/FemVTKTools.cpp @@ -339,14 +339,12 @@ FemMesh* FemVTKTools::readVTKMesh(const char* filename, FemMesh* mesh) return mesh; } -void exportFemMeshEdges(vtkSmartPointer grid, +void exportFemMeshEdges(vtkSmartPointer& elemArray, + std::vector& types, const SMDS_EdgeIteratorPtr& aEdgeIter) { Base::Console().Log(" Start: VTK mesh builder edges.\n"); - vtkSmartPointer elemArray = vtkSmartPointer::New(); - std::vector types; - while (aEdgeIter->more()) { const SMDS_MeshEdge* aEdge = aEdgeIter->next(); // edge @@ -362,21 +360,15 @@ void exportFemMeshEdges(vtkSmartPointer grid, } } - if (elemArray->GetNumberOfCells() > 0) { - grid->SetCells(types.data(), elemArray); - } - Base::Console().Log(" End: VTK mesh builder edges.\n"); } -void exportFemMeshFaces(vtkSmartPointer grid, +void exportFemMeshFaces(vtkSmartPointer& elemArray, + std::vector& types, const SMDS_FaceIteratorPtr& aFaceIter) { Base::Console().Log(" Start: VTK mesh builder faces.\n"); - vtkSmartPointer elemArray = vtkSmartPointer::New(); - std::vector types; - while (aFaceIter->more()) { const SMDS_MeshFace* aFace = aFaceIter->next(); // triangle @@ -400,21 +392,15 @@ void exportFemMeshFaces(vtkSmartPointer grid, } } - if (elemArray->GetNumberOfCells() > 0) { - grid->SetCells(types.data(), elemArray); - } - Base::Console().Log(" End: VTK mesh builder faces.\n"); } -void exportFemMeshCells(vtkSmartPointer grid, +void exportFemMeshCells(vtkSmartPointer& elemArray, + std::vector& types, const SMDS_VolumeIteratorPtr& aVolIter) { Base::Console().Log(" Start: VTK mesh builder volumes.\n"); - vtkSmartPointer elemArray = vtkSmartPointer::New(); - std::vector types; - while (aVolIter->more()) { const SMDS_MeshVolume* aVol = aVolIter->next(); @@ -447,15 +433,12 @@ void exportFemMeshCells(vtkSmartPointer grid, } } - if (elemArray->GetNumberOfCells() > 0) { - grid->SetCells(types.data(), elemArray); - } - Base::Console().Log(" End: VTK mesh builder volumes.\n"); } void FemVTKTools::exportVTKMesh(const FemMesh* mesh, vtkSmartPointer grid, + bool highest, float scale) { @@ -489,22 +472,45 @@ void FemVTKTools::exportVTKMesh(const FemMesh* mesh, Base::Console().Log(" Size of nodes in VTK grid: %i.\n", nNodes); Base::Console().Log(" End: VTK mesh builder nodes.\n"); - // edges - SMDS_EdgeIteratorPtr aEdgeIter = meshDS->edgesIterator(); - exportFemMeshEdges(grid, aEdgeIter); + vtkSmartPointer elemArray = vtkSmartPointer::New(); + std::vector types; - // faces - SMDS_FaceIteratorPtr aFaceIter = meshDS->facesIterator(); - exportFemMeshFaces(grid, aFaceIter); + if (highest) { + // try volumes + SMDS_VolumeIteratorPtr aVolIter = meshDS->volumesIterator(); + exportFemMeshCells(elemArray, types, aVolIter); + // try faces + if (elemArray->GetNumberOfCells() == 0) { + SMDS_FaceIteratorPtr aFaceIter = meshDS->facesIterator(); + exportFemMeshFaces(elemArray, types, aFaceIter); + } + // try edges + if (elemArray->GetNumberOfCells() == 0) { + SMDS_EdgeIteratorPtr aEdgeIter = meshDS->edgesIterator(); + exportFemMeshEdges(elemArray, types, aEdgeIter); + } + } + else { + // export all elements + // edges + SMDS_EdgeIteratorPtr aEdgeIter = meshDS->edgesIterator(); + exportFemMeshEdges(elemArray, types, aEdgeIter); + // faces + SMDS_FaceIteratorPtr aFaceIter = meshDS->facesIterator(); + exportFemMeshFaces(elemArray, types, aFaceIter); + // volumes + SMDS_VolumeIteratorPtr aVolIter = meshDS->volumesIterator(); + exportFemMeshCells(elemArray, types, aVolIter); + } - // volumes - SMDS_VolumeIteratorPtr aVolIter = meshDS->volumesIterator(); - exportFemMeshCells(grid, aVolIter); + if (elemArray->GetNumberOfCells() > 0) { + grid->SetCells(types.data(), elemArray); + } Base::Console().Log("End: VTK mesh builder ======================\n"); } -void FemVTKTools::writeVTKMesh(const char* filename, const FemMesh* mesh) +void FemVTKTools::writeVTKMesh(const char* filename, const FemMesh* mesh, bool highest) { Base::TimeElapsed Start; @@ -512,7 +518,7 @@ void FemVTKTools::writeVTKMesh(const char* filename, const FemMesh* mesh) Base::FileInfo f(filename); vtkSmartPointer grid = vtkSmartPointer::New(); - exportVTKMesh(mesh, grid); + exportVTKMesh(mesh, grid, highest); Base::Console().Log("Start: writing mesh data ======================\n"); if (f.hasExtension("vtu")) { writeVTKFile(filename, grid); diff --git a/src/Mod/Fem/App/FemVTKTools.h b/src/Mod/Fem/App/FemVTKTools.h index 19fb2d32b0..34a3552e76 100644 --- a/src/Mod/Fem/App/FemVTKTools.h +++ b/src/Mod/Fem/App/FemVTKTools.h @@ -42,9 +42,11 @@ public: // data static void importVTKMesh(vtkSmartPointer grid, FemMesh* mesh, float scale = 1.0); - // extract data from FreCAD FEM mesh and fill a vtkUnstructuredGrid instance with that data + // extract data from FreCAD FEM mesh and fill a vtkUnstructuredGrid instance with that data. Set + // `highest` to false to export all elements levels. static void exportVTKMesh(const FemMesh* mesh, vtkSmartPointer grid, + bool highest = true, float scale = 1.0); // extract data from vtkUnstructuredGrid object and fill a FreeCAD FEM result object with that @@ -61,7 +63,7 @@ public: static FemMesh* readVTKMesh(const char* filename, FemMesh* mesh); // FemMesh write to vtkUnstructuredGrid data file - static void writeVTKMesh(const char* Filename, const FemMesh* mesh); + static void writeVTKMesh(const char* Filename, const FemMesh* mesh, bool highest = true); // FemResult (activeObject or created if res= NULL) read from vtkUnstructuredGrid dataset file static App::DocumentObject* readResult(const char* Filename, diff --git a/src/Mod/Fem/Gui/DlgSettingsFemInOutVtk.ui b/src/Mod/Fem/Gui/DlgSettingsFemInOutVtk.ui index 94cf6da1fb..6d92bf1ec4 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemInOutVtk.ui +++ b/src/Mod/Fem/Gui/DlgSettingsFemInOutVtk.ui @@ -84,6 +84,41 @@ exported from FreeCAD. + + + Export + + + + + + Mesh elements to export + + + + + + + Mesh element level to export + + + QComboBox::AdjustToContents + + + MeshExportLevel + + + Mod/Fem/InOutVtk + + + + + + + + + + Qt::Vertical diff --git a/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.cpp b/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.cpp index fb23e50f71..9d6f21d934 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.cpp +++ b/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.cpp @@ -51,6 +51,7 @@ void DlgSettingsFemInOutVtkImp::saveSettings() hGrp->SetInt("ImportObject", ui->comboBoxVtkImportObject->currentIndex()); ui->comboBoxVtkImportObject->onSave(); + ui->cb_export_level->onSave(); } void DlgSettingsFemInOutVtkImp::loadSettings() @@ -64,6 +65,9 @@ void DlgSettingsFemInOutVtkImp::loadSettings() if (index > -1) { ui->comboBoxVtkImportObject->setCurrentIndex(index); } + + populateExportLevel(); + ui->cb_export_level->onRestore(); } /** @@ -81,4 +85,19 @@ void DlgSettingsFemInOutVtkImp::changeEvent(QEvent* e) } } +void DlgSettingsFemInOutVtkImp::populateExportLevel() const +{ + std::list values = {"All", "Highest"}; + + for (const auto& val : values) { + ui->cb_export_level->addItem(QString::fromStdString(val)); + } + + auto hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Fem/InOutVtk"); + std::string current = hGrp->GetASCII("MeshExportLevel", "Highest"); + int index = ui->cb_export_level->findText(QString::fromStdString(current)); + ui->cb_export_level->setCurrentIndex(index); +} + #include "moc_DlgSettingsFemInOutVtkImp.cpp" diff --git a/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.h b/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.h index 316c68327c..d3502efc56 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.h +++ b/src/Mod/Fem/Gui/DlgSettingsFemInOutVtkImp.h @@ -48,6 +48,7 @@ protected: void changeEvent(QEvent* e) override; private: + void populateExportLevel() const; std::unique_ptr ui; };