Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Position resizable circles near each other

I am working on this browser-based experiment where i am given N specific circles (let's say they have a unique picture in them) and need to position them together, leaving as little space between them as possible. It doesn't have to be arranged in a circle, but they should be "clustered" together.

The circle sizes are customizable and a user will be able to change the sizes by dragging a javascript slider, changing some circles' sizes (for example, in 10% of the slider the circle 4 will have radius of 20px, circle 2 10px, circle 5 stays the same, etc...). As you may have already guessed, i will try to "transition" the resizing-repositioning smoothly when the slider is being moved.

The approach i have tried tried so far: instead of manually trying to position them i've tried to use a physics engine-

my approach example

The idea:

  1. place some kind of gravitational pull in the center of the screen
  2. use a physics engine to take care of the balls collision
  3. during the "drag the time" slider event i would just set different ball sizes and let the engine take care of the rest

For this task i have used "box2Dweb". i placed a gravitational pull to the center of the screen, however, it took a really long time until the balls were placed in the center and they floated around. Then i put a small static piece of ball in the center so they would hit it and then stop. It looked like this:

box2d trial

The results were a bit better, but the circles still moved for some time before they went static. Even after playing around with variables like the ball friction and different gravitational pulls, the whole thing just floated around and felt very "wobbly", while i wanted the balls move only when i drag the time slider (when they change sizes). Plus, box2d doesn't allow to change the sizes of the objects and i would have to hack my way for a workaround.

So, the box2d approach made me realize that maybe to leave a physics engine to handle this isn't the best solution for the problem. Or maybe i have to include some other force i haven't thought of. I have found this similar question to mine on StackOverflow. However, the very important difference is that it just generates some n unspecific circles "at once" and doesn't allow for additional specific ball size and position manipulation.

I am really stuck now, does anyone have any ideas how to approach this problem?

update: it's been almost a year now and i totally forgot about this thread. what i did in the end is to stick to the physics model and reset forces/stop in almost idle conditions. the result can be seen here http://stateofwealth.net/ the triangles you see are inside those circles. the remaining lines are connected via "delaunay triangulation algorithm"

like image 479
user151496 Avatar asked Jul 15 '13 18:07

user151496


1 Answers

I recall seeing a d3.js demo that is very similar to what you're describing. It's written by Mike Bostock himself: http://bl.ocks.org/mbostock/1747543

Screenshot of d3.js circle packing

It uses quadtrees for fast collision detection and uses a force based graph, which are both d3.js utilities.

In the tick function, you should be able to add a .attr("r", function(d) { return d.radius; }) which will update the radius each tick for when you change the nodes data. Just for starters you can set it to return random and the circles should jitter around like crazy.

like image 113
gak Avatar answered Oct 05 '22 04:10

gak