Располагайте изменяемые круги вокруг друг друга

Я работаю над этим экспериментом на основе браузера, где мне дают N определенных кругов (скажем, у них есть уникальная картина в них), и им нужно их расположить вместе, оставляя как можно меньше места между ними. Он не должен располагаться по кругу, но они должны быть "сгруппированы" вместе.

Размеры окружности настраиваются, и пользователь сможет изменить размеры, перетащив ползунок javascript, изменив размеры некоторых кругов (например, в 10% слайдера круг 4 будет иметь радиус 20 пикселей, круг 2 10px, круг 5 остается неизменным и т.д.). Как вы, возможно, уже догадались, я попытаюсь "переходить" на изменение размера при правильном перемещении при перемещении ползунка.

Подход, который я пробовал до сих пор: вместо того, чтобы вручную их расположить, я попытался использовать физический движок -

my approach example

Идея:

  • поместите какое-то гравитационное натяжение в центр экрана.
  • используйте физический движок, чтобы заботиться о столкновении с шарами.
  • во время слайдера "перетащить время" я бы просто установил разные размеры шара и пусть двигатель позаботится об остальном

Для этой задачи я использовал "box2Dweb". Я поместил гравитационное притяжение в центр экрана, однако потребовалось очень долгое время, пока шары не были помещены в центр, и они плыли вокруг. Затем я положил небольшой статический кусок шара в центр, чтобы они ударили его, а затем остановились. Это выглядело так:

box2d trial

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

Итак, подход box2d заставил меня понять, что, возможно, оставить физический движок для решения этой проблемы не лучшим решением проблемы. Или, может быть, мне нужно включить какую-то другую силу, о которой я не думал. Я нашел этот аналогичный вопрос для моего на StackOverflow. Однако очень важным отличием является то, что он просто генерирует некоторые n неспецифических кругов "сразу" и не допускает дополнительных конкретных размеров шара и манипуляции с позициями.

Я действительно застрял сейчас, есть ли у кого-нибудь идеи, как подойти к этой проблеме?

update: прошло почти год, и я полностью забыл об этой теме. в конце концов я должен придерживаться физической модели и reset заставляет/останавливается в почти незанятых условиях. результат можно увидеть здесь http://stateofwealth.net/ треугольники, которые вы видите, находятся внутри этих кругов. остальные линии связаны через "алгоритм триангуляции delaunay"

Ответ 1

Я помню, что видел демонстрацию d3.js, которая очень похожа на то, что вы описываете. Это написано самим Майком Бостоком: http://bl.ocks.org/mbostock/1747543

Screenshot of d3.js circle packing

Он использует квадранты для быстрого обнаружения столкновений и использует граф, основанный на силе, которые являются обеими утилитами d3.js.

В функции tick вы можете добавить .attr("r", function(d) { return d.radius; }), который будет обновлять радиус каждого тика, когда вы измените данные nodes. Просто для начала вы можете установить его для возврата случайным образом, и круги должны дрожать вокруг, как сумасшедшие.

Ответ 2

(Не комментарий, потому что он не подходит)

Я впечатлен тем, что вы ввели Box2D, чтобы помочь в тяжелой атлетике, но это правда, что, к сожалению, это, вероятно, не очень подходит для ваших требований, поскольку Box2D в лучшем случае, когда вы после имитации жестких объектов и их динамика столкновений.

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

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

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

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

Ответ 3

По крайней мере, для меня кажется, что самое легкое решение - сначала настроить круги в кластере. Поэтому сначала установите самый большой круг в центре, поставьте второй круг рядом с первым. Для третьего вы можете просто поставить его рядом с первым кругом, а затем переместить его вдоль края, пока он не достигнет второго круга. enter image description here

Все остальные круги могут следовать одному и тому же методу: поместите его рядом с произвольным кругом и переместите его вдоль края, пока он не коснется, но не пересечет другой круг. Обратите внимание, что это не сделает ее наиболее эффективной кластеризацией, но она работает. После этого, когда вы расширяете, скажем, круг 1, вы перемещаете все смежные круги наружу и перемещаете их для повторного кластера.