Example #1
0
def make_arrow(cyl_mesh, head_mesh, start_vec, end_vec, width, head_width,
               head_length, color):
    start_vec = np.array(start_vec)
    end_vec = np.array(end_vec)
    v = end_vec - start_vec
    l = np.sqrt(v.dot(v))
    v_norm = v / l
    cyl_height = l - head_length
    z_rot = np.arccos(v_norm.dot(np.array([0.0, 1.0, 0.0])))
    y_rot = np.arctan2(v[2], v[0])

    cyl_center = start_vec + cyl_height / 2 * v_norm
    head_center = start_vec + (cyl_height + head_length / 2) * v_norm
    cyl_geom = pjs.CylinderGeometry(radiusTop=width,
                                    radiusBottom=width,
                                    height=cyl_height)
    cyl_mesh.geometry = cyl_geom
    cyl_mesh.material = pjs.MeshLambertMaterial(color=color)
    cyl_mesh.position = cyl_center.tolist()
    cyl_mesh.setRotationFromMatrix(
        [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0])
    cyl_mesh.rotateY(-y_rot)
    cyl_mesh.rotateZ(-z_rot)

    head_geom = pjs.CylinderGeometry(radiusTop=0.0,
                                     radiusBottom=head_width,
                                     height=head_length)
    head_mesh.geometry = head_geom
    head_mesh.material = pjs.MeshLambertMaterial(color=color)
    head_mesh.position = head_center.tolist()
    head_mesh.setRotationFromMatrix(
        [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0])
    head_mesh.rotateY(-y_rot)
    head_mesh.rotateZ(-z_rot)
Example #2
0
    def ghostMaterial(self, origMaterial, solidColor):
        name = self._mangledNameForMaterial(True, origMaterial)
        if name not in self.materials:
            args = {'transparent': True, 'opacity': 0.25}
            args.update(
                self._colorTexArgs(
                    *self._extractMaterialDescriptors(origMaterial),
                    solidColor))
            if (self.isLineMesh):
                self.materials[name] = pythreejs.LineBasicMaterial(
                    **args, **self.commonArgs)
            elif (self.isPointCloud):
                self.materials[name] = pythreejs.PointsMaterial(
                    **args, **self.commonArgs, size=5, sizeAttenuation=False)
            else:
                self.materials[name] = pythreejs.MeshLambertMaterial(
                    **args, **self.commonArgs)
        else:
            # Update the existing ghost material's color (if a solid color is used)
            useVertexColors, textureMapDataTex = self._extractMaterialDescriptors(
                origMaterial)
            if (useVertexColors == False) and (textureMapDataTex is None):
                self.materials[name].color = solidColor

        return self.materials[name]
Example #3
0
    def __init__(self, structure, modeDoF = None, eigenvalues = None, width=512, height=512, numSteps=8, amplitude = 0.05, normalize = True, wireframe = False):
        super().__init__(structure, width, height, wireframe=wireframe)
        self.normalize = normalize
        self.amplitude = amplitude
        self.layout = ipywidgets.VBox()
        self.controls_layout = ipywidgets.HBox()
        self.action = None
        # Note: numSteps cannot be changed because this requires changing the number of morph attributes
        self.numSteps = numSteps

        self.morphMaterial = pythreejs.MeshLambertMaterial(color='lightgray', side='DoubleSide', morphTargets = True)
        self.modeMesh = None
        self.wireframeAction = None

        # Infer the methods for getting/setting the object's deformed
        # configuration. This involves, e.g., `setVars` for
        # microstructures/inflatables, `setDoFs` for elastic rods, and
        # `setVertices` FEMMeshes.
        self.meshMethods = dir(self.mesh)
        self.numVars, self.varGetter, self.varSetter = None, None, None
        if   ("getVars"     in self.meshMethods): self.numVars, self.varGetter, self.varSetter = self.mesh.numVars(), self.mesh.getVars, self.mesh.setVars
        elif ("getDoFs"     in self.meshMethods): self.numVars, self.varGetter, self.varSetter = self.mesh.numDoF (), self.mesh.getDoFs, self.mesh.setDoFs
        elif ("setVertices" in self.meshMethods): # Mesh version
            self.numVars   = self.mesh.numNodes() * self.mesh.embeddingDimension
            self.varGetter = lambda: self.mesh.nodes().ravel()
            # Note: setVertices will ignore the excess edge nodes in degree 2 case since
            # we do not implement isoparametric FEM.
            self.varSetter = lambda x: self.mesh.setVertices(x.reshape(-1, self.mesh.embeddingDimension));
        else: raise Exception("Unable to infer object's variable accessor interface")

        if (modeDoF is not None):
            self.setModes(modeDoF, eigenvalues=eigenvalues)
