| 
									
										
										
										
											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)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const hasSomeChange = mappings.has(key) | 
					
						
							|  |  |  |             || wayHasChangedNode || relationHasChangedMembers | 
					
						
							|  |  |  |         if(hasSomeChange){ | 
					
						
							|  |  |  |             change = {...change} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         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
										 |  |  | } |