Skip to content

Commit

Permalink
MeshIO Python Filters: Add support for .ply files and vertex geometries.
Browse files Browse the repository at this point in the history
Signed-off-by: Joey Kleingers <[email protected]>
  • Loading branch information
joeykleingers committed Dec 19, 2024
1 parent 6b590b0 commit 37e1884
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The following mesh formats are supported by this filter:
+ Ansys (.msh)
+ Gmsh (.msh)
+ Med (.med)
+ PLY (.ply)
+ TetGen (.node/.ele)
+ VTK (.vtu)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,14 @@ def parameters(self) -> nx.Parameters:
params = nx.Parameters()

params.insert(params.Separator("Input Parameters"))
params.insert(nx.FileSystemPathParameter(ReadMeshFile.INPUT_FILE_PATH_KEY, 'Input File (.inp, .msh, .med, .node, .ele, .vtu)', 'The input file that contains the mesh which will be read in as a geometry.', '', extensions_type={'.inp', '.msh', '.med', '.node', '.ele', '.vtu'}, path_type=nx.FileSystemPathParameter.PathType.InputFile))
params.insert(nx.FileSystemPathParameter(ReadMeshFile.INPUT_FILE_PATH_KEY, 'Input File (.inp, .msh, .med, .node, .ele, .ply, .vtu)', 'The input file that contains the mesh which will be read in as a geometry.', '', extensions_type={'.inp', '.msh', '.med', '.node', '.ele', '.vtu', '.ply'}, path_type=nx.FileSystemPathParameter.PathType.InputFile))

params.insert(params.Separator("Created Parameters"))
params.insert(nx.DataGroupCreationParameter(ReadMeshFile.CREATED_GEOMETRY_PATH, 'Created Geometry', 'The path to where the geometry will be created in the data structure.', nx.DataPath()))
params.insert(nx.DataObjectNameParameter(ReadMeshFile.VERTEX_ATTR_MATRIX_NAME, 'Vertex Attribute Matrix Name', 'The name of the vertex attribute matrix that will be created inside the geometry.', 'Vertex Data'))
params.insert(nx.DataObjectNameParameter(ReadMeshFile.CELL_ATTR_MATRIX_NAME, 'Cell Attribute Matrix Name', 'The name of the cell attribute matrix that will be created inside the geometry.', 'Cell Data'))
params.insert(nx.DataObjectNameParameter(ReadMeshFile.CELL_ATTR_MATRIX_NAME, 'Cell Attribute Matrix Name', 'The name of the cell attribute matrix that will be created inside the geometry. This attribute matrix will only be created IF the input mesh file has cells!', 'Cell Data'))
params.insert(nx.DataObjectNameParameter(ReadMeshFile.VERTEX_ARRAY_NAME, 'Vertex Array Name', 'The name of the vertex array that will be created inside the geometry.', 'Vertices'))
params.insert(nx.DataObjectNameParameter(ReadMeshFile.CELL_ARRAY_NAME, 'Cell Array Name', 'The name of the cell array that will be created inside the geometry.', 'Cells'))
params.insert(nx.DataObjectNameParameter(ReadMeshFile.CELL_ARRAY_NAME, 'Cell Array Name', 'The name of the cell array that will be created inside the geometry. This array will only be created IF the input mesh file has cells!', 'Cells'))

return params

