From 8bd77b36630a4c05ee0ae4c5abc35b40804af258 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 26 May 2023 19:24:44 +1000 Subject: [PATCH] New get_shape_matrix utility. --- .../geometry_processing.rst | 23 ++++++++++++------- .../ifcopenshell/util/shape.py | 16 ++++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_processing.rst b/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_processing.rst index 20ee185476..5bd4131902 100644 --- a/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_processing.rst +++ b/src/ifcopenshell-python/docs/ifcopenshell-python/geometry_processing.rst @@ -20,6 +20,7 @@ related information in ``shape.geometry``: import ifcopenshell import ifcopenshell.geom + import ifcopenshell.util.shape ifc_file = ifcopenshell.open('model.ifc') element = ifc_file.by_type('IfcWall')[0] @@ -55,19 +56,25 @@ related information in ``shape.geometry``: # Objects are never scaled, so the scale factor of the matrix is always 1. matrix = shape.transformation.matrix.data - # Indices of vertices per triangle face e.g. [f1v1, f1v2, f1v3, f2v1, f2v2, f2v3, ...] - faces = shape.geometry.faces - - # Indices of vertices per edge e.g. [e1v1, e1v2, e2v1, e2v2, ...] - edges = shape.geometry.edges + # For convenience, you might want the matrix as a nested numpy array, so you can do matrix math. + matrix = ifcopenshell.util.shape.get_shape_matrix(shape) # X Y Z of vertices in flattened list e.g. [v1x, v1y, v1z, v2x, v2y, v2z, ...] verts = shape.geometry.verts + # Indices of vertices per edge e.g. [e1v1, e1v2, e2v1, e2v2, ...] + edges = shape.geometry.edges + + # Indices of vertices per triangle face e.g. [f1v1, f1v2, f1v3, f2v1, f2v2, f2v3, ...] + faces = shape.geometry.faces + # Since the lists are flattened, you may prefer to group them like so depending on your geometry kernel - grouped_verts = [[verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)] - grouped_edges = [[edges[i], edges[i + 1]] for i in range(0, len(edges), 2)] - grouped_faces = [[faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)] + # A nested numpy array e.g. [[v1x, v1y, v1z], [v2x, v2y, v2z], ...] + grouped_verts = ifcopenshell.util.shape.get_vertices(shape.geometry) + # A nested numpy array e.g. [[e1v1, e1v2], [e2v1, e2v2], ...] + grouped_edges = ifcopenshell.util.shape.get_edges(shape.geometry) + # A nested numpy array e.g. [[f1v1, f1v2, f1v3], [f2v1, f2v2, f2v3], ...] + grouped_faces = ifcopenshell.util.shape.get_faces(shape.geometry) # A list of styles that are relevant to this shape styles = shape.geometry.materials diff --git a/src/ifcopenshell-python/ifcopenshell/util/shape.py b/src/ifcopenshell-python/ifcopenshell/util/shape.py index 7de09a4f2c..9053838679 100644 --- a/src/ifcopenshell-python/ifcopenshell/util/shape.py +++ b/src/ifcopenshell-python/ifcopenshell/util/shape.py @@ -66,6 +66,11 @@ def get_z(geometry): return max(z_values) - min(z_values) +def get_shape_matrix(shape): + m = shape.transformation.matrix.data + return np.array(([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])) + + def get_bbox_centroid(geometry): x_values = [geometry.verts[i] for i in range(0, len(geometry.verts), 3)] y_values = [geometry.verts[i + 1] for i in range(0, len(geometry.verts), 3)] @@ -89,9 +94,7 @@ def get_element_bbox_centroid(element, geometry): def get_shape_bbox_centroid(shape, geometry): centroid = get_bbox_centroid(geometry) - m = shape.transformation.matrix.data - mat = np.array(([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])) - return (mat @ np.array([*centroid, 1.0]))[0:3] + return (get_shape_matrix(shape) @ np.array([*centroid, 1.0]))[0:3] def get_vertices(geometry): @@ -110,14 +113,15 @@ def get_faces(geometry): def get_shape_vertices(shape, geometry): - m = shape.transformation.matrix.data - mat = np.array(([m[0], m[3], m[6], m[9]], [m[1], m[4], m[7], m[10]], [m[2], m[5], m[8], m[11]], [0, 0, 0, 1])) + verts = get_vertices(geometry) + mat = get_shape_matrix(shape) return np.array([mat @ np.array([verts[i], verts[i + 1], verts[i + 2]]) for i in range(0, len(verts), 3)]) def get_element_vertices(element, geometry): + verts = get_vertices(geometry) if not element.ObjectPlacement or not element.ObjectPlacement.is_a("IfcLocalPlacement"): - return get_shape_vertices(geometry) + return verts mat = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement) return np.array([mat @ np.array([verts[i], verts[i + 1], verts[i + 2]]) for i in range(0, len(verts), 3)])