| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | import { OsmNode, OsmRelation, OsmWay } from "../OsmObject" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Represents a single change to an object | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | export interface ChangeDescription { | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Metadata to be included in the changeset | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     meta: { | 
					
						
							|  |  |  |         /* | 
					
						
							|  |  |  |          * The theme with which this changeset was made | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         theme: string | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * The type of the change | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |         changeType: "answer" | "create" | "split" | "delete" | "move" | "import" | string | null | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |         /** | 
					
						
							|  |  |  |          * THe motivation for the change, e.g. 'deleted because does not exist anymore' | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2021-11-09 01:49:07 +01:00
										 |  |  |         specialMotivation?: string | 
					
						
							|  |  |  |         /** | 
					
						
							|  |  |  |          * Added by Changes.ts | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         distanceToObject?: number | 
					
						
							| 
									
										
										
										
											2021-10-04 03:12:42 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Identifier of the object | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     type: "node" | "way" | "relation" | 
					
						
							|  |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |      * Identifier of the object | 
					
						
							|  |  |  |      * Negative for new objects | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     id: number | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * All changes to tags | 
					
						
							|  |  |  |      * v = "" or v = undefined to erase this tag | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2021-10-10 00:53:14 +02:00
										 |  |  |      * Note that this list will only contain the _changes_ to the tags, not the full set of tags | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     tags?: { k: string; v: string }[] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * A change to the geometry: | 
					
						
							|  |  |  |      * 1) Change of node location | 
					
						
							|  |  |  |      * 2) Change of way geometry | 
					
						
							|  |  |  |      * 3) Change of relation members (untested) | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |     changes?: | 
					
						
							|  |  |  |         | { | 
					
						
							|  |  |  |               lat: number | 
					
						
							|  |  |  |               lon: number | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         | { | 
					
						
							| 
									
										
										
										
											2021-10-29 16:38:33 +02:00
										 |  |  |               /* Coordinates are only used for rendering. They should be LON, LAT | 
					
						
							|  |  |  |                * */ | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |               coordinates: [number, number][] | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  |               nodes: number[] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         | { | 
					
						
							|  |  |  |               members: { type: "node" | "way" | "relation"; ref: number; role: string }[] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* | 
					
						
							|  |  |  |     Set to delete the object | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     doDelete?: boolean | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | export class ChangeDescriptionTools { | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Rewrites all the ids in a changeDescription | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * // should rewrite the id of the changed object
 | 
					
						
							|  |  |  |      * const change = <ChangeDescription> { | 
					
						
							|  |  |  |      *             id: -1234, | 
					
						
							|  |  |  |      *             type: "node", | 
					
						
							|  |  |  |      *             meta:{ | 
					
						
							|  |  |  |      *                 theme:"test", | 
					
						
							|  |  |  |      *                 changeType: "answer" | 
					
						
							|  |  |  |      *             }, | 
					
						
							|  |  |  |      *             tags:[ | 
					
						
							|  |  |  |      *                 { | 
					
						
							|  |  |  |      *                     k: "key", | 
					
						
							|  |  |  |      *                     v: "value" | 
					
						
							|  |  |  |      *                 } | 
					
						
							|  |  |  |      *             ] | 
					
						
							|  |  |  |      *         } | 
					
						
							|  |  |  |      * } | 
					
						
							|  |  |  |      * const mapping = new Map<string, string>([["node/-1234", "node/42"]]) | 
					
						
							|  |  |  |      * const rewritten = ChangeDescriptionTools.rewriteIds(change, mapping) | 
					
						
							|  |  |  |      * rewritten.id // => 42
 | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * // should rewrite ids in nodes of a way
 | 
					
						
							|  |  |  |      * const change = <ChangeDescription> { | 
					
						
							|  |  |  |      *     type: "way", | 
					
						
							|  |  |  |      *     id: 789, | 
					
						
							|  |  |  |      *     changes: { | 
					
						
							|  |  |  |      *         nodes: [-1, -2, -3, 68453], | 
					
						
							|  |  |  |      *         coordinates: [] | 
					
						
							|  |  |  |      *     }, | 
					
						
							|  |  |  |      *     meta:{ | 
					
						
							|  |  |  |      *         theme:"test", | 
					
						
							|  |  |  |      *         changeType: "create" | 
					
						
							|  |  |  |      *     } | 
					
						
							|  |  |  |      * } | 
					
						
							|  |  |  |      * const mapping = new Map<string, string>([["node/-1", "node/42"],["node/-2", "node/43"],["node/-3", "node/44"]]) | 
					
						
							|  |  |  |      * const rewritten = ChangeDescriptionTools.rewriteIds(change, mapping) | 
					
						
							|  |  |  |      * rewritten.id // => 789
 | 
					
						
							|  |  |  |      * rewritten.changes["nodes"] // => [42,43,44, 68453]
 | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * // should rewrite ids in relationship members
 | 
					
						
							|  |  |  |      * const change = <ChangeDescription> { | 
					
						
							|  |  |  |      *     type: "way", | 
					
						
							|  |  |  |      *     id: 789, | 
					
						
							|  |  |  |      *     changes: { | 
					
						
							|  |  |  |      *         members: [{type: "way", ref: -1, role: "outer"},{type: "way", ref: 48, role: "outer"}], | 
					
						
							|  |  |  |      *     }, | 
					
						
							|  |  |  |      *     meta:{ | 
					
						
							|  |  |  |      *         theme:"test", | 
					
						
							|  |  |  |      *         changeType: "create" | 
					
						
							|  |  |  |      *     } | 
					
						
							|  |  |  |      * } | 
					
						
							|  |  |  |      * const mapping = new Map<string, string>([["way/-1", "way/42"],["node/-2", "node/43"],["node/-3", "node/44"]]) | 
					
						
							|  |  |  |      * const rewritten = ChangeDescriptionTools.rewriteIds(change, mapping) | 
					
						
							|  |  |  |      * rewritten.id // => 789
 | 
					
						
							|  |  |  |      * rewritten.changes["members"] // => [{type: "way", ref: 42, role: "outer"},{type: "way", ref: 48, role: "outer"}]
 | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public static rewriteIds( | 
					
						
							|  |  |  |         change: ChangeDescription, | 
					
						
							|  |  |  |         mappings: Map<string, string> | 
					
						
							|  |  |  |     ): ChangeDescription { | 
					
						
							|  |  |  |         const key = change.type + "/" + change.id | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const wayHasChangedNode = ((change.changes ?? {})["nodes"] ?? []).some((id) => | 
					
						
							|  |  |  |             mappings.has("node/" + id) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         const relationHasChangedMembers = ((change.changes ?? {})["members"] ?? []).some( | 
					
						
							|  |  |  |             (obj: { type: string; ref: number }) => mappings.has(obj.type + "/" + obj.ref) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const hasSomeChange = mappings.has(key) || wayHasChangedNode || relationHasChangedMembers | 
					
						
							|  |  |  |         if (hasSomeChange) { | 
					
						
							|  |  |  |             change = { ...change } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-08 04:18:53 +02:00
										 |  |  |         if (mappings.has(key)) { | 
					
						
							|  |  |  |             const [_, newId] = mappings.get(key).split("/") | 
					
						
							|  |  |  |             change.id = Number.parseInt(newId) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (wayHasChangedNode) { | 
					
						
							|  |  |  |             change.changes = { ...change.changes } | 
					
						
							|  |  |  |             change.changes["nodes"] = change.changes["nodes"].map((id) => { | 
					
						
							|  |  |  |                 const key = "node/" + id | 
					
						
							|  |  |  |                 if (!mappings.has(key)) { | 
					
						
							|  |  |  |                     return id | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const [_, newId] = mappings.get(key).split("/") | 
					
						
							|  |  |  |                 return Number.parseInt(newId) | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (relationHasChangedMembers) { | 
					
						
							|  |  |  |             change.changes = { ...change.changes } | 
					
						
							|  |  |  |             change.changes["members"] = change.changes["members"].map( | 
					
						
							|  |  |  |                 (obj: { type: string; ref: number }) => { | 
					
						
							|  |  |  |                     const key = obj.type + "/" + obj.ref | 
					
						
							|  |  |  |                     if (!mappings.has(key)) { | 
					
						
							|  |  |  |                         return obj | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     const [_, newId] = mappings.get(key).split("/") | 
					
						
							|  |  |  |                     return { ...obj, ref: Number.parseInt(newId) } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return change | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |     public static getGeojsonGeometry(change: ChangeDescription): any { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |         switch (change.type) { | 
					
						
							|  |  |  |             case "node": | 
					
						
							|  |  |  |                 const n = new OsmNode(change.id) | 
					
						
							|  |  |  |                 n.lat = change.changes["lat"] | 
					
						
							|  |  |  |                 n.lon = change.changes["lon"] | 
					
						
							|  |  |  |                 return n.asGeoJson().geometry | 
					
						
							|  |  |  |             case "way": | 
					
						
							|  |  |  |                 const w = new OsmWay(change.id) | 
					
						
							|  |  |  |                 w.nodes = change.changes["nodes"] | 
					
						
							| 
									
										
										
										
											2022-02-22 14:13:41 +01:00
										 |  |  |                 w.coordinates = change.changes["coordinates"].map(([lon, lat]) => [lat, lon]) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 return w.asGeoJson().geometry | 
					
						
							|  |  |  |             case "relation": | 
					
						
							|  |  |  |                 const r = new OsmRelation(change.id) | 
					
						
							|  |  |  |                 r.members = change.changes["members"] | 
					
						
							|  |  |  |                 return r.asGeoJson().geometry | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-07-15 20:47:28 +02:00
										 |  |  | } |