Ejemplo n.º 1
0
 def _grid_views_default(self):
     # This needs to generate the geometries and access the materials
     grid_views = []
     cmap = mcm.get_cmap("inferno")
     for level in range(self.ds.max_level + 1):
         # We truncate at half of the colormap so that we just get a slight
         # linear progression
         color = mcolors.to_hex(
             cmap(self.cmap_truncate * level / self.ds.max_level))
         # Corners is shaped like 8, 3, NGrids
         this_level = self.ds.index.grid_levels[:, 0] == level
         corners = np.rollaxis(self.ds.index.grid_corners[:, :, this_level],
                               2).astype("float32")
         indices = (((np.arange(corners.shape[0]) * 8)[:, None] +
                     _CORNER_INDICES[None, :]).ravel().astype("uint32"))
         corners.shape = (corners.size // 3, 3)
         geometry = pythreejs.BufferGeometry(attributes=dict(
             position=pythreejs.BufferAttribute(array=corners,
                                                normalized=False),
             index=pythreejs.BufferAttribute(array=indices,
                                             normalized=False),
         ))
         material = pythreejs.LineBasicMaterial(color=color,
                                                linewidth=1,
                                                linecap="round",
                                                linejoin="round")
         segments = pythreejs.LineSegments(geometry=geometry,
                                           material=material)
         grid_views.append(segments)
     return grid_views
Ejemplo n.º 2
0
    def mesh(self, colors={}):
        import pythreejs as js
        import numpy as np

        lines = []
        line_colors = []

        red = [1, 0, 0]
        green = [0, 1, 0]
        exterior = self.project(exterior=True)
        interior = self.project(exterior=False)
        for color, polygons in zip([green, red], [exterior, interior]):
            for polygon in polygons:
                for segment in polygon.segments():
                    lines.extend([segment.p1, segment.p2])
                    line_colors.extend([color, color])

        lines = np.array(lines, dtype=np.float32)
        line_colors = np.array(line_colors, dtype=np.float32)
        geometry = js.BufferGeometry(attributes={
            'position':
            js.BufferAttribute(lines, normalized=False),
            'color':
            js.BufferAttribute(line_colors, normalized=False),
        }, )
        material = js.LineBasicMaterial(vertexColors='VertexColors',
                                        linewidth=1)
        return js.LineSegments(geometry, material)
Ejemplo n.º 3
0
    def __add_line_geometry(self, lines, shading, obj=None):
        lines = lines.astype("float32", copy=False)
        mi = np.min(lines, axis=0)
        ma = np.max(lines, axis=0)
        geometry = p3s.BufferGeometry(
            attributes={
                'position': p3s.BufferAttribute(lines, normalized=False)
            })
        material = p3s.LineBasicMaterial(linewidth=shading["line_width"],
                                         color=shading["line_color"])
        #, vertexColors='VertexColors'),
        lines = p3s.LineSegments(geometry=geometry,
                                 material=material)  #type='LinePieces')
        line_obj = {
            "geometry": geometry,
            "mesh": lines,
            "material": material,
            "max": ma,
            "min": mi,
            "type": "Lines",
            "wireframe": None
        }

        if obj:
            return self.__add_object(line_obj, obj), line_obj
        else:
            return self.__add_object(line_obj)
Ejemplo n.º 4
0
def build_geometry(triangles, positions, normals=None, colors=None):
    attributes = {
        "position": three.BufferAttribute(
            np.array(positions, dtype="float32").reshape(-1, 3),
            normalized=False,
        ),
        "index": three.BufferAttribute(
            np.array(triangles, dtype="uint32"),
            normalized=False,
        ),
    }
    if normals:
        attributes["normal"] = three.BufferAttribute(
            np.array(normals, dtype="float32").reshape(-1, 3),
            normalized=False,
        )
    if colors:
        attributes["color"] = three.BufferAttribute(
            np.array(colors, dtype="uint8").reshape(-1, 4),
            normalized=False,
        )
    geometry = three.BufferGeometry(attributes=attributes)

    # Compute normals from face geometry if they were not specified.
    if not normals:
        geometry.exec_three_obj_method("computeVertexNormals")

    return geometry
Ejemplo n.º 5
0
    def _make_threejs_primitive(self):
        geometry = pythreejs.BufferGeometry()
        material = pythreejs.MeshStandardMaterial(
            vertexColors=pythreejs.enums.Colors.VertexColors, metalness=0.05, roughness=.9)
        result = pythreejs.Mesh(geometry, material)

        return result
Ejemplo n.º 6
0
        def traverse_func(node, trans):
            # Underlying mesh
            mesh = node.primitive.mesh
            if mesh is None:
                return

            # Iterate through all triangles
            vs = []

            def process_triangle(face_index, tri):
                vs.append(list(tri.p1.p))
                vs.append(list(tri.p2.p))
                vs.append(list(tri.p3.p))

            mesh.foreach_triangle(process_triangle)

            # Create geometry
            ps_attr = three.BufferAttribute(array=vs, normalized=False)
            geom = three.BufferGeometry(attributes={'position': ps_attr})

            # Create mesh
            mesh = three.Mesh(geometry=geom, material=mat_default)
            mesh.matrixAutoUpdate = False
            mesh.matrix = trans.T.flatten().tolist()
            scene.add(mesh)
Ejemplo n.º 7
0
 def __get_points_from_pointcloud(self): 
     vertices = self.geometry.vertices.astype(np.float32)
     buffer = np.empty((int(vertices.shape[0] * 3), 3), dtype=np.float32).reshape(-1, 3)
     buffer[:vertices.shape[0]] = vertices
     vertex_buffer = self.__as_buffer_attr(buffer)
     points = three.BufferGeometry(attributes={'position': vertex_buffer})
     points.exec_three_obj_method("setDrawRange", 0, vertices.shape[0])
     return points
Ejemplo n.º 8
0
def scatter_children(points, color="red", size=4):
    scene_children = []
    geometry_point = p3js.BufferGeometry(
        attributes={"position": p3js.BufferAttribute(array=points)})
    material_point = p3js.PointsMaterial(color=color, size=size)
    pts = p3js.Points(geometry_point, material_point)
    scene_children.append(pts)
    return scene_children
Ejemplo n.º 9
0
def get_pointcloud_pythreejs(xyz, colors):
    points_geometry = pythreejs.BufferGeometry(attributes=dict(
        position=pythreejs.BufferAttribute(xyz, normalized=False),
        color=pythreejs.BufferAttribute(list(map(tuple, colors)))))

    points_material = pythreejs.PointsMaterial(vertexColors='VertexColors')

    return pythreejs.Points(geometry=points_geometry, material=points_material)
Ejemplo n.º 10
0
 def __get_wireframe_from_boundary(self):
     edges = self.geometry.vertices[self.geometry.as_edges_flat()].astype(
         np.float32)
     buffer = np.empty((int(edges.shape[0] * 3), 3),
                       dtype=np.float32).reshape(-1, 3)
     buffer[:edges.shape[0]] = edges
     vertices = self.__as_buffer_attr(buffer)
     wireframe = three.BufferGeometry(attributes={'position': vertices})
     wireframe.exec_three_obj_method("setDrawRange", 0, edges.shape[0])
     return wireframe
Ejemplo n.º 11
0
    def add_points(self, points, c=None, shading={}, obj=None, **kwargs):
        shading.update(kwargs)
        if len(points.shape) == 1:
            if len(points) == 2:
                points = np.array([[points[0], points[1], 0]])
        else:
            if points.shape[1] == 2:
                points = np.append(points, np.zeros([points.shape[0], 1]), 1)
        sh = self.__get_shading(shading)
        points = points.astype("float32", copy=False)
        mi = np.min(points, axis=0)
        ma = np.max(points, axis=0)

        g_attributes = {
            "position": p3s.BufferAttribute(points, normalized=False)
        }
        m_attributes = {"size": sh["point_size"]}

        if sh["point_shape"] == "circle":  # Plot circles
            tex = p3s.DataTexture(data=gen_circle(16, 16),
                                  format="RGBAFormat",
                                  type="FloatType")
            m_attributes["map"] = tex
            m_attributes["alphaTest"] = 0.5
            m_attributes["transparency"] = True
        else:  # Plot squares
            pass

        colors, v_colors = self.__get_point_colors(points, c, sh)
        if v_colors:  # Colors per point
            m_attributes["vertexColors"] = 'VertexColors'
            g_attributes["color"] = p3s.BufferAttribute(colors,
                                                        normalized=False)

        else:  # Colors for all points
            m_attributes["color"] = colors

        material = p3s.PointsMaterial(**m_attributes)
        geometry = p3s.BufferGeometry(attributes=g_attributes)
        points = p3s.Points(geometry=geometry, material=material)
        point_obj = {
            "geometry": geometry,
            "mesh": points,
            "material": material,
            "max": ma,
            "min": mi,
            "type": "Points",
            "wireframe": None
        }

        if obj:
            return self.__add_object(point_obj, obj), point_obj
        else:
            return self.__add_object(point_obj)
Ejemplo n.º 12
0
 def create_points_geometry(self):
     """
     Make a PointsGeometry using pythreejs
     """
     points_geometry = p3.BufferGeometry(
         attributes={
             'position': p3.BufferAttribute(array=self.positions),
             'rgba_color': p3.BufferAttribute(array=self.slice_data(None))
         })
     points_material = self.create_points_material()
     points = p3.Points(geometry=points_geometry, material=points_material)
     return points_geometry, points_material, points
Ejemplo n.º 13
0
 def __get_wireframe_from_boundary(self):
     #edges in the boundary box
     edges = self.geometry.vertices[self.geometry.as_edges_flat()].astype(np.float32)
     #The function empty returns an array without values initialized
     buffer = np.empty((int(edges.shape[0] * 3), 3), dtype=np.float32).reshape(-1, 3)
     buffer[:edges.shape[0]] = edges
     vertices = self.__as_buffer_attr(buffer)
     wireframe = three.BufferGeometry(attributes={'position': vertices})
     #Excute the method specified by `method_name` on the three object, with arguments `args`
     #SetDrawRange is a function that sets the attribute DrawRange which determines the part of the geometry to render. (start, end)
     wireframe.exec_three_obj_method("setDrawRange", 0, edges.shape[0])
     return wireframe
Ejemplo n.º 14
0
 def _create_point_cloud(self, pos_array):
     """
     Make a PointsGeometry using pythreejs
     """
     rgba_shape = list(pos_array.shape)
     rgba_shape[1] += 1
     self.points_geometry = p3.BufferGeometry(
         attributes={
             'position':
             p3.BufferAttribute(array=pos_array),
             'rgba_color':
             p3.BufferAttribute(array=np.ones(rgba_shape, dtype=np.float32))
         })
     self.point_cloud = p3.Points(geometry=self.points_geometry,
                                  material=self.points_material)
Ejemplo n.º 15
0
 def geometry(self):
     attributes = dict(
         position=pythreejs.BufferAttribute(self.vertices, normalized=False),
         index=pythreejs.BufferAttribute(
             self.indices.ravel(order="C").astype("u4"), normalized=False
         ),
     )
     if self.attributes is not None:
         attributes["color"] = pythreejs.BufferAttribute(self.attributes)
         # Face colors requires
         # https://speakerdeck.com/yomotsu/low-level-apis-using-three-dot-js?slide=22
         # and
         # https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderLib.js
     geometry = pythreejs.BufferGeometry(attributes=attributes)
     geometry.exec_three_obj_method("computeFaceNormals")
     return geometry
Ejemplo n.º 16
0
    def mesh(self):
        import numpy as np
        import pythreejs as js

        wireframe = self.view_data.get('wireframe', False)

        def triangles(polygon):
            points = polygon.points
            return [(points[0], points[ix], points[ix + 1])
                    for ix in range(1, len(polygon.points) - 1)]

        def _ba(vs):
            points = np.array(vs, dtype=np.float32)
            return js.BufferAttribute(array=points, normalized=False)

        vertices = [
            list(p.xyz) for polygon in self.polygons
            for t in triangles(polygon)
            for p in t
        ]
        normals = [
            list(polygon.plane.normal.xyz) for polygon in self.polygons
            for t in triangles(polygon)
            for p in t
        ]

        geometry = js.BufferGeometry(
            attributes={
                'position': _ba(vertices),
                'normal': _ba(normals)
            },
        )

        if not wireframe:
            color = self.view_data.get('color', 'white')
            material = material=js.MeshLambertMaterial(color=color)
            opacity = self.view_data.get('opacity')
            if opacity is not None:
                material.opacity = opacity
                material.transparent = True
            return js.Mesh(geometry, material)
        else:
            color = self.view_data.get('color', '#00ff00')
            material = js.MeshBasicMaterial(color=color, wireframe=True)
            return js.Mesh(geometry, material)
Ejemplo n.º 17
0
 def _get_mesh(self, u):
     if self.codim == 2:
         u = u[self.entity_map]
     elif self.grid.reference_element == triangle:
         u = np.repeat(u, 3)
     else:
         u = np.tile(np.repeat(u, 3), 2)
     data = p3js.BufferAttribute(_normalize(u, self.vmin, self.vmax),
                                 normalized=True)
     geo = p3js.BufferGeometry(
         index=self.buffer_faces,
         attributes=dict(position=self.buffer_vertices, data=data))
     mesh = p3js.Mesh(geometry=geo, material=self.material)
     mesh.visible = False
     # translate to origin where the camera is looking by default, avoids camera not updating in nbconvert run
     mesh.position = tuple(p - i
                           for p, i in zip(mesh.position, self.mesh_center))
     return mesh
Ejemplo n.º 18
0
def display_portal(th_scene, portal):
    """Display portal."""
    def portal_vertices(portal):
        p1 = np.array(portal[0])
        p2 = np.array(portal[1])
        p4 = np.array(portal[2])
        p3 = p1 + (p2 - p1) + (p4 - p1)
        return [p1, p2, p3, p1, p3, p4]

    ps_attr = three.BufferAttribute(array=portal_vertices(portal),
                                    normalized=False)
    geom = three.BufferGeometry(attributes={'position': ps_attr})
    mat = three.MeshBasicMaterial(color='#ff0000',
                                  transparent=True,
                                  opacity=0.1,
                                  side='DoubleSide')
    mesh = three.Mesh(geometry=geom, material=mat)
    th_scene.add(mesh)
Ejemplo n.º 19
0
    def __get_drawable_from_boundary(self):

        geometry_attributes = {}
        tris, vtx_normals = self.geometry._as_threejs_triangle_soup()
        new_colors = self.geometry_color[
            self.geometry._as_threejs_colors()].astype(np.float32)
        interleaved_array = np.concatenate((tris, new_colors, vtx_normals),
                                           axis=1)
        buffer = three.InterleavedBuffer(array=interleaved_array, stride=3)
        geometry_attributes['position'] = three.InterleavedBufferAttribute(
            data=buffer, itemSize=3, dynamic=True)
        geometry_attributes['color'] = three.InterleavedBufferAttribute(
            data=buffer, itemSize=3, offset=3, dynamic=True)
        geometry_attributes['normal'] = three.InterleavedBufferAttribute(
            data=buffer, itemSize=3, offset=6, dynamic=True)
        drawable_geometry = three.BufferGeometry(
            attributes=geometry_attributes)

        return drawable_geometry
Ejemplo n.º 20
0
def axes_1d(x, y, color="#000000", linewidth=1.5):

    N = len(x)

    pts = np.zeros([5, 3])

    xmin = np.amin(x)
    xmax = np.amax(x)
    ymin = np.amin(y)
    ymax = np.amax(y)

    pts[:, 0] = x
    pts[:, 1] = y
    geometry = p3.BufferGeometry(attributes={
        'position': p3.BufferAttribute(array=pts),
    })
    material = p3.LineBasicMaterial(color=color, linewidth=linewidth)
    line = p3.Line(geometry=geometry, material=material)
    width = 800
    height = 500
Ejemplo n.º 21
0
def to_edge_mesh(surf, mapper, prop, use_edge_coloring=True, use_lines=False):
    """Convert a pyvista surface to a three.js edge mesh."""
    # extract all edges from the surface.  Should not use triangular
    # mesh here as mesh may contain more than triangular faces
    if use_lines:
        edges_mesh = surf
        edges = segment_poly_cells(surf)
    else:
        edges_mesh = surf.extract_all_edges()
        edges = edges_mesh.lines.reshape(-1, 3)[:, 1:]

    attr = {
        'position': array_to_float_buffer(edges_mesh.points),
        'index': cast_to_min_size(edges, surf.n_points),
    }

    # add in colors
    coloring = get_coloring(mapper, surf)
    if coloring != 'NoColors' and not use_edge_coloring:
        if mapper.GetScalarModeAsString() == 'UsePointData':
            edge_scalars = edges_mesh.point_data.active_scalars
            edge_colors = map_scalars(mapper, edge_scalars)
            attr['color'] = array_to_float_buffer(edge_colors)

    edge_geo = tjs.BufferGeometry(attributes=attr)

    mesh_attr = {}
    if coloring != 'NoColors':
        mesh_attr['vertexColors'] = coloring

    if use_edge_coloring:
        edge_color = prop.GetEdgeColor()
    else:
        edge_color = prop.GetColor()

    edge_mat = tjs.LineBasicMaterial(color=color_to_hex(edge_color),
                                     linewidth=prop.GetLineWidth(),
                                     opacity=prop.GetOpacity(),
                                     side='FrontSide',
                                     **mesh_attr)
    return tjs.LineSegments(edge_geo, edge_mat)
Ejemplo n.º 22
0
def to_tjs_points(dataset, mapper, prop):
    """Extract the points from a dataset and return a buffered geometry."""
    attr = {
        'position': array_to_float_buffer(dataset.points),
    }

    coloring = get_coloring(mapper, dataset)
    if coloring == 'VertexColors':
        colors = map_scalars(mapper, dataset.point_data.active_scalars)
        attr['color'] = array_to_float_buffer(colors)

    geo = tjs.BufferGeometry(attributes=attr)

    m_attr = {
        'color': color_to_hex(prop.GetColor()),
        'size': prop.GetPointSize() / 100,
        'vertexColors': coloring,
    }

    point_mat = tjs.PointsMaterial(**m_attr)
    return tjs.Points(geo, point_mat)
Ejemplo n.º 23
0
def plot_1d(x, y, color="blue", linewidth=2, background="#DDDDDD"):

    if len(x) != len(y):
        raise RuntimeError("bad shape")

    N = len(x)

    dx = config.figure["width"]
    dy = config.figure["height"]

    xmin = np.amin(x)
    ymin = np.amin(y)

    scale_x = dx / (np.amax(x) - xmin)
    scale_y = dy / (np.amax(y) - ymin)

    pts = np.zeros([N, 3], dtype=np.float32)
    pts[:, 0] = (x - xmin) * scale_x
    pts[:, 1] = (y - ymin) * scale_y
    # arr = p3.BufferAttribute(array=pts)
    geometry = p3.BufferGeometry(attributes={
        'position': p3.BufferAttribute(array=pts),
    })
    material = p3.LineBasicMaterial(color=color, linewidth=linewidth)
    line = p3.Line(geometry=geometry, material=material)
    # width = 800
    # height= 500

    # Create the threejs scene with ambient light and camera
    # camera = p3.PerspectiveCamera(position=[0.5*dx, 0.5*dy, 0],
    #                                         aspect=dx / dy)
    camera = p3.OrthographicCamera(0, dx, dy, 0, 0.5 * dx, -0.5 * dx)

    return render(objects=line,
                  camera=camera,
                  background=background,
                  enableRotate=False,
                  width=dx,
                  height=dy)
Ejemplo n.º 24
0
    def visualize(self, colors={}):
        from ..space import Vector
        import pythreejs as js
        import numpy as np

        prior = Motion(x=0, y=0, z=0, f=0)
        lines = []
        line_colors = []

        for parent, command in self.commands():
            if isinstance(command, Motion):
                updated = prior.merge(command)
                pv = Vector(*prior.xyz)
                uv = Vector(*updated.xyz)
                delta = pv - uv
                start = (uv + pv) / 2
                lines.extend([prior.xyz, updated.xyz])
                a1 = delta.rotate(Vector(0, 0, 1), tau / 16) * 0.1
                a2 = delta.rotate(Vector(0, 0, 1), -tau / 16) * 0.1
                lines.extend(
                    [start, (a1 + start).xyz, start, (a2 + start).xyz])
                prior = updated
                color = getattr(parent, 'color', [0, 1, 0])
                line_colors.extend([color, color])
                line_colors.extend([color, color])
                line_colors.extend([color, color])

        lines = np.array(lines, dtype=np.float32)
        line_colors = np.array(line_colors, dtype=np.float32)
        geometry = js.BufferGeometry(attributes={
            'position':
            js.BufferAttribute(lines, normalized=False),
            'color':
            js.BufferAttribute(line_colors, normalized=False),
        }, )
        material = js.LineBasicMaterial(vertexColors='VertexColors',
                                        linewidth=1)
        return js.LineSegments(geometry, material)
Ejemplo n.º 25
0
    def _render_obj(self, rendered_obj, **kw):
        obj_geometry = pjs.BufferGeometry(attributes=dict(
            position=pjs.BufferAttribute(rendered_obj.plot_verts),
            color=pjs.BufferAttribute(rendered_obj.base_cols),
            normal=pjs.BufferAttribute(
                rendered_obj.face_normals.astype('float32'))))
        vertices = rendered_obj.vertices

        # Create a mesh. Note that the material need to be told to use the vertex colors.
        my_object_mesh = pjs.Mesh(
            geometry=obj_geometry,
            material=pjs.MeshLambertMaterial(vertexColors='VertexColors'),
            position=[0, 0, 0],
        )

        line_material = pjs.LineBasicMaterial(color='#ffffff',
                                              transparent=True,
                                              opacity=0.3,
                                              linewidth=1.0)
        my_object_wireframe_mesh = pjs.LineSegments(
            geometry=obj_geometry,
            material=line_material,
            position=[0, 0, 0],
        )

        n_vert = vertices.shape[0]
        center = vertices.mean(axis=0)

        extents = self._get_extents(vertices)
        max_delta = np.max(extents[:, 1] - extents[:, 0])
        camPos = [center[i] + 4 * max_delta for i in range(3)]
        light_pos = [center[i] + (i + 3) * max_delta for i in range(3)]

        # Set up a scene and render it:
        camera = pjs.PerspectiveCamera(position=camPos,
                                       fov=20,
                                       children=[
                                           pjs.DirectionalLight(
                                               color='#ffffff',
                                               position=light_pos,
                                               intensity=0.5)
                                       ])
        camera.up = (0, 0, 1)

        v = [0.0, 0.0, 0.0]
        if n_vert > 0: v = vertices[0].tolist()
        select_point_geom = pjs.SphereGeometry(radius=1.0)
        select_point_mesh = pjs.Mesh(
            select_point_geom,
            material=pjs.MeshBasicMaterial(color=SELECTED_VERTEX_COLOR),
            position=v,
            scale=(0.0, 0.0, 0.0))

        #select_edge_mesh = pjs.ArrowHelper(dir=pjs.Vector3(1.0, 0.0, 0.0), origin=pjs.Vector3(0.0, 0.0, 0.0), length=1.0,
        #                                  hex=SELECTED_EDGE_COLOR_INT, headLength=0.1, headWidth=0.05)

        arrow_cyl_mesh = pjs.Mesh(geometry=pjs.SphereGeometry(radius=0.01),
                                  material=pjs.MeshLambertMaterial())
        arrow_head_mesh = pjs.Mesh(geometry=pjs.SphereGeometry(radius=0.001),
                                   material=pjs.MeshLambertMaterial())

        scene_things = [
            my_object_mesh, my_object_wireframe_mesh, select_point_mesh,
            arrow_cyl_mesh, arrow_head_mesh, camera,
            pjs.AmbientLight(color='#888888')
        ]

        if self.draw_grids:
            grids, space = self._get_grids(vertices)
            scene_things.append(grids)

        scene = pjs.Scene(children=scene_things, background=BACKGROUND_COLOR)

        click_picker = pjs.Picker(controlling=my_object_mesh, event='dblclick')
        out = Output()
        top_msg = HTML()

        def on_dblclick(change):
            if change['name'] == 'point':
                try:
                    point = np.array(change['new'])
                    face = click_picker.faceIndex
                    face_points = rendered_obj.face_verts[face]
                    face_vecs = face_points - np.roll(face_points, 1, axis=0)
                    edge_lens = np.sqrt((face_vecs**2).sum(axis=1))
                    point_vecs = face_points - point[np.newaxis, :]
                    point_dists = (point_vecs**2).sum(axis=1)
                    min_point = np.argmin(point_dists)
                    v1s = point_vecs.copy()
                    v2s = np.roll(v1s, -1, axis=0)
                    edge_mids = 0.5 * (v2s + v1s)
                    edge_mid_dists = (edge_mids**2).sum(axis=1)
                    min_edge_point = np.argmin(edge_mid_dists)
                    edge_start = min_edge_point
                    edge = face * 3 + edge_start
                    close_vert = rendered_obj.face_verts[face, min_point]
                    edge_start_vert = rendered_obj.face_verts[face, edge_start]
                    edge_end_vert = rendered_obj.face_verts[face,
                                                            (edge_start + 1) %
                                                            3]

                    vertex = face * 3 + min_point
                    radius = min(
                        [edge_lens.max() * 0.02, 0.1 * edge_lens.min()])

                    edge_head_length = radius * 4
                    edge_head_width = radius * 2
                    select_point_mesh.scale = (radius, radius, radius)
                    top_msg.value = '<font color="{}">selected face: {}</font>, <font color="{}">edge: {}</font>, <font color="{}"> vertex: {}</font>'.format(
                        SELECTED_FACE_COLOR, face, SELECTED_EDGE_COLOR, edge,
                        SELECTED_VERTEX_COLOR, vertex)
                    newcols = rendered_obj.base_cols.copy()
                    newcols[face * 3:(face + 1) * 3] = np.array(
                        SELECTED_FACE_RGB, dtype='float32')
                    select_point_mesh.position = close_vert.tolist()
                    obj_geometry.attributes['color'].array = newcols

                    with out:
                        make_arrow(arrow_cyl_mesh, arrow_head_mesh,
                                   edge_start_vert, edge_end_vert, radius / 2,
                                   radius, radius * 3, SELECTED_EDGE_COLOR)

                except:
                    with out:
                        print(traceback.format_exc())

        click_picker.observe(on_dblclick, names=['point'])

        renderer_obj = pjs.Renderer(
            camera=camera,
            background='#cccc88',
            background_opacity=0,
            scene=scene,
            controls=[pjs.OrbitControls(controlling=camera), click_picker],
            width=self.width,
            height=self.height)

        display_things = [top_msg, renderer_obj, out]
        if self.draw_grids:
            s = """
<svg width="{}" height="30">
<rect width="20" height="20" x="{}" y="0" style="fill:none;stroke-width:1;stroke:rgb(0,255,0)" />
    <text x="{}" y="15">={:.1f}</text>
  Sorry, your browser does not support inline SVG.
</svg>""".format(self.width, self.width // 2, self.width // 2 + 25, space)
            display_things.append(HTML(s))

        display(VBox(display_things))
Ejemplo n.º 26
0
    def add_mesh(self, v, f, c=None, uv=None, shading={}, texture_data=None):
        sh = self.__get_shading(shading)
        mesh_obj = {}

        #it is a tet
        if v.shape[1] == 3 and f.shape[1] == 4:
            f_tmp = np.ndarray([f.shape[0]*4, 3], dtype=f.dtype)
            for i in range(f.shape[0]):
                f_tmp[i*4+0] = np.array([f[i][1], f[i][0], f[i][2]])
                f_tmp[i*4+1] = np.array([f[i][0], f[i][1], f[i][3]])
                f_tmp[i*4+2] = np.array([f[i][1], f[i][2], f[i][3]])
                f_tmp[i*4+3] = np.array([f[i][2], f[i][0], f[i][3]])
            f = f_tmp

        if v.shape[1] == 2:
            v = np.append(v, np.zeros([v.shape[0], 1]), 1)


        # Type adjustment vertices
        v = v.astype("float32", copy=False)

        # Color setup
        colors, coloring = self.__get_colors(v, f, c, sh)

        # Type adjustment faces and colors
        c = colors.astype("float32", copy=False)

        # Material and geometry setup
        ba_dict = {"color": p3s.BufferAttribute(c)}
        if coloring == "FaceColors":
            verts = np.zeros((f.shape[0]*3, 3), dtype="float32")
            for ii in range(f.shape[0]):
                #print(ii*3, f[ii])
                verts[ii*3] = v[f[ii,0]]
                verts[ii*3+1] = v[f[ii,1]]
                verts[ii*3+2] = v[f[ii,2]]
            v = verts
        else:
            f = f.astype("uint32", copy=False).ravel()
            ba_dict["index"] = p3s.BufferAttribute(f, normalized=False)

        ba_dict["position"] = p3s.BufferAttribute(v, normalized=False)

        if type(uv) != type(None):
            uv = (uv - np.min(uv)) / (np.max(uv) - np.min(uv))
            if texture_data is None:
                texture_data = gen_checkers(20, 20)
            tex = p3s.DataTexture(data=texture_data, format="RGBFormat", type="FloatType")
            material = p3s.MeshStandardMaterial(map=tex, reflectivity=sh["reflectivity"], side=sh["side"],
                    roughness=sh["roughness"], metalness=sh["metalness"], flatShading=sh["flat"],
                    polygonOffset=True, polygonOffsetFactor= 1, polygonOffsetUnits=5)
            ba_dict["uv"] = p3s.BufferAttribute(uv.astype("float32", copy=False))
        else:
            material = p3s.MeshStandardMaterial(vertexColors=coloring, reflectivity=sh["reflectivity"],
                    side=sh["side"], roughness=sh["roughness"], metalness=sh["metalness"],
                    flatShading=sh["flat"],
                    polygonOffset=True, polygonOffsetFactor= 1, polygonOffsetUnits=5)

        geometry = p3s.BufferGeometry(attributes=ba_dict)

        if coloring == "VertexColors":
            geometry.exec_three_obj_method('computeVertexNormals')
        else:
            geometry.exec_three_obj_method('computeFaceNormals')

        # Mesh setup
        mesh = p3s.Mesh(geometry=geometry, material=material)

        # Wireframe setup
        mesh_obj["wireframe"] = None
        if sh["wireframe"]:
            wf_geometry = p3s.WireframeGeometry(mesh.geometry) # WireframeGeometry
            wf_material = p3s.LineBasicMaterial(color=sh["wire_color"], linewidth=sh["wire_width"])
            wireframe = p3s.LineSegments(wf_geometry, wf_material)
            mesh.add(wireframe)
            mesh_obj["wireframe"] = wireframe

        # Bounding box setup
        if sh["bbox"]:
            v_box, f_box = self.__get_bbox(v)
            _, bbox = self.add_edges(v_box, f_box, sh, mesh)
            mesh_obj["bbox"] = [bbox, v_box, f_box]

        # Object setup
        mesh_obj["max"] = np.max(v, axis=0)
        mesh_obj["min"] = np.min(v, axis=0)
        mesh_obj["geometry"] = geometry
        mesh_obj["mesh"] = mesh
        mesh_obj["material"] = material
        mesh_obj["type"] = "Mesh"
        mesh_obj["shading"] = sh
        mesh_obj["coloring"] = coloring
        mesh_obj["arrays"] = [v, f, c] # TODO replays with proper storage or remove if not needed

        return self.__add_object(mesh_obj)
Ejemplo n.º 27
0
    def __get_drawable_from_boundary(self):
        geometry_attributes = {}
        tris, vtx_normals = self.geometry._as_threejs_triangle_soup()
        new_colors = self.geometry_color[self.geometry._as_threejs_colors()].astype(np.float32)

        if self.geometry.uvcoords is not None:
            uvcoords =  self.geometry.uvcoords.astype(np.float32)
            coor = self.geometry.coor


            uv = []
            if len(uvcoords) != 0:
            #corrispondenza delle coordinate uv in triangle soup
            #Uv coords in triangle soup
                if 'Quadmesh' in self.type:
                    coor = np.c_[coor[:,:3], coor[:,2:], coor[:,0]]


            coor = coor.flatten()
            for c in coor:
                uv.append(uvcoords[c - 1])


            self.faceVertexUvs = np.array(uv).astype(np.float32)

        if  len(self.faceVertexUvs) != 0 :
            interleaved_array = np.concatenate((tris, new_colors, vtx_normals, self.faceVertexUvs), axis=1)
            buffer = three.InterleavedBuffer(array=interleaved_array, stride=4)
        else:
            interleaved_array = np.concatenate((tris, new_colors, vtx_normals), axis=1)
            buffer = three.InterleavedBuffer(array=interleaved_array, stride=3)


        #Making the interleavedBuffer using the interleaved_array made up of the triangle soup, the color and the vertices' normals, with a stride of 3

        #itemsize = item size, dynamic = (is the normalized attribute o f the super class)?, offset = it's the offset from the start item,
        geometry_attributes['position'] = three.InterleavedBufferAttribute(data=buffer, itemSize=3, dynamic = True)
        geometry_attributes['color'] = three.InterleavedBufferAttribute(data=buffer, itemSize=3, offset=3, dynamic=True)
        geometry_attributes['normal'] = three.InterleavedBufferAttribute(data=buffer, itemSize=3, offset=6, dynamic=True)
        if self.geometry.material is not {} or self.geometry.texture is not None :
            geometry_attributes['uv'] = three.InterleavedBufferAttribute(data=buffer, itemSize=2, offset=9, dynamic=True)
        #         # Buffer Geometry = an efficient representation of mesh, line, or point geometry
        # Includes vertex positions, face indices, normals, colors, UVs, and custom attributes within buffers
        drawable_geometry = three.BufferGeometry(attributes=geometry_attributes)

        #The multiplier is used because groups need faces' indices in triangle soup and 'count' counts only the number of faces per material
        mult = 1
        if 'Trimesh' in self.type:
            mult = 3
        elif 'Quadmesh' in self.type:
            mult = 6

        if len(self.geometry.material) != 0:
            '''
             group = { start: Integer, count: Integer, materialIndex: Integer } where:
             - start : the first triangle index of the group
             - count : how many indices are included
             - materialIndex : the material array index to use for this group 
            '''

            i = 0
            for g in self.geometry.groups:
                if i == 0:
                    n = copy.copy(g)
                    drawable_geometry.exec_three_obj_method("addGroup", 0, mult * self.geometry.groups[g], self.search_key(g))
                else:
                    drawable_geometry.exec_three_obj_method("addGroup", mult * self.geometry.groups[n], mult * self.geometry.groups[g],
                                                            self.search_key(g))
                    n = copy.copy(g)

                i = i + 1

        return drawable_geometry
Ejemplo n.º 28
0
    def setGeometry(self, vertices, idxs, normals, preserveExisting=False, updateModelMatrix=False, textureMap=None, scalarField=None, vectorField=None):
        self.scalarField = scalarField
        self.vectorField = vectorField

        if (updateModelMatrix):
            translate = -np.mean(vertices, axis=0)
            self.bbSize = np.max(np.abs(vertices + translate))
            scaleFactor = 2.0 / self.bbSize
            self.objects.scale = [scaleFactor, scaleFactor, scaleFactor]
            self.objects.position = tuple(scaleFactor * translate)

        ########################################################################
        # Construct the raw attributes describing the new mesh.
        ########################################################################
        attrRaw = {'position': vertices,
                   'index':    idxs.ravel(),
                   'normal':   normals}

        if (textureMap is not None): attrRaw['uv'] = np.array(textureMap.uv, dtype=np.float32)

        useVertexColors = False
        if (self.scalarField is not None):
            # Construct scalar field from raw data array if necessary
            if (not isinstance(self.scalarField, ScalarField)):
                self.scalarField = ScalarField(self.mesh, self.scalarField)
            self.scalarField.validateSize(vertices.shape[0], idxs.shape[0])

            attrRaw['color'] = np.array(self.scalarField.colors(), dtype=np.float32)
            if (self.scalarField.domainType == DomainType.PER_TRI):
                # Replicate vertex data in the per-face case (positions, normal, uv) and remove index buffer; replicate colors x3
                # This is needed according to https://stackoverflow.com/questions/41670308/three-buffergeometry-how-do-i-manually-set-face-colors
                # since apparently indexed geometry doesn't support the 'FaceColors' option.
                replicateAttributesPerTriCorner(attrRaw)
            useVertexColors = True

        # Turn the current mesh into a ghost if preserveExisting
        if (preserveExisting and (self.currMesh is not None)):
            oldMesh = self.currMesh
            self.currMesh = None
            oldMesh.material = self.materialLibrary.ghostMaterial(oldMesh.material)
            self.meshes.remove(oldMesh)
            self.ghostMeshes.add(oldMesh)

            # Also convert the current vector field into a ghost (if one is displayed)
            if (self.vectorFieldMesh in self.meshes.children):
                oldVFMesh = self.vectorFieldMesh
                self.vectorFieldMesh = None
                oldVFMesh.material.transparent = True
                colors = oldVFMesh.geometry.attributes['arrowColor'].array
                colors[:, 3] = 0.25
                oldVFMesh.geometry.attributes['arrowColor'].array = colors
                self.meshes.remove(oldVFMesh)
                self.ghostMeshes.add(oldVFMesh)
        else:
            self.__cleanMeshes(self.ghostMeshes)

        material = self.materialLibrary.material(useVertexColors, None if textureMap is None else textureMap.dataTex)

        ########################################################################
        # Build or update mesh from the raw attributes.
        ########################################################################
        stashableKeys = ['index', 'color', 'uv']
        def allocateUpdateOrStashBufferAttribute(attr, key):
            # Verify invariant that attributes, if they exist, must either be
            # attached to the current geometry or in the stash (but not both)
            assert((key not in attr) or (key not in self.bufferAttributeStash))

            if key in attrRaw:
                if key in self.bufferAttributeStash:
                    # Reuse the stashed index buffer
                    attr[key] = self.bufferAttributeStash[key]
                    self.bufferAttributeStash.pop(key)

                # Update existing attribute or allocate it for the first time
                if key in attr:
                    attr[key].array = attrRaw[key]
                else:
                    attr[key] = pythreejs.BufferAttribute(attrRaw[key])
            else:
                if key in attr:
                    # Stash the existing, unneeded attribute
                    self.bufferAttributeStash[key] = attr[key]
                    attr.pop(key)

        # Avoid flicker/partial redraws during updates
        if self.avoidRedrawFlicker:
            self.renderer.pauseRendering()

        if (self.currMesh is None):
            attr = {}

            presentKeys = list(attrRaw.keys())
            for key in presentKeys:
                if key in stashableKeys:
                    allocateUpdateOrStashBufferAttribute(attr, key)
                    attrRaw.pop(key)
            attr.update({k: pythreejs.BufferAttribute(v) for k, v in attrRaw.items()})

            geom = pythreejs.BufferGeometry(attributes=attr)
            m = self.MeshConstructor(geometry=geom, material=material)
            self.currMesh = m
            self.meshes.add(m)
        else:
            # Update the current mesh...
            attr = self.currMesh.geometry.attributes.copy()
            attr['position'].array = attrRaw['position']
            attr['normal'  ].array = attrRaw['normal']

            for key in stashableKeys:
                allocateUpdateOrStashBufferAttribute(attr, key)

            self.currMesh.geometry.attributes = attr
            self.currMesh.material = material

        # If we reallocated the current mesh (preserveExisting), we need to point
        # the wireframe/points mesh at the new geometry.
        if self.wireframeMesh is not None:
            self.wireframeMesh.geometry = self.currMesh.geometry
        if self.pointsMesh is not None:
            self.pointsMesh.geometry = self.currMesh.geometry

        ########################################################################
        # Build/update the vector field mesh if requested (otherwise hide it).
        ########################################################################
        if (self.vectorField is not None):
            # Construct vector field from raw data array if necessary
            if (not isinstance(self.vectorField, VectorField)):
                self.vectorField = VectorField(self.mesh, self.vectorField)
            self.vectorField.validateSize(vertices.shape[0], idxs.shape[0])

            self.vectorFieldMesh = self.vectorField.getArrows(vertices, idxs, material=self.arrowMaterial, existingMesh=self.vectorFieldMesh)

            self.arrowMaterial = self.vectorFieldMesh.material
            self.arrowMaterial.updateUniforms(arrowSizePx_x  = self.arrowSize,
                                              rendererWidth  = self.renderer.width,
                                              targetDepth    = np.linalg.norm(np.array(self.cam.position) - np.array(self.controls.target)),
                                              arrowAlignment = self.vectorField.align.getRelativeOffset())
            self.controls.shaderMaterial = self.arrowMaterial
            if (self.vectorFieldMesh not in self.meshes.children):
                self.meshes.add(self.vectorFieldMesh)
        else:
            if (self.vectorFieldMesh in self.meshes.children):
                self.meshes.remove(self.vectorFieldMesh)

        if self.avoidRedrawFlicker:
            # The scene is now complete; reenable rendering and redraw immediatley.
            self.renderer.resumeRendering()
Ejemplo n.º 29
0
def mesh_animation(times, xt, faces):
    """ Animate a mesh from a sequence of mesh vertex positions

        Args:
        times   - a list of time values t_i at which the configuration x is specified
        xt      -   i.e., x(t). A list of arrays representing mesh vertex positions at times t_i.
                    Dimensions of each array should be the same as that of mesh.geometry.array
        TODO nt - n(t) vertex normals
        faces    - array of faces, with vertex loop for each face

        Side effects:
            displays rendering of mesh, with animation action

        Returns: None
        TODO renderer - THREE.Render to show the default scene
        TODO position_action - THREE.AnimationAction IPython widget
    """

    position_morph_attrs = []
    for pos in xt[
            1:]:  # xt[0] uses as the Mesh's default/initial vertex position
        position_morph_attrs.append(
            THREE.BufferAttribute(pos, normalized=False))

    # Testing mesh.geometry.morphAttributes = {'position': position_morph_attrs}
    geom = THREE.BufferGeometry(
        attributes={
            'position': THREE.BufferAttribute(xt[0], normalized=False),
            'index': THREE.BufferAttribute(faces.ravel())
        },
        morphAttributes={'position': position_morph_attrs})
    matl = THREE.MeshStandardMaterial(side='DoubleSide',
                                      color='red',
                                      wireframe=True,
                                      morphTargets=True)

    mesh = THREE.Mesh(geom, matl)

    # create key frames
    position_track = THREE.NumberKeyframeTrack(
        name='.morphTargetInfluences[0]',
        times=times,
        values=list(range(0, len(times))))
    # create animation clip from the morph targets
    position_clip = THREE.AnimationClip(tracks=[position_track])
    # create animation action
    position_action = THREE.AnimationAction(THREE.AnimationMixer(mesh),
                                            position_clip, mesh)

    # TESTING
    camera = THREE.PerspectiveCamera(position=[2, 1, 2], aspect=600 / 400)
    scene = THREE.Scene(children=[
        mesh, camera,
        THREE.AxesHelper(0.2),
        THREE.DirectionalLight(position=[3, 5, 1], intensity=0.6),
        THREE.AmbientLight(intensity=0.5)
    ])
    renderer = THREE.Renderer(
        camera=camera,
        scene=scene,
        controls=[THREE.OrbitControls(controlling=camera)],
        width=600,
        height=400)

    display(renderer, position_action)
Ejemplo n.º 30
0
    def plot(self,
             backend="pythreejs",
             width=800,
             height=500,
             background="black",
             mesh=False,
             use_as_color=["red", "green", "blue"],
             cmap="hsv",
             return_scene=False,
             output_name="pyntcloud_plot",
             polylines={}):
        """Visualize a PyntCloud  using different backends.

        Parameters
        ----------
        backend: {"pythreejs", "threejs"}, optional
            Default: "pythreejs"
            Used to select one of the available libraries for plotting.

        width: int, optional
            Default: 800

        height: int, optional
            Default: 500

        background: str, optional
            Default: "black"
            Used to select the default color of the background.
            In some backends, i.e "pythreejs" the background can be dynamically changed.

        use_as_color: str or ["red", "green", "blue"], optional
            Default: ["red", "green", "blue"]
            Indicates which scalar fields will be used to colorize the rendered
            point cloud.

        cmap: str, optional
            Default: "hsv"
            Color map that will be used to convert a single scalar field into rgb.
            Check matplotlib cmaps.

        return_scene: bool, optional
            Default: False.
            Used with "pythreejs" backend in order to return the pythreejs.Scene object

        polylines: dict, optional
            Default {}.
            Mapping hexadecimal colors to a list of list(len(3)) representing the points of the polyline.
            Example:
            polylines={
                "0xFFFFFF": [[0, 0, 0], [0, 0, 1]],
                "0xFF00FF": [[1, 0, 0], [1, 0, 1], [1, 1, 1]]
            }

        Returns
        -------
        pythreejs.Scene if return_scene else None
        """
        try:
            colors = self.points[use_as_color].values
        except KeyError:
            colors = None

        if use_as_color != ["red", "green", "blue"] and colors is not None:
            import matplotlib.pyplot as plt
            s_m = plt.cm.ScalarMappable(cmap=cmap)
            colors = s_m.to_rgba(colors)[:, :-1] * 255
        elif colors is None:
            # default color orange
            colors = np.repeat([[255, 125, 0]], self.xyz.shape[0], axis=0)

        colors = colors.astype(np.uint8)

        ptp = self.xyz.ptp()

        if backend == "pythreejs":
            import ipywidgets
            import pythreejs
            from IPython.display import display

            if mesh:
                raise NotImplementedError(
                    "Plotting mesh geometry with pythreejs backend is not supported yet."
                )

            if polylines:
                raise NotImplementedError(
                    "Plotting polylines with pythreejs backend is not supported yet."
                )

            points_geometry = pythreejs.BufferGeometry(attributes=dict(
                position=pythreejs.BufferAttribute(self.xyz, normalized=False),
                color=pythreejs.BufferAttribute(list(map(tuple, colors)))))

            points_material = pythreejs.PointsMaterial(
                vertexColors='VertexColors')

            points = pythreejs.Points(geometry=points_geometry,
                                      material=points_material,
                                      position=tuple(self.centroid))

            camera = pythreejs.PerspectiveCamera(
                fov=90,
                aspect=width / height,
                position=tuple(
                    self.centroid +
                    [0,
                     abs(self.xyz.max(0)[1]),
                     abs(self.xyz.max(0)[2]) * 2]),
                up=[0, 0, 1])

            orbit_control = pythreejs.OrbitControls(controlling=camera)
            orbit_control.target = tuple(self.centroid)

            camera.lookAt(tuple(self.centroid))

            scene = pythreejs.Scene(children=[points, camera],
                                    background=background)

            renderer = pythreejs.Renderer(scene=scene,
                                          camera=camera,
                                          controls=[orbit_control],
                                          width=width,
                                          height=height)

            display(renderer)

            size = ipywidgets.FloatSlider(min=0.,
                                          max=(ptp / 100),
                                          step=(ptp / 1000))
            ipywidgets.jslink((size, 'value'), (points_material, 'size'))

            color = ipywidgets.ColorPicker()
            ipywidgets.jslink((color, 'value'), (scene, 'background'))

            display(
                ipywidgets.HBox(children=[
                    ipywidgets.Label('Background color:'), color,
                    ipywidgets.Label('Point size:'), size
                ]))
            return scene if return_scene else None

        elif backend == "threejs":
            points = pd.DataFrame(self.xyz, columns=["x", "y", "z"])

            for n, i in enumerate(["red", "green", "blue"]):
                points[i] = colors[:, n]

            new_PyntCloud = PyntCloud(points)

            if mesh and self.mesh is not None:
                new_PyntCloud.mesh = self.mesh[["v1", "v2", "v3"]]

            return plot_PyntCloud(new_PyntCloud,
                                  IFrame_shape=(width, height),
                                  point_size=ptp / 100,
                                  point_opacity=0.9,
                                  output_name=output_name,
                                  polylines=polylines)
        else:
            raise NotImplementedError(
                "{} backend is not supported".format(backend))