def _get_spheres(ctk_scene, d_args=None): """return the ASY string output to draw the spheres Arguments: ctk_scene {Scene} -- CTK Scene Object with ctk_scene.type == 'spheres' Keyword Arguments: d_args {dict} -- User defined defaults of the plot (default: {None}) """ assert ctk_scene.type == "spheres" updated_defaults = update_object_args(d_args, object_name="Spheres", allowed_args=["radius", "color"]) positions = [tuple(pos) for pos in ctk_scene.positions] radius = ctk_scene.radius or updated_defaults["radius"] color = ctk_scene.color or updated_defaults["color"] color = color.replace("#", "") if ctk_scene.phiStart or ctk_scene.phiEnd: raise NotImplementedError # phiStart = ctk_scene.phiStart or 0 # not yet implemented # phiEnd = ctk_scene.phiEnd or 2*pi return (Environment().from_string(TEMP_SPHERE).render(positions=positions, radius=radius, color=color))
def _get_lines(ctk_scene, d_args=None): """return the ASY string output to draw cylinders Arguments: ctk_scene {Scene} -- CTK Scene Object with ctk_scene.type == 'cylinders' Keyword Arguments: d_args {dict} -- User defined defaults of the plot (default: {None}) """ assert ctk_scene.type == "lines" updated_defaults = update_object_args( d_args, object_name="Lines", allowed_args=["linewidth", "color"] ) ipos = map(tuple, ctk_scene.positions[0::2]) fpos = map(tuple, ctk_scene.positions[1::2]) posPairs = [*zip(ipos, fpos)] linewidth = ctk_scene.linewidth or updated_defaults["linewidth"] color = ctk_scene.color or updated_defaults["color"] color = color.replace("#", "") return ( Environment() .from_string(TEMP_LINE) .render(posPairs=posPairs, color=color, linewidth=linewidth) )
def _get_surface(ctk_scene, d_args=None): """return the ASY string output to draw cylinders Arguments: ctk_scene {Scene} -- CTK Scene Object with ctk_scene.type == 'surface' Keyword Arguments: d_args {dict} -- User defined defaults of the plot (default: {None}) """ assert ctk_scene.type == "surface" updated_defaults = update_object_args( d_args, object_name="Surfaces", allowed_args=["opacity", "color", "edge_width"] ) color = ctk_scene.color or updated_defaults["color"] color = color.replace("#", "") opacity = ctk_scene.opacity or updated_defaults["opacity"] positions = tuple( map(lambda x: "{" + f"{x[0]}, {x[1]}, {x[2]}" + "}", ctk_scene.positions) ) num_triangle = len(ctk_scene.positions) / 3.0 # sanity check the mesh must be triangles assert num_triangle.is_integer() # # make decision on transparency # transparent = if obj_args['opacity'] < 0.99 # # # asymptote just needs the xyz positions num_triangle = int(num_triangle) pos_xyz = tuple( chain.from_iterable( [ (positions[itr * 3], positions[itr * 3 + 1], positions[itr * 3 + 2]) for itr in range(num_triangle) ] ) ) # # # write the data array data_array_asy = ( Environment() .from_string(TEMP_SURF) .render(positions=pos_xyz, face_color=color, opac=opacity) ) return data_array_asy
def _get_line_from_vec(v0, v1, scene_args): """ Draw the line given the two endpoints, some Three.js capabilities still don't work well in pythreejs (unable to update linewidth and such) LineSegments2 is the only one that has been tested successfully, but it cannot handle LineDashedMaterial :param v0: list, one endpoint of line :param v1: list, other endpoint of line :param scene_args: dict, properties of the line (line_width and color) :return: pythreejs object that displays the line segment """ obj_args = update_object_args(scene_args, "Lines", ["linewidth", "color"]) logger.debug(obj_args) line = LineSegments2( LineSegmentsGeometry(positions=[[v0, v1]]), LineMaterial(**obj_args), # Dashed lines do not work in pythreejs yet ) return line
def _get_surface_from_positions(positions, d_args, draw_edges=False): # get defaults obj_args = update_object_args(d_args, "Surfaces", ["color", "opacity"]) num_triangle = len(positions) / 3.0 assert num_triangle.is_integer() # make decision on transparency if obj_args["opacity"] > 0.99: transparent = False else: transparent = True num_triangle = int(num_triangle) index_list = [[itr * 3, itr * 3 + 1, itr * 3 + 2] for itr in range(num_triangle)] # Vertex ositions as a list of lists surf_vertices = BufferAttribute(array=positions, normalized=False) # Indices surf_indices = BufferAttribute(array=np.array(index_list, dtype=np.uint16).ravel(), normalized=False) geometry = BufferGeometry(attributes={ "position": surf_vertices, "index": surf_indices }) new_surface = Mesh( geometry=geometry, material=MeshLambertMaterial( color=obj_args["color"], side="DoubleSide", transparent=transparent, opacity=obj_args["opacity"], ), ) if draw_edges == True: edges = EdgesGeometry(geometry) edges_lines = LineSegments(edges, LineBasicMaterial(color=obj_args["color"])) return new_surface, edges_lines else: return new_surface, None
def _get_cylinders(ctk_scene, d_args=None): """return the ASY string output to draw cylinders Arguments: ctk_scene {Scene} -- CTK Scene Object with ctk_scene.type == 'cylinders' Keyword Arguments: d_args {dict} -- User defined defaults of the plot (default: {None}) """ assert ctk_scene.type == "cylinders" updated_defaults = update_object_args(d_args, object_name="Cylinders", allowed_args=["radius", "color"]) posPairs = [[tuple(ipos), tuple(fpos)] for ipos, fpos in ctk_scene.positionPairs] radius = ctk_scene.radius or updated_defaults["radius"] color = ctk_scene.color or updated_defaults["color"] color = color.replace("#", "") return (Environment().from_string(TEMP_CYLINDER).render(posPairs=posPairs, color=color, radius=radius))
def _get_cylinder_from_vec(v0, v1, d_args=None): """ Draw the cylinder given the two endpoints. :param v0: list, one endpoint of line :param v1: list, other endpoint of line :param d_args: dict, properties of the line (line_width and color) :return: Mesh, pythreejs object that displays the cylinders """ obj_args = update_object_args(d_args, "Cylinders", ["radius", "color"]) v0 = np.array(v0) v1 = np.array(v1) vec = v1 - v0 mid_point = (v0 + v1) / 2.0 rot_vec = np.cross([0, 1, 0], vec) rot_vec_len = np.linalg.norm(rot_vec) rot_vec = rot_vec / rot_vec_len rot_arg = np.arccos(np.dot([0, 1, 0], vec) / np.linalg.norm(vec)) new_bond = Mesh( geometry=CylinderBufferGeometry( radiusTop=obj_args["radius"], radiusBottom=obj_args["radius"], height=np.linalg.norm(v1 - v0), radialSegments=12, heightSegments=10, ), material=MeshLambertMaterial(color=obj_args["color"]), position=tuple(mid_point), ) rot = R.from_rotvec(rot_arg * rot_vec) quat = tuple(rot.as_quat()) if any(isnan(itr_q) for itr_q in quat): new_bond.quaternion = (0, 0, 0, 0) else: new_bond.quaternion = quat return new_bond