describe('iD.actionMergePolygon', function () { function node(id, x, y) { e.push(iD.osmNode({ id: id, loc: [x, y] })); } function way(id, nodes) { e.push(iD.osmWay({ id: id, nodes: nodes.map(function(n) { return 'n' + n; }) })); } var e = []; node('n0', 0, 0); node('n1', 5, 0); node('n2', 5, 5); node('n3', 0, 5); node('n4', 1, 1); node('n5', 4, 1); node('n6', 4, 4); node('n7', 1, 4); node('n8', 2, 2); node('n9', 3, 2); node('n10', 3, 3); node('n11', 2, 3); node('n13', 8, 8); node('n14', 8, 9); node('n15', 9, 9); way('w0', [0, 1, 2, 3, 0]); way('w1', [4, 5, 6, 7, 4]); way('w2', [8, 9, 10, 11, 8]); way('w3', [4, 5, 6]); way('w4', [6, 7, 4]); way('w5', [13, 14, 15, 13]); var graph; beforeEach(function() { graph = iD.coreGraph(e); }); function find(relation, id) { return relation.members.find(function (m) { return m.id === id; }); } it('creates a multipolygon from two closed ways', function() { graph = iD.actionMergePolygon(['w0', 'w1'], 'r')(graph); var r = graph.entity('r'); expect(!!r).to.equal(true); expect(r.geometry(graph)).to.equal('area'); expect(r.isMultipolygon()).to.equal(true); expect(r.members.length).to.equal(2); expect(find(r, 'w0').role).to.equal('outer'); expect(find(r, 'w0').type).to.equal('way'); expect(find(r, 'w1').role).to.equal('inner'); expect(find(r, 'w1').type).to.equal('way'); }); it('creates a multipolygon from a closed way and a multipolygon relation', function() { graph = iD.actionMergePolygon(['w0', 'w1'], 'r')(graph); graph = iD.actionMergePolygon(['r', 'w2'])(graph); var r = graph.entity('r'); expect(r.members.length).to.equal(3); }); it('creates a multipolygon from two multipolygon relations and keeps the oldest alive', function() { graph = iD.actionMergePolygon(['w0', 'w1'], 'r2')(graph); graph = iD.actionMergePolygon(['w2', 'w5'], 'r1')(graph); graph = iD.actionMergePolygon(['r2', 'r1'])(graph); // Delete other relation expect(graph.hasEntity('r2')).to.equal(undefined); var r = graph.entity('r1'); expect(find(r, 'w0').role).to.equal('outer'); expect(find(r, 'w1').role).to.equal('inner'); expect(find(r, 'w2').role).to.equal('outer'); expect(find(r, 'w5').role).to.equal('outer'); }); it('merges multipolygon tags', function() { var graph = iD.coreGraph([ iD.osmRelation({id: 'r1', tags: {type: 'multipolygon', a: 'a'}}), iD.osmRelation({id: 'r2', tags: {type: 'multipolygon', b: 'b'}}) ]); graph = iD.actionMergePolygon(['r1', 'r2'])(graph); expect(graph.entity('r1').tags.a).to.equal('a'); expect(graph.entity('r1').tags.b).to.equal('b'); }); it('merges tags from closed outer ways', function() { graph = graph.replace(graph.entity('w0').update({ tags: { 'building': 'yes' }})); graph = iD.actionMergePolygon(['w0', 'w5'], 'r')(graph); expect(graph.entity('w0').tags.building).to.equal(undefined); expect(graph.entity('r').tags.building).to.equal('yes'); }); it('merges no tags from unclosed outer ways', function() { graph = graph.replace(graph.entity('w3').update({ tags: { 'natural': 'water' }})); var r1 = iD.osmRelation({id: 'r1', tags: {type: 'multipolygon'}}); var r2 = iD.osmRelation({id: 'r2', tags: {type: 'multipolygon'}, members: [ { type: 'way', role: 'outer', id: 'w3' }, { type: 'way', role: 'outer', id: 'w4' } ]}); graph = graph.replace(r1).replace(r2); graph = iD.actionMergePolygon(['r1', 'r2'])(graph); expect(graph.entity('w3').tags.natural).to.equal('water'); expect(graph.entity('r1').tags.natural).to.equal(undefined); }); it('merges no tags from inner ways', function() { graph = graph.replace(graph.entity('w1').update({ tags: { 'natural': 'water' }})); graph = iD.actionMergePolygon(['w0', 'w1'], 'r')(graph); expect(graph.entity('w1').tags.natural).to.equal('water'); expect(graph.entity('r').tags.natural).to.equal(undefined); }); it('doesn\'t copy area tags from ways', function() { graph = graph.replace(graph.entity('w0').update({ tags: { 'area': 'yes' }})); graph = iD.actionMergePolygon(['w0', 'w1'], 'r')(graph); var r = graph.entity('r'); expect(r.tags.area).to.equal(undefined); }); it('creates a multipolygon with two disjunct outer rings', function() { graph = iD.actionMergePolygon(['w0', 'w5'], 'r')(graph); var r = graph.entity('r'); expect(find(r, 'w0').role).to.equal('outer'); expect(find(r, 'w5').role).to.equal('outer'); }); it('creates a multipolygon with an island in a hole', function() { graph = iD.actionMergePolygon(['w0', 'w1'], 'r')(graph); graph = iD.actionMergePolygon(['r', 'w2'])(graph); var r = graph.entity('r'); expect(find(r, 'w0').role).to.equal('outer'); expect(find(r, 'w1').role).to.equal('inner'); expect(find(r, 'w2').role).to.equal('outer'); }); it('extends a multipolygon with multi-way rings', function() { var r = iD.osmRelation({ id: 'r', tags: { type: 'multipolygon' }, members: [ { type: 'way', role: 'outer', id: 'w0' }, { type: 'way', role: 'inner', id: 'w3' }, { type: 'way', role: 'inner', id: 'w4' } ]}); graph = graph.replace(r); graph = iD.actionMergePolygon(['r', 'w2'])(graph); r = graph.entity('r'); expect(find(r, 'w0').role).to.equal('outer'); expect(find(r, 'w2').role).to.equal('outer'); expect(find(r, 'w3').role).to.equal('inner'); expect(find(r, 'w4').role).to.equal('inner'); }); });