#javascript #d3.js #topojson #map-projections
#javascript #d3.js #topojson #карта-проекции
Вопрос:
Я создаю карту Филиппин с d3.js и по странной причине карта выглядит повернутой влево, так что страна выглядит не такой, какая она есть на самом деле. Я пытался изменить поле projection.rotate, но, похоже, это не линия коррекции.
var width = 1060,
height = 860;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.style("overflow", "auto");
d3.json("ph.json", function(error, ph) {
if (error) return console.error(error);
var subunits = topojson.feature(ph, ph.objects.ph_subunits);
var projection = d3.geo.albers();
projection.rotate([-4 ,0]);
projection.scale(3000);
projection.center([122.427150, 12.499176]);
projection.parallels([10, 15])
projection.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection)
.pointRadius(2);
svg.append("path")
.datum(subunits)
.attr("d", path);
});
Это код.
Любая помощь была бы отличной!
Спасибо!
Ответ №1:
Проекции Альберса могут быть немного сложными, если вы не знаете базовых преобразований. Если не показывать США (для которых по умолчанию заданы параметры d3.geoAlbers), вам, вероятно, потребуется изменить параллели, поворот и центр.
Стандартные параллели
Это проекция Альберса, для параллелей которой установлены значения 10 и 15 .parallels([10,15])
, как в вашем вопросе, и масштаб 100 (а для поворота и центра установлено значение [0,0]):
Такая форма обусловлена конической природой проекции. Если выбраны южные параллели, вогнутость меняется на противоположную. Более экстремальные широты / параллели приведут к большему изгибу.
Выбранные параллели должны проходить через интересующую вас область, поскольку область рядом с параллелями — это место, где искажения минимизированы.
Поворот
Если бы мы хотели сказать, сосредоточьтесь на Австралии (я сохраню параллели такими же, как на изображении выше, для демонстрации):
Мы могли бы просто использовать географический центр Австралии в качестве центра проекции .projection.center([x,y])
и масштабировать до соответствующего уровня .projection.scale(1000)
:
Единственное изменение заключается в том, что Австралия больше, она по-прежнему так же искажена, как когда она была в углу карты, и меньше. Она была сдвинута вверх / вниз и влево / вправо, а затем увеличена без каких-либо других преобразований.
Как следует из вашего вопроса, вращение — это решение проблемы отображения областей, расположенных не вблизи нулевого меридиана.
Если мы повернем первую карту (которая совпадает со второй картой) на 100 градусов долготы .projection.rotate([100,0])
, мы получим:
Мир развернулся на 100 градусов, и воображаемая линия, проведенная вертикально через центр карты, совпадает с меридианом на -100 градусов долготы или 100 градусов западной долготы.
Центрирование
Если наша область интересов — Центральная Америка (для которой параллели, которые вы использовали — и я продолжаю использовать — будут работать), то следующим шагом будет смещение центра карты вверх и вниз вдоль центрального меридиана проекции. Для Центральной Америки этот сдвиг может составлять 20 градусов : .projection.center([0,20])
. При соответствующем масштабе, скажем, 1000, результат будет выглядеть так:
Филиппины
Итак, для Филиппин, используя вашу центральную координату [122.427150, 12.499176] и параллели, идеальная проекция Альберса может выглядеть так:
projection.rotate([-122.427150,0])
.center([0,12.499176])
.scale(1200)
.parallels([10,15]);
Краткие сведения
Для Альберса:
projection.parellels([a,b])
.rotate([-x,0])
.center([0,y])
.translate([w/2,h/2])
Где a
и b
— параллели, пересекающие интересующую область, y
центральная параллель и x
центральный меридиан.
При использовании метода ( projeciton.fitSize
/ projection.fitExtent
) для автоматического центрирования и масштабирования объекта вам не нужно использовать методы center и rotate, но вы все равно должны сначала установить параллели и поворот.