Beispiel #1
0
def create_face_geom(
        coord_vals: SoCoordValsListType,
        face_indices: SoIndicesListType,
        face_color: SoVectorType,
        transparency: float,
        translation: SoVectorType = None,
        quaternion: SoQuaternionType = None
) -> ThreeJSSceneGraphObjectListType:
    """
    Returns a pythreejs `Mesh` object that consists of the faces given by
    face_indices and the coord_vals.
    
    Additionally the attributes `Mesh.default_material` and `Mesh.geometry.default_color`
    will be set before returning the Mesh. Those attributes contain references to the
    default colors and materials that are set in this function to restore later changes.
    """
    vertices = np.asarray(coord_vals, dtype='float32')
    faces = np.asarray(face_indices, dtype='uint16')

    normals = compute_normals(faces, vertices)

    faces = faces.ravel()
    vertexcolors = np.asarray([face_color] * len(coord_vals), dtype='float32')

    face_geometry = BufferGeometry(
        attributes=dict(position=BufferAttribute(vertices, normalized=False),
                        index=BufferAttribute(faces, normalized=False),
                        normal=BufferAttribute(normals, normalized=False),
                        color=BufferAttribute(vertexcolors, normalized=False)))
    # this is used for returning to original state after highlighting
    face_geometry.default_color = vertexcolors

    # BUG: This is a bug in pythreejs and currently does not work
    #faceGeometry.exec_three_obj_method('computeFaceNormals')
    #faceGeometry.exec_three_obj_method('computeVertexNormals')
    col = so_col_to_hex(face_color)
    material = MeshPhongMaterial(color=col,
                                 transparency=transparency,
                                 depthTest=True,
                                 depthWrite=True,
                                 metalness=0)
    object_mesh = Mesh(
        geometry=face_geometry,
        material=material,
        position=[0, 0, 0]  # Center the cube
    )
    object_mesh.default_material = material

    if quaternion:
        object_mesh.quaternion = quaternion
    if translation:
        object_mesh.position = translation
    return [object_mesh]
Beispiel #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
Beispiel #3
0
    def AddVerticesToScene(self, pnt_list, vertex_color, vertex_width=5):
        """ shp is a list of gp_Pnt
        """
        vertices_list = []  # will be passed to pythreejs
        BB = BRep_Builder()
        compound = TopoDS_Compound()
        BB.MakeCompound(compound)

        for vertex in pnt_list:
            vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape()
            BB.Add(compound, vertex_to_add)
            vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()])

        # map the Points and the AIS_PointCloud
        # and to the dict of shapes, to have a mapping between meshes and shapes
        point_cloud_id = "%s" % uuid.uuid4().hex
        self._shapes[point_cloud_id] = compound

        vertices_list = np.array(vertices_list, dtype=np.float32)
        attributes = {
            "position": BufferAttribute(vertices_list, normalized=False)
        }
        mat = PointsMaterial(color=vertex_color,
                             sizeAttenuation=True,
                             size=vertex_width)
        geom = BufferGeometry(attributes=attributes)
        points = Points(geometry=geom, material=mat, name=point_cloud_id)
        return points
Beispiel #4
0
def edges_to_mesh(name,
                  np_edge_vertices,
                  np_edge_indices,
                  edge_color,
                  linewidth=1):
    """

    :param name:
    :param np_edge_vertices:
    :param np_edge_indices:
    :param edge_color:
    :param linewidth:
    :return:
    :rtype: pythreejs.objects.LineSegments_autogen.LineSegments
    """
    edge_geometry = BufferGeometry(
        attributes={
            "position": BufferAttribute(np_edge_vertices),
            "index": BufferAttribute(np_edge_indices),
        })
    edge_material = LineBasicMaterial(color=format_color(*edge_color),
                                      linewidth=linewidth)

    edge_geom = LineSegments(
        geometry=edge_geometry,
        material=edge_material,
        type="LinePieces",
        name=name,
    )

    return edge_geom
