Beispiel #1
0
 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)
Beispiel #2
0
 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")))
Beispiel #3
0
 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)
Beispiel #6
0
 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)
Beispiel #10
0
    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)
Beispiel #11
0
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)
Beispiel #15
0
    def tessellate(shape):
        tess = Tesselator(shape.wrapped)
        tess.Compute(compute_edges=True, mesh_quality=tolerance)

        return tess
Beispiel #16
0
##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
Beispiel #17
0
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)
Beispiel #19
0
    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)
Beispiel #20
0
    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