def parse_shape(self, geometry): # compute the tessellation tess = ShapeTesselator(geometry) tess.Compute(compute_edges=True) # tess.Compute(compute_edges=False, mesh_quality=1.0, parallel=True) # get the vertices vertices = [] vertex_count = tess.ObjGetVertexCount() for i_vertex in range(0, vertex_count): i1, i2, i3 = tess.GetVertex(i_vertex) vertices.append(i1) vertices.append(i2) vertices.append(i3) # get the normals normals = [] normals_count = tess.ObjGetNormalCount() for i_normal in range(0, normals_count): i1, i2, i3 = tess.GetNormal(i_normal) normals.append(i1) normals.append(i2) normals.append(i3) # get the triangles triangles = [] triangle_count = tess.ObjGetTriangleCount() for i_triangle in range(0, triangle_count): i1, i2, i3 = tess.GetTriangleIndex(i_triangle) triangles.append(i1) triangles.append(i2) triangles.append(i3) # get the edges edges = [] edge_count = tess.ObjGetEdgeCount() for i_edge in range(0, edge_count): vertex_count = tess.ObjEdgeGetVertexCount(i_edge) # edge = [] for i_vertex in range(0, vertex_count): vertex = tess.GetEdgeVertex(i_edge, i_vertex) # edge.append(vertex) # edges.append(i_vertex) edges.append(vertex[0]) edges.append(vertex[1]) edges.append(vertex[2]) # edges.append(edge) return vertices, normals, triangles, edges
def occ_shape_to_faces( shape: "TopoDS_Shape", quality=1.0, render_edges=False, parallel=True ) -> Tuple[np.ndarray, np.ndarray, np.ndarray, Union[None, np.ndarray]]: from OCC.Core.Tesselator import ShapeTesselator # first, compute the tesselation try: tess = ShapeTesselator(shape) except RuntimeError as e: raise UnableToCreateTesselationFromSolidOCCGeom(e) tess.Compute(compute_edges=render_edges, mesh_quality=quality, parallel=parallel) # get vertices and normals vertices_position = tess.GetVerticesPositionAsTuple() number_of_triangles = tess.ObjGetTriangleCount() number_of_vertices = len(vertices_position) # number of vertices should be a multiple of 3 if number_of_vertices % 3 != 0: raise AssertionError("Wrong number of vertices") if number_of_triangles * 9 != number_of_vertices: raise AssertionError("Wrong number of triangles") # then we build the vertex and faces collections as numpy ndarrays np_vertices = np.array(vertices_position, dtype="float32").reshape( int(number_of_vertices / 3), 3) # Note: np_faces is just [0, 1, 2, 3, 4, 5, ...], thus arange is used np_faces = np.arange(np_vertices.shape[0], dtype="uint32") np_normals = np.array(tess.GetNormalsAsTuple(), dtype="float32").reshape(-1, 3) edges = np.array( map( lambda i_edge: [ tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range(tess.ObjEdgeGetVertexCount(i_edge)) ], range(tess.ObjGetEdgeCount()), )) return np_vertices, np_faces, np_normals, edges
def compute(self): shape_tesselator = ShapeTesselator(self._shape) shape_tesselator.Compute(compute_edges=self._export_edges, mesh_quality=self._mesh_quality, parallel=True) self._triangle_sets.append( shape_tesselator.ExportShapeToX3DTriangleSet()) # then process edges if self._export_edges: # get number of edges nbr_edges = shape_tesselator.ObjGetEdgeCount() for i_edge in range(nbr_edges): edge_point_set = [] nbr_vertices = shape_tesselator.ObjEdgeGetVertexCount(i_edge) for i_vert in range(nbr_vertices): edge_point_set.append( shape_tesselator.GetEdgeVertex(i_edge, i_vert)) ils = export_edge_to_indexed_lineset(edge_point_set) self._line_sets.append(ils)
def draw_shape_mpl(shape): """ Draw a TopoDS_Shape with matplotlib """ tess = ShapeTesselator(shape) tess.Compute() triangles = [] edges = [] # get the triangles triangle_count = tess.ObjGetTriangleCount() for i_triangle in range(0, triangle_count): i1, i2, i3 = tess.GetTriangleIndex(i_triangle) triangles.append( [tess.GetVertex(i1), tess.GetVertex(i2), tess.GetVertex(i3)]) # get the edges edge_count = tess.ObjGetEdgeCount() for i_edge in range(0, edge_count): vertex_count = tess.ObjEdgeGetVertexCount(i_edge) edge = [] for i_vertex in range(0, vertex_count): vertex = tess.GetEdgeVertex(i_edge, i_vertex) edge.append(vertex) edges.append(edge) # plot it fig = plt.figure() ax = Axes3D(fig) ax.add_collection3d(Poly3DCollection(triangles, linewidths=0.2, alpha=0.5)) ax.add_collection3d(Line3DCollection(edges, colors='w', linewidths=1.0)) ax.get_xaxis().set_visible(True) ax.get_yaxis().set_visible(True) ax.set_autoscale_on(True) plt.show()
def DisplayShape(self, shape, export_edges=False, color=(0.65, 0.65, 0.7), specular_color=(0.2, 0.2, 0.2), shininess=0.9, transparency=0., line_color=(0, 0., 0.), line_width=1., mesh_quality=1.): # if the shape is an edge or a wire, use the related functions if is_edge(shape): print("discretize an edge") pnts = discretize_edge(shape) edge_hash = "edg%s" % uuid.uuid4().hex str_to_write = export_edgedata_to_json(edge_hash, pnts) edge_full_path = os.path.join(self._path, edge_hash + '.json') with open(edge_full_path, "w") as edge_file: edge_file.write(str_to_write) # store this edge hash self._3js_edges[edge_hash] = [color, line_width] return self._3js_shapes, self._3js_edges elif is_wire(shape): print("discretize a wire") pnts = discretize_wire(shape) wire_hash = "wir%s" % uuid.uuid4().hex str_to_write = export_edgedata_to_json(wire_hash, pnts) wire_full_path = os.path.join(self._path, wire_hash + '.json') with open(wire_full_path, "w") as wire_file: wire_file.write(str_to_write) # store this edge hash self._3js_edges[wire_hash] = [color, line_width] return self._3js_shapes, self._3js_edges shape_uuid = uuid.uuid4().hex shape_hash = "shp%s" % shape_uuid # tesselate tess = ShapeTesselator(shape) tess.Compute(compute_edges=export_edges, mesh_quality=mesh_quality, parallel=True) # update spinning cursor sys.stdout.write("\r%s mesh shape %s, %i triangles " % (next( self.spinning_cursor), shape_hash, tess.ObjGetTriangleCount())) sys.stdout.flush() # export to 3JS shape_full_path = os.path.join(self._path, shape_hash + '.json') # add this shape to the shape dict, sotres everything related to it self._3js_shapes[shape_hash] = [ export_edges, color, specular_color, shininess, transparency, line_color, line_width ] # generate the mesh #tess.ExportShapeToThreejs(shape_hash, shape_full_path) # and also to JSON with open(shape_full_path, 'w') as json_file: json_file.write(tess.ExportShapeToThreejsJSONString(shape_uuid)) # draw edges if necessary if export_edges: # export each edge to a single json # get number of edges nbr_edges = tess.ObjGetEdgeCount() for i_edge in range(nbr_edges): # after that, the file can be appended str_to_write = '' edge_point_set = [] nbr_vertices = tess.ObjEdgeGetVertexCount(i_edge) for i_vert in range(nbr_vertices): edge_point_set.append(tess.GetEdgeVertex(i_edge, i_vert)) # write to file edge_hash = "edg%s" % uuid.uuid4().hex str_to_write += export_edgedata_to_json( edge_hash, edge_point_set) # create the file edge_full_path = os.path.join(self._path, edge_hash + '.json') with open(edge_full_path, "w") as edge_file: edge_file.write(str_to_write) # store this edge hash, with black color self._3js_edges[edge_hash] = [(0, 0, 0), line_width] return self._3js_shapes, self._3js_edges
def AddShapeToScene( self, shp, shape_color=None, # the default render_edges=False, edge_color=None, vertex_color=None, quality=1.0, transparency=False, opacity=1.0, ): # first, compute the tesselation tess = ShapeTesselator(shp) tess.Compute(compute_edges=render_edges, mesh_quality=quality, parallel=True) # get vertices and normals vertices_position = tess.GetVerticesPositionAsTuple() number_of_triangles = tess.ObjGetTriangleCount() number_of_vertices = len(vertices_position) # number of vertices should be a multiple of 3 if number_of_vertices % 3 != 0: raise AssertionError("Wrong number of vertices") if number_of_triangles * 9 != number_of_vertices: raise AssertionError("Wrong number of triangles") # then we build the vertex and faces collections as numpy ndarrays np_vertices = np.array(vertices_position, dtype="float32").reshape( int(number_of_vertices / 3), 3) # Note: np_faces is just [0, 1, 2, 3, 4, 5, ...], thus arange is used np_faces = np.arange(np_vertices.shape[0], dtype="uint32") # set geometry properties buffer_geometry_properties = { "position": BufferAttribute(np_vertices), "index": BufferAttribute(np_faces), } if self._compute_normals_mode == NORMAL.SERVER_SIDE: # get the normal list, converts to a numpy ndarray. This should not raise # any issue, since normals have been computed by the server, and are available # as a list of floats np_normals = np.array(tess.GetNormalsAsTuple(), dtype="float32").reshape(-1, 3) # quick check if np_normals.shape != np_vertices.shape: raise AssertionError("Wrong number of normals/shapes") buffer_geometry_properties["normal"] = BufferAttribute(np_normals) # build a BufferGeometry instance shape_geometry = BufferGeometry(attributes=buffer_geometry_properties) # if the client has to render normals, add the related js instructions if self._compute_normals_mode == NORMAL.CLIENT_SIDE: shape_geometry.exec_three_obj_method("computeVertexNormals") # then a default material shp_material = self._material(shape_color, transparent=transparency, opacity=opacity) # and to the dict of shapes, to have a mapping between meshes and shapes mesh_id = "%s" % uuid.uuid4().hex self._shapes[mesh_id] = shp # finally create the mesh shape_mesh = Mesh(geometry=shape_geometry, material=shp_material, name=mesh_id) # edge rendering, if set to True if render_edges: edges = list( map( lambda i_edge: [ tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range(tess.ObjEdgeGetVertexCount(i_edge)) ], range(tess.ObjGetEdgeCount()), )) edge_list = _flatten(list(map(_explode, edges))) lines = LineSegmentsGeometry(positions=edge_list) mat = LineMaterial(linewidth=1, color=edge_color) edge_lines = LineSegments2(lines, mat, name=mesh_id) self._displayed_non_pickable_objects.add(edge_lines) return shape_mesh
def ConvertShape( self, shape, export_edges=False, color=(0.65, 0.65, 0.7), specular_color=(0.2, 0.2, 0.2), shininess=0.9, transparency=0.0, line_color=(0, 0.0, 0.0), line_width=1.0, point_size=1.0, mesh_quality=1.0, ): # if the shape is an edge or a wire, use the related functions color = color_to_hex(color) specular_color = color_to_hex(specular_color) if is_edge(shape): print("discretize an edge") pnts = discretize_edge(shape) edge_hash = "edg%s" % uuid.uuid4().hex shape_content = export_edgedata_to_json(edge_hash, pnts) # store this edge hash self._3js_edges[edge_hash] = [color, line_width, shape_content] return self._3js_shapes, self._3js_edges, self._3js_vertex elif is_wire(shape): print("discretize a wire") pnts = discretize_wire(shape) wire_hash = "wir%s" % uuid.uuid4().hex shape_content = export_edgedata_to_json(wire_hash, pnts) # store this edge hash self._3js_edges[wire_hash] = [color, line_width, shape_content] return self._3js_shapes, self._3js_edges, self._3js_vertex # if shape is array of gp_Pnt elif isinstance(shape, list) and isinstance(shape[0], gp_Pnt): print("storage points") vertices_list = [] # will be passed to javascript BB = BRep_Builder() compound = TopoDS_Compound() BB.MakeCompound(compound) for vertex in shape: vertext_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape() BB.Add(compound, vertext_to_add) vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()]) points_hash = "pnt%s" % uuid.uuid4().hex # store this vertex hash. Note: TopoDS_Compound did not save now self._3js_vertex[points_hash] = [color, point_size, vertices_list] return self._3js_shapes, self._3js_edges, self._3js_vertex # convert as TopoDS_Shape shape_uuid = uuid.uuid4().hex shape_hash = "shp%s" % shape_uuid # tesselate tess = ShapeTesselator(shape) tess.Compute(compute_edges=export_edges, mesh_quality=mesh_quality, parallel=True) # update spinning cursor sys.stdout.write("\r%s mesh shape %s, %i triangles " % (next( self.spinning_cursor), shape_hash, tess.ObjGetTriangleCount())) sys.stdout.flush() # export to 3JS # generate the mesh shape_content = tess.ExportShapeToThreejsJSONString(shape_uuid) # add this shape to the shape dict, sotres everything related to it self._3js_shapes[shape_hash] = [ export_edges, color, specular_color, shininess, transparency, line_color, line_width, shape_content, ] # draw edges if necessary if export_edges: # export each edge to a single json # get number of edges nbr_edges = tess.ObjGetEdgeCount() for i_edge in range(nbr_edges): # after that, the file can be appended edge_content = "" edge_point_set = [] nbr_vertices = tess.ObjEdgeGetVertexCount(i_edge) for i_vert in range(nbr_vertices): edge_point_set.append(tess.GetEdgeVertex(i_edge, i_vert)) # write to file edge_hash = "edg%s" % uuid.uuid4().hex edge_content += export_edgedata_to_json( edge_hash, edge_point_set) # store this edge hash, with black color self._3js_edges[edge_hash] = [ color_to_hex((0, 0, 0)), line_width, edge_content, ] return self._3js_shapes, self._3js_edges, self._3js_vertex