mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-30 03:39:36 +02:00
116 lines
3.9 KiB
JavaScript
116 lines
3.9 KiB
JavaScript
iD.svg.Areas = function(projection) {
|
|
// For fixing up rendering of multipolygons with tags on the outer member.
|
|
// https://github.com/systemed/iD/issues/613
|
|
function isSimpleMultipolygonOuterMember(entity, graph) {
|
|
if (entity.type !== 'way')
|
|
return false;
|
|
|
|
var parents = graph.parentRelations(entity);
|
|
if (parents.length !== 1)
|
|
return false;
|
|
|
|
var parent = parents[0];
|
|
if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
|
|
return false;
|
|
|
|
var members = parent.members, member;
|
|
for (var i = 0; i < members.length; i++) {
|
|
member = members[i];
|
|
if (member.id === entity.id && member.role && member.role !== 'outer')
|
|
return false; // Not outer member
|
|
if (member.id !== entity.id && (!member.role || member.role === 'outer'))
|
|
return false; // Not a simple multipolygon
|
|
}
|
|
|
|
return parent;
|
|
}
|
|
|
|
// Patterns only work in Firefox when set directly on element
|
|
var patterns = d3.set([
|
|
'wetland', 'beach', 'scrub', 'construction', 'cemetery', 'meadow',
|
|
'farmland', 'orchard'
|
|
]);
|
|
|
|
function setPattern(selection) {
|
|
selection.each(function(d) {
|
|
if (d.tags.landuse && patterns.has(d.tags.landuse)) {
|
|
this.style.fill = 'url("#pattern-' + d.tags.landuse + '")';
|
|
return;
|
|
}
|
|
if (d.tags.natural && patterns.has(d.tags.natural)) {
|
|
this.style.fill = 'url("#pattern-' + d.tags.natural + '")';
|
|
return;
|
|
}
|
|
});
|
|
}
|
|
|
|
return function drawAreas(surface, graph, entities, filter) {
|
|
var path = d3.geo.path().projection(projection),
|
|
areas = {},
|
|
multipolygon;
|
|
|
|
for (var i = 0; i < entities.length; i++) {
|
|
var entity = entities[i];
|
|
if (entity.geometry(graph) !== 'area') continue;
|
|
|
|
if (multipolygon = isSimpleMultipolygonOuterMember(entity, graph)) {
|
|
areas[multipolygon.id] = {
|
|
entity: multipolygon.mergeTags(entity.tags),
|
|
area: Math.abs(path.area(entity.asGeoJSON(graph, true)))
|
|
};
|
|
} else if (!areas[entity.id]) {
|
|
areas[entity.id] = {
|
|
entity: entity,
|
|
area: Math.abs(path.area(entity.asGeoJSON(graph, true)))
|
|
};
|
|
}
|
|
}
|
|
|
|
areas = d3.values(areas);
|
|
areas.sort(function(a, b) { return b.area - a.area; });
|
|
|
|
function drawPaths(group, areas, filter, klass, closeWay) {
|
|
var tagClasses = iD.svg.TagClasses();
|
|
|
|
if (klass === 'stroke') {
|
|
tagClasses.tags(iD.svg.MultipolygonMemberTags(graph));
|
|
}
|
|
|
|
var paths = group.selectAll('path.area')
|
|
.filter(filter)
|
|
.data(areas, iD.Entity.key);
|
|
|
|
paths.enter()
|
|
.append('path')
|
|
.attr('class', function(d) { return d.type + ' area ' + klass; });
|
|
|
|
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);
|
|
|
|
paths.exit()
|
|
.remove();
|
|
|
|
return paths;
|
|
}
|
|
|
|
areas = _.pluck(areas, 'entity');
|
|
|
|
var strokes = areas.filter(function(area) {
|
|
return area.type === 'way';
|
|
});
|
|
|
|
var shadow = surface.select('.layer-shadow'),
|
|
fill = surface.select('.layer-fill'),
|
|
stroke = surface.select('.layer-stroke');
|
|
|
|
drawPaths(shadow, strokes, filter, 'shadow');
|
|
drawPaths(fill, areas, filter, 'fill', true);
|
|
drawPaths(stroke, strokes, filter, 'stroke');
|
|
};
|
|
};
|