Example #4
0
def draw_mesh(mesh, color=None):
    vertices, faces = mesh.to_vertices_and_faces()
    hexcolor = rgb_to_hex(color[:3]) if color else '#cccccc'
    vertexcolors = [hexcolor] * len(vertices)
    faces = [f + [None, [vertexcolors[i] for i in f], None] for f in faces]
    geo = p3js.Geometry(vertices=vertices, faces=faces)
    geo.exec_three_obj_method('computeFaceNormals')
    return p3js.Mesh(geometry=geo, material=p3js.MeshLambertMaterial(vertexColors='VertexColors'), position=[0, 0, 0])
Example #5
0
 def __init__(self, bead, color, **kwargs):
     super().__init__(geometry=three.SphereGeometry(radius=3,
                                                    widthSegments=10,
                                                    heightSegments=10),
                      material=three.MeshLambertMaterial(color=color),
                      position=bead.position.tolist(),
                      **kwargs)
     self.bead = bead
Example #6
0
 def ghostMaterial(self, origMaterial):
     name = self._mangledNameForMaterial(True, origMaterial)
     if name not in self.materials:
         args = {'transparent': True, 'opacity': 0.25}
         args.update(self._colorTexArgs(*self._extractMaterialDescriptors(origMaterial), 'red'))
         if (self.isLineMesh): self.materials[name] = pythreejs.  LineBasicMaterial(**args, **self.commonArgs)
         else:                 self.materials[name] = pythreejs.MeshLambertMaterial(**args, **self.commonArgs)
     return self.materials[name]
Example #7
0
 def material(self, useVertexColors, textureMapDataTex = None):
     name = self._mangledMaterialName(False, useVertexColors, textureMapDataTex)
     if name not in self.materials:
         if (self.isLineMesh):
             args = self._colorTexArgs(useVertexColors, textureMapDataTex, 'black')
             self.materials[name] = pythreejs.LineBasicMaterial(**args, **self.commonArgs)
         else:
             args = self._colorTexArgs(useVertexColors, textureMapDataTex, 'lightgray')
             self.materials[name] = pythreejs.MeshLambertMaterial(**args, **self.commonArgs)
     return self.materials[name]
Example #8
0
def draw_mesh(mesh, hexcolor):
    mesh_quads_to_triangles(mesh)
    vertices, faces = mesh.to_vertices_and_faces()
    vertexcolors = [hexcolor] * len(vertices)
    faces = [f + [None, [vertexcolors[i] for i in f], None] for f in faces]
    geo = p3js.Geometry(vertices=vertices, faces=faces)
    geo.exec_three_obj_method('computeFaceNormals')
    return p3js.Mesh(
        geometry=geo,
        material=p3js.MeshLambertMaterial(vertexColors='VertexColors'),
        position=[0, 0, 0])
Example #9
0
def render_mesh(mesh, up_vector=(0, 1, 0)):
    geometry = build_geometry(
        mesh.triangles,
        mesh.positions,
        normals=getattr(mesh, "normals", None),
        colors=getattr(mesh, "colors", None),
    )

    if hasattr(mesh, "colors"):
        material = three.MeshLambertMaterial(vertexColors="VertexColors")
    else:
        material = three.MeshLambertMaterial()

    obj = three.Mesh(
        geometry=geometry,
        material=material,
        position=[0, 0, 0],
    )

    center = np.array(mesh.positions).reshape(-1, 3).mean(axis=0)
    offset = 8 * np.array(mesh.positions).reshape(-1, 3).std(axis=0)
    return render_scene(Scene(eye_pos=center + offset, obj_pos=center, obj=obj, up=up_vector))
Example #10
0
 def __init__(self):
     # TODO: arguments for width/height
     self._width = 600
     self._height = 400
     self._ball = _three.Mesh(
         geometry=_three.SphereGeometry(
             radius=1,
             widthSegments=30,
             heightSegments=20,
         ),
         material=_three.MeshLambertMaterial(color='lightgray'),
     )
     self._axes = _three.AxesHelper(size=1.2)
     self._ambient_light = _three.AmbientLight(
         intensity=0.5,
     )
     self._directional_light1 = _three.DirectionalLight(
         position=[0, 0, 1],
         intensity=0.6,
     )
     self._directional_light2 = _three.DirectionalLight(
         position=[0, 0, -1],
         intensity=0.6,
     )
     self._scene = _three.Scene(
         children=[
             self._ball,
             self._axes,
             self._ambient_light,
             self._directional_light1,
             self._directional_light2,
         ],
     )
     self._camera = _three.PerspectiveCamera(
         position=[0, 0, 2.4],
         up=[0, 0, 1],
         aspect=self._width/self._height,
     )
     self._controls = _three.OrbitControls(controlling=self._camera)
     self._renderer = _three.Renderer(
         camera=self._camera,
         scene=self._scene,
         controls=[self._controls],
         width=self._width,
         height=self._height,
         #alpha=True,
         #clearOpacity=0.5,
     )
