pygel3d.jupyter_display
This is a module with a function, display, that provides functionality for displaying a Manifold or a Graph as an interactive 3D model in a Jupyter Notebook. It is based on plotly.
1""" This is a module with a function, display, that provides functionality for displaying a 2 Manifold or a Graph as an interactive 3D model in a Jupyter Notebook. It is based on 3 plotly. """ 4from pygel3d import hmesh, graph 5from numpy import array 6import plotly.graph_objs as go 7import plotly.offline as py 8import plotly.express as px 9 10 11EXPORT_MODE = False 12 13def set_export_mode(_exp_mode=True): 14 """ Calling this function will set export mode to true. It is necessary 15 to do so if we wish to export a notebook containing interactive 16 plotly graphics (made with display below) to HTML. In other words, this function 17 should not necessarily be called in normal usage but only when we export to HTML. It is 18 then called once in the beginning of the notebook. However, as a bit of a twist on 19 this story, it appears that if we don't call this function, any call to display must 20 be the last thing that happens in a cell. So, maybe it is best to always call 21 set_export_mode in the beginning of a notebook. 22 """ 23 global EXPORT_MODE 24 EXPORT_MODE=_exp_mode 25 if EXPORT_MODE: 26 py.init_notebook_mode(connected=False) 27 28def display(m,wireframe=True,smooth=True,data=None): 29 """ The display function shows an interactive presentation of the Manifold, m, inside 30 a Jupyter Notebook. wireframe=True means that a wireframe view of the mesh is 31 superimposed on the 3D model. If smooth=True, the mesh is rendered with vertex 32 normals. Otherwise, the mesh is rendered with face normals. If data=None, the 33 mesh is shown in a light grey color. If data contains an array of scalar values 34 per vertex, these are mapped to colors used to color the mesh. Finally, note that 35 m can also be a Graph. In that case the display function just draws the edges as 36 black lines. """ 37 mesh_data = [] 38 if isinstance(m,hmesh.Manifold): 39 xyz = array([ p for p in m.positions()]) 40 m_tri = hmesh.Manifold(m) 41 hmesh.triangulate(m_tri, clip_ear=False) 42 ijk = array([[ idx for idx in m_tri.circulate_face(f,'v')] for f in m_tri.faces()]) 43 mesh = go.Mesh3d(x=xyz[:,0],y=xyz[:,1],z=xyz[:,2], 44 i=ijk[:,0],j=ijk[:,1],k=ijk[:,2],color='#dddddd',flatshading=not smooth) 45 if data is not None: 46 mesh['intensity'] = data 47 mesh['contour'] = {'show': True, 'color': '#ff0000'} 48 mesh_data += [mesh] 49 if wireframe: 50 pos = m.positions() 51 xyze = [] 52 for h in m.halfedges(): 53 if h < m.opposite_halfedge(h): 54 p0 = pos[m.incident_vertex(m.opposite_halfedge(h))] 55 p1 = pos[m.incident_vertex(h)] 56 xyze.append(array(p0)) 57 xyze.append(array(p1)) 58 xyze.append(array([None, None, None])) 59 xyze = array(xyze) 60 trace1=go.Scatter3d(x=xyze[:,0],y=xyze[:,1],z=xyze[:,2], 61 mode='lines', 62 line=dict(color='rgb(125,0,0)', width=1), 63 hoverinfo='none') 64 mesh_data += [trace1] 65 elif isinstance(m,graph.Graph): 66 pos = m.positions() 67 xyze = [] 68 for v in m.nodes(): 69 for w in m.neighbors(v): 70 if v < w: 71 p0 = pos[v] 72 p1 = pos[w] 73 xyze.append(array(p0)) 74 xyze.append(array(p1)) 75 xyze.append(array([None, None, None])) 76 xyze = array(xyze) 77 trace1=go.Scatter3d(x=xyze[:,0],y=xyze[:,1],z=xyze[:,2], 78 mode='lines', 79 line=dict(color='rgb(0,0,0)', width=1), 80 hoverinfo='none') 81 mesh_data += [trace1] 82 83 84 lyt = go.Layout(width=850,height=800) 85 lyt.scene.aspectmode="data" 86 if EXPORT_MODE: 87 py.iplot(dict(data=mesh_data,layout=lyt)) 88 else: 89 return go.FigureWidget(mesh_data,lyt)
14def set_export_mode(_exp_mode=True): 15 """ Calling this function will set export mode to true. It is necessary 16 to do so if we wish to export a notebook containing interactive 17 plotly graphics (made with display below) to HTML. In other words, this function 18 should not necessarily be called in normal usage but only when we export to HTML. It is 19 then called once in the beginning of the notebook. However, as a bit of a twist on 20 this story, it appears that if we don't call this function, any call to display must 21 be the last thing that happens in a cell. So, maybe it is best to always call 22 set_export_mode in the beginning of a notebook. 23 """ 24 global EXPORT_MODE 25 EXPORT_MODE=_exp_mode 26 if EXPORT_MODE: 27 py.init_notebook_mode(connected=False)
Calling this function will set export mode to true. It is necessary to do so if we wish to export a notebook containing interactive plotly graphics (made with display below) to HTML. In other words, this function should not necessarily be called in normal usage but only when we export to HTML. It is then called once in the beginning of the notebook. However, as a bit of a twist on this story, it appears that if we don't call this function, any call to display must be the last thing that happens in a cell. So, maybe it is best to always call set_export_mode in the beginning of a notebook.
29def display(m,wireframe=True,smooth=True,data=None): 30 """ The display function shows an interactive presentation of the Manifold, m, inside 31 a Jupyter Notebook. wireframe=True means that a wireframe view of the mesh is 32 superimposed on the 3D model. If smooth=True, the mesh is rendered with vertex 33 normals. Otherwise, the mesh is rendered with face normals. If data=None, the 34 mesh is shown in a light grey color. If data contains an array of scalar values 35 per vertex, these are mapped to colors used to color the mesh. Finally, note that 36 m can also be a Graph. In that case the display function just draws the edges as 37 black lines. """ 38 mesh_data = [] 39 if isinstance(m,hmesh.Manifold): 40 xyz = array([ p for p in m.positions()]) 41 m_tri = hmesh.Manifold(m) 42 hmesh.triangulate(m_tri, clip_ear=False) 43 ijk = array([[ idx for idx in m_tri.circulate_face(f,'v')] for f in m_tri.faces()]) 44 mesh = go.Mesh3d(x=xyz[:,0],y=xyz[:,1],z=xyz[:,2], 45 i=ijk[:,0],j=ijk[:,1],k=ijk[:,2],color='#dddddd',flatshading=not smooth) 46 if data is not None: 47 mesh['intensity'] = data 48 mesh['contour'] = {'show': True, 'color': '#ff0000'} 49 mesh_data += [mesh] 50 if wireframe: 51 pos = m.positions() 52 xyze = [] 53 for h in m.halfedges(): 54 if h < m.opposite_halfedge(h): 55 p0 = pos[m.incident_vertex(m.opposite_halfedge(h))] 56 p1 = pos[m.incident_vertex(h)] 57 xyze.append(array(p0)) 58 xyze.append(array(p1)) 59 xyze.append(array([None, None, None])) 60 xyze = array(xyze) 61 trace1=go.Scatter3d(x=xyze[:,0],y=xyze[:,1],z=xyze[:,2], 62 mode='lines', 63 line=dict(color='rgb(125,0,0)', width=1), 64 hoverinfo='none') 65 mesh_data += [trace1] 66 elif isinstance(m,graph.Graph): 67 pos = m.positions() 68 xyze = [] 69 for v in m.nodes(): 70 for w in m.neighbors(v): 71 if v < w: 72 p0 = pos[v] 73 p1 = pos[w] 74 xyze.append(array(p0)) 75 xyze.append(array(p1)) 76 xyze.append(array([None, None, None])) 77 xyze = array(xyze) 78 trace1=go.Scatter3d(x=xyze[:,0],y=xyze[:,1],z=xyze[:,2], 79 mode='lines', 80 line=dict(color='rgb(0,0,0)', width=1), 81 hoverinfo='none') 82 mesh_data += [trace1] 83 84 85 lyt = go.Layout(width=850,height=800) 86 lyt.scene.aspectmode="data" 87 if EXPORT_MODE: 88 py.iplot(dict(data=mesh_data,layout=lyt)) 89 else: 90 return go.FigureWidget(mesh_data,lyt)
The display function shows an interactive presentation of the Manifold, m, inside a Jupyter Notebook. wireframe=True means that a wireframe view of the mesh is superimposed on the 3D model. If smooth=True, the mesh is rendered with vertex normals. Otherwise, the mesh is rendered with face normals. If data=None, the mesh is shown in a light grey color. If data contains an array of scalar values per vertex, these are mapped to colors used to color the mesh. Finally, note that m can also be a Graph. In that case the display function just draws the edges as black lines.