Puedes usar la biblioteca proj4 para describir un círculo usando la distancia del gran círculo.
Por ejemplo, aquí hay un radio de 3000 km desde Edimburgo, Tokio, Ciudad del Cabo y Quito en wgs84/Equirectangular. Solo Quito es vagamente 'redondo', debido a su proximidad al ecuador. También he agregado una sola línea de radio densificada con un azimut de 36 grados (aprox. NE)
Si cambiamos a una proyección equidistante azimutal centrada en Edimburgo, verás que el radio alrededor de Edimburgo se resuelve en un círculo...
En Mercator (como tu aplicación web), ves más distorsión a medida que te alejas del ecuador, pero los buffers son más elípticos.
El siguiente código de Python hace eso (requiere pyproj y shapely)
import pyproj
from shapely.geometry import Polygon, MultiPoint, LineString
import math
def geodesicpointbuffer(longitude, latitude,
segments, distance_m,
geom_type=MultiPoint):
"""
Crea un buffer en metros alrededor de un punto dado como longitud, latitud en WGS84
Usa la geodésica, por lo que debería ser más preciso en distancias largas
:param longitude: longitud de punto central
:param latitude: latitud de punto central
:param segments: segmentos para aproximar (más = más suave)
:param distance_m: distancia en metros
:param geom_type: tipo shapely (por ejemplo, Multipoint, Linestring, Polygon)
:return: tupla (cadena proj4, WKT de la geometría del buffer)
"""
geodesic = pyproj.Geod(ellps='WGS84')
coords = []
for i in range(0, segments):
angle = (360.0 / segments) * float(i)
x1, y1, z1 = geodesic.fwd(lons=longitude,
lats=latitude,
az=angle,
dist=distance_m,
radians=False)
coords.append((x1, y1))
# hace un gran círculo para una línea de radio.
if i==200:
example = geodesic.npts(longitude,latitude,x1,y1,1000)
coords2 = []
for xx,yy in example:
coords2.append((xx,yy))
coords2.append((x1,y1)) # asegúrate de incluir el punto final ;-)
flight = LineString(coords2)
print(flight.wkt)
ring = geom_type(coords)
return "+init=EPSG:4326", ring.wkt
def main():
# ejemplo: Ciudad del Cabo. Buffer de 3000 km.
spec, wkt = geodesicpointbuffer(18.4637082653, -33.8496404007, 2000, 3000000.0, Polygon)
print(spec)
print(wkt)
if __name__ == "__main__":
main()
Puedes pegar la salida de WKT en QGIS usando el útil plugin QuickWKT.
Puedes usar otros métodos - como mencionó coneypylon, puedes crear un círculo en una proyección equidistante personalizada en metros, centrada en tu punto de partida. Sin embargo, encuentro que para distancias largas se produce un error (solo unos pocos km a 2000 km, pero para distancias intercontinentales estos errores pueden acumularse)
De memoria, el complemento mmqgis permite realizar buffering en km. No estoy seguro qué método utiliza, sin embargo.
Ten en cuenta que puedes tener problemas para renderizar polígonos en QGIS que crucen el antimeridiano si estás comenzando en Asia - ogr2ogr con la opción -wrapdateline puede ayudar aquí. Es posible que encuentres que esto es menos problema con openlayers/leaflet, si mal no recuerdo, permiten longitudes mayores que 180 y menores que -180.
Hay un buen artículo sobre el buffering geodésico aquí en el blog de esri.