Example #1
0
    def __init__(self, bb_center, length=1, width=3):
        super().__init__(bb_center)

        self.axes = []
        for vector, color in zip(([length, 0, 0], [0, length, 0], [0, 0, length]), ('red', 'green', 'blue')):
            self.axes.append(
                LineSegments2(
                    LineSegmentsGeometry(positions=[[self.center, self._shift(self.center, vector)]]),
                    LineMaterial(linewidth=width, color=color)))
Example #2
0
    def occ_shape_to_threejs(self, shp: TopoDS_Shape, shape_color, edge_color,
                             transparency, opacity):
        # first, compute the tesselation
        from .renderer_occ import occ_shape_to_faces
        from .threejs_utils import create_material

        np_vertices, np_faces, np_normals, edges = occ_shape_to_faces(
            shp, self.quality, self.render_edges, self.parallel)

        # set geometry properties
        buffer_geometry_properties = {
            "position": BufferAttribute(np_vertices),
            "index": BufferAttribute(np_faces),
        }
        if self.compute_normals_mode == NORMAL.SERVER_SIDE:
            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 = create_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.mesh_id = mesh_id
        # finally create the mesh
        shape_mesh = Mesh(geometry=shape_geometry,
                          material=shp_material,
                          name=mesh_id)

        # edge rendering, if set to True
        if self.render_edges:
            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)
        else:
            edge_lines = None

        return shape_mesh, edge_lines
def _get_line_from_vec(v0, v1, scene_args):
    """
    Draw the line given the two endpoints, some Three.js capabilities still
    don't work well in pythreejs (unable to update linewidth and such)
    LineSegments2 is the only one that has been tested successfully, but
    it cannot handle LineDashedMaterial
    :param v0: list, one endpoint of line
    :param v1: list, other endpoint of line
    :param scene_args: dict, properties of the line (line_width and color)
    :return: pythreejs object that displays the line segment
    """
    obj_args = update_object_args(scene_args, "Lines", ["linewidth", "color"])
    logger.debug(obj_args)
    line = LineSegments2(
        LineSegmentsGeometry(positions=[[v0, v1]]),
        LineMaterial(**obj_args),  # Dashed lines do not work in pythreejs yet
    )
    return line
def _get_line_from_vec(v0, v1, d_args):
    """Draw the line given the two endpoints, some threejs functionalities still don't work well in pythreejs (unable to update linewidth and such) 
    LineSegments2 is the onlyone that has tested sucessfully but it cannot handle LineDashedMaterial
    
    Args:
        v0 (list): one endpoint of line
        v1 (list): other endpoint of line
        d_args (dict): properties of the line (line_width and color)
    
    Returns:
        LineSegments2: Pythreejs object that displays the line sement
    """
    obj_args = update_object_args(d_args, "Lines", ['linewidth', 'color'])
    logger.debug(obj_args)
    line = LineSegments2(
        LineSegmentsGeometry(positions=[[v0, v1]]),
        LineMaterial(**obj_args),  # Dashed lines do not work in pythreejs yet
    )
    return line
Example #5
0
    def __init__(self,
        lines: Iterable[Edge],
        colors: Union[Iterable[Tuple[Coord3, ColorRGB]], Iterable[ColorRGB], ColorRGB, None] = None,
        width:int = 10,
        *args,
        **kwargs):
        """
        Plots a series of line segments.

        Arguments:
            lines: Iterable of (u,v), where u,v are 3 tuples of float coordinates.
            Lines are drawn between each u and v.
            colors: Either
                * An iterable of (u,c), where u is a coordinate, and c is a color.
                * a list of c (3coord, RGB), the same length as lines
                * single 3 tuple (RGB) applied to all lines


        """
        super().__init__(layer_name='lines',*args, **kwargs)
        if isinstance(colors, tuple):
            color = colors
            colors = None
        else:
            color = [0,0,0]
        colors = colors if (not colors is None) else [color for _ in lines]

        colors = np.array([c if len(c) == 2 else [c, c] for c in colors],dtype=np.float32)
        coords = []
        for uv in lines:
            coords.extend(uv)
        self._coords = np.array(coords)
        geo = LineSegmentsGeometry(
            positions=np.array(lines,dtype=np.float32),
            colors=colors,
        )
        mat = LineMaterial(linewidth=width, vertexColors="VertexColors")
        self._objects.append(LineSegments2(geo, mat))
Example #6
0
    def __init__(self, bb_center, length=1, width=3, display_labels=False):
        Helpers.__init__(self, bb_center)

        self.axes = []
        for vector, color in zip(
            ([length, 0, 0], [0, length, 0], [0, 0, length]),
            ('red', 'green', 'blue')):
            self.axes.append(
                LineSegments2(
                    LineSegmentsGeometry(
                        positions=[[self.center,
                                    _shift(self.center, vector)]]),
                    LineMaterial(linewidth=width, color=color)))

        if display_labels:
            # add x, y and z labels
            x_text = make_text("X", [length, 0, 0])
            y_text = make_text("Y", [0, length, 0])
            z_text = make_text("Z", [0, 0, length])

            self.axes.append(x_text)
            self.axes.append(y_text)
            self.axes.append(z_text)
Example #7
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 _get_line_from_vec(v0, v1):
    line = LineSegments2(
        LineSegmentsGeometry(positions=[[v0, v1]]),
        LineMaterial(linewidth=3, color="black"),
    )
    return line
Example #9
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)
Example #10
0
    def _render_shape(
        self,
        shape=None,
        edges=None,
        vertices=None,
        mesh_color=None,
        edge_color=None,
        vertex_color=None,
        edge_width=1,
        vertex_width=5,
        transparent=False,
        opacity=1.0,
    ):

        edge_list = []
        normals_list = []
        edge_lines = []
        normal_lines = []
        points = None
        shape_mesh = None

        # edge_accuracy = None

        if shape is not None:
            # Compute the tesselation and build mesh
            with Timer(self.timeit, "", "build mesh:", 5):
                edge_list, normals_list = shape["edges"]
                shape_geometry = BufferGeometry(
                    attributes={
                        "position": BufferAttribute(shape["vertices"]),
                        "index": BufferAttribute(shape["triangles"]),
                        "normal": BufferAttribute(shape["normals"]),
                    }
                )

                if mesh_color is None:
                    mesh_color = self.default_mesh_color
                shp_material = material(mesh_color, transparent=transparent, opacity=opacity)
                shape_mesh = IndexedMesh(geometry=shape_geometry, material=shp_material)

        if vertices is not None:
            if vertex_color is None:
                vertex_color = self.default_edge_color  # same as edge_color

            vertices_list = vertices
            attributes = {"position": BufferAttribute(vertices_list, normalized=False)}

            mat = PointsMaterial(color=vertex_color, sizeAttenuation=False, size=vertex_width)
            geom = BufferGeometry(attributes=attributes)
            points = IndexedPoints(geometry=geom, material=mat)

        if edges is not None:
            edge_list = edges

        if len(edge_list) > 0:
            if edge_color is None:
                edge_color = self.default_edge_color

            if isinstance(edge_color, (list, tuple)):
                if len(edge_list) != len(edge_color):
                    print("warning: color list and edge list have different length, using first color for all edges")
                    edge_color = edge_color[0]

            if isinstance(edge_color, (list, tuple)):
                lines = LineSegmentsGeometry(
                    positions=edge_list,
                    colors=[[Color(color).percentage] * 2 for color in edge_color],
                )
                mat = LineMaterial(linewidth=edge_width, vertexColors="VertexColors")
                edge_lines = [IndexedLineSegments2(lines, mat)]
            else:
                lines = LineSegmentsGeometry(positions=edge_list)
                mat = LineMaterial(
                    linewidth=edge_width, color=edge_color.web_color if isinstance(edge_color, Color) else edge_color
                )
                edge_lines = [IndexedLineSegments2(lines, mat)]

        if len(normals_list) > 0:
            lines = LineSegmentsGeometry(positions=normals_list)
            mat = LineMaterial(linewidth=2, color="#9400d3")
            normal_lines = [IndexedLineSegments2(lines, mat)]

        return shape_mesh, edge_lines, normal_lines, points
