D3.geo: Сферические дуги, а не прямые линии для параллелей?

Я только что сделал локализатор глобуса 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);

Для больших площадей это даже кривая, противоположная ожиданиям (для ограничительной рамки):

Как добавить достаточно элегантные сферические дуги?

2 ответа

Решение

Учитывая известную ограничивающую рамку в десятичных градусах ( начните здесь для 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⁰):... и с правильным боксом:

Локализатор теперь идеален! Живая демо на блоках

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 добро пожаловать.

Для этого вы можете использовать встроенный генератор координатной сетки 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]]);

Затем используйте функцию структуры генератора сетки, чтобы нарисовать путь:

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

географическая

Полный рабочий пример можно найти здесь.

Другие вопросы по тегам