Beispiel #5
0
def faces_to_mesh(name, vertices, faces, colors, opacity=None):
    """

    :param name:
    :param vertices:
    :param faces:
    :param colors:
    :param opacity:
    :return:
    """
    geometry = BufferGeometry(attributes=dict(
        position=BufferAttribute(vertices, normalized=False),
        index=BufferAttribute(faces, normalized=False),
        color=BufferAttribute(colors),
    ))

    mat_atts = dict(vertexColors="VertexColors", side="DoubleSide")
    if opacity is not None:
        mat_atts["opacity"] = opacity
        mat_atts["transparent"] = True

    material = MeshBasicMaterial(**mat_atts)
    mesh = Mesh(
        name=name,
        geometry=geometry,
        material=material,
    )
    return mesh
Beispiel #6
0
 def __init__(self, points, point_size=0.001, color='green'):
     geometry = BufferGeometry(
         attributes={
             'position': BufferAttribute(array=points.astype(np.float32))
         })
     material = PointsMaterial(size=point_size, color=color)
     Points.__init__(self, geometry=geometry, material=material)
Beispiel #7
0
    def tessellate(self,
                   compound,
                   quality=0.1,
                   angular_tolerance=0.1,
                   debug=False):

        hash = id(
            compound
        )  # use python id instead of compound.HashCode(HASH_CODE_MAX)
        if self.objects.get(hash) is None:
            np_vertices, np_triangles, np_normals = tessellate(
                compound, quality, angular_tolerance)

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

            shape_geometry = BufferGeometry(
                attributes={
                    "position": BufferAttribute(np_vertices),
                    "index": BufferAttribute(np_triangles.ravel()),
                    "normal": BufferAttribute(np_normals),
                })
            if debug:
                print(f"| | | (Caching {hash})")
            self.objects[hash] = shape_geometry
        else:
            if debug:
                print(f"| | | (Taking {hash} from cache)")
        return self.objects[hash]
Beispiel #8
0
    def AddCurveToScene(self, shp, edge_color, deflection):
        """ shp is either a TopoDS_Wire or a TopodS_Edge.
        """
        if is_edge(shp):
            pnts = discretize_edge(shp, deflection)
        elif is_wire(shp):
            pnts = discretize_wire(shp, deflection)
        np_edge_vertices = np.array(pnts, dtype=np.float32)
        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)

        # and to the dict of shapes, to have a mapping between meshes and shapes
        edge_id = "%s" % uuid.uuid4().hex
        self._shapes[edge_id] = shp

        edge_line = Line(geometry=edge_geometry,
                         material=edge_material,
                         name=edge_id)

        # and to the dict of shapes, to have a mapping between meshes and shapes
        edge_id = "%s" % uuid.uuid4().hex
        self._shapes[edge_id] = shp

        return edge_line
Beispiel #9
0
def create_line_geom(
        coord_vals: SoCoordValsListType,
        indices: SoIndicesListType,
        line_color: SoVectorType,
        translation: SoVectorType = None,
        quaternion: SoQuaternionType = None
) -> ThreeJSSceneGraphObjectListType:
    """
    Return a pythreejs Line object consisting of lines
    defined by the line_indices and the coord_vals.
    
    Additionally the attributes `Line.default_color` and `Line.edge_index`
    will be set before returning the `Line` array. Those attributes contain references to the
    default colors, that are set in this function to restore later changes, and the FreeCAD edge index.
    """
    lines = []
    for i, line_indices in enumerate(indices):
        vertices = generate_line_vertices(line_indices, coord_vals)
        vertices = np.array(vertices, dtype="float32")
        line_geom = BufferGeometry(attributes=dict(
            position=BufferAttribute(vertices, normalized=False)))
        # BUG: This is a bug in pythreejs and currently does not work
        #linesgeom.exec_three_obj_method('computeVertexNormals')
        col = so_col_to_hex(line_color)
        material = LineBasicMaterial(linewidth=LINE_WIDTH, color=col)
        material.default_color = col
        line = Line(geometry=line_geom, material=material)
        line.edge_index = i + 1  # using FreeCAD's 1-based indexing
        if translation:
            line.position = translation
        if quaternion:
            line.quaternion = quaternion
        lines.append(line)
    return lines
Beispiel #10
0
 def __init__(self, start, end, color='white', linewidth=1):
     geometry = BufferGeometry(
         attributes={
             'position':
             BufferAttribute(np.vstack((start, end)).astype(np.float32),
                             normalized=False)
         })
     material = LineBasicMaterial(color=color, linewidth=linewidth)
     pythreejs.Line.__init__(self, geometry=geometry, material=material)
Beispiel #11
0
 def __init__(self, p1, p2, p3, color='yellow'):
     geometry = BufferGeometry(
         attributes={
             'position':
             BufferAttribute(np.vstack((
                 p1, p2, p3)).reshape(3, 3).astype(np.float32),
                             normalized=False)
         })
     material = MeshBasicMaterial(color=color)
     material.side = 'DoubleSide'
     Mesh.__init__(self, geometry=geometry, material=material)
Beispiel #12
0
 def _load_mesh(self, dae, scale):
     materials = self._load_material(dae)
     for geometry in dae.geometries:
         for primitive in geometry.primitives:
             vertices = primitive.vertex[primitive.vertex_index] * scale
             normals = primitive.normal[primitive.normal_index]
             buffer_geometry = BufferGeometry(
                 attributes={
                     'position': BufferAttribute(array=vertices),
                     'normal': BufferAttribute(array=normals)
                 })
             material = materials[primitive.material]
             mesh = Mesh(geometry=buffer_geometry, material=material)
             self.add(mesh)
Beispiel #13
0
    def AddCurveToScene(self, shp, color):
        """ shp is either a TopoDS_Wire or a TopodS_Edge.
        """
        if is_edge(shp):
            pnts = discretize_edge(shp)
        elif is_wire(shp):
            pnts = discretize_wire(shp)
        np_edge_vertices = np.array(pnts, dtype=np.float32)
        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=color, linewidth=1)
        edge_lines = Line(geometry=edge_geometry, material=edge_material)

        # Add geometries to pickable or non pickable objects
        self._displayed_pickable_objects.add(edge_lines)
Beispiel #14
0
def vertices_to_mesh(name, vertices, vertex_color, vertex_width=5):
    """

    :param name:
    :param vertices:
    :param vertex_color: RGB tuple (r, g, b)
    :param vertex_width:
    :return:
    :rtype: pythreejs.objects.Points_autogen.Points
    """
    vertices = np.array(vertices, dtype=np.float32)
    attributes = {"position": BufferAttribute(vertices, normalized=False)}
    mat = PointsMaterial(color=format_color(*vertex_color),
                         sizeAttenuation=False,
                         size=vertex_width)
    geom = BufferGeometry(attributes=attributes)
    points = Points(geometry=geom, material=mat, name=name)
    return points
def _get_surface_from_positions(positions, d_args, draw_edges=False):
    # get defaults
    obj_args = update_object_args(d_args, "Surfaces", ["color", "opacity"])
    num_triangle = len(positions) / 3.0
    assert num_triangle.is_integer()
    # make decision on transparency
    if obj_args["opacity"] > 0.99:
        transparent = False
    else:
        transparent = True

    num_triangle = int(num_triangle)
    index_list = [[itr * 3, itr * 3 + 1, itr * 3 + 2]
                  for itr in range(num_triangle)]
    # Vertex ositions as a list of lists
    surf_vertices = BufferAttribute(array=positions, normalized=False)
    # Indices
    surf_indices = BufferAttribute(array=np.array(index_list,
                                                  dtype=np.uint16).ravel(),
                                   normalized=False)
    geometry = BufferGeometry(attributes={
        "position": surf_vertices,
        "index": surf_indices
    })
    new_surface = Mesh(
        geometry=geometry,
        material=MeshLambertMaterial(
            color=obj_args["color"],
            side="DoubleSide",
            transparent=transparent,
            opacity=obj_args["opacity"],
        ),
    )
    if draw_edges == True:
        edges = EdgesGeometry(geometry)
        edges_lines = LineSegments(edges,
                                   LineBasicMaterial(color=obj_args["color"]))
        return new_surface, edges_lines
    else:
        return new_surface, None
