Skip to content

Commit

Permalink
Fix mark bounds for removed label overlaps. Add tests. (#1747)
Browse files Browse the repository at this point in the history
  • Loading branch information
jheer committed Apr 6, 2019
1 parent b4ba4e5 commit c130455
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 13 deletions.
5 changes: 4 additions & 1 deletion packages/vega-view-transforms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@
"build": "yarn rollup",
"postbuild": "terser build/vega-view-transforms.js -c -m -o build/vega-view-transforms.min.js",
"pretest": "yarn prebuild && yarn rollup",
"test": "tape 'test/**/*-test.js' && eslint index.js src",
"test": "tape 'test/**/*-test.js' && eslint index.js src test",
"prepublishOnly": "yarn test && yarn build",
"postpublish": "git push && git push --tags"
},
"dependencies": {
"vega-dataflow": "^5.1.1",
"vega-scenegraph": "^4.1.0",
"vega-util": "^1.8.0"
},
"devDependencies": {
"vega-transforms": "*"
}
}
26 changes: 14 additions & 12 deletions packages/vega-view-transforms/src/Overlap.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,11 @@ var prototype = inherits(Overlap, Transform);

var methods = {
parity: function(items) {
return items.filter(function(item, i) {
return i % 2 ? (item.opacity = 0) : 1;
});
return items.filter((item, i) => i % 2 ? (item.opacity = 0) : 1);
},
greedy: function(items, sep) {
var a;
return items.filter(function(b, i) {
return items.filter((b, i) => {
if (!i || !intersect(a.bounds, b.bounds, sep)) {
a = b;
return 1;
Expand Down Expand Up @@ -84,14 +82,12 @@ function boundTest(scale, orient, tolerance) {
}
b.expand(tolerance || 1);

return function(item) {
return b.encloses(item.bounds);
};
return item => b.encloses(item.bounds);
}

// reset all items to be fully opaque
function reset(source) {
source.forEach(function(item) { item.opacity = 1; });
source.forEach(item => item.opacity = 1);
return source;
}

Expand All @@ -105,9 +101,9 @@ prototype.transform = function(_, pulse) {
var reduce = methods[_.method] || methods.parity,
source = pulse.materialize(pulse.SOURCE).source,
sep = _.separation || 0,
items, test;
items, test, bounds;

if (!source) return;
if (!source || !source.length) return;

if (!_.method) {
// early exit if method is falsy
Expand Down Expand Up @@ -141,10 +137,16 @@ prototype.transform = function(_, pulse) {

if (_.boundScale && _.boundTolerance >= 0) {
test = boundTest(_.boundScale, _.boundOrient, +_.boundTolerance);
source.forEach(function(item) {
source.forEach(item => {
if (!test(item)) item.opacity = 0;
})
});
}

// re-calculate mark bounds
bounds = items[0].mark.bounds.clear();
source.forEach(item => {
if (item.opacity) bounds.union(item.bounds);
});

return pulse;
};
63 changes: 63 additions & 0 deletions packages/vega-view-transforms/test/overlap-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
var tape = require('tape'),
vega = require('vega-dataflow'),
Bounds = require('vega-scenegraph').Bounds,
Collect = require('vega-transforms').collect,
tx = require('../'),
Overlap = tx.overlap;

function items() {
var mark = {bounds: new Bounds(0, 0, 20, 10)};
return [
{opacity: 1, mark: mark, bounds: new Bounds().set( 0, 0, 3, 10)},
{opacity: 1, mark: mark, bounds: new Bounds().set( 5, 0, 20, 10)},
{opacity: 1, mark: mark, bounds: new Bounds().set(10, 0, 18, 10)}
];
}

tape('Overlap removes overlapping items (parity)', function(t) {
var data = items(),
df = new vega.Dataflow(),
co = df.add(Collect),
ov = df.add(Overlap, {method: 'parity', pulse: co});

df.pulse(co, df.changeset().insert(data)).run();

// overlap sets proper opacity values
t.equal(ov.pulse.add.length, 3);
t.equal(data[0].opacity, 1);
t.equal(data[1].opacity, 0);
t.equal(data[2].opacity, 1);

// overlap updates mark bounds
t.deepEqual(data[0].mark.bounds, {x1: 0, y1: 0, x2: 18, y2: 10});

t.end();
});

tape('Overlap removes overlapping items (greedy)', function(t) {
var data = items(),
df = new vega.Dataflow(),
co = df.add(Collect),
ov = df.add(Overlap, {method: 'greedy', pulse: co});

// add extra item to test greedy strategy
data.push({
opacity: 1,
mark: data[0].mark,
bounds: new Bounds().set(30, 0, 35, 10)
});

df.pulse(co, df.changeset().insert(data)).run();

// overlap sets proper opacity values
t.equal(ov.pulse.add.length, 4);
t.equal(data[0].opacity, 1);
t.equal(data[1].opacity, 1);
t.equal(data[2].opacity, 0);
t.equal(data[3].opacity, 1);

// overlap updates mark bounds
t.deepEqual(data[0].mark.bounds, {x1: 0, y1: 0, x2: 35, y2: 10});

t.end();
});

0 comments on commit c130455

Please sign in to comment.