def test_radians_between_vectors(self): v1 = (1, 1, 1) v2 = (1, 1, 1) self.assertEqual(0, vector_utils.radians_between_vectors(v1, v2)) v1 = (1, 0, 0) v2 = (0, 1, 0) self.assertAlmostEqual(90, math.degrees(vector_utils.radians_between_vectors(v1, v2))) v1 = (1, 1, 0) v2 = (1, 0, 0) self.assertAlmostEqual(45, math.degrees(vector_utils.radians_between_vectors(v1, v2))) v1 = (1, 0, 0) v2 = (-1, 0, 0) self.assertAlmostEqual(180, abs(math.degrees(vector_utils.radians_between_vectors(v1, v2))))
def adjacent_bins_are_safe(bin_dict, point, key, num_adjacent, min_dist, clamp_factor): """ Uses spatial datastructure in bin_dict to determine whether any points stored in this or adjacent bins (determined by num_adjacent) in any direction are less than min_dist from the given point. This can be used when prospectively placing a new point to cheaply determine whether it is too close to any existing points. A note on spatial binning: Points on a sphere can be separated based on their position into a series of bins; approximately equally sized areas. Storing this spatial structure (and the points sorted into them) in a dictionary allows for a fast way of determining for a given location what other points are nearby. The alternative to using a spatial datastructure would be to exhaustively compare a point to every other point, which would be very slow. """ for x_off in range(-num_adjacent, num_adjacent+1, 1): for y_off in range(-num_adjacent, num_adjacent+1, 1): for z_off in range(-num_adjacent, num_adjacent+1, 1): # Search this clamps bin to find whether any points are too close adjacent_bin_key = (key[0]+x_off, key[1]+y_off, key[2]+z_off) if not adjacent_bin_key in bin_dict: # Bin not in clamps dict, so no points are here # This is perfectly acceptable continue for possible_neighbour in bin_dict[adjacent_bin_key]: if radians_between_vectors(possible_neighbour, point) < min_dist: # Neighbour is too close. point location is unsuitable return False # Neighbour must be far enough away # The new location is safe return True
def radians_between_locations(loc1, loc2): """ Calculates angle between two coordinate locations on sphere using conversion to cartesian coordinates. Result is equal/equivalent to distance_between_locations which uses Haversine formula instead. :param loc1: [lon,lat] location :param loc2: [lon, lat] location :return: radian angle between locations """ return radians_between_vectors(*geographic_to_cartesian([loc1, loc2]))