Coverage for pyguymer3/geo/find_point_on_great_circle.py: 95%
22 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def find_point_on_great_circle(
5 frac,
6 lon1_deg,
7 lat1_deg,
8 lon2_deg,
9 lat2_deg,
10 /,
11):
12 """Calculate an arbitrary point on the great circle that connects two
13 coordinates.
15 This function reads in two coordinates (in degrees) on the surface of the
16 Earth and calculates an arbitrary point on the great circle that connects
17 them, correctly handling crossing over the anti-meridian (should it occur).
19 Parameters
20 ----------
21 frac : float
22 the location of the arbitrary point on the great circle from the first
23 coordinate to the second coordinate
24 lon1 : float
25 the longitude of the first coordinate (in degrees)
26 lat1 : float
27 the latitude of the first coordinate (in degrees)
28 lon2 : float
29 the longitude of the second coordinate (in degrees)
30 lat2 : float
31 the latitude of the second coordinate (in degrees)
33 Returns
34 -------
35 lon3 : float
36 the longitude of the arbitrary point on the great circle (in degrees)
37 lat3 : float
38 the latitude of the arbitrary point on the great circle (in degrees)
40 Notes
41 -----
42 Copyright 2017 Thomas Guymer [1]_
44 References
45 ----------
46 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
47 """
49 # Import standard modules ...
50 import math
52 # Import sub-functions ...
53 from .calc_angle_between_two_locs import calc_angle_between_two_locs
55 # **************************************************************************
57 # Check arguments ...
58 if lon1_deg == lon2_deg and lat1_deg == lat2_deg:
59 return lon1_deg, lat1_deg
60 if frac <= 0.0:
61 return lon1_deg, lat1_deg
62 if frac >= 1.0:
63 return lon2_deg, lat2_deg
65 # Convert to radians ...
66 lon1_rad = math.radians(lon1_deg) # [rad]
67 lat1_rad = math.radians(lat1_deg) # [rad]
68 lon2_rad = math.radians(lon2_deg) # [rad]
69 lat2_rad = math.radians(lat2_deg) # [rad]
71 # Calculate point ...
72 rad = math.radians(calc_angle_between_two_locs(lon1_deg, lat1_deg, lon2_deg, lat2_deg)) # [rad]
73 a = math.sin((1.0 - frac) * rad) / math.sin(rad)
74 b = math.sin(frac * rad) / math.sin(rad)
75 x = a * math.cos(lat1_rad) * math.cos(lon1_rad) + b * math.cos(lat2_rad) * math.cos(lon2_rad)
76 y = a * math.cos(lat1_rad) * math.sin(lon1_rad) + b * math.cos(lat2_rad) * math.sin(lon2_rad)
77 z = a * math.sin(lat1_rad) + b * math.sin(lat2_rad)
78 lat3_rad = math.atan2(
79 z,
80 math.hypot(
81 x,
82 y
83 )
84 ) # [rad]
85 lon3_rad = math.atan2(
86 y,
87 x
88 ) # [rad]
90 # Return point ...
91 return math.degrees(lon3_rad), math.degrees(lat3_rad)