def update(self, x, z): rotation_x = quaternion.Quaternion( quaternion.create_from_eulers([x, 0, 0])) rotation_z = self.rotation_x.conjugate.cross( quaternion.Quaternion(quaternion.create_from_eulers([0, 0, z]))) self.rotation_x = self.rotation_x.cross(rotation_x) self.matrix = numpy.matmul( self.matrix, matrix44.create_from_quaternion(rotation_z.cross(self.rotation_x))) self.inverse_matrix = numpy.linalg.inv(self.matrix)
def test_exp(self): source = np.array([0, 0, 0, 1.0]) result = quaternion.exp(source) expected = np.array([0, 0, 0, np.exp(1)]) np.testing.assert_almost_equal(result, expected) source = quaternion.create_from_eulers([np.pi, 0, 0]) result = quaternion.exp(source) expected = np.array([0.84147098, 0, 0, 0.54030231]) np.testing.assert_almost_equal(result, expected) # Tests from the boost::math::quaternion source = np.array([4 * np.arctan(1), 0, 0, 0]) result = quaternion.exp(source) + [0, 0, 0, 1.0] result = np.linalg.norm(result) expected = 2 * np.finfo(result.dtype).eps np.testing.assert_almost_equal(result, expected) source = np.array([0, 4 * np.arctan(1), 0, 0]) result = quaternion.exp(source) + [0, 0, 0, 1.0] result = np.linalg.norm(result) expected = 2 * np.finfo(result.dtype).eps np.testing.assert_almost_equal(result, expected) source = np.array([0, 0, 4 * np.arctan(1), 0]) result = quaternion.exp(source) + [0, 0, 0, 1.0] result = np.linalg.norm(result) expected = 2 * np.finfo(result.dtype).eps np.testing.assert_almost_equal(result, expected)
def octasphere(ndivisions: int): """Creates a unit sphere using octagon subdivision. Creates a unit sphere using octagon subdivision. Modified slightly from the original code by Philip Rideout (https://prideout.net/blog/octasphere). """ n = 2**ndivisions + 1 num_verts = n * (n + 1) // 2 verts = empty((num_verts, 3)) j = 0 for i in range(n): theta = pi * 0.5 * i / (n - 1) point_a = [0, sin(theta), cos(theta)] point_b = [cos(theta), sin(theta), 0] num_segments = n - 1 - i j = compute_geodesic(verts, j, point_a, point_b, num_segments) assert len(verts) == num_verts num_faces = (n - 2) * (n - 1) + n - 1 faces = empty((num_faces, 3), dtype='int') f, j0 = 0, 0 for col_index in range(n - 1): col_height = n - 1 - col_index j1 = j0 + 1 j2 = j0 + col_height + 1 j3 = j0 + col_height + 2 for row in range(col_height - 1): faces[f + 0] = [j0 + row, j1 + row, j2 + row] faces[f + 1] = [j2 + row, j1 + row, j3 + row] f = f + 2 row = col_height - 1 faces[f] = [j0 + row, j1 + row, j2 + row] f = f + 1 j0 = j2 euler_angles = array([ [0, 0, 0], [0, 1, 0], [0, 2, 0], [0, 3, 0], [1, 0, 0], [1, 0, 1], [1, 0, 2], [1, 0, 3], ]) * pi * 0.5 quats = (quaternion.create_from_eulers(e) for e in euler_angles) offset, combined_verts, combined_faces = 0, [], [] for quat in quats: rotated_verts = [quaternion.apply_to_vector(quat, v) for v in verts] rotated_faces = faces + offset combined_verts.append(rotated_verts) combined_faces.append(rotated_faces) offset = offset + len(verts) return vstack(combined_verts), vstack(combined_faces)
def test_create_from_eulers(self): result = quaternion.create_from_eulers([1.0, 2.0, 3.0]) np.testing.assert_almost_equal( result, [0.7549338, -0.2061492, 0.5015091, -0.3688714], decimal=5) self.assertTrue(result.dtype == np.float)
def test_create_from_eulers_identity(self): result = quaternion.create_from_eulers([0., 0., 0.]) np.testing.assert_equal(result, [0., 0., 0., 1.]) self.assertTrue(result.dtype == np.float)
def test_create_from_eulers(self): result = quaternion.create_from_eulers([1.0, 2.0, 3.0]) np.testing.assert_almost_equal(result, [0.7549338, -0.2061492, 0.5015091, -0.3688714], decimal=5) self.assertTrue(result.dtype == np.float)