def rotation_around_arbitrary_axis_by_zero_radians(self): starting_p = vector_utils.normalized([1, 1, 1])[0] axis_vector = [0, 1, 0] theta = 0 rotated_vec = cartesian_utils.randomly_rotate_about_arbitrary_axis_in_radians(starting_p, axis_vector, theta) # Are you back to where you started? self.assertEqual(rotated_vec, starting_p)
def test_stable_rotation_around_z(self): starting_p = vector_utils.normalized([1, 1, 1])[0] z_vec = [0, 0, 1] angle = math.radians(15) # Check old distance arc_dist_before = cartesian_utils.cartesian_arc_distance(starting_p, z_vec) # Rotate starting_p around z new_p = vector_utils.rotate_about_arbitrary_axis_in_radians(starting_p, z_vec, angle) # Check new distance arc_dist_after = cartesian_utils.cartesian_arc_distance(new_p, z_vec) self.assertEqual(arc_dist_before, arc_dist_after)
def test_arc_dist_same_over_rotation(self): starting_p = vector_utils.normalized([1, 1, 1])[0] min_angle = math.radians(15) max_angle = math.radians(16) spin_angle = math.radians(50) # Generate twice.. should be deterministic near_p = cartesian_utils.rotate_to_vec_in_anulus_in_radians(starting_p, min_angle, min_angle, spin_angle) far_p = cartesian_utils.rotate_to_vec_in_anulus_in_radians(starting_p, max_angle, max_angle, spin_angle) first_anulus_arc_width = cartesian_utils.cartesian_arc_distance(near_p, far_p) # Still same angle between them min_angle = math.radians(5) max_angle = math.radians(6) near_p = cartesian_utils.rotate_to_vec_in_anulus_in_radians(starting_p, min_angle, min_angle, spin_angle) far_p = cartesian_utils.rotate_to_vec_in_anulus_in_radians(starting_p, max_angle, max_angle, spin_angle) second_anulus_arc_width = cartesian_utils.cartesian_arc_distance(near_p, far_p) # Allow some tolerance self.assertAlmostEqual(first_anulus_arc_width, second_anulus_arc_width)
def generate_variable_point_rows_on_sphere(nodes_in_lat, switch_axis=False): """ This method has different numbers of nodes at each latitude, which will not perfectly line up from one latitude to the next (though the 'error' will be minor if latAngle is small) """ points = list() sphere_radius = 1 angle_between_latitudes = pi / nodes_in_lat # Iterate over latitudes a = angle_between_latitudes * 0.5 b = 0 for row in range(nodes_in_lat): vec_to_circle_centre = None if switch_axis: vec_to_circle_centre = np.array([0, sphere_radius * cos(0.5 * (a * 2)), 0]) else: vec_to_circle_centre = np.array([0, 0, sphere_radius * cos(0.5 * (a * 2))]) circle_radius = sphere_radius * sin(a) circle_circumference = 2 * pi * circle_radius nodes_in_long = int(circle_circumference / angle_between_latitudes) for col in range(nodes_in_long): # Rotate x and z around y axis # x' = x cos(a) - z sin(a) # z' = x sin(a) + z cos(a) # But as our vector would be (0,0,circle_radius), can simplify to... x = -circle_radius*sin(b) z = circle_radius*cos(b) vec_to_circle_point = None if switch_axis: vec_to_circle_point = np.array([x, 0, z]) else: vec_to_circle_point = np.array([x, z, 0]) # Vector from centre to node is same as node's coordinates, as sphere is centralised vec_to_node = normalized(np.add(vec_to_circle_centre, vec_to_circle_point))[0] points.append(vec_to_node) b += angle_between_latitudes # Increment angle for next lat a += angle_between_latitudes return points