forked from MapComplete/MapComplete
		
	Fix #596
This commit is contained in:
		
							parent
							
								
									5182085f35
								
							
						
					
					
						commit
						1e3206120c
					
				
					 6 changed files with 108 additions and 69 deletions
				
			
		|  | @ -311,7 +311,7 @@ export default class FeaturePipeline { | |||
| 
 | ||||
| 
 | ||||
|         // Also load points/lines that are newly added. 
 | ||||
|         const newGeometry = new NewGeometryFromChangesFeatureSource(state.changes, state.osmConnection._oauth_config.url) | ||||
|         const newGeometry = new NewGeometryFromChangesFeatureSource(state.changes, state.allElements, state.osmConnection._oauth_config.url) | ||||
|         newGeometry.features.addCallbackAndRun(geometries => { | ||||
|             console.debug("New geometries are:", geometries) | ||||
|         }) | ||||
|  | @ -323,7 +323,10 @@ export default class FeaturePipeline { | |||
|                 // We don't bother to split them over tiles as it'll contain little features by default, so we simply add them like this
 | ||||
|                 perLayerHierarchy.get(perLayer.layer.layerDef.id).registerTile(perLayer) | ||||
|                 // AT last, we always apply the metatags whenever possible
 | ||||
|                 perLayer.features.addCallbackAndRunD(_ => self.onNewDataLoaded(perLayer)) | ||||
|                 perLayer.features.addCallbackAndRunD(feats => { | ||||
|                     console.log("New feature for layer ", perLayer.layer.layerDef.id, ":", feats) | ||||
|                     self.onNewDataLoaded(perLayer); | ||||
|                 }) | ||||
| 
 | ||||
|             }, | ||||
|             newGeometry, | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ export default class PerLayerFeatureSourceSplitter { | |||
|             } | ||||
| 
 | ||||
|             for (const f of features) { | ||||
|                 console.log("Classifying ", f.feature) | ||||
|                 for (const layer of layers.data) { | ||||
|                     if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { | ||||
|                         // We have found our matching layer!
 | ||||
|  | @ -50,8 +51,8 @@ export default class PerLayerFeatureSourceSplitter { | |||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     noLayerFound.push(f) | ||||
|                 } | ||||
|                 noLayerFound.push(f) | ||||
|             } | ||||
| 
 | ||||
|             // At this point, we have our features per layer as a list
 | ||||
|  |  | |||
|  | @ -63,7 +63,6 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | |||
|     } | ||||
| 
 | ||||
|     private update() { | ||||
|         console.log("FIltering", this.upstream.name) | ||||
|         const self = this; | ||||
|         const layer = this.upstream.layer; | ||||
|         const features: { feature: any; freshness: Date }[] = (this.upstream.features.data ?? []); | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| import {Changes} from "../../Osm/Changes"; | ||||
| import {OsmNode, OsmRelation, OsmWay} from "../../Osm/OsmObject"; | ||||
| 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"; | ||||
| 
 | ||||
| export class NewGeometryFromChangesFeatureSource implements FeatureSource { | ||||
|     // This class name truly puts the 'Java' into 'Javascript'
 | ||||
|  | @ -13,79 +14,115 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | |||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]); | ||||
|     public readonly name: string = "newFeatures"; | ||||
| 
 | ||||
|     constructor(changes: Changes, backendUrl: string) { | ||||
|     constructor(changes: Changes, allElementStorage: ElementStorage, 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; | ||||
|         changes.pendingChanges.addCallbackAndRunD(changes => { | ||||
|             if (changes.length === 0) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             const now = new Date(); | ||||
|             let somethingChanged = false; | ||||
| 
 | ||||
|             function add(feature) { | ||||
|                 feature.id = feature.properties.id | ||||
|                 features.push({ | ||||
|                     feature: feature, | ||||
|                     freshness: now | ||||
|                 }) | ||||
|                 somethingChanged = true; | ||||
|             } | ||||
| 
 | ||||
|             for (const change of changes) { | ||||
|                 if (seenChanges.has(change)) { | ||||
|                     // Already handled
 | ||||
|                     continue; | ||||
|                 } | ||||
|                 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 | ||||
|                 } | ||||
| 
 | ||||
|                 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) | ||||
|                 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
 | ||||
|                     if (allElementStorage.has(change.id)) { | ||||
|                         // const currentTags = allElementStorage.getEventSourceById(change.id).data
 | ||||
|                         continue; | ||||
|                     } | ||||
|                     console.debug("Detected a reused point") | ||||
|                     // The 'allElementsStore' does _not_ have this point yet, so we have to create it
 | ||||
|                     OsmObject.DownloadObjectAsync(change.type + "/" + change.id).then(feat => { | ||||
|                         console.log("Got the reused point:", feat) | ||||
|                         for (const kv of change.tags) { | ||||
|                             feat.tags[kv.k] = kv.v | ||||
|                         } | ||||
|                         const geojson=  feat.asGeoJson(); | ||||
|                         allElementStorage.addOrGetElement(geojson) | ||||
|                         self.features.data.push({feature: geojson, freshness: new Date()}) | ||||
|                         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!") | ||||
|                     } | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 | ||||
|                 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) | ||||
|                 } | ||||
| 
 | ||||
|             } | ||||
|             if (somethingChanged) { | ||||
|                 self.features.ping() | ||||
|             }) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -153,8 +153,7 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L | |||
|             "mapRendering": [ | ||||
|                 { | ||||
|                     "location": [ | ||||
|                         "point", | ||||
|                         "centroid" | ||||
|                         "point" | ||||
|                     ], | ||||
|                     "icon": { | ||||
|                         "render": "circle:white;help:black", | ||||
|  |  | |||
|  | @ -230,7 +230,7 @@ export default class LayerConfig extends WithContextLoader { | |||
|             if (this.lineRendering.length === 0 && this.mapRendering.length === 0) { | ||||
|                 console.log(json.mapRendering) | ||||
|                 throw("The layer " + this.id + " does not have any maprenderings defined and will thus not show up on the map at all. If this is intentional, set maprenderings to 'null' instead of '[]'") | ||||
|             } else if (!hasCenterRendering && this.lineRendering.length === 0) { | ||||
|             } else if (!hasCenterRendering && this.lineRendering.length === 0 && !this.source.geojsonSource?.startsWith("https://api.openstreetmap.org/api/0.6/notes.json")) { | ||||
|                 throw "The layer " + this.id + " might not render ways. This might result in dropped information" | ||||
|             } | ||||
|         } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue