@@ -972,10 +972,7 @@ def convert_geometry_to_mesh(
972972 if verts is None :
973973 verts = ifcopenshell .util .shape .get_vertices (geometry )
974974 faces = ifcopenshell .util .shape .get_faces (geometry )
975- total_faces : int
976- if total_faces := faces .shape [0 ]:
977- num_vertices : int = verts .shape [0 ]
978-
975+ if faces .shape [0 ] > 0 :
979976 # See bug 3546
980977 # ios_edges holds true edges that aren't triangulated.
981978 #
@@ -984,38 +981,7 @@ def convert_geometry_to_mesh(
984981 ios_item_ids = ifcopenshell .util .shape .get_faces_representation_item_ids (geometry ).tolist ()
985982 mesh ["ios_item_ids" ] = ios_item_ids
986983
987- mesh .vertices .add (num_vertices )
988- mesh .vertices .foreach_set ("co" , verts .ravel ().astype ("f" ))
989-
990- is_triangulated = True
991- num_vertex_indices = faces .size
992- if is_triangulated :
993- loop_start = np .arange (0 , num_vertex_indices , 3 , dtype = "I" )
994- loop_total = np .full (total_faces , 3 , dtype = "I" )
995- use_smooth = np .zeros (num_vertex_indices , dtype = "?" )
996-
997- mesh .loops .add (num_vertex_indices )
998- mesh .loops .foreach_set ("vertex_index" , faces .ravel ().astype ("I" ))
999- mesh .polygons .add (total_faces )
1000- mesh .polygons .foreach_set ("loop_start" , loop_start )
1001- mesh .polygons .foreach_set ("loop_total" , loop_total )
1002- mesh .polygons .foreach_set ("use_smooth" , use_smooth )
1003- else :
1004- # TODO: optimize using correct numpy array types.
1005- faces_array = np .array (geometry .faces , dtype = object )
1006- loop_total = np .array (tuple (len (face ) for face in faces_array ), dtype = "I" )
1007- loop_start = np .cumsum ((0 ,) + loop_total )[:- 1 ]
1008- vertex_index = np .concatenate (faces_array )
1009- use_smooth = np .zeros (num_vertex_indices , dtype = "?" )
1010-
1011- mesh .loops .add (len (vertex_index ))
1012- mesh .loops .foreach_set ("vertex_index" , vertex_index )
1013- mesh .polygons .add (len (loop_start ))
1014- mesh .polygons .foreach_set ("loop_start" , loop_start )
1015- mesh .polygons .foreach_set ("loop_total" , loop_total )
1016- mesh .polygons .foreach_set ("use_smooth" , use_smooth )
1017-
1018- mesh .update ()
984+ mesh = tool .Loader .create_mesh_from_shape (mesh = mesh , verts = verts , faces = faces )
1019985
1020986 rep_str : str = geometry .id
1021987 if load_indexed_maps and "openings" not in rep_str :
@@ -1043,6 +1009,72 @@ def convert_geometry_to_mesh(
10431009 mesh ["ios_material_ids" ] = ifcopenshell .util .shape .get_faces_material_style_ids (geometry ).tolist ()
10441010 return mesh
10451011
1012+ @classmethod
1013+ def create_mesh_from_shape (
1014+ cls ,
1015+ geometry : Optional [ifcopenshell .geom .ShapeType ] = None ,
1016+ mesh : Optional [bpy .types .Mesh ] = None ,
1017+ * ,
1018+ verts : Optional [npt .NDArray [np .float64 ]] = None ,
1019+ faces : Optional [npt .NDArray [np .int32 ]] = None ,
1020+ ) -> bpy .types .Mesh :
1021+ """
1022+ Either geometry or verts+faces should be provided.
1023+
1024+ :param verts: Numpy array of shape (n, 3).
1025+ :param faces: Numpy array of shape (m, 3).
1026+ """
1027+ assert geometry is not None or (verts is not None and faces is not None ), (
1028+ "Either geometry or verts+faces should be provided.\n "
1029+ f"Current geometry: { geometry } \n "
1030+ f"Current verts: { verts } \n "
1031+ f"Current faces: { faces } "
1032+ )
1033+
1034+ if mesh is None :
1035+ mesh = bpy .data .meshes .new ("temp" )
1036+
1037+ if verts is None or faces is None :
1038+ verts = ifcopenshell .util .shape .get_vertices (geometry )
1039+ faces = ifcopenshell .util .shape .get_faces (geometry )
1040+
1041+ total_faces : int = faces .shape [0 ]
1042+ num_vertices : int = verts .shape [0 ]
1043+ mesh .vertices .add (num_vertices )
1044+ mesh .vertices .foreach_set ("co" , verts .ravel ().astype ("f" ))
1045+
1046+ is_triangulated = True
1047+ num_vertex_indices = faces .size
1048+ if is_triangulated :
1049+ loop_start = np .arange (0 , num_vertex_indices , 3 , dtype = "I" )
1050+ loop_total = np .full (total_faces , 3 , dtype = "I" )
1051+ use_smooth = np .zeros (num_vertex_indices , dtype = "?" )
1052+
1053+ mesh .loops .add (num_vertex_indices )
1054+ mesh .loops .foreach_set ("vertex_index" , faces .ravel ().astype ("I" ))
1055+ mesh .polygons .add (total_faces )
1056+ mesh .polygons .foreach_set ("loop_start" , loop_start )
1057+ mesh .polygons .foreach_set ("loop_total" , loop_total )
1058+ mesh .polygons .foreach_set ("use_smooth" , use_smooth )
1059+ else :
1060+ # TODO: optimize using correct numpy array types.
1061+ faces_array = np .array (geometry .faces , dtype = object )
1062+ loop_total = np .array (tuple (len (face ) for face in faces_array ), dtype = "I" )
1063+ loop_start = np .cumsum ((0 ,) + loop_total )[:- 1 ]
1064+ vertex_index = np .concatenate (faces_array )
1065+ use_smooth = np .zeros (num_vertex_indices , dtype = "?" )
1066+
1067+ mesh .loops .add (len (vertex_index ))
1068+ mesh .loops .foreach_set ("vertex_index" , vertex_index )
1069+ mesh .polygons .add (len (loop_start ))
1070+ mesh .polygons .foreach_set ("loop_start" , loop_start )
1071+ mesh .polygons .foreach_set ("loop_total" , loop_total )
1072+ mesh .polygons .foreach_set ("use_smooth" , use_smooth )
1073+
1074+ mesh .update ()
1075+
1076+ return mesh
1077+
10461078 @classmethod
10471079 def setup_active_bsdd_classification (cls ) -> None :
10481080 ifc_file = tool .Ifc .get ()
0 commit comments