From 3761fed3651fc4b9840cbb978c337df9b6821f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20Schl=C3=B6mer?= Date: Thu, 29 Apr 2021 11:19:40 +0200 Subject: [PATCH 1/6] call polygon a polygon, not polygonN --- meshio/_mesh.py | 7 +++++-- meshio/vtk/_vtk.py | 18 +++++++++++------- test/helpers.py | 4 ++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/meshio/_mesh.py b/meshio/_mesh.py index 4429e8996..fd1a22c97 100644 --- a/meshio/_mesh.py +++ b/meshio/_mesh.py @@ -84,8 +84,11 @@ def __repr__(self): lines = ["", f" Number of points: {len(self.points)}"] if len(self.cells) > 0: lines.append(" Number of cells:") - for tpe, elems in self.cells: - lines.append(f" {tpe}: {len(elems)}") + for cell_type, elems in self.cells: + string = cell_type + if cell_type == "polygon": + string += f"({elems.shape[1]})" + lines.append(f" {string}: {len(elems)}") else: lines.append(" No cells.") diff --git a/meshio/vtk/_vtk.py b/meshio/vtk/_vtk.py index df09f67e5..11710703b 100644 --- a/meshio/vtk/_vtk.py +++ b/meshio/vtk/_vtk.py @@ -586,12 +586,17 @@ def translate_cells(data, types, cell_data_raw): cell = data[cell_idx] cell_type = vtk_to_meshio_type[vtk_cell_type] - if cell_type == "polygon": - cell_type += str(data[offsets[idx]]) - if len(cells) > 0 and cells[-1].type == cell_type: + if ( + len(cells) > 0 + and cells[-1].type == cell_type + # the following check if needed for polygons; key can be equal, but + # still needs to go into a new block + and len(cell) == len(cells[-1].data[-1]) + ): cells[-1].data.append(cell) else: + # open up a new cell block cells.append(CellBlock(cell_type, [cell])) # convert data to numpy arrays @@ -752,15 +757,14 @@ def _write_cells(f, cells, binary): f.write(f"CELL_TYPES {total_num_cells}\n".encode("utf-8")) if binary: for c in cells: - key_ = c.type[:7] if c.type[:7] == "polygon" else c.type - vtk_type = meshio_to_vtk_type[key_] + vtk_type = meshio_to_vtk_type[c.type] np.full(len(c.data), vtk_type, dtype=np.dtype(">i4")).tofile(f, sep="") f.write(b"\n") else: # ascii for c in cells: - key_ = c.type[:7] if c.type[:7] == "polygon" else c.type - np.full(len(c.data), meshio_to_vtk_type[key_]).tofile(f, sep="\n") + vtk_type = meshio_to_vtk_type[c.type] + np.full(len(c.data), vtk_type).tofile(f, sep="\n") f.write(b"\n") diff --git a/test/helpers.py b/test/helpers.py index 2b6a91378..d53b86690 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -254,8 +254,8 @@ [ ("triangle", [[0, 1, 2], [4, 5, 6]]), ("quad", [[0, 1, 2, 3]]), - ("polygon5", [[1, 4, 5, 6, 2]]), - ("polygon6", [[0, 3, 7, 8, 9, 10], [1, 3, 7, 8, 9, 10]]), + ("polygon", [[1, 4, 5, 6, 2]]), + ("polygon", [[0, 3, 7, 8, 9, 10], [1, 3, 7, 8, 9, 10]]), ], ) From 1a17cc0e457907af54ec744ed3a0b9d5b329b547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20Schl=C3=B6mer?= Date: Thu, 29 Apr 2021 11:21:36 +0200 Subject: [PATCH 2/6] fix for vtu polygon --- meshio/vtu/_vtu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshio/vtu/_vtu.py b/meshio/vtu/_vtu.py index 36b9a0d1b..26ef72ccc 100644 --- a/meshio/vtu/_vtu.py +++ b/meshio/vtu/_vtu.py @@ -97,7 +97,7 @@ def _cells_from_data(connectivity, offsets, types, cell_data_raw): start_cn[items + 1], _vtk_to_meshio_order(types[start], sz, dtype=offsets.dtype) - sz, ) - cells.append(CellBlock(meshio_type + str(sz), connectivity[indices])) + cells.append(CellBlock(meshio_type, connectivity[indices])) # Store cell data for this set of cells for name, d in cell_data_raw.items(): From 15545a0caa347896f591bfbc297b915362875b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20Schl=C3=B6mer?= Date: Thu, 29 Apr 2021 11:51:53 +0200 Subject: [PATCH 3/6] vtu fix --- meshio/vtu/_vtu.py | 34 +++++++--------------------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/meshio/vtu/_vtu.py b/meshio/vtu/_vtu.py index 26ef72ccc..b7f20552d 100644 --- a/meshio/vtu/_vtu.py +++ b/meshio/vtu/_vtu.py @@ -668,9 +668,10 @@ def write(filename, mesh, binary=True, compression="zlib", header_type=None): # in certain places. is_polyhedron_grid = False for c in mesh.cells: - if c.type[:10] == "polyhedron": + if c.type.startswith("polyhedron"): is_polyhedron_grid = True break + # The current implementation cannot mix polyhedral cells with other cell types. # To write such meshes, represent all cells as polyhedra. if is_polyhedron_grid: @@ -908,31 +909,9 @@ def _polyhedron_face_cells(face_cells): # types types_array = [] - for k, v in mesh.cells: - # For polygon and polyhedron grids, the number of nodes is part of the cell - # type key. This part must be stripped away. - special_cells = [ - "polygon", - "polyhedron", - "VTK_LAGRANGE_CURVE", - "VTK_LAGRANGE_TRIANGLE", - "VTK_LAGRANGE_QUADRILATERAL", - "VTK_LAGRANGE_TETRAHEDRON", - "VTK_LAGRANGE_HEXAHEDRON", - "VTK_LAGRANGE_WEDGE", - "VTK_LAGRANGE_PYRAMID", - ] - key_ = None - for string in special_cells: - if k.startswith(string): - key_ = string - - if key_ is None: - # No special treatment - key_ = k - - # further adaptions for polyhedron - if k.startswith("polyhedron"): + for key, v in mesh.cells: + # some adaptions for polyhedron + if key.startswith("polyhedron"): # Get face-cell relation on the vtu format. See comments in helper # function for more information of how to specify this. faces_loc, faceoffsets_loc = _polyhedron_face_cells(v) @@ -944,8 +923,9 @@ def _polyhedron_face_cells(face_cells): assert faces is not None faces += faces_loc faceoffsets += faceoffsets_loc + key = "polyhedron" - types_array.append(np.full(len(v), meshio_to_vtk_type[key_])) + types_array.append(np.full(len(v), meshio_to_vtk_type[key])) types = np.concatenate( types_array From 28067177b531679d1316c0a3f65fa48308498fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20Schl=C3=B6mer?= Date: Thu, 29 Apr 2021 11:52:36 +0200 Subject: [PATCH 4/6] repr fix --- meshio/_mesh.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/meshio/_mesh.py b/meshio/_mesh.py index fd1a22c97..516ba3b52 100644 --- a/meshio/_mesh.py +++ b/meshio/_mesh.py @@ -82,11 +82,22 @@ def __init__( def __repr__(self): lines = ["", f" Number of points: {len(self.points)}"] + special_cells = [ + "polygon", + "polyhedron", + "VTK_LAGRANGE_CURVE", + "VTK_LAGRANGE_TRIANGLE", + "VTK_LAGRANGE_QUADRILATERAL", + "VTK_LAGRANGE_TETRAHEDRON", + "VTK_LAGRANGE_HEXAHEDRON", + "VTK_LAGRANGE_WEDGE", + "VTK_LAGRANGE_PYRAMID", + ] if len(self.cells) > 0: lines.append(" Number of cells:") for cell_type, elems in self.cells: string = cell_type - if cell_type == "polygon": + if cell_type in special_cells: string += f"({elems.shape[1]})" lines.append(f" {string}: {len(elems)}") else: From 01e691c241997ccb2c76ae6e48bd9f60589eba58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20Schl=C3=B6mer?= Date: Thu, 29 Apr 2021 12:16:42 +0200 Subject: [PATCH 5/6] ply polygon test + fixes --- meshio/ply/_ply.py | 41 ++++++++++++++++------------------------- test/test_ply.py | 1 + 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/meshio/ply/_ply.py b/meshio/ply/_ply.py index e14b7144f..60c05be22 100644 --- a/meshio/ply/_ply.py +++ b/meshio/ply/_ply.py @@ -43,25 +43,17 @@ numpy_to_ply_dtype = {np.dtype(v): k for k, v in ply_to_numpy_dtype.items()} -_cell_type_to_count = {"vertex": 1, "line": 2, "triangle": 3, "quad": 4} - - -def cell_type_to_count(cell_type): - if cell_type in _cell_type_to_count: - return _cell_type_to_count[cell_type] - - match = re.fullmatch(r"polygon(\d+)", cell_type) - if match: - return int(match.group(1)) - - -_cell_type_from_count = {val: key for (key, val) in _cell_type_to_count.items()} - - def cell_type_from_count(count): - """Reverse of ``cell_type_to_count``, defaults to ``"polygon" + str(counr)`` - if unknown.""" - return _cell_type_from_count.get(count) or "polygon" + str(count) + if count == 1: + return "vertex" + elif count == 2: + return "line" + elif count == 3: + return "triangle" + elif count == 4: + return "quad" + + return "polygon" def read(filename): @@ -145,7 +137,6 @@ def read_buffer(f): f"got `{line}`" ) - # read header if is_binary: mesh = _read_binary( f, @@ -210,7 +201,7 @@ def _read_ascii( } cell_data = {} - # the faces must be read line-by-line + # polygons must be read line-by-line polygons = collections.defaultdict(list) for k in range(num_cells): line = f.readline().decode("utf-8").strip() @@ -445,9 +436,11 @@ def write(filename, mesh, binary=True): # noqa: C901 pd.append(value) num_cells = 0 + legal_cell_types = ["vertex", "line", "triangle", "quad", "polygon"] for cell_type, c in mesh.cells: - if cell_type_to_count(cell_type): + if cell_type in legal_cell_types: num_cells += c.data.shape[0] + if num_cells > 0: fh.write(f"element face {num_cells:d}\n".encode("utf-8")) @@ -474,9 +467,7 @@ def write(filename, mesh, binary=True): # noqa: C901 if cell_dtype is not None: ply_type = numpy_to_ply_dtype[cell_dtype] fh.write( - "property list {} {} vertex_indices\n".format( - "uint8", ply_type - ).encode("utf-8") + f"property list uint8 {ply_type} vertex_indices\n".encode("utf-8") ) # TODO other cell data @@ -489,7 +480,7 @@ def write(filename, mesh, binary=True): # noqa: C901 # cells for cell_type, data in mesh.cells: - if cell_type_to_count(cell_type) is None: + if cell_type not in legal_cell_types: warnings.warn( 'cell_type "{}" is not supported by ply format - skipping' ) diff --git a/test/test_ply.py b/test/test_ply.py index ba3f02a15..dde35d78f 100644 --- a/test/test_ply.py +++ b/test/test_ply.py @@ -17,6 +17,7 @@ helpers.add_point_data(helpers.tri_mesh, 1, dtype=int), helpers.add_point_data(helpers.tri_mesh, 1, dtype=float), helpers.line_mesh, + helpers.polygon_mesh, # helpers.add_cell_data(helpers.tri_mesh, [("a", (), np.float64)]), # helpers.add_cell_data(helpers.tri_mesh, [("a", (2,), np.float64)]), # helpers.add_cell_data(helpers.tri_mesh, [("a", (3,), np.float64)]), From 05255572a4f8bf3dfb803b4757e9223eb7cefe5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nico=20Schl=C3=B6mer?= Date: Thu, 29 Apr 2021 12:18:36 +0200 Subject: [PATCH 6/6] change log --- CHANGELOG.md | 7 +++++++ setup.cfg | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec3caf4a9..2940651a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ This document only describes _breaking_ changes in meshio. If you are interested fixes, enhancements etc., best follow [the meshio project on GitHub](https://github.com/nschloe/meshio). +## v4.4.0 (Apr 29, 2021) + +- Polygons are now stored as `"polygon"` cell blocks, not `"polygonN"` (where `N` is the + number of nodes per polygon). One can simply retrieve the number of points via + `cellblock.data.shape[1]`. + + ## v4.0.0 (Feb 18, 2020) - `mesh.cells` used to be a dictionary of the form diff --git a/setup.cfg b/setup.cfg index 4edd6cc66..ee3ee49db 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = meshio -version = 4.3.13 +version = 4.4.0 author = Nico Schlömer et al. author_email = nico.schloemer@gmail.com description = I/O for many mesh formats