diff --git a/modules/osm/relation.js b/modules/osm/relation.js index 2af55cabe..2c33b7b0c 100644 --- a/modules/osm/relation.js +++ b/modules/osm/relation.js @@ -308,8 +308,9 @@ Object.assign(osmRelation.prototype, { inners = osmJoinWays(inners, resolver); var sequenceToLineString = function(sequence) { - if (sequence.nodes[0] !== sequence.nodes[sequence.nodes.length - 1]) { - // treat all parts as closed even if they aren't + if (sequence.nodes.length > 2 && + sequence.nodes[0] !== sequence.nodes[sequence.nodes.length - 1]) { + // close unclosed parts to ensure correct area rendering - #2945 sequence.nodes.push(sequence.nodes[0]); } return sequence.nodes.map(function(node) { return node.loc; }); diff --git a/test/spec/osm/relation.js b/test/spec/osm/relation.js index e0810eef6..42d40a02c 100644 --- a/test/spec/osm/relation.js +++ b/test/spec/osm/relation.js @@ -647,7 +647,7 @@ describe('iD.osmRelation', function () { var r = iD.osmRelation({members: [{id: w.id, type: 'way'}]}); var g = iD.coreGraph([a, b, c, w, r]); - expect(r.multipolygon(g)).to.eql([[[a.loc, b.loc, c.loc]]]); + expect(r.multipolygon(g)).to.eql([[[a.loc, b.loc, c.loc, a.loc]]]); }); specify('invalid geometry: unclosed ring consisting of multiple ways', function () { @@ -659,7 +659,7 @@ describe('iD.osmRelation', function () { var r = iD.osmRelation({members: [{id: w1.id, type: 'way'}, {id: w2.id, type: 'way'}]}); var g = iD.coreGraph([a, b, c, w1, w2, r]); - expect(r.multipolygon(g)).to.eql([[[a.loc, b.loc, c.loc]]]); + expect(r.multipolygon(g)).to.eql([[[a.loc, b.loc, c.loc, a.loc]]]); }); specify('invalid geometry: unclosed ring consisting of multiple ways, alternate order', function () { @@ -672,7 +672,7 @@ describe('iD.osmRelation', function () { var r = iD.osmRelation({members: [{id: w1.id, type: 'way'}, {id: w2.id, type: 'way'}]}); var g = iD.coreGraph([a, b, c, d, w1, w2, r]); - expect(r.multipolygon(g)).to.eql([[[d.loc, c.loc, b.loc, a.loc]]]); + expect(r.multipolygon(g)).to.eql([[[d.loc, c.loc, b.loc, a.loc, d.loc]]]); }); specify('invalid geometry: unclosed ring consisting of multiple ways, one needing reversal', function () { @@ -685,7 +685,7 @@ describe('iD.osmRelation', function () { var r = iD.osmRelation({members: [{id: w1.id, type: 'way'}, {id: w2.id, type: 'way'}]}); var g = iD.coreGraph([a, b, c, d, w1, w2, r]); - expect(r.multipolygon(g)).to.eql([[[d.loc, c.loc, b.loc, a.loc]]]); + expect(r.multipolygon(g)).to.eql([[[a.loc, d.loc, c.loc, b.loc, a.loc]]]); }); specify('invalid geometry: unclosed ring consisting of multiple ways, one needing reversal, alternate order', function () { @@ -698,7 +698,7 @@ describe('iD.osmRelation', function () { var r = iD.osmRelation({members: [{id: w1.id, type: 'way'}, {id: w2.id, type: 'way'}]}); var g = iD.coreGraph([a, b, c, d, w1, w2, r]); - expect(r.multipolygon(g)).to.eql([[[d.loc, c.loc, b.loc, a.loc]]]); + expect(r.multipolygon(g)).to.eql([[[d.loc, c.loc, b.loc, a.loc, d.loc]]]); }); specify('single polygon with single single-way inner', function () { @@ -805,7 +805,7 @@ describe('iD.osmRelation', function () { var r = iD.osmRelation({members: [{id: w2.id, type: 'way'}, {id: w1.id, type: 'way'}]}); var g = iD.coreGraph([a, b, c, w1, r]); - expect(r.multipolygon(g)).to.eql([[[a.loc, b.loc, c.loc]]]); + expect(r.multipolygon(g)).to.eql([[[a.loc, c.loc, b.loc, a.loc]]]); }); });