d3.geo.path 矩形包裹错误的方式

Posted

技术标签:

【中文标题】d3.geo.path 矩形包裹错误的方式【英文标题】:d3.geo.path rectangle wrapping the wrong way 【发布时间】:2016-02-05 01:41:01 【问题描述】:

这个简单的 geojson 矩形在一些 geojson 查看器中正确显示,我得到了一个预期的矩形。但是当我用 d3 做它时,矩形似乎环绕。

var polygonData = 
      "type": "Feature",
      "geometry": 
        "type": "Polygon",
        "coordinates": [
          [
            [ -100, -20 ],
            [ -100, 20 ],
            [ 100, 20 ],
            [ 100, -20 ],
            [ -100, -20 ]
          ]
        ]
      ,
      "properties": 
    ;
    
    var width = 1000;
    var height = 500;
    
    var projection = d3.geo.equirectangular()
      .scale(100)
      .translate([width / 2, height / 2])
      .rotate([0, 0])
	  .center([0, 0])
      .precision(0);
    
    var path = d3.geo.path()
	  	.projection(projection);

    var svg = d3.select("body").append("svg")
      .attr(
        width: width,
      	height: height
      );

    svg.append('path')
      .datum(polygonData)
      .attr(
        d: path,
        fill: 'orange',
        opacity: 0.5
      );
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
  <style>
  </style>
</head>

<body>

</body>

这是我通过geojson viewer 得到的:

但这就是我从上面的d3 code得到的:

颠倒缠绕顺序只会填充相反的形状,并不能解决问题。我猜这是一个逆子午线切割问题。一种解决方法是添加一些中间点以强制路径不环绕,但我需要能够使用更复杂的路径自动执行此解决方案。

知道如何将这个 geojson 与 d3 一起使用,并强制它像其他 geojson 查看器一样显示为地图上的一个简单矩形?

【问题讨论】:

从他默认的反子午线切割切换到小圆圈切割似乎可以解决问题:projection.clipAngle(181) ***.com/a/30996241/537080 我想知道是否更好的解决方法是使用投影流? 【参考方案1】:

我不认为,D3 有什么可责备的;据我了解,错误的是其他 GeoJSON 查看器。作为一个生活在或多或少平坦的表面上的人,很容易被欺骗相信一个具有四个角的多边形,具有像您这样精心选择的坐标,应该看起来像一个矩形。在足够小的尺度上并给出合适的投影,这甚至适用于球面几何。但由于您的点几乎相隔半个地球,因此情况并非如此。

为了阐明这一点,我使用正交投影来显示一些地理特征以及您的多边形:

从这个视图可以明显看出,沿子午线的线是连接点[-100,-20][-100,20] 的第一条边。从那一点[-100,20] 在墨西哥西北部的某个地方是great arc,即最短的连接,到下一点[100,20] 绕地球半个地球。然后该路径在南半球周围同样封闭。因此,多边形的轮廓是地球表面上按给定顺序连接所有点的最短路径。

虽然您的多边形是由它的坐标决定的,但它的外观将取决于所使用的投影。这是使用墨卡托投影的同一多边形的另一个视图:

【讨论】:

感谢您的精彩解释。我同意我得到的形状是连接点和填充形状的合乎逻辑的方式。但是我需要的表示仍然应该看起来像等角投影中的矩形。了解默认情况下 d3 将按照最短路径连接点,这使我找到了一种方法来迫使它走更长的路。使用 projection.clipAngle 似乎可行。 @Biovisualize Ab使用projection.clipAngle() 感觉就像在欺骗我。我认为这是一条危险的道路,因为它要显示所需的输出,它依赖于 1)通过将其设置为 >180 度来关闭剪辑,以及 2)通过设置 .precision(0) 来关闭自适应重采样。除了这些设置的副作用之外,如果这些先决条件中的任何一个发生变化,您的可视化就会中断。 我完全同意,但是在 equirectangular 位置在这个位置获得一个矩形的解决方案是什么?也许根本不使用 d3.geo.path? @Biovisualize 沿着平行线画一条线会很繁琐,涉及到很多中间点。我认为这很值得提出一个新问题。这在很大程度上取决于你真正追求的是什么。甚至可能值得考虑使用未投影的矩形。但这又取决于你想用那个矩形实现什么。目前你的问题有点像XY problem。尝试解释您的实际问题,而不是您为什么认为您尝试的解决方案存在一些缺陷。 你是对的,我会关闭这个,你的回答是有道理的。我需要将其显示为“在地图上作为一个简单的矩形”,因为它是围绕某些特征的边界框,但标题和解释并不清楚。无论如何,我有一些解决方案:hacky 剪裁,作为非投影路径的简单绘图(而不是在我的 equirectangular 情况下工作的 geo.path),并且还为切割逻辑添加中间点以选择其他方式作为最短路径。谢谢!

以上是关于d3.geo.path 矩形包裹错误的方式的主要内容,如果未能解决你的问题,请参考以下文章

D3绘制空投影的经度/纬度

Angular2中的GeoJson地图

d3.js 地图上的鱼眼失真

如何计算边界矩形的宽度,以使文本包裹以适合特定比例?

包裹系统编写以及过程中发现的错误

包裹第 n 个或更少的元素,错误的结果