Esempio n. 1
0
    def show(self, camera_position=[2.0, 5.0, 2.0], action=None, geometry=None):

        self.camera.position = camera_position

        children = [p3js.AmbientLight(color='#dddddd'), self.camera]
        children += list(self.geometry)
        if geometry:
            children += geometry

        scene = p3js.Scene(children=children, background="#aaaaaa")

        #gridHelper = p3js.GridHelper(10, 10)
        #scene.add(gridHelper)
        #axesHelper = p3js.AxesHelper(1)
        #axesHelper.exec_three_obj_method('geometry.rotateX', -3.14159 / 2.0)
        #scene.add(axesHelper)

        controls = p3js.OrbitControls(controlling=self.camera)
        controls.target = (2.0, 1.0, -2.0)

        renderer = p3js.Renderer(scene=scene, camera=self.camera, 
                                 controls=[controls],
                                 width=self.width, height=self.height)
        if not action:
            display(renderer)
        else:
            display(renderer, action)
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 __init__(self, *args, **kwargs):
        self._backend_objects = dict(scene=pythreejs.Scene())
        self._clip_scale = 1

        self.z_offset = kwargs.get('translation', (0, 0, 0))[2]

        size = (40, 30)
        (width, height) = size
        dz = np.linalg.norm(size)*self._clip_scale
        self._backend_objects['camera'] = pythreejs.OrthographicCamera(
            -width/2, width/2, height/2, -height/2, 1, 1 + dz, position=(0, 0, 1))
        self._backend_objects['controls'] = pythreejs.OrbitControls(
            self._backend_objects['camera'], target=(0, 0, 0))
        self._backend_objects['scene'].add(self._backend_objects['camera'])
        self._backend_objects['directional_lights'] = []

        (pixel_width, pixel_height) = (width*10, height*10)
        renderer_kwargs = dict(
            width=pixel_width, height=pixel_height, antialias=True,
            **self._backend_objects)
        renderer_kwargs['controls'] = [renderer_kwargs['controls']]
        self._backend_objects['renderer'] = pythreejs.Renderer(**renderer_kwargs)

        super(Scene, self).__init__(*args, **kwargs)
        self._update_canvas_size()

        # directly re-initialize rotation after camera has been set up
        self.rotation = kwargs.get('rotation', (1, 0, 0, 0))
        self.translation = kwargs.get('translation', (0, 0, 0))
Esempio n. 4
0
def plot_voxelgrid_with_pythreejs(voxel_centers, voxel_colors, width, height,
                                  **kwargs):
    if pythreejs is None:
        raise ImportError(
            "pythreejs is needed for plotting with pythreejs backend.")
    if display is None:
        raise ImportError(
            "IPython is needed for plotting with pythreejs backend.")

    centroid, camera_position = get_centroid_and_camera_position(voxel_centers)
    camera = pythreejs.PerspectiveCamera(fov=90,
                                         aspect=width / height,
                                         position=camera_position,
                                         up=[0, 0, 1])
    mesh = get_voxelgrid_pythreejs(voxel_centers, voxel_colors)
    scene = pythreejs.Scene(children=[camera, mesh], background=None)
    controls = pythreejs.OrbitControls(controlling=camera,
                                       target=tuple(centroid))
    camera.lookAt(tuple(centroid))
    renderer = pythreejs.Renderer(scene=scene,
                                  camera=camera,
                                  controls=[controls],
                                  width=width,
                                  height=height)
    display(renderer)
Esempio n. 5
0
 def _renderer_default(self):
     center = tuple(self.ds.domain_center.in_units("code_length").d)
     right = tuple((self.ds.domain_right_edge +
                    (self.ds.domain_right_edge - self.ds.domain_center) *
                    2.0).in_units("code_length").d)
     camera = pythreejs.PerspectiveCamera(
         position=right, fov=20, children=[pythreejs.AmbientLight()])
     scene = pythreejs.Scene(
         children=[camera, pythreejs.AmbientLight(color="#dddddd")] +
         self.grid_views)
     orbit_control = pythreejs.OrbitControls(controlling=camera)
     renderer = pythreejs.Renderer(
         scene=scene,
         camera=camera,
         controls=[orbit_control],
         width=400,
         height=400,
         background="black",
         background_opacity=1,
         antialias=True,
     )
     camera.lookAt(center)
     orbit_control.target = center
     renderer.layout.border = "1px solid darkgrey"
     return renderer
Esempio n. 6
0
    def _ipython_display_(self):
        # This needs to actually display, which is not the same as returning a display.
        cam = pythreejs.PerspectiveCamera(
            position=[25, 35, 100],
            fov=20,
            children=[pythreejs.AmbientLight()],
        )
        children = [cam, pythreejs.AmbientLight(color="#dddddd")]
        material = pythreejs.MeshBasicMaterial(color="#ff0000",
                                               vertexColors="VertexColors",
                                               side="DoubleSide")
        for model in self.components:
            mesh = pythreejs.Mesh(geometry=model.geometry,
                                  material=material,
                                  position=[0, 0, 0])
            children.append(mesh)

        scene = pythreejs.Scene(children=children)

        rendererCube = pythreejs.Renderer(
            camera=cam,
            background="white",
            background_opacity=1,
            scene=scene,
            controls=[pythreejs.OrbitControls(controlling=cam)],
            width=800,
            height=800,
        )

        return rendererCube
Esempio n. 7
0
    def __init__(self, obj, width=512, height=512, textureMap=None, scalarField=None, vectorField=None):
        # Note: subclass's constructor should define
        # self.MeshConstructor and self.isLineMesh, which will
        # determine how the geometry is interpreted.
        if (self.isLineMesh is None):
            self.isLineMesh = False
        if (self.MeshConstructor is None):
            self.MeshConstructor = pythreejs.Mesh

        light = pythreejs.PointLight(color='white', position=[0, 0, 5])
        light.intensity = 0.6
        self.cam = pythreejs.PerspectiveCamera(position = [0, 0, 5], up = [0, 1, 0], aspect=width / height,
                                               children=[light])

        self.avoidRedrawFlicker = False

        self.objects      = pythreejs.Group()
        self.meshes       = pythreejs.Group()
        self.ghostMeshes  = pythreejs.Group() # Translucent meshes kept around by preserveExisting

        self.materialLibrary = MaterialLibrary(self.isLineMesh)

        # Sometimes we do not use a particular attribute buffer, e.g. the index buffer when displaying
        # per-face scalar fields. But to avoid reallocating these buffers when
        # switching away from these cases, we need to preserve the buffers
        # that may have previously been allocated. This is done with the bufferAttributeStash.
        # A buffer attribute, if it exists, must always be attached to the
        # current BufferGeometry or in this stash (but not both!).
        self.bufferAttributeStash = {}

        self.currMesh        = None # The main mesh being viewed
        self.wireframeMesh   = None # Wireframe for the main visualization mesh
        self.pointsMesh      = None # Points for the main visualization mesh
        self.vectorFieldMesh = None

        self.cachedWireframeMaterial = None
        self.cachedPointsMaterial    = None

        self.objects.add([self.meshes, self.ghostMeshes])
        self.shouldShowWireframe = False
        self.scalarField = None
        self.vectorField = None

        self.arrowMaterial = None # Will hold this viewer's instance of the special vector field shader
        self._arrowSize    = 60

        # Camera needs to be part of the scene because the scene light is its child
        # (so that it follows the camera).
        self.scene = pythreejs.Scene(children=[self.objects, self.cam, pythreejs.AmbientLight(intensity=0.5)])

        # Sane trackball controls.
        self.controls = pythreejs.TrackballControls(controlling=self.cam)
        self.controls.staticMoving = True
        self.controls.rotateSpeed  = 2.0
        self.controls.zoomSpeed    = 2.0
        self.controls.panSpeed     = 1.0

        self.renderer = pythreejs.Renderer(camera=self.cam, scene=self.scene, controls=[self.controls], width=width, height=height)
        self.update(True, obj, updateModelMatrix=True, textureMap=textureMap, scalarField=scalarField, vectorField=vectorField)
Esempio n. 8
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. 9
0
 def __initialize_scene(self):
     threejs_items = []
     for drawable in self.drawables:
         threejs_items += drawable.threejs_items
     scene = three.Scene(children=[
         three.AmbientLight(color='white', intensity=1), self.camera,
         *threejs_items
     ])
     return scene
