GeoDjango:如何根据点和半径在地球上的任何地方创建一个圆?

问题描述

我有一个this one 类似的问题。使用 geodjango,我想在地图上绘制一个以公里为单位的特定半径的圆。但是,建议的解决方

a) 不使用公里而是使用度数,并且

b) 进一步向北或向南变成椭圆形。

这是我所做的:

from django.contrib.gis import geos
lat = 49.17
lng = -123.96
center = geos.Point(lng,lat)

radius = 0.01
circle = center.buffer(radius)

# And I then use folium to show a map on-screen:
map = folium.Map(
    location=[lat,lng],zoom_start=14,attr="MapBox"
)
folium.GeoJson(
    circle.geojson,name="geojson",).add_to(map)

结果如下:

Map with oval

我该怎么办

a) 画一个半径始终为 3 公里的圆,与地球上的位置无关,并且

b) 确保在所有纬度都是圆形而不是椭圆形?

解决方法

这是代码

from django.contrib.gis import geos
import folium

lat = 49.17
lng = -123.96
center = geos.Point(x=lng,y=lat,srid=4326)

center.transform(3857) # Transform Projection to Web Mercator     
radius = 3000 # now you can use meters
circle = center.buffer(radius) 
circle.transform(4326) # Transform back to WGS84 to create geojson

# And I then use folium to show a map on-screen:
map = folium.Map(
    location=[lat,lng],zoom_start=14,attr="Mapbox"
)
geojson = folium.GeoJson(
    circle.geojson,name="geojson",)

geojson.add_to(map)

说明

这个问题是由地图投影引起的。

纬度/经度坐标由地图投影 WGS84 表示。值以度为单位。

您在 folium 中看到的地图有另一个地图投影 (Web Mercator)。它试图将世界表示为一个平面,从而产生向北和向南的扭曲。坐标值以米为单位。

在地球上,您创建的圆看起来完全是圆的,但由于 folium 使用了另一个投影,所以它会变形。

了解每个投影都由一个数字(EPSG 代码)表示也很重要。使用此 epsg 代码,您可以将坐标从一种投影转换为另一种投影。

  • Web 墨卡托 -> EPSG 3857
  • WGS84 -> EPSG 4326

使用我的代码,您现在可以在 Web Mercator 中获得一个圆形的大叶圆,但请注意,在地球上看它时,它会看起来是椭圆形和扭曲的。

Circle on a map

这只是一个非常简单的解释。您可以查看 Map Projections 以更好地理解问题。 本指南提供了一个很好的概述: Map Projections

,

试试这个

folium.Circle(
radius=3000,location=[lat,popup="Whatever name",color="#3186cc",fill=True,fill_color="#3186cc",).add_to(m)