mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-23 16:49:40 +02:00
preserve step_count/… while joining ways (#10926)
* preserve the sum of certain tags (`step_count`, `parking:*:capacity`) during _join_ operation * preserve total value of `parking:*:capacity` tags during _split_ operation by distributing it proportionally to the resulting ways * the abstract osm entity now accepts a list of tags to override during the merging, but otherwise is agnostic about how tags can be merged: the concrete merging resolution might depend on the concrete action that was performed
This commit is contained in:
+15
-2
@@ -1,6 +1,6 @@
|
||||
import { actionDeleteRelation } from './delete_relation';
|
||||
import { actionDeleteWay } from './delete_way';
|
||||
import { osmIsInterestingTag } from '../osm/tags';
|
||||
import { osmIsInterestingTag, osmSummableTags } from '../osm/tags';
|
||||
import { osmJoinWays } from '../osm/multipolygon';
|
||||
import { geoPathIntersections } from '../geo';
|
||||
import { utilArrayGroupBy, utilArrayIdentical, utilArrayIntersection, utilOldestID } from '../util';
|
||||
@@ -61,7 +61,12 @@ export function actionJoin(ids) {
|
||||
graph = graph.replace(parent.replaceMember(way, survivor));
|
||||
});
|
||||
|
||||
survivor = survivor.mergeTags(way.tags);
|
||||
const summedTags = {};
|
||||
for (const key in way.tags) {
|
||||
if (!canSumTags(key, way.tags, survivor.tags)) continue;
|
||||
summedTags[key] = (+way.tags[key] + +survivor.tags[key]).toString();
|
||||
}
|
||||
survivor = survivor.mergeTags(way.tags, summedTags);
|
||||
|
||||
graph = graph.replace(survivor);
|
||||
graph = actionDeleteWay(way.id)(graph);
|
||||
@@ -181,6 +186,8 @@ export function actionJoin(ids) {
|
||||
for (var k in way.tags) {
|
||||
if (!(k in tags)) {
|
||||
tags[k] = way.tags[k];
|
||||
} else if (canSumTags(k, tags, way.tags)) {
|
||||
tags[k] = (+tags[k] + +way.tags[k]).toString();
|
||||
} else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
|
||||
conflicting = true;
|
||||
}
|
||||
@@ -196,6 +203,12 @@ export function actionJoin(ids) {
|
||||
}
|
||||
};
|
||||
|
||||
function canSumTags(key, tagsA, tagsB) {
|
||||
return osmSummableTags.has(key) &&
|
||||
isFinite(tagsA[key] &&
|
||||
isFinite(tagsB[key]));
|
||||
}
|
||||
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
+12
-12
@@ -2,6 +2,7 @@ import { geoSphericalDistance } from '../geo/geo';
|
||||
import { osmRelation } from '../osm/relation';
|
||||
import { osmWay } from '../osm/way';
|
||||
import { utilArrayIntersection, utilWrap, utilArrayUniq } from '../util';
|
||||
import { osmSummableTags } from '../osm/tags';
|
||||
|
||||
|
||||
// Split a way at the given node.
|
||||
@@ -136,32 +137,31 @@ export function actionSplit(nodeIds, newWayIds) {
|
||||
wayB = wayB.update({ nodes: nodesB });
|
||||
}
|
||||
|
||||
if (wayA.tags.step_count) {
|
||||
// divide up the the step count proportionally between the two ways
|
||||
for (const key in wayA.tags) {
|
||||
if (!osmSummableTags.has(key)) continue;
|
||||
|
||||
var stepCount = Number(wayA.tags.step_count);
|
||||
if (stepCount &&
|
||||
// divide up the the e.g. step count proportionally between the two ways
|
||||
var count = Number(wayA.tags[key]);
|
||||
if (count &&
|
||||
// ensure a number
|
||||
isFinite(stepCount) &&
|
||||
isFinite(count) &&
|
||||
// ensure positive
|
||||
stepCount > 0 &&
|
||||
count > 0 &&
|
||||
// ensure integer
|
||||
Math.round(stepCount) === stepCount) {
|
||||
|
||||
Math.round(count) === count) {
|
||||
var tagsA = Object.assign({}, wayA.tags);
|
||||
var tagsB = Object.assign({}, wayB.tags);
|
||||
|
||||
var ratioA = lengthA / (lengthA + lengthB);
|
||||
var countA = Math.round(stepCount * ratioA);
|
||||
tagsA.step_count = countA.toString();
|
||||
tagsB.step_count = (stepCount - countA).toString();
|
||||
var countA = Math.round(count * ratioA);
|
||||
tagsA[key] = countA.toString();
|
||||
tagsB[key] = (count - countA).toString();
|
||||
|
||||
wayA = wayA.update({ tags: tagsA });
|
||||
wayB = wayB.update({ tags: tagsB });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
graph = graph.replace(wayA);
|
||||
graph = graph.replace(wayB);
|
||||
|
||||
|
||||
+21
-6
@@ -123,12 +123,20 @@ osmEntity.prototype = {
|
||||
},
|
||||
|
||||
|
||||
mergeTags: function(tags) {
|
||||
var merged = Object.assign({}, this.tags); // shallow copy
|
||||
var changed = false;
|
||||
for (var k in tags) {
|
||||
var t1 = merged[k];
|
||||
var t2 = tags[k];
|
||||
/**
|
||||
*
|
||||
* @param {Tags} tags tags to merge into this entity's tags
|
||||
* @param {Tags} setTags (optional) a set of tags to overwrite in this entity's tags
|
||||
* @returns {iD.OsmEntity}
|
||||
*/
|
||||
mergeTags: function(tags, setTags = {}) {
|
||||
const merged = Object.assign({}, this.tags); // shallow copy
|
||||
let changed = false;
|
||||
|
||||
for (const k in tags) {
|
||||
if (setTags.hasOwnProperty(k)) continue;
|
||||
const t1 = this.tags[k];
|
||||
const t2 = tags[k];
|
||||
if (!t1) {
|
||||
changed = true;
|
||||
merged[k] = t2;
|
||||
@@ -140,6 +148,13 @@ osmEntity.prototype = {
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const k in setTags) {
|
||||
if (this.tags[k] !== setTags[k]) {
|
||||
changed = true;
|
||||
merged[k] = setTags[k];
|
||||
}
|
||||
}
|
||||
|
||||
return changed ? this.update({ tags: merged }) : this;
|
||||
},
|
||||
|
||||
|
||||
@@ -322,3 +322,10 @@ export function osmShouldRenderDirection(vertexTags, wayTags) {
|
||||
if (vertexTags.cycleway === 'asl') return !!wayTags.highway;
|
||||
return true;
|
||||
}
|
||||
|
||||
export var osmSummableTags = new Set([
|
||||
'step_count',
|
||||
'parking:both:capacity',
|
||||
'parking:left:capacity',
|
||||
'parking:left:capacity'
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user