Esempio n. 10
0
def convert_renderer(pv_renderer):
    """Convert a pyvista renderer to a pythreejs renderer."""
    # verify plotter hasn't been closed

    width, height = pv_renderer.width, pv_renderer.height
    pv_camera = pv_renderer.camera
    children = meshes_from_actors(pv_renderer.actors.values(),
                                  pv_camera.focal_point)

    lights = extract_lights_from_renderer(pv_renderer)
    aspect = width / height
    camera = pvcamera_to_threejs_camera(pv_camera, lights, aspect)

    children.append(camera)

    if pv_renderer.axes_enabled:
        children.append(tjs.AxesHelper(0.1))

    scene = tjs.Scene(children=children,
                      background=color_to_hex(pv_renderer.background_color))

    # replace inf with a real value here due to changes in
    # ipywidges==6.4.0 see
    # https://github.com/ipython/ipykernel/issues/771
    inf = 1E20
    orbit_controls = tjs.OrbitControls(
        controlling=camera,
        maxAzimuthAngle=inf,
        maxDistance=inf,
        maxZoom=inf,
        minAzimuthAngle=-inf,
    )

    renderer = tjs.Renderer(
        camera=camera,
        scene=scene,
        alpha=True,
        clearOpacity=0,
        controls=[orbit_controls],
        width=width,
        height=height,
        antialias=pv_renderer.GetUseFXAA(),
    )

    if pv_renderer.has_border:
        bdr_color = color_to_hex(pv_renderer.border_color)
        renderer.layout.border = f'solid {pv_renderer.border_width}px {bdr_color}'

    # for now, we can't dynamically size the render windows.  If
    # unset, the renderer widget will attempt to resize and the
    # threejs renderer will not resize.
    # renderer.layout.width = f'{width}px'
    # renderer.layout.height = f'{height}px'
    return renderer
Esempio n. 11
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. 12
0
 def __init__(self, eye_pos, obj_pos, obj, up=(0, 1, 0)):
     self.camera = three.PerspectiveCamera(
         position=tuple(eye_pos),
         lookAt=tuple(obj_pos),
         fov=30,
     )
     self.camera.up = up
     self.light = three.PointLight(
         color="white",
         position=(-eye_pos[0], eye_pos[1], eye_pos[2]),
     )
     self.obj = obj
     self.scene = three.Scene(children=[self.obj, self.light, self.camera])
Esempio n. 13
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. 14
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. 15
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. 16
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. 17
0
def render(objects=None, camera=None, background="#DDDDDD", enableRotate=True,
           width=0, height=0):

    if isinstance(objects, list):
        children = objects + [camera]
    else:
        try:
            _ = iter(objects)
            children = list(objects) + [camera]
        except TypeError:
            children = [objects, camera]
    scene = p3.Scene(children=children, background=background)
    controller = p3.OrbitControls(controlling=camera, enableRotate=enableRotate)
    # Render the scene into a widget
    renderer = p3.Renderer(camera=camera, scene=scene,
                                     controls=[controller],
                                     width=width,
                                     height=height)
    return renderer
Esempio n. 18
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. 19
0
    def _setup_scene(self, bounding_box, render_size):
        self.min_width = render_size[0]
        self.min_height = render_size[1]
        fov_angle = 60
        if len(bounding_box[0]) == 2:
            lower = np.array([bounding_box[0][0], bounding_box[0][1], 0])
            upper = np.array([bounding_box[1][0], bounding_box[1][1], 0])
            bounding_box = (lower, upper)
        combined_bounds = np.hstack(bounding_box)

        absx = np.abs(combined_bounds[0] - combined_bounds[3])
        not_mathematical_distance_scaling = 1.2
        self.camera_distance = np.sin(
            (90 - fov_angle / 2) * np.pi / 180) * 0.5 * absx / np.sin(
                fov_angle / 2 * np.pi / 180)
        self.camera_distance *= not_mathematical_distance_scaling
        xhalf = (combined_bounds[0] + combined_bounds[3]) / 2
        yhalf = (combined_bounds[1] + combined_bounds[4]) / 2
        zhalf = (combined_bounds[2] + combined_bounds[5]) / 2
        self.mesh_center = (xhalf, yhalf, zhalf)
        self.cam = p3js.PerspectiveCamera(
            aspect=render_size[0] / render_size[1],
            position=[0, 0, 0 + self.camera_distance])
        self.light = p3js.AmbientLight(color='white', intensity=1.0)
        self.scene = p3js.Scene(children=[self.cam, self.light],
                                background='white')
        self.controller = p3js.OrbitControls(
            controlling=self.cam,
            position=[0, 0, 0 + self.camera_distance],
            target=[0, 0, 0])
        self.freeze_camera(True)
        self.renderer = p3js.Renderer(camera=self.cam,
                                      scene=self.scene,
                                      controls=[self.controller],
                                      webgl_version=1,
                                      width=render_size[0],
                                      height=render_size[1])
Esempio n. 20
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. 21
0
    def __init__(self,
                 cmap=None,
                 norm=None,
                 figsize=None,
                 unit=None,
                 log=None,
                 nan_color=None,
                 masks=None,
                 pixel_size=None,
                 tick_size=None,
                 background=None,
                 show_outline=True,
                 extend=None,
                 xlabel=None,
                 ylabel=None,
                 zlabel=None):

        if figsize is None:
            figsize = (config.plot.width, config.plot.height)

        # Figure toolbar
        self.toolbar = PlotToolbar(ndim=3)

        # Prepare colormaps
        self.cmap = cmap
        self.cmap.set_bad(color=nan_color)
        self.scalar_map = cm.ScalarMappable(norm=norm, cmap=self.cmap)
        self.masks_scalar_map = None
        if len(masks) > 0:
            self.masks_cmap = masks["cmap"]
            self.masks_cmap.set_bad(color=nan_color)
            self.masks_scalar_map = cm.ScalarMappable(norm=norm,
                                                      cmap=self.masks_cmap)

        self.axlabels = {"x": xlabel, "y": ylabel, "z": zlabel}
        self.positions = None
        self.pixel_size = pixel_size
        self.tick_size = tick_size
        self.show_outline = show_outline
        self.unit = unit

        # Create the colorbar image
        self.cbar_image = ipw.Image()
        self.cbar_fig, self.cbar = self._create_colorbar(figsize, extend)

        # Create the point cloud material with pythreejs
        self.points_material = self._create_points_material()
        self.points_geometry = None
        self.point_cloud = None
        self.outline = None
        self.axticks = None
        self.camera_reset = {}

        # Define camera
        self.camera = p3.PerspectiveCamera(position=[0, 0, 0],
                                           aspect=config.plot.width /
                                           config.plot.height)

        # Add red/green/blue axes helper
        self.axes_3d = p3.AxesHelper()

        # Create the pythreejs scene
        self.scene = p3.Scene(children=[self.camera, self.axes_3d],
                              background=background)

        # Add camera controller
        self.controls = p3.OrbitControls(controlling=self.camera)

        # Render the scene into a widget
        self.renderer = p3.Renderer(camera=self.camera,
                                    scene=self.scene,
                                    controls=[self.controls],
                                    width=figsize[0],
                                    height=figsize[1])
Esempio n. 22
0
def plot_with_pythreejs(cloud, **kwargs):
    if ipywidgets is None:
        raise ImportError(
            "ipywidgets is needed for plotting with pythreejs backend.")
    if pythreejs is None:
        raise ImportError(
            "pythreejs is needed for plotting with pythreejs backend.")
    if display is None:
        raise ImportError(
            "IPython is needed for plotting with pythreejs backend.")

    colors = get_colors(cloud, kwargs["use_as_color"], kwargs["cmap"])

    ptp = cloud.xyz.ptp()

    children = []
    widgets = []

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

    if kwargs["polylines"]:
        lines = get_polylines_pythreejs(kwargs["polylines"])
        children.extend(lines)

    points = get_pointcloud_pythreejs(cloud.xyz, colors)
    children.append(points)

    initial_point_size = kwargs["initial_point_size"] or ptp / 10
    size = ipywidgets.FloatSlider(value=initial_point_size,
                                  min=0.0,
                                  max=initial_point_size * 10,
                                  step=initial_point_size / 100)
    ipywidgets.jslink((size, 'value'), (points.material, 'size'))
    widgets.append(ipywidgets.Label('Point size:'))
    widgets.append(size)

    if kwargs["scene"]:
        kwargs["scene"].children = [points] + list(kwargs["scene"].children)
    else:
        camera = get_camera_pythreejs(cloud.centroid, cloud.xyz,
                                      kwargs["width"], kwargs["height"])
        children.append(camera)

        controls = [get_orbit_controls(camera, cloud.centroid)]

        scene = pythreejs.Scene(children=children)

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

        display(renderer)

        color = ipywidgets.ColorPicker()
        ipywidgets.jslink((color, 'value'), (scene, 'background'))
        widgets.append(ipywidgets.Label('Background color:'))
        widgets.append(color)

    display(ipywidgets.HBox(children=widgets))

    return scene if kwargs["return_scene"] else None
Esempio n. 23
0
def create_js_scene_view(gcollect,
                         add_objects=True,
                         add_labels=False,
                         gobject_jsmap=None,
                         jslink=False):
    """create PyThreeJS Scene for GeometricCollection
    and one-way link all GeometricObject attributes and creation/deletion

    Properties
    ----------
    gcollect : GeometricCollection
    add_objects: bool 
        add objects to scene
    add_labels : bool
        add object labels to scene
    gobject_jsmap : None or dict
        if None use default gobject->jsobject mapping
    jslink : bool
        if True, where possible, create client side links
        http://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Events.html#The-difference-between-linking-in-the-kernel-and-linking-in-the-client     
    
    Returns
    -------
    scene : pythreejs.Scene
        scene.children = [gobjcontainer,light]
                        
    Examples
    --------
    
    >>> from pandas3js.models import GeometricCollection, Sphere
    >>> collection = GeometricCollection()
    >>> scene = create_js_scene_view(collection,add_objects=True,add_labels=True)
    >>> container = scene.children[0]
    >>> [type(child) for child in container.children]
    []
                        
    >>> sphere = Sphere(id=1)
    >>> collection.add_object(sphere)
    >>> [type(child) for child in container.children]    
    [<class 'traitlets.traitlets.Sprite'>, <class 'traitlets.traitlets.Mesh'>]
                        
    >>> mesh = container.children[1]
    >>> mesh.position
    [0.0, 0.0, 0.0]
                        
    >>> sphere.position = (1,0,0)
    >>> mesh.position
    [1.0, 0.0, 0.0]

    >>> sphere = collection.pop(1)
    >>> [type(child) for child in container.children]
    []
        
    """
    assert isinstance(
        gcollect,
        GeometricCollection), 'gcollect must be a GeometricCollection'

    meshes = []
    for gobject in gcollect.idobjects:
        if add_labels:
            lmesh = create_jslabelmesh_view(gobject,
                                            gobject_jsmap,
                                            jslink=jslink)
            meshes.append(lmesh)
        if add_objects:
            gmesh = create_jsmesh_view(gobject, gobject_jsmap, jslink=jslink)
            meshes.append(gmesh)

    # create dummy parent mesh to house all meshes, so we can use single mouse picker
    # NB: it would be better to use groups https://threejs.org/docs/#api/objects/Group
    # but this is not implemented in pythreejs
    gcontainer = js.Mesh(geometry=js.Geometry(),
                         material=js.BasicMaterial(),
                         position=[0, 0, 0],
                         children=meshes)

    scenelight = js.AmbientLight(color='#777777')
    scene = js.Scene(children=[gcontainer, scenelight])

    def gobjects_changed(change):

        old = set(change.old)
        new = set(change.new)
        removed_objects = old.difference(new)
        added_objects = new.difference(old)

        if removed_objects:
            removed_ids = [o.id for o in removed_objects]
            original_children = []
            for child in gcontainer.children:
                if child.gobject_id not in removed_ids:
                    original_children.append(child)
        else:
            original_children = gcontainer.children

        new_meshes = []
        for gobject in added_objects:
            if add_labels:
                new_meshes.append(
                    create_jslabelmesh_view(gobject,
                                            gobject_jsmap,
                                            jslink=jslink))
            if add_objects:
                new_meshes.append(
                    create_jsmesh_view(gobject, gobject_jsmap, jslink=jslink))

        gcontainer.children = new_meshes + original_children

    gcollect.observe(gobjects_changed, names='idobjects')

    return scene
Esempio n. 24
0
 def _default_scene(self):
     # could be removed when https://github.com/jovyan/pythreejs/issues/176 is solved
     # the default for pythreejs is white, which leads the volume rendering pass to make everything white
     return pythreejs.Scene(background=None)
Esempio n. 25
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. 26
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. 27
0
 def _default_scene(self):
     # return pythreejs.CombinedCamera(fov=46, position=(0, 0, 2), width=400, height=500)
     return pythreejs.Scene()
Esempio n. 28
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. 29
0
def mesh_animation(times, xt, faces):
    """ Animate a mesh from a sequence of mesh vertex positions

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

        Side effects:
            displays rendering of mesh, with animation action

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

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

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

    mesh = THREE.Mesh(geom, matl)

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

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

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

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

        width: int, optional
            Default: 800

        height: int, optional
            Default: 500

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

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

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

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

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

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

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

        colors = colors.astype(np.uint8)

        ptp = self.xyz.ptp()

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

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

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

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

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

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

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

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

            camera.lookAt(tuple(self.centroid))

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

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

            display(renderer)

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

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

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

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

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

            new_PyntCloud = PyntCloud(points)

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

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