Example #1
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
def pseudomaterial_render(atoms):
    c = cm.get_cmap("plasma")

    scale_axis_vertices = [[-1, -1, -1], [9, -1, -1]]
    scale_line_geom = Geometry(vertices=scale_axis_vertices,
                               colors=['black'] * len(scale_axis_vertices))
    scale_lines = Line(
        geometry=scale_line_geom,
        material=LineBasicMaterial(linewidth=50, vertexColors='VertexColors'),
        type='LinePieces',
    )

    a = atoms.a[1]
    cube_vertices = [[0, 0, 0], [a, 0, 0], [a, 0, a], [a, 0, 0], [a, a, 0],
                     [a, a, a], [a, a, 0], [0, a, 0], [0, a, a], [0, a, 0],
                     [0, 0, 0], [0, 0, a], [a, 0, a], [a, a, a], [0, a, a],
                     [0, 0, a]]

    linesgeom = Geometry(vertices=cube_vertices,
                         colors=['black'] * len(cube_vertices))

    lines = Line(
        geometry=linesgeom,
        material=LineBasicMaterial(linewidth=5, vertexColors='VertexColors'),
        type='LinePieces',
    )

    balls = []
    for p in atoms.itertuples():
        positions = (p.x * p.a, p.y * p.a, p.z * p.a)
        new_ball = Mesh(
            geometry=SphereGeometry(radius=p.sigma,
                                    widthSegments=32,
                                    heightSegments=24),
            material=MeshLambertMaterial(color=rgb2hex(c(p.epsilon_norm))),
            position=positions)
        balls.append(new_ball)


#             [scale*2*a,scale*2*a,scale*2*a]
    camera = PerspectiveCamera(position=[25, a, a],
                               up=[0, 1, 0],
                               children=[
                                   DirectionalLight(color='white',
                                                    position=[3, 5, 1],
                                                    intensity=0.5)
                               ])

    scene = Scene(children=[
        scale_lines, lines, *balls, camera,
        AmbientLight(color='#777')
    ])

    renderer = Renderer(
        camera=camera,
        scene=scene,
        controls=[OrbitControls(controlling=camera, target=[a, a, a])])

    return renderer
Example #3
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
Example #4
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
Example #5
0
def get_line_geometries(geom: ThreeJSSceneGraphObjectType) -> LineSegments:
    """
    Return line segments that represent the edges of the given objects mesh.
    """
    line_geom = EdgesGeometry(geom.geometry)
    lines = LineSegments(geometry=line_geom,
                         material=LineBasicMaterial(linewidth=LINE_WIDTH,
                                                    color='#000000'))
    return lines
Example #6
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)
Example #7
0
 def __init__(self,
              num_cells=5,
              color='#cccccc',
              linewidth=1,
              cellsize=0.5):
     Group.__init__(self)
     material = LineBasicMaterial(color=color, linewidth=linewidth)
     for i in range(num_cells + 1):
         edge = cellsize * num_cells / 2
         position = edge - (i * cellsize)
         geometry_h = Geometry(vertices=[(-edge, position,
                                          0), (edge, position, 0)])
         geometry_v = Geometry(vertices=[(position, -edge,
                                          0), (position, edge, 0)])
         self.add(pythreejs.Line(geometry=geometry_h, material=material))
         self.add(pythreejs.Line(geometry=geometry_v, material=material))
