2021-04-18 14:24:30 +02:00
|
|
|
import State from "../../State";
|
2021-09-21 02:10:42 +02:00
|
|
|
import {UIEventSource} from "../UIEventSource";
|
2021-04-18 14:24:30 +02:00
|
|
|
|
|
|
|
export interface Relation {
|
|
|
|
id: number,
|
|
|
|
type: "relation"
|
|
|
|
members: {
|
|
|
|
type: ("way" | "node" | "relation"),
|
|
|
|
ref: number,
|
|
|
|
role: string
|
|
|
|
}[],
|
|
|
|
tags: any,
|
|
|
|
// Alias for tags; tags == properties
|
|
|
|
properties: any
|
|
|
|
}
|
|
|
|
|
2021-09-21 02:10:42 +02:00
|
|
|
export default class RelationsTracker {
|
2021-04-18 14:24:30 +02:00
|
|
|
|
2021-09-21 02:10:42 +02:00
|
|
|
public knownRelations = new UIEventSource<Map<string, { role: string; relation: Relation }[]>>(new Map(), "Relation memberships");
|
|
|
|
|
|
|
|
constructor() {
|
|
|
|
}
|
|
|
|
|
|
|
|
public RegisterRelations(overpassJson: any): void {
|
|
|
|
this.UpdateMembershipTable(RelationsTracker.GetRelationElements(overpassJson))
|
2021-04-18 14:24:30 +02:00
|
|
|
}
|
2021-04-22 03:30:46 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets an overview of the relations - except for multipolygons. We don't care about those
|
|
|
|
* @param overpassJson
|
|
|
|
* @constructor
|
|
|
|
*/
|
2021-09-21 02:10:42 +02:00
|
|
|
private static GetRelationElements(overpassJson: any): Relation[] {
|
2021-04-22 03:30:46 +02:00
|
|
|
const relations = overpassJson.elements
|
|
|
|
.filter(element => element.type === "relation" && element.tags.type !== "multipolygon")
|
2021-04-18 14:24:30 +02:00
|
|
|
for (const relation of relations) {
|
|
|
|
relation.properties = relation.tags
|
|
|
|
}
|
|
|
|
return relations
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Build a mapping of {memberId --> {role in relation, id of relation} }
|
|
|
|
* @param relations
|
|
|
|
* @constructor
|
|
|
|
*/
|
2021-09-21 02:10:42 +02:00
|
|
|
private UpdateMembershipTable(relations: Relation[]): void {
|
|
|
|
const memberships = this.knownRelations.data
|
|
|
|
let changed = false;
|
2021-04-18 14:24:30 +02:00
|
|
|
for (const relation of relations) {
|
|
|
|
for (const member of relation.members) {
|
|
|
|
const role = {
|
|
|
|
role: member.role,
|
|
|
|
relation: relation
|
|
|
|
}
|
|
|
|
const key = member.type + "/" + member.ref
|
|
|
|
if (!memberships.has(key)) {
|
|
|
|
memberships.set(key, [])
|
|
|
|
}
|
2021-09-21 02:10:42 +02:00
|
|
|
const knownRelations = memberships.get(key)
|
|
|
|
|
|
|
|
const alreadyExists = knownRelations.some(knownRole => {
|
|
|
|
return knownRole.role === role.role && knownRole.relation === role.relation
|
|
|
|
})
|
|
|
|
if (!alreadyExists) {
|
|
|
|
knownRelations.push(role)
|
|
|
|
changed = true;
|
|
|
|
}
|
2021-04-18 14:24:30 +02:00
|
|
|
}
|
|
|
|
}
|
2021-09-21 02:10:42 +02:00
|
|
|
if (changed) {
|
|
|
|
this.knownRelations.ping()
|
|
|
|
}
|
2021-04-18 14:24:30 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|