From de488e252fd4a6f1900b9f355b158b97f53807ad Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Mon, 22 Jan 2018 15:06:58 -0500 Subject: [PATCH] Draw covered/underground lines beneath areas (closes #4718) --- modules/osm/way.js | 1 + modules/svg/lines.js | 112 +++++++++++++++++++++-------------------- modules/svg/osm.js | 2 +- test/spec/osm/way.js | 4 ++ test/spec/svg/lines.js | 4 +- test/spec/svg/osm.js | 11 ++-- 6 files changed, 71 insertions(+), 63 deletions(-) diff --git a/modules/osm/way.js b/modules/osm/way.js index 28dbccf95..af1b3d476 100644 --- a/modules/osm/way.js +++ b/modules/osm/way.js @@ -89,6 +89,7 @@ _extend(osmWay.prototype, { } // implied layer tag.. + if (this.tags.covered === 'yes') return -1; if (this.tags.location === 'overground') return 1; if (this.tags.location === 'underground') return -1; if (this.tags.location === 'underwater') return -10; diff --git a/modules/svg/lines.js b/modules/svg/lines.js index 727d0178b..24eb23870 100644 --- a/modules/svg/lines.js +++ b/modules/svg/lines.js @@ -173,71 +173,73 @@ export function svgLines(projection, context) { }); - var layer = selection.selectAll('.layer-lines .layer-lines-lines'); + var covered = selection.selectAll('.layer-covered'); // under areas + var uncovered = selection.selectAll('.layer-lines .layer-lines-lines'); // over areas - var layergroup = layer - .selectAll('g.layergroup') - .data(d3_range(-10, 11)); + [covered, uncovered].forEach(function(selection) { + var range = (selection === covered ? d3_range(-10,0) : d3_range(0,11)); + var layergroup = selection + .selectAll('g.layergroup') + .data(range); - layergroup = layergroup.enter() - .append('g') - .attr('class', function(d) { return 'layergroup layer' + String(d); }) - .merge(layergroup); + layergroup = layergroup.enter() + .append('g') + .attr('class', function(d) { return 'layergroup layer' + String(d); }) + .merge(layergroup); - layergroup - .selectAll('g.linegroup') - .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']) - .enter() - .append('g') - .attr('class', function(d) { return 'linegroup line-' + d; }); + layergroup + .selectAll('g.linegroup') + .data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']) + .enter() + .append('g') + .attr('class', function(d) { return 'linegroup line-' + d; }); + + layergroup.selectAll('g.line-shadow') + .call(drawLineGroup, 'shadow', false); + layergroup.selectAll('g.line-casing') + .call(drawLineGroup, 'casing', false); + layergroup.selectAll('g.line-stroke') + .call(drawLineGroup, 'stroke', false); + + layergroup.selectAll('g.line-shadow-highlighted') + .call(drawLineGroup, 'shadow', true); + layergroup.selectAll('g.line-casing-highlighted') + .call(drawLineGroup, 'casing', true); + layergroup.selectAll('g.line-stroke-highlighted') + .call(drawLineGroup, 'stroke', true); - layergroup.selectAll('g.line-shadow') - .call(drawLineGroup, 'shadow', false); - layergroup.selectAll('g.line-casing') - .call(drawLineGroup, 'casing', false); - layergroup.selectAll('g.line-stroke') - .call(drawLineGroup, 'stroke', false); + var onewaygroup = layergroup + .selectAll('g.onewaygroup') + .data(['oneway']); - layergroup.selectAll('g.line-shadow-highlighted') - .call(drawLineGroup, 'shadow', true); - layergroup.selectAll('g.line-casing-highlighted') - .call(drawLineGroup, 'casing', true); - layergroup.selectAll('g.line-stroke-highlighted') - .call(drawLineGroup, 'stroke', true); + onewaygroup = onewaygroup.enter() + .append('g') + .attr('class', 'onewaygroup') + .merge(onewaygroup); + var oneways = onewaygroup + .selectAll('path') + .filter(filter) + .data( + function data() { return onewaydata[this.parentNode.__data__] || []; }, + function key(d) { return [d.id, d.index]; } + ); - var onewaygroup = layergroup - .selectAll('g.onewaygroup') - .data(['oneway']); + oneways.exit() + .remove(); - onewaygroup = onewaygroup.enter() - .append('g') - .attr('class', 'onewaygroup') - .merge(onewaygroup); - - var oneways = onewaygroup - .selectAll('path') - .filter(filter) - .data( - function data() { return onewaydata[this.parentNode.__data__] || []; }, - function key(d) { return [d.id, d.index]; } - ); - - oneways.exit() - .remove(); - - oneways = oneways.enter() - .append('path') - .attr('class', 'oneway') - .attr('marker-mid', 'url(#oneway-marker)') - .merge(oneways) - .attr('d', function(d) { return d.d; }); - - if (detected.ie) { - oneways.each(function() { this.parentNode.insertBefore(this, this); }); - } + oneways = oneways.enter() + .append('path') + .attr('class', 'oneway') + .attr('marker-mid', 'url(#oneway-marker)') + .merge(oneways) + .attr('d', function(d) { return d.d; }); + if (detected.ie) { + oneways.each(function() { this.parentNode.insertBefore(this, this); }); + } + }); // touch targets selection.selectAll('.layer-lines .layer-lines-targets') diff --git a/modules/svg/osm.js b/modules/svg/osm.js index db9a26a12..a580e2a73 100644 --- a/modules/svg/osm.js +++ b/modules/svg/osm.js @@ -4,7 +4,7 @@ export function svgOsm(projection, context, dispatch) { function drawOsm(selection) { selection.selectAll('.layer-osm') - .data(['areas', 'lines', 'points', 'labels']) + .data(['covered', 'areas', 'lines', 'points', 'labels']) .enter() .append('g') .attr('class', function(d) { return 'layer-osm layer-' + d; }); diff --git a/test/spec/osm/way.js b/test/spec/osm/way.js index 2680e0dea..45039eca6 100644 --- a/test/spec/osm/way.js +++ b/test/spec/osm/way.js @@ -234,6 +234,10 @@ describe('iD.osmWay', function() { expect(iD.Way({tags: { location: 'overground' }}).layer()).to.equal(1); }); + it('returns -1 for covered=yes', function() { + expect(iD.Way({tags: { covered: 'yes' }}).layer()).to.equal(-1); + }); + it('returns -1 for location=underground', function() { expect(iD.Way({tags: { location: 'underground' }}).layer()).to.equal(-1); }); diff --git a/test/spec/svg/lines.js b/test/spec/svg/lines.js index d10fe09a6..d89517f35 100644 --- a/test/spec/svg/lines.js +++ b/test/spec/svg/lines.js @@ -90,8 +90,8 @@ describe('iD.svgLines', function () { iD.osmNode({id: 'b', loc: [1, 1]}), iD.osmNode({id: 'c', loc: [0, 0]}), iD.osmNode({id: 'd', loc: [1, 1]}), - iD.osmWay({id: 'lo', tags: {highway: 'residential', tunnel: 'yes'}, nodes: ['a', 'b']}), - iD.osmWay({id: 'hi', tags: {highway: 'residential', bridge: 'yes'}, nodes: ['c', 'd']}) + iD.osmWay({id: 'lo', tags: {highway: 'residential', layer: '0'}, nodes: ['a', 'b']}), + iD.osmWay({id: 'hi', tags: {highway: 'residential', layer: '1'}, nodes: ['c', 'd']}) ]); it('stacks higher lines above lower ones in a single render', function () { diff --git a/test/spec/svg/osm.js b/test/spec/svg/osm.js index 43358b11f..84761c96f 100644 --- a/test/spec/svg/osm.js +++ b/test/spec/svg/osm.js @@ -8,11 +8,12 @@ describe('iD.svgOsm', function () { it('creates default osm layers', function () { container.call(iD.svgOsm()); var layers = container.selectAll('g.layer-osm').nodes(); - expect(layers.length).to.eql(4); - expect(d3.select(layers[0]).classed('layer-areas')).to.be.true; - expect(d3.select(layers[1]).classed('layer-lines')).to.be.true; - expect(d3.select(layers[2]).classed('layer-points')).to.be.true; - expect(d3.select(layers[3]).classed('layer-labels')).to.be.true; + expect(layers.length).to.eql(5); + expect(d3.select(layers[0]).classed('layer-covered')).to.be.true; + expect(d3.select(layers[1]).classed('layer-areas')).to.be.true; + expect(d3.select(layers[2]).classed('layer-lines')).to.be.true; + expect(d3.select(layers[3]).classed('layer-points')).to.be.true; + expect(d3.select(layers[4]).classed('layer-labels')).to.be.true; }); it('creates default osm point layers', function () {