Example #11
0
    def render_shape(
        self,
        shape=None,
        edges=None,
        vertices=None,
        mesh_color=None,
        edge_color=None,
        vertex_color=None,
        render_edges=True,
        render_shapes=True,
        edge_width=1,
        vertex_width=5,
        transparent=False,
        opacity=1.0,
    ):

        edge_list = None
        edge_lines = None
        points = None
        shape_mesh = None

        render_timer = Timer(self.timeit, "| | shape render time")
        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

            # Compute the tesselation and build mesh
            tesselation_timer = Timer(self.timeit, "| | | build mesh time")
            shape_geometry = RENDER_CACHE.tessellate(shape, self.quality,
                                                     self.angular_tolerance,
                                                     self.timeit)

            shp_material = material(mesh_color.web_color,
                                    transparent=transparent,
                                    opacity=opacity)
            # Do not cache building the mesh. Might lead to unpredictable results
            shape_mesh = IndexedMesh(geometry=shape_geometry,
                                     material=shp_material)

            tesselation_timer.stop()

            if render_edges:
                edges = get_edges(shape)

            # unset shape_mesh again
            if not render_shapes:
                shape_mesh = None

        if vertices is not None:
            vertices_list = []
            for vertex in vertices:
                vertices_list.append(get_point(vertex))
            vertices_list = np.array(vertices_list, dtype=np.float32)

            attributes = {
                "position": BufferAttribute(vertices_list, normalized=False)
            }

            mat = PointsMaterial(color=vertex_color.web_color,
                                 sizeAttenuation=False,
                                 size=vertex_width)
            geom = BufferGeometry(attributes=attributes)
            points = IndexedPoints(geometry=geom, material=mat)

        if edges is not None:
            discretize_timer = Timer(self.timeit, "| | | discretize time")
            edge_list = [
                discretize_edge(edge, self.edge_accuracy) for edge in edges
            ]
            discretize_timer.stop()

        if edge_list is not None:
            discretize_timer = Timer(self.timeit, "| | | edge list")
            edge_list = flatten(list(map(explode, edge_list)))
            if isinstance(edge_color, (list, tuple)):
                if len(edge_list) != len(edge_color):
                    print(
                        "warning: color list and edge list have different length, using first color for all edges"
                    )
                    edge_color = edge_color[0]

            if isinstance(edge_color, (list, tuple)):
                lines = LineSegmentsGeometry(
                    positions=edge_list,
                    colors=[[color.percentage] * 2 for color in edge_color],
                )
                mat = LineMaterial(linewidth=edge_width,
                                   vertexColors="VertexColors")
                edge_lines = [IndexedLineSegments2(lines, mat)]
            else:
                lines = LineSegmentsGeometry(positions=edge_list)
                mat = LineMaterial(linewidth=edge_width,
                                   color=edge_color.web_color)
                edge_lines = [IndexedLineSegments2(lines, mat)]
            discretize_timer.stop()

        render_timer.stop()

        return shape_mesh, edge_lines, points
Example #12
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,
        transparent=False,
        opacity=1.0,
    ):

        edge_list = None
        edge_lines = None
        points = None
        shape_mesh = None

        start_render_time = self._start_timer()
        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

            # Compute the tesselation
            start_tesselation_time = self._start_timer()

            np_vertices, np_triangles, np_normals = tessellate(
                shape, self.quality, self.angular_tolerance
            )

            if np_normals.shape != np_vertices.shape:
                raise AssertionError("Wrong number of normals/shapes")

            self._stop_timer("tesselation time", start_tesselation_time)

            # build a BufferGeometry instance
            shape_geometry = BufferGeometry(
                attributes={
                    "position": BufferAttribute(np_vertices),
                    "index": BufferAttribute(np_triangles.ravel()),
                    "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:
                edges = get_edges(shape)

        if vertices is not None:
            vertices_list = []
            for vertex in vertices:
                vertices_list.append(get_point(vertex))
            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:
            start_discretize_time = self._start_timer()
            edge_list = [discretize_edge(edge, self.edge_accuracy) for edge in edges]
            self._stop_timer("discretize time", start_discretize_time)

        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)
        self._stop_timer("shape render time", start_render_time)