mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-21 07:46:58 +02:00
Optimize area rendering
Use iD.svg.Path for caching, and teach iD.svg.Path to round coordinates.
This commit is contained in:
+21
-2
@@ -17,10 +17,29 @@ iD.svg = {
|
||||
var cache = {},
|
||||
path = d3.geo.path().projection(projection);
|
||||
|
||||
return function(entity) {
|
||||
function result(entity) {
|
||||
if (entity.id in cache) return cache[entity.id];
|
||||
return cache[entity.id] = path(entity.asGeoJSON(graph));
|
||||
|
||||
var buffer = '';
|
||||
|
||||
path.context({
|
||||
beginPath: function() {},
|
||||
moveTo: function(x, y) { buffer += 'M' + Math.floor(x) + ',' + Math.floor(y); },
|
||||
lineTo: function(x, y) { buffer += 'L' + Math.floor(x) + ',' + Math.floor(y); },
|
||||
arc: function() {},
|
||||
closePath: function() { buffer += 'Z'; }
|
||||
});
|
||||
|
||||
path(entity.asGeoJSON(graph));
|
||||
|
||||
return cache[entity.id] = buffer;
|
||||
}
|
||||
|
||||
result.area = function(entity) {
|
||||
return path.area(entity.asGeoJSON(graph, true));
|
||||
};
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
OneWaySegments: function(projection, graph, dt) {
|
||||
|
||||
+11
-12
@@ -28,7 +28,7 @@ iD.svg.Areas = function(projection) {
|
||||
}
|
||||
|
||||
return function drawAreas(surface, graph, entities, filter) {
|
||||
var path = d3.geo.path().projection(projection),
|
||||
var path = iD.svg.Path(projection, graph),
|
||||
areas = {},
|
||||
multipolygon;
|
||||
|
||||
@@ -39,25 +39,25 @@ iD.svg.Areas = function(projection) {
|
||||
if (multipolygon = iD.geo.isSimpleMultipolygonOuterMember(entity, graph)) {
|
||||
areas[multipolygon.id] = {
|
||||
entity: multipolygon.mergeTags(entity.tags),
|
||||
area: Math.abs(path.area(entity.asGeoJSON(graph, true)))
|
||||
area: Math.abs(path.area(entity))
|
||||
};
|
||||
} else if (!areas[entity.id]) {
|
||||
areas[entity.id] = {
|
||||
entity: entity,
|
||||
area: Math.abs(path.area(entity.asGeoJSON(graph, true)))
|
||||
area: Math.abs(path.area(entity))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
areas = d3.values(areas);
|
||||
areas.sort(function(a, b) { return b.area - a.area; });
|
||||
areas = d3.values(areas).filter(function hasPath(a) { return path(a.entity); });
|
||||
areas.sort(function areaSort(a, b) { return b.area - a.area; });
|
||||
areas = _.pluck(areas, 'entity');
|
||||
|
||||
var strokes = areas.filter(function(area) {
|
||||
var strokes = areas.filter(function isWay(area) {
|
||||
return area.type === 'way';
|
||||
});
|
||||
|
||||
function drawPaths(areas, klass, closeWay) {
|
||||
function drawPaths(areas, klass, path) {
|
||||
var paths = surface.select('.layer-' + klass)
|
||||
.selectAll('path.area')
|
||||
.filter(filter)
|
||||
@@ -78,7 +78,7 @@ iD.svg.Areas = function(projection) {
|
||||
|
||||
paths
|
||||
.order()
|
||||
.attr('d', function(entity) { return path(entity.asGeoJSON(graph, closeWay)); });
|
||||
.attr('d', path);
|
||||
|
||||
if (klass === 'fill') paths.call(setPattern);
|
||||
|
||||
@@ -88,9 +88,8 @@ iD.svg.Areas = function(projection) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
drawPaths(strokes, 'shadow');
|
||||
drawPaths(strokes, 'stroke');
|
||||
|
||||
drawPaths(areas, 'fill', true);
|
||||
drawPaths(strokes, 'shadow', path);
|
||||
drawPaths(strokes, 'stroke', path);
|
||||
drawPaths(areas, 'fill', path);
|
||||
};
|
||||
};
|
||||
|
||||
+21
-11
@@ -9,20 +9,30 @@ describe("iD.svg.Areas", function () {
|
||||
});
|
||||
|
||||
it("adds way and area classes", function () {
|
||||
var area = iD.Way({tags: {area: 'yes'}}),
|
||||
graph = iD.Graph([area]);
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a', loc: [0, 0]}),
|
||||
'b': iD.Node({id: 'b', loc: [1, 0]}),
|
||||
'c': iD.Node({id: 'c', loc: [1, 1]}),
|
||||
'd': iD.Node({id: 'd', loc: [0, 1]}),
|
||||
'w': iD.Way({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
|
||||
});
|
||||
|
||||
surface.call(iD.svg.Areas(projection), graph, [area], filter);
|
||||
surface.call(iD.svg.Areas(projection), graph, [graph.entity('w')], filter);
|
||||
|
||||
expect(surface.select('path.way')).to.be.classed('way');
|
||||
expect(surface.select('path.area')).to.be.classed('area');
|
||||
});
|
||||
|
||||
it("adds tag classes", function () {
|
||||
var area = iD.Way({tags: {area: 'yes', building: 'yes'}}),
|
||||
graph = iD.Graph([area]);
|
||||
var graph = iD.Graph({
|
||||
'a': iD.Node({id: 'a', loc: [0, 0]}),
|
||||
'b': iD.Node({id: 'b', loc: [1, 0]}),
|
||||
'c': iD.Node({id: 'c', loc: [1, 1]}),
|
||||
'd': iD.Node({id: 'd', loc: [0, 1]}),
|
||||
'w': iD.Way({id: 'w', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']})
|
||||
});
|
||||
|
||||
surface.call(iD.svg.Areas(projection), graph, [area], filter);
|
||||
surface.call(iD.svg.Areas(projection), graph, [graph.entity('w')], filter);
|
||||
|
||||
expect(surface.select('.area')).to.be.classed('tag-building');
|
||||
expect(surface.select('.area')).to.be.classed('tag-building-yes');
|
||||
@@ -47,8 +57,8 @@ describe("iD.svg.Areas", function () {
|
||||
'b': iD.Node({id: 'b', loc: [1, 0]}),
|
||||
'c': iD.Node({id: 'c', loc: [1, 1]}),
|
||||
'd': iD.Node({id: 'd', loc: [0, 1]}),
|
||||
's': iD.Way({area: true, tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']}),
|
||||
'l': iD.Way({area: true, tags: {landuse: 'park'}, nodes: ['a', 'b', 'c', 'd', 'a']})
|
||||
's': iD.Way({id: 's', tags: {building: 'yes'}, nodes: ['a', 'b', 'c', 'a']}),
|
||||
'l': iD.Way({id: 'l', tags: {landuse: 'park'}, nodes: ['a', 'b', 'c', 'd', 'a']})
|
||||
}),
|
||||
areas = [graph.entity('s'), graph.entity('l')];
|
||||
|
||||
@@ -91,7 +101,7 @@ describe("iD.svg.Areas", function () {
|
||||
b = iD.Node({loc: [2, 2]}),
|
||||
c = iD.Node({loc: [3, 3]}),
|
||||
w = iD.Way({tags: {area: 'yes'}, nodes: [a.id, b.id, c.id, a.id]}),
|
||||
r = iD.Relation({members: [{id: w.id}], tags: {type: 'multipolygon', natural: 'wood'}}),
|
||||
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon', natural: 'wood'}}),
|
||||
graph = iD.Graph([a, b, c, w, r]);
|
||||
|
||||
surface.call(iD.svg.Areas(projection), graph, [w], filter);
|
||||
@@ -105,7 +115,7 @@ describe("iD.svg.Areas", function () {
|
||||
b = iD.Node({loc: [2, 2]}),
|
||||
c = iD.Node({loc: [3, 3]}),
|
||||
w = iD.Way({tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]}),
|
||||
r = iD.Relation({members: [{id: w.id}], tags: {type: 'multipolygon'}}),
|
||||
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}}),
|
||||
graph = iD.Graph([a, b, c, w, r]);
|
||||
|
||||
surface.call(iD.svg.Areas(projection), graph, [w, r], filter);
|
||||
@@ -120,7 +130,7 @@ describe("iD.svg.Areas", function () {
|
||||
b = iD.Node({loc: [2, 2]}),
|
||||
c = iD.Node({loc: [3, 3]}),
|
||||
w = iD.Way({tags: {natural: 'wood'}, nodes: [a.id, b.id, c.id, a.id]}),
|
||||
r = iD.Relation({members: [{id: w.id}], tags: {type: 'multipolygon'}}),
|
||||
r = iD.Relation({members: [{id: w.id, type: 'way'}], tags: {type: 'multipolygon'}}),
|
||||
graph = iD.Graph([a, b, c, w, r]);
|
||||
|
||||
surface.call(iD.svg.Areas(projection), graph, [w, r], filter);
|
||||
|
||||
Reference in New Issue
Block a user