Esempio n. 1
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,
     )
Esempio n. 2
0
def view_3js(sheet, coords=['x', 'y', 'z'], **draw_specs):
    """
    Creates a javascript renderer of the edge lines to be displayed
    in Jupyter Notebooks

    Returns
    -------

    renderer: a :class:`pythreejs.pythreejs.Renderer` instance
    lines: a :class:`pythreejs.pythreejs.Line` object

    Example
    -------
    >>> from IPython import display
    >>> renderer, lines = view_3js(eptm)
    >>> display(renderer)
    """

    lines = edge_lines(sheet, coords, **draw_specs)
    scene = py3js.Scene(children=[
        lines,
        py3js.DirectionalLight(color='#ccaabb', position=[0, 5, 0]),
        py3js.AmbientLight(color='#cccccc')
    ])

    c = py3js.PerspectiveCamera(position=[0, 5, 5])
    renderer = py3js.Renderer(camera=c,
                              scene=scene,
                              controls=[py3js.OrbitControls(controlling=c)])
    return renderer, lines
Esempio n. 3
0
def Plot3D(S,size=(800,200),center=(0,0,0), rot=[(pi/3., pi/6., 0 )],scale=1):
    """Function to create 3D interactive visualization widgets in a jupiter 
    notebook

    **ARGUMENTS:**

        ====== =================================================================
        S      System, component or surface to plot
        size   Field of view in mm window shown in the notebook
        center Coordinate of the center of the visualization window
        rot    List of tuples. Each tuple describe an (Rx, Ry, Rz) rotation and
               are applied in order to generate the first view of the window. 
        scale  Scale factor applied to the rendered window
        ====== =================================================================

    **RETURN VALUE**

        pyjs renderer needed to show the image in the jupiter notebook.

    """
    width,height=size
    
    
    light =  py3js.DirectionalLight(color='#ffffff',
                                    intensity=.7,
                                    position=[0, 1000,0])
    alight =  py3js.AmbientLight(color='#777777',)

    
    # Set up a scene and render it:
    #cam = py3js.PerspectiveCamera(position=[0, 0, 500], fov=70, children=[light], aspect=width / height)

    pos = array((0, 0, 500))

    for r in rot:
        pos=dot(rot_z(r[2]),pos)
        pos=dot(rot_y(r[1]),pos)
        pos=dot(rot_x(r[0]),pos)
    
    cam = py3js.OrthographicCamera(-width/2*scale,width/2*scale, height/2*scale,
                                   -height/2*scale,children=[light],
                                   position=list(pos),
                                   zoom=scale)

    if isinstance(S,System):
        c=sys2mesh(S)
    elif isinstance(S,Component):
        c=comp2mesh(S,(0,0,0),(0,0,0))
    else:
        c=surf2mesh(S,(0,0,0),(0,0,0))

        
    scene = py3js.Scene(children=[c, alight,cam],background="#000000")
    oc=py3js.OrbitControls(controlling=cam)
    oc.target=center
    renderer = py3js.Renderer(camera=cam, background='black', background_opacity=1,
                          scene=scene, controls=[oc],width=width*scale, height=height*scale)

    return(renderer)
Esempio n. 4
0
 def __initialize_camera(self, width, height):
     camera_target = np.mean([drawable.center for drawable in self.drawables], axis=0)
     camera_position = tuple(camera_target + [0, 0, np.mean([drawable.scale for drawable in self.drawables])])
     directional_light = three.DirectionalLight(color = '#ffffff', position = [0, 10, 0], intensity = 1)
     camera = three.PerspectiveCamera(
         position=camera_position, aspect=width/height, lookAt=camera_target, fov=50, near=.1, far=20000,
         children=[directional_light]
     )
     return camera
Esempio n. 5
0
    def __init__(self, width=600, height=400):
        light = p3js.DirectionalLight(color='#ffffff', position=[0, 0, 1], intensity=0.5)
        self.camera = p3js.PerspectiveCamera(position=[2.0, 5.0, 2.0], fov=50, children=[light], aspect=width/float(height))
        self.camera.up = (0.0, 0.0, 1.0)

        self.width = 600
        self.height = 400
        self.geometry = []
        self.draw_axes(size=1)
