这比看起来要困难得多,我记得几年前看过这个。最干净的解决方案是创建一个新的预剪裁函数,该函数确定投影地球的哪些部分应该位于更靠近原点的部分后面/覆盖。但事实证明,这相对难以定义——至少我自己——而且也很难在新的预裁剪函数中使用。
相反,我们可以作弊。有几种方法,我将提出一种几乎可以解决问题的方法 - 不过您仍然可以看到一些重叠。我们将使用 d3 的反子午线预裁剪来确保没有任何要素超出反子午线,然后我们将使用裁剪角度来删除需要删除的地球部分。
设置夹角
当混合投影为purely正交,剪角很大:剪角在所有方向上都是相同的。这里应该是90度。
当等距长方体为dominant在混合投影中,不需要剪切角度(我使用 180 度的角度,不会剪切下面的任何内容)。这是因为整个地球应该仍然可见。
但除此之外,混合夹角在所有方向上都不相同 - 这就是为什么这不是一个完美的解决方案。然而,它确实消除了几乎所有的重叠。因此,当我们从大部分等矩形投影变为完全正交投影时,我们会慢慢减小夹角。
Example
从等距柱状投影开始并过渡到正交投影,只有当过渡完成 40% 时,我们才会开始将 ClipAngle 从 180 度过渡到 90 度:
function getProjection(d) {
var clip = Math.PI; // Starting with 180 degrees: don't clip anything.
var projection = d3.geoProjection(project)
.rotate([posX, posY])
.fitExtent([[10, 10], [width - 10, height - 10]], {
type: "Sphere"
})
// Apply the two pre clipping functions:
.preclip( function(stream){
stream = d3.geoClipAntimeridian(stream) // cut antimeridian
return d3.geoClipCircle(clip)(stream) // apply clip angle
})
var path = d3.geoPath(projection);
function project(λ, φ) {
λ *= 180 / Math.PI,
φ *= 180 / Math.PI;
var p0 = projections[0]([λ, φ]),
p1 = projections[1]([λ, φ]);
// Don't actually clip anything until t == 0.4
if(t > 0.4) {
clip = Math.PI/2 + (0.60-(t-0.4)) * Math.PI/2
}
return [
(1 - t) * p0[0] + t * p1[0],
(1 - t) * -p0[1] + t * -p1[1]
];
}
return path(d)
}
这是一个example https://bl.ocks.org/Andrew-Reid/629a24623efc14bc514262522dbb58bd.