【发布时间】:2016-09-04 19:10:16
【问题描述】:
使用d3.geo.tile插件,例子都有地图投影的比例和传递给tile()函数的比例的区别。特别是tile_scale = projection_scale * 2 * Math.PI。请参阅示例 here 和 here。
这个 2 * PI 乘法是什么意思?
【问题讨论】:
-
2 PI 暗示某种球面到平面的计算...
使用d3.geo.tile插件,例子都有地图投影的比例和传递给tile()函数的比例的区别。特别是tile_scale = projection_scale * 2 * Math.PI。请参阅示例 here 和 here。
这个 2 * PI 乘法是什么意思?
【问题讨论】:
要了解在使用 d3.geo.tile 插件时为什么要在比例尺上应用额外的 2π 因子,了解 @ 使用的投影之间的差异很重要987654321@ 和绘制光栅图块时使用的那个。
D3 使用以下公式实现标准Mercator projection:
此投影使用以格林威治子午线为中心的单位圆半径R = 1。到目前为止,没有应用缩放或任何平移。投影将产生以下间隔的输出值:
在 D3 v4 中这是 implemented
export function mercatorRaw(lambda, phi) {
return [lambda, log(tan((halfPi + phi) / 2))];
}
D3 v3 使用了稍微不同的表示法,它更接近于上述公式,当然,也等同于较新的实现:
function d3_geo_mercator(λ, φ) {
return [λ, Math.log(Math.tan(π / 4 + φ / 2))];
}
间隔的值经常被d3.geo.mercator() 使用translation 和scaling 的默认值这一事实所掩盖。您必须明确地将它们设置为 .translate([0,0]).scale(1) 才能获得上述间隔。
另一方面,Tiles 使用一个稍微修改过的墨卡托投影版本,称为Web Mercator。相关公式为
该投影的核心是使用与标准墨卡托投影相同的计算。这可以从上述方程右侧的黑色项中轻松看出,这些项与墨卡托投影所使用的项完全相同。只是通过应用一些缩放和平移来调整输出间隔以更好地适应屏幕显示的需要。
首先,南北纬都超过投影被截断
从而将整个地图投影到一个正方形上。之后,有三处调整(上式中按颜色匹配):
这将产生间隔的输出值
正是所涉及的投影比例的差异,这就是您需要乘以/除以 2π 的原因。如果您想同时使用d3.geo.mercator() 以及同一地图中的瓦片,则需要修改比例以相互匹配。
对标准墨卡托投影施加与 Web 墨卡托投影相同的纬度限制,您最终会得到以下间隔:
标准墨卡托投影
项目到区间
有 长度 = 2π。
网络墨卡托投影
项目到区间
有 长度 = 256。
在设置投影比例时会更正
var projection = d3.geoMercator()
.scale((1 << 12) / 2 / Math.PI );
使用简单的幂运算,比例因子可以重写为
(1 << 4) * (1 << 8) / 2 / Math.PI
还有更多
(1 << 4) * 256 / ( 2 * Math.PI )
第一项(1 << 4) 等于24,这是要使用的实际缩放系数:16。这将获得zoom level 4 的图块。下一届
是调整比例的校正因子,其中包括您的问题所涉及的 2π。
【讨论】:
一些d3 投影,包括d3.geo.mercator(在这些示例中使用)具有自然比例,经度范围从-π 到π:
var s = d3.geo.mercator().translate([0,0]).scale(1);
s([180, 0]); // [3.141592653589793, 0]
s([-180, 0]); // [-3.141592653589793, 0]
这是一个简单的默认比例,因为您可以在 d3.geo.mercator 投影 (Wikipedia formula) 中看到,投影的 x 值与经度角成线性比例。如果您将 Web 墨卡托投影视为展开和展平一个完美的球体,这是非常有意义的 - 围绕球体圆周的 1 度将等于 x 距离的 1 个单位。因此,D3 实现根本不缩放经度 - 它只是将其作为 x 值 (see code) 返回。经度以弧度为单位输入此函数,因此它具有从-π 到π 的自然范围,即描述圆的整个圆周的2π 角度。
但重点是每个比例的比例因子是effectively arbitrary,并且在预测中不一致。
所以基本上,2 * Math.PI 代表刻度的最大范围,除以这个因子意味着将此范围归一化为 1 以便于计算。
【讨论】:
1 << 12,即2^12,它位于图块缩放范围的中间。说var initialZoom = 1 << 12; 并将投影缩放到initialZoom / 2 / Math.PI 会更清楚。
-π到π;由于x 随经度线性缩放,使用-π 到π 作为输出范围意味着您根本不需要缩放x,只需返回输入经度即可。