mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 17:23:02 +00:00
Optimize presets.match
Previous implementation was linear in the number of presets. This should be near constant time.
This commit is contained in:
@@ -11,6 +11,37 @@ iD.presets = function() {
|
||||
other,
|
||||
other_area;
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
var index = {
|
||||
point: {},
|
||||
vertex: {},
|
||||
line: {},
|
||||
area: {},
|
||||
relation: {}
|
||||
};
|
||||
|
||||
all.match = function(entity, resolver) {
|
||||
var geometry = entity.geometry(resolver),
|
||||
geometryMatches = index[geometry],
|
||||
best = -1,
|
||||
match = geometry === 'area' ? other_area : other;
|
||||
|
||||
for (var k in entity.tags) {
|
||||
var keyMatches = geometryMatches[k];
|
||||
if (!keyMatches) continue;
|
||||
|
||||
for (var i = 0; i < keyMatches.length; i++) {
|
||||
var score = keyMatches[i].matchScore(entity);
|
||||
if (score > best) {
|
||||
best = score;
|
||||
match = keyMatches[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
};
|
||||
|
||||
all.load = function(d) {
|
||||
|
||||
if (d.fields) {
|
||||
@@ -45,6 +76,18 @@ iD.presets = function() {
|
||||
other = all.item('other');
|
||||
other_area = all.item('other_area');
|
||||
|
||||
for (var i = 0; i < all.collection.length; i++) {
|
||||
var preset = all.collection[i],
|
||||
geometry = preset.geometry;
|
||||
|
||||
for (var j = 0; j < geometry.length; j++) {
|
||||
var g = index[geometry[j]];
|
||||
for (var k in preset.tags) {
|
||||
(g[k] = g[k] || []).push(preset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return all;
|
||||
};
|
||||
|
||||
|
||||
@@ -10,32 +10,12 @@ iD.presets.Collection = function(collection) {
|
||||
});
|
||||
},
|
||||
|
||||
match: function(entity, resolver) {
|
||||
return presets.matchGeometry(entity.geometry(resolver)).matchTags(entity);
|
||||
},
|
||||
|
||||
matchGeometry: function(geometry) {
|
||||
return iD.presets.Collection(collection.filter(function(d) {
|
||||
return d.matchGeometry(geometry);
|
||||
}));
|
||||
},
|
||||
|
||||
matchTags: function(entity) {
|
||||
|
||||
var best = -1,
|
||||
match;
|
||||
|
||||
for (var i = 0; i < collection.length; i++) {
|
||||
var score = collection[i].matchScore(entity);
|
||||
if (score > best) {
|
||||
best = score;
|
||||
match = collection[i];
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
},
|
||||
|
||||
search: function(value) {
|
||||
if (!value) return this;
|
||||
|
||||
|
||||
@@ -246,6 +246,7 @@
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script src="spec/presets.js"></script>
|
||||
<script src="spec/presets/preset.js"></script>
|
||||
<script src="spec/presets/collection.js"></script>
|
||||
<script src="spec/presets/category.js"></script>
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
|
||||
<script src="spec/modes/add_point.js"></script>
|
||||
|
||||
<script src="spec/presets.js"></script>
|
||||
<script src="spec/presets/preset.js"></script>
|
||||
<script src="spec/presets/collection.js"></script>
|
||||
<script src="spec/presets/category.js"></script>
|
||||
|
||||
38
test/spec/presets.js
Normal file
38
test/spec/presets.js
Normal file
@@ -0,0 +1,38 @@
|
||||
describe("iD.presets", function() {
|
||||
var p = {
|
||||
other: {
|
||||
tags: {},
|
||||
geometry: ['point', 'vertex', 'line', 'area']
|
||||
},
|
||||
residential: {
|
||||
tags: {
|
||||
highway: 'residential'
|
||||
},
|
||||
geometry: ['line']
|
||||
},
|
||||
park: {
|
||||
tags: {
|
||||
leisure: 'park'
|
||||
},
|
||||
geometry: ['point', 'area']
|
||||
}
|
||||
};
|
||||
|
||||
var c = iD.presets().load({presets: p}),
|
||||
w = iD.Way({tags: { highway: 'residential'}}),
|
||||
g = iD.Graph().replace(w);
|
||||
|
||||
describe("#match", function() {
|
||||
it("returns a collection containing presets matching a geometry and tags", function() {
|
||||
var way = iD.Way({tags: { highway: 'residential'}}),
|
||||
graph = iD.Graph([way]);
|
||||
expect(c.match(way, graph).id).to.eql('residential');
|
||||
});
|
||||
|
||||
it("returns an other preset when no tags match", function() {
|
||||
var way = iD.Way({tags: {foo: 'bar'}}),
|
||||
graph = iD.Graph([way]);
|
||||
expect(c.match(way, graph).id).to.eql('other');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -36,12 +36,6 @@ describe("iD.presets.Collection", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#matchTags", function() {
|
||||
it("returns a new collection only containing presets matching an entity's tags", function() {
|
||||
expect(c.matchTags(w, g)).to.eql(p.residential);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#search", function() {
|
||||
it("filters presets by name", function() {
|
||||
expect(c.search("resid").collection.indexOf(p.residential) >= 0).to.eql(true);
|
||||
|
||||
Reference in New Issue
Block a user