I am not that experienced in python but improving it thanks to this community! I desperately need a function which takes the input and gives the ouput below:
Depending on the precision you need, you may or may not consider the Earth as a sphere. In the second case, calculations become more complex.
The best option for precise measurements when the radius is small (as in your example) is to use a projection (UTM for example) and then apply the common flat euclidean calculations.
Let's first copy the flat circle intersection function from https://stackoverflow.com/a/55817881/2148416:
def circle_intersection(x0, y0, r0, x1, y1, r1):
d = math.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
if d > r0 + r1: # non intersecting
return None
if d < abs(r0 - r1): # one circle within other
return None
if d == 0 and r0 == r1: # coincident circles
return None
a = (r0 ** 2 - r1 ** 2 + d ** 2) / (2 * d)
h = math.sqrt(r0 ** 2 - a ** 2)
x2 = x0 + a * (x1 - x0) / d
y2 = y0 + a * (y1 - y0) / d
x3 = x2 + h * (y1 - y0) / d
y3 = y2 - h * (x1 - x0) / d
x4 = x2 - h * (y1 - y0) / d
y4 = y2 + h * (x1 - x0) / d
return (x3, y3), (x4, y4)
The precise calculation for a small radius (up to a few kilometers) can be done in UTM coordinates with the help of the utm library. It handles all the complications regarding the fact the the Earth is more an ellipsoid than a sphere:
import utm
def geo_circle_intersection(latlon0, radius0, latlon1, radius1):
# Convert lat/lon to UTM
x0, y0, zone, letter = utm.from_latlon(latlon0[0], latlon0[1])
x1, y1, _, _ = utm.from_latlon(latlon1[0], latlon1 [1], force_zone_number=zone)
# Calculate intersections in UTM coordinates
a_utm, b_utm = circle_intersection(x0, y0, r0, x1, y1, r1)
# Convert intersections from UTM back to lat/lon
a = utm.to_latlon(a_utm[0], a_utm[1], zone, letter)
b = utm.to_latlon(b_utm[0], b_utm[1], zone, letter)
return a, b
Using your example (with slightly larger radii):
>>> p0 = 50.851295, 5.667969
>>> r0 = 2000
>>> p1 = 50.844101, 5.725889
>>> r1 = 3000
>>> a, b = geo_circle_intersection(p0, r0, p1, r1)
>>> print(a)
(50.836848562566004, 5.684869539768468)
>>> print(b)
(50.860635308778285, 5.692236858407678)