Example #11
0
 def __initialize_mesh(self):
     drawable_geometry = self.__get_drawable_from_boundary()
     material = three.MeshLambertMaterial(
         polygonOffset=True,
         polygonOffsetFactor=1,
         polygonOffsetUnits=1,
         flatShading=True,
         color="white",
         opacity=1.,
         transparent=False,
         side='DoubleSide',
         wireframe=False,
         vertexColors='FaceColors',
     )
     return three.Mesh(geometry=drawable_geometry,
                       material=material,
                       position=[0, 0, 0])
Example #12
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)
Example #13
0
    def __initialize_mesh(self):
        drawable_geometry = self.__get_drawable_from_boundary()

        #No color under textures or materials
        if len(self.geometry.material) != 0 or self.geometry.texture is not None:
            vertexEnum = 'NoColors'
        else:
            vertexEnum = 'FaceColors'
        materials = []

        #LambertMaterial is a material for non-shiny surfaces, without specular highlights.
        if len(self.geometry.material) == 0: #No material or texture

            material_geometry = three.MeshLambertMaterial(
                                           map = self.getTexture(self.texture),
                                           polygonOffset=True,
                                           polygonOffsetFactor=1,
                                           polygonOffsetUnits=1,
                                           flatShading = True,
                                           opacity = 1.,
                                           transparent = False,
                                           side = 'DoubleSide',
                                           wireframe=False,
                                           vertexColors = vertexEnum)
            materials = material_geometry


        else:

            for m in self.geometry.material:
                if self.geometry.smoothness:
                    material_geometry = three.MeshLambertMaterial(
                        map=self.getTexture(self.geometry.material[m]["map_kd"]),
                        color=self.color(self.geometry.material[m]["kd"]),
                        emissiveIntensity=self.geometry.material[m]["ke"],
                        specular=self.color(self.geometry.material[m]["ks"]),
                        shininess=self.geometry.material[m]["ns"],
                        transparence=self.geometry.material[m]["transparence"],
                        opacity=self.geometry.material[m]["opacity"],
                        emissiveMap=self.getTexture(self.geometry.material[m]["map_ke"]),
                        alphaMap=self.getTexture(self.geometry.material[m]["map_d"]),
                        specularMap=self.getTexture(self.geometry.material[m]["map_ks"]),
                        bumpMap=self.getTexture(self.geometry.material[m]["bump"]),
                        normalMap=self.getTexture(self.geometry.material[m]["norm"]),
                        refractionRatio=self.geometry.material[m]["ni"]
                    )
                else:
                    material_geometry = three.MeshPhongMaterial(
                        map = self.getTexture(self.geometry.material[m]["map_kd"]),
                        color = self.color(self.geometry.material[m]["kd"]),
                        emissiveIntensity = self.geometry.material[m]["ke"],
                        specular = self.color(self.geometry.material[m]["ks"]),
                        shininess  =self.geometry.material[m]["ns"],
                        transparence = self.geometry.material[m]["transparence"],
                        opacity = self.geometry.material[m]["opacity"],
                        emissiveMap = self.getTexture(self.geometry.material[m]["map_ke"]),
                        alphaMap = self.getTexture(self.geometry.material[m]["map_d"]),
                        specularMap = self.getTexture(self.geometry.material[m]["map_ks"]),
                        bumpMap = self.getTexture(self.geometry.material[m]["bump"]),
                        normalMap = self.getTexture(self.geometry.material[m]["norm"]),
                        refractionRatio = self.geometry.material[m]["ni"]
                    )

                materials.append(material_geometry)

        mesh1 = three.Mesh(
                geometry=drawable_geometry,
                material=materials,
                position=[0, 0, 0]
            )

        return mesh1
