geo_utils.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. from __future__ import annotations
  2. import math
  3. def cos_rad_lat(latitude: float) -> float:
  4. return math.cos(math.radians(latitude))
  5. def sin_rad_lat(latitude: float) -> float:
  6. return math.sin(math.radians(latitude))
  7. def rad_lng(longitude: float) -> float:
  8. return math.radians(longitude)
  9. def earth_distance(
  10. location: tuple[float, float], other_location: tuple[float, float]
  11. ) -> float:
  12. """Great circle distance in km between two locations on Earth."""
  13. r = 6371 # Radius of Earth in kilometres
  14. _cos_rad_lat = cos_rad_lat(location[0])
  15. _sin_rad_lat = sin_rad_lat(location[0])
  16. _rad_lng = rad_lng(location[1])
  17. other_cos_rad_lat = cos_rad_lat(other_location[0])
  18. other_sin_rad_lat = sin_rad_lat(other_location[0])
  19. other_rad_lng = rad_lng(other_location[1])
  20. return (
  21. math.acos(
  22. _cos_rad_lat * other_cos_rad_lat * math.cos(_rad_lng - other_rad_lng)
  23. + _sin_rad_lat * other_sin_rad_lat
  24. )
  25. * r
  26. )
  27. def parse_lat_lng(kwargs) -> tuple[float, float] | tuple[None, None]:
  28. """Parses latitude and longitude values stated in kwargs.
  29. Can be called with an object that has latitude and longitude properties, for example:
  30. lat, lng = parse_lat_lng(object=asset)
  31. Can also be called with latitude and longitude parameters, for example:
  32. lat, lng = parse_lat_lng(latitude=32, longitude=54)
  33. lat, lng = parse_lat_lng(lat=32, lng=54)
  34. """
  35. if kwargs is not None:
  36. if all(k in kwargs for k in ("latitude", "longitude")):
  37. return kwargs["latitude"], kwargs["longitude"]
  38. elif all(k in kwargs for k in ("lat", "lng")):
  39. return kwargs["lat"], kwargs["lng"]
  40. elif "object" in kwargs:
  41. obj = kwargs["object"]
  42. if hasattr(obj, "latitude") and hasattr(obj, "longitude"):
  43. return obj.latitude, obj.longitude
  44. elif hasattr(obj, "lat") and hasattr(obj, "lng"):
  45. return obj.lat, obj.lng
  46. elif hasattr(obj, "location"):
  47. return obj.location
  48. return None, None