【问题标题】:D3.geo : Spherical arcs rather than straight lines for parallels?D3.geo:平行线是球弧而不是直线?
【发布时间】:2023-03-19 21:44:01
【问题描述】:

我刚刚制作了一个 D3js 地球定位器,如下所示:

如果你仔细看,红色方块看起来很丑,因为它不遵循地球的曲线。我有十进制度的区域边界框:

var bb = {W:-5.0, N:50.0, E:10.0, S:40.0 }

我画的线如下:

svg.append("path")
.datum({type: "LineString", coordinates: 
        [[-5, 40], [-5, 50], [10, 50], [10, 40], [-5, 40]]
       })
.attr("d", path);

对于更大的区域,它甚至是与预期相反的曲线(对于边界框):

如何添加相当优雅的球弧?

【问题讨论】:

    标签: d3.js topojson d3.geo


    【解决方案1】:

    给定一个已知的十进制度边界框 (dig in start here for bb),例如:

      bounds = [[-50.8,20.0][30,51.5]];
      WNES0 = bounds[0][0], // West    "W":-50.8  
      WNES1 = bounds[1][2], // North   "N": 51.5
      WNES2 = bounds[1][0], // East    "E": 30
      WNES3 = bounds[0][3], // South   "S": 20.0
    

    需要一些数学知识。

    // *********** MATH TOOLKIT ********** //
    function parallel(φ, λ0, λ1) {
      if (λ0 > λ1) λ1 += 360;
      var dλ = λ1 - λ0,
          step = dλ / Math.ceil(dλ);
      return d3.range(λ0, λ1 + .5 * step, step).map(function(λ) { return [normalise(λ), φ]; });
    }
    function normalise(x) {
      return (x + 180) % 360 - 180;
    }   
    

    然后,让我们计算多边形的坐标并进行投影:

    // *********** APPEND SHAPES ********** //
    svg.append("path")
    .datum({type: "Polygon", coordinates: [
        [[WNES0,WNES3]]
          .concat(parallel(WNES1, WNES0, WNES2))
          .concat(parallel(WNES3, WNES0, WNES2).reverse())
      ]})
    .attr("d", path)
    .style({'fill': '#B10000', 'fill-opacity': 0.3, 'stroke': '#B10000', 'stroke-linejoin': 'round'})
    .style({'stroke-width': 1 });
    

    180经: 180经上的箱子需要特别管理。例如,将一组太平洋岛屿定位在东 155⁰ 和西 -155 之间最初会给出.... ...正确旋转(+180⁰): ...并使用正确的拳击:

    本地化器现在完美! Live demo on blocks

    var bb = { "item":"India", "W": 67.0, "N":37.5, "E": 99.0, "S": 5.0 }, 
    localisator("body", 200, bb.item, bb.W, bb.N, bb.E, bb.S);
    

    欢迎+1。

    【讨论】:

      【解决方案2】:

      您可以为此使用 d3 内置的 graticule generator

      var bb = {W: -5.0, N: 50.0, E: 10.0, S: 40.0 };
      var arc = d3.geo.graticule()
          .majorExtent([[bb.W, bb.S], [bb.E, bb.N]]);
      

      然后使用刻度生成器的轮廓功能来绘制路径:

      svg.append("path")
          .attr("class", "arc")
          .attr("d", path(arc.outline()));
      

      可以在here找到完整的工作示例。

      【讨论】:

      • 根据文档github.com/mbostock/d3/wiki/Geo-Paths#graticule_majorExtent 需要稍作修正。.majorExtent([[bb.W, bb.E], [bb.N, bb.S]]); 更改为.majorExtent([[bb.W, bb.S], [bb.E, bb.N]]);,然后它就摇摆不定!
      • (我编辑了文字,等待验证。图片要更新)
      • 我未能成功让感兴趣的区域穿过 180 度经线。这种情况很少见,但可能需要检查和探索。
      猜你喜欢
      • 1970-01-01
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 2015-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多