Example #8
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)
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
Example #10
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)
Example #11
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)
Example #12
0
    def visualize(self):
        """Start the visualization and initialize widgets"""
        from pythreejs import PlainGeometry, Mesh, LambertMaterial, \
                PhongMaterial, DirectionalLight, \
                PerspectiveCamera, Scene, AmbientLight, \
                Renderer, OrbitControls, Line, \
                LineBasicMaterial, BoxGeometry, make_text
        from matplotlib import colors
        from matplotlib import cm
        from IPython.display import display
        import numpy as np
        import ipywidgets as widgets

        bbox = self._compute_bounding_box()
        diam = bbox[1, :] - bbox[0, :]
        center = .5 * _np.sum(bbox, axis=0)

        xmin, ymin, zmin = bbox[0, :]
        xmax, ymax, zmax = bbox[1, :]

        position = (center + 2.5 * diam).tolist()

        # Generate coordinate system base

        box = PlainGeometry(
            vertices=_np.array([[xmin, ymin, zmin], [xmax, ymin, zmin],
                                [xmin, ymin, zmin], [xmin, ymax, zmin],
                                [xmin, ymin, zmin], [xmin, ymin, zmax]]),
            colors=['red', 'red', 'green', 'green', 'blue', 'blue'])

        self._coord_box = Line(geometry=box,
                               material=LineBasicMaterial(
                                   linewidth=10, vertexColors='VertexColors'),
                               type='LinePieces')

        if self.data is not None:
            vis_data = self.data
            if not self.is_real:
                vis_data = _np.real(self.data)
            if not self.is_scalar:
                vis_data = _np.sum(_np.abs(self.data)**2, axis=2)
            self._vis_data = vis_data
            self._cmap = cm.jet
            self._vmin = vis_data.min()
            self._vmax = vis_data.max()
            cnorm = colors.Normalize(vmin=self._vmin, vmax=self._vmax)
            facecolors = self._convert_data_to_colors(self._cmap, cnorm,
                                                      vis_data)
        else:
            facecolors = self.elements.shape[0] * [
                3 * [_np.array([1., 1., 1.])]
            ]
        self._geom = PlainGeometry(vertices=self.vertices,
                                   faces=self.elements,
                                   faceColors=facecolors)

        self._mesh = Mesh(
            geometry=self._geom,
            material=LambertMaterial(vertexColors='VertexColors'))
        self._wireframe = Mesh(geometry=self._geom,
                               material=PhongMaterial(wireframe=True,
                                                      color='black'))
        light = DirectionalLight(color='white',
                                 position=position,
                                 intensity=0.5)
        camera = PerspectiveCamera(position=position, fov=20)
        self._scene = Scene(children=[
            self._coord_box, self._mesh, self._wireframe,
            AmbientLight(color='white')
        ])

        self._renderer = Renderer(camera=camera,
                                  background='white',
                                  background_opacity=1,
                                  scene=self._scene,
                                  controls=[OrbitControls(controlling=camera)])

        self._axes_info = widgets.Label(value="x: red; y: green; z: blue")

        coord_system_toggle = widgets.Checkbox(
            value=self._coord_box.visible,
            description='Show coordinate axes',
            disabled=False)
        coord_system_toggle.observe(self.on_toggle_coord_system, names='value')

        if self.data is not None:

            # Enable/Disable wireframe
            wireframe_toggle = widgets.Checkbox(value=self._wireframe.visible,
                                                description='Enable wireframe',
                                                disabled=False)
            wireframe_toggle.observe(self.on_toggle_wireframe, names='value')

            # Change vmin/vmax
            vmin_box = widgets.FloatText(value=self._vmin,
                                         description='vmin:',
                                         disabled=False)
            vmin_box.observe(self.on_change_vmin, names='value')

            vmax_box = widgets.FloatText(value=self._vmax,
                                         description='vmax:',
                                         disabled=False)
            vmax_box.observe(self.on_change_vmax, names='value')

            vmin_info = widgets.Label(
                value='Lower bound: {0}'.format(self._vmin))
            vmax_info = widgets.Label(
                value='Upper bound: {0}'.format(self._vmax))

            range_info_box = widgets.VBox([vmin_info, vmax_info])
            range_change = widgets.HBox([vmin_box, vmax_box])
            toggles = widgets.HBox([wireframe_toggle, coord_system_toggle])
            vbox = widgets.VBox(
                [self._axes_info, range_info_box, range_change, toggles])
            display(self._renderer, vbox)
        else:
            display(self._renderer, self._axes_info, coord_system_toggle)
Example #13
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)
        ]