Beispiel #16
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)
Beispiel #17
0
    def __init__(self,
        mesh: trimesh.Trimesh = None,
        obj: str = None,
        normalize: bool =False,
        color: Union[str,ColorRGB] ="#00bbee",
        alpha: float=1.,
        transform: Union[Callable, None] = None,
        *args,
        **kwargs
        ):
        """
        Add a mesh to the scene.

        Arguments:
            mesh: Mesh object, with attributes verticies, faces
            obj: object filename
            normalize : Normalize the coordinates of the vertices
                to be between -1 and 1
            color: Color for the mesh
            alpha: transparency of the mesh
            transform: a function to transform the vertices

        """
        if mesh is not None and obj is not None:
            raise ValueError('Received both mesh and obj')
        if isinstance(mesh, str):
            # perhaps this is a filename?
            try:
                mesh = trimesh.load(args[0])
            except Exception as e:
                raise ValueError(
                    "Did not understand arguments to method Figure#mesh"
                ) from e
        if isinstance(obj, np.ndarray):
            obj_data = obj
        elif isinstance(obj, list):
            obj_data = np.asarray(obj)
            # Do something with this obj_data?
        elif isinstance(obj, str):
            if "\n" in obj:
                # this is the file contents.
                raise NotImplementedError()
            else:
                try:
                    # open the mesh file
                    mesh = trimesh.load(obj)

                except Exception as e:
                    raise ValueError("Could not read file as OBJ") from e
        assert hasattr(mesh, "vertices") and hasattr(mesh, "faces"), "Invalid mesh object"
        if mesh is None:
            raise ValueError("Could not understand how to parse mesh.")

        if transform is None:
            transform = lambda x: x

        verts = transform(mesh.vertices)
        faces = mesh.faces

        if normalize:
            # Normalize the vertex indices to be between -1,1
            # Shifting these does change the coordinate system,
            # so visualizing multiple meshes won't work
            verts[:, 0] = _normalize_shift(verts[:, 0])
            verts[:, 1] = _normalize_shift(verts[:, 1])
            verts[:, 2] = _normalize_shift(verts[:, 2])

        geo = BufferGeometry(
            attributes={
                "position": BufferAttribute(
                    array=verts.astype("float32"),
                    normalized=False,
                    # dtype=np.float64
                ),
                "index": BufferAttribute(
                    array=faces.astype("uint64").ravel(),
                    normalized=False,
                    # dtype=np.float64,
                ),
            }
        )
        self._coords = verts
        transparent = alpha != 1.
        mat = MeshLambertMaterial(color=color, opacity=alpha, transparent=transparent)
        mesh = Mesh(geometry=geo, material=mat)
        geo.exec_three_obj_method("computeVertexNormals")
        super().__init__(*args, **kwargs)
        self._objects.append(mesh)
Beispiel #18
0
    def DisplayMesh(self,
                    part,
                    edge_color=None,
                    vertex_color=None,
                    vertex_width=2):
        """

        :param part:
        :param edge_color:
        :param vertex_color:
        :param vertex_width:
        :type part: ada.Part
        """
        from itertools import chain
        from random import randint

        from OCC.Core.BRep import BRep_Builder
        from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeVertex
        from OCC.Core.gp import gp_Pnt
        from OCC.Core.TopoDS import TopoDS_Compound

        # edge_color = format_color(*part.colour) if edge_color is None else edge_color

        edge_color = (format_color(randint(0, 255), randint(
            0, 255), randint(0, 255)) if edge_color is None else edge_color)
        vertex_color = self._default_vertex_color if vertex_color is None else vertex_color

        pmesh_id = "%s" % uuid.uuid4().hex

        BB = BRep_Builder()
        compound = TopoDS_Compound()
        BB.MakeCompound(compound)
        vertices_list = []

        def togp(n_):
            return gp_Pnt(float(n_[0]), float(n_[1]), float(n_[2]))

        for vertex in map(togp, part.fem.nodes):
            vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape()
            BB.Add(compound, vertex_to_add)
            vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()])

        attributes = {
            "position": BufferAttribute(vertices_list, normalized=False)
        }
        mat = PointsMaterial(color=vertex_color,
                             sizeAttenuation=False,
                             size=vertex_width)
        geom = BufferGeometry(attributes=attributes)
        points_geom = Points(geometry=geom, material=mat, name=pmesh_id)

        def grab_nodes(el):
            """

            :param el:
            :type el: ada.fem.Elem
            :return:
            """
            if el.edges_seq is None:
                return None
            return [
                part.fem.nodes.from_id(i).p for i in
                [el.nodes[e].id for ed_seq in el.edges_seq for e in ed_seq]
            ]

        lmesh_id = "%s" % uuid.uuid4().hex

        edges_nodes = list(
            chain.from_iterable(
                filter(None, map(grab_nodes, part.fem.elements))))
        np_edge_vertices = np.array(edges_nodes, dtype=np.float32)
        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_geom = LineSegments(
            geometry=edge_geometry,
            material=edge_material,
            type="LinePieces",
            name=lmesh_id,
        )
        output = [points_geom, edge_geom]

        for elem in output:
            self._shapes[elem.name] = compound
            self._refs[elem.name] = part
            self._displayed_pickable_objects.add(elem)

        self._fem_sets_opts.options = ["None"] + [
            s.name for s in filter(
                lambda x: "internal" not in x.metadata.keys(), part.fem.sets)
        ]
