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. 
 |         // 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 => { |         newGeometry.features.addCallbackAndRun(geometries => { | ||||||
|             console.debug("New geometries are:", 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
 |                 // 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) |                 perLayerHierarchy.get(perLayer.layer.layerDef.id).registerTile(perLayer) | ||||||
|                 // AT last, we always apply the metatags whenever possible
 |                 // 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, |             newGeometry, | ||||||
|  |  | ||||||
|  | @ -41,6 +41,7 @@ export default class PerLayerFeatureSourceSplitter { | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (const f of features) { |             for (const f of features) { | ||||||
|  |                 console.log("Classifying ", f.feature) | ||||||
|                 for (const layer of layers.data) { |                 for (const layer of layers.data) { | ||||||
|                     if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { |                     if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { | ||||||
|                         // We have found our matching layer!
 |                         // We have found our matching layer!
 | ||||||
|  | @ -50,8 +51,8 @@ export default class PerLayerFeatureSourceSplitter { | ||||||
|                             break; |                             break; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     noLayerFound.push(f) |  | ||||||
|                 } |                 } | ||||||
|  |                 noLayerFound.push(f) | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // At this point, we have our features per layer as a list
 |             // 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() { |     private update() { | ||||||
|         console.log("FIltering", this.upstream.name) |  | ||||||
|         const self = this; |         const self = this; | ||||||
|         const layer = this.upstream.layer; |         const layer = this.upstream.layer; | ||||||
|         const features: { feature: any; freshness: Date }[] = (this.upstream.features.data ?? []); |         const features: { feature: any; freshness: Date }[] = (this.upstream.features.data ?? []); | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| import {Changes} from "../../Osm/Changes"; | 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 FeatureSource from "../FeatureSource"; | ||||||
| import {UIEventSource} from "../../UIEventSource"; | import {UIEventSource} from "../../UIEventSource"; | ||||||
| import {ChangeDescription} from "../../Osm/Actions/ChangeDescription"; | import {ChangeDescription} from "../../Osm/Actions/ChangeDescription"; | ||||||
|  | import {ElementStorage} from "../../ElementStorage"; | ||||||
| 
 | 
 | ||||||
| export class NewGeometryFromChangesFeatureSource implements FeatureSource { | export class NewGeometryFromChangesFeatureSource implements FeatureSource { | ||||||
|     // This class name truly puts the 'Java' into 'Javascript'
 |     // This class name truly puts the 'Java' into 'Javascript'
 | ||||||
|  | @ -13,28 +14,19 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | ||||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]); |     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource<{ feature: any; freshness: Date }[]>([]); | ||||||
|     public readonly name: string = "newFeatures"; |     public readonly name: string = "newFeatures"; | ||||||
| 
 | 
 | ||||||
|     constructor(changes: Changes, backendUrl: string) { |     constructor(changes: Changes, allElementStorage: ElementStorage, backendUrl: string) { | ||||||
| 
 | 
 | ||||||
|         const seenChanges = new Set<ChangeDescription>(); |         const seenChanges = new Set<ChangeDescription>(); | ||||||
|         const features = this.features.data; |         const features = this.features.data; | ||||||
|         const self = this; |         const self = this; | ||||||
| 
 | 
 | ||||||
|         changes.pendingChanges |         changes.pendingChanges.addCallbackAndRunD(changes => { | ||||||
|             .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) { |             if (changes.length === 0) { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const now = new Date(); |             const now = new Date(); | ||||||
|  |             let somethingChanged = false; | ||||||
| 
 | 
 | ||||||
|             function add(feature) { |             function add(feature) { | ||||||
|                 feature.id = feature.properties.id |                 feature.id = feature.properties.id | ||||||
|  | @ -42,10 +34,54 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | ||||||
|                     feature: feature, |                     feature: feature, | ||||||
|                     freshness: now |                     freshness: now | ||||||
|                 }) |                 }) | ||||||
|  |                 somethingChanged = true; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             for (const change of changes) { |             for (const change of changes) { | ||||||
|  |                 if (seenChanges.has(change)) { | ||||||
|  |                     // Already handled
 | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|                 seenChanges.add(change) |                 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 | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 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 { |                 try { | ||||||
|                     const tags = {} |                     const tags = {} | ||||||
|                     for (const kv of change.tags) { |                     for (const kv of change.tags) { | ||||||
|  | @ -83,8 +119,9 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|             } |             } | ||||||
| 
 |             if (somethingChanged) { | ||||||
|                 self.features.ping() |                 self.features.ping() | ||||||
|  |             } | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -153,8 +153,7 @@ export default class CreateNoteImportLayer extends Conversion<LayerConfigJson, L | ||||||
|             "mapRendering": [ |             "mapRendering": [ | ||||||
|                 { |                 { | ||||||
|                     "location": [ |                     "location": [ | ||||||
|                         "point", |                         "point" | ||||||
|                         "centroid" |  | ||||||
|                     ], |                     ], | ||||||
|                     "icon": { |                     "icon": { | ||||||
|                         "render": "circle:white;help:black", |                         "render": "circle:white;help:black", | ||||||
|  |  | ||||||
|  | @ -230,7 +230,7 @@ export default class LayerConfig extends WithContextLoader { | ||||||
|             if (this.lineRendering.length === 0 && this.mapRendering.length === 0) { |             if (this.lineRendering.length === 0 && this.mapRendering.length === 0) { | ||||||
|                 console.log(json.mapRendering) |                 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 '[]'") |                 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" |                 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