d3 地理投影从正交到 X 的转换

问题描述

我正在开发一个教育地图项目,其中显示了不同的地图投影。我想在选择不同的投影之间实现变形过渡。

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

您可以在此示例中在选择“正交”作为第一个投影时看到它,例如“Equirectangular”为第二个: https://bl.ocks.org/alexmacy/082cb12c8f4d5c0d5c4445c16a3db383

剪切路径遵循较暗的线条而不是当前地图范围。有没有办法正确实现它?

解决方法

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

相反,我们可以作弊。有几种方法,我将提出一种几乎可以解决问题的方法 - 尽管如此,您仍然可以看到一些重叠。我们将使用 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 值的“包罗万象”,反过来也很有用。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...