D3.geo:球面弧线而不是直线的平行线?

Hug*_*lpz 6 d3.js topojson d3.geo

我刚刚创建了一个D3js globe localisator,它看起来像这样:

在此输入图像描述

如果仔细观察,红色方块看起来很难看,因为它不符合地球的曲线.我有十进制度的区域边界框:

var bb = {W:-5.0, N:50.0, E:10.0, S:40.0 }
Run Code Online (Sandbox Code Playgroud)

我画的线条如下:

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

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

在此输入图像描述

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

Hug*_*lpz 10

在此输入图像描述

给定一个已知的十进制度边界框(从这里开始挖掘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
Run Code Online (Sandbox Code Playgroud)

有些数学是必需的.

// *********** 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;
}   
Run Code Online (Sandbox Code Playgroud)

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

// *********** 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 });
Run Code Online (Sandbox Code Playgroud)

第180经络:第180经线上的盒子需要特殊管理.例如,在155⁰东和-155 West之间定位一组太平洋岛屿最初给出.... 在此输入图像描述 ......旋转正确(+180⁰): 在此输入图像描述 ......并且正确的拳击: 在此输入图像描述

Localisator现在完美!块上的现场演示

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);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

+1欢迎.


Jos*_*osh 9

您可以使用d3的内置格线生成器:

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]]);
Run Code Online (Sandbox Code Playgroud)

然后使用格线生成器的outline函数绘制路径:

svg.append("path")
    .attr("class", "arc")
    .attr("d", path(arc.outline()));
Run Code Online (Sandbox Code Playgroud)

地理'弧'

完整的工作示例可以在这里找到.