10

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"

Community
  • 1
  • 1
user151496
  • 1,849
  • 24
  • 38
  • Try linear and angular damping. And box2d supports resize via recreate (is that your hack?). – Pavel Jul 16 '13 at 02:44
  • yes, i am destroying and creaing the objects in box2d. however, this produces very "jumpy" results. i feel as if i have picked wrong framework for this task. i will google for box2d linear/angular damping for less a wobbly model, however i'm a bit skeptic it will solve my problems atm – user151496 Jul 16 '13 at 07:27

3 Answers3

5

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.

gak
  • 32,061
  • 28
  • 119
  • 154
  • thank you for this suggestion. i have tested this engine out and it is quite good! however, there is one thing that boggles me when using this engine and it's such a shame because it's good- that being: when i moved/resized the circles, they overlapped :( it is quite important for me for the circles not to overlap, as the main aspect of the experiment is an aesthetic experience. i have tried looking for some kind of variable/settings for a precise collision detection even when you move the circles but unfortunately found none:/ do you know how could you deal with this problem of the engine? – user151496 Jul 22 '13 at 08:07
  • Without knowing the code myself, it seems that the circles are overlapping due to `cluster()` and the force layout, but eventually the circles separate when it is settled over time via `collision()`. Maybe if you call `collision()` more often per tick, or just loop until there are no collisions detected anymore. There's also an `alpha` variable (https://github.com/mbostock/d3/wiki/Force-Layout#wiki-alpha) that might be handy to tweak. – gak Jul 23 '13 at 00:49
  • Also, if you have more issues, I would recommend creating a demo of your problem and posting on the d3.js mailing list. They're usually very helpful. – gak Jul 23 '13 at 05:30
  • thank you for your suggestions, i will definitely play with the collision(). i just hope it won't be too choppy afterwards – user151496 Jul 23 '13 at 07:16
1

(Not a comment because it wouldn't fit)

I'm impressed that you've brought in Box2D to help with the heavy-lifting, but it's true that unfortunately it is probably not well-suited to your requirements, as Box2D is at its best when you are after simulating rigid objects and their collision dynamics.

I think if you really consider what it is that you need, it isn't quite so much a rigid body dynamics problem at all. You actually want none of the complexity of box2d as all of your geometry consists of spheres (which I assure you are vastly simpler to model than arbitrary convex polygons, which is what IMO Box2D's complexity arises from), and like you mention, Box2D's inability to smoothly change the geometric parameters isn't helping as it will bog down the browser with unnecessary geometry allocations and deallocations and fail to apply any sort of smooth animation.

What you are probably looking for is an algorithm or method to evolve the positions of a set of coordinates (each with a radius that is also potentially changing) so that they stay separated by their radii and also minimize their distance to the center position. If this has to be smooth, you can't just apply the minimal solution every time, as you may get "warping" as the optimal configuration might shift dramatically at particular points along your slider's movement. Suffice it to say there is a lot of tweaking for you to do, but not really anything scarier than what one must contend with inside of Box2D.

How important is it that your circles do not overlap? I think you should just do a simple iterative "solver" that first tries to bring the circles toward their target (center of screen?), and then tries to separate them based on radii.

I believe if you try to come up with a simplified mathematical model for the motion that you want, it will be better than trying to get Box2D to do it. Box2D is magical, but it's only good at what it's good at.

Steven Lu
  • 41,389
  • 58
  • 210
  • 364
  • I didn't expect to impress anyone with the idea :D i actually thought it's a "dumb" approach to use physics to fix my problems. I see your point that box2d is kind of an overkill for my problem, as i really want to deal just with circles and not rigid ones too. However, when i use only circles, the box2d calculations are quite fast, as i don't use any other complex polygons. I even managed to "kind of smoothly" resize the shapes by destroying and creating them very fast- BUT- here is where the framerate dropped massively and that's the problem i deal with now. [comment too long, tbc..] – user151496 Jul 22 '13 at 08:13
  • [..comment continues] It is quite important for me for circles not to overlap, as it's done for a visual pleasure. But it's not important at all to have a minimal solution, another criterion is the smooth transitions (that's why i picked a physics engine). I have actually tried to code my own simple collision circle logic at first but it failed. The circles overlapped, it just jumped around, etc. that's why i decided to pick an engine from someone who knows how to do it properly (and found box2d). Do you know of any other physics engine that would be suitable for the problem? – user151496 Jul 22 '13 at 08:18
  • I still don't consider it a physics problem. What kind of physical things smoothly expand and contract like this? You probably need to develop a new branch of math to model it. Using something heavyweight like box2d in the browser (which will just thrash the GC in your poor browser needlessly as you create and destroy things in loops) will not bring you closer to the goal of smooth motion. – Steven Lu Jul 22 '13 at 13:09
  • physics model doesn't mean simulating real life physics it can be also atoms, springs, anything. well, so far the box2d model was the closes to what i want. the d3.js library that someone mentioned in here(which also uses a physics model) was also very good for it, however, it has the problem of overlapping which is crucial to me. the problem with poor box2d framerate is the object recreation because of its rigid body model. so unless i find a better model for the task i'm stuck with box2d. but if you know of this "math model" i would be only glad to use it. after all, i'm here cause i'm stuck – user151496 Jul 22 '13 at 15:03
  • Well, guess my point is that Box2D has not made any sort of effort to incorporate into its formulation of geometry the notion of dynamic radii. It's entirely possible to do so, and if it had this capability it would be perfect for your use. I've done my own digging into its architecture and I believe there exists a reasonable way to model such "ballooning" circle geometries; it's just a feature that would only come in handy for really specific situations like yours. It may work also to model some form of explosion shock-wave, but even with that, I would prefer a softer impact response. – Steven Lu Jul 22 '13 at 19:21
0

At least for me, seems like the easiest solution is to first set up the circles in a cluster. So first set the largest circle in the center, put the second circle next to the first one. For the third one you can just put it next to the first circle, and then move it along the edge until it hits the second circle. enter image description here

All the other circles can follow the same method: place it next to an arbitrary circle, and move it along the edge until it is touching, but not intersecting, another circle. Note that this won't make it the most efficient clustering, but it works. After that, when you expand, say, circle 1, you'd move all the adjacent circles outward, and shift them around to re-cluster.

woojoo666
  • 7,801
  • 7
  • 45
  • 57
  • thank you for your suggestion, the idea of the circle placement is very fine but the approach is more suitable for a static "set and leave as a picture" approach. the approach can't handle the need for the dynamic/smooth transition when resizing or moving the circles. – user151496 Jul 22 '13 at 08:08