Beispiel #19
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
    def DisplayMesh(self,
                    mesh,
                    color=default_mesh_color):
        """ Display a MEFISTO2 triangle mesh
        """
        if not HAVE_SMESH:
            print("SMESH not installed, DisplayMesh method unavailable.")
            return
        if not isinstance(mesh, SMESH_Mesh):
            raise AssertionError("You mush provide an SMESH_Mesh instance")
        mesh_ds = mesh.GetMeshDS()  # the mesh data source
        face_iter = mesh_ds.facesIterator()
        # vertices positions are stored to a liste
        vertices_position = []
        for _ in range(mesh_ds.NbFaces()-1):
            face = face_iter.next()
            #print('Face %i, type %i' % (i, face.GetType()))
            #print(dir(face))
            # if face.GetType == 3 : triangle mesh, then 3 nodes
            for j in range(3):
                node = face.GetNode(j)
                #print('Coordinates of node %i:(%f,%f,%f)'%(i, node.X(), node.Y(), node.Z()))
                vertices_position.append(node.X())
                vertices_position.append(node.Y())
                vertices_position.append(node.Z())
        number_of_vertices = len(vertices_position)
        # 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)}
        # build a BufferGeometry instance
        mesh_geometry = BufferGeometry(attributes=buffer_geometry_properties)

        mesh_geometry.exec_three_obj_method('computeVertexNormals')

        # then a default material
        mesh_material = MeshPhongMaterial(color=color,
                                          polygonOffset=True,
                                          polygonOffsetFactor=1,
                                          polygonOffsetUnits=1,
                                          shininess=0.5,
                                          wireframe=False,
                                          side='DoubleSide')
        edges_material = MeshPhongMaterial(color='black',
                                           polygonOffset=True,
                                           polygonOffsetFactor=1,
                                           polygonOffsetUnits=1,
                                           shininess=0.5,
                                           wireframe=True)
        # create a mesh unique id
        mesh_id = uuid.uuid4().hex

        # finally create the mash
        shape_mesh = Mesh(geometry=mesh_geometry,
                          material=mesh_material,
                          name=mesh_id)
        edges_mesh = Mesh(geometry=mesh_geometry,
                          material=edges_material,
                          name=mesh_id)


        # a special display for the mesh
        camera_target = [0., 0., 0.]  # the point to look at
        camera_position = [0, 0., 100.]  # the camera initial position
        camera = PerspectiveCamera(position=camera_position,
                                   lookAt=camera_target,
                                   up=[0, 0, 1],
                                   fov=50,
                                   children=[DirectionalLight(color='#ffffff',
                                                              position=[50, 50, 50],
                                                              intensity=0.9)])
        scene_shp = Scene(children=[shape_mesh, edges_mesh, camera, AmbientLight(color='#101010')])

        renderer = Renderer(camera=camera,
                            background=self._background,
                            background_opacity=self._background_opacity,
                            scene=scene_shp,
                            controls=[OrbitControls(controlling=camera, target=camera_target)],
                            width=self._size[0],
                            height=self._size[1],
                            antialias=True)

        display(renderer)