Example #14
0
def visualise(mesh,
              geometric_field,
              number_of_dimensions,
              xi_interpolation,
              dependent_field=None,
              variable=None,
              mechanics_animation=False,
              colour_map_dependent_component_number=None,
              cmap='gist_rainbow',
              resolution=1,
              node_labels=False):

    if number_of_dimensions != 3:
        print(
            'Warning: Only visualisation of 3D meshes is currently supported.')
        return

    if xi_interpolation != [1, 1, 1]:
        print(
            'Warning: Only visualisation of 3D elements with linear Lagrange \
            interpolation along all coordinate directions is currently \
            supported.')
        return

    view_width = 600
    view_height = 600

    debug = False
    if debug:
        vertices = [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0],
                    [1, 0, 1], [1, 1, 0], [1, 1, 1]]

        faces = [[0, 1, 3], [0, 3, 2], [0, 2, 4], [2, 6, 4], [0, 4, 1],
                 [1, 4, 5], [2, 3, 6], [3, 7, 6], [1, 5, 3], [3, 5, 7],
                 [4, 6, 5], [5, 6, 7]]

        vertexcolors = [
            '#000000', '#0000ff', '#00ff00', '#ff0000', '#00ffff', '#ff00ff',
            '#ffff00', '#ffffff'
        ]
    else:
        # Get mesh topology information.
        num_nodes = mesh_tools.num_nodes_get(mesh, mesh_component=1)
        node_nums = list(range(1, num_nodes + 1))
        num_elements, element_nums = mesh_tools.num_element_get(
            mesh, mesh_component=1)

        # Convert geometric field to a morphic mesh and export to json
        mesh = mesh_tools.OpenCMISS_to_morphic(mesh,
                                               geometric_field,
                                               element_nums,
                                               node_nums,
                                               dimension=3,
                                               interpolation='linear')
        vertices, faces, _, xi_element_nums, xis = get_faces(
            mesh, res=resolution, exterior_only=True, include_xi=True)

        vertices = vertices.tolist()
        faces = faces.tolist()

    centroid = np.mean(vertices, axis=0)
    max_positions = np.max(vertices, axis=0)
    min_positions = np.min(vertices, axis=0)
    range_positions = max_positions - min_positions

    if (dependent_field is not None) and (colour_map_dependent_component_number
                                          is not None):

        solution = np.zeros(xis.shape[0])
        for idx, (xi, xi_element_num) in enumerate(zip(xis, xi_element_nums)):
            solution[idx] = mesh_tools.interpolate_opencmiss_field_xi(
                dependent_field,
                xi,
                element_ids=[xi_element_num],
                dimension=3,
                deriv=1)[colour_map_dependent_component_number - 1]

        minima = min(solution)
        maxima = max(solution)

        import matplotlib
        norm = matplotlib.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
        mapper = cm.ScalarMappable(norm=norm, cmap=cm.get_cmap(name=cmap))

        vertex_colors = np.zeros((len(vertices), 3), dtype='float32')
        for idx, v in enumerate(solution):
            vertex_colors[idx, :] = mapper.to_rgba(v, alpha=None)[:3]
        # else:
        #     raise ValueError('Visualisation not supported.')
    else:
        vertex_colors = np.tile(np.array([0.5, 0.5, 0.5], dtype='float32'),
                                (len(vertices), 1))

    geometry = pjs.BufferGeometry(attributes=dict(
        position=pjs.BufferAttribute(vertices, normalized=False),
        index=pjs.BufferAttribute(
            np.array(faces).astype(dtype='uint16').ravel(), normalized=False),
        color=pjs.BufferAttribute(vertex_colors),
    ))

    if mechanics_animation:
        deformed_vertices = np.zeros((xis.shape[0], 3), dtype='float32')
        for idx, (xi, xi_element_num) in enumerate(zip(xis, xi_element_nums)):
            deformed_vertices[idx, :] = \
            mesh_tools.interpolate_opencmiss_field_xi(
                dependent_field, xi, element_ids=[xi_element_num],
                dimension=3,
                deriv=1)[0][:3]
        geometry.morphAttributes = {
            'position': [
                pjs.BufferAttribute(deformed_vertices),
            ]
        }

        geometry.exec_three_obj_method('computeFaceNormals')
        geometry.exec_three_obj_method('computeVertexNormals')

        surf1 = pjs.Mesh(geometry,
                         pjs.MeshPhongMaterial(color='#ff3333',
                                               shininess=150,
                                               morphTargets=True,
                                               side='FrontSide'),
                         name='A')
        surf2 = pjs.Mesh(geometry,
                         pjs.MeshPhongMaterial(color='#ff3333',
                                               shininess=150,
                                               morphTargets=True,
                                               side='BackSide'),
                         name='B')
        surf = pjs.Group(children=[surf1, surf2])

        # camera = pjs.PerspectiveCamera(
        #     fov=20, position=[range_positions[0] * 10,
        #                       range_positions[1] * 10,
        #                       range_positions[2] * 10],
        #     width=view_width,
        #     height=view_height, near=1,
        #     far=max(range_positions) * 10)

        camera = pjs.PerspectiveCamera(position=[
            range_positions[0] * 3, range_positions[1] * 3,
            range_positions[2] * 3
        ],
                                       aspect=view_width / view_height)
        camera.up = [0, 0, 1]
        camera.lookAt(centroid.tolist())

        scene3 = pjs.Scene(children=[
            surf1, surf2, camera,
            pjs.DirectionalLight(position=[3, 5, 1], intensity=0.6),
            pjs.AmbientLight(intensity=0.5)
        ])
        axes = pjs.AxesHelper(size=range_positions[0] * 2)
        scene3.add(axes)

        A_track = pjs.NumberKeyframeTrack(
            name='scene/A.morphTargetInfluences[0]',
            times=[0, 3],
            values=[0, 1])
        B_track = pjs.NumberKeyframeTrack(
            name='scene/B.morphTargetInfluences[0]',
            times=[0, 3],
            values=[0, 1])
        pill_clip = pjs.AnimationClip(tracks=[A_track, B_track])
        pill_action = pjs.AnimationAction(pjs.AnimationMixer(scene3),
                                          pill_clip, scene3)

        renderer3 = pjs.Renderer(
            camera=camera,
            scene=scene3,
            controls=[pjs.OrbitControls(controlling=camera)],
            width=view_width,
            height=view_height)

        display(renderer3, pill_action)

    else:
        geometry.exec_three_obj_method('computeFaceNormals')
        geometry.exec_three_obj_method('computeVertexNormals')

        surf1 = pjs.Mesh(geometry=geometry,
                         material=pjs.MeshLambertMaterial(
                             vertexColors='VertexColors',
                             side='FrontSide'))  # Center the cube.
        surf2 = pjs.Mesh(geometry=geometry,
                         material=pjs.MeshLambertMaterial(
                             vertexColors='VertexColors',
                             side='BackSide'))  # Center the cube.
        surf = pjs.Group(children=[surf1, surf2])

        camera = pjs.PerspectiveCamera(position=[
            range_positions[0] * 3, range_positions[1] * 3,
            range_positions[2] * 3
        ],
                                       aspect=view_width / view_height)

        camera.up = [0, 0, 1]
        camera.lookAt(centroid.tolist())

        # if perspective:
        #     camera.mode = 'perspective'
        # else:
        #     camera.mode = 'orthographic'

        lights = [
            pjs.DirectionalLight(position=[
                range_positions[0] * 16, range_positions[1] * 12,
                range_positions[2] * 17
            ],
                                 intensity=0.5),
            pjs.AmbientLight(intensity=0.8),
        ]
        orbit = pjs.OrbitControls(controlling=camera,
                                  screenSpacePanning=True,
                                  target=centroid.tolist())

        scene = pjs.Scene()
        axes = pjs.AxesHelper(size=max(range_positions) * 2)
        scene.add(axes)
        scene.add(surf1)
        scene.add(surf2)
        scene.add(lights)

        if node_labels:
            # Add text labels for each mesh node.
            v, ids = mesh.get_node_ids(group='_default')
            for idx, v in enumerate(v):
                text = make_text(str(ids[idx]), position=(v[0], v[1], v[2]))
                scene.add(text)

        # Add text for axes labels.
        x_axis_label = make_text('x',
                                 position=(max(range_positions) * 2, 0, 0))
        y_axis_label = make_text('y',
                                 position=(0, max(range_positions) * 2, 0))
        z_axis_label = make_text('z',
                                 position=(0, 0, max(range_positions) * 2))
        scene.add(x_axis_label)
        scene.add(y_axis_label)
        scene.add(z_axis_label)

        renderer = pjs.Renderer(scene=scene,
                                camera=camera,
                                controls=[orbit],
                                width=view_width,
                                height=view_height)
        camera.zoom = 1
        display(renderer)

    return vertices, faces