Esempio n. 6
0
def pvlight_to_threejs_light(pvlight):
    """Convert a pyvista headlight into a three.js directional light."""
    if pvlight.is_camera_light or pvlight.is_headlight:
        # extend the position of the light to make "near infinite"
        position = np.array(pvlight.position) * 100000
        return tjs.DirectionalLight(
            color=color_to_hex(pvlight.diffuse_color, True),
            position=position.tolist(),
            intensity=pvlight.intensity,
        )
Esempio n. 7
0
File: scene.py Progetto: zizai/pydy
    def display_jupyter(self, window_size=(800, 600), axes_arrow_length=None):
        """Returns a PyThreeJS Renderer and AnimationAction for displaying and
        animating the scene inside a Jupyter notebook.

        Parameters
        ==========
        window_size : 2-tuple of integers
            2-tuple containing the width and height of the renderer window in
            pixels.
        axes_arrow_length : float
            If a positive value is supplied a red (x), green (y), and blue (z)
            arrows of the supplied length will be displayed as arrows for the
            global axes.

        Returns
        =======
        vbox : widgets.VBox
            A vertical box containing the action (pythreejs.AnimationAction)
            and renderer (pythreejs.Renderer).

        """
        if p3js is None:
            raise ImportError('pythreejs needs to be installed.')

        self._generate_meshes_tracks()

        view_width = window_size[0]
        view_height = window_size[1]

        camera = p3js.PerspectiveCamera(position=[1, 1, 1],
                                        aspect=view_width / view_height)
        key_light = p3js.DirectionalLight()
        ambient_light = p3js.AmbientLight()

        children = self._meshes + [camera, key_light, ambient_light]

        if axes_arrow_length is not None:
            children += [p3js.AxesHelper(size=abs(axes_arrow_length))]

        scene = p3js.Scene(children=children)

        controller = p3js.OrbitControls(controlling=camera)
        renderer = p3js.Renderer(camera=camera,
                                 scene=scene,
                                 controls=[controller],
                                 width=view_width,
                                 height=view_height)

        clip = p3js.AnimationClip(tracks=self._tracks, duration=self.times[-1])
        action = p3js.AnimationAction(p3js.AnimationMixer(scene), clip, scene)

        return widgets.VBox([action, renderer])
Esempio n. 8
0
    def __init__(self, settings):
        self.__update_settings(settings)
        self._light = p3s.DirectionalLight(color='white', position=[0, 0, 1], intensity=0.6)
        self._light2 = p3s.AmbientLight(intensity=0.5)
        self._cam = p3s.PerspectiveCamera(position=[0, 0, 1], lookAt=[0, 0, 0], fov=self.__s["fov"],
                                     aspect=self.__s["width"]/self.__s["height"], children=[self._light])
        self._orbit = p3s.OrbitControls(controlling=self._cam)
        self._scene = p3s.Scene(children=[self._cam, self._light2], background=self.__s["background"])#"#4c4c80"
        self._renderer = p3s.Renderer(camera=self._cam, scene = self._scene, controls=[self._orbit],
                    width=self.__s["width"], height=self.__s["height"], antialias=self.__s["antialias"])

        self.__objects = {}
        self.__cnt = 0
Esempio n. 9
0
def Plot3D(S,
           size=(800, 200),
           center=(0, 0, 0),
           rot=[(pi / 3., pi / 6., 0)],
           scale=1):

    width, height = size

    light = py3js.DirectionalLight(color='#ffffff',
                                   intensity=.7,
                                   position=[0, 1000, 0])
    alight = py3js.AmbientLight(color='#777777', )

    # Set up a scene and render it:
    #cam = py3js.PerspectiveCamera(position=[0, 0, 500], fov=70, children=[light], aspect=width / height)

    pos = array((0, 0, 500))

    for r in rot:
        pos = dot(rot_z(r[2]), pos)
        pos = dot(rot_y(r[1]), pos)
        pos = dot(rot_x(r[0]), pos)

    cam = py3js.OrthographicCamera(-width / 2 * scale,
                                   width / 2 * scale,
                                   height / 2 * scale,
                                   -height / 2 * scale,
                                   children=[light],
                                   position=list(pos),
                                   zoom=scale)

    if isinstance(S, System):
        c = sys2mesh(S)
    elif isinstance(S, Component):
        c = comp2mesh(S, (0, 0, 0), (0, 0, 0))
    else:
        c = surf2mesh(S, (0, 0, 0), (0, 0, 0))

    scene = py3js.Scene(children=[c, alight, cam], background="#000000")
    oc = py3js.OrbitControls(controlling=cam)
    oc.target = center
    renderer = py3js.Renderer(camera=cam,
                              background='black',
                              background_opacity=1,
                              scene=scene,
                              controls=[oc],
                              width=width * scale,
                              height=height * scale)

    return (renderer)
Esempio n. 10
0
 def enable(self, name, auto_value=None, **parameters):
     super(Scene, self).enable(name, auto_value, **parameters)
     if name == 'ambient_light':
         light = pythreejs.AmbientLight('#ffffff', self.get_feature_config(name)['value'])
         self.disable(name, strict=False)
         self._backend_objects['scene'].add(light)
     elif name == 'directional_light':
         # Remove existing lights
         self._remove_lights()
         # Create new lights
         dz = np.linalg.norm(self.size) * self._clip_scale
         for light_vector in np.atleast_2d(
                 self.get_feature_config(name).get('value', DEFAULT_DIRECTIONAL_LIGHTS)):
             position = (-light_vector * dz).tolist()
             light = pythreejs.DirectionalLight(
                 color='#ffffff', position=position, intensity=np.linalg.norm(light_vector))
             self._backend_objects['directional_lights'].append(light)
             self._backend_objects['camera'].add(light)
Esempio n. 11
0
def viewer_cloth(cloth):
    view_width = 800
    view_height = 600
    camera = THREE.PerspectiveCamera(position=[20, 5, 30],
                                     aspect=view_width / view_height)
    key_light = THREE.DirectionalLight(position=[10, 10, 10])
    ambient_light = THREE.AmbientLight()
    axes_helper = THREE.AxesHelper(0.5)

    scene = THREE.Scene()
    controller = THREE.OrbitControls(controlling=camera)
    renderer = THREE.Renderer(camera=camera,
                              scene=scene,
                              controls=[controller],
                              width=view_width,
                              height=view_height)
    scene.children = [cloth, axes_helper, camera, key_light, ambient_light]
    return renderer
Esempio n. 12
0
    def getView(self, regenerateView=False, viewWidth=600, viewHeight=400):
        if regenerateView or self.view is None:
            center = self.model.get_center()
            camera = three.PerspectiveCamera(
                position=(center + np.array([0, 200, 0])).tolist(),
                aspect=viewWidth / viewHeight)
            key_light = three.DirectionalLight(position=[0, 10, 10])
            ambient_light = three.AmbientLight()

            scene = three.Scene(
                children=[self.selectable, camera, key_light, ambient_light])

            three.Picker(controlling=scene, event='mousemove')
            controller = three.OrbitControls(controlling=camera,
                                             screenSpacePanning=True,
                                             target=center.tolist())
            camera.lookAt(center.tolist())

            self.coord_label = HTML('Select beads by double-clicking')
            selIncrButton = Button(description='Increase selection')
            selIncrButton.on_click(self.increaseSelection)
            selDecrButton = Button(description='Decrease selection')
            selDecrButton.on_click(self.decreaseSelection)

            click_picker = three.Picker(controlling=self.selectable,
                                        event='dblclick')
            click_picker.observe(self.selectBead, names=['point'])

            renderer = three.Renderer(camera=camera,
                                      scene=scene,
                                      controls=[controller, click_picker],
                                      width=viewWidth,
                                      height=viewHeight,
                                      antialias=True)

            self.view = VBox([
                self.coord_label, renderer,
                HBox([selDecrButton, selIncrButton])
            ])
        return self.view
