diff --git a/js/id/actions/merge_polygon.js b/js/id/actions/merge_polygon.js index 8eb94766f..7472837ae 100644 --- a/js/id/actions/merge_polygon.js +++ b/js/id/actions/merge_polygon.js @@ -20,14 +20,27 @@ iD.actions.MergePolygon = function(ids) { var action = function(graph) { var entities = groupEntities(graph); - // an array of all the polygons to be merged - var polygons = _.unique(entities.multipolygon.reduce(function(polygons, m) { - return polygons.concat(m.members.filter(function(d) { - return d.type === 'way'; - }).map(function(d) { - return graph.entity(d.id); - })); - }, entities.closedWay)); + // An array of objects representing all the polygons that are part of the multipolygon. + // + // Each object has two properties: + // ids - an array of ids of entities that are part of that polygon + // locs - an array of the locations forming the polygon + var polygons = entities.multipolygon.reduce(function(polygons, m) { + m.multipolygon(graph).forEach(function(group) { + group.forEach(function(ring) { + polygons.push({ + ids: ring.ids, + locs: ring + }); + }); + }); + return polygons; + }, []).concat(entities.closedWay.map(function(d) { + return { + ids: [d.id], + locs: graph.childNodes(d).map(function(n) { return n.loc; }) + }; + })); // contained is an array of arrays of boolean values, // where contained[j][k] is true iff the jth way is @@ -35,15 +48,10 @@ iD.actions.MergePolygon = function(ids) { var contained = polygons.map(function(w, i) { return polygons.map(function(d, n) { if (i === n) return null; - return iD.geo.polygonContainsPolygon(getLocs(d), getLocs(w)); + return iD.geo.polygonContainsPolygon(d.locs, w.locs); }); }); - function getLocs(way) { - return graph.childNodes(way).map(function(d) { return d.loc; }); - } - - // Sort all polygons as either outer or inner ways var members = []; outer = true; @@ -65,10 +73,12 @@ iD.actions.MergePolygon = function(ids) { function extractUncontained(polygons) { polygons.forEach(function(d, i) { if (!isContained(d, i)) { - members.push({ - type: 'way', - id: d.id, - role: outer ? 'outer' : 'inner' + d.ids.forEach(function(id) { + members.push({ + type: 'way', + id: id, + role: outer ? 'outer' : 'inner' + }); }); } }); diff --git a/js/id/core/relation.js b/js/id/core/relation.js index 13f7dc294..90de844e8 100644 --- a/js/id/core/relation.js +++ b/js/id/core/relation.js @@ -169,10 +169,12 @@ _.extend(iD.Relation.prototype, { .map(function(m) { return { role: m.role || 'outer', id: m.id, nodes: resolver.childNodes(resolver.entity(m.id)) }; }); function join(ways) { - var joined = [], current, first, last, i, how, what; + var joined = [], way, current, first, last, i, how, what; while (ways.length) { - current = ways.pop().nodes.slice(); + way = ways.pop(); + current = way.nodes.slice(); + current.ids = [way.id]; joined.push(current); while (ways.length && _.first(current) !== _.last(current)) { @@ -206,12 +208,17 @@ _.extend(iD.Relation.prototype, { if (!what) break; // Invalid geometry (unclosed ring) + current.ids.push(ways[i].id); ways.splice(i, 1); how.apply(current, what); } } - return joined.map(function(nodes) { return _.pluck(nodes, 'loc'); }); + return joined.map(function(nodes) { + var locs = _.pluck(nodes, 'loc'); + locs.ids = nodes.ids; + return locs; + }); } function findOuter(inner) { diff --git a/test/index.html b/test/index.html index 569ebe82b..c2f9662a1 100644 --- a/test/index.html +++ b/test/index.html @@ -110,6 +110,7 @@ +