Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ <h2>D3-Labeler</h2>
<p>A D3 plug-in for automatic label placement using simulated annealing that easily incorporates into existing D3 code, with <br> syntax mirroring other D3 layouts.</p>

<form>
Force bounds: <input type="checkbox" id="bounds" value="false">&nbsp;|&nbsp;
Number of labels: <input type="text" id="n_labels" value=50 size="6"> &nbsp;&nbsp;|&nbsp;&nbsp;
<input type="radio" name="dist" id="uniform" value="Uniform" checked="checked">Uniform&nbsp;&nbsp;<input type="radio" name="dist" id="gaussian" value="Gaussian">Gaussian&nbsp;&nbsp;|&nbsp;&nbsp;
Number of MC sweeps: <input type="text" id="n_sweeps" value=1000 size="6"> &nbsp;&nbsp;|&nbsp;&nbsp;
Expand Down Expand Up @@ -241,6 +242,7 @@ <h2>D3-Labeler</h2>
var nlabels = document.getElementById('n_labels').value;
var is_uniform = document.getElementById('uniform').checked;
var nsweeps = document.getElementById('n_sweeps').value;
var force_bounds = document.getElementById('bounds').checked;

// Randomly distribute data
randomize(nlabels, is_uniform);
Expand Down
56 changes: 38 additions & 18 deletions labeler.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,30 @@ d3.labeler = function() {

var max_move = 5.0,
max_angle = 0.5,
acc = 0;
acc = 0,
rej = 0;

// weights
var w_len = 0.2, // leader line length
var w_len = 0.2, // leader line length
w_inter = 1.0, // leader line intersection
w_lab2 = 30.0, // label-label overlap
w_lab_anc = 30.0; // label-anchor overlap
w_lab_anc = 30.0, // label-anchor overlap
w_overlap_graph_bounds = 50.0, // label-svg bounds overlap
w_orient = 3.0; // orientation bias

// booleans for user defined functions
var user_energy = false,
user_schedule = false;

var user_defined_energy,
var user_defined_energy,
user_defined_schedule;

var force_bounds = false;

energy = function(index) {
// energy function, tailored for label placement

var m = lab.length,
var m = lab.length,
ener = 0,
dx = lab[index].x - anc[index].x,
dy = anc[index].y - lab[index].y,
Expand Down Expand Up @@ -85,14 +88,22 @@ d3.labeler = function() {
ener += (overlap_area * w_lab_anc);

}

if (force_bounds && (x21 <= 0 || x22 >= w || y22 >= h || y21 <= 0)) {
x_overlap = Math.min(w,x22) - Math.max(0,x21);
y_overlap = Math.min(h,y22) - Math.max(0,y21);
overlap_area = x_overlap * y_overlap;
ener += (lab[index].width * lab[index].height - overlap_area) * w_overlap_graph_bounds;
}

return ener;
};

mcmove = function(currT) {
// Monte Carlo translation move

// select a random label
var i = Math.floor(Math.random() * lab.length);
var i = Math.floor(Math.random() * lab.length);

// save old coordinates
var x_old = lab[i].x;
Expand All @@ -108,10 +119,12 @@ d3.labeler = function() {
lab[i].y += (Math.random() - 0.5) * max_move;

// hard wall boundaries
if (lab[i].x > w) lab[i].x = x_old;
if (lab[i].x < 0) lab[i].x = x_old;
if (lab[i].y > h) lab[i].y = y_old;
if (lab[i].y < 0) lab[i].y = y_old;
if (!force_bounds) {
if (lab[i].x > w) lab[i].x = x_old;
if (lab[i].x < 0) lab[i].x = x_old;
if (lab[i].y > h) lab[i].y = y_old;
if (lab[i].y < 0) lab[i].y = y_old;
}

// new energy
var new_energy;
Expand All @@ -136,7 +149,7 @@ d3.labeler = function() {
// Monte Carlo rotation move

// select a random label
var i = Math.floor(Math.random() * lab.length);
var i = Math.floor(Math.random() * lab.length);

// save old coordinates
var x_old = lab[i].x;
Expand Down Expand Up @@ -166,10 +179,12 @@ d3.labeler = function() {
lab[i].y = y_new + anc[i].y

// hard wall boundaries
if (lab[i].x > w) lab[i].x = x_old;
if (lab[i].x < 0) lab[i].x = x_old;
if (lab[i].y > h) lab[i].y = y_old;
if (lab[i].y < 0) lab[i].y = y_old;
if (!force_bounds) {
if (lab[i].x > w) lab[i].x = x_old;
if (lab[i].x < 0) lab[i].x = x_old;
if (lab[i].y > h) lab[i].y = y_old;
if (lab[i].y < 0) lab[i].y = y_old;
}

// new energy
var new_energy;
Expand All @@ -187,7 +202,7 @@ d3.labeler = function() {
lab[i].y = y_old;
rej += 1;
}

};

intersect = function(x1, x2, x3, x4, y1, y2, y3, y4) {
Expand Down Expand Up @@ -222,7 +237,7 @@ d3.labeler = function() {
initialT = 1.0;

for (var i = 0; i < nsweeps; i++) {
for (var j = 0; j < m; j++) {
for (var j = 0; j < m; j++) {
if (Math.random() < 0.5) { mcmove(currT); }
else { mcrotate(currT); }
}
Expand All @@ -240,7 +255,7 @@ d3.labeler = function() {
labeler.height = function(x) {
// users insert graph height
if (!arguments.length) return h;
h = x;
h = x;
return labeler;
};

Expand Down Expand Up @@ -274,6 +289,11 @@ d3.labeler = function() {
return labeler;
};

labeler.force_bounds = function (flag) {
force_bounds = !!flag;
return labeler;
};

return labeler;
};

Expand Down