def test_tesselate_box(self): """ 1st test : tesselation of a box """ a_box = BRepPrimAPI_MakeBox(10, 20, 30).Shape() tess = Tesselator(a_box) tess.Compute() self.assertEqual(tess.ObjGetTriangleCount(), 12) self.assertEqual(tess.ObjGetNormalCount(), 24)
def test_export_to_x3d(self): """ 3rd test : export a sphere to X3D file format """ a_sphere = BRepPrimAPI_MakeSphere(10.).Shape() tess = Tesselator(a_sphere) tess.Compute() tess.ExportShapeToX3D(os.path.join("test_io", "sphere.x3d")) self.assertTrue(os.path.exists(os.path.join("test_io", "sphere.x3d")))
def test_tesselate_torus_with_edges(self): """ 2st test : tesselation of a torus """ a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape() tess = Tesselator(a_torus) tess.Compute(compute_edges=True) self.assertGreater(tess.ObjGetTriangleCount(), 100) self.assertGreater(tess.ObjGetNormalCount(), 100)
def test_tesselate_torus(self): """ 2st test : tesselation of a torus """ a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape() tess = Tesselator(a_torus, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.) tess.Compute() self.assertGreater(tess.ObjGetTriangleCount(), 100) self.assertGreater(tess.ObjGetNormalCount(), 100)
def test_tesselate_box(self): """ 1st test : tesselation of a box """ a_box = BRepPrimAPI_MakeBox(10, 20, 30).Shape() tess = Tesselator(a_box, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.) tess.Compute() self.assert_(tess.ObjGetTriangleCount() == 12) self.assert_(tess.ObjGetNormalCount() == 24)
def test_export_to_x3d_TriangleSet(self): """ 3rd test : export a sphere to an X3D TriangleSet triangle mesh """ a_sphere = BRepPrimAPI_MakeBox(10., 10., 10.).Shape() tess = Tesselator(a_sphere) tess.Compute() ifs = tess.ExportShapeToX3DIndexedFaceSet() self.assertTrue(ifs.startswith("<TriangleSet")) self.assertTrue("0 10 0" in ifs) # a vertex self.assertTrue("0 0 1" in ifs) # a normal
def test_export_to_3js_JSON(self): a_box = BRepPrimAPI_MakeBox(10, 20, 30).Shape() tess = Tesselator(a_box) tess.Compute() # get the JSON string JSON_str = tess.ExportShapeToThreejsJSONString("myshapeid") # check the python JSON parser can decode the string # i.e. the JSON string is well formed dico = json.loads(JSON_str) # after that, check that the number of vertices is ok self.assertEqual(len(dico["data"]["attributes"]["position"]["array"]), 36*3)
def test_tesselate_torus_with_bad_quality(self): """ 2st test : tesselation of a torus """ a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape() tess = Tesselator(a_torus, atNormal, 1.0, 1, 0.01, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.) tess.Compute(mesh_quality=40.) # since mesh quality is much lower, we should count less vertices and # triangles self.assert_(tess.ObjGetTriangleCount() > 10) self.assert_(tess.ObjGetTriangleCount() < 100) self.assert_(tess.ObjGetNormalCount() > 10) self.assert_(tess.ObjGetNormalCount() < 100)
def DisplayShape(self, shape, vertex_shader=None, fragment_shader=None, map_faces_to_mesh=False, export_edges=False, color=(0.65, 0.65, 0.65), specular_color=(1, 1, 1), shininess=0.9, transparency=0., line_color=(0, 0., 0.), line_width=2., mesh_quality=1.): # create the shape hash shape_uuid = uuid.uuid4().hex shape_hash = "shp%s" % shape_uuid # tesselate tess = Tesselator(shape) tess.Compute(compute_edges=export_edges, mesh_quality=mesh_quality) # sys.stdout.write( "\r%s mesh shape, %i triangles" % (next(self.spinning_cursor), 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 edges = [] 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 += ExportEdgeToJSON(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 self._edges_hash.append(edge_hash)
def _Tesselateor(self, shape, mesh_quality=1.0): from OCC.Core.Visualization import Tesselator tess = Tesselator(shape) tess.Compute(compute_edges=False, mesh_quality=mesh_quality, uv_coords=False, parallel=True) vertices = [] for i in range(0, tess.ObjGetVertexCount()): vertices.append(tess.GetVertex(i)) normals = [] for i in range(0, tess.ObjGetNormalCount()): normals.append(tess.GetNormal(i)) triangles = [] for i in range(0, tess.ObjGetTriangleCount()): triangles.append(tess.GetTriangleIndex(i)) return (vertices, normals, triangles)
def draw_shape_mpl(shape): """ Draw a TopoDS_Shape with matplotlib """ tess = Tesselator(shape) 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 compute(self): shape_tesselator = Tesselator(self._shape) shape_tesselator.Compute(compute_edges=self._export_edges, mesh_quality=self._mesh_quality) self._triangle_sets.append(shape_tesselator.ExportShapeToX3DIndexedFaceSet()) # 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 = ExportEdgeToILS(edge_point_set) self._line_sets.append(ils)
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=2., 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 = Tesselator(shape) tess.Compute(compute_edges=export_edges, mesh_quality=mesh_quality, uv_coords=False, 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[hash] = [(0, 0, 0), line_width] return self._3js_shapes, self._3js_edges
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, opacity=opacity, side='DoubleSide') # 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 tessellate(shape): tess = Tesselator(shape.wrapped) tess.Compute(compute_edges=True, mesh_quality=tolerance) return tess
##along with pythonOCC. If not, see <http://www.gnu.org/licenses/>. from OCC.Core.Visualization import Tesselator from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakeBox try: import numpy as np HAVE_NUMPY = True except ImportError: 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 if number_of_vertices % 3 != 0: raise AssertionError("wrong number of vertices returned by the teselator") if number_of_triangles * 9 != number_of_vertices: raise AssertionError("wrong number of triangles returned by the teselator") # get normals
def _shape_to_json(shape, filename, export_edges=False, color=(0.65, 0.65, 0.65), specular_color=(1, 1, 1), shininess=0.9, transparency=0., line_color=(0, 0., 0.), line_width=2., mesh_quality=1.): r"""Converts a shape to a JSON file representation Parameters ---------- shape : OCC shape filename : str Full path to the file where the conversion is written export_edges : bool color specular_color shininess transparency line_color line_width mesh_quality Returns ------- Nothing, it is a procedure, not a function """ logger.info("Starting the conversion of a shape to JSON(%s)" % filename) _3js_shapes = {} _3js_edges = {} # if the shape is an edge or a wire, use the related functions if is_edge(shape): logger.debug("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(path, edge_hash + '.json') with open(filename, "w") as edge_file: edge_file.write(str_to_write) # store this edge hash _3js_edges[edge_hash] = [color, line_width] return True elif is_wire(shape): logger.debug("discretize a wire") pnts = discretize_wire(list(TopologyExplorer(shape).wires())[0]) wire_hash = "wir%s" % uuid.uuid4().hex str_to_write = export_edgedata_to_json(wire_hash, pnts) # wire_full_path = os.path.join(path, wire_hash + '.json') with open(filename, "w") as wire_file: wire_file.write(str_to_write) # store this edge hash _3js_edges[wire_hash] = [color, line_width] return True shape_uuid = uuid.uuid4().hex shape_hash = "shp%s" % shape_uuid # tesselate tess = Tesselator(shape) tess.Compute(compute_edges=export_edges, mesh_quality=mesh_quality, uv_coords=False, parallel=True) # export to 3JS # shape_full_path = os.path.join(path, shape_hash + '.json') # add this shape to the shape dict, sotres everything related to it _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(filename, '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(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 # _3js_edges[hash] = [(0, 0, 0), line_width] logger.info("End of the conversion of a shape to JSON(%s)" % filename)
# TEST 1 : one big STEP file into one single compound # loads the step file # load twice, not a copy/paste typo. It's because meshes are stored # the second time, meshing time is much faster print("TEST 1 ===") shp = read_step_file( os.path.join('..', 'examples', 'models', 'RC_Buggy_2_front_suspension.stp')) shp2 = read_step_file( os.path.join('..', 'examples', 'models', 'RC_Buggy_2_front_suspension.stp')) # tesselate in single thread mode print("Tesselate in single thread mode") t_single = Tesselator(shp) t0 = time.monotonic() t_single.Compute(parallel=False, mesh_quality=0.5) t1 = time.monotonic() delta_single = t1 - t0 # tesselate in parallel thread mode print("Tesselate in parallelized mode") t_multi = Tesselator(shp2) t2 = time.monotonic() t_multi.Compute(parallel=True, mesh_quality=0.5) t3 = time.monotonic() delta_multi = t3 - t2 print("Test 1 Results:") print(" * single thread runtime: %.2fs" % delta_single)
def _render_shape(self, shape_index, shape=None, edges=None, vertices=None, mesh_color=None, edge_color=None, vertex_color=None, render_edges=False, edge_width=1, vertex_width=5, deflection=0.05, transparent=False, opacity=1.0): edge_list = None edge_lines = None points = None shape_mesh = None if shape is not None: if mesh_color is None: mesh_color = self.default_mesh_color if edge_color is None: edge_color = self.default_edge_color if vertex_color is None: vertex_color = self.default_edge_color # same as edge_color # BEGIN copy # The next lines are copied with light modifications from # https://github.com/tpaviot/pythonocc-core/blob/master/src/Display/WebGl/jupyter_renderer.py # first, compute the tesselation tess = Tesselator(shape) tess.Compute(uv_coords=False, compute_edges=render_edges, mesh_quality=self.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') # compute normals np_normals = np.array(tess.GetNormalsAsTuple(), dtype='float32').reshape(-1, 3) if np_normals.shape != np_vertices.shape: raise AssertionError("Wrong number of normals/shapes") # build a BufferGeometry instance shape_geometry = BufferGeometry( attributes={ 'position': BufferAttribute(np_vertices), 'index': BufferAttribute(np_faces), 'normal': BufferAttribute(np_normals) }) shp_material = self._material(mesh_color, transparent=True, opacity=opacity) shape_mesh = Mesh(geometry=shape_geometry, material=shp_material, name="mesh_%d" % shape_index) if render_edges: edge_list = list( map( lambda i_edge: [ tess.GetEdgeVertex(i_edge, i_vert) for i_vert in range( tess.ObjEdgeGetVertexCount(i_edge)) ], range(tess.ObjGetEdgeCount()))) # END copy if vertices is not None: vertices_list = [] for vertex in vertices: p = BRep_Tool.Pnt(vertex) vertices_list.append((p.X(), p.Y(), p.Z())) vertices_list = np.array(vertices_list, dtype=np.float32) attributes = { "position": BufferAttribute(vertices_list, normalized=False) } mat = PointsMaterial(color=vertex_color, sizeAttenuation=False, size=vertex_width) geom = BufferGeometry(attributes=attributes) points = Points(geometry=geom, material=mat) if edges is not None: edge_list = [discretize_edge(edge, deflection) for edge in edges] if edge_list is not None: edge_list = _flatten(list(map(_explode, edge_list))) lines = LineSegmentsGeometry(positions=edge_list) mat = LineMaterial(linewidth=edge_width, color=edge_color) edge_lines = LineSegments2(lines, mat, name="edges_%d" % shape_index) if shape_mesh is not None or edge_lines is not None or points is not None: index_mapping = {"mesh": None, "edges": None, "shape": shape_index} if shape_mesh is not None: ind = len(self.pickable_objects.children) self.pickable_objects.add(shape_mesh) index_mapping["mesh"] = ind if edge_lines is not None: ind = len(self.pickable_objects.children) self.pickable_objects.add(edge_lines) index_mapping["edges"] = ind if points is not None: ind = len(self.pickable_objects.children) self.pickable_objects.add(points) index_mapping["mesh"] = ind self.pick_mapping.append(index_mapping)
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.): # first, compute the tesselation tess = Tesselator(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) self._displayed_non_pickable_objects.add(edge_lines) return shape_mesh
def generate_json_from_shape( shape, uri, export_edges=False, color=(0.65, 0.65, 0.65), specular_color=(1, 1, 1), shininess=0.9, transparency=0.0, line_color=(0, 0.0, 0.0), line_width=2.0, mesh_quality=1.0, filename="test", ): # 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 True # 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") # print(wire_full_path) # 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 True # TODO change uuid here # shape_uuid = uuid.uuid4().hex shape_uuid = uri # shape_hash = "shp%s" % shape_uuid shape_hash = "shp%s" % uuid.uuid4().hex # tesselate tess = Tesselator(shape) tess.Compute( compute_edges=export_edges, mesh_quality=mesh_quality, uv_coords=False, parallel=True, ) sys.stdout.flush() # export to 3JS # shape_full_path = os.path.join(self._path, shape_hash + '.json') # print(f'{shape_full_path} shape path') dirpath = os.getcwd() staticpath = "src/app/render/static/shapes" shape_full_path = os.path.join(dirpath, staticpath, shape_hash + ".json") # 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[hash] = [(0, 0, 0), line_width] return shape_hash