def AddShapeToScene(self, shp, # the TopoDS_Shape to be displayed shape_color=default_shape_color, # the default render_edges=False, edge_color=default_edge_color, compute_uv_coords=False, quality=1.0, transparency=False, opacity=1.): # first, compute the tesselation tess = Tesselator(shp) tess.Compute(uv_coords=compute_uv_coords, compute_edges=render_edges, mesh_quality=quality, parallel=self._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 assert number_of_vertices % 3 == 0 assert number_of_triangles * 9 == number_of_vertices # 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 assert np_normals.shape == np_vertices.shape 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 = MeshPhongMaterial(color=shape_color, polygonOffset=True, polygonOffsetFactor=1, polygonOffsetUnits=1, shininess=0.9, transparent=transparency) # create a mesh unique id mesh_id = uuid.uuid4().hex # finally create the mash shape_mesh = Mesh(geometry=shape_geometry, material=shp_material, name=mesh_id) # and to the dict of shapes, to have a mapping between meshes and shapes self._shapes[mesh_id] = shp # edge rendering, if set to True edge_lines = None 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()))) edges = list(filter(lambda edge: len(edge) == 2, edges)) np_edge_vertices = np.array(edges, dtype=np.float32).reshape(-1, 3) np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32) edge_geometry = BufferGeometry(attributes={ 'position': BufferAttribute(np_edge_vertices), 'index' : BufferAttribute(np_edge_indices) }) edge_material = LineBasicMaterial(color=edge_color, linewidth=1) edge_lines = LineSegments(geometry=edge_geometry, material=edge_material) # Add geometries to pickable or non pickable objects self._displayed_pickable_objects.add(shape_mesh) if render_edges: self._displayed_non_pickable_objects.add(edge_lines)
def DisplayShape(self, shp, # the TopoDS_Shape to be displayed shape_color=default_shape_color, # the default render_edges=False, edge_color=default_edge_color, compute_uv_coords=False, quality=1.0, update=False): """ Displays a topods_shape in the renderer instance. shp: the TopoDS_Shape to render shape_color: the shape color, in html corm, eg '#abe000' render_edges: optional, False by default. If True, compute and dislay all edges as a linear interpolation of segments. edge_color: optional, black by default. The color used for edge rendering, in html form eg '#ff00ee' compute_uv_coords: optional, false by default. If True, compute texture coordinates (required if the shape has to be textured) quality: optional, 1.0 by default. If set to something lower than 1.0, mesh will be more precise. If set to something higher than 1.0, mesh will be less precise, i.e. lower numer of triangles. update: optional, False by default. If True, render all the shapes. """ # first, compute the tesselation tess = Tesselator(shp) tess.Compute(uv_coords=compute_uv_coords, compute_edges=render_edges, mesh_quality=quality, parallel=self._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 assert number_of_vertices % 3 == 0 assert number_of_triangles * 9 == number_of_vertices # 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 assert np_normals.shape == np_vertices.shape 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 = MeshPhongMaterial(color=shape_color, polygonOffset=True, polygonOffsetFactor=1, polygonOffsetUnits=1, shininess=0.9) # create a mesh unique id mesh_id = uuid.uuid4().hex # finally create the mash shape_mesh = Mesh(geometry=shape_geometry, material=shp_material, name=mesh_id) # adds this mesh to the list of meshes self._displayed_pickable_objects.add(shape_mesh) # and to the dict of shapes, to have a mapping between meshes and shapes self._shapes[mesh_id] = shp # edge rendering, if set to True edge_lines = None 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()))) edges = list(filter(lambda edge: len(edge) == 2, edges)) np_edge_vertices = np.array(edges, dtype=np.float32).reshape(-1, 3) np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32) edge_geometry = BufferGeometry(attributes={ 'position': BufferAttribute(np_edge_vertices), 'index' : BufferAttribute(np_edge_indices) }) edge_material = LineBasicMaterial(color=edge_color, linewidth=1) edge_lines = LineSegments(geometry=edge_geometry, material=edge_material) self._displayed_pickable_objects.add(edge_lines) if update: self.Display()
try: import numpy as np HAVE_NUMPY = True except: HAVE_NUMPY = False # create the shape box_s = BRepPrimAPI_MakeBox(10, 20, 30).Shape() # compute the tesselation tess = Tesselator(box_s) tess.Compute() # get vertices vertices_position = tess.GetVerticesPositionAsTuple() number_of_triangles = tess.ObjGetTriangleCount() number_of_vertices = len(vertices_position) # number of vertices should be a multiple of 3 assert number_of_vertices % 3 == 0 assert number_of_triangles * 9 == number_of_vertices # get normals normals = tess.GetNormalsAsTuple() number_of_normals = len(normals) assert number_of_normals == number_of_vertices # if HAVE_NUMPY, we try to reshape the tuple so that it is of # a ndarray such as [[x1, y1, z1], [x2, y2, z2], ...]