I\'d like to automatically place 100-200 bubble labels so that the following requirements are met:
I think if you are using D3 inside your tools, you can use "force-based" label placement algorithm. The solution originally belongs to Max Planck Research Networks but there is already a ready-made Javascript example, here: Force-based label placement in D3
This thread is very good in covering some approaches. I am using the force layout with multiple foci, as it seems like the best overall method.
This can be formulated as a Linear Programming problem. You want to maximize or minimize a function (representing the "weight" or "goodness" of the solution) subject to certain constraints (your requirements). You'll need to formalize your requirements as values. Something like this:
Variables:
x1 = 1 if Labels overlap, 0 otherwise
x2 = some measure of "how much" a label overlaps a bubble
x3 = distance from label to bubble //Label should be close to bubble
x4 = distance between ideal and actual label position
x5 = difference between actual and ideal font size
minimize x1 + 10*x2 + x3 + 20*x4 + 5*x5
subject to constraints:
x1 = 0 // labels can never overlap
x2 < /* maximum amount a label is allowed to overlap a bubble */
...
x5 < 6 // font size does not vary by more than +/- 6 pts.
I made up the coefficients and the constraints, you can use them to tune the result based on which features are most important to you. Coefficients increase the value of a requirement (in this case, f4
is weighted most so it 'most important'. The constraints are hard limits that cannot be violated.
Since this is a well-known problem, you can now solve it using a number of methods. The Simplex algorithm is popular. There is a whole chapter in Cormen et. al about these problems.
Maybe play with some helper toolkits like the following:
How about
label.substring(0, Math.sqrt(bubbleValueOrRadius))
I found this in one of protovis.js examples.
I imagine you're working with javascript, html and css? Well in any case two approaches come to mind.
First is to formulate it as an optimisation problem. You need to compute the ideal position for each label. This will be based on the size of the bubble, the desired location (i.e. top, down, left, right), and the size of the label (both font and length). Then you need to parameterise your coordinates, for example into a list of 2N elements where N is the number of labels. Then you need to initialise the labels in some position (or a population if using a genetic algorithm) and apply an optimisation algorithm which will require a cost function. This would be based on how far a set of label positions are from the ideal, as well as anything that violates your rules, such as overlapping.
Or, make it a physics problem. 'Attach' each label to its bubble with some rigid link. Give every label and every bubble a repelling force and also add a global and stronger graviational force (in the preferred top/left/right/down direction). Have a short physical simulation until you reach an equilibrium. The maths shouldn't be too hard.