Beispiel #1
0
 def test_tesselate_torus_with_bad_quality(self):
     """2st test : tesselation of a torus"""
     a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape()
     tess = ShapeTesselator(a_torus)
     tess.Compute(mesh_quality=40.0)
     # since mesh quality is much lower, we should count less vertices and
     # triangles
     self.assertGreater(tess.ObjGetTriangleCount(), 10)
     self.assertLess(tess.ObjGetTriangleCount(), 100)
     self.assertGreater(tess.ObjGetNormalCount(), 10)
     self.assertLess(tess.ObjGetNormalCount(), 100)
Beispiel #2
0
 def test_tesselate_box(self):
     """1st test : tesselation of a box"""
     a_box = BRepPrimAPI_MakeBox(10, 20, 30).Shape()
     tess = ShapeTesselator(a_box)
     tess.Compute()
     self.assertEqual(tess.ObjGetTriangleCount(), 12)
     self.assertEqual(tess.ObjGetNormalCount(), 24)
Beispiel #3
0
 def test_tesselate_torus_with_edges(self):
     """2st test : tesselation of a torus"""
     a_torus = BRepPrimAPI_MakeTorus(10, 4).Shape()
     tess = ShapeTesselator(a_torus)
     tess.Compute(compute_edges=True)
     self.assertGreater(tess.ObjGetTriangleCount(), 100)
     self.assertGreater(tess.ObjGetNormalCount(), 100)
Beispiel #4
0
 def drawShape(self,
                  shape,
                  color=(0.65, 0.65, 0.7),
                  transparency=0.,
                  line_width=1.,
                 ):
     # if the shape is an edge or a wire, use the related functions
     shininess=0.9
     specular_color=(0.2, 0.2, 0.2)
     shape_precision, wire_precision = self.precision
     if is_edge(shape):
         print("discretize an edge")
         pnts = discretize_edge(shape, wire_precision)
         edge_hash = "exp_%s_edge" % str(self.shapeNum).zfill(3)
         self.shapeNum += 1
         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.stringList.append("\tzdeskXCurve(slidePath+'%s.json', %s, %g);\n"
                                     % (edge_hash, color_to_hex(color), line_width))
         print("%s, %i segments" % (edge_hash ,len(pnts)-1))
     elif is_wire(shape):
         print("discretize a wire")
         pnts = discretize_wire(shape, wire_precision)
         wire_hash = "exp_%s_wire" % str(self.shapeNum).zfill(3)
         self.shapeNum += 1
         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.stringList.append("\tzdeskXCurve(slidePath+'%s.json', %s, %g);\n"
                                     % (wire_hash, color_to_hex(color), line_width))
         print("%s, %i segments" % (wire_hash ,len(pnts)-1))
     else: #solid or shell
         print("tesselate a shape")
         shape_uuid = uuid.uuid4().hex
         shape_hash = "exp_%s_shape" % str(self.shapeNum).zfill(3)
         self.shapeNum += 1
         # tesselate
         tess = ShapeTesselator(shape)
         tess.Compute(compute_edges=False,
                      mesh_quality=shape_precision,
                      parallel=True)
         # export to 3JS
         shape_full_path = os.path.join(self._path, shape_hash + '.json')
         with open(shape_full_path, 'w') as json_file:
             json_file.write(tess.ExportShapeToThreejsJSONString(shape_uuid))
         self.stringList.append("\tzdeskXShape(slidePath+'%s.json', %s, %s, %g, %g);\n"
                                     % (shape_hash, color_to_hex(color), color_to_hex(specular_color), shininess, 1 - transparency))
         print("%s, %i triangles\n" % (shape_hash, tess.ObjGetTriangleCount()))
Beispiel #5
0
    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
Beispiel #6
0
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
Beispiel #7
0
    def to_tesselation(self) -> Mesh:
        """Create a tesselation of the shape for visualisation.

        Returns
        -------
        :class:`~compas.datastructures.Mesh`

        """
        tesselation = ShapeTesselator(self.shape)
        tesselation.Compute()
        vertices = [
            tesselation.GetVertex(i)
            for i in range(tesselation.ObjGetVertexCount())
        ]
        triangles = [
            tesselation.GetTriangleIndex(i)
            for i in range(tesselation.ObjGetTriangleCount())
        ]
        return Mesh.from_vertices_and_faces(vertices, triangles)
Beispiel #8
0
    def to_tesselation(self):
        """Convert the surface to a triangle mesh.

        Returns
        -------
        :class:`~compas.datastructures.Mesh`

        """
        from OCC.Core.Tesselator import ShapeTesselator

        tess = ShapeTesselator(self.occ_shape)
        tess.Compute()
        vertices = []
        triangles = []
        for i in range(tess.ObjGetVertexCount()):
            vertices.append(tess.GetVertex(i))
        for i in range(tess.ObjGetTriangleCount()):
            triangles.append(tess.GetTriangleIndex(i))
        return Mesh.from_vertices_and_faces(vertices, triangles)
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()
Beispiel #10
0
 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
    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 tessellation
tess = ShapeTesselator(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
normals = tess.GetNormalsAsTuple()
number_of_normals = len(normals)
if not number_of_normals == number_of_vertices:
    raise AssertionError("wrong number of normals returned by the tessellator")

# if HAVE_NUMPY, we try to reshape the tuple so that it is of
Beispiel #12
0
# ==============================================================================
# Tesselation
# ==============================================================================

tess = ShapeTesselator(shell)
tess.Compute()

vertices = []
triangles = []

for i in range(tess.ObjGetVertexCount()):
    xyz = tess.GetVertex(i)
    vertices.append(xyz)

for i in range(tess.ObjGetTriangleCount()):
    a, b, c = tess.GetTriangleIndex(i)
    triangles.append([a, b, c])

mesh = Mesh.from_vertices_and_faces(vertices, triangles)

# ==============================================================================
# Viz
# ==============================================================================

print(mesh.number_of_vertices())
print(mesh.number_of_faces())

viewer = App()
viewer.add(mesh)
viewer.run()
Beispiel #13
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.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