forked from MapComplete/MapComplete
More work on splitting roads, WIP; refactoring tests
This commit is contained in:
parent
e374bb355c
commit
1f93923820
62 changed files with 1163 additions and 823 deletions
142
Logic/Osm/Actions/RelationSplitHandler.ts
Normal file
142
Logic/Osm/Actions/RelationSplitHandler.ts
Normal file
|
@ -0,0 +1,142 @@
|
|||
import OsmChangeAction from "./OsmChangeAction";
|
||||
import {Changes} from "../Changes";
|
||||
import {ChangeDescription} from "./ChangeDescription";
|
||||
import {OsmObject, OsmRelation, OsmWay} from "../OsmObject";
|
||||
|
||||
export interface RelationSplitInput {
|
||||
relation: OsmRelation,
|
||||
originalWayId: number,
|
||||
allWayIdsInOrder: number[],
|
||||
originalNodes: number[],
|
||||
allWaysNodesInOrder: number[][]
|
||||
}
|
||||
|
||||
/**
|
||||
* When a way is split and this way is part of a relation, the relation should be updated too to have the new segment if relevant.
|
||||
*/
|
||||
export default class RelationSplitHandler extends OsmChangeAction {
|
||||
|
||||
constructor(input: RelationSplitInput) {
|
||||
super()
|
||||
}
|
||||
|
||||
async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A simple strategy to split relations:
|
||||
* -> Download the way members just before and just after the original way
|
||||
* -> Make sure they are still aligned
|
||||
*
|
||||
* Note that the feature might appear multiple times.
|
||||
*/
|
||||
export class InPlaceReplacedmentRTSH extends OsmChangeAction {
|
||||
private readonly _input: RelationSplitInput;
|
||||
|
||||
constructor(input: RelationSplitInput) {
|
||||
super();
|
||||
this._input = input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns which node should border the member at the given index
|
||||
*/
|
||||
private async targetNodeAt(i: number, first: boolean) {
|
||||
const member = this._input.relation.members[i]
|
||||
if (member === undefined) {
|
||||
return undefined
|
||||
}
|
||||
if (member.type === "node") {
|
||||
return member.ref
|
||||
}
|
||||
if (member.type === "way") {
|
||||
const osmWay = <OsmWay>await OsmObject.DownloadObjectAsync("way/" + member.ref)
|
||||
const nodes = osmWay.nodes
|
||||
if (first) {
|
||||
return nodes[0]
|
||||
} else {
|
||||
return nodes[nodes.length - 1]
|
||||
}
|
||||
}
|
||||
if (member.type === "relation") {
|
||||
return undefined
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async CreateChangeDescriptions(changes: Changes): Promise<ChangeDescription[]> {
|
||||
|
||||
const wayId = this._input.originalWayId
|
||||
const relation = this._input.relation
|
||||
const members = relation.members
|
||||
const originalNodes = this._input.originalNodes;
|
||||
const firstNode = originalNodes[0]
|
||||
const lastNode = originalNodes[originalNodes.length - 1]
|
||||
const newMembers: { type: "node" | "way" | "relation", ref: number, role: string }[] = []
|
||||
|
||||
for (let i = 0; i < members.length; i++) {
|
||||
const member = members[i];
|
||||
if (member.type !== "way" || member.ref !== wayId) {
|
||||
newMembers.push(member)
|
||||
continue;
|
||||
}
|
||||
|
||||
const nodeIdBefore = await this.targetNodeAt(i - 1, false)
|
||||
const nodeIdAfter = await this.targetNodeAt(i + 1, true)
|
||||
|
||||
const firstNodeMatches = nodeIdBefore === undefined || nodeIdBefore === firstNode
|
||||
const lastNodeMatches =nodeIdAfter === undefined || nodeIdAfter === lastNode
|
||||
|
||||
if (firstNodeMatches && lastNodeMatches) {
|
||||
// We have a classic situation, forward situation
|
||||
for (const wId of this._input.allWayIdsInOrder) {
|
||||
newMembers.push({
|
||||
ref: wId,
|
||||
type: "way",
|
||||
role: member.role
|
||||
})
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const firstNodeMatchesRev = nodeIdBefore === undefined || nodeIdBefore === lastNode
|
||||
const lastNodeMatchesRev =nodeIdAfter === undefined || nodeIdAfter === firstNode
|
||||
if (firstNodeMatchesRev || lastNodeMatchesRev) {
|
||||
// We (probably) have a reversed situation, backward situation
|
||||
for (let i1 = this._input.allWayIdsInOrder.length - 1; i1 >= 0; i1--){
|
||||
// Iterate BACKWARDS
|
||||
const wId = this._input.allWayIdsInOrder[i1];
|
||||
newMembers.push({
|
||||
ref: wId,
|
||||
type: "way",
|
||||
role: member.role
|
||||
})
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Euhm, allright... Something weird is going on, but let's not care too much
|
||||
// Lets pretend this is forward going
|
||||
for (const wId of this._input.allWayIdsInOrder) {
|
||||
newMembers.push({
|
||||
ref: wId,
|
||||
type: "way",
|
||||
role: member.role
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [{
|
||||
id: relation.id,
|
||||
type: "relation",
|
||||
changes: {members: newMembers}
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue