示例#1
0
    def callback_f(change):
        """
        This functions implements highlighting and displaying the name 
        of selected faces and edges as well as vertices. You seemingly can't
        select nothing, it only triggers on objects.
        """
        value = picker.object
        value_freecad_name = freecad_name_from_obj3d(value)
        last_value = picker.last_object

        if value is None:
            if not (last_value is None):
                reset_object_highlighting(last_value)
            html.value = "<b>No selection.</b>"
            return

        if isinstance(value, Line):
            if not (last_value is None):
                reset_object_highlighting(last_value)
            value.material.color = so_col_to_hex(HIGHLIGHTING_COLOR)
            html.value = "{} <b>Edge{}</b>".format(value_freecad_name,
                                                   value.edge_index)
            return

        face_index = int(picker.faceIndex)
        part_index = part_index_by_name(get_name(value), part_indices)
        shape_face_index = index_by_face_index(part_index, face_index)

        if not (last_value is None):
            # check for case of selecting the same freecad face
            if (last_value.name == value.name) and (picker.shape_face_index_old
                                                    == shape_face_index):
                return
            reset_object_highlighting(last_value)

        face_indices = value.geometry.attributes["index"].array
        cols_default = value.geometry.default_color
        cols_highlighted = vertices_col_highlight_face(shape_face_index,
                                                       cols_default,
                                                       part_index,
                                                       face_indices)
        value.geometry.attributes["color"].array = cols_highlighted
        value.geometry.attributes["color"].needsUpdate = True

        material = MeshLambertMaterial(vertexColors='VertexColors',
                                       shininess=1)
        material.name = value.material.color
        value.material = material
        picker.shape_face_index_old = shape_face_index
        picker.last_object = value

        html.value = "{} <b>Face{}</b>".format(value_freecad_name,
                                               shape_face_index)
def convert_object_to_pythreejs(object):
    """
    Cases for the conversion
    :return:
    """
    obs = []
    if object["type"] == "spheres":
        for ipos in object["positions"]:
            obj3d = Mesh(
                geometry=SphereBufferGeometry(radius=object["radius"],
                                              widthSegments=32,
                                              heightSegments=16),
                material=MeshLambertMaterial(color=object["color"]),
                position=ipos,
            )
            obs.append(obj3d)
    elif object["type"] == "cylinders":
        for ipos in object["positionPairs"]:
            obj3d = _get_cylinder_from_vec(ipos[0],
                                           ipos[1],
                                           color=object["color"])
            obs.append(obj3d)
    elif object["type"] == "lines":
        for ipos, jpos in zip(object["positions"][::2],
                              object["positions"][1::2]):
            obj3d = _get_line_from_vec(ipos, jpos)
            obs.append(obj3d)
    else:
        warnings.warn(
            f"Primitive type {object['type']} has not been implemented for this renderer."
        )
    return obs
示例#3
0
def virtualHelixMesh(pos1,
                     pos2,
                     radius: float = 1.0,
                     color: str = 'red') -> Mesh:
    pos1 = np.array(pos1, dtype=float)
    pos2 = np.array(pos2, dtype=float)
    delta = pos2 - pos1
    dist = np.linalg.norm(delta)
    c_geometry = CylinderBufferGeometry(radiusTop=radius,
                                        radiusBottom=radius,
                                        height=dist,
                                        radiusSegments=16)
    # print(c_geometry.height)
    v2 = normalize(delta)

    # NOTE default direction in Three.js is the Y direction for geometry
    v1 = np.array((0, 1, 0))

    # Calculate angle between Vectors
    angle = math.atan2(np.dot(np.cross(v1, v2), v1), np.dot(v1, v2))

    normal_vec = normalize(np.cross(v1, v2)).tolist()

    mid_point = (pos2 + pos1) / 2
    xAxis = [mid_point[0], 0, 0]
    yAxis = [0, mid_point[1], 0]
    zAxis = [0, 0, mid_point[2]]

    mesh = Mesh(geometry=c_geometry, material=MeshLambertMaterial(color=color))

    rotm = rotationMatrix(v2)
    mesh.setRotationFromMatrix(threeMatrix(rotm))
    mesh.position = mid_point.tolist()
    return mesh, mid_point
示例#4
0
def convert_object_to_pythreejs(object):
    """
    Cases for the conversion
    :return:
    """
    obs = []
    if object['type'] == 'spheres':
        for ipos in object['positions']:
            obj3d = Mesh(geometry=SphereBufferGeometry(radius=object['radius'],
                                                       widthSegments=32,
                                                       heightSegments=16),
                         material=MeshLambertMaterial(color=object["color"]),
                         position=ipos)
            obs.append(obj3d)
    elif object['type'] == 'cylinders':
        for ipos in object['positionPairs']:
            obj3d = _get_cylinder_from_vec(ipos[0],
                                           ipos[1],
                                           color=object['color'])
            obs.append(obj3d)
    elif object['type'] == 'lines':
        for ipos, jpos in zip(object['positions'][::2],
                              object['positions'][1::2]):
            obj3d = _get_line_from_vec(ipos, jpos)
            obs.append(obj3d)
    return obs
示例#5
0
def pseudomaterial_render(atoms):
    c = cm.get_cmap("plasma")

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

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

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

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

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


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

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

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

    return renderer
示例#6
0
def _get_cylinder_from_vec(v0, v1, radius=0.15, color="#FFFFFF"):
    v0 = np.array(v0)
    v1 = np.array(v1)
    vec = v1 - v0
    mid_point = (v0 + v1) / 2.
    rot_vec = np.cross([0, 1, 0], vec)
    rot_vec_len = np.linalg.norm(rot_vec)
    rot_vec = rot_vec / rot_vec_len
    rot_arg = np.arccos(np.dot([0, 1, 0], vec) / np.linalg.norm(vec))
    new_bond = Mesh(geometry=CylinderBufferGeometry(radiusTop=radius,
                                                    radiusBottom=radius,
                                                    height=np.linalg.norm(v1 -
                                                                          v0),
                                                    radialSegments=12,
                                                    heightSegments=10),
                    material=MeshLambertMaterial(color=color),
                    position=tuple(mid_point))
    rot = R.from_rotvec(rot_arg * rot_vec)
    new_bond.quaternion = tuple(rot.as_quat())
    return new_bond
def _get_spheres(ctk_scene, d_args=None):

    if ctk_scene.phiEnd and ctk_scene.phiStart:
        phi_length = ctk_scene.phiEnd - ctk_scene.phiStart
    else:
        phi_length = np.pi * 2

    return [
        Mesh(
            geometry=SphereBufferGeometry(
                radius=ctk_scene.radius,
                phiStart=ctk_scene.phiStart or 0,
                phiLength=phi_length,
                widthSegments=32,
                heightSegments=32,
            ),
            material=MeshLambertMaterial(color=ctk_scene.color),
            position=tuple(ipos),
        ) for ipos in ctk_scene.positions
    ]
def _get_surface_from_positions(positions, d_args, draw_edges=False):
    # get defaults
    obj_args = update_object_args(d_args, "Surfaces", ["color", "opacity"])
    num_triangle = len(positions) / 3.0
    assert num_triangle.is_integer()
    # make decision on transparency
    if obj_args["opacity"] > 0.99:
        transparent = False
    else:
        transparent = True

    num_triangle = int(num_triangle)
    index_list = [[itr * 3, itr * 3 + 1, itr * 3 + 2]
                  for itr in range(num_triangle)]
    # Vertex ositions as a list of lists
    surf_vertices = BufferAttribute(array=positions, normalized=False)
    # Indices
    surf_indices = BufferAttribute(array=np.array(index_list,
                                                  dtype=np.uint16).ravel(),
                                   normalized=False)
    geometry = BufferGeometry(attributes={
        "position": surf_vertices,
        "index": surf_indices
    })
    new_surface = Mesh(
        geometry=geometry,
        material=MeshLambertMaterial(
            color=obj_args["color"],
            side="DoubleSide",
            transparent=transparent,
            opacity=obj_args["opacity"],
        ),
    )
    if draw_edges == True:
        edges = EdgesGeometry(geometry)
        edges_lines = LineSegments(edges,
                                   LineBasicMaterial(color=obj_args["color"]))
        return new_surface, edges_lines
    else:
        return new_surface, None
