OpenStreetMap logo OpenStreetMap

Manchmal lädt man sich nicht alle Daten in den Editor. Und manchmal vergisst man betroffene Dinge. Passiert mir auch immer wieder.

Mitte dieses Monats bin ich auf eine Serie von Änderungen gestoßen, wo Wege aufgeteilt worden sind, ohne Routenrelationen mitzubearbeiten. Und weil da zwar viele Routen betroffen waren, aber alle Lücken räumlich begrenzt waren, hab ich mir gedacht ich probier, ob ich das nachträglich programmatisch angehen kann, die OSM Editoren schaffen das ja auch.

Die Daten hab ich schnell abgefragt und nachdem ich über alte turnlanes:turns-Relationen gestoßen bin und die zusammen mit den Abbiegebeschränkungen überprüft hab, hab ich mich auch schon den Routen zuwenden können und zu basteln begonnen:

function findRouteWays(startWay, endWay) {
	let queue = [{ path: [startWay], nodes: startWay.nodes }];
	let visited = [startWay.id];
	while (queue.length) {
		let { path, nodes } = queue.shift();
		for (let candidate of elements) {
			if (candidate.type !== "way") continue;
			if (visited.includes(candidate.id)) continue;
			if (!nodes.some(node => candidate.nodes.includes(node))) continue;
			if (candidate.id === endWay.id) return [...path, endWay];
			queue.push({
				path: [...path, candidate],
				nodes: candidate.nodes,
			});
			visited.push(candidate.id);
		}
	}
	throw new Error('No path found');
}
function isConnected(a, b) {
	let aNodes = a.geometry.map(JSON.stringify);
	let bNodes = b.geometry.map(JSON.stringify);
	return aNodes.some(node => bNodes.includes(node));
}
let replacements = [];
for (let route of elements.filter(l => l.type === "relation" && l.tags.type === "route")) {
	let members = route.members.filter(m => m.type === "way" && !m.role);
	for (let i = 0; i < members.length - 1; i++) {
		if (isConnected(members[i], members[i + 1])) continue;
		let from = [0, 1].map(d => elements.find(l => l.type === "way" && l.id === members[i + d].ref));
		if (from.some(way => !way)) continue;
		let to = findRouteWays(...from);
		replacements.push({ from, to });
	}
}

Und dann war’s nur noch eine Frage des Ersetzens in level0 und dem Kontrollieren, dass wirklich nur neu erstellte Wege eingefügt werden.

Hab ich mir zumindest gedacht. Tatsächlich hab ich beim ersten Änderungssatz vergessen, dass neue Wegteile auch unbearbeitete Wege berühren können. Das war aber auch schnell korrigiert, schließlich hab ich ja nur beim wieder rauf-rekurrieren den Filter nach Nutzer und Datum zurücknehmen müssen.

Trotz der vergleichsweise ineffizienten Breitensuche hat das mit nur einer Zehntelsekunde nicht allzu lang gedauert. ^^ Am längsten hat ja das Schreiben hier gedauert, aber wer sagt denn, dass ich gut darin bin?

Location: KG Kagran, Donaustadt, Wien, 1220, Österreich

Discussion

Log in to leave a comment