Example #15
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))
Example #16
0
def hand_obj_children(
    obj_verts=None,
    obj_faces=None,
    gt_obj_verts=None,
    gt_obj_faces=None,
    hand_verts=None,
    mano_faces_left=None,
    display_wireframe=False,
    inside_face_colors=True,
    hand_opacity=1,
    obj_opacity=0.2,
):
    """Args:
        obj_verts(numpy.ndarray): vertices of object
        hand_verts(numpy.ndarray): vertices of handect
        *_faces(numpy.ndarray): faces
    """

    scene_children = []
    if obj_verts is not None:
        geo_obj = p3js.Geometry(vertices=obj_verts.tolist(),
                                faces=obj_faces.tolist())
        geo_obj.exec_three_obj_method("computeFaceNormals")
        mat = p3js.MeshLambertMaterial(color="red",
                                       side="FrontSide",
                                       transparent=True)
        mat.opacity = obj_opacity  # obj_opacity
        surf_obj = p3js.Mesh(geometry=geo_obj, material=mat)
        if inside_face_colors:
            back_color = "#a91818"
        else:
            back_color = "red"
        mat_bak = p3js.MeshLambertMaterial(color=back_color,
                                           side="BackSide",
                                           transparent=True)
        mat_bak.opacity = obj_opacity
        surf_obj_back = p3js.Mesh(geometry=geo_obj, material=mat_bak)
        scene_children.append(surf_obj)
        scene_children.append(surf_obj_back)
        if display_wireframe:
            obj_edges = p3js.Mesh(
                geometry=geo_obj,
                material=p3js.MeshBasicMaterial(color="black", wireframe=True),
            )
            scene_children.append(obj_edges)
    if gt_obj_verts is not None:
        geo_obj = p3js.Geometry(vertices=gt_obj_verts.tolist(),
                                faces=gt_obj_faces.tolist())
        geo_obj.exec_three_obj_method("computeFaceNormals")
        mat = p3js.MeshLambertMaterial(color="orange",
                                       side="FrontSide",
                                       transparent=True)
        mat.opacity = obj_opacity
        surf_obj = p3js.Mesh(geometry=geo_obj, material=mat)
        mat_back = p3js.MeshLambertMaterial(color="#a91818",
                                            side="BackSide",
                                            transparent=True)
        mat_back.opacity = obj_opacity
        surf_obj_back = p3js.Mesh(geometry=geo_obj, material=mat_bak)
        scene_children.append(surf_obj)
        scene_children.append(surf_obj_back)
        if display_wireframe:
            obj_edges = p3js.Mesh(
                geometry=geo_obj,
                material=p3js.MeshBasicMaterial(color="black", wireframe=True),
            )
            scene_children.append(obj_edges)
    if hand_verts is not None:
        geo_hand = p3js.Geometry(vertices=hand_verts.tolist(),
                                 faces=mano_faces_left.tolist())
        geo_hand.exec_three_obj_method("computeFaceNormals")
        mat = p3js.MeshLambertMaterial(color="blue",
                                       side="FrontSide",
                                       transparent=True)
        mat.opacity = hand_opacity
        surf_hand = p3js.Mesh(geometry=geo_hand, material=mat)
        bak_mat = p3js.MeshLambertMaterial(color="blue",
                                           side="BackSide",
                                           transparent=True)
        bak_mat.opacity = hand_opacity
        surf_hand_bak = p3js.Mesh(geometry=geo_hand, material=bak_mat)

        scene_children.append(surf_hand)
        scene_children.append(surf_hand_bak)
        if display_wireframe:
            hand_edges = p3js.Mesh(
                geometry=geo_hand,
                material=p3js.MeshBasicMaterial(color="black", wireframe=True),
            )
            scene_children.append(hand_edges)

    return scene_children
