def axes(max_dist, axis_rad=0.25, axis_color='yellow'): """ Generate X, Y, Z axes of length max_width in the form of a pythreejs Line object. Parameters ---------- max_dist : float maximum extent of grid from origin in each dimension axis_rad : float radius of cylinder representing each axis (default: 0.25) axis_color : color color the axes are drawn in (default: 'yellow') Returns ------- Xaxis, Yaxis, Zaxis : pythreejs.Mesh*3 Three pythreejs Mesh objects representing the x, y, and z axes. """ Xaxis = p3j.Mesh(geometry=p3j.CylinderBufferGeometry(radiusTop=axis_rad, radiusBottom=axis_rad, height=max_dist, radiusSegments=12, heightSegments=1, openEnded=False, thetaStart=0, thetaLength=2*np.pi), material=p3j.MeshBasicMaterial(color=axis_color), position=[max_dist/2, 0, 0]) Xaxis.rotateZ(np.pi/2) Yaxis = p3j.Mesh(geometry=p3j.CylinderBufferGeometry(radiusTop=axis_rad, radiusBottom=axis_rad, height=max_dist, radiusSegments=12, heightSegments=1, openEnded=False, thetaStart=0, thetaLength=2*np.pi), material=p3j.MeshBasicMaterial(color=axis_color), position=[0, max_dist/2, 0]) Zaxis = p3j.Mesh(geometry=p3j.CylinderBufferGeometry(radiusTop=axis_rad, radiusBottom=axis_rad, height=max_dist, radiusSegments=12, heightSegments=1, openEnded=False, thetaStart=0, thetaLength=2*np.pi), material=p3j.MeshBasicMaterial(color=axis_color), position=[0, 0, max_dist/2]) Zaxis.rotateX(np.pi/2) return Xaxis, Yaxis, Zaxis
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
def add_view_frustum(): position = np.array(lm_camera_params['eye']) center = np.array(lm_camera_params['center']) up = np.array(lm_camera_params['up']) aspect = lm_camera_params['aspect'] fov = math.radians(lm_camera_params['vfov']) M = lookat_matrix(position, center, up) z = 5 half_fov = fov * .5 y = math.tan(half_fov) * z x = aspect * y p = list(position) p1 = list(position + np.dot(M, [-x, -y, -z])) p2 = list(position + np.dot(M, [x, -y, -z])) p3 = list(position + np.dot(M, [x, y, -z])) p4 = list(position + np.dot(M, [-x, y, -z])) # Add mesh geom = three.Geometry( vertices=[p, p1, p2, p, p2, p3, p, p3, p4, p, p4, p1]) mat = three.MeshBasicMaterial(color='#00ff00', wireframe=True, side='DoubleSide') mesh = three.Line(geometry=geom, material=mat) scene.add(mesh)
def xyplane(max_dist, grid_space): """ Generates and returns two pythreejs items: a mesh of a flat surface and a SurfaceGrid object, both representing the xy plane. NOTE: max_dist will be rounded UP to next grid_space position (e.g. if yoru submit a max_width of 38 but a grid_space of 5, the max_width will be silently rounded up to 40 to allow an integer number of grids). Keyword arguments: max_dist (float): Maximum extent of grid from origin in each dimension grid_space (float): The grid spacing in system units. Parameters ---------- max_dist : float maximum extent of grid from origin in each dimension grid_space : float the grid spacing in system units. Returns ------- surface : pythreejs.Mesh a pythreejs Mesh object representing the xy plane. surf_grid : pythreejs.SurfaceGrid a pythreejs SurfaceGrid object for the grid on the xy plane. """ # Determine the gridsize to use, adding one additional step if necessary x_steps = int(np.ceil(max_dist / grid_space)) xmax = x_steps * grid_space # Number of vertices (subtract one for number of boxes shown) nx, ny = (2 * x_steps + 1, 2 * x_steps + 1) x = np.linspace(-xmax, xmax, nx) y = np.linspace(-xmax, xmax, ny) xx, yy = np.meshgrid(x, y) z = 0 * xx + 0 * yy # Generate the 3D surface and surface grid to return surf_g = p3j.SurfaceGeometry(z=list(z[::-1].flat), width=2 * xmax, height=2 * xmax, width_segments=nx - 1, height_segments=ny - 1) surface_material = p3j.MeshBasicMaterial(color='darkslategrey', transparent=True, opacity=0.5) surf = p3j.Mesh(geometry=surf_g, material=surface_material) grid_material = p3j.LineBasicMaterial(color='grey') # To avoid overlap, lift grid slightly above the plane scaling # by size of grid surfgrid = p3j.SurfaceGrid(geometry=surf_g, material=grid_material, position=[0, 0, 1e-2 * max_dist]) return surf, surfgrid
def OldStarMesh(temp=Te_Sun, rad=1, scale=(1, 1, 1), pos=[0, 0, 0]): """ This function creates a pythreejs object that represents a star using a texture based on public domain STEREO Heliographic map made with images taken of the Sun on Dec. 30, 2011. Image downloaded from https://stereo.gsfc.nasa.gov/360blog/ and had its brightness and resolution rescaled. Parameters ---------- temp : float temperature of star in Kelvin (default 5777) rad : float radius of the star in system units (default 1) scale : tuple pythreejs scale in each dimension as tuple (default (1, 1, 1) ) pos : list three-dimensional position as list (default [0, 0, 0] ) Returns ------- star : pythreejs.Mesh a spherical pythreejs Mesh object representing a star """ # Check is position is a list if isinstance(pos, list): # Check if this is a list of 3 items if (len(pos) != 3): raise TypeError('pos passed to StarMesh must be list of 3 numbers') # Check that all the items in the list are numbers for this_pos in pos: try: i = float(this_pos) except ValueError: raise TypeError('ValueError: pos contains list item that is not a number.') else: raise TypeError('pos passed to StarMesh must be list of 3 numbers') # Check is scale is a tuple if isinstance(scale, tuple): if (len(scale) != 3): raise TypeError('scale passed to StarMesh must be tuple of 3 numbers') else: raise TypeError('scale must be a tuple') # Define color and texture of star surface hexcolor = tc.rgb2hex(tc.temp2rgb(float(temp)))[0] StarTexture = p3j.ImageTexture(imageUri='images/sun_surface.jpg') # Create sphere using MeshBasicMaterial (which is unaffected by lighting) StarSurface = p3j.MeshBasicMaterial(color=hexcolor, map=StarTexture) StarGeom = p3j.SphereBufferGeometry(radius=rad, widthSegments=32, heightSegments=16) return p3j.Mesh(geometry=StarGeom, material=StarSurface, position=pos, scale=scale)
def _create_mesh(geometry, color, wireframe, position): if wireframe: edges = p3.EdgesGeometry(geometry) mesh = p3.LineSegments(geometry=edges, material=p3.LineBasicMaterial(color=color)) else: material = p3.MeshBasicMaterial(color=color) mesh = p3.Mesh(geometry=geometry, material=material) mesh.position = tuple(position.value) return mesh
def mesh(self): import numpy as np import pythreejs as js wireframe = self.view_data.get('wireframe', False) def triangles(polygon): points = polygon.points return [(points[0], points[ix], points[ix + 1]) for ix in range(1, len(polygon.points) - 1)] def _ba(vs): points = np.array(vs, dtype=np.float32) return js.BufferAttribute(array=points, normalized=False) vertices = [ list(p.xyz) for polygon in self.polygons for t in triangles(polygon) for p in t ] normals = [ list(polygon.plane.normal.xyz) for polygon in self.polygons for t in triangles(polygon) for p in t ] geometry = js.BufferGeometry( attributes={ 'position': _ba(vertices), 'normal': _ba(normals) }, ) if not wireframe: color = self.view_data.get('color', 'white') material = material=js.MeshLambertMaterial(color=color) opacity = self.view_data.get('opacity') if opacity is not None: material.opacity = opacity material.transparent = True return js.Mesh(geometry, material) else: color = self.view_data.get('color', '#00ff00') material = js.MeshBasicMaterial(color=color, wireframe=True) return js.Mesh(geometry, material)
def display_portal(th_scene, portal): """Display portal.""" def portal_vertices(portal): p1 = np.array(portal[0]) p2 = np.array(portal[1]) p4 = np.array(portal[2]) p3 = p1 + (p2 - p1) + (p4 - p1) return [p1, p2, p3, p1, p3, p4] ps_attr = three.BufferAttribute(array=portal_vertices(portal), normalized=False) geom = three.BufferGeometry(attributes={'position': ps_attr}) mat = three.MeshBasicMaterial(color='#ff0000', transparent=True, opacity=0.1, side='DoubleSide') mesh = three.Mesh(geometry=geom, material=mat) th_scene.add(mesh)
def add_lm_scene_mesh(): # Default material mat_default = three.MeshBasicMaterial(color='#000000', wireframe=True, transparent=True, opacity=0.2, depthTest=False) # Convert lm mesh def traverse_func(node, trans): # Underlying mesh mesh = node.primitive.mesh if mesh is None: return # Iterate through all triangles vs = [] def process_triangle(face_index, tri): vs.append(list(tri.p1.p)) vs.append(list(tri.p2.p)) vs.append(list(tri.p3.p)) mesh.foreach_triangle(process_triangle) # Create geometry ps_attr = three.BufferAttribute(array=vs, normalized=False) geom = three.BufferGeometry(attributes={'position': ps_attr}) # Create mesh mesh = three.Mesh(geometry=geom, material=mat_default) mesh.matrixAutoUpdate = False mesh.matrix = trans.T.flatten().tolist() scene.add(mesh) lm_scene.traverse_primitive_nodes(traverse_func)
def StarMesh(temp=Te_Sun, rad=1, scale=(1, 1, 1), pos=[0, 0, 0]): """ This function creates a pythreejs object that represents a star using a set of nested spheres that are partly transparent to simulate limb darkening. Parameters ---------- temp : float temperature of star in Kelvin (default 5777) rad : float radius of the star in system units (default 1) scale : tuple pythreejs scale in each dimension as tuple (default (1, 1, 1) ) pos : list three-dimensional position as list (default [0, 0, 0] ) Returns ------- star : pythreejs.Mesh a spherical pythreejs Mesh object representing a star """ # Check is position is a list if isinstance(pos, list): # Check if this is a list of 3 items if (len(pos) != 3): raise TypeError('pos passed to StarMesh must be list of 3 numbers') # Check that all the items in the list are numbers for this_pos in pos: try: i = float(this_pos) except ValueError: raise TypeError( 'ValueError: pos contains list item that is not a number.') else: raise TypeError('pos passed to StarMesh must be list of 3 numbers') # Check is scale is a tuple if isinstance(scale, tuple): if (len(scale) != 3): raise TypeError( 'scale passed to StarMesh must be tuple of 3 numbers') else: raise TypeError('scale must be a tuple') # Define color of star surface hexcolor = tc.rgb2hex(tc.temp2rgb(float(temp)))[0] # Number of transparent layers to use to build star layers = 20 # Radial scaling drad = 0.97 # Starting resolution N_azi, N_pol = 32, 16 # Layer opacity tau = 0.4 # Radii to use radii = rad * drad**np.array(range(layers - 1, -1, -1)) # 3D object to represent star star = p3j.Object3D() # Build the object from inside out for i in range(layers): # Tweak number of vertices in sphere up for the outer surface sphere if (i > (layers - 2)): N_azi *= 2 N_pol *= 2 geom = p3j.SphereBufferGeometry(radius=radii[i], widthSegments=N_azi, heightSegments=N_pol, renderOrder=-i) material = p3j.MeshBasicMaterial(color=hexcolor, transparent=True, opacity=tau) star.add(p3j.Mesh(geom, material)) # Set the position and scale of this mesh star.position = pos star.scale = scale return star
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))
def to_surf_mesh(actor, surf, mapper, prop, add_attr={}): """Convert a pyvista surface to a buffer geometry. General Notes ------------- * THREE.BufferGeometry expects position and index attributes representing a triangulated mesh points and face indices or just a position array representing individual faces of a mesh. * The normals attribute is needed for physically based rendering, but not for the other mesh types. * Colors must be a RGB array with one value per point. Shading Notes ------------- To match VTK, the following materials are used to match VTK's shading: * MeshPhysicalMaterial when physically based rendering is enabled * MeshPhongMaterial when physically based rendering is disabled, but lighting is enabled. * MeshBasicMaterial when lighting is disabled. """ # convert to an all-triangular surface if surf.is_all_triangles(): trimesh = surf else: trimesh = surf.triangulate() position = array_to_float_buffer(trimesh.points) # convert to minimum index type face_ind = trimesh.faces.reshape(-1, 4)[:, 1:] index = cast_to_min_size(face_ind, trimesh.n_points) attr = { 'position': position, 'index': index, } if prop.GetInterpolation(): # something other than flat shading attr['normal'] = buffer_normals(trimesh) # extract point/cell scalars for coloring colors = None scalar_mode = mapper.GetScalarModeAsString() if scalar_mode == 'UsePointData': colors = map_scalars(mapper, trimesh.point_data.active_scalars) elif scalar_mode == 'UseCellData': # special handling for RGBA if mapper.GetColorMode() == 2: scalars = trimesh.cell_data.active_scalars.repeat(3, axis=0) scalars = scalars.astype(np.float32, copy=False) colors = scalars[:, :3] / 255 # ignore alpha else: # must repeat for each triangle scalars = trimesh.cell_data.active_scalars.repeat(3) colors = map_scalars(mapper, scalars) position = array_to_float_buffer(trimesh.points[face_ind]) attr = {'position': position} # add colors to the buffer geometry attributes if colors is not None: attr['color'] = array_to_float_buffer(colors) # texture coordinates t_coords = trimesh.active_t_coords if t_coords is not None: attr['uv'] = array_to_float_buffer(t_coords) # TODO: Convert PBR textures # base_color_texture = prop.GetTexture("albedoTex") # orm_texture = prop.GetTexture("materialTex") # anisotropy_texture = prop.GetTexture("anisotropyTex") # normal_texture = prop.GetTexture("normalTex") # emissive_texture = prop.GetTexture("emissiveTex") # coatnormal_texture = prop.GetTexture("coatNormalTex") if prop.GetNumberOfTextures(): # pragma: no cover warnings.warn( 'pythreejs converter does not support PBR textures (yet).') # create base buffer geometry surf_geo = tjs.BufferGeometry(attributes=attr) # add texture to the surface buffer if available texture = actor.GetTexture() tjs_texture = None if texture is not None: wrapped_tex = pv.wrap(texture.GetInput()) data = wrapped_tex.active_scalars dim = (wrapped_tex.dimensions[0], wrapped_tex.dimensions[1], data.shape[1]) data = data.reshape(dim) fmt = "RGBFormat" if data.shape[1] == 3 else "RGBAFormat" # Create data texture and catch invalid warning with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="Given trait value dtype") tjs_texture = tjs.DataTexture(data=data, format="RGBFormat", type="UnsignedByteType") # these attributes are always used regardless of the material shared_attr = { 'vertexColors': get_coloring(mapper, trimesh), 'wireframe': prop.GetRepresentation() == 1, 'opacity': prop.GetOpacity(), 'wireframeLinewidth': prop.GetLineWidth(), # 'side': 'DoubleSide' # enabling seems to mess with textures } if colors is None: shared_attr['color'] = color_to_hex(prop.GetColor()) if tjs_texture is not None: shared_attr['map'] = tjs_texture else: shared_attr['side'] = 'DoubleSide' if prop.GetOpacity() < 1.0: shared_attr['transparent'] = True if prop.GetInterpolation() == 3: # using physically based rendering material = tjs.MeshPhysicalMaterial(flatShading=False, roughness=prop.GetRoughness(), metalness=prop.GetMetallic(), reflectivity=0, **shared_attr, **add_attr) elif prop.GetLighting(): # specular disabled to fix lighting issues material = tjs.MeshPhongMaterial( shininess=0, flatShading=prop.GetInterpolation() == 0, specular=color_to_hex((0, 0, 0)), reflectivity=0, **shared_attr, **add_attr) else: # no lighting material = tjs.MeshBasicMaterial(**shared_attr, **add_attr) return tjs.Mesh(geometry=surf_geo, material=material)
def plot_2d(x, y, data, cmap="viridis", vmin=None, vmax=None): # if len(x) != len(y): # raise RuntimeError("bad shape") N = data.size dx = config.figure["width"] dy = config.figure["height"] xe = centers_to_edges(x) ye = centers_to_edges(y) xmin = np.amin(xe) ymin = np.amin(ye) scale_x = dx / (np.amax(xe) - xmin) scale_y = dy / (np.amax(ye) - ymin) # # x_grid, y_grid = np.meshgrid((x - xmin) * scale_x, (y - ymin) * scale_y, indexing="ij") # y_grid, x_grid = np.meshgrid((y - ymin) * scale_y, (x - xmin) * scale_x, indexing="ij") # pixel_size_x = (xe[1] - xe[0]) * scale_x # pixel_size_y = (ye[1] - ye[0]) * scale_y # pts = np.zeros([N, 3], dtype=np.float32) # pts[:, 0] = x_grid.flatten() # pts[:, 1] = y_grid.flatten() # pts = p3.BufferAttribute(array=det_pos) scalar_map = get_cmap(data=None, cmap="viridis", log=False, vmin=None, vmax=None) colors = scalar_map.to_rgba(data).astype(np.float32) # colors = p3.BufferAttribute( # array=scalar_map.to_rgba(data).astype(np.float32)) nx = xe.shape[0] - 1 ny = ye.shape[0] - 1 npixels = nx * ny arr_x = np.zeros(2 * nx, dtype=np.float32) arr_x[::2] = xe[:-1] arr_x[1::2] = xe[1:] arr_y = np.zeros(2 * ny, dtype=np.float32) arr_y[::2] = ye[:-1] arr_y[1::2] = ye[1:] x_grid, y_grid = np.meshgrid((arr_x - xmin) * scale_x, (arr_y - ymin) * scale_y) # x_grid, y_grid = np.meshgrid(arr_x, arr_y) # print(arr_x.dtype) # print(x_grid.dtype, y_grid.dtype) # print(x_grid.ravel().dtype) vertices = np.array([x_grid.ravel(), y_grid.ravel(), np.zeros(x_grid.size, dtype=np.float32)]).T del x_grid, y_grid face_elem = np.array([[0, 1, nx*2], [1, nx*2+1, nx*2]], dtype=np.uint32) # faces = np.tile # self.vertices = np.tile(detector_shape, [self.ndets, 1]) + np.repeat(self.det_pos, self.nverts, axis=0) # faces = np.arange(self.nverts * self.ndets, dtype=np.uint) faces = np.tile(face_elem, [npixels, 1]) + \ np.repeat(np.arange(0, npixels*2, 2, dtype=np.uint32), 2*3, axis=0).reshape(npixels*2, 3) + \ np.repeat(np.arange(0, (nx*2)*ny, nx*2, dtype=np.uint32), (nx*2)*3, axis=0).reshape(npixels*2, 3) # faces = np.tile(detector_faces, [self.ndets, 1]) + np.repeat( # np.arange(0, self.ndets*self.nverts, self.nverts, dtype=np.uint32), self.nfaces*3, axis=0).reshape(self.nfaces*self.ndets, 3) # vertexcolors = np.repeat(colors[:, :3], 4, axis=0).astype(np.float32) vertexcolors = np.zeros([2*nx, 2*ny, 3], dtype=np.float32) # print(np.shape(vertexcolors)) # print(np.shape(vertexcolors[::2, ::2, :])) # print(np.shape(colors[:, :, :3])) vertexcolors[::2, ::2, :] = colors[:, :, :3] vertexcolors[1::2, 1::2, :] = colors[:, :, :3] vertexcolors[1::2, ::2, :] = colors[:, :, :3] vertexcolors[::2, 1::2, :] = colors[:, :, :3] # arr_y = np.zeros(2 * ny, dtype=np.float32) # arr_y[::2] = ye[:-1] # arr_y[1::2] = ye[1:] del colors # vertexcolors = np.zeros([npixels*2, 3], dtype=np.float32) # print(vertices.shape) # print(faces.shape) # print(vertexcolors.shape) # print(vertices.dtype) # print(faces.dtype) # print(vertexcolors.dtype) # print("vertices") # print(vertices) # print("faces") # print(faces) # print("colors") # print(vertexcolors) # print(colors) geometry = p3.BufferGeometry(attributes=dict( position=p3.BufferAttribute(vertices, normalized=False), index=p3.BufferAttribute(faces.ravel(), normalized=False), color=p3.BufferAttribute(vertexcolors.reshape(4*nx*ny, 3, order='F')), )) material = p3.MeshBasicMaterial(vertexColors='VertexColors') # material = p3.MeshBasicMaterial() # self.material = self.p3.MeshPhongMaterial(vertexColors='VertexColors', # transparent=True) image = p3.Mesh(geometry=geometry, material=material) # geometry = p3.BufferGeometry(attributes={ # 'position': p3.BufferAttribute(array=pts), # 'color': p3.BufferAttribute( # array=scalar_map.to_rgba(data).astype(np.float32)) # }) # material = p3.PointsMaterial(vertexColors='VertexColors', # size=pixel_size_x) # # map=texture, # # depthTest=False, # # transparent=True) # image = p3.Points(geometry=geometry, material=material) # # arr = p3.BufferAttribute(array=pts) # geometry = p3.BufferGeometry(attributes={ # 'position': p3.BufferAttribute(array=pts), # }) # material = p3.LineBasicMaterial(color=color, linewidth=linewidth) # line = p3.Line(geometry=geometry, # material=material) # # width = 800 # # height= 500 # # Create the threejs scene with ambient light and camera # camera = p3.PerspectiveCamera(position=[0.5*dx, 0.5*dy, 0.5*dx], # aspect=dx / dy) # camera = p3.PerspectiveCamera(45, dx/dy, 1, 5000) camera = p3.OrthographicCamera(0, dx, dy, 0, 0.5*dx, -0.5*dx) return render(objects=image, camera=camera, enableRotate=True, width=dx, height=dy)
def hand_obj_children( obj_verts=None, obj_faces=None, gt_obj_verts=None, gt_obj_faces=None, hand_verts=None, mano_faces_left=None, display_wireframe=False, inside_face_colors=True, hand_opacity=1, obj_opacity=0.2, ): """Args: obj_verts(numpy.ndarray): vertices of object hand_verts(numpy.ndarray): vertices of handect *_faces(numpy.ndarray): faces """ scene_children = [] if obj_verts is not None: geo_obj = p3js.Geometry(vertices=obj_verts.tolist(), faces=obj_faces.tolist()) geo_obj.exec_three_obj_method("computeFaceNormals") mat = p3js.MeshLambertMaterial(color="red", side="FrontSide", transparent=True) mat.opacity = obj_opacity # obj_opacity surf_obj = p3js.Mesh(geometry=geo_obj, material=mat) if inside_face_colors: back_color = "#a91818" else: back_color = "red" mat_bak = p3js.MeshLambertMaterial(color=back_color, side="BackSide", transparent=True) mat_bak.opacity = obj_opacity surf_obj_back = p3js.Mesh(geometry=geo_obj, material=mat_bak) scene_children.append(surf_obj) scene_children.append(surf_obj_back) if display_wireframe: obj_edges = p3js.Mesh( geometry=geo_obj, material=p3js.MeshBasicMaterial(color="black", wireframe=True), ) scene_children.append(obj_edges) if gt_obj_verts is not None: geo_obj = p3js.Geometry(vertices=gt_obj_verts.tolist(), faces=gt_obj_faces.tolist()) geo_obj.exec_three_obj_method("computeFaceNormals") mat = p3js.MeshLambertMaterial(color="orange", side="FrontSide", transparent=True) mat.opacity = obj_opacity surf_obj = p3js.Mesh(geometry=geo_obj, material=mat) mat_back = p3js.MeshLambertMaterial(color="#a91818", side="BackSide", transparent=True) mat_back.opacity = obj_opacity surf_obj_back = p3js.Mesh(geometry=geo_obj, material=mat_bak) scene_children.append(surf_obj) scene_children.append(surf_obj_back) if display_wireframe: obj_edges = p3js.Mesh( geometry=geo_obj, material=p3js.MeshBasicMaterial(color="black", wireframe=True), ) scene_children.append(obj_edges) if hand_verts is not None: geo_hand = p3js.Geometry(vertices=hand_verts.tolist(), faces=mano_faces_left.tolist()) geo_hand.exec_three_obj_method("computeFaceNormals") mat = p3js.MeshLambertMaterial(color="blue", side="FrontSide", transparent=True) mat.opacity = hand_opacity surf_hand = p3js.Mesh(geometry=geo_hand, material=mat) bak_mat = p3js.MeshLambertMaterial(color="blue", side="BackSide", transparent=True) bak_mat.opacity = hand_opacity surf_hand_bak = p3js.Mesh(geometry=geo_hand, material=bak_mat) scene_children.append(surf_hand) scene_children.append(surf_hand_bak) if display_wireframe: hand_edges = p3js.Mesh( geometry=geo_hand, material=p3js.MeshBasicMaterial(color="black", wireframe=True), ) scene_children.append(hand_edges) return scene_children
normals = np.zeros(faces.shape) normals += np.array([0, 1, 0]) geometry = THREE.BufferGeometry( attributes={ 'position': THREE.BufferAttribute(np.array(x0, dtype=np.float32), normalized=False), 'normal': THREE.BufferAttribute(np.array(normals, dtype=np.float32), normalized=False), 'index': THREE.BufferAttribute(np.array(faces.ravel(), dtype=np.uint16)), }) mesh = THREE.Mesh( geometry, THREE.MeshBasicMaterial(sice='DoubleSide', wireframe=True, color='red')) # %% 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,
def allocateWireframeMaterial(self): return pythreejs.MeshBasicMaterial(color='black', side='DoubleSide', wireframe=True, morphTargets=True)
def generate_3js_render( element_groups, canvas_size, zoom, camera_fov=30, background_color="white", background_opacity=1.0, reuse_objects=False, use_atom_arrays=False, use_label_arrays=False, ): """Create a pythreejs scene of the elements. Regarding initialisation performance, see: https://github.com/jupyter-widgets/pythreejs/issues/154 """ import pythreejs as pjs key_elements = {} group_elements = pjs.Group() key_elements["group_elements"] = group_elements unique_atom_sets = {} for el in element_groups["atoms"]: element_hash = ( ("radius", el.sradius), ("color", el.color), ("fill_opacity", el.fill_opacity), ("stroke_color", el.get("stroke_color", "black")), ("ghost", el.ghost), ) unique_atom_sets.setdefault(element_hash, []).append(el) group_atoms = pjs.Group() group_ghosts = pjs.Group() atom_geometries = {} atom_materials = {} outline_materials = {} for el_hash, els in unique_atom_sets.items(): el = els[0] data = dict(el_hash) if reuse_objects: atom_geometry = atom_geometries.setdefault( el.sradius, pjs.SphereBufferGeometry(radius=el.sradius, widthSegments=30, heightSegments=30), ) else: atom_geometry = pjs.SphereBufferGeometry(radius=el.sradius, widthSegments=30, heightSegments=30) if reuse_objects: atom_material = atom_materials.setdefault( (el.color, el.fill_opacity), pjs.MeshLambertMaterial(color=el.color, transparent=True, opacity=el.fill_opacity), ) else: atom_material = pjs.MeshLambertMaterial(color=el.color, transparent=True, opacity=el.fill_opacity) if use_atom_arrays: atom_mesh = pjs.Mesh(geometry=atom_geometry, material=atom_material) atom_array = pjs.CloneArray( original=atom_mesh, positions=[e.position.tolist() for e in els], merge=False, ) else: atom_array = [ pjs.Mesh( geometry=atom_geometry, material=atom_material, position=e.position.tolist(), name=e.info_string, ) for e in els ] data["geometry"] = atom_geometry data["material_body"] = atom_material if el.ghost: key_elements["group_ghosts"] = group_ghosts group_ghosts.add(atom_array) else: key_elements["group_atoms"] = group_atoms group_atoms.add(atom_array) if el.get("stroke_width", 1) > 0: if reuse_objects: outline_material = outline_materials.setdefault( el.get("stroke_color", "black"), pjs.MeshBasicMaterial( color=el.get("stroke_color", "black"), side="BackSide", transparent=True, opacity=el.get("stroke_opacity", 1.0), ), ) else: outline_material = pjs.MeshBasicMaterial( color=el.get("stroke_color", "black"), side="BackSide", transparent=True, opacity=el.get("stroke_opacity", 1.0), ) # TODO use stroke width to dictate scale if use_atom_arrays: outline_mesh = pjs.Mesh( geometry=atom_geometry, material=outline_material, scale=(1.05, 1.05, 1.05), ) outline_array = pjs.CloneArray( original=outline_mesh, positions=[e.position.tolist() for e in els], merge=False, ) else: outline_array = [ pjs.Mesh( geometry=atom_geometry, material=outline_material, position=e.position.tolist(), scale=(1.05, 1.05, 1.05), ) for e in els ] data["material_outline"] = outline_material if el.ghost: group_ghosts.add(outline_array) else: group_atoms.add(outline_array) key_elements.setdefault("atom_arrays", []).append(data) group_elements.add(group_atoms) group_elements.add(group_ghosts) group_labels = add_labels(element_groups, key_elements, use_label_arrays) group_elements.add(group_labels) if len(element_groups["cell_lines"]) > 0: cell_line_mat = pjs.LineMaterial( linewidth=1, color=element_groups["cell_lines"].group_properties["color"]) cell_line_geo = pjs.LineSegmentsGeometry(positions=[ el.position.tolist() for el in element_groups["cell_lines"] ]) cell_lines = pjs.LineSegments2(geometry=cell_line_geo, material=cell_line_mat) key_elements["cell_lines"] = cell_lines group_elements.add(cell_lines) if len(element_groups["bond_lines"]) > 0: bond_line_mat = pjs.LineMaterial( linewidth=element_groups["bond_lines"]. group_properties["stroke_width"], vertexColors="VertexColors", ) bond_line_geo = pjs.LineSegmentsGeometry( positions=[ el.position.tolist() for el in element_groups["bond_lines"] ], colors=[[Color(c).rgb for c in el.color] for el in element_groups["bond_lines"]], ) bond_lines = pjs.LineSegments2(geometry=bond_line_geo, material=bond_line_mat) key_elements["bond_lines"] = bond_lines group_elements.add(bond_lines) group_millers = pjs.Group() if len(element_groups["miller_lines"]) or len( element_groups["miller_planes"]): key_elements["group_millers"] = group_millers if len(element_groups["miller_lines"]) > 0: miller_line_mat = pjs.LineMaterial( linewidth=3, vertexColors="VertexColors" # TODO use stroke_width ) miller_line_geo = pjs.LineSegmentsGeometry( positions=[ el.position.tolist() for el in element_groups["miller_lines"] ], colors=[[Color(el.stroke_color).rgb] * 2 for el in element_groups["miller_lines"]], ) miller_lines = pjs.LineSegments2(geometry=miller_line_geo, material=miller_line_mat) group_millers.add(miller_lines) for el in element_groups["miller_planes"]: vertices = el.position.tolist() faces = [( 0, 1, 2, triangle_normal(vertices[0], vertices[1], vertices[2]), "black", 0, )] if len(vertices) == 4: faces.append(( 2, 3, 0, triangle_normal(vertices[2], vertices[3], vertices[0]), "black", 0, )) elif len(vertices) != 3: raise NotImplementedError("polygons with more than 4 points") plane_geom = pjs.Geometry(vertices=vertices, faces=faces) plane_mat = pjs.MeshBasicMaterial( color=el.fill_color, transparent=True, opacity=el.fill_opacity, side="DoubleSide", ) plane_mesh = pjs.Mesh(geometry=plane_geom, material=plane_mat) group_millers.add(plane_mesh) group_elements.add(group_millers) scene = pjs.Scene(background=None) scene.add([group_elements]) view_width, view_height = canvas_size minp, maxp = element_groups.get_position_range() # compute a minimum camera distance, that is guaranteed to encapsulate all elements camera_dist = maxp[2] + sqrt(maxp[0]**2 + maxp[1]**2) / tan( radians(camera_fov / 2)) camera = pjs.PerspectiveCamera( fov=camera_fov, position=[0, 0, camera_dist], aspect=view_width / view_height, zoom=zoom, ) scene.add([camera]) ambient_light = pjs.AmbientLight(color="lightgray") key_elements["ambient_light"] = ambient_light direct_light = pjs.DirectionalLight(position=(maxp * 2).tolist()) key_elements["direct_light"] = direct_light scene.add([camera, ambient_light, direct_light]) camera_control = pjs.OrbitControls(controlling=camera, screenSpacePanning=True) atom_picker = pjs.Picker(controlling=group_atoms, event="dblclick") key_elements["atom_picker"] = atom_picker material = pjs.SpriteMaterial( map=create_arrow_texture(right=False), transparent=True, depthWrite=False, depthTest=False, ) atom_pointer = pjs.Sprite(material=material, scale=(4, 3, 1), visible=False) scene.add(atom_pointer) key_elements["atom_pointer"] = atom_pointer renderer = pjs.Renderer( camera=camera, scene=scene, controls=[camera_control, atom_picker], width=view_width, height=view_height, alpha=True, clearOpacity=background_opacity, clearColor=background_color, ) return renderer, key_elements