Fix issue where valid merge operations could be blocked

Disable merge when it'd create a redundant multipolygon or add a redundant membership
This commit is contained in:
Quincy Morgan
2020-06-29 10:51:12 -04:00
parent 02a08ca899
commit 22df464e0d
2 changed files with 42 additions and 12 deletions

View File

@@ -1,6 +1,6 @@
import { geoPolygonContainsPolygon } from '../geo';
import { osmJoinWays, osmRelation } from '../osm';
import { utilArrayGroupBy, utilObjectOmit } from '../util';
import { utilArrayGroupBy, utilArrayIntersection, utilObjectOmit } from '../util';
export function actionMergePolygon(ids, newRelationId) {
@@ -114,10 +114,35 @@ export function actionMergePolygon(ids, newRelationId) {
action.disabled = function(graph) {
var entities = groupEntities(graph);
if (entities.other.length > 0 ||
entities.closedWay.length + entities.multipolygon.length < 2)
entities.closedWay.length + entities.multipolygon.length < 2) {
return 'not_eligible';
if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
}
if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); })) {
return 'incomplete_relation';
}
if (!entities.multipolygon.length) {
var sharedMultipolygons = [];
entities.closedWay.forEach(function(way, i) {
if (i === 0) {
sharedMultipolygons = graph.parentMultipolygons(way);
} else {
sharedMultipolygons = utilArrayIntersection(sharedMultipolygons, graph.parentMultipolygons(way));
}
});
sharedMultipolygons = sharedMultipolygons.filter(function(relation) {
return relation.members.length === entities.closedWay.length;
});
if (sharedMultipolygons.length) {
// don't create a new multipolygon if it'd be redundant
return 'not_eligible';
}
} else if (entities.closedWay.some(function(way) {
return utilArrayIntersection(graph.parentMultipolygons(way), entities.multipolygon).length;
})) {
// don't add a way to a multipolygon again if it's already a member
return 'not_eligible';
}
};

View File

@@ -14,19 +14,24 @@ export function operationMerge(context, selectedIDs) {
var _action = getAction();
function getAction() {
// prefer a non-disabled action first
var join = actionJoin(selectedIDs);
if (join.disabled(context.graph()) !== 'not_eligible') {
return join;
}
if (!join.disabled(context.graph())) return join;
var merge = actionMerge(selectedIDs);
if (merge.disabled(context.graph()) !== 'not_eligible') {
return merge;
}
if (!merge.disabled(context.graph())) return merge;
var mergePolygon = actionMergePolygon(selectedIDs);
if (mergePolygon.disabled(context.graph()) !== 'not_eligible') {
return mergePolygon;
}
if (!mergePolygon.disabled(context.graph())) return mergePolygon;
var mergeNodes = actionMergeNodes(selectedIDs);
if (!mergeNodes.disabled(context.graph())) return mergeNodes;
// otherwise prefer an action with an interesting disabled reason
if (join.disabled(context.graph()) !== 'not_eligible') return join;
if (merge.disabled(context.graph()) !== 'not_eligible') return merge;
if (mergePolygon.disabled(context.graph()) !== 'not_eligible') return mergePolygon;
return mergeNodes;
}