Beispiel #21
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
Beispiel #22
0
    def DisplayMesh(self,
                    part: "Part",
                    edge_color=None,
                    vertex_color=None,
                    vertex_width=2):
        from OCC.Core.BRep import BRep_Builder
        from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeVertex
        from OCC.Core.gp import gp_Pnt
        from OCC.Core.TopoDS import TopoDS_Compound

        # edge_color = format_color(*part.colour) if edge_color is None else edge_color
        rgb = randint(0, 255), randint(0, 255), randint(0, 255)
        edge_color = format_color(*rgb) if edge_color is None else edge_color
        vertex_color = self._default_vertex_color if vertex_color is None else vertex_color

        pmesh_id = "%s" % uuid.uuid4().hex

        BB = BRep_Builder()
        compound = TopoDS_Compound()
        BB.MakeCompound(compound)
        vertices_list = []

        def togp(n_):
            return gp_Pnt(float(n_[0]), float(n_[1]), float(n_[2]))

        for vertex in map(togp, part.fem.nodes):
            vertex_to_add = BRepBuilderAPI_MakeVertex(vertex).Shape()
            BB.Add(compound, vertex_to_add)
            vertices_list.append([vertex.X(), vertex.Y(), vertex.Z()])

        attributes = {
            "position": BufferAttribute(vertices_list, normalized=False)
        }
        mat = PointsMaterial(color=vertex_color,
                             sizeAttenuation=False,
                             size=vertex_width)
        geom = BufferGeometry(attributes=attributes)
        points_geom = Points(geometry=geom, material=mat, name=pmesh_id)
        lmesh_id = "%s" % uuid.uuid4().hex
        edges_nodes = list(
            chain.from_iterable(
                filter(
                    None,
                    [get_vertices_from_elem(el) for el in part.fem.elements])))
        np_edge_vertices = np.array(edges_nodes, dtype=np.float32)
        np_edge_indices = np.arange(np_edge_vertices.shape[0], dtype=np.uint32)
        vertex_col = tuple([x / 255 for x in rgb])
        edge_geometry = BufferGeometry(
            attributes={
                "position": BufferAttribute(np_edge_vertices),
                "index": BufferAttribute(np_edge_indices),
                "color": BufferAttribute(
                    [vertex_col for n in np_edge_vertices]),
            })
        edge_material = LineBasicMaterial(vertexColors="VertexColors",
                                          linewidth=5)

        edge_geom = LineSegments(
            geometry=edge_geometry,
            material=edge_material,
            type="LinePieces",
            name=lmesh_id,
        )
        output = [points_geom, edge_geom]

        for elem in output:
            self._shapes[elem.name] = compound
            self._refs[elem.name] = part
            self._displayed_pickable_objects.add(elem)

        self._fem_sets_opts.options = ["None"] + [
            f"{part.fem.name}.{s.name}" for s in filter(
                lambda x: "internal" not in x.metadata.keys(), part.fem.sets)
        ]
        self._fem_refs[part.fem.name] = (part.fem, edge_geometry)
    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
        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)
        # 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 #24
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
Beispiel #25
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 #26
0
    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
        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)
        # 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 #27
0
    def __init__(self,*args, **kwargs):
        """
        There are several options for arguments this this function.

        One positional array-like
            Figure#scatter(np.random.randint(0, 10, (10, 3)))

        Three positional list-likes
            Figure#scatter(xs, ys, zs)

        Three named list-likes
            Figure#scatter(xs=[1, 2], ys=[2, 3], zs=[10, 20])

        Three positional column names and a dataframe
            Figure#scatter("x", "y", "depth", my_dataframe)

        Arguments:
            attenuate_size (False): Whether items further from
                the camera should appear smaller

        """
        super().__init__(**kwargs)
        pts = None
        if len(args) == 1:
            if isinstance(args[0], (np.ndarray, Iterable)):
                pts = np.asarray(args[0], dtype=np.float32)

        if len(args) == 3 and isinstance(args[0], (list, np.ndarray)):
            pts = np.asarray([i for i in zip(args[0], args[1], args[2])],dtype=np.float32)

        if pts is None:
            raise ValueError("Unsupported arguments to scatter.")
        self._coords = pts
        color = kwargs.get("c") if "c" in kwargs else None
        if color is None:
            color = kwargs.get("color", None)
        if color is None:
            color = pts / pts.max()
        if len(color) != len(pts):
            color = [color for _ in pts]

        colors = (
            BufferAttribute(array=color, dtype=np.float32)
            if color is not None
            else BufferAttribute(array=np.asarray(pts / pts.max(), dtype=np.float32))
        )
        geometry = BufferGeometry(
            attributes={
                "position": BufferAttribute(array=np.asarray(pts, dtype=np.float32)),
                "color": colors,
            }
        )

        tex = CIRCLE_MAP
        if kwargs.get("marker") in [".", "o", "circle"]:
            tex = CIRCLE_MAP
        elif kwargs.get("marker") in ["[]", "r", "q", "square"]:
            tex = None
        elif "map" in kwargs:
            tex = kwargs.get("map")

        material = PointsMaterial(
            vertexColors="VertexColors",
            size=kwargs.get("size", 5),
            sizeAttenuation=kwargs.get("attenuate_size", False),
            **({"map": tex} if tex else {}),
        )
        p = Points(geometry=geometry, material=material)
        self._objects.append(p)