Esempio n. 13
0
def Plot3D(S,
           size=(800, 200),
           center=(0, 0, 0),
           rot=[(pi / 3.0, pi / 6.0, 0)],
           scale=1):
    """Function to create 3D interactive visualization widgets in a jupyter
    notebook

    Args:
        S: (:class:`~pyoptools.raytrace.system.System`,
            :class:`~pyoptools.raytrace.component.Component` or
            :class:`~pyoptools.raytrace.component.Component`) Object to plot
        size: (Tuple(float,float)) Field of view in X and Y for the window
            shown in the notebook.
        center: (Tuple(float,float,float) Coordinate of the center of the
            visualization window given in the coordinate system of the object
            to plot.
        rot:   List of tuples. Each tuple describe an (Rx, Ry, Rz) rotation and
               are applied in order to generate the first view of the window.
        scale: (float)  Scale factor applied to the rendered window
    Returns:
        pyjs renderer needed to show the image in the jupiter notebook.

    """
    width, height = size

    light = py3js.DirectionalLight(color="#ffffff",
                                   intensity=0.7,
                                   position=[0, 1000, 0])
    alight = py3js.AmbientLight(color="#777777", )

    # Set up a scene and render it:
    # cam = py3js.PerspectiveCamera(position=[0, 0, 500], fov=70, children=[light], aspect=width / height)

    pos = array((0, 0, 500))

    for r in rot:
        pos = dot(rot_z(r[2]), pos)
        pos = dot(rot_y(r[1]), pos)
        pos = dot(rot_x(r[0]), pos)

    cam = py3js.OrthographicCamera(
        -width / 2 * scale,
        width / 2 * scale,
        height / 2 * scale,
        -height / 2 * scale,
        children=[light],
        position=list(pos),
        zoom=scale,
    )

    if isinstance(S, System):
        c = sys2mesh(S)
    elif isinstance(S, Component):
        c = comp2mesh(S, (0, 0, 0), (0, 0, 0))
    else:
        c = surf2mesh(S, (0, 0, 0), (0, 0, 0))

    scene = py3js.Scene(children=[c, alight, cam], background="#000000")
    oc = py3js.OrbitControls(controlling=cam)
    oc.target = center
    renderer = py3js.Renderer(
        camera=cam,
        background="black",
        background_opacity=1,
        scene=scene,
        controls=[oc],
        width=width * scale,
        height=height * scale,
    )

    return renderer
