forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			91 lines
		
	
	
		
			No EOL
		
	
	
		
			3.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			No EOL
		
	
	
		
			3.6 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 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'
 | |
| 
 | |
|     /**
 | |
|      * 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";
 | |
| 
 | |
|     constructor(changes: Changes, backendUrl: string) {
 | |
| 
 | |
|         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
 | |
|                         }
 | |
|                         tags["id"] = change.type + "/" + change.id
 | |
| 
 | |
|                         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)
 | |
|                                 break;
 | |
|                             case "way":
 | |
|                                 const w = new OsmWay(change.id)
 | |
|                                 w.tags = tags
 | |
|                                 w.nodes = change.changes["nodes"]
 | |
|                                 w.coordinates = change.changes["coordinates"].map(coor => [coor[1], coor[0]])
 | |
|                                 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)
 | |
|                     }
 | |
| 
 | |
|                 }
 | |
| 
 | |
|                 self.features.ping()
 | |
|             })
 | |
|     }
 | |
| 
 | |
| } |