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 @@
+