Круг Топойсона D3 с радиусом в милях

(при условии существующей проекции / topojson)

Я пытаюсь создать круг в точке ([long, lat]) радиуса (r) в милях. Я знаю, что для этого есть функция d3.geo, но после некоторого размышления я не думаю, что она будет очень совместима с моим конкретным приложением.

Итак, теперь я ищу собственное решение svg circle, где cx и cy - широта и долгота, а r - радиус в милях. Я знаю cx и cy, но не знаю, как убедиться, что r составляет 15 миль. Итак, главное - как обеспечить масштабирование радиуса в милях при рисовании в пиксельном пространстве. Должен быть способ использовать функцию projection, чтобы установить соответствующий масштаб для радиуса. Но на практике я этого не видел.

Также я должен отметить, что моя проекция является динамической, в зависимости от пользовательских событий проекция (включая масштаб) может меняться. Так что я не уверен, повлияет ли это на масштабирование кругов в контексте существующей проекции, но я подумал, что раскрою это на всякий случай.


person Arash Howaida    schedule 22.03.2017    source источник
comment
Несколько вопросов, которые следует учитывать: 1 миля - это переменное расстояние в пикселях, зависящее от того, где находится пользователь, как вы указываете. Функция проекции наивна для расстояний базовой карты в единицах. Вам нужен способ сообщить функции проекции, сколько 1 мили находится в вашем файле topojson. Один из способов сделать это - вычислить расстояние как долю расстояния вокруг Земли в аркрадианах. См. Здесь: bl.ocks.org/thomasthoren/6a543c4d804f35a240f9   -  person Union find    schedule 25.03.2017
comment
Да, я знаю об этом блоке, я видел его раньше в своих предыдущих исследованиях. Однако это влечет за собой довольно большое расстояние до функции пикселей, и он допускает, что его математика может быть не на 100% верной. Я надеялся, что, предложив награду, я смогу увидеть, есть ли какие-нибудь более изысканные альтернативы.   -  person Arash Howaida    schedule 25.03.2017


Ответы (1)


Почему бы не использовать встроенный генератор кругов d3.geoCircle()?

Возвращает новый объект геометрии GeoJSON типа «Многоугольник», аппроксимирующий круг на поверхности сферы, с текущим center, radius и precision. Любые аргументы передаются методам доступа.

Вам остается только вычислить радиус круга в градусах. Поскольку Земля не является идеальной сферой, это само по себе может стать серьезной проблемой. Но для многих приложений достаточно приближения. Принимая во внимание только средний радиус 3 958 миль, расчеты можно записать как:

var EARTH_RADIUS = 3959;                         // mean radius in miles
var radiusMi     = 5;                            // radius to be drawn in miles
var radiusDeg    = radiusMi / EARTH_RADIUS * 90; // radius in degrees for circle generator

Затем это можно передать генератору кругов:

var circle = d3.geoCircle().radius(radiusDeg);

Наконец, генератор круга используется для передачи его вывода через привязку данных к соответствующему генератору пути с учетом проекции:

svg.append("path")
  .datum(circle)
    .attr("d", path);

Взгляните на этот блок, в котором есть круги радиусом 50 миль каждый в разных точках земного шара. . Генератор кругов в сочетании с проекцией контролирует правильный размер и внешний вид круга.

введите описание изображения здесь


D3 v3

Если вы все еще придерживаетесь D3 v3, пример тоже подойдет. Однако вам необходимо соответствующим образом изменить имена:

Кроме того, были переименованы некоторые методы генератора кругов:

Применяя эти настройки к моему вышеупомянутому связанному блоку, это также работает для v3: v3 Block.


Этот подход раскрывает свои сильные стороны, когда речь идет о необычных проекциях с серьезными искажениями. Это становится легко заметным, просто изменив проекцию в блоке на d3.geoGnomonic(). На следующем снимке экрана из обновленного блока все еще показаны те же круги, что и выше, с радиусом 50 миль. каждый:

введите описание изображения здесь

person altocumulus    schedule 25.03.2017
comment
Отличное объяснение, оно помогает мне понять общую картину. Позвольте мне поиграть с этим и вернуться к вам. - person Arash Howaida; 25.03.2017
comment
После дополнительного тестирования я должен придерживаться своей оценки, о которой я упоминал в первых нескольких строках своего сообщения. Использование родных svg-кругов сделало бы мою жизнь намного проще. Однако ваш ответ здесь был хорошо объяснен, поэтому я был настроен оптимистично и оправдал свое сомнение. Возможно, я не смогу использовать его для своего исходного приложения Circle (нужен svg), но я все еще пытался в этот минимальный блок, который я сделал для проверки вашего d3.geo. Пользуюсь d3 v3. Но не работает. Так что, если вы не возражаете, не могли бы вы решить эти две проблемы? - person Arash Howaida; 26.03.2017
comment
Отбросив на мгновение родные svg-круги. Я предполагаю, что d3.geo.circle может делать все, что умеют собственные круги svg, как только я пойму это лучше. Не поймите меня неправильно, я разогреваюсь до этого подхода, но это немного сложно, потому что дальше по конвейеру идут круги svg, и моя среда ожидает аналогичного взаимодействия. Например, мне нужно иметь возможность динамически изменять радиус. С родным svg: my_circle.attr({r:my_new_radius_value}) Однако, когда я попробовал my_geo_circle.angle(my_new_radius_value), я не получил ошибки функции. Это можно обойти? - person Arash Howaida; 27.03.2017
comment
После добавления: my_geo_circle.datum(new_circle).attr(d, geo_path) я мог динамически изменять радиус. Потерпите мою кривую обучения, я не самый острый инструмент в сарае картографических инструментов. В любом случае, ваше решение сработало довольно хорошо, большое вам спасибо. Настоящим я награждаю вас наградой в размере 50! - person Arash Howaida; 28.03.2017
comment
radiusMi / EARTH_RADIUS * 90 неправильно? Я думаю тебе нужно radiusMi / EARTH_RADIUS * 360 / (2 * Math.PI). - person Ahmed Fasih; 14.09.2020