def prim_triangularprism(): """Return vertices and triangle for a regular triangular prism. Returns ------- vertices: ndarray vertices coords that compose our prism triangles: ndarray triangles that compose our prism """ # Local variable to represent the square root of three rounded # to 7 decimal places three = float('{:.7f}'.format(math.sqrt(3))) vertices = np.array([[0, -1/three, 1/2], [-1/2, 1/2/three, 1/2], [1/2, 1/2/three, 1/2], [-1/2, 1/2/three, -1/2], [1/2, 1/2/three, -1/2], [0, -1/three, -1/2]]) triangles = np.array([[0, 1, 2], [2, 1, 3], [2, 3, 4], [1, 0, 5], [1, 5, 3], [0, 2, 4], [0, 4, 5], [5, 4, 3]]) triangles = fix_winding_order(vertices, triangles, clockwise=True) return vertices, triangles
def prim_frustum(): """Return vertices and triangle for a square frustum prism. Returns ------- vertices: ndarray vertices coords that compose our prism triangles: ndarray triangles that compose our prism """ vertices = np.array([[-.5, -.5, .5], [.5, -.5, .5], [.5, .5, .5], [-.5, .5, .5], [-1, -1, -.5], [1, -1, -.5], [1, 1, -.5], [-1, 1, -.5]]) triangles = np.array([[4, 6, 5], [6, 4, 7], [0, 2, 1], [2, 0, 3], [4, 3, 0], [3, 4, 7], [7, 2, 3], [2, 7, 6], [6, 1, 2], [1, 6, 5], [5, 0, 1], [0, 5, 4]], dtype='u8') vertices /= 2 triangles = fix_winding_order(vertices, triangles, clockwise=True) return vertices, triangles
def prim_octagonalprism(): """Return vertices and triangle for an octagonal prism. Returns ------- vertices: ndarray vertices coords that compose our prism triangles: ndarray triangles that compose our prism """ # Local variable to represent the square root of two rounded # to 7 decimal places two = float('{:.7f}'.format(math.sqrt(2))) vertices = np.array([[-1, -(1 + two), -1], [1, -(1 + two), -1], [1, (1 + two), -1], [-1, (1 + two), -1], [-(1 + two), -1, -1], [(1 + two), -1, -1], [(1 + two), 1, -1], [-(1 + two), 1, -1], [-1, -(1 + two), 1], [1, -(1 + two), 1], [1, (1 + two), 1], [-1, (1 + two), 1], [-(1 + two), -1, 1], [(1 + two), -1, 1], [(1 + two), 1, 1], [-(1 + two), 1, 1]]) triangles = np.array( [[0, 8, 9], [9, 1, 0], [5, 13, 9], [9, 1, 5], [3, 11, 10], [10, 2, 3], [2, 10, 14], [14, 6, 2], [5, 13, 14], [14, 6, 5], [7, 15, 11], [11, 3, 7], [7, 15, 12], [12, 4, 7], [0, 8, 12], [12, 4, 0], [ 0, 3, 4 ], [3, 4, 7], [0, 3, 1], [1, 2, 3], [2, 5, 6], [5, 2, 1], [8, 11, 12], [11, 12, 15], [8, 11, 9], [9, 10, 11], [10, 13, 14], [13, 10, 9]], dtype='u8') vertices /= 4 triangles = fix_winding_order(vertices, triangles, clockwise=True) return vertices, triangles
def prim_pentagonalprism(): """Return vertices and triangles for a pentagonal prism. Returns ------- vertices: ndarray vertices coords that compose our prism triangles: ndarray triangles that compose our prism """ # Local variable to represent the square root of five five = math.sqrt(5) onec = (five - 1) / 4.0 twoc = (five + 1) / 4.0 sone = (math.sqrt(10 + (2 * five))) / 4.0 stwo = (math.sqrt(10 - (2 * five))) / 4.0 vertices = np.array([[stwo / 2, twoc / 2, -0.5], [sone / 2, -onec / 2, -0.5], [0, -1 / 2, -0.5], [-sone / 2, -onec / 2, -0.5], [-stwo / 2, twoc / 2, -0.5], [stwo / 2, twoc / 2, 0.5], [sone / 2, -onec / 2, 0.5], [0, -1 / 2, 0.5], [-sone / 2, -onec / 2, 0.5], [-stwo / 2, twoc / 2, 0.5]]) triangles = np.array([[9, 5, 4], [4, 5, 0], [5, 6, 0], [0, 6, 1], [6, 7, 1], [1, 7, 2], [7, 8, 2], [2, 8, 3], [8, 9, 3], [3, 9, 4], [0, 1, 4], [1, 4, 3], [1, 3, 2], [5, 6, 9], [6, 8, 9], [6, 7, 8]]) triangles = fix_winding_order(vertices, triangles, clockwise=True) return vertices, triangles
def test_winding_order(): vertices = np.array([[0, 0, 0], [1, 2, 0], [3, 0, 0], [2, 0, 0]]) triangles = np.array([[0, 1, 3], [2, 1, 0]]) expected_triangles = np.array([[0, 1, 3], [2, 1, 0]]) npt.assert_equal(expected_triangles, utils.fix_winding_order(vertices, triangles))
def prim_sphere(name='symmetric362', gen_faces=False): """Provide vertices and triangles of the spheres. Parameters ---------- name : str which sphere - one of: * 'symmetric362' * 'symmetric642' * 'symmetric724' * 'repulsion724' * 'repulsion100' * 'repulsion200' gen_faces : bool, optional If True, triangulate a set of vertices on the sphere to get the faces. Otherwise, we load the saved faces from a file. Default: False Returns ------- vertices: ndarray vertices coords that composed our sphere triangles: ndarray triangles that composed our sphere Examples -------- >>> import numpy as np >>> from fury.primitive import prim_sphere >>> verts, faces = prim_sphere('symmetric362') >>> verts.shape == (362, 3) True >>> faces.shape == (720, 3) True """ fname = SPHERE_FILES.get(name) if fname is None: raise ValueError('No sphere called "%s"' % name) res = np.load(fname) verts = res['vertices'].copy() faces = faces_from_sphere_vertices(verts) if gen_faces else res['faces'] faces = fix_winding_order(res['vertices'], faces, clockwise=True) return res['vertices'], faces
def prim_rhombicuboctahedron(): """Return vertices and triangles for rhombicuboctahedron. Returns ------- vertices: numpy.ndarray 24 vertices coordinates to the rhombicuboctahedron triangles: numpy.ndarray 44 triangles representing the rhombicuboctahedron """ phi = (math.sqrt(2) - 1) / 2.0 vertices = np.array([[0.5, phi, phi], [0.5, phi, -phi], [0.5, -phi, phi], [0.5, -phi, -phi], [phi, 0.5, phi], [phi, 0.5, -phi], [-phi, 0.5, phi], [-phi, 0.5, -phi], [phi, phi, 0.5], [phi, -phi, 0.5], [-phi, phi, 0.5], [-phi, -phi, 0.5], [-0.5, phi, phi], [-0.5, phi, -phi], [-0.5, -phi, phi], [-0.5, -phi, -phi], [phi, -0.5, phi], [phi, -0.5, -phi], [-phi, -0.5, phi], [-phi, -0.5, -phi], [phi, phi, -0.5], [phi, -phi, -0.5], [-phi, phi, -0.5], [-phi, -phi, -0.5]]) triangles = np.array([[0, 1, 2], [1, 3, 2], [0, 4, 5], [0, 5, 1], [6, 4, 7], [4, 5, 7], [0, 8, 4], [0, 2, 8], [2, 9, 8], [8, 9, 10], [9, 11, 10], [6, 8, 10], [6, 8, 4], [6, 10, 12], [6, 12, 7], [7, 12, 13], [10, 11, 14], [10, 14, 12], [12, 14, 15], [12, 15, 13], [2, 3, 16], [3, 17, 16], [2, 16, 9], [9, 16, 11], [11, 16, 18], [18, 16, 19], [16, 17, 19], [11, 18, 14], [14, 18, 19], [14, 19, 15], [1, 21, 3], [1, 20, 21], [3, 21, 17], [17, 21, 23], [17, 23, 19], [21, 20, 23], [23, 20, 22], [19, 23, 15], [15, 23, 13], [13, 23, 22], [13, 22, 7], [22, 7, 5], [22, 20, 5], [20, 1, 5]], dtype='i8') triangles = fix_winding_order(vertices, triangles, clockwise=True) return vertices, triangles
def prim_sphere(name='symmetric362', gen_faces=False, phi=None, theta=None): """Provide vertices and triangles of the spheres. Parameters ---------- name : str, optional which sphere - one of: * 'symmetric362' * 'symmetric642' * 'symmetric724' * 'repulsion724' * 'repulsion100' * 'repulsion200' gen_faces : bool, optional If True, triangulate a set of vertices on the sphere to get the faces. Otherwise, we load the saved faces from a file. Default: False phi : int, optional Set the number of points in the latitude direction theta : int, optional Set the number of points in the longitude direction Returns ------- vertices: ndarray vertices coords that composed our sphere triangles: ndarray triangles that composed our sphere Examples -------- >>> import numpy as np >>> from fury.primitive import prim_sphere >>> verts, faces = prim_sphere('symmetric362') >>> verts.shape == (362, 3) True >>> faces.shape == (720, 3) True """ if phi is None or theta is None: fname = SPHERE_FILES.get(name) if fname is None: raise ValueError('No sphere called "%s"' % name) res = np.load(fname) verts = res['vertices'].copy() faces = faces_from_sphere_vertices( verts) if gen_faces else res['faces'] faces = fix_winding_order(res['vertices'], faces, clockwise=True) return verts, faces else: phi = phi if phi >= 3 else 3 theta = theta if theta >= 3 else 3 phi_indices, theta_indices = np.arange(0, phi), np.arange(1, theta-1) # phi and theta angles are same as standard physics convention phi_angles = 2*np.pi*phi_indices / phi theta_angles = np.pi*theta_indices / (theta-1) # combinations of all phi and theta angles mesh = np.array(np.meshgrid(phi_angles, theta_angles)) combs = mesh.T.reshape(-1, 2) _angles = np.array([[1, 1], [0, np.pi], [np.pi/2, -np.pi/2]]) _points = np.array(sphere2cart(_angles[0], _angles[1], _angles[2])).T x, y, z = sphere2cart(1, combs[:, 1:], combs[:, :1]) x = np.reshape(np.append(x, _points[:, :1]), (-1, )) y = np.reshape(np.append(y, _points[:, 1:2]), (-1, )) z = np.reshape(np.append(z, _points[:, -1:]), (-1, )) verts = np.vstack([x, y, z]).T faces = faces_from_sphere_vertices(verts) faces = fix_winding_order(verts, faces, clockwise=True) return verts, faces
length=140) line_slider_x = ui.LineSlider2D(min_value=0, max_value=grid_shape[0] - 1, initial_value=grid_shape[0] / 2, text_template="{value:.0f}", length=140) ############################################################################### # We also define a high resolution sphere to demonstrate the capability to # dynamically change the sphere used for SH to SF projection. sphere_high = get_sphere('symmetric362') # We fix the order of the faces' three vertices to a clockwise winding. This # ensures all faces have a normal going away from the center of the sphere. sphere_high.faces = fix_winding_order(sphere_high.vertices, sphere_high.faces, True) B_high = sh_to_sf_matrix(sphere_high, 8, return_inv=False) ############################################################################### # We add a combobox for choosing the sphere resolution during execution. sphere_dict = {'Low resolution': (sphere_low, B_low), 'High resolution': (sphere_high, B_high)} combobox = ui.ComboBox2D(items=list(sphere_dict)) scene.add(combobox) ############################################################################### # Here we will write callbacks for the sliders and combo box and register them. def change_slice_z(slider): i = int(np.round(slider.value))