Example #17
0
    def _render_stl(self, stl_file):
        vertices, faces = self._conv_stl(stl_file)

        # Map the vertex colors into the 'color' slot of the faces
        faces = [f + [None, [OBJ_COLOR for i in f], None] for f in faces]

        # Create the geometry:
        obj_geometry = pjs.Geometry(vertices=vertices,
                                    faces=faces,
                                    colors=[OBJ_COLOR] * len(vertices))
        # Calculate normals per face, for nice crisp edges:
        obj_geometry.exec_three_obj_method('computeFaceNormals')

        # 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],  # Center the cube
        )

        n_vert = len(vertices)
        center = [
            sum([vertex[i] for vertex in vertices]) / float(n_vert)
            for i in range(3)
        ]
        extents = self._get_extents(vertices)
        max_delta = max([extent[1] - extent[0] for extent in extents])
        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)

        scene_things = [
            my_object_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)

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

        display_things = [renderer_obj]
        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(*display_things)
Example #18
0
def material_from_color(color=None):
    if color:
        return p3js.MeshLambertMaterial(color=color)
    else:
        return p3js.MeshLambertMaterial(color='#cccccc')
Example #19
0
def generate_3js_render(
    element_groups,
    canvas_size,
    zoom,
    camera_fov=30,
    background_color="white",
    background_opacity=1.0,
    reuse_objects=False,
    use_atom_arrays=False,
    use_label_arrays=False,
):
    """Create a pythreejs scene of the elements.

    Regarding initialisation performance, see: https://github.com/jupyter-widgets/pythreejs/issues/154
    """
    import pythreejs as pjs

    key_elements = {}
    group_elements = pjs.Group()
    key_elements["group_elements"] = group_elements

    unique_atom_sets = {}
    for el in element_groups["atoms"]:
        element_hash = (
            ("radius", el.sradius),
            ("color", el.color),
            ("fill_opacity", el.fill_opacity),
            ("stroke_color", el.get("stroke_color", "black")),
            ("ghost", el.ghost),
        )
        unique_atom_sets.setdefault(element_hash, []).append(el)

    group_atoms = pjs.Group()
    group_ghosts = pjs.Group()

    atom_geometries = {}
    atom_materials = {}
    outline_materials = {}

    for el_hash, els in unique_atom_sets.items():
        el = els[0]
        data = dict(el_hash)

        if reuse_objects:
            atom_geometry = atom_geometries.setdefault(
                el.sradius,
                pjs.SphereBufferGeometry(radius=el.sradius,
                                         widthSegments=30,
                                         heightSegments=30),
            )
        else:
            atom_geometry = pjs.SphereBufferGeometry(radius=el.sradius,
                                                     widthSegments=30,
                                                     heightSegments=30)

        if reuse_objects:
            atom_material = atom_materials.setdefault(
                (el.color, el.fill_opacity),
                pjs.MeshLambertMaterial(color=el.color,
                                        transparent=True,
                                        opacity=el.fill_opacity),
            )
        else:
            atom_material = pjs.MeshLambertMaterial(color=el.color,
                                                    transparent=True,
                                                    opacity=el.fill_opacity)

        if use_atom_arrays:
            atom_mesh = pjs.Mesh(geometry=atom_geometry,
                                 material=atom_material)
            atom_array = pjs.CloneArray(
                original=atom_mesh,
                positions=[e.position.tolist() for e in els],
                merge=False,
            )
        else:
            atom_array = [
                pjs.Mesh(
                    geometry=atom_geometry,
                    material=atom_material,
                    position=e.position.tolist(),
                    name=e.info_string,
                ) for e in els
            ]

        data["geometry"] = atom_geometry
        data["material_body"] = atom_material

        if el.ghost:
            key_elements["group_ghosts"] = group_ghosts
            group_ghosts.add(atom_array)
        else:
            key_elements["group_atoms"] = group_atoms
            group_atoms.add(atom_array)

        if el.get("stroke_width", 1) > 0:
            if reuse_objects:
                outline_material = outline_materials.setdefault(
                    el.get("stroke_color", "black"),
                    pjs.MeshBasicMaterial(
                        color=el.get("stroke_color", "black"),
                        side="BackSide",
                        transparent=True,
                        opacity=el.get("stroke_opacity", 1.0),
                    ),
                )
            else:
                outline_material = pjs.MeshBasicMaterial(
                    color=el.get("stroke_color", "black"),
                    side="BackSide",
                    transparent=True,
                    opacity=el.get("stroke_opacity", 1.0),
                )
            # TODO use stroke width to dictate scale
            if use_atom_arrays:
                outline_mesh = pjs.Mesh(
                    geometry=atom_geometry,
                    material=outline_material,
                    scale=(1.05, 1.05, 1.05),
                )
                outline_array = pjs.CloneArray(
                    original=outline_mesh,
                    positions=[e.position.tolist() for e in els],
                    merge=False,
                )
            else:
                outline_array = [
                    pjs.Mesh(
                        geometry=atom_geometry,
                        material=outline_material,
                        position=e.position.tolist(),
                        scale=(1.05, 1.05, 1.05),
                    ) for e in els
                ]

            data["material_outline"] = outline_material

            if el.ghost:
                group_ghosts.add(outline_array)
            else:
                group_atoms.add(outline_array)

        key_elements.setdefault("atom_arrays", []).append(data)

    group_elements.add(group_atoms)
    group_elements.add(group_ghosts)

    group_labels = add_labels(element_groups, key_elements, use_label_arrays)
    group_elements.add(group_labels)

    if len(element_groups["cell_lines"]) > 0:
        cell_line_mat = pjs.LineMaterial(
            linewidth=1,
            color=element_groups["cell_lines"].group_properties["color"])
        cell_line_geo = pjs.LineSegmentsGeometry(positions=[
            el.position.tolist() for el in element_groups["cell_lines"]
        ])
        cell_lines = pjs.LineSegments2(geometry=cell_line_geo,
                                       material=cell_line_mat)
        key_elements["cell_lines"] = cell_lines
        group_elements.add(cell_lines)

    if len(element_groups["bond_lines"]) > 0:
        bond_line_mat = pjs.LineMaterial(
            linewidth=element_groups["bond_lines"].
            group_properties["stroke_width"],
            vertexColors="VertexColors",
        )
        bond_line_geo = pjs.LineSegmentsGeometry(
            positions=[
                el.position.tolist() for el in element_groups["bond_lines"]
            ],
            colors=[[Color(c).rgb for c in el.color]
                    for el in element_groups["bond_lines"]],
        )
        bond_lines = pjs.LineSegments2(geometry=bond_line_geo,
                                       material=bond_line_mat)
        key_elements["bond_lines"] = bond_lines
        group_elements.add(bond_lines)

    group_millers = pjs.Group()
    if len(element_groups["miller_lines"]) or len(
            element_groups["miller_planes"]):
        key_elements["group_millers"] = group_millers

    if len(element_groups["miller_lines"]) > 0:
        miller_line_mat = pjs.LineMaterial(
            linewidth=3,
            vertexColors="VertexColors"  # TODO use stroke_width
        )
        miller_line_geo = pjs.LineSegmentsGeometry(
            positions=[
                el.position.tolist() for el in element_groups["miller_lines"]
            ],
            colors=[[Color(el.stroke_color).rgb] * 2
                    for el in element_groups["miller_lines"]],
        )
        miller_lines = pjs.LineSegments2(geometry=miller_line_geo,
                                         material=miller_line_mat)
        group_millers.add(miller_lines)

    for el in element_groups["miller_planes"]:
        vertices = el.position.tolist()
        faces = [(
            0,
            1,
            2,
            triangle_normal(vertices[0], vertices[1], vertices[2]),
            "black",
            0,
        )]
        if len(vertices) == 4:
            faces.append((
                2,
                3,
                0,
                triangle_normal(vertices[2], vertices[3], vertices[0]),
                "black",
                0,
            ))
        elif len(vertices) != 3:
            raise NotImplementedError("polygons with more than 4 points")
        plane_geom = pjs.Geometry(vertices=vertices, faces=faces)
        plane_mat = pjs.MeshBasicMaterial(
            color=el.fill_color,
            transparent=True,
            opacity=el.fill_opacity,
            side="DoubleSide",
        )
        plane_mesh = pjs.Mesh(geometry=plane_geom, material=plane_mat)
        group_millers.add(plane_mesh)

    group_elements.add(group_millers)

    scene = pjs.Scene(background=None)
    scene.add([group_elements])

    view_width, view_height = canvas_size

    minp, maxp = element_groups.get_position_range()
    # compute a minimum camera distance, that is guaranteed to encapsulate all elements
    camera_dist = maxp[2] + sqrt(maxp[0]**2 + maxp[1]**2) / tan(
        radians(camera_fov / 2))

    camera = pjs.PerspectiveCamera(
        fov=camera_fov,
        position=[0, 0, camera_dist],
        aspect=view_width / view_height,
        zoom=zoom,
    )
    scene.add([camera])
    ambient_light = pjs.AmbientLight(color="lightgray")
    key_elements["ambient_light"] = ambient_light
    direct_light = pjs.DirectionalLight(position=(maxp * 2).tolist())
    key_elements["direct_light"] = direct_light
    scene.add([camera, ambient_light, direct_light])

    camera_control = pjs.OrbitControls(controlling=camera,
                                       screenSpacePanning=True)

    atom_picker = pjs.Picker(controlling=group_atoms, event="dblclick")
    key_elements["atom_picker"] = atom_picker
    material = pjs.SpriteMaterial(
        map=create_arrow_texture(right=False),
        transparent=True,
        depthWrite=False,
        depthTest=False,
    )
    atom_pointer = pjs.Sprite(material=material,
                              scale=(4, 3, 1),
                              visible=False)
    scene.add(atom_pointer)
    key_elements["atom_pointer"] = atom_pointer

    renderer = pjs.Renderer(
        camera=camera,
        scene=scene,
        controls=[camera_control, atom_picker],
        width=view_width,
        height=view_height,
        alpha=True,
        clearOpacity=background_opacity,
        clearColor=background_color,
    )
    return renderer, key_elements