| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | import {Changes} from "../../Osm/Changes"; | 
					
						
							|  |  |  | import {OsmNode, OsmRelation, OsmWay} from "../../Osm/OsmObject"; | 
					
						
							|  |  |  | import FeatureSource from "../FeatureSource"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../UIEventSource"; | 
					
						
							|  |  |  | import {ChangeDescription} from "../../Osm/Actions/ChangeDescription"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  |     /** | 
					
						
							|  |  |  |      * A feature source containing exclusively new elements | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]); | 
					
						
							|  |  |  |     public readonly name: string = "newFeatures"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-05 05:20:33 +01:00
										 |  |  |     constructor(changes: Changes, backendUrl: string) { | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const seenChanges = new Set<ChangeDescription>(); | 
					
						
							|  |  |  |         const features = this.features.data; | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         changes.pendingChanges | 
					
						
							|  |  |  |             .map(changes => changes.filter(ch => | 
					
						
							|  |  |  |                 // only new objects allowed
 | 
					
						
							|  |  |  |                 ch.id < 0 && | 
					
						
							|  |  |  |                 // The change is an update to the object (e.g. tags or geometry) - not the actual create
 | 
					
						
							|  |  |  |                 ch.changes !== undefined && | 
					
						
							|  |  |  |                 // If tags is undefined, this is probably a new point that is part of a split road
 | 
					
						
							|  |  |  |                 ch.tags !== undefined && | 
					
						
							|  |  |  |                 // Already handled
 | 
					
						
							|  |  |  |                 !seenChanges.has(ch))) | 
					
						
							|  |  |  |             .addCallbackAndRunD(changes => { | 
					
						
							|  |  |  |                 if (changes.length === 0) { | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 const now = new Date(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 function add(feature) { | 
					
						
							|  |  |  |                     feature.id = feature.properties.id | 
					
						
							|  |  |  |                     features.push({ | 
					
						
							|  |  |  |                         feature: feature, | 
					
						
							|  |  |  |                         freshness: now | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (const change of changes) { | 
					
						
							|  |  |  |                     seenChanges.add(change) | 
					
						
							|  |  |  |                     try { | 
					
						
							|  |  |  |                         const tags = {} | 
					
						
							|  |  |  |                         for (const kv of change.tags) { | 
					
						
							|  |  |  |                             tags[kv.k] = kv.v | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  |                         tags["id"] = change.type + "/" + change.id | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-05 05:20:33 +01:00
										 |  |  |                         tags["_backend"] = backendUrl | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                         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) | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             case "way": | 
					
						
							|  |  |  |                                 const w = new OsmWay(change.id) | 
					
						
							|  |  |  |                                 w.tags = tags | 
					
						
							|  |  |  |                                 w.nodes = change.changes["nodes"] | 
					
						
							| 
									
										
										
										
											2021-11-03 00:44:53 +01:00
										 |  |  |                                 w.coordinates = change.changes["coordinates"].map(coor => [coor[1], coor[0]]) | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                                 add(w.asGeoJson()) | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                             case "relation": | 
					
						
							|  |  |  |                                 const r = new OsmRelation(change.id) | 
					
						
							|  |  |  |                                 r.tags = tags | 
					
						
							|  |  |  |                                 r.members = change.changes["members"] | 
					
						
							|  |  |  |                                 add(r.asGeoJson()) | 
					
						
							|  |  |  |                                 break; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } catch (e) { | 
					
						
							|  |  |  |                         console.error("Could not generate a new geometry to render on screen for:", e) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-11-07 16:34:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  |                 self.features.ping() | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |