def scene2mesh(scene, property=None): """Return a mesh from a scene""" d = Tesselator() indices, vertices, colors, attribute=[], [], [], [] colordict={} count=-1 offset=0 curves = [] for obj in scene: if obj.geometry.isACurve(): curves.append(obj) continue obj.geometry.apply(d) idl = np.array([tuple(index) for index in list(d.discretization.indexList)])+offset pts = [(pt.x, pt.y, pt.z) for pt in list(d.discretization.pointList)] vertices.extend(pts) color = obj.appearance.ambient color = (color.red, color.green, color.blue) if color not in colordict: count += 1 colordict[color] = count offset += len(pts) attribute.extend([colordict[color]]*len(pts)) indices.extend(idl.tolist()) colors=np.array(list(colordict.keys()))/255. if property is not None: property = np.repeat(np.array(property), [3]*len(property)) mesh = k3d.mesh(vertices=vertices, indices=indices, attribute=property, color_map=k3d.basic_color_maps.Jet, color_range=[min(property), max(property)]) elif len(colors) == 1: colorhex = int(matplotlib.colors.rgb2hex(colors[0])[1:], 16) mesh = k3d.mesh(vertices=vertices, indices=indices) mesh.color=colorhex else: color_map = list(zip(list(np.array(list(colordict.values())) / float(max(colordict.values()))), colors[:,0], colors[:,1], colors[:,2])) color_map.sort() #color_map=k3d.basic_color_maps.Jet attribute = list(np.array(attribute)/float(max(attribute))) mesh = k3d.mesh(vertices=vertices, indices=indices, attribute=attribute, color_map=color_map) meshes = [mesh] if curves: meshes.extend([curve2mesh([crv]) for crv in curves]) print("Display %d curves"%len(curves)) return meshes
def _get_k3d_meshes(self, bp): self.m1 = k3d.mesh(bp.mesh.vertices, bp.mesh.faces, wireframe=True, color=int("262626", 16)) self.m2 = k3d.mesh(bp.gmesh.vertices, bp.gmesh.faces, wireframe=True, color=int("ce7500", 16)) self.m3 = k3d.mesh(bp.pmesh.vertices, bp.pmesh.faces, wireframe=True, color=int("3a5587", 16))
def setup_plot(self, pb): X_Ia = np.array( [ [0, 0, 0], #0 [1, 0, 0], #1 [0, 1, 0], #2 [1, 1, 0], #3 [0, 0, 1], #4 [1, 0, 1], #5 [0, 1, 1], #6 [1, 1, 1], #7 ], dtype=np.float_) I_Fi = np.array([ [0, 1, 2], [3, 1, 2], [4, 5, 6], [5, 6, 7], ]) wb_mesh = k3d.mesh(X_Ia.astype(np.float32), I_Fi.astype(np.uint32), color=0x999999, side='double') pb.objects = {'wb_mesh', wb_mesh} pb.plot_fig += wb_mesh
def _add_wireframe_to_fig(self, pb, X_Ia, I_Fi): k3d_mesh_wireframe = k3d.mesh(X_Ia, I_Fi, color=0x000000, wireframe=True) pb.plot_fig += k3d_mesh_wireframe pb.objects[self.WIREFRAME] = k3d_mesh_wireframe
def mesh2k3d(neuron, legendgroup, showlegend, label, color, **kwargs): """Convert MeshNeuron to k3d object.""" # Skip empty neurons if neuron.n_vertices == 0: return [] opacity = 1 if isinstance(color, np.ndarray) and color.ndim == 2: if len(color) == len(neuron.vertices): color = [color_to_int(c) for c in color] color_kwargs = dict(colors=color) else: raise ValueError('Colors must match number of vertices for K3D meshes.') else: c = color_to_int(color) color_kwargs = dict(color=c) if len(color) == 4: opacity = color[3] with warnings.catch_warnings(): warnings.simplefilter("ignore") trace_data = [k3d.mesh(vertices=neuron.vertices.astype('float32'), indices=neuron.faces.astype('uint32'), name=label, flat_shading=False, opacity=opacity, **color_kwargs)] return trace_data
def mtg2mesh(g, property_name): """Return a mesh from a MTG object depending on a specific property""" d = Tesselator() geometry = g.property('geometry') prop = g.property(property_name) vertices, indices, attr = [], [], [] offset = 0 for vid, geom in six.iteritems(geometry): if vid in prop: geom.apply(d) idl = np.array( [tuple(index) for index in list(d.discretization.indexList)]) + offset pts = [(pt.x, pt.y, pt.z) for pt in list(d.discretization.pointList)] vertices.extend(pts) offset += len(pts) indices.extend(idl.tolist()) attr.extend([prop[vid]] * len(pts)) #else: # attr.extend([0]*len(pts)) mesh = k3d.mesh(vertices=vertices, indices=indices, attribute=attr, color_map=k3d.basic_color_maps.Jet) return mesh
def volume2k3d(x, colormap, **kwargs): """Convert Volumes to plotly objects.""" trace_data = [] for i, v in enumerate(x): # Skip empty data if isinstance(v.vertices, np.ndarray): if not v.vertices.any(): continue elif not v.vertices: continue name = getattr(v, 'name', None) c = colormap[i] if len(c) == 4: opacity = c[3] else: opacity = 0.5 with warnings.catch_warnings(): warnings.simplefilter("ignore") trace_data = [k3d.mesh(vertices=v.vertices.astype('float32'), indices=v.faces.astype('uint32'), name=name, color=color_to_int(c[:3]), flat_shading=False, opacity=opacity)] return trace_data
def Icosahedron(origin, size=1): if np.shape(origin) == (3, ): fi = (1 + np.sqrt(5)) / 2 icosahedron_vertices = k3d.points([(1, fi, 0), (1, -fi, 0), (-1, fi, 0), (-1, -fi, 0), (fi, 0, 1), (fi, 0, -1), (-fi, 0, 1), (-fi, 0, -1), (0, 1, fi), (0, 1, -fi), (0, -1, fi), (0, -1, -fi)], point_size=0.1) icosahedron_vertices.positions = np.float32( size * np.array(icosahedron_vertices.positions) + np.array(origin)) icosahedron_mesh = k3d.mesh(icosahedron_vertices.positions, indices=[ 0, 2, 8, 0, 4, 8, 0, 2, 9, 0, 5, 9, 2, 6, 8, 2, 7, 9, 2, 6, 7, 0, 4, 5, 1, 4, 5, 1, 5, 11, 7, 9, 11, 3, 7, 11, 3, 6, 7, 3, 6, 10, 4, 8, 10, 6, 8, 10, 1, 4, 10, 1, 3, 11, 1, 3, 10, 5, 9, 11 ]) else: raise TypeError('Origin attribute should have 3 coordinates.') return [icosahedron_vertices, icosahedron_mesh]
def setup_plot(self, pb): k3d_plot = pb.plot_fig self.X_Ia = np.array( [ [0, 0, 0], #0 [1, 0, 0], #1 [0, 1, 0], #2 [1, 1, 0], #3 [0, 0, 1], #4 [1, 0, 1], #5 [0, 1, 1], #6 [1, 1, 1], #7 ], dtype=np.float_) self.I_Fi = np.array([ [0, 1, 2], [3, 1, 2], [4, 5, 6], [5, 6, 7], ]) wb_mesh = k3d.mesh(self.X_Ia.astype(np.float32), self.I_Fi.astype(np.uint32), color=0x999999, side='double') k3d_plot += wb_mesh pb.objects = {'mesh': wb_mesh}
def tomesh(geometry, d=None): """Return a mesh from a geometry object""" if d is None: d = Tesselator() geometry.apply(d) idl = [tuple(index) for index in list(d.discretization.indexList)] pts = [(pt.x, pt.y, pt.z) for pt in list(d.discretization.pointList)] mesh = k3d.mesh(vertices=pts, indices=idl) return mesh
def illustrate_mesh(vertices, faces, plot=None): if plot is None: plot = k3d.plot() plt_surface = k3d.mesh(vertices, faces, color_map=k3d.colormaps.basic_color_maps.Blues, attribute=vertices[:, 2]) plot += plt_surface return plot
def setup_plot(self, pb): print('analysis: setup_plot') X_Id = self.xdomain.mesh.X_Id if len(self.hist.U_t) == 0: U_1 = np.zeros_like(X_Id) print('analysis: U_I', ) else: U_1 = self.hist.U_t[-1] U_1 = U_1.reshape(-1, self.xdomain.fets.n_nodal_dofs)[:, :3] X1_Id = X_Id + U_1 X1_Id = X1_Id.astype(np.float32) I_Ei = self.xdomain.I_Ei.astype(np.uint32) # Original state mesh wb_mesh_0 = k3d.mesh(self.xdomain.X_Id.astype(np.float32), I_Ei, color=0x999999, opacity=0.5, side='double') pb.plot_fig += wb_mesh_0 pb.objects['wb_mesh_0'] = wb_mesh_0 # Deformed state mesh wb_mesh_1 = k3d.mesh(X1_Id, I_Ei, color_map=k3d.colormaps.basic_color_maps.Jet, attribute=U_1[:, 2], color_range=[np.min(U_1), np.max(U_1)], side='double') pb.plot_fig += wb_mesh_1 pb.objects['wb_mesh_1'] = wb_mesh_1 if self.show_wireframe: k3d_mesh_wireframe = k3d.mesh(X1_Id, I_Ei, color=0x000000, wireframe=True) pb.plot_fig += k3d_mesh_wireframe pb.objects['mesh_wireframe'] = k3d_mesh_wireframe
def visualize_mesh(vertices, faces, flip_axes=False): plot = k3d.plot(name='points', grid_visible=False, grid=(-0.55, -0.55, -0.55, 0.55, 0.55, 0.55)) if flip_axes: vertices[:, 2] = vertices[:, 2] * -1 vertices[:, [0, 1, 2]] = vertices[:, [0, 2, 1]] plt_mesh = k3d.mesh(vertices.astype(np.float32), faces.astype(np.uint32), color=0xd0d0d0) plot += plt_mesh plt_mesh.shader = '3d' plot.display()
def setup_plot(self, pb): X_Id = self.X_Id.astype(np.float32) I_Fi = self.I_Fi.astype(np.uint32) fe_mesh = k3d.mesh(X_Id, I_Fi, color=0x999999, opacity=1.0, side='double') pb.plot_fig += fe_mesh pb.objects['mesh'] = fe_mesh if self.show_wireframe: k3d_mesh_wireframe = k3d.mesh(X_Id, I_Fi, color=0x000000, wireframe=True) pb.plot_fig += k3d_mesh_wireframe pb.objects['mesh_wireframe'] = k3d_mesh_wireframe if self.show_node_labels: self._add_nodes_labels_to_fig(pb, X_Id)
def setup_plot(self, pb): X_Ia = self.X_Ia.astype(np.float32) I_Fi = self.I_Fi.astype(np.uint32) cell_mesh = k3d.mesh(X_Ia, I_Fi, opacity=self.opacity, color=0x999999, side='double') pb.plot_fig += cell_mesh pb.objects[self.K3D_CELL_MESH] = cell_mesh if self.show_wireframe: self._add_wireframe_to_fig(pb, X_Ia, I_Fi) if self.show_node_labels: self._add_nodes_labels_to_fig(pb, self.X_Ia)
def add_cell_to_pb(self, pb, X_Ia, I_Fi, obj_name): plot = pb.plot_fig wb_mesh = k3d.mesh( X_Ia.astype(np.float32), I_Fi.astype(np.uint32), # opacity=0.9, color=0x999999, side='double') rand_color = random.randint(0, 0xFFFFFF) plot += wb_mesh self.k3d_mesh[obj_name] = wb_mesh # wb_points = k3d.points(X_Ia.astype(np.float32), # color=0x999999, # point_size=100) # plot +=wb_points if self.show_node_labels: texts = [] for I, X_a in enumerate(X_Ia): k3d_text = k3d.text('%g' % I, tuple(X_a), label_box=False, size=0.8, color=rand_color) plot += k3d_text texts.append(k3d_text) self.k3d_labels[obj_name] = texts wb_mesh_wireframe = k3d.mesh(X_Ia.astype(np.float32), I_Fi.astype(np.uint32), color=0x000000, wireframe=True) plot += wb_mesh_wireframe self.k3d_wireframe[obj_name] = wb_mesh_wireframe
def visualize_shape_alignment(R=None, t=None): mesh_input = trimesh.load( Path(__file__).parent.parent / "resources" / "mesh_input.obj") mesh_target = trimesh.load( Path(__file__).parent.parent / "resources" / "mesh_target.obj") plot = k3d.plot(name='aligment', grid_visible=False, grid=(-0.55, -0.55, -0.55, 0.55, 0.55, 0.55)) input_vertices = np.array(mesh_input.vertices) if not (R is None or t is None): t_broadcast = np.broadcast_to(t[:, np.newaxis], (3, mesh_input.vertices.shape[0])) input_vertices = (R @ input_vertices.T + t_broadcast).T plt_mesh_0 = k3d.mesh(input_vertices.astype(np.float32), np.array(mesh_input.faces).astype(np.uint32), color=0xd00d0d) plt_mesh_1 = k3d.mesh(np.array(mesh_target.vertices).astype(np.float32), np.array(mesh_target.faces).astype(np.uint32), color=0x0dd00d) plot += plt_mesh_0 plot += plt_mesh_1 plt_mesh_0.shader = '3d' plt_mesh_1.shader = '3d' plot.display()
def setup_plot(self, pb): X_Ia = self.mesh.X_Ia.astype(np.float32) I_Fi = self.mesh.I_Fi.astype(np.uint32) X_Ma = X_Ia[self.bc_J_xyz] self.k3d_fixed_xyz = k3d.points(X_Ma) pb.plot_fig += self.k3d_fixed_xyz X_Ma = X_Ia[self.bc_J_x] self.k3d_fixed_x = k3d.points(X_Ma, color=0x22ffff) pb.plot_fig += self.k3d_fixed_x X_Ma = X_Ia[self.bc_J_F_xyz] self.k3d_load_z = k3d.points(X_Ma, color=0xff22ff) pb.plot_fig += self.k3d_load_z self.k3d_mesh = k3d.mesh(X_Ia, I_Fi, color=0x999999, side='double') pb.plot_fig += self.k3d_mesh
def Octahedron(origin, size=1): if np.shape(origin) == (3, ): octahedron_vertices = k3d.points([(1, 0, 0), (0, 1, 0), (0, 0, 1), (-1, 0, 0), (0, -1, 0), (0, 0, -1)], point_size=0.1) octahedron_vertices.positions = np.float32( size * np.array(octahedron_vertices.positions) + np.array(origin)) octahedron_mesh = k3d.mesh(octahedron_vertices.positions, indices=[ 0, 1, 2, 0, 1, 5, 1, 2, 3, 1, 3, 5, 0, 4, 5, 0, 2, 4, 2, 3, 4, 3, 4, 5 ]) else: raise TypeError('Origin attribute should have 3 coordinates.') return [octahedron_vertices, octahedron_mesh]
def Tetrahedron(origin, size=1): if np.shape(origin) == (3, ): tetrahedron_vertices = k3d.points(positions=[(1, 1, 1), (1, -1, -1), (-1, 1, -1), (-1, -1, 1)], point_size=0.1) tetrahedron_vertices.positions = np.float32( size * np.array(tetrahedron_vertices.positions) + np.array(origin, np.float32)) tetrahedron_mesh = k3d.mesh( tetrahedron_vertices.positions, indices=[0, 1, 2, 0, 1, 3, 1, 2, 3, 0, 2, 3]) else: raise TypeError('Origin attribute should have 3 coordinates.') return [tetrahedron_vertices, tetrahedron_mesh]
def display_3d(K,show_labels=False): """display a 3d simplicial complex using k3d, in jupyter to install it: sudo pip install k3d sudo jupyter nbextension install --py k3d sudo jupyter nbextension enable --py k3d """ import k3d if not isinstance(K.vertices[0] ,Point): raise Exception("Can display only Point-class vertices of dim 3!!!") dim=K.vertices[0].dim if dim != 3: sys.stderr.write("Not yet implemented display in dim = %s\n" % dim ) return None vertices = [v.coords for v in K.vertices] edges = [ s for s in K.simplices[1] ] faces = [] if 2 in K.simplices: faces = [ s for s in K.simplices[2] ] plt=k3d.plot(name='points') plt_points = k3d.points( positions=vertices , point_size=0.05) plt_points.shader ='3dSpecular' plt_points.color = 14 plt += plt_points # now lines: for s in edges: plt_line = k3d.line([vertices[s[0]],vertices[s[1]] ],shader='mesh', width=0.01, color=0xff0000) plt += plt_line # now convert all faces to a mesh plt_mesh = k3d.mesh(vertices,faces,color=0xff, wireframe=False, opacity=0.7, name="Simplicial Complex") plt += plt_mesh # now add the text for P in K.vertices: if show_labels and P.label is not None: plt_text = k3d.text("%s" % repr(P), position = P.coords, color=0x7700,size=1) plt += plt_text #finally display plt.display()
def tomesh(geometry, d=None): """Return a mesh from a geometry object""" isCurve = False if geometry.isACurve(): isCurve = True if d is None: d = Tesselator() if not isCurve else Discretizer() geometry.apply(d) if isCurve: pts = [(pt.x, pt.y, pt.z) for pt in list(d.result.pointList)] mesh = k3d.line(pts, shader='mesh') else: idl = [tuple(index) for index in list(d.discretization.indexList)] pts = [(pt.x, pt.y, pt.z) for pt in list(d.discretization.pointList)] mesh = k3d.mesh(vertices=pts, indices=idl) return mesh
def Cube(origin, size=1): if np.shape(origin) == (3, ): cube_vertices = np.array(list(product([1, -1], [1, -1], [1, -1])), np.float32) cube_vertices = k3d.points(positions=cube_vertices, point_size=0.1) cube_vertices.positions = np.float32(size * cube_vertices.positions + np.array(origin)) cube_mesh = k3d.mesh(cube_vertices.positions, indices=[ 0, 1, 2, 1, 2, 3, 0, 1, 4, 1, 4, 5, 1, 3, 5, 3, 5, 7, 0, 2, 4, 2, 4, 6, 2, 3, 7, 2, 6, 7, 4, 5, 6, 5, 6, 7 ]) else: raise TypeError('Origin attribute should have 3 coordinates.') return [cube_vertices, cube_mesh]
def setup_plot(self, pb): self.pb = pb X_Ia = self.X_Ia.astype(np.float32) I_Fi = self.I_Fi.astype(np.uint32) I_M = self.I_CDij[(0, -1), :, (0, -1), :] _, idx_remap = self.unique_node_map J_M = idx_remap[I_M] X_Ma = X_Ia[J_M.flatten()] k3d_mesh = k3d.mesh(X_Ia, I_Fi, color=0x999999, side='double') pb.objects['k3d_mesh'] = k3d_mesh pb.plot_fig += k3d_mesh if self.show_nodes: self._add_nodes_to_fig(pb, X_Ma) if self.wb_cell.show_node_labels: self._add_nodes_labels_to_fig(pb, X_Ia) if self.show_wireframe: self._add_wireframe_to_fig(pb, X_Ia, I_Fi)
def Dodecahedron(origin, size=1): origin = np.array(origin, dtype=np.float32) if np.shape(origin) == (3, ): fi = (1 + np.sqrt(5)) / 2 dodecahedron_vertices = list(product([-1, 1], [-1, 1], [-1, 1])) dodecahedron_vertices += [(0, fi, 1 / fi), (0, -fi, 1 / fi), (0, -fi, -1 / fi), (0, fi, -1 / fi), (1 / fi, 0, fi), (-1 / fi, 0, fi), (-1 / fi, 0, -fi), (1 / fi, 0, -fi), (fi, 1 / fi, 0), (-fi, 1 / fi, 0), (-fi, -1 / fi, 0), (fi, -1 / fi, 0)] dodecahedron_vertices = np.float32(size * np.array(dodecahedron_vertices) + origin) dodecahedron_vertices = k3d.points(dodecahedron_vertices, point_size=0.1, visible=False) indices = [ 0, 1, 18, 0, 1, 10, 1, 9, 10, 0, 10, 14, 10, 14, 15, 4, 10, 15, 4, 9, 10, 4, 5, 9, 4, 5, 19, 4, 15, 19, 6, 15, 19, 6, 16, 19, 6, 7, 16, 6, 7, 8, 6, 8, 11, 2, 3, 17, 2, 3, 8, 2, 8, 11, 1, 3, 13, 1, 3, 18, 3, 17, 18, 1, 9, 13, 9, 12, 13, 5, 9, 12, 5, 12, 19, 12, 16, 19, 7, 12, 16, 3, 7, 8, 3, 7, 12, 3, 12, 13, 14, 6, 15, 14, 6, 11, 2, 11, 14, 0, 17, 18, 0, 2, 17, 0, 2, 14 ] dodecahedron_mesh = k3d.mesh(dodecahedron_vertices.positions, indices=indices, wireframe=False) else: raise TypeError('Origin attribute should have 3 coordinates.') return [dodecahedron_vertices, dodecahedron_mesh]
def mesh(self): """Return k3d.mesh object of the solid.""" return k3d.mesh(self.vertices, self.indices)
def __init__( self, data, name: str, cs_vis: CoordinateSystemVisualizerK3D, plot: k3d.Plot = None, color: int = RGB_BLACK, visualization_method: str = "auto", show_wireframe: bool = False, ): """Create a 'SpatialDataVisualizer' instance. Parameters ---------- data : numpy.ndarray or weldx.geometry.SpatialData The data that should be visualized name : str Name of the data cs_vis : CoordinateSystemVisualizerK3D An instance of the 'CoordinateSystemVisualizerK3D'. This serves as reference coordinate system for the data and is needed to calculate the correct position of the data plot : k3d.Plot A k3d plotting widget. color : int The RGB color of the coordinate system (affects trace and label) as a 24 bit integer value. visualization_method : str The initial data visualization method. Options are 'point', 'mesh', 'both' and 'auto'. If 'auto' is selected, a mesh will be drawn if triangle data is available and points if not. show_wireframe : bool If 'True', meshes will be drawn as wireframes """ triangles = None if isinstance(data, geo.SpatialData): triangles = data.triangles data = data.coordinates.data self._cs_vis = cs_vis self._label_pos = np.mean(data, axis=0) self._label = None if name is not None: self._label = k3d.text( text=name, position=self._label_pos, reference_point="cc", color=color, size=0.5, label_box=True, ) self._points = k3d.points(data, point_size=0.05, color=color) self._mesh = None if triangles is not None: self._mesh = k3d.mesh(data, triangles, side="double", color=color, wireframe=show_wireframe) self.update_model_matrix() self.set_visualization_method(visualization_method) if plot is not None: plot += self._points if self._mesh is not None: plot += self._mesh if self._label is not None: plot += self._label
import vtkplotter from vtkplotter import settings, Plotter vp = Plotter() import k3d vertices = [ -10, 0, -1, 10, 0, -1, 10, 0, 1, -10, 0, 1, ] indices = [ 0, 1, 3, 1, 2, 3 ] plot = k3d.plot() plot += k3d.mesh(vertices, indices) plot.display() vp = Plotter(screensize=(500,500)) g = vtkplotter.load(vtkplotter.datadir+'timecourse1d/') from vtkplotter import load volume = load("/home/rawkintrevo/gits/sidegrifts/basis-vectors-for-covid-kf/data/case001/axial/") #returns a vtkVolume object show(volume, bg='white')
def __init__( self, data: Union[np.ndarray, geo.SpatialData], name: str, reference_system: str, plot: k3d.Plot = None, color: int = None, visualization_method: str = "auto", show_wireframe: bool = False, ): """Create a ``SpatialDataVisualizer`` instance. Parameters ---------- data : The data that should be visualized name : Name of the data reference_system : Name of the data's reference system plot : A k3d plotting widget. color : The RGB color of the coordinate system (affects trace and label) as a 24 bit integer value. visualization_method : The initial data visualization method. Options are ``point``, ``mesh``, ``both``and ``auto``. If ``auto`` is selected, a mesh will be drawn if triangle data is available and points if not. show_wireframe : If `True`, meshes will be drawn as wireframes """ if not isinstance(data, geo.SpatialData): data = geo.SpatialData(coordinates=data) colors = [] if color is None or isinstance(color, str): if isinstance(color, str): colors = data.attributes[color] color = RGB_GREY if data.triangles is not None: triangles = data.triangles.astype(np.uint32) else: triangles = None self._reference_system = reference_system self._label_pos = data.coordinates.mean(dim=data.additional_dims).data if isinstance(self._label_pos, Q_): self._label_pos = self._label_pos.to(_DEFAULT_LEN_UNIT).m self._label = None if name is not None: self._label = k3d.text( text=name, position=self._label_pos, reference_point="cc", color=color, size=0.5, label_box=True, name=name if name is None else f"{name} (text)", ) coordinates = data.coordinates.data if isinstance(coordinates, Q_): coordinates = coordinates.to(_DEFAULT_LEN_UNIT).m self._points = k3d.points( coordinates, point_size=0.05, color=color, name=name if name is None else f"{name} (points)", ) self._mesh = None if data.triangles is not None: self._mesh = k3d.mesh( coordinates.astype(np.float32).reshape(-1, 3), triangles, side="double", color=color, attribute=colors, color_map=k3d.colormaps.matplotlib_color_maps.Viridis, wireframe=show_wireframe, name=name if name is None else f"{name} (mesh)", ) self.set_visualization_method(visualization_method) if plot is not None: plot += self._points if self._mesh is not None: plot += self._mesh if self._label is not None: plot += self._label self.data = data
def _process_series(self, series): self._init_cyclers() self._fig.auto_rendering = False # clear data for o in self._fig.objects: self._fig.remove_class(o) for ii, s in enumerate(series): if s.is_3Dline and s.is_point: x, y, z, _ = s.get_data() positions = np.vstack([x, y, z]).T.astype(np.float32) a = dict(point_size=0.2, color=self._convert_to_int(next(self._cl))) line_kw = self._kwargs.get("line_kw", dict()) plt_points = k3d.points(positions=positions, **merge({}, a, line_kw)) plt_points.shader = "mesh" self._fig += plt_points elif s.is_3Dline: x, y, z, param = s.get_data() # K3D doesn't like masked arrays, so filled them with NaN x, y, z = [ np.ma.filled(t) if isinstance(t, np.ma.core.MaskedArray) else t for t in [x, y, z] ] vertices = np.vstack([x, y, z]).T.astype(np.float32) # keyword arguments for the line object a = dict( width=0.1, name=s.label if self._kwargs.get("show_label", False) else None, color=self._convert_to_int(next(self._cl)), shader="mesh", ) if self._use_cm: a["attribute"] = (param.astype(np.float32), ) a["color_map"] = next(self._cm) a["color_range"] = [s.start, s.end] line_kw = self._kwargs.get("line_kw", dict()) line = k3d.line(vertices, **merge({}, a, line_kw)) self._fig += line elif (s.is_3Dsurface and (not s.is_complex)) or (s.is_3Dsurface and s.is_complex and (s.real or s.imag or s.abs)): x, y, z = s.get_data() # K3D doesn't like masked arrays, so filled them with NaN x, y, z = [ np.ma.filled(t) if isinstance(t, np.ma.core.MaskedArray) else t for t in [x, y, z] ] # TODO: # Can I use get_vertices_indices also for non parametric surfaces? if s.is_parametric: vertices, indices = get_vertices_indices(x, y, z) vertices = vertices.astype(np.float32) else: x = x.flatten() y = y.flatten() z = z.flatten() vertices = np.vstack([x, y, z]).T.astype(np.float32) indices = Triangulation(x, y).triangles.astype(np.uint32) self._high_aspect_ratio(x, y, z) a = dict( name=s.label if self._kwargs.get("show_label", False) else None, side="double", flat_shading=False, wireframe=False, color=self._convert_to_int(next(self._cl)), ) if self._use_cm: a["color_map"] = next(self._cm) a["attribute"] = z.astype(np.float32) surface_kw = self._kwargs.get("surface_kw", dict()) surf = k3d.mesh(vertices, indices, **merge({}, a, surface_kw)) self._fig += surf elif s.is_3Dvector and self._kwargs.get("streamlines", False): xx, yy, zz, uu, vv, ww = s.get_data() # K3D doesn't like masked arrays, so filled them with NaN xx, yy, zz, uu, vv, ww = [ np.ma.filled(t) if isinstance(t, np.ma.core.MaskedArray) else t for t in [xx, yy, zz, uu, vv, ww] ] magnitude = np.sqrt(uu**2 + vv**2 + ww**2) min_mag = min(magnitude.flatten()) max_mag = max(magnitude.flatten()) import vtk from vtk.util import numpy_support vector_field = np.array( [uu.flatten(), vv.flatten(), ww.flatten()]).T vtk_vector_field = numpy_support.numpy_to_vtk( num_array=vector_field, deep=True, array_type=vtk.VTK_FLOAT) vtk_vector_field.SetName("vector_field") points = vtk.vtkPoints() points.SetNumberOfPoints(s.n2 * s.n1 * s.n3) for i, (x, y, z) in enumerate( zip(xx.flatten(), yy.flatten(), zz.flatten())): points.SetPoint(i, [x, y, z]) grid = vtk.vtkStructuredGrid() grid.SetDimensions([s.n2, s.n1, s.n3]) grid.SetPoints(points) grid.GetPointData().SetVectors(vtk_vector_field) stream_kw = self._kwargs.get("stream_kw", dict()) starts = stream_kw.pop("starts", None) max_prop = stream_kw.pop("max_prop", 500) streamer = vtk.vtkStreamTracer() streamer.SetInputData(grid) streamer.SetMaximumPropagation(max_prop) if starts is None: seeds_points = get_seeds_points(xx, yy, zz, uu, vv, ww) seeds = vtk.vtkPolyData() points = vtk.vtkPoints() for p in seeds_points: points.InsertNextPoint(p) seeds.SetPoints(points) streamer.SetSourceData(seeds) streamer.SetIntegrationDirectionToForward() elif isinstance(starts, dict): if not all([t in starts.keys() for t in ["x", "y", "z"]]): raise KeyError( "``starts`` must contains the following keys: " + "'x', 'y', 'z', whose values are going to be " + "lists of coordinates.") seeds_points = np.array( [starts["x"], starts["y"], starts["z"]]).T seeds = vtk.vtkPolyData() points = vtk.vtkPoints() for p in seeds_points: points.InsertNextPoint(p) seeds.SetPoints(points) streamer.SetSourceData(seeds) streamer.SetIntegrationDirectionToBoth() else: npoints = stream_kw.get("npoints", 200) radius = stream_kw.get("radius", None) center = 0, 0, 0 if not radius: xmin, xmax = min(xx[0, :, 0]), max(xx[0, :, 0]) ymin, ymax = min(yy[:, 0, 0]), max(yy[:, 0, 0]) zmin, zmax = min(zz[0, 0, :]), max(zz[0, 0, :]) radius = max([ abs(xmax - xmin), abs(ymax - ymin), abs(zmax - zmin) ]) center = (xmax - xmin) / 2, (ymax - ymin) / 2, ( zmax - zmin) / 2 seeds = vtk.vtkPointSource() seeds.SetRadius(radius) seeds.SetCenter(*center) seeds.SetNumberOfPoints(npoints) streamer.SetSourceConnection(seeds.GetOutputPort()) streamer.SetIntegrationDirectionToBoth() streamer.SetComputeVorticity(0) streamer.SetIntegrator(vtk.vtkRungeKutta4()) streamer.Update() streamline = streamer.GetOutput() streamlines_points = numpy_support.vtk_to_numpy( streamline.GetPoints().GetData()) streamlines_velocity = numpy_support.vtk_to_numpy( streamline.GetPointData().GetArray("vector_field")) streamlines_speed = np.linalg.norm(streamlines_velocity, axis=1) vtkLines = streamline.GetLines() vtkLines.InitTraversal() point_list = vtk.vtkIdList() lines = [] lines_attributes = [] while vtkLines.GetNextCell(point_list): start_id = point_list.GetId(0) end_id = point_list.GetId(point_list.GetNumberOfIds() - 1) l = [] v = [] for i in range(start_id, end_id): l.append(streamlines_points[i]) v.append(streamlines_speed[i]) lines.append(np.array(l)) lines_attributes.append(np.array(v)) count = sum([len(l) for l in lines]) vertices = np.nan * np.zeros((count + (len(lines) - 1), 3)) attributes = np.zeros(count + (len(lines) - 1)) c = 0 for k, (l, a) in enumerate(zip(lines, lines_attributes)): vertices[c:c + len(l), :] = l attributes[c:c + len(l)] = a if k < len(lines) - 1: c = c + len(l) + 1 skw = dict(width=0.1, shader="mesh", compression_level=9) if self._use_cm and ("color" not in stream_kw.keys()): skw["color_map"] = next(self._cm) skw["color_range"] = [min_mag, max_mag] skw["attribute"] = attributes else: col = stream_kw.pop("color", next(self._cl)) if not isinstance(col, int): col = self._convert_to_int(col) stream_kw["color"] = col self._fig += k3d.line(vertices.astype(np.float32), **merge({}, skw, stream_kw)) elif s.is_3Dvector: xx, yy, zz, uu, vv, ww = s.get_data() # K3D doesn't like masked arrays, so filled them with NaN xx, yy, zz, uu, vv, ww = [ np.ma.filled(t) if isinstance(t, np.ma.core.MaskedArray) else t for t in [xx, yy, zz, uu, vv, ww] ] xx, yy, zz, uu, vv, ww = [ t.flatten().astype(np.float32) for t in [xx, yy, zz, uu, vv, ww] ] # default values qkw = dict(scale=1) # user provided values quiver_kw = self._kwargs.get("quiver_kw", dict()) qkw = merge(qkw, quiver_kw) scale = qkw["scale"] magnitude = np.sqrt(uu**2 + vv**2 + ww**2) vectors = np.array((uu, vv, ww)).T * scale origins = np.array((xx, yy, zz)).T if self._use_cm and ("color" not in quiver_kw.keys()): colormap = next(self._cm) colors = k3d.helpers.map_colors(magnitude, colormap, []) self._handles[ii] = [qkw, colormap] else: col = quiver_kw.get("color", next(self._cl)) if not isinstance(col, int): col = self._convert_to_int(col) colors = col * np.ones(len(magnitude)) self._handles[ii] = [qkw, None] vec_colors = np.zeros(2 * len(colors)) for i, c in enumerate(colors): vec_colors[2 * i] = c vec_colors[2 * i + 1] = c vec_colors = vec_colors.astype(np.uint32) vec = k3d.vectors( origins=origins - vectors / 2, vectors=vectors, colors=vec_colors, ) self._fig += vec elif s.is_complex and s.is_3Dsurface and ( not s.is_domain_coloring): x, y, mag_arg, colors, colorscale = s.get_data() mag, arg = mag_arg[:, :, 0], mag_arg[:, :, 1] x, y, z = [t.flatten() for t in [x, y, mag]] vertices = np.vstack([x, y, z]).T.astype(np.float32) indices = Triangulation(x, y).triangles.astype(np.uint32) self._high_aspect_ratio(x, y, z) a = dict( name=s.label if self._kwargs.get("show_label", False) else None, side="double", flat_shading=False, wireframe=False, color=self._convert_to_int(next(self._cl)), color_range=[-np.pi, np.pi], ) if self._use_cm: colors = colors.reshape((-1, 3)) a["colors"] = [self._rgb_to_int(c) for c in colors] r = [] loc = np.linspace(0, 1, colorscale.shape[0]) colorscale = colorscale / 255 for l, c in zip(loc, colorscale): r.append(l) r += list(c) a["color_map"] = r a["color_range"] = [-np.pi, np.pi] surface_kw = self._kwargs.get("surface_kw", dict()) surf = k3d.mesh(vertices, indices, **merge({}, a, surface_kw)) self._fig += surf else: raise NotImplementedError( "{} is not supported by {}\n".format( type(s), type(self).__name__) + "K3D-Jupyter only supports 3D plots.") xl = self.xlabel if self.xlabel else "x" yl = self.ylabel if self.ylabel else "y" zl = self.zlabel if self.zlabel else "z" self._fig.axes = [xl, yl, zl] if self.title: self._fig += k3d.text2d(self.title, position=[0.025, 0.015], color=0, size=1, label_box=False) self._fig.auto_rendering = True