Search code examples
pythonpython-3.xmapsfoliumgeopy

How can I include many coordinates on a map within a circle with Python?


I have a list of coordinates. Can I draw on map a circle that briefly covers them? I was thinking about using the folium package and drawing a circle centered at the average coordinates with radius of the distance to the farthest point. However, it turns out radius doesn't correspond to real distance on map, so it wouldn't change accordingly when I zooming in/out.

import folium
import numpy as np
from geopy.distance import geodesic

points = [(39.9756783, 116.3308383),
          (39.9756649, 116.3308749),
          (39.97564, 116.3308749),
          (39.9756533, 116.3308583),
          (39.9756316, 116.3308299)]
center = (np.mean([a for a,b in points]), np.mean([b for a,b in points]))
MAP = folium.Map(location = list(center), zoom_start = 10)
folium.CircleMarker(location = list(center), 
                    radius = max([geodesic(center,point).meters for point in points]),
                    color = '#3186cc', fill = True, fill_color = '#3186cc'
                   ).add_to(MAP)
MAP

When the list is too long to pinpoint every pair of coordinates, I really want to roughly illustrate the scope they fall into.


Solution

  • IIUC, you could use Circle(), which gives you the opportunity to specify the radius in meters (note that I multiply the max by 10 in order to get a larger circle).

    For example:

    import folium
    import numpy as np
    from geopy.distance import geodesic
    
    points = [(39.9756783, 116.3308383),
              (39.9756649, 116.3308749),
              (39.97564, 116.3308749),
              (39.9756533, 116.3308583),
              (39.9756316, 116.3308299)]
    center = (np.mean([a for a,b in points]), np.mean([b for a,b in points]))
    MAP = folium.Map(location = list(center), zoom_start = 10)
    
    for p in points:
        folium.Marker(p).add_to(MAP)
    
    folium.Circle(location = list(center),
                        radius = max([geodesic(center,point).meters for point in points])*10,
                        color = '#3186cc',
                        fill = True,
                        fill_color = '#3186cc').add_to(MAP)
    MAP
    

    and zooming in you get:

    enter image description here