Beispiel #28
0
    def DisplayMesh(self,
                    mesh,
                    color=default_mesh_color):
        """ Display a MEFISTO2 triangle mesh
        """
        if not HAVE_SMESH:
            print("SMESH not installed, DisplayMesh method unavailable.")
            return
        if not isinstance(mesh, SMESH_Mesh):
            raise AssertionError("You mush provide an SMESH_Mesh instance")
        mesh_ds = mesh.GetMeshDS()  # the mesh data source
        face_iter = mesh_ds.facesIterator()
        # vertices positions are stored to a liste
        vertices_position = []
        for _ in range(mesh_ds.NbFaces()-1):
            face = face_iter.next()
            #print('Face %i, type %i' % (i, face.GetType()))
            #print(dir(face))
            # if face.GetType == 3 : triangle mesh, then 3 nodes
            for j in range(3):
                node = face.GetNode(j)
                #print('Coordinates of node %i:(%f,%f,%f)'%(i, node.X(), node.Y(), node.Z()))
                vertices_position.append(node.X())
                vertices_position.append(node.Y())
                vertices_position.append(node.Z())
        number_of_vertices = len(vertices_position)
        # 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)}
        # build a BufferGeometry instance
        mesh_geometry = BufferGeometry(attributes=buffer_geometry_properties)

        mesh_geometry.exec_three_obj_method('computeVertexNormals')

        # then a default material
        mesh_material = MeshPhongMaterial(color=color,
                                          polygonOffset=True,
                                          polygonOffsetFactor=1,
                                          polygonOffsetUnits=1,
                                          shininess=0.5,
                                          wireframe=False,
                                          side='DoubleSide')
        edges_material = MeshPhongMaterial(color='black',
                                           polygonOffset=True,
                                           polygonOffsetFactor=1,
                                           polygonOffsetUnits=1,
                                           shininess=0.5,
                                           wireframe=True)
        # create a mesh unique id
        mesh_id = uuid.uuid4().hex

        # finally create the mash
        shape_mesh = Mesh(geometry=mesh_geometry,
                          material=mesh_material,
                          name=mesh_id)
        edges_mesh = Mesh(geometry=mesh_geometry,
                          material=edges_material,
                          name=mesh_id)


        # a special display for the mesh
        camera_target = [0., 0., 0.]  # the point to look at
        camera_position = [0, 0., 100.]  # the camera initial position
        camera = PerspectiveCamera(position=camera_position,
                                   lookAt=camera_target,
                                   up=[0, 0, 1],
                                   fov=50,
                                   children=[DirectionalLight(color='#ffffff',
                                                              position=[50, 50, 50],
                                                              intensity=0.9)])
        scene_shp = Scene(children=[shape_mesh, edges_mesh, camera, AmbientLight(color='#101010')])

        renderer = Renderer(camera=camera,
                            background=self._background,
                            background_opacity=self._background_opacity,
                            scene=scene_shp,
                            controls=[OrbitControls(controlling=camera, target=camera_target)],
                            width=self._size[0],
                            height=self._size[1],
                            antialias=True)

        display(renderer)