Fem: Fix mesh export to vtk formats

This commit is contained in:
marioalexis
2024-09-18 00:31:52 -03:00
committed by Chris Hennes
parent dd1419cd5f
commit f6e33eb5f4
8 changed files with 131 additions and 46 deletions

View File

@@ -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<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
if (obj->getTypeId().isDerivedFrom(meshId)) {
static_cast<FemMeshObject*>(obj)->FemMesh.getValue().write(EncodedName.c_str());
auto femMesh = static_cast<FemMeshObject*>(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();
}
}

View File

@@ -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")) {

View File

@@ -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:

View File

@@ -339,14 +339,12 @@ FemMesh* FemVTKTools::readVTKMesh(const char* filename, FemMesh* mesh)
return mesh;
}
void exportFemMeshEdges(vtkSmartPointer<vtkUnstructuredGrid> grid,
void exportFemMeshEdges(vtkSmartPointer<vtkCellArray>& elemArray,
std::vector<int>& types,
const SMDS_EdgeIteratorPtr& aEdgeIter)
{
Base::Console().Log(" Start: VTK mesh builder edges.\n");
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
std::vector<int> types;
while (aEdgeIter->more()) {
const SMDS_MeshEdge* aEdge = aEdgeIter->next();
// edge
@@ -362,21 +360,15 @@ void exportFemMeshEdges(vtkSmartPointer<vtkUnstructuredGrid> grid,
}
}
if (elemArray->GetNumberOfCells() > 0) {
grid->SetCells(types.data(), elemArray);
}
Base::Console().Log(" End: VTK mesh builder edges.\n");
}
void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
void exportFemMeshFaces(vtkSmartPointer<vtkCellArray>& elemArray,
std::vector<int>& types,
const SMDS_FaceIteratorPtr& aFaceIter)
{
Base::Console().Log(" Start: VTK mesh builder faces.\n");
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
std::vector<int> types;
while (aFaceIter->more()) {
const SMDS_MeshFace* aFace = aFaceIter->next();
// triangle
@@ -400,21 +392,15 @@ void exportFemMeshFaces(vtkSmartPointer<vtkUnstructuredGrid> grid,
}
}
if (elemArray->GetNumberOfCells() > 0) {
grid->SetCells(types.data(), elemArray);
}
Base::Console().Log(" End: VTK mesh builder faces.\n");
}
void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> grid,
void exportFemMeshCells(vtkSmartPointer<vtkCellArray>& elemArray,
std::vector<int>& types,
const SMDS_VolumeIteratorPtr& aVolIter)
{
Base::Console().Log(" Start: VTK mesh builder volumes.\n");
vtkSmartPointer<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
std::vector<int> types;
while (aVolIter->more()) {
const SMDS_MeshVolume* aVol = aVolIter->next();
@@ -447,15 +433,12 @@ void exportFemMeshCells(vtkSmartPointer<vtkUnstructuredGrid> 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<vtkUnstructuredGrid> 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<vtkCellArray> elemArray = vtkSmartPointer<vtkCellArray>::New();
std::vector<int> 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<vtkUnstructuredGrid> grid = vtkSmartPointer<vtkUnstructuredGrid>::New();
exportVTKMesh(mesh, grid);
exportVTKMesh(mesh, grid, highest);
Base::Console().Log("Start: writing mesh data ======================\n");
if (f.hasExtension("vtu")) {
writeVTKFile<vtkXMLUnstructuredGridWriter>(filename, grid);

View File

@@ -42,9 +42,11 @@ public:
// data
static void importVTKMesh(vtkSmartPointer<vtkDataSet> 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<vtkUnstructuredGrid> 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,

View File

@@ -84,6 +84,41 @@ exported from FreeCAD.</string>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="gb_export">
<property name="title">
<string>Export</string>
</property>
<layout class="QGridLayout" name="gl_export">
<item row="0" column="0">
<widget class="QLabel" name="lbl_export_level">
<property name="text">
<string>Mesh elements to export</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Gui::PrefComboBox" name="cb_export_level">
<property name="toolTip">
<string>Mesh element level to export</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<property name="prefEntry" stdset="0">
<cstring>MeshExportLevel</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Fem/InOutVtk</cstring>
</property>
<property name="prefType" stdset="0">
<string></string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>

View File

@@ -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<std::string> 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"

View File

@@ -48,6 +48,7 @@ protected:
void changeEvent(QEvent* e) override;
private:
void populateExportLevel() const;
std::unique_ptr<Ui_DlgSettingsFemInOutVtk> ui;
};