半径以英里为单位的 D3 Topojson 圆

D3 Topojson Circle with Radius Scaled in Miles

(假设现有 projection/topojson)

我想做的是在半径 (r) 以英里为单位的点 ([long,lat]) 处创建一个圆。我知道为此有一个 d3.geo 函数,但经过一番考虑后,我认为它与我的特定应用程序不太兼容。

所以现在我正在寻找使用原生 svg circle 的解决方案,其中 cx 和 cy 是纬度和经度,r 是以英里为单位的半径。我知道 cx 和 cy,但我不知道如何确保 r 是 15 英里。所以最主要的是如何确保在以像素 space 绘制时以英里为单位缩放半径。一定有办法使用 projection 函数来为半径设置适当的比例。但是我没有在实践中看到这个。

我还应该指出,我的投影是动态的,根据用户事件投影(包括比例)可以改变。所以我不确定这是否会影响圆圈在现有投影的上下文中的缩放方式,但我想为了安全起见我会透露这一点。

为什么不使用内置的圆生成器d3.geoCircle()

Returns a new GeoJSON geometry object of type “Polygon” approximating a circle on the surface of a sphere, with the current center, radius and precision. Any arguments are passed to the accessors.

留给您的唯一任务就是计算圆的半径(以度为单位)。因为地球不是一个完美的球体,所以这本身就是一个挑战。但对于许多应用程序来说,一个近似值就足够了。仅考虑 3,958 mimean radius,计算可写为:

var EARTH_RADIUS = 3959;                         // mean radius in miles
var radiusMi     = 5;                            // radius to be drawn in miles
var radiusDeg    = radiusMi / EARTH_RADIUS * 90; // radius in degrees for circle generator

然后可以将其传递给圆生成器:

var circle = d3.geoCircle().radius(radiusDeg);

最后,圆生成器用于通过数据绑定将其输出传递给考虑到投影的适当路径生成器:

svg.append("path")
  .datum(circle)
    .attr("d", path);

看看这个 Block,它以 50 英里半径的圆圈为特色,每个圆圈位于全球不同的位置。圆形生成器与投影相结合将控制正确的尺寸和正确的圆形外观。


D3 v3

如果您仍然坚持使用 D3 v3,该示例也适用。但是,您需要相应地调整 names

除此之外,圆生成器的一些方法已重命名:

将这些调整应用于我上面的链接块,这也适用于 v3:v3 Block.


当涉及到具有严重扭曲的异常投影时,这种方法可以发挥其优势。只需将块中的投影更改为 d3.geoGnomonic() this becomes easily visible. The following screenshot from the updated Block 仍会显示与上述相同的圆,每个圆的半径为 50 英里: