d3 地理投影从正交过渡到 X

d3 geo projection transitions from orthographic to X

我正在处理一个显示不同地图投影的教育地图项目。我想在选择不同的投影之间实现变形过渡。

我找到了一个很好的例子来实现它,而且我没有太多的麻烦来重新创建它。不幸的是,我还需要能够裁剪投影。这对目标状态完美无缺,但在变形投影时却不行。

选择“正码”作为第一个投影,例如“ equiretangular”作为第二个: https://bl.ocks.org/alexmacy/082cb12c8f4d5c0d5c4445c16a3db383

裁剪路径沿着较暗的线而不是当前地图范围。有没有正确实现的方法?

实现起来比看起来要复杂得多,我记得几年前看过这个。最干净的解决方案是创建一个新的预裁剪函数,该函数确定投影地球的哪些部分应该 behind/covered 靠近原点的部分。但事实证明,这相对难以定义——至少我是这样——而且也很难在新的预裁剪函数中使用。

相反,我们可以作弊。有几种方法,我会提出一种几乎可以解决问题的方法——尽管您仍然可以看到一些重叠。我们将使用 d3 的反子午线预裁剪来确保没有特征延伸到反子午线上,然后我们将使用裁剪角度来移除需要移除的地球部分。

设置剪辑角度

当混合投影正交时,夹角很大:各个方向的夹角都一样。这里应该是90度。

当等距柱状投影在混合投影中占优势时,不需要裁剪角(我使用的是180度角,不会裁剪下面的任何东西)。这是因为整个地球应该还是可见的。

但除此之外,混合剪辑角度在所有方向上都不相同 - 这就是为什么这不是一个完美的解决方案。但是,它确实消除了几乎所有的重叠。因此,当我们从主要是等距柱状投影到完全正交投影时,我们会慢慢减小夹角。

例子

从等距柱状投影开始过渡到正交投影,只有在过渡完成 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

安德鲁·里德回答得好!我只是做了一个小改动。我删除了 t > 0.4 if 语句并使用此剪辑 转换为正交投影:

clip = Math.PI/2 + (1 - t) * Math.PI/2

.. 以及此片段 从正交投影中过渡 :

clip = Math.PI/2 + t * Math.PI/2

我喜欢这个,因为它稍微干净一些,是任何 t 值的 'catch-all',反过来也很有用。