Source code for ddg.math.discrete_objects

"""The module 'discrete_objects' defines coordinates and faces of objects."""
import numpy as np

from ddg.math.euclidean import circle_fct


[docs]def tetrahedron_faces(): """Generate faces of a tetrahedron as numpy.ndarray The faces have type numpy.ndarray of shape (3,). They consist of integers representing the adjacent vertices. Returns ------- faces : numpy.ndarray The faces of the tetrahedron """ faces = np.array([[0, 1, 2], [2, 3, 0], [1, 3, 2], [0, 3, 1]]) return faces
[docs]def tetrahedron_coordinates(): """Generate coordinates of a tetrahedron as numpy.ndarray The coordinates are in 3D space. The object is centered at the origin, meaning at [0,0,0]. Returns ------- coords : numpy.ndarray The coordinates of the tetrahedron """ coords = np.array([[1, 1, 1], [1, -1, -1], [-1, 1, -1], [-1, -1, 1]]) return coords
[docs]def cube_faces(): """Generate faces of a cube as numpy.ndarray The faces have type numpy.ndarray of shape (4,). They consist of integers representing the adjacent vertices. Returns ------- faces : numpy.ndarray The faces of the cube """ faces = np.array( [ [4, 5, 1, 0], [6, 2, 1, 5], [7, 3, 2, 6], [4, 0, 3, 7], [1, 2, 3, 0], [7, 6, 5, 4], ] ) return faces
[docs]def cube_coordinates(): """Generate coordinates of a cube as numpy.ndarray The coordinates are in 3D space. The object is centered at the origin, meaning at [0,0,0]. Returns ------- coords : numpy.ndarray The coordinates of the cube """ coords = np.array( [ [-1, -1, -1], [1, -1, -1], [1, -1, 1], [-1, -1, 1], [-1, 1, -1], [1, 1, -1], [1, 1, 1], [-1, 1, 1], ] ) return coords
[docs]def octahedron_faces(): """Generate faces of an octahedron as numpy.ndarray The faces have type numpy.ndarray of shape (3,). They consist of integers representing the adjacent vertices. Returns ------- faces : numpy.ndarray The faces of the octahedron """ faces = np.array( [ [1, 5, 3], [1, 3, 4], [1, 2, 5], [3, 5, 0], [1, 4, 2], [3, 0, 4], [2, 0, 5], [2, 4, 0], ] ) return faces
[docs]def octahedron_coordinates(): """Generate coordinates of an octahedron as numpy.ndarray The coordinates are in 3D space. The object is centered at the origin, meaning at [0,0,0]. Returns ------- coords : numpy.ndarray The coordinates of the octahedron """ coords = np.array( [[0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1], [1, 0, 0], [-1, 0, 0]] ) return coords
[docs]def dodecahedron_faces(): """Generate faces of a dodecahedron as numpy.ndarray The faces have type numpy.ndarray of shape (5,). They consist of integers representing the adjacent vertices. Returns ------- faces : numpy.ndarray The faces of the dodecahedron """ faces = np.array( [ [10, 6, 19, 7, 11], [11, 3, 17, 2, 10], [7, 15, 13, 3, 11], [19, 18, 5, 15, 7], [6, 14, 4, 18, 19], [6, 10, 2, 12, 14], [3, 13, 1, 16, 17], [17, 16, 0, 12, 2], [5, 9, 1, 13, 15], [18, 4, 8, 9, 5], [1, 9, 8, 0, 16], [12, 0, 8, 4, 14], ] ) return faces
[docs]def dodecahedron_coordinates(): """Generate coordinates of a dodecahedron as numpy.ndarray The coordinates are in 3D space. The object is centered at the origin, meaning at [0,0,0]. Returns ------- coords : numpy.ndarray The coordinates of the dodecahedron """ p = (1 + np.sqrt(5)) / 2 coords = np.array( [ [1, 1, 1], [1, 1, -1], [1, -1, 1], [1, -1, -1], [-1, 1, 1], [-1, 1, -1], [-1, -1, 1], [-1, -1, -1], [0, p, 1 / p], [0, p, -1 / p], [0, -p, 1 / p], [0, -p, -1 / p], [1 / p, 0, p], [1 / p, 0, -p], [-1 / p, 0, p], [-1 / p, 0, -p], [p, 1 / p, 0], [p, -1 / p, 0], [-p, 1 / p, 0], [-p, -1 / p, 0], ] ) return coords
[docs]def icosahedron_faces(): """Generate faces of an icosahedron as numpy.ndarray The faces have type numpy.ndarray of shape (3,). They consist of integers representing the adjacent vertices. Returns ------- faces : numpy.ndarray The faces of the icosahedron """ faces = np.array( [ [9, 4, 2], [2, 11, 9], [9, 5, 4], [2, 4, 0], [2, 6, 11], [3, 9, 11], [3, 5, 9], [8, 4, 5], [2, 0, 6], [8, 0, 4], [11, 6, 7], [11, 7, 3], [3, 1, 5], [8, 5, 1], [10, 6, 0], [10, 0, 8], [10, 7, 6], [3, 7, 1], [8, 1, 10], [10, 1, 7], ] ) return faces
[docs]def icosahedron_coordinates(): """Generate coordinates of an icosahedron as numpy.ndarray The coordinates are in 3D space. The object is centered at the origin, meaning at [0,0,0]. Returns ------- coords : numpy.ndarray The coordinates of the icosahedron """ p = (1 + np.sqrt(5)) / 2 coords = np.array( [ [0, 1, p], [0, 1, -p], [0, -1, p], [0, -1, -p], [p, 0, 1], [p, 0, -1], [-p, 0, 1], [-p, 0, -1], [1, p, 0], [1, -p, 0], [-1, p, 0], [-1, -p, 0], ] ) return coords
[docs]def disc_face(resolution): """Generate the face of a disc as numpy.ndarray A disc is a circle with an inscribed face. The face has type numpy.ndarray of shape ('resolution',). It consists of integers representing the adjacent vertices. Parameters ---------- resolution : int The number of vertices of the disc Returns ------- face : numpy.ndarray The face of the disc """ face = np.arange(resolution).reshape((1, resolution)) return face
[docs]def disc_coordinates(resolution, center=(0, 0, 0), normal=(0, 0, 1), radius=1): """Generate coordinates of a disc as numpy.ndarray The coordinates are in 3D space. By default, the disc is centered at [0,0,0]. Parameters ---------- resolution : int The number of vertices of the disc center : iterable (default=(0,0,0)) The center of the disc in 3D space. normal : iterable (default=(0,0,1)) The normal vector of the disc. radius : float (default=1) The radius of the disc. Returns ------- coords : numpy.ndarray The coordinates of the disc """ t = np.linspace(0, 2 * np.pi, resolution, endpoint=False) coords = [circle_fct(t[i], center, radius, normal) for i in range(resolution)] return np.array(coords)
[docs]def cone_faces(resolution): """ Generate the face of a cone as numpy.ndarray. The faces are of type numpy.ndarray with non-uniform lengths. They consist of integers representing the adjacent vertices. Parameters ---------- resolution : int The resolution of the cone. Returns ------- numpy.ndarray of shape (n + 1, k) The faces of the cone where n is the resolution and k varies. Note that `dtype=object` because of k. """ tris = np.vstack( ( np.arange(resolution), np.append(np.arange(1, resolution), 0), np.full(resolution, resolution), ) ) faces = list(np.split(np.ravel(tris.T), resolution)) faces.insert(0, np.arange(resolution - 1, -1, -1)) return np.array(faces, dtype=object)
[docs]def cone_coordinates( resolution, radius=1, length=1, center=(0, 0, 0), normal=(0, 0, 1) ): """ Generate coordinates of a cone as numpy.ndarray. The coordinates are in 3D. By default, the cone's bottom is at [0,0,0] and the cone points upwards. Parameters ---------- resolution : int The number of vertices. radius : float (default=1) The radius of the base of the cone. length : float (default=1) The length of the cone. center : iterable (default=(0,0,0)) The center of the base. normal : iterable (default=(0,0,1)) The normal of the cone's base. Returns ------- coords : numpy.ndarray of shape (n + 1, 3) The coordinates of the cone where n is the resolution. """ center = np.array(center) + normal / np.linalg.norm(normal) * length / 2 t = np.linspace(0, 2 * np.pi, resolution, endpoint=False) base_coordinates = np.array( [ circle_fct( t[i], (center[0], center[1], center[2] - length / 2), radius, normal ) for i in range(resolution) ] ) tip_coordinates = np.array( [circle_fct(0, (center[0], center[1], center[2] + length / 2), 0, normal)] ) return np.row_stack((base_coordinates, tip_coordinates))
[docs]def cylinder_faces(resolution): """Generate the faces of a cylinder as numpy.ndarray The faces are of type numpy.ndarray with non-uniform lengths. They consist of integers representing the adjacent vertices. The first face is the bottom face, the second the top and the remaining faces the side faces. Parameters ---------- resolution : int The resolution of the cylinder Returns ------- faces : numpy.ndarray The faces of the cylinder """ # Generate bottom face faces = [list(range(resolution - 1, -1, -1))] # Generate top face faces += [list(range(resolution, 2 * resolution))] # Generate remaining faces faces += [ [i, i + 1, i + 1 + resolution, i + resolution] for i in range(resolution - 1) ] # Add last face separately because it breaks the formula faces += [[resolution - 1, 0, resolution, 2 * resolution - 1]] return np.array(faces, dtype=object)
[docs]def cylinder_coordinates( resolution, top_radius=1, bot_radius=1, length=1, center=(0, 0, 0), normal=(0, 0, 1) ): """Generate coordinates of a cylinder as numpy.ndarray The coordinates are in 3D. By default, the cylinder's bottom is at [0,0,0]. Parameters ---------- resolution : int The number of vertices at each side. top_radius : float The radius of the top of the cylinder. bot_radius : float The radius of the bottom of the cylinder. length : float The length of the cylinder. center : iterable (default=(0,0,0)) The center of the bottom of the cylinder. normal : iterable (default=(0,0,1)) The normal of the cylinder's top and bottom faces. Returns ------- coords : numpy.ndarray The coordinates of the cylinder """ center = np.array(center) + normal / np.linalg.norm(normal) * length / 2 t = np.linspace(0, 2 * np.pi, resolution, endpoint=False) bottom_coordinates = np.array( [ circle_fct( t[i], (center[0], center[1], center[2] - length / 2), bot_radius, normal ) for i in range(resolution) ] ) top_coordinates = np.array( [ circle_fct( t[i], (center[0], center[1], center[2] + length / 2), top_radius, normal ) for i in range(resolution) ] ) return np.row_stack((bottom_coordinates, top_coordinates))
[docs]def arrow_faces(resolution): """Generate faces of an arrow as numpy.ndarray The faces are of type numpy.ndarray with non-uniform lengths. They consist of integers representing the adjacent vertices. First bottom face, then the faces of the stick, then the faces of the base of the tip and finally the faces of the tip. Parameters ---------- resolution : int The resolution of the arrow Returns ------- faces : numpy.ndarray The faces of the arrow """ # Generate bottom face faces = [list(range(resolution - 1, -1, -1))] # Generate faces of the stick faces += [ [i, i + 1, i + 1 + resolution, i + resolution] for i in range(resolution - 1) ] # Add last face of the stick faces += [[resolution - 1, 0, resolution, 2 * resolution - 1]] # Generate faces of base of tip faces += [ [i + resolution, i + 1 + resolution, i + 1 + 2 * resolution, i + 2 * resolution] for i in range(resolution - 1) ] # Add last face of base of tip separately faces += [[2 * resolution - 1, resolution, 2 * resolution, 3 * resolution - 1]] # Generate faces of the tip faces += [ [i + 2 * resolution, i + 1 + 2 * resolution, 3 * resolution] for i in range(resolution - 1) ] # Add last face of tip faces += [[3 * resolution - 1, 2 * resolution, 3 * resolution]] return np.array(faces, dtype=object)
[docs]def arrow_coordinates(resolution, heights=(0, 0.7, 0.7, 1), radii=(0.05, 0.05, 0.125)): """Generate coordinates of an arrow as numpy.ndarray The coordinates are in 3D. By default, the arrow's bottom is at [0,0,0] and it's head at [0,0,1]. Parameters ---------- resolution : int The resolution of the arrow heights : iterable (default=(0,0.7,0.7,1)) First element defines height of the bottom of the stick, the second the height of the top of the stick, the third the height of the base of the tip and the forth the height of the tip of the head. radii : iterable (default=(0.05,0.05,0.125)) First element defines the radius of the bottom of the stick, second the radius of the top of the stick and the third the radius of the base of the tip. Returns ------- coordinates : numpy.ndarray The coordinates of the arrow """ delta = np.linspace(0, 2 * np.pi, resolution, endpoint=False) bottom_coordinates = np.column_stack( ( np.cos(delta) * radii[0], np.sin(delta) * radii[0], np.ones(resolution) * heights[0], ) ) top_coordinates = np.column_stack( ( np.cos(delta) * radii[1], np.sin(delta) * radii[1], np.ones(resolution) * heights[1], ) ) base_tip_coordinates = np.column_stack( ( np.cos(delta) * radii[2], np.sin(delta) * radii[2], np.ones(resolution) * heights[2], ) ) tip_coordinates = np.array([0, 0, heights[3]]).reshape((1, 3)) return np.row_stack( (bottom_coordinates, top_coordinates, base_tip_coordinates, tip_coordinates) )