Expand Down Expand Up @@ -118,17 +118,14 @@ def preflight_impl(self, data_structure: nx.DataStructure, args: dict, message_h
_mesh_cache = meshio.read(str(input_file_path))
_input_file_path_cache = input_file_path

if len(_mesh_cache.cells) == 0:
return nx.IFilter.PreflightResult(errors=[make_error_result(code=-3040, message=f"Mesh file '{str(input_file_path)}' does not contain a cell type. A cell type is required to be able to create a geometry from the mesh file!")])

if len(_mesh_cache.cells) > 1:
return nx.IFilter.PreflightResult(errors=[make_error_result(code=-3041, message=f"Mesh file '{str(input_file_path)}' has more than one declared cell type. Multiple cell types in one file are not supported.")])

# Create the proper geometry
output_actions: nx.OutputActions = nx.OutputActions()
warnings: List[nx.Warning] = []
cell_type: str = _mesh_cache.cells[0].type
cells_array: np.ndarray = _mesh_cache.cells[0].data
cell_type: str = _mesh_cache.cells[0].type if len(_mesh_cache.cells) != 0 else mu.VERTEX_TYPE_STR
cells_array: np.ndarray = _mesh_cache.cells[0].data if len(_mesh_cache.cells) != 0 else None
points_array: np.ndarray = _mesh_cache.points

if cell_type == mu.EDGE_TYPE_STR:
Expand All @@ -141,6 +138,8 @@ def preflight_impl(self, data_structure: nx.DataStructure, args: dict, message_h
output_actions.append_action(nx.CreateTetrahedralGeometryAction(created_geometry_path, cells_array.shape[0], points_array.shape[0], vertex_attr_matrix_name, cell_attr_matrix_name, vertex_array_name, cell_array_name))
elif cell_type == mu.HEXAHEDRAL_TYPE_STR:
output_actions.append_action(nx.CreateHexahedralGeometryAction(created_geometry_path, cells_array.shape[0], points_array.shape[0], vertex_attr_matrix_name, cell_attr_matrix_name, vertex_array_name, cell_array_name))
elif cell_type == mu.VERTEX_TYPE_STR:
output_actions.append_action(nx.CreateVertexGeometryAction(created_geometry_path, points_array.shape[0], vertex_attr_matrix_name, vertex_array_name))
else:
return nx.IFilter.PreflightResult(errors=[nx.Error(code=-3042, message=f"Unsupported mesh type '{cell_type}'. Only '{mu.EDGE_TYPE_STR}', '{mu.TRIANGLE_TYPE_STR}', '{mu.QUAD_TYPE_STR}', '{mu.TETRAHEDRAL_TYPE_STR}', and '{mu.HEXAHEDRAL_TYPE_STR}' types are supported.")])

Expand All @@ -161,7 +160,6 @@ def preflight_impl(self, data_structure: nx.DataStructure, args: dict, message_h
# Create the point data arrays
vertex_attr_mat_path = created_geometry_path.create_child_path(vertex_attr_matrix_name)
for point_data_array_name, point_data_array in _mesh_cache.point_data.items():
point_data_array = point_data_array[0]
point_array_path = vertex_attr_mat_path.create_child_path(point_data_array_name)
point_data_tuple_dims = [point_data_array.shape[0]]
point_data_comp_dims = point_data_array.shape[1:]
Expand All @@ -187,38 +185,36 @@ def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_han
geometry: nx.INodeGeometry1D = data_structure[created_geometry_path]

# Grab the proper cells array from the geometry
cells_array = None
if isinstance(geometry, nx.INodeGeometry3D):
cells_array = geometry.polyhedra
elif isinstance(geometry, nx.INodeGeometry2D):
cells_array = geometry.faces
elif isinstance(geometry, nx.INodeGeometry1D):
cells_array = geometry.edges
else:
# This SHOULD NOT happen, but we'll check for it anyways...
return Result(errors=[make_error_result(code=-3042, message=f"Created geometry at path '{str(created_geometry_path)}' with type '{type(geometry).__name__}' is not a 1D, 2D, or 3D node-based geometry.")])

# Copy over the vertices
vertices_np_array = geometry.vertices.npview()
vertices_np_array[:] = _mesh_cache.points[:]

# Copy over the cells
cells_np_array = cells_array.npview()
cells_np_array[:] = _mesh_cache.cells[0].data[:]
if cells_array is not None:
cells_np_array = cells_array.npview()
cells_np_array[:] = _mesh_cache.cells[0].data[:]

# Copy over the cell data
cell_attr_mat_path = created_geometry_path.create_child_path(cell_attr_matrix_name)
for cell_data_array_name, cell_data_array in _mesh_cache.cell_data.items():
cell_data_array = cell_data_array[0]
cell_data_array_path = cell_attr_mat_path.create_child_path(cell_data_array_name)
cell_data_np_array = np.squeeze(data_structure[cell_data_array_path].npview())
cell_data_np_array[:] = _mesh_cache.cell_data[cell_data_array_name][0][:]
cell_data_np_array[:] = np.squeeze(cell_data_array[:])

# Copy over the point data
vertex_attr_mat_path = created_geometry_path.create_child_path(vertex_attr_matrix_name)
for point_data_array_name, point_data_array in _mesh_cache.point_data.items():
point_data_array = point_data_array[0]
point_data_array_path = vertex_attr_mat_path.create_child_path(point_data_array_name)
point_data_np_array = np.squeeze(data_structure[point_data_array_path].npview())
point_data_np_array[:] = _mesh_cache.point_data[point_data_array_name][0][:]
point_data_np_array[:] = np.squeeze(point_data_array[:])

return nx.Result()
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def parameters(self) -> nx.Parameters:
params = nx.Parameters()

params.insert(params.Separator("Input Parameters"))
params.insert(nx.GeometrySelectionParameter(WriteAbaqusFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the ABAQUS file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))
params.insert(nx.GeometrySelectionParameter(WriteAbaqusFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the ABAQUS file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Vertex, nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))

params.insert(params.Separator("Output Parameters"))
params.insert(nx.FileSystemPathParameter(WriteAbaqusFile.OUTPUT_FILE_PATH_KEY, 'Output File (.inp)', 'The output file that contains the specified geometry as a mesh.', '', extensions_type={'.inp'}, path_type=nx.FileSystemPathParameter.PathType.OutputFile))
Expand Down Expand Up @@ -108,4 +108,5 @@ def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_han
input_geometry_path: nx.DataPath = args[WriteAbaqusFile.INPUT_GEOMETRY_KEY]
output_file_path: Path = args[WriteAbaqusFile.OUTPUT_FILE_PATH_KEY]

return mu.execute_meshio_writer_filter(file_format='abaqus', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=None, point_data_array_paths=None, output_file_path=output_file_path)
message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Writing geometry to Abaqus file "{str(output_file_path)}"'))
return mu.execute_meshio_writer_filter(file_format='abaqus', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=None, point_data_array_paths=None, output_file_path=output_file_path, message_handler=message_handler, should_cancel=should_cancel)
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def parameters(self) -> nx.Parameters:
params = nx.Parameters()

params.insert(params.Separator("Input Parameters"))
params.insert(nx.GeometrySelectionParameter(WriteAnsysFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the ANSYS file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))
params.insert(nx.GeometrySelectionParameter(WriteAnsysFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the ANSYS file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Vertex, nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))

params.insert(params.Separator("Output Parameters"))
params.insert(nx.FileSystemPathParameter(WriteAnsysFile.OUTPUT_FILE_PATH_KEY, 'Output File (.msh)', 'The output file that contains the specified geometry as a mesh.', '', extensions_type={'.msh'}, path_type=nx.FileSystemPathParameter.PathType.OutputFile))
Expand Down Expand Up @@ -109,4 +109,5 @@ def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_han
input_geometry_path: nx.DataPath = args[WriteAnsysFile.INPUT_GEOMETRY_KEY]
output_file_path: Path = args[WriteAnsysFile.OUTPUT_FILE_PATH_KEY]

return mu.execute_meshio_writer_filter(file_format='ansys', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=None, point_data_array_paths=None, output_file_path=output_file_path, binary=True)
message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Writing geometry to Ansys file "{str(output_file_path)}"'))
return mu.execute_meshio_writer_filter(file_format='ansys', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=None, point_data_array_paths=None, output_file_path=output_file_path, message_handler=message_handler, should_cancel=should_cancel, binary=True)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List
from pathlib import Path
import simplnx as nx
import numpy as np
import meshio
from .utilities import meshio_utilities as mu

Expand Down Expand Up @@ -75,7 +76,7 @@ def parameters(self) -> nx.Parameters:
params = nx.Parameters()

params.insert(params.Separator("Input Parameters"))
params.insert(nx.GeometrySelectionParameter(WriteGmshFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the ANSYS file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))
params.insert(nx.GeometrySelectionParameter(WriteGmshFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the ANSYS file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Vertex, nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))
params.insert(nx.MultiArraySelectionParameter(WriteGmshFile.CELL_DATA_ARRAY_PATHS_KEY, 'Cell Data Arrays To Write', 'The cell data arrays to write to the ANSYS file.', [], allowed_types={nx.IArray.ArrayType.DataArray}, allowed_data_types=nx.get_all_data_types()))
params.insert(nx.MultiArraySelectionParameter(WriteGmshFile.POINT_DATA_ARRAY_PATHS_KEY, 'Point Data Arrays To Write', 'The point data arrays to write to the ANSYS file.', [], allowed_types={nx.IArray.ArrayType.DataArray}, allowed_data_types=nx.get_all_data_types()))

Expand Down Expand Up @@ -117,4 +118,16 @@ def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_han
cell_data_array_paths = args[WriteGmshFile.CELL_DATA_ARRAY_PATHS_KEY]
point_data_array_paths = args[WriteGmshFile.POINT_DATA_ARRAY_PATHS_KEY]

return mu.execute_meshio_writer_filter(file_format='gmsh', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=cell_data_array_paths, point_data_array_paths=point_data_array_paths, output_file_path=output_file_path)
message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Writing geometry to Gmsh file "{str(output_file_path)}"'))
mesh, result = mu.create_mesh(file_format='gmsh', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=cell_data_array_paths, point_data_array_paths=point_data_array_paths, output_file_path=output_file_path, message_handler=message_handler, should_cancel=should_cancel)
if result.invalid():
return result

# Write the dim_tags for the point data
geom = data_structure[input_geometry_path]
mesh.point_data["gmsh:dim_tags"] = np.full((geom.vertices.tdims[0], 2), [3, 0], dtype=np.int64)

# Output the mesh
meshio.write(output_file_path, mesh, file_format='gmsh')

return nx.Result()
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def parameters(self) -> nx.Parameters:
params = nx.Parameters()

params.insert(params.Separator("Input Parameters"))
params.insert(nx.GeometrySelectionParameter(WriteMedFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the MED file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))
params.insert(nx.GeometrySelectionParameter(WriteMedFile.INPUT_GEOMETRY_KEY, 'Input Geometry', 'The input geometry that will be written to the MED file.', nx.DataPath(), allowed_types={nx.IGeometry.Type.Vertex, nx.IGeometry.Type.Edge, nx.IGeometry.Type.Triangle, nx.IGeometry.Type.Quad, nx.IGeometry.Type.Tetrahedral, nx.IGeometry.Type.Hexahedral}))
params.insert(nx.MultiArraySelectionParameter(WriteMedFile.CELL_DATA_ARRAY_PATHS_KEY, 'Cell Data Arrays To Write', 'The cell data arrays to write to the MED file.', [], allowed_types={nx.IArray.ArrayType.DataArray}, allowed_data_types=nx.get_all_data_types()))
params.insert(nx.MultiArraySelectionParameter(WriteMedFile.POINT_DATA_ARRAY_PATHS_KEY, 'Point Data Arrays To Write', 'The point data arrays to write to the MED file.', [], allowed_types={nx.IArray.ArrayType.DataArray}, allowed_data_types=nx.get_all_data_types()))

Expand Down Expand Up @@ -117,4 +117,5 @@ def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_han
cell_data_array_paths = args[WriteMedFile.CELL_DATA_ARRAY_PATHS_KEY]
point_data_array_paths = args[WriteMedFile.POINT_DATA_ARRAY_PATHS_KEY]

return mu.execute_meshio_writer_filter(file_format='med', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=cell_data_array_paths, point_data_array_paths=point_data_array_paths, output_file_path=output_file_path)
message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Writing geometry to Med file "{str(output_file_path)}"'))
return mu.execute_meshio_writer_filter(file_format='med', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=cell_data_array_paths, point_data_array_paths=point_data_array_paths, output_file_path=output_file_path, message_handler=message_handler, should_cancel=should_cancel)
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,6 @@ def execute_impl(self, data_structure: nx.DataStructure, args: dict, message_han
cell_data_array_paths = args[WriteTetGenFile.CELL_DATA_ARRAY_PATHS_KEY]
point_data_array_paths = args[WriteTetGenFile.POINT_DATA_ARRAY_PATHS_KEY]

return mu.execute_meshio_writer_filter(file_format='tetgen', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=cell_data_array_paths, point_data_array_paths=point_data_array_paths, output_file_path=output_file_path)
no_suffix_path = output_file_path.with_suffix("")
message_handler(nx.IFilter.Message(nx.IFilter.Message.Type.Info, f'Writing geometry to TetGen files "{str(no_suffix_path.with_suffix(".node"))}" and "{str(no_suffix_path.with_suffix(".ele"))}"'))
return mu.execute_meshio_writer_filter(file_format='tetgen', data_structure=data_structure, input_geometry_path=input_geometry_path, cell_data_array_paths=cell_data_array_paths, point_data_array_paths=point_data_array_paths, output_file_path=output_file_path, message_handler=message_handler, should_cancel=should_cancel)
Loading

0 comments on commit 37e1884

Please sign in to comment.