Esempio n. 14
0
def cqdisplay(result, color='#708090', scale=1.0):
    'display CQ object in a ThreeJS Webgl context'
    # Open stream
    output = StringIO.StringIO()

    # cadquery will stream a ThreeJS JSON (using old v3 schema, which is deprecated)
    exporters.exportShape(result.shape.findSolid().scale(scale), 'TJS', output)

    # store stream to a variable
    contents = output.getvalue()

    # Close stream
    output.close()

    # Overwrite the JSON color portion with user defined color. Disallows NAMED colors
    col = list(matplotlib.colors.hex2color(color))
    old_col_str = '"colorDiffuse" : [0.6400000190734865, 0.10179081114814892, 0.126246120426746]'
    new_col_str = '"colorDiffuse" : ' + str(col)
    new_contents = contents.replace(old_col_str, new_col_str)

    # Take the string and create a proper json object
    contents = json.loads(contents)

    # Vertices and Faces are both flat lists, but the pythreejs module requires list of lists
    old_v = contents['vertices']
    old_f = contents['faces']

    # Splits the list up in 3s, to produce a list of lists representing the vertices
    vertices = [old_v[i:i+3] for i in range(0, len(old_v), 3)]

    # JSON Schema has first position in the face's list reserved to indicate type.
    # Cadquery returns Triangle mesh, so we know that we must split list into lists of length 4
    # 1st entry to indicate triangle, next 3 to specify vertices
    three_faces = [old_f[i:i+4] for i in range(0, len(old_f), 4)]
    faces = []

    # Drop the first entry in the face list
    for entry in three_faces:
        entry.pop(0)
        faces.append(entry)

    # Cadquery does not supply face normals in the JSON,
    # and we cannot use THREE.JS built in 'computefaceNormals'
    # (at least, not easily)
    # Instead, we just calculate the face normals ourselves.
    # It is just the cross product of 2 vectors in the triangle.
    # TODO: see if there is a better way to achieve this result
    face_normals = []

    for entry in faces:
        v_a = np.asarray(vertices[entry[0]])
        v_b = np.asarray(vertices[entry[1]])
        v_c = np.asarray(vertices[entry[2]])

        vec_a = v_b - v_a
        vec_b = v_c - v_a

        cross = np.cross(vec_a, vec_b)

        face_normals.append([cross[0], cross[1], cross[2]])

    # set up geometry
    geom = pythreejs.PlainGeometry(vertices=vertices, faces=faces, faceNormals=face_normals)
    mtl = pythreejs.LambertMaterial(color=color, shading='FlatShading')
    obj = pythreejs.Mesh(geometry=geom, material=mtl)

    # set up scene and camera
    cam_dist = 50
    fov = 35
    cam = pythreejs.PerspectiveCamera(
        position=[cam_dist, cam_dist, cam_dist], fov=fov,
        children=[pythreejs.DirectionalLight(color='#ffffff', position=[-3, 5, 1], intensity=0.45)])
    scn_chld = [
        obj,
        pythreejs.AmbientLight(color='#dddddd')
    ]
    scn = pythreejs.Scene(children=scn_chld)

    render = pythreejs.Renderer(
        width='830'.decode('utf-8'),
        height='553'.decode('utf-8'),
        camera=cam,
        scene=scn,
        controls=[pythreejs.OrbitControls(controlling=cam)]
        )

    return render
Esempio n. 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))
Esempio n. 16
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)
Esempio n. 17
0
def create_jsrenderer(scene,
                      height=400,
                      width=400,
                      background='gray',
                      orthographic=False,
                      camera_position=(0, 0, -10),
                      view=(10, -10, -10, 10),
                      fov=50):
    """
    
    Properties
    ----------
    orthographic : bool
        use orthographic camera (True) or perspective (False) 
    camera_position : tuple
        position of camera in scene
    view : tuple
        view extents: (top, bottom, left, right) (orthographic only)
    fov : float
        camera field of view (perspective only)
    
    Returns
    -------
    camera : pythreejs.Camera
    renderer : pythreejs.Renderer
                      
    Examples
    --------
    
    >>> import pythreejs as js
    >>> scene = js.Scene(children=[js.AmbientLight(color='#777777')])
    >>> camera, renderer = create_jsrenderer(scene,200,200, 'gray', (1,-1,-1,1))
    >>> type(renderer)
    <class 'pythreejs.pythreejs.Renderer'>
    >>> type(camera)
    <class 'pythreejs.pythreejs.OrthographicCamera'>
    
    """

    if orthographic:
        top, bottom, left, right = view
        camera = js.OrthographicCamera(position=camera_position,
                                       up=[0, 0, 1],
                                       top=top,
                                       bottom=bottom,
                                       left=left,
                                       right=right,
                                       near=.1,
                                       far=2000)
    else:
        camera = js.PerspectiveCamera(position=camera_position,
                                      up=[0, 0, 1],
                                      far=2000,
                                      near=.1,
                                      fov=fov,
                                      aspect=width / float(height))
    camera.children = [
        js.DirectionalLight(color='white', position=[3, 5, 1], intensity=0.5)
    ]
    control = js.OrbitControls(controlling=camera)
    renderer = js.Renderer(camera=camera,
                           background=background,
                           background_opacity=.1,
                           height=str(height),
                           width=str(width),
                           scene=scene,
                           controls=[control])
    return camera, renderer
Esempio n. 18
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
Esempio n. 19
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)
Esempio n. 20
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