def _get_cylinder_from_vec(v0, v1, d_args=None):
    """Draw the cylinder given the two endpoints.
    
    Args:
        v0 (list): one endpoint of line
        v1 (list): other endpoint of line
        d_args (dict): properties of the line (line_width and color)
    
    Returns:
        Mesh: Pythreejs object that displays the cylinders
    """
    obj_args = update_object_args(d_args, "Cylinders", ['radius', 'color'])
    v0 = np.array(v0)
    v1 = np.array(v1)
    vec = v1 - v0
    mid_point = (v0 + v1) / 2.0
    rot_vec = np.cross([0, 1, 0], vec)
    rot_vec_len = np.linalg.norm(rot_vec)
    rot_vec = rot_vec / rot_vec_len
    rot_arg = np.arccos(np.dot([0, 1, 0], vec) / np.linalg.norm(vec))
    new_bond = Mesh(
        geometry=CylinderBufferGeometry(
            radiusTop=obj_args['radius'],
            radiusBottom=obj_args['radius'],
            height=np.linalg.norm(v1 - v0),
            radialSegments=12,
            heightSegments=10,
        ),
        material=MeshLambertMaterial(color=obj_args['color']),
        position=tuple(mid_point),
    )
    rot = R.from_rotvec(rot_arg * rot_vec)
    quat = tuple(rot.as_quat())
    if any(isnan(itr_q) for itr_q in quat):
        new_bond.quaternion = (0, 0, 0, 0)
    else:
        new_bond.quaternion = quat

    return new_bond
示例#10
0
 def __init__(self, color='red', radius=0.025):
     Mesh.__init__(self,
                   geometry=SphereGeometry(radius=radius),
                   material=MeshLambertMaterial(color=color))
示例#11
0
"""
Link up the StructureMoleculeComponent objects to pythreejs
Also includes some helper functions for draw addition objects using pythreejs
"""

from pythreejs import MeshLambertMaterial, Mesh, SphereBufferGeometry, CylinderBufferGeometry, Object3D, LineSegments2, LineSegmentsGeometry, LineMaterial, Scene, AmbientLight, Renderer, OrbitControls, OrthographicCamera, DirectionalLight
from crystal_toolkit.components.structure import StructureMoleculeComponent
from IPython.display import display
from scipy.spatial.transform import Rotation as R
import numpy as np
ball = Mesh(geometry=SphereBufferGeometry(radius=1,
                                          widthSegments=32,
                                          heightSegments=16),
            material=MeshLambertMaterial(color='red'),
            position=[0, 1, 0])


def traverse_scene_object(scene_data, parent=None):
    """
    Recursivesly populate a scene object with tree of children
    :param scene_data:
    :param parent:
    :return:
    """
    for sub_object in scene_data["contents"]:
        if "type" in sub_object.keys():
            parent.add(convert_object_to_pythreejs(sub_object))
        else:
            new_parent = Object3D(name=sub_object["name"])
            if parent is None:
                parent = new_parent
示例#12
0
文件: layers.py 项目: aplbrain/pytri
    def __init__(self,
        mesh: trimesh.Trimesh = None,
        obj: str = None,
        normalize: bool =False,
        color: Union[str,ColorRGB] ="#00bbee",
        alpha: float=1.,
        transform: Union[Callable, None] = None,
        *args,
        **kwargs
        ):
        """
        Add a mesh to the scene.

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

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

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

        if transform is None:
            transform = lambda x: x

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

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

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