| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import { Changes } from "../../Osm/Changes" | 
					
						
							|  |  |  | import { OsmNode, OsmObject, OsmRelation, OsmWay } from "../../Osm/OsmObject" | 
					
						
							|  |  |  | import FeatureSource from "../FeatureSource" | 
					
						
							|  |  |  | import { UIEventSource } from "../../UIEventSource" | 
					
						
							|  |  |  | import { ChangeDescription } from "../../Osm/Actions/ChangeDescription" | 
					
						
							|  |  |  | import { ElementStorage } from "../../ElementStorage" | 
					
						
							|  |  |  | import { OsmId, OsmTags } from "../../../Models/OsmFeature" | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export class NewGeometryFromChangesFeatureSource implements FeatureSource { | 
					
						
							|  |  |  |     // This class name truly puts the 'Java' into 'Javascript'
 | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2022-06-13 01:35:50 +02:00
										 |  |  |      * A feature source containing exclusively new elements. | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-06-13 01:35:50 +02:00
										 |  |  |      * These elements are probably created by the 'SimpleAddUi' which generates a new point, but the import functionality might create a line or polygon too. | 
					
						
							|  |  |  |      * Other sources of new points are e.g. imports from nodes | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = | 
					
						
							|  |  |  |         new UIEventSource<{ feature: any; freshness: Date }[]>([]) | 
					
						
							|  |  |  |     public readonly name: string = "newFeatures" | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |     constructor(changes: Changes, allElementStorage: ElementStorage, backendUrl: string) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const seenChanges = new Set<ChangeDescription>() | 
					
						
							|  |  |  |         const features = this.features.data | 
					
						
							|  |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         changes.pendingChanges.stabilized(100).addCallbackAndRunD((changes) => { | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |             if (changes.length === 0) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 return | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             const now = new Date() | 
					
						
							|  |  |  |             let somethingChanged = false | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |             function add(feature) { | 
					
						
							|  |  |  |                 feature.id = feature.properties.id | 
					
						
							|  |  |  |                 features.push({ | 
					
						
							|  |  |  |                     feature: feature, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     freshness: now, | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                 }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 somethingChanged = true | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const change of changes) { | 
					
						
							|  |  |  |                 if (seenChanges.has(change)) { | 
					
						
							|  |  |  |                     // Already handled
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 seenChanges.add(change) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (change.tags === undefined) { | 
					
						
							|  |  |  |                     // If tags is undefined, this is probably a new point that is part of a split road
 | 
					
						
							|  |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                 if (change.id > 0) { | 
					
						
							|  |  |  |                     // This is an already existing object
 | 
					
						
							|  |  |  |                     // In _most_ of the cases, this means that this _isn't_ a new object
 | 
					
						
							|  |  |  |                     // However, when a point is snapped to an already existing point, we have to create a representation for this point!
 | 
					
						
							|  |  |  |                     // For this, we introspect the change
 | 
					
						
							| 
									
										
										
										
											2022-03-02 16:00:02 +01:00
										 |  |  |                     if (allElementStorage.has(change.type + "/" + change.id)) { | 
					
						
							|  |  |  |                         // The current point already exists, we don't have to do anything here
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         continue | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                     } | 
					
						
							|  |  |  |                     console.debug("Detected a reused point") | 
					
						
							|  |  |  |                     // The 'allElementsStore' does _not_ have this point yet, so we have to create it
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     OsmObject.DownloadObjectAsync(change.type + "/" + change.id).then((feat) => { | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                         console.log("Got the reused point:", feat) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                         for (const kv of change.tags) { | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                             feat.tags[kv.k] = kv.v | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         const geojson = feat.asGeoJson() | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                         allElementStorage.addOrGetElement(geojson) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         self.features.data.push({ feature: geojson, freshness: new Date() }) | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                         self.features.ping() | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 } else if (change.id < 0 && change.changes === undefined) { | 
					
						
							|  |  |  |                     // The geometry is not described - not a new point
 | 
					
						
							|  |  |  |                     if (change.id < 0) { | 
					
						
							|  |  |  |                         console.error("WARNING: got a new point without geometry!") | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     continue | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                 try { | 
					
						
							| 
									
										
										
										
											2022-09-21 02:21:20 +02:00
										 |  |  |                     const tags: OsmTags & {id: OsmId & string} = { | 
					
						
							|  |  |  |                         id: <OsmId & string>(change.type + "/" + change.id), | 
					
						
							| 
									
										
										
										
											2022-09-02 13:43:14 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                     for (const kv of change.tags) { | 
					
						
							|  |  |  |                         tags[kv.k] = kv.v | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     tags["_backend"] = backendUrl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     switch (change.type) { | 
					
						
							|  |  |  |                         case "node": | 
					
						
							|  |  |  |                             const n = new OsmNode(change.id) | 
					
						
							|  |  |  |                             n.tags = tags | 
					
						
							|  |  |  |                             n.lat = change.changes["lat"] | 
					
						
							|  |  |  |                             n.lon = change.changes["lon"] | 
					
						
							|  |  |  |                             const geojson = n.asGeoJson() | 
					
						
							|  |  |  |                             add(geojson) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             break | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                         case "way": | 
					
						
							|  |  |  |                             const w = new OsmWay(change.id) | 
					
						
							|  |  |  |                             w.tags = tags | 
					
						
							|  |  |  |                             w.nodes = change.changes["nodes"] | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             w.coordinates = change.changes["coordinates"].map(([lon, lat]) => [ | 
					
						
							|  |  |  |                                 lat, | 
					
						
							|  |  |  |                                 lon, | 
					
						
							|  |  |  |                             ]) | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                             add(w.asGeoJson()) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             break | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                         case "relation": | 
					
						
							|  |  |  |                             const r = new OsmRelation(change.id) | 
					
						
							|  |  |  |                             r.tags = tags | 
					
						
							|  |  |  |                             r.members = change.changes["members"] | 
					
						
							|  |  |  |                             add(r.asGeoJson()) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                             break | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } catch (e) { | 
					
						
							|  |  |  |                     console.error("Could not generate a new geometry to render on screen for:", e) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |             if (somethingChanged) { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 self.features.ping() | 
					
						
							| 
									
										
										
										
											2022-01-21 03:57:49 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |