Reduce calls to iD.svg.TagClasses

For fills and shadows, style changes can happen only when
a new version of the feature is produced. If we include a
version number in the key, we need only call TagClasses on
the enter selection.

We cannot apply the same optimization for strokes, since
stroke style can depend on the tags of parent relations
as well.
This commit is contained in:
John Firebaugh
2013-05-05 22:55:45 -07:00
parent 63321b7bec
commit 6060e886cb
6 changed files with 37 additions and 21 deletions
+6 -2
View File
@@ -9,9 +9,13 @@
iD.Difference = function(base, head) {
var changes = {}, length = 0;
function changed(h, b) {
return !_.isEqual(_.omit(h, 'v'), _.omit(b, 'v'));
}
_.each(head.entities, function(h, id) {
var b = base.entities[id];
if (!_.isEqual(h, b)) {
if (changed(h, b)) {
changes[id] = {base: b, head: h};
length++;
}
@@ -19,7 +23,7 @@ iD.Difference = function(base, head) {
_.each(base.entities, function(b, id) {
var h = head.entities[id];
if (!changes[id] && !_.isEqual(h, b)) {
if (!changes[id] && changed(h, b)) {
changes[id] = {base: b, head: h};
length++;
}
+2 -2
View File
@@ -31,7 +31,7 @@ iD.Entity.id.type = function(id) {
// A function suitable for use as the second argument to d3.selection#data().
iD.Entity.key = function(entity) {
return entity.id;
return entity.id + ',' + entity.v;
};
iD.Entity.prototype = {
@@ -72,7 +72,7 @@ iD.Entity.prototype = {
},
update: function(attrs) {
return iD.Entity(this, attrs);
return iD.Entity(this, attrs, {v: 1 + (this.v || 0)});
},
mergeTags: function(tags) {
+10 -8
View File
@@ -58,25 +58,27 @@ iD.svg.Areas = function(projection) {
});
function drawPaths(areas, klass, closeWay) {
var tagClasses = iD.svg.TagClasses();
if (klass === 'stroke') {
tagClasses.tags(iD.svg.MultipolygonMemberTags(graph));
}
var paths = surface.select('.layer-' + klass)
.selectAll('path.area')
.filter(filter)
.data(areas, iD.Entity.key);
paths.enter()
var enter = paths.enter()
.append('path')
.attr('class', function(d) { return d.type + ' area ' + klass + ' ' + d.id; });
// Optimization: call simple TagClasses only on enter selection. This
// works because iD.Entity.key is defined to include the entity v attribute.
if (klass !== 'stroke') {
enter.call(iD.svg.TagClasses());
} else {
paths.call(iD.svg.TagClasses()
.tags(iD.svg.MultipolygonMemberTags(graph)));
}
paths
.order()
.attr('d', function(entity) { return path(entity.asGeoJSON(graph, closeWay)); })
.call(tagClasses)
.call(iD.svg.MemberClasses(graph));
if (klass === 'fill') paths.call(setPattern);
+10 -8
View File
@@ -50,25 +50,27 @@ iD.svg.Lines = function(projection) {
lines.sort(waystack);
function drawPaths(klass) {
var tagClasses = iD.svg.TagClasses();
if (klass === 'stroke') {
tagClasses.tags(iD.svg.MultipolygonMemberTags(graph));
}
var paths = surface.select('.layer-' + klass)
.selectAll('path.line')
.filter(filter)
.data(lines, iD.Entity.key);
paths.enter()
var enter = paths.enter()
.append('path')
.attr('class', function(d) { return 'way line ' + klass + ' ' + d.id; });
// Optimization: call simple TagClasses only on enter selection. This
// works because iD.Entity.key is defined to include the entity v attribute.
if (klass !== 'stroke') {
enter.call(iD.svg.TagClasses());
} else {
paths.call(iD.svg.TagClasses()
.tags(iD.svg.MultipolygonMemberTags(graph)));
}
paths
.order()
.attr('d', path)
.call(tagClasses)
.call(iD.svg.MemberClasses(graph));
paths.exit()
+1 -1
View File
@@ -19,7 +19,7 @@ iD.svg.TagClasses = function() {
var t = tags(entity);
for (var k in t) {
if (!keys.has(k)) continue;
classes += ' tag-' + k + ' ' + 'tag-' + k + '-' + t[k];
classes += ' tag-' + k + ' tag-' + k + '-' + t[k];
}
classes = classes.trim();
+8
View File
@@ -61,6 +61,14 @@ describe('iD.Entity', function () {
it("doesn't copy prototype properties", function () {
expect(iD.Entity().update({})).not.to.have.ownProperty('update');
});
it("sets v to 1 if previously undefined", function() {
expect(iD.Entity().update({}).v).to.equal(1);
});
it("increments v", function() {
expect(iD.Entity({v: 1}).update({}).v).to.equal(2);
});
});
describe("#mergeTags", function () {