import { UIEventSource } from "../UIEventSource" 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 } export default class RelationsTracker { public knownRelations = new UIEventSource>( new Map(), "Relation memberships" ) constructor() {} /** * Gets an overview of the relations - except for multipolygons. We don't care about those * @param overpassJson * @constructor */ private static GetRelationElements(overpassJson: any): Relation[] { const relations = overpassJson.elements.filter( (element) => element.type === "relation" && element.tags.type !== "multipolygon" ) for (const relation of relations) { relation.properties = relation.tags } return relations } public RegisterRelations(overpassJson: any): void { this.UpdateMembershipTable(RelationsTracker.GetRelationElements(overpassJson)) } /** * Build a mapping of {memberId --> {role in relation, id of relation} } * @param relations * @constructor */ private UpdateMembershipTable(relations: Relation[]): void { const memberships = this.knownRelations.data let changed = false 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, []) } 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 } } } if (changed) { this.knownRelations.ping() } } }