2024-02-07 14:48:43 +05:00
|
|
|
# -*- coding: iso-8859-1 -*-
|
|
|
|
# Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
|
|
|
|
#
|
|
|
|
# This library is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
|
|
# License as published by the Free Software Foundation; either
|
|
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This library is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
# Lesser General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
|
|
# License along with this library; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#
|
|
|
|
# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
|
|
|
|
#
|
|
|
|
|
|
|
|
# =======================================
|
|
|
|
# Testing export/import of some simple shapes in different formats with meshio library
|
|
|
|
# File : SMESH_MeshioShapes.py
|
|
|
|
# Module : SMESH
|
|
|
|
|
|
|
|
import tempfile
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
import salome
|
|
|
|
salome.salome_init()
|
|
|
|
|
|
|
|
import GEOM
|
|
|
|
from salome.geom import geomBuilder
|
|
|
|
|
|
|
|
import SMESH
|
|
|
|
from salome.smesh import smeshBuilder
|
|
|
|
|
|
|
|
import SALOME
|
|
|
|
|
2024-05-15 00:50:43 +05:00
|
|
|
import platform
|
|
|
|
|
2024-02-07 14:48:43 +05:00
|
|
|
# Constants
|
|
|
|
EXPORT_TITLE = 'Export'
|
|
|
|
IMPORT_TITLE = 'Import'
|
|
|
|
UNKNOWN_EXCEPTION = 'Unknown exception'
|
|
|
|
OUTPUT_DIVIDER = '\n==============================================='
|
|
|
|
|
|
|
|
|
|
|
|
geompy = geomBuilder.New()
|
|
|
|
smesh = smeshBuilder.New()
|
|
|
|
|
|
|
|
|
|
|
|
def make_plane():
|
|
|
|
"""
|
|
|
|
Makes default plane for testing.
|
|
|
|
"""
|
|
|
|
|
|
|
|
plane = geompy.MakeFaceHW(100, 100, 1)
|
|
|
|
geompy.addToStudy( plane, 'plane' )
|
|
|
|
|
|
|
|
return plane
|
|
|
|
|
|
|
|
|
|
|
|
def make_box():
|
|
|
|
"""
|
|
|
|
Makes default box for testing.
|
|
|
|
"""
|
|
|
|
|
|
|
|
box = geompy.MakeBoxDXDYDZ(200, 200, 200)
|
|
|
|
geompy.addToStudy(box, 'box')
|
|
|
|
|
|
|
|
return box
|
|
|
|
|
|
|
|
|
|
|
|
def make_mesh(shape, name):
|
|
|
|
"""
|
|
|
|
Makes a mesh from a given shape.
|
|
|
|
"""
|
|
|
|
res_mesh = smesh.Mesh(shape,name)
|
|
|
|
NETGEN_1D_2D = res_mesh.Triangle(algo=smeshBuilder.NETGEN_1D2D)
|
|
|
|
isDone = res_mesh.Compute()
|
|
|
|
assert isDone
|
|
|
|
|
|
|
|
smesh.SetName(res_mesh, name)
|
|
|
|
smesh.SetName(NETGEN_1D_2D.GetAlgorithm(), 'NETGEN 1D-2D')
|
|
|
|
smesh.SetName(res_mesh.GetMesh(), name)
|
|
|
|
|
|
|
|
return res_mesh
|
|
|
|
|
|
|
|
|
|
|
|
def file_extensions():
|
|
|
|
"""
|
|
|
|
Returns all files extensions supported by meshio.
|
|
|
|
Commented formats should be checked on next meshio release to see if the problem was fixed.
|
|
|
|
"""
|
|
|
|
|
2024-05-15 00:50:43 +05:00
|
|
|
extensions = [
|
2024-02-07 14:48:43 +05:00
|
|
|
'.avs',
|
|
|
|
'.bdf',
|
|
|
|
# '.cgns', # meshio IndexError: index 2 is out of bounds for axis 1 with size 2
|
|
|
|
# '.dat', # meshio ValueError: need at least one array to concatenate
|
|
|
|
'.dato',
|
|
|
|
'.dato.gz',
|
|
|
|
'.e',
|
|
|
|
# '.ele', # never returns from meshio convert command
|
|
|
|
'.exo',
|
|
|
|
# '.f3grid', # meshio IndexError: Replacement index 3 out of range for positional args tuple
|
|
|
|
'.fem',
|
|
|
|
# '.h5m', # meshio AttributeError: 'list' object has no attribute 'items'
|
|
|
|
'.inp',
|
|
|
|
'.mdpa',
|
|
|
|
'.med',
|
|
|
|
'.mesh',
|
|
|
|
'.meshb',
|
|
|
|
# '.msh', # meshio KeyError: "Illegal ANSYS cell type 'line'
|
|
|
|
'.nas',
|
|
|
|
# '.node', # never returns from meshio convert command
|
|
|
|
# '.obj', # meshio._exceptions.WriteError: Wavefront .obj files can only contain triangle or quad cells
|
|
|
|
# '.off', # failed on Windows only
|
|
|
|
# '.ply', # Export Warning: PLY doesn't support 64-bit integers. Casting down to 32-bit. Then import failed
|
|
|
|
'.post',
|
|
|
|
'.post.gz',
|
|
|
|
'.stl',
|
|
|
|
# '.su2', # meshio TypeError: cannot unpack non-iterable CellBlock object
|
|
|
|
# '.svg', # meshio._exceptions.WriteError: SVG can only handle flat 2D meshes
|
|
|
|
# '.ugrid', # meshio AttributeError: 'list' object has no attribute 'reshape'
|
|
|
|
'.vol',
|
|
|
|
'.vol.gz',
|
|
|
|
'.vtk',
|
|
|
|
'.vtu',
|
|
|
|
# '.wkt', # Export Warning: WTK only supports triangle cells. Skipping {", ".join(skip)} then import failed
|
|
|
|
'.xdmf',
|
|
|
|
'.xmf',
|
|
|
|
'.xml'
|
|
|
|
]
|
2024-05-15 00:50:43 +05:00
|
|
|
if platform.system() == 'Windows':
|
|
|
|
extensions = [ext for ext in extensions if not ext in ['.e', '.exo']] # needs to be digged out - presumably an issue about encoding.
|
2024-02-07 14:48:43 +05:00
|
|
|
|
2024-05-15 00:50:43 +05:00
|
|
|
return extensions
|
2024-02-07 14:48:43 +05:00
|
|
|
|
|
|
|
def exception_handle(file_name, errors, operation_type, ex_text):
|
|
|
|
"""
|
|
|
|
Pepares and saves an exception message.
|
|
|
|
"""
|
|
|
|
|
|
|
|
ext = Path(file_name).suffix.upper()
|
|
|
|
msg = '{} {} failed! File name: {}'.format(operation_type, ext, file_name)
|
|
|
|
if ex_text:
|
|
|
|
msg += ' Exception: ' + ex_text + OUTPUT_DIVIDER + '\n'
|
|
|
|
|
|
|
|
errors.append(msg)
|
|
|
|
|
|
|
|
|
|
|
|
def export_mesh(mesh, file_name, errors):
|
|
|
|
"""
|
|
|
|
Performs an export operatin.
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
print('Export to file: ', file_name)
|
|
|
|
|
|
|
|
# Here we use an empty selected filter to make things simpler
|
|
|
|
mesh.ExportMESHIO(file_name, '', mesh)
|
|
|
|
return True
|
|
|
|
|
|
|
|
except SALOME.SALOME_Exception as ex:
|
|
|
|
exception_handle(file_name, errors, EXPORT_TITLE, ex.details.text)
|
|
|
|
|
|
|
|
except:
|
|
|
|
exception_handle(file_name, errors, EXPORT_TITLE, UNKNOWN_EXCEPTION)
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
def import_file(file_name, errors):
|
|
|
|
"""
|
|
|
|
Performs an import operatin.
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
print('Import from file: ', file_name)
|
|
|
|
|
|
|
|
([mesh], status) = smesh.CreateMeshesFromMESHIO(file_name)
|
|
|
|
return mesh
|
|
|
|
|
|
|
|
except SALOME.SALOME_Exception as ex:
|
|
|
|
exception_handle(file_name, errors, IMPORT_TITLE, ex.details.text)
|
|
|
|
|
|
|
|
except:
|
|
|
|
exception_handle(file_name, errors, IMPORT_TITLE, UNKNOWN_EXCEPTION)
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
def print_errors(errors):
|
|
|
|
"""
|
|
|
|
Checks if we have got any saved error messages and print them.
|
|
|
|
The test failed in this case.
|
|
|
|
"""
|
|
|
|
|
|
|
|
if not len(errors):
|
|
|
|
return
|
|
|
|
|
|
|
|
print('\nErrors:\n')
|
|
|
|
for idx, err in enumerate(errors):
|
|
|
|
print('{:02}: {}'.format(idx, err))
|
|
|
|
|
|
|
|
print(OUTPUT_DIVIDER)
|
|
|
|
|
|
|
|
|
|
|
|
def perform(mesh, name, errors):
|
|
|
|
"""
|
|
|
|
Exports a given mesh and imports it back for each file format.
|
|
|
|
"""
|
|
|
|
|
|
|
|
for ext in file_extensions():
|
|
|
|
with tempfile.NamedTemporaryFile(suffix=ext, prefix=name) as file:
|
|
|
|
file.close() # prevents PermissionError on Windows
|
|
|
|
if (export_mesh(mesh, file.name, errors)):
|
|
|
|
file.close() # prevents PermissionError on Windows
|
|
|
|
import_file(file.name, errors)
|
|
|
|
|
|
|
|
|
|
|
|
def test_box(errors):
|
|
|
|
"""
|
|
|
|
Tests export / import of a mesh for a default box geometry.
|
|
|
|
"""
|
|
|
|
|
|
|
|
box = make_box()
|
|
|
|
|
|
|
|
mesh_name = 'Test_box_'
|
|
|
|
mesh = make_mesh(box, mesh_name)
|
|
|
|
perform(mesh, mesh_name, errors)
|
|
|
|
|
|
|
|
|
|
|
|
def test_plane(errors):
|
|
|
|
"""
|
|
|
|
Tests export / import of a mesh for a default plane geometry.
|
|
|
|
"""
|
|
|
|
|
|
|
|
plane = make_plane()
|
|
|
|
|
|
|
|
mesh_name = 'Test_plane_'
|
|
|
|
mesh = make_mesh(plane, mesh_name)
|
|
|
|
perform(mesh, mesh_name, errors)
|
|
|
|
|
|
|
|
|
|
|
|
def test():
|
|
|
|
"""
|
|
|
|
Creates meshes from plane and box and tries to export them to a temp files
|
|
|
|
and import them back with different formats supported by meshio library.
|
|
|
|
Prints errors if we have any.
|
|
|
|
"""
|
|
|
|
|
|
|
|
errors = []
|
|
|
|
|
|
|
|
test_plane(errors)
|
|
|
|
test_box(errors)
|
|
|
|
|
|
|
|
print_errors(errors)
|
|
|
|
assert not len(errors)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
test()
|