jupyter-widgets / pythreejs

A Jupyter - Three.js bridge
https://pythreejs.readthedocs.io
Other
936 stars 187 forks source link

D3 selection of objects #235

Closed scottlittle closed 5 years ago

scottlittle commented 5 years ago

Over a year ago, I made this demo for navigating the iris dataset in VR using A-Frame. I used D3 for selecting data points (spheres) and displaying information about them as the focus was on them. Is there any way for me to recreate that using pythreejs, or would that be a whole other project (for instance, 'pyaframejs')?

vidartf commented 5 years ago

You should definitely be able to recreate the demo with threejs. However, I don't think d3 makes sense as it is a framework for working with DOM nodes, and threejs does not represent its objects in the DOM.

If you want to use pythreejs in the notebook, I'm not sure if you can currently get it to work with VR. You should be able to use it with the mouse though.

scottlittle commented 5 years ago

Based on the pythreejs example notebook, this is what I've hacked up so far for selection and display of info on datapoints. If I wanted to display info near the datapoint, would I use TextGeometry to do that?

from pythreejs import *
import numpy as np
from IPython.display import display
from ipywidgets import HTML, Text, Output, VBox
from traitlets import link, dlink

ball_pos = [ [0,0,0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [-1, -1, -1] ]
ball_info = [ 'George','Kelly','Scott','Dave','Bob'  ]

spheres=[]
for pos in ball_pos:
    ball = Mesh(geometry=SphereGeometry(radius=.1, widthSegments=32, heightSegments=24), 
                material=MeshLambertMaterial(color='red'),
                position=pos)
    spheres.append(ball)

g2 = LineSegmentsGeometry(
    positions=[
        [[0, 0, 0], [1, 0, 0]],
        [[0, 0, 0], [0, 1, 0]],
        [[0, 0, 0], [0, 0, 1]],
        [[0, 0, 0], [-1, -1, -1]]
    ],
)
m2 = LineMaterial(linewidth=5, color='blue')
line2 = LineSegments2(g2, m2)

hover_pickers = [None]*len(spheres)        
for i,sphere in enumerate(spheres):
    hover_pickers[i] = Picker(controlling=sphere, event='mousemove')

h = HTML()
def g(change):
    h.value = str(ball_info[picker_id[change['owner'].model_id]]) #where picker_id chosen, display info

picker_id = {}
for i, hover_picker in enumerate(hover_pickers):
    hover_picker.observe( g, names=['point'] )
    picker_id[hover_picker.model_id] = i #associate each picker id with an index

scene = Scene(children=[ *spheres,
    line2,
    DirectionalLight(color='#ccaabb', position=[0,10,0]),
    AmbientLight(color='#cccccc'),
    ])

c = PerspectiveCamera(position=[5, 1, 2])
renderer = Renderer(camera=c, background='black', background_opacity=1, scene=scene, 
                    controls=[OrbitControls(controlling=c), *hover_pickers],
                    width=300, height=300)

display( VBox([renderer,h]) )
scottlittle commented 5 years ago

Here's an update of a 3D graph of Les Miserables characters. I used this Plotly code as inspiration. One of my main complaints is that it can get a bit awkward to navigate.

vidartf commented 5 years ago

From your code, I would say that:

scottlittle commented 5 years ago

Follow up to above code:

ball = Mesh(geometry=sphere_geom, 
            material=MeshStandardMaterial(color=ball_color_dict[ball_color[i]],
                                         opacity=sphere_opacity, transparent=True, reflectivity=0.05,
                                          clearCoat=0.9, clearCoatRoughness=0.95),
            position=pos,
            children=[Sprite(SpriteMaterial( map=TextTexture(size=60, color='black'), sizeAttenuation=False,
                                transparent=True, opacity=0.8, depthWrite=False, depthTest=False), 
                                scale=(.1,.1,.1), center=(0.5,0.1) )
                     ]
           )

In which I updated the text with this (for the i_th ball):

renderer.scene.children[i].children[0].material.map.string ='my text' 
vidartf commented 5 years ago

Thanks for the followup. Is there anything else you are wondering about here, or do you consider this issue as resolved?