forked from MapComplete/MapComplete
		
	Refactoring(maplibre): remove 'freshness' and 'name' from FeatureSource to simplify the code
This commit is contained in:
		
							parent
							
								
									1b3609b13f
								
							
						
					
					
						commit
						231d67361e
					
				
					 30 changed files with 161 additions and 269 deletions
				
			
		|  | @ -13,15 +13,15 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig" | |||
| import Constants from "../../Models/Constants" | ||||
| import TileFreshnessCalculator from "../FeatureSource/TileFreshnessCalculator" | ||||
| import { Tiles } from "../../Models/TileRange" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class OverpassFeatureSource implements FeatureSource { | ||||
|     public readonly name = "OverpassFeatureSource" | ||||
| 
 | ||||
|     /** | ||||
|      * The last loaded features of the geojson | ||||
|      * The last loaded features, as geojson | ||||
|      */ | ||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = | ||||
|         new UIEventSource<any[]>(undefined) | ||||
|     public readonly features: UIEventSource<Feature[]> = new UIEventSource(undefined) | ||||
| 
 | ||||
|     public readonly runningQuery: UIEventSource<boolean> = new UIEventSource<boolean>(false) | ||||
|     public readonly timeout: UIEventSource<number> = new UIEventSource<number>(0) | ||||
|  | @ -243,7 +243,6 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|             data.features.forEach((feature) => | ||||
|                 SimpleMetaTagger.objectMetaInfo.applyMetaTagsOnFeature( | ||||
|                     feature, | ||||
|                     date, | ||||
|                     undefined, | ||||
|                     this.state | ||||
|                 ) | ||||
|  |  | |||
|  | @ -101,7 +101,7 @@ export default class MetaTagRecalculator { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public registerSource(source: FeatureSourceForLayer & Tiled, recalculateOnEveryChange = false) { | ||||
|     public registerSource(source: FeatureSourceForLayer & Tiled) { | ||||
|         if (source === undefined) { | ||||
|             return | ||||
|         } | ||||
|  |  | |||
|  | @ -1,20 +1,19 @@ | |||
| import FeatureSource from "../FeatureSource" | ||||
| import { Store } from "../../UIEventSource" | ||||
| import { ElementStorage } from "../../ElementStorage" | ||||
| import FeatureSource from "../FeatureSource"; | ||||
| import { Store } from "../../UIEventSource"; | ||||
| import { ElementStorage } from "../../ElementStorage"; | ||||
| import { Feature } from "geojson"; | ||||
| 
 | ||||
| /** | ||||
|  * Makes sure that every feature is added to the ElementsStorage, so that the tags-eventsource can be retrieved | ||||
|  */ | ||||
| export default class RegisteringAllFromFeatureSourceActor { | ||||
|     public readonly features: Store<{ feature: any; freshness: Date }[]> | ||||
|     public readonly name | ||||
|     public readonly features: Store<Feature[]> | ||||
| 
 | ||||
|     constructor(source: FeatureSource, allElements: ElementStorage) { | ||||
|         this.features = source.features | ||||
|         this.name = "RegisteringSource of " + source.name | ||||
|         this.features.addCallbackAndRunD((features) => { | ||||
|             for (const feature of features) { | ||||
|                 allElements.addOrGetElement(feature.feature) | ||||
|                 allElements.addOrGetElement(<any> feature) | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ import { BBox } from "../../BBox" | |||
| import SimpleFeatureSource from "../Sources/SimpleFeatureSource" | ||||
| import FilteredLayer from "../../../Models/FilteredLayer" | ||||
| import Loc from "../../../Models/Loc" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| /*** | ||||
|  * Saves all the features that are passed in to localstorage, so they can be retrieved on the next run | ||||
|  | @ -82,7 +83,7 @@ export default class SaveTileToLocalStorageActor { | |||
|                         continue | ||||
|                     } | ||||
|                     loadedTiles.add(key) | ||||
|                     this.GetIdb(key).then((features: { feature: any; freshness: Date }[]) => { | ||||
|                     this.GetIdb(key).then((features: Feature[]) => { | ||||
|                         if (features === undefined) { | ||||
|                             return | ||||
|                         } | ||||
|  | @ -90,7 +91,7 @@ export default class SaveTileToLocalStorageActor { | |||
|                         const src = new SimpleFeatureSource( | ||||
|                             self._flayer, | ||||
|                             key, | ||||
|                             new UIEventSource<{ feature: any; freshness: Date }[]>(features) | ||||
|                             new UIEventSource<Feature[]>(features) | ||||
|                         ) | ||||
|                         registerTile(src) | ||||
|                     }) | ||||
|  |  | |||
|  | @ -136,7 +136,7 @@ export default class FeaturePipeline { | |||
|             // Passthrough to passed function, except that it registers as well
 | ||||
|             handleFeatureSource(src) | ||||
|             src.features.addCallbackAndRunD((fs) => { | ||||
|                 fs.forEach((ff) => state.allElements.addOrGetElement(<any>ff.feature)) | ||||
|                 fs.forEach((ff) => state.allElements.addOrGetElement(<any>ff)) | ||||
|             }) | ||||
|         } | ||||
| 
 | ||||
|  | @ -422,7 +422,7 @@ export default class FeaturePipeline { | |||
|         } | ||||
|         return TileHierarchyTools.getTiles(requestedHierarchy, bbox) | ||||
|             .filter((featureSource) => featureSource.features?.data !== undefined) | ||||
|             .map((featureSource) => featureSource.features.data.map((fs) => fs.feature)) | ||||
|             .map((featureSource) => <OsmFeature[]>featureSource.features.data) | ||||
|     } | ||||
| 
 | ||||
|     public GetTilesPerLayerWithin( | ||||
|  | @ -639,10 +639,7 @@ export default class FeaturePipeline { | |||
|      * Inject a new point | ||||
|      */ | ||||
|     InjectNewPoint(geojson) { | ||||
|         this.newGeometryHandler.features.data.push({ | ||||
|             feature: geojson, | ||||
|             freshness: new Date(), | ||||
|         }) | ||||
|         this.newGeometryHandler.features.data.push(geojson) | ||||
|         this.newGeometryHandler.features.ping() | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -1,15 +1,10 @@ | |||
| import { Store, UIEventSource } from "../UIEventSource" | ||||
| import { Store } from "../UIEventSource" | ||||
| import FilteredLayer from "../../Models/FilteredLayer" | ||||
| import { BBox } from "../BBox" | ||||
| import { Feature, Geometry } from "@turf/turf" | ||||
| import { OsmFeature } from "../../Models/OsmFeature" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default interface FeatureSource { | ||||
|     features: Store<{ feature: OsmFeature; freshness: Date }[]> | ||||
|     /** | ||||
|      * Mainly used for debuging | ||||
|      */ | ||||
|     name: string | ||||
|     features: Store<Feature[]> | ||||
| } | ||||
| 
 | ||||
| export interface Tiled { | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ import FeatureSource, { FeatureSourceForLayer, Tiled } from "./FeatureSource" | |||
| import { Store } from "../UIEventSource" | ||||
| import FilteredLayer from "../../Models/FilteredLayer" | ||||
| import SimpleFeatureSource from "./Sources/SimpleFeatureSource" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| /** | ||||
|  * In some rare cases, some elements are shown on multiple layers (when 'passthrough' is enabled) | ||||
|  | @ -32,7 +33,7 @@ export default class PerLayerFeatureSourceSplitter { | |||
|             // We try to figure out (for each feature) in which feature store it should be saved.
 | ||||
|             // Note that this splitter is only run when it is invoked by the overpass feature source, so we can't be sure in which layer it should go
 | ||||
| 
 | ||||
|             const featuresPerLayer = new Map<string, { feature; freshness }[]>() | ||||
|             const featuresPerLayer = new Map<string, Feature[]>() | ||||
|             const noLayerFound = [] | ||||
| 
 | ||||
|             for (const layer of layers.data) { | ||||
|  | @ -42,7 +43,7 @@ export default class PerLayerFeatureSourceSplitter { | |||
|             for (const f of features) { | ||||
|                 let foundALayer = false | ||||
|                 for (const layer of layers.data) { | ||||
|                     if (layer.layerDef.source.osmTags.matchesProperties(f.feature.properties)) { | ||||
|                     if (layer.layerDef.source.osmTags.matchesProperties(f.properties)) { | ||||
|                         // We have found our matching layer!
 | ||||
|                         featuresPerLayer.get(layer.layerDef.id).push(f) | ||||
|                         foundALayer = true | ||||
|  |  | |||
|  | @ -6,11 +6,11 @@ import { UIEventSource } from "../../UIEventSource" | |||
| import { FeatureSourceForLayer, IndexedFeatureSource } from "../FeatureSource" | ||||
| import FilteredLayer from "../../../Models/FilteredLayer" | ||||
| import { ChangeDescription, ChangeDescriptionTools } from "../../Osm/Actions/ChangeDescription" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class ChangeGeometryApplicator implements FeatureSourceForLayer { | ||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = | ||||
|         new UIEventSource<{ feature: any; freshness: Date }[]>([]) | ||||
|     public readonly name: string | ||||
|     public readonly features: UIEventSource<Feature[]> = | ||||
|         new UIEventSource<Feature[]>([]) | ||||
|     public readonly layer: FilteredLayer | ||||
|     private readonly source: IndexedFeatureSource | ||||
|     private readonly changes: Changes | ||||
|  | @ -20,8 +20,7 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { | |||
|         this.changes = changes | ||||
|         this.layer = source.layer | ||||
| 
 | ||||
|         this.name = "ChangesApplied(" + source.name + ")" | ||||
|         this.features = new UIEventSource<{ feature: any; freshness: Date }[]>(undefined) | ||||
|         this.features = new UIEventSource<Feature[]>(undefined) | ||||
| 
 | ||||
|         const self = this | ||||
|         source.features.addCallbackAndRunD((_) => self.update()) | ||||
|  | @ -58,9 +57,9 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { | |||
|                 changesPerId.set(key, [ch]) | ||||
|             } | ||||
|         } | ||||
|         const newFeatures: { feature: any; freshness: Date }[] = [] | ||||
|         const newFeatures: Feature[] = [] | ||||
|         for (const feature of upstreamFeatures) { | ||||
|             const changesForFeature = changesPerId.get(feature.feature.properties.id) | ||||
|             const changesForFeature = changesPerId.get(feature.properties.id) | ||||
|             if (changesForFeature === undefined) { | ||||
|                 // No changes for this element
 | ||||
|                 newFeatures.push(feature) | ||||
|  | @ -73,7 +72,7 @@ export default class ChangeGeometryApplicator implements FeatureSourceForLayer { | |||
|             } | ||||
|             // We only apply the last change as that one'll have the latest geometry
 | ||||
|             const change = changesForFeature[changesForFeature.length - 1] | ||||
|             copy.feature.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) | ||||
|             copy.geometry = ChangeDescriptionTools.getGeojsonGeometry(change) | ||||
|             console.log( | ||||
|                 "Applying a geometry change onto:", | ||||
|                 feature, | ||||
|  |  | |||
|  | @ -1,16 +1,13 @@ | |||
| import { UIEventSource } from "../../UIEventSource" | ||||
| import FeatureSource, { FeatureSourceForLayer, IndexedFeatureSource, Tiled } from "../FeatureSource" | ||||
| import FilteredLayer from "../../../Models/FilteredLayer" | ||||
| import { Tiles } from "../../../Models/TileRange" | ||||
| import { BBox } from "../../BBox" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class FeatureSourceMerger | ||||
|     implements FeatureSourceForLayer, Tiled, IndexedFeatureSource | ||||
| { | ||||
|     public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< | ||||
|         { feature: any; freshness: Date }[] | ||||
|     >([]) | ||||
|     public readonly name | ||||
|     public features: UIEventSource<Feature[]> = new UIEventSource([]) | ||||
|     public readonly layer: FilteredLayer | ||||
|     public readonly tileIndex: number | ||||
|     public readonly bbox: BBox | ||||
|  | @ -32,12 +29,6 @@ export default class FeatureSourceMerger | |||
|         this.bbox = bbox | ||||
|         this._sources = sources | ||||
|         this.layer = layer | ||||
|         this.name = | ||||
|             "FeatureSourceMerger(" + | ||||
|             layer.layerDef.id + | ||||
|             ", " + | ||||
|             Tiles.tile_from_index(tileIndex).join(",") + | ||||
|             ")" | ||||
|         const self = this | ||||
| 
 | ||||
|         const handledSources = new Set<FeatureSource>() | ||||
|  | @ -63,14 +54,11 @@ export default class FeatureSourceMerger | |||
| 
 | ||||
|     private Update() { | ||||
|         let somethingChanged = false | ||||
|         const all: Map<string, { feature: any; freshness: Date }> = new Map< | ||||
|             string, | ||||
|             { feature: any; freshness: Date } | ||||
|         >() | ||||
|         const all: Map<string, Feature> = new Map() | ||||
|         // We seed the dictionary with the previously loaded features
 | ||||
|         const oldValues = this.features.data ?? [] | ||||
|         for (const oldValue of oldValues) { | ||||
|             all.set(oldValue.feature.id, oldValue) | ||||
|             all.set(oldValue.properties.id, oldValue) | ||||
|         } | ||||
| 
 | ||||
|         for (const source of this._sources.data) { | ||||
|  | @ -78,7 +66,7 @@ export default class FeatureSourceMerger | |||
|                 continue | ||||
|             } | ||||
|             for (const f of source.features.data) { | ||||
|                 const id = f.feature.properties.id | ||||
|                 const id = f.properties.id | ||||
|                 if (!all.has(id)) { | ||||
|                     // This is a new feature
 | ||||
|                     somethingChanged = true | ||||
|  | @ -89,11 +77,11 @@ export default class FeatureSourceMerger | |||
|                 // This value has been seen already, either in a previous run or by a previous datasource
 | ||||
|                 // Let's figure out if something changed
 | ||||
|                 const oldV = all.get(id) | ||||
|                 if (oldV.freshness < f.freshness) { | ||||
|                     // Jup, this feature is fresher
 | ||||
|                     all.set(id, f) | ||||
|                     somethingChanged = true | ||||
|                 if (oldV === f) { | ||||
|                     continue | ||||
|                 } | ||||
|                 all.set(id, f) | ||||
|                 somethingChanged = true | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,13 +4,10 @@ import { FeatureSourceForLayer, Tiled } from "../FeatureSource" | |||
| import { BBox } from "../../BBox" | ||||
| import { ElementStorage } from "../../ElementStorage" | ||||
| import { TagsFilter } from "../../Tags/TagsFilter" | ||||
| import { OsmFeature } from "../../../Models/OsmFeature" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class FilteringFeatureSource implements FeatureSourceForLayer, Tiled { | ||||
|     public features: UIEventSource<{ feature: any; freshness: Date }[]> = new UIEventSource< | ||||
|         { feature: any; freshness: Date }[] | ||||
|     >([]) | ||||
|     public readonly name | ||||
|     public features: UIEventSource<Feature[]> = new UIEventSource([]) | ||||
|     public readonly layer: FilteredLayer | ||||
|     public readonly tileIndex: number | ||||
|     public readonly bbox: BBox | ||||
|  | @ -36,7 +33,6 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | |||
|         upstream: FeatureSourceForLayer, | ||||
|         metataggingUpdated?: UIEventSource<any> | ||||
|     ) { | ||||
|         this.name = "FilteringFeatureSource(" + upstream.name + ")" | ||||
|         this.tileIndex = tileIndex | ||||
|         this.bbox = tileIndex === undefined ? undefined : BBox.fromTileIndex(tileIndex) | ||||
|         this.upstream = upstream | ||||
|  | @ -73,15 +69,14 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | |||
|     private update() { | ||||
|         const self = this | ||||
|         const layer = this.upstream.layer | ||||
|         const features: { feature: OsmFeature; freshness: Date }[] = | ||||
|             this.upstream.features.data ?? [] | ||||
|         const features: Feature[] = this.upstream.features.data ?? [] | ||||
|         const includedFeatureIds = new Set<string>() | ||||
|         const globalFilters = self.state.globalFilters?.data?.map((f) => f.filter) | ||||
|         const newFeatures = (features ?? []).filter((f) => { | ||||
|             self.registerCallback(f.feature) | ||||
|             self.registerCallback(f) | ||||
| 
 | ||||
|             const isShown: TagsFilter = layer.layerDef.isShown | ||||
|             const tags = f.feature.properties | ||||
|             const tags = f.properties | ||||
|             if (isShown !== undefined && !isShown.matchesProperties(tags)) { | ||||
|                 return false | ||||
|             } | ||||
|  | @ -92,10 +87,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | |||
|             const tagsFilter = Array.from(layer.appliedFilters?.data?.values() ?? []) | ||||
|             for (const filter of tagsFilter) { | ||||
|                 const neededTags: TagsFilter = filter?.currentFilter | ||||
|                 if ( | ||||
|                     neededTags !== undefined && | ||||
|                     !neededTags.matchesProperties(f.feature.properties) | ||||
|                 ) { | ||||
|                 if (neededTags !== undefined && !neededTags.matchesProperties(f.properties)) { | ||||
|                     // Hidden by the filter on the layer itself - we want to hide it no matter what
 | ||||
|                     return false | ||||
|                 } | ||||
|  | @ -103,16 +95,13 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | |||
| 
 | ||||
|             for (const filter of globalFilters ?? []) { | ||||
|                 const neededTags: TagsFilter = filter?.currentFilter | ||||
|                 if ( | ||||
|                     neededTags !== undefined && | ||||
|                     !neededTags.matchesProperties(f.feature.properties) | ||||
|                 ) { | ||||
|                 if (neededTags !== undefined && !neededTags.matchesProperties(f.properties)) { | ||||
|                     // Hidden by the filter on the layer itself - we want to hide it no matter what
 | ||||
|                     return false | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             includedFeatureIds.add(f.feature.properties.id) | ||||
|             includedFeatureIds.add(f.properties.id) | ||||
|             return true | ||||
|         }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,9 +8,10 @@ import { FeatureSourceForLayer, Tiled } from "../FeatureSource" | |||
| import { Tiles } from "../../../Models/TileRange" | ||||
| import { BBox } from "../../BBox" | ||||
| import { GeoOperations } from "../../GeoOperations" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { | ||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> | ||||
|     public readonly features: UIEventSource<Feature[]> | ||||
|     public readonly state = new UIEventSource<undefined | { error: string } | "loaded">(undefined) | ||||
|     public readonly name | ||||
|     public readonly isOsmCache: boolean | ||||
|  | @ -69,7 +70,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { | |||
|         this.name = "GeoJsonSource of " + url | ||||
| 
 | ||||
|         this.isOsmCache = flayer.layerDef.source.isOsmCacheLayer | ||||
|         this.features = new UIEventSource<{ feature: any; freshness: Date }[]>([]) | ||||
|         this.features = new UIEventSource<Feature[]>([]) | ||||
|         this.LoadJSONFrom(url) | ||||
|     } | ||||
| 
 | ||||
|  | @ -110,7 +111,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { | |||
|                 } | ||||
| 
 | ||||
|                 const time = new Date() | ||||
|                 const newFeatures: { feature: any; freshness: Date }[] = [] | ||||
|                 const newFeatures: Feature[] = [] | ||||
|                 let i = 0 | ||||
|                 let skipped = 0 | ||||
|                 for (const feature of json.features) { | ||||
|  | @ -146,7 +147,7 @@ export default class GeoJsonSource implements FeatureSourceForLayer, Tiled { | |||
|                         freshness = new Date(props["_last_edit:timestamp"]) | ||||
|                     } | ||||
| 
 | ||||
|                     newFeatures.push({ feature: feature, freshness: freshness }) | ||||
|                     newFeatures.push(feature) | ||||
|                 } | ||||
| 
 | ||||
|                 if (newFeatures.length == 0) { | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import { UIEventSource } from "../../UIEventSource" | |||
| import { ChangeDescription } from "../../Osm/Actions/ChangeDescription" | ||||
| import { ElementStorage } from "../../ElementStorage" | ||||
| import { OsmId, OsmTags } from "../../../Models/OsmFeature" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export class NewGeometryFromChangesFeatureSource implements FeatureSource { | ||||
|     // This class name truly puts the 'Java' into 'Javascript'
 | ||||
|  | @ -15,9 +16,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | |||
|      * 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 | ||||
|      */ | ||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> = | ||||
|         new UIEventSource<{ feature: any; freshness: Date }[]>([]) | ||||
|     public readonly name: string = "newFeatures" | ||||
|     public readonly features: UIEventSource<Feature[]> = new UIEventSource<Feature[]>([]) | ||||
| 
 | ||||
|     constructor(changes: Changes, allElementStorage: ElementStorage, backendUrl: string) { | ||||
|         const seenChanges = new Set<ChangeDescription>() | ||||
|  | @ -29,15 +28,11 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | |||
|                 return | ||||
|             } | ||||
| 
 | ||||
|             const now = new Date() | ||||
|             let somethingChanged = false | ||||
| 
 | ||||
|             function add(feature) { | ||||
|                 feature.id = feature.properties.id | ||||
|                 features.push({ | ||||
|                     feature: feature, | ||||
|                     freshness: now, | ||||
|                 }) | ||||
|                 features.push(feature) | ||||
|                 somethingChanged = true | ||||
|             } | ||||
| 
 | ||||
|  | @ -71,7 +66,7 @@ export class NewGeometryFromChangesFeatureSource implements FeatureSource { | |||
|                         } | ||||
|                         const geojson = feat.asGeoJson() | ||||
|                         allElementStorage.addOrGetElement(geojson) | ||||
|                         self.features.data.push({ feature: geojson, freshness: new Date() }) | ||||
|                         self.features.data.push(geojson) | ||||
|                         self.features.ping() | ||||
|                     }) | ||||
|                     continue | ||||
|  |  | |||
|  | @ -5,28 +5,25 @@ | |||
| import FeatureSource, { Tiled } from "../FeatureSource" | ||||
| import { Store, UIEventSource } from "../../UIEventSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class RememberingSource implements FeatureSource, Tiled { | ||||
|     public readonly features: Store<{ feature: any; freshness: Date }[]> | ||||
|     public readonly name | ||||
|     public readonly features: Store<Feature[]> | ||||
|     public readonly tileIndex: number | ||||
|     public readonly bbox: BBox | ||||
| 
 | ||||
|     constructor(source: FeatureSource & Tiled) { | ||||
|         const self = this | ||||
|         this.name = "RememberingSource of " + source.name | ||||
|         this.tileIndex = source.tileIndex | ||||
|         this.bbox = source.bbox | ||||
| 
 | ||||
|         const empty = [] | ||||
|         const featureSource = new UIEventSource<{ feature: any; freshness: Date }[]>(empty) | ||||
|         const featureSource = new UIEventSource<Feature[]>(empty) | ||||
|         this.features = featureSource | ||||
|         source.features.addCallbackAndRunD((features) => { | ||||
|             const oldFeatures = self.features?.data ?? empty | ||||
|             // Then new ids
 | ||||
|             const ids = new Set<string>( | ||||
|                 features.map((f) => f.feature.properties.id + f.feature.geometry.type) | ||||
|             ) | ||||
|             const ids = new Set<string>(features.map((f) => f.properties.id + f.geometry.type)) | ||||
|             // the old data
 | ||||
|             const oldData = oldFeatures.filter( | ||||
|                 (old) => !ids.has(old.feature.properties.id + old.feature.geometry.type) | ||||
|  |  | |||
|  | @ -1,13 +1,12 @@ | |||
| /** | ||||
|  * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. | ||||
|  */ | ||||
| import { Store } from "../../UIEventSource" | ||||
| import { GeoOperations } from "../../GeoOperations" | ||||
| import FeatureSource from "../FeatureSource" | ||||
| import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig" | ||||
| import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" | ||||
| import LineRenderingConfig from "../../../Models/ThemeConfig/LineRenderingConfig" | ||||
| 
 | ||||
| /** | ||||
|  * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. | ||||
|  */ | ||||
| export default class RenderingMultiPlexerFeatureSource { | ||||
|     public readonly features: Store< | ||||
|         (any & { | ||||
|  | @ -64,8 +63,7 @@ export default class RenderingMultiPlexerFeatureSource { | |||
|                 withIndex.push(patched) | ||||
|             } | ||||
| 
 | ||||
|             for (const f of features) { | ||||
|                 const feat = f.feature | ||||
|             for (const feat of features) { | ||||
|                 if (feat === undefined) { | ||||
|                     continue | ||||
|                 } | ||||
|  |  | |||
|  | @ -2,23 +2,18 @@ import { UIEventSource } from "../../UIEventSource" | |||
| import FilteredLayer from "../../../Models/FilteredLayer" | ||||
| import { FeatureSourceForLayer, Tiled } from "../FeatureSource" | ||||
| import { BBox } from "../../BBox" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| export default class SimpleFeatureSource implements FeatureSourceForLayer, Tiled { | ||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> | ||||
|     public readonly name: string = "SimpleFeatureSource" | ||||
|     public readonly features: UIEventSource<Feature[]> | ||||
|     public readonly layer: FilteredLayer | ||||
|     public readonly bbox: BBox = BBox.global | ||||
|     public readonly tileIndex: number | ||||
| 
 | ||||
|     constructor( | ||||
|         layer: FilteredLayer, | ||||
|         tileIndex: number, | ||||
|         featureSource?: UIEventSource<{ feature: any; freshness: Date }[]> | ||||
|     ) { | ||||
|         this.name = "SimpleFeatureSource(" + layer.layerDef.id + ")" | ||||
|     constructor(layer: FilteredLayer, tileIndex: number, featureSource?: UIEventSource<Feature[]>) { | ||||
|         this.layer = layer | ||||
|         this.tileIndex = tileIndex ?? 0 | ||||
|         this.bbox = BBox.fromTileIndex(this.tileIndex) | ||||
|         this.features = featureSource ?? new UIEventSource<{ feature: any; freshness: Date }[]>([]) | ||||
|         this.features = featureSource ?? new UIEventSource<Feature[]>([]) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -8,63 +8,34 @@ import { Feature } from "geojson" | |||
|  * A simple, read only feature store. | ||||
|  */ | ||||
| export default class StaticFeatureSource implements FeatureSource { | ||||
|     public readonly features: Store<{ feature: any; freshness: Date }[]> | ||||
|     public readonly name: string | ||||
|     public readonly features: Store<Feature[]> | ||||
| 
 | ||||
|     constructor( | ||||
|         features: Store<{ feature: Feature; freshness: Date }[]>, | ||||
|         name = "StaticFeatureSource" | ||||
|         features: | ||||
|             | Store<Feature[]> | ||||
|             | Feature[] | ||||
|             | { features: Feature[] } | ||||
|             | { features: Store<Feature[]> } | ||||
|     ) { | ||||
|         if (features === undefined) { | ||||
|             throw "Static feature source received undefined as source" | ||||
|         } | ||||
|         this.name = name | ||||
|         this.features = features | ||||
|         let feats: Feature[] | Store<Feature[]> | ||||
|         if (features["features"]) { | ||||
|             feats = features["features"] | ||||
|         } else { | ||||
|             feats = <Feature[] | Store<Feature[]>>features | ||||
|         } | ||||
| 
 | ||||
|         if (Array.isArray(feats)) { | ||||
|             this.features = new ImmutableStore(feats) | ||||
|         } else { | ||||
|             this.features = feats | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static fromGeojsonAndDate( | ||||
|         features: { feature: Feature; freshness: Date }[], | ||||
|         name = "StaticFeatureSourceFromGeojsonAndDate" | ||||
|     ): StaticFeatureSource { | ||||
|         return new StaticFeatureSource(new ImmutableStore(features), name) | ||||
|     } | ||||
| 
 | ||||
|     public static fromGeojson( | ||||
|         geojson: Feature[], | ||||
|         name = "StaticFeatureSourceFromGeojson" | ||||
|     ): StaticFeatureSource { | ||||
|         const now = new Date() | ||||
|         return StaticFeatureSource.fromGeojsonAndDate( | ||||
|             geojson.map((feature) => ({ feature, freshness: now })), | ||||
|             name | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     public static fromGeojsonStore( | ||||
|         geojson: Store<Feature[]>, | ||||
|         name = "StaticFeatureSourceFromGeojson" | ||||
|     ): StaticFeatureSource { | ||||
|         const now = new Date() | ||||
|         const mapped: Store<{ feature: Feature; freshness: Date }[]> = geojson.map((features) => | ||||
|             features.map((feature) => ({ feature, freshness: now })) | ||||
|         ) | ||||
|         return new StaticFeatureSource(mapped, name) | ||||
|     } | ||||
| 
 | ||||
|     static fromDateless( | ||||
|         featureSource: Store<{ feature: Feature }[]>, | ||||
|         name = "StaticFeatureSourceFromDateless" | ||||
|     ) { | ||||
|         const now = new Date() | ||||
|         return new StaticFeatureSource( | ||||
|             featureSource.map((features) => | ||||
|                 features.map((feature) => ({ | ||||
|                     feature: feature.feature, | ||||
|                     freshness: now, | ||||
|                 })) | ||||
|             ), | ||||
|             name | ||||
|         ) | ||||
|     public static fromGeojson(geojson: Feature[]): StaticFeatureSource { | ||||
|         return new StaticFeatureSource(geojson) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -76,11 +47,7 @@ export class TiledStaticFeatureSource | |||
|     public readonly tileIndex: number | ||||
|     public readonly layer: FilteredLayer | ||||
| 
 | ||||
|     constructor( | ||||
|         features: Store<{ feature: any; freshness: Date }[]>, | ||||
|         layer: FilteredLayer, | ||||
|         tileIndex: number = 0 | ||||
|     ) { | ||||
|     constructor(features: Store<Feature[]>, layer: FilteredLayer, tileIndex: number = 0) { | ||||
|         super(features) | ||||
|         this.tileIndex = tileIndex | ||||
|         this.layer = layer | ||||
|  |  | |||
|  | @ -53,11 +53,9 @@ export default class FullNodeDatabaseSource implements TileHierarchy<FeatureSour | |||
|                 src.ping() | ||||
|             } | ||||
|         } | ||||
|         const now = new Date() | ||||
|         const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => ({ | ||||
|             feature: osmNode.asGeoJson(), | ||||
|             freshness: now, | ||||
|         })) | ||||
|         const asGeojsonFeatures = Array.from(nodesById.values()).map((osmNode) => | ||||
|             osmNode.asGeoJson() | ||||
|         ) | ||||
| 
 | ||||
|         const featureSource = new SimpleFeatureSource(this.layer, tileId) | ||||
|         featureSource.features.setData(asGeojsonFeatures) | ||||
|  |  | |||
|  | @ -175,7 +175,7 @@ export default class OsmFeatureSource { | |||
|                 new PerLayerFeatureSourceSplitter( | ||||
|                     this.filteredLayers, | ||||
|                     this.handleTile, | ||||
|                     StaticFeatureSource.fromGeojson(geojson.features), | ||||
|                     new StaticFeatureSource(geojson.features), | ||||
|                     { | ||||
|                         tileIndex: index, | ||||
|                     } | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import FilteredLayer from "../../../Models/FilteredLayer" | |||
| import TileHierarchy from "./TileHierarchy" | ||||
| import { Tiles } from "../../../Models/TileRange" | ||||
| import { BBox } from "../../BBox" | ||||
| import { Feature } from "geojson"; | ||||
| 
 | ||||
| /** | ||||
|  * Contains all features in a tiled fashion. | ||||
|  | @ -29,7 +30,7 @@ export default class TiledFeatureSource | |||
| 
 | ||||
|     public readonly maxFeatureCount: number | ||||
|     public readonly name | ||||
|     public readonly features: UIEventSource<{ feature: any; freshness: Date }[]> | ||||
|     public readonly features: UIEventSource<Feature[]> | ||||
|     public readonly containedIds: Store<Set<string>> | ||||
| 
 | ||||
|     public readonly bbox: BBox | ||||
|  | @ -80,7 +81,7 @@ export default class TiledFeatureSource | |||
|             if (features === undefined) { | ||||
|                 return undefined | ||||
|             } | ||||
|             return new Set(features.map((f) => f.feature.properties.id)) | ||||
|             return new Set(features.map((f) => f.properties.id)) | ||||
|         }) | ||||
| 
 | ||||
|         // We register this tile, but only when there is some data in it
 | ||||
|  | @ -132,7 +133,7 @@ export default class TiledFeatureSource | |||
|      * @param features | ||||
|      * @private | ||||
|      */ | ||||
|     private addFeatures(features: { feature: any; freshness: Date }[]) { | ||||
|     private addFeatures(features: Feature[]) { | ||||
|         if (features === undefined || features.length === 0) { | ||||
|             return | ||||
|         } | ||||
|  | @ -180,7 +181,7 @@ export default class TiledFeatureSource | |||
|         const overlapsboundary = [] | ||||
| 
 | ||||
|         for (const feature of features) { | ||||
|             const bbox = BBox.get(feature.feature) | ||||
|             const bbox = BBox.get(feature) | ||||
| 
 | ||||
|             // There are a few strategies to deal with features that cross tile boundaries
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ import SimpleMetaTaggers, { SimpleMetaTagger } from "./SimpleMetaTagger" | |||
| import { ExtraFuncParams, ExtraFunctions } from "./ExtraFunctions" | ||||
| import LayerConfig from "../Models/ThemeConfig/LayerConfig" | ||||
| import { ElementStorage } from "./ElementStorage" | ||||
| import { Feature } from "geojson" | ||||
| 
 | ||||
| /** | ||||
|  * Metatagging adds various tags to the elements, e.g. lat, lon, surface area, ... | ||||
|  | @ -20,7 +21,7 @@ export default class MetaTagging { | |||
|      * Returns true if at least one feature has changed properties | ||||
|      */ | ||||
|     public static addMetatags( | ||||
|         features: { feature: any; freshness: Date }[], | ||||
|         features: Feature[], | ||||
|         params: ExtraFuncParams, | ||||
|         layer: LayerConfig, | ||||
|         state?: { allElements?: ElementStorage }, | ||||
|  | @ -55,8 +56,7 @@ export default class MetaTagging { | |||
| 
 | ||||
|         for (let i = 0; i < features.length; i++) { | ||||
|             const ff = features[i] | ||||
|             const feature = ff.feature | ||||
|             const freshness = ff.freshness | ||||
|             const feature = ff | ||||
|             let somethingChanged = false | ||||
|             let definedTags = new Set(Object.getOwnPropertyNames(feature.properties)) | ||||
|             for (const metatag of metatagsToApply) { | ||||
|  | @ -72,19 +72,14 @@ export default class MetaTagging { | |||
|                             continue | ||||
|                         } | ||||
|                         somethingChanged = true | ||||
|                         metatag.applyMetaTagsOnFeature(feature, freshness, layer, state) | ||||
|                         metatag.applyMetaTagsOnFeature(feature, layer, state) | ||||
|                         if (options?.evaluateStrict) { | ||||
|                             for (const key of metatag.keys) { | ||||
|                                 feature.properties[key] | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                         const newValueAdded = metatag.applyMetaTagsOnFeature( | ||||
|                             feature, | ||||
|                             freshness, | ||||
|                             layer, | ||||
|                             state | ||||
|                         ) | ||||
|                         const newValueAdded = metatag.applyMetaTagsOnFeature(feature, layer, state) | ||||
|                         /* Note that the expression: | ||||
|                          * `somethingChanged = newValueAdded || metatag.applyMetaTagsOnFeature(feature, freshness)` | ||||
|                          * Is WRONG | ||||
|  |  | |||
|  | @ -17,12 +17,7 @@ export class SimpleMetaTagger { | |||
|     public readonly doc: string | ||||
|     public readonly isLazy: boolean | ||||
|     public readonly includesDates: boolean | ||||
|     public readonly applyMetaTagsOnFeature: ( | ||||
|         feature: any, | ||||
|         freshness: Date, | ||||
|         layer: LayerConfig, | ||||
|         state | ||||
|     ) => boolean | ||||
|     public readonly applyMetaTagsOnFeature: (feature: any, layer: LayerConfig, state) => boolean | ||||
| 
 | ||||
|     /*** | ||||
|      * A function that adds some extra data to a feature | ||||
|  | @ -41,7 +36,7 @@ export class SimpleMetaTagger { | |||
|             isLazy?: boolean | ||||
|             cleanupRetagger?: boolean | ||||
|         }, | ||||
|         f: (feature: any, freshness: Date, layer: LayerConfig, state) => boolean | ||||
|         f: (feature: any, layer: LayerConfig, state) => boolean | ||||
|     ) { | ||||
|         this.keys = docs.keys | ||||
|         this.doc = docs.doc | ||||
|  | @ -71,7 +66,7 @@ export class ReferencingWaysMetaTagger extends SimpleMetaTagger { | |||
|                 isLazy: true, | ||||
|                 doc: "_referencing_ways contains - for a node - which ways use this this node as point in their geometry. ", | ||||
|             }, | ||||
|             (feature, _, __, state) => { | ||||
|             (feature, _, state) => { | ||||
|                 if (!ReferencingWaysMetaTagger.enabled) { | ||||
|                     return false | ||||
|                 } | ||||
|  | @ -116,7 +111,7 @@ export class CountryTagger extends SimpleMetaTagger { | |||
|                 doc: "The country code of the property (with latlon2country)", | ||||
|                 includesDates: false, | ||||
|             }, | ||||
|             (feature, _, __, state) => { | ||||
|             (feature, _, state) => { | ||||
|                 let centerPoint: any = GeoOperations.centerpoint(feature) | ||||
|                 const lat = centerPoint.geometry.coordinates[1] | ||||
|                 const lon = centerPoint.geometry.coordinates[0] | ||||
|  | @ -236,7 +231,7 @@ export default class SimpleMetaTaggers { | |||
|             keys: ["_layer"], | ||||
|             includesDates: false, | ||||
|         }, | ||||
|         (feature, freshness, layer) => { | ||||
|         (feature, _, layer) => { | ||||
|             if (feature.properties._layer === layer.id) { | ||||
|                 return false | ||||
|             } | ||||
|  | @ -322,7 +317,7 @@ export default class SimpleMetaTaggers { | |||
|             doc: "If 'units' is defined in the layoutConfig, then this metatagger will rewrite the specified keys to have the canonical form (e.g. `1meter` will be rewritten to `1m`; `1` will be rewritten to `1m` as well)", | ||||
|             keys: ["Theme-defined keys"], | ||||
|         }, | ||||
|         (feature, _, __, state) => { | ||||
|         (feature, _, state) => { | ||||
|             const units = Utils.NoNull( | ||||
|                 [].concat(...(state?.layoutToUse?.layers?.map((layer) => layer.units) ?? [])) | ||||
|             ) | ||||
|  | @ -395,7 +390,7 @@ export default class SimpleMetaTaggers { | |||
|             includesDates: true, | ||||
|             isLazy: true, | ||||
|         }, | ||||
|         (feature, _, __, state) => { | ||||
|         (feature, _, state) => { | ||||
|             if (Utils.runningFromConsole) { | ||||
|                 // We are running from console, thus probably creating a cache
 | ||||
|                 // isOpen is irrelevant
 | ||||
|  | @ -508,17 +503,13 @@ export default class SimpleMetaTaggers { | |||
| 
 | ||||
|     private static currentTime = new SimpleMetaTagger( | ||||
|         { | ||||
|             keys: ["_now:date", "_now:datetime", "_loaded:date", "_loaded:_datetime"], | ||||
|             keys: ["_now:date", "_now:datetime"], | ||||
|             doc: "Adds the time that the data got loaded - pretty much the time of downloading from overpass. The format is YYYY-MM-DD hh:mm, aka 'sortable' aka ISO-8601-but-not-entirely", | ||||
|             includesDates: true, | ||||
|         }, | ||||
|         (feature, freshness) => { | ||||
|         (feature) => { | ||||
|             const now = new Date() | ||||
| 
 | ||||
|             if (typeof freshness === "string") { | ||||
|                 freshness = new Date(freshness) | ||||
|             } | ||||
| 
 | ||||
|             function date(d: Date) { | ||||
|                 return d.toISOString().slice(0, 10) | ||||
|             } | ||||
|  | @ -529,8 +520,6 @@ export default class SimpleMetaTaggers { | |||
| 
 | ||||
|             feature.properties["_now:date"] = date(now) | ||||
|             feature.properties["_now:datetime"] = datetime(now) | ||||
|             feature.properties["_loaded:date"] = date(freshness) | ||||
|             feature.properties["_loaded:datetime"] = datetime(freshness) | ||||
|             return true | ||||
|         } | ||||
|     ) | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ export default class FeaturePipelineState extends MapState { | |||
|         function registerSource(source: FeatureSourceForLayer & Tiled) { | ||||
|             clusterCounter.addTile(source) | ||||
|             const sourceBBox = source.features.map((allFeatures) => | ||||
|                 BBox.bboxAroundAll(allFeatures.map((f) => BBox.get(f.feature))) | ||||
|                 BBox.bboxAroundAll(allFeatures.map(BBox.get)) | ||||
|             ) | ||||
| 
 | ||||
|             // Do show features indicates if the respective 'showDataLayer' should be shown. It can be hidden by e.g. clustering
 | ||||
|  | @ -131,7 +131,7 @@ export default class FeaturePipelineState extends MapState { | |||
|             handleRawFeatureSource: registerRaw, | ||||
|         }) | ||||
|         this.metatagRecalculator = new MetaTagRecalculator(this, this.featurePipeline) | ||||
|         this.metatagRecalculator.registerSource(this.currentView, true) | ||||
|         this.metatagRecalculator.registerSource(this.currentView) | ||||
| 
 | ||||
|         sourcesToRegister.forEach((source) => self.metatagRecalculator.registerSource(source)) | ||||
| 
 | ||||
|  |  | |||
|  | @ -213,38 +213,33 @@ export default class MapState extends UserRelatedState { | |||
| 
 | ||||
|         let i = 0 | ||||
|         const self = this | ||||
|         const features: Store<{ feature: any; freshness: Date }[]> = this.currentBounds.map( | ||||
|             (bounds) => { | ||||
|                 if (bounds === undefined) { | ||||
|                     return [] | ||||
|                 } | ||||
|                 i++ | ||||
|                 const feature = { | ||||
|                     freshness: new Date(), | ||||
|                     feature: { | ||||
|                         type: "Feature", | ||||
|                         properties: { | ||||
|                             id: "current_view-" + i, | ||||
|                             current_view: "yes", | ||||
|                             zoom: "" + self.locationControl.data.zoom, | ||||
|                         }, | ||||
|                         geometry: { | ||||
|                             type: "Polygon", | ||||
|                             coordinates: [ | ||||
|                                 [ | ||||
|                                     [bounds.maxLon, bounds.maxLat], | ||||
|                                     [bounds.minLon, bounds.maxLat], | ||||
|                                     [bounds.minLon, bounds.minLat], | ||||
|                                     [bounds.maxLon, bounds.minLat], | ||||
|                                     [bounds.maxLon, bounds.maxLat], | ||||
|                                 ], | ||||
|                             ], | ||||
|                         }, | ||||
|                     }, | ||||
|                 } | ||||
|                 return [feature] | ||||
|         const features: Store<Feature[]> = this.currentBounds.map((bounds) => { | ||||
|             if (bounds === undefined) { | ||||
|                 return [] | ||||
|             } | ||||
|         ) | ||||
|             i++ | ||||
|             const feature = { | ||||
|                 type: "Feature", | ||||
|                 properties: { | ||||
|                     id: "current_view-" + i, | ||||
|                     current_view: "yes", | ||||
|                     zoom: "" + self.locationControl.data.zoom, | ||||
|                 }, | ||||
|                 geometry: { | ||||
|                     type: "Polygon", | ||||
|                     coordinates: [ | ||||
|                         [ | ||||
|                             [bounds.maxLon, bounds.maxLat], | ||||
|                             [bounds.minLon, bounds.maxLat], | ||||
|                             [bounds.minLon, bounds.minLat], | ||||
|                             [bounds.maxLon, bounds.minLat], | ||||
|                             [bounds.maxLon, bounds.maxLat], | ||||
|                         ], | ||||
|                     ], | ||||
|                 }, | ||||
|             } | ||||
|             return [feature] | ||||
|         }) | ||||
| 
 | ||||
|         this.currentView = new TiledStaticFeatureSource(features, currentViewLayer) | ||||
|     } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { Feature, Geometry } from "@turf/turf" | ||||
| import { Feature, Geometry } from "geojson" | ||||
| 
 | ||||
| export type RelationId = `relation/${number}` | ||||
| export type WayId = `way/${number}` | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ export class CompareToAlreadyExistingNotes | |||
|             state, | ||||
|             zoomToFeatures: true, | ||||
|             leafletMap: comparisonMap.leafletMap, | ||||
|             features: StaticFeatureSource.fromGeojsonStore( | ||||
|             features: new StaticFeatureSource( | ||||
|                 partitionedImportPoints.map((p) => <Feature[]>p.hasNearby) | ||||
|             ), | ||||
|             popup: (tags, layer) => new FeatureInfoBox(tags, layer, state), | ||||
|  |  | |||
|  | @ -166,7 +166,7 @@ export default class ConflationChecker | |||
|             [osmLiveData.bounds, zoomLevel.GetValue()] | ||||
|         ) | ||||
| 
 | ||||
|         const preview = StaticFeatureSource.fromGeojsonStore(geojsonFeatures) | ||||
|         const preview = new StaticFeatureSource(geojsonFeatures) | ||||
| 
 | ||||
|         new ShowDataLayer({ | ||||
|             layerToShow: new LayerConfig(currentview), | ||||
|  | @ -225,7 +225,7 @@ export default class ConflationChecker | |||
|             }, | ||||
|             [nearbyCutoff.GetValue().stabilized(500)] | ||||
|         ) | ||||
|         const nearbyFeatures = StaticFeatureSource.fromGeojsonStore(geojsonMapped) | ||||
|         const nearbyFeatures = new StaticFeatureSource(geojsonMapped) | ||||
|         const paritionedImport = ImportUtils.partitionFeaturesIfNearby( | ||||
|             toImport, | ||||
|             geojson, | ||||
|  | @ -233,7 +233,7 @@ export default class ConflationChecker | |||
|         ) | ||||
| 
 | ||||
|         // Featuresource showing OSM-features which are nearby a toImport-feature
 | ||||
|         const toImportWithNearby = StaticFeatureSource.fromGeojsonStore( | ||||
|         const toImportWithNearby = new StaticFeatureSource( | ||||
|             paritionedImport.map((els) => <Feature[]>els?.hasNearby ?? []) | ||||
|         ) | ||||
|         toImportWithNearby.features.addCallback((nearby) => | ||||
|  |  | |||
|  | @ -8,8 +8,6 @@ import Constants from "../../Models/Constants" | |||
| import { DropDown } from "../Input/DropDown" | ||||
| import { Utils } from "../../Utils" | ||||
| import LayerConfig from "../../Models/ThemeConfig/LayerConfig" | ||||
| import BaseLayer from "../../Models/BaseLayer" | ||||
| import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" | ||||
| import Loc from "../../Models/Loc" | ||||
| import Minimap from "../Base/Minimap" | ||||
| import Attribution from "../BigComponents/Attribution" | ||||
|  | @ -140,9 +138,7 @@ export class MapPreview | |||
|             new ShowDataLayer({ | ||||
|                 layerToShow, | ||||
|                 zoomToFeatures: true, | ||||
|                 features: StaticFeatureSource.fromDateless( | ||||
|                     matching.map((features) => features.map((feature) => ({ feature }))) | ||||
|                 ), | ||||
|                 features: new StaticFeatureSource(matching), | ||||
|                 leafletMap: map.leafletMap, | ||||
|                 popup: (tag) => new PreviewPanel(tag), | ||||
|             }) | ||||
|  |  | |||
|  | @ -53,7 +53,7 @@ export default class LocationInput | |||
|      * Used for rendering | ||||
|      * @private | ||||
|      */ | ||||
|     private readonly _snapToRaw: Store<{ feature: Feature }[]> | ||||
|     private readonly _snapToRaw: Store<Feature[]> | ||||
|     private readonly _value: Store<Loc> | ||||
|     private readonly _snappedPoint: Store<any> | ||||
|     private readonly _maxSnapDistance: number | ||||
|  | @ -112,7 +112,7 @@ export default class LocationInput | |||
|     constructor(options?: { | ||||
|         minZoom?: number | ||||
|         mapBackground?: UIEventSource<BaseLayer> | ||||
|         snapTo?: UIEventSource<{ feature: Feature }[]> | ||||
|         snapTo?: UIEventSource<Feature[]> | ||||
|         renderLayerForSnappedPoint?: LayerConfig | ||||
|         maxSnapDistance?: number | ||||
|         snappedPointTags?: any | ||||
|  | @ -276,7 +276,7 @@ export default class LocationInput | |||
|             if (this._snapToRaw !== undefined) { | ||||
|                 // Show the lines to snap to
 | ||||
|                 new ShowDataMultiLayer({ | ||||
|                     features: StaticFeatureSource.fromDateless(this._snapToRaw), | ||||
|                     features: new StaticFeatureSource(this._snapToRaw), | ||||
|                     zoomToFeatures: false, | ||||
|                     leafletMap: this.map.leafletMap, | ||||
|                     layers: this._state.filteredLayers, | ||||
|  | @ -286,12 +286,12 @@ export default class LocationInput | |||
|                     if (loc === undefined) { | ||||
|                         return [] | ||||
|                     } | ||||
|                     return [{ feature: loc }] | ||||
|                     return [loc] | ||||
|                 }) | ||||
| 
 | ||||
|                 // The 'matchlayer' is the layer which shows the target location
 | ||||
|                 new ShowDataLayer({ | ||||
|                     features: StaticFeatureSource.fromDateless(matchPoint), | ||||
|                     features: new StaticFeatureSource(matchPoint), | ||||
|                     zoomToFeatures: false, | ||||
|                     leafletMap: this.map.leafletMap, | ||||
|                     layerToShow: this._matching_layer, | ||||
|  |  | |||
|  | @ -3,7 +3,6 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection" | |||
| import FeaturePipeline from "../../Logic/FeatureSource/FeaturePipeline" | ||||
| import BaseUIElement from "../BaseUIElement" | ||||
| import LocationInput from "../Input/LocationInput" | ||||
| import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers" | ||||
| import { BBox } from "../../Logic/BBox" | ||||
| import { TagUtils } from "../../Logic/Tags/TagUtils" | ||||
| import { SubtleButton } from "../Base/SubtleButton" | ||||
|  | @ -12,7 +11,6 @@ import Translations from "../i18n/Translations" | |||
| import Svg from "../../Svg" | ||||
| import Toggle from "../Input/Toggle" | ||||
| import SimpleAddUI, { PresetInfo } from "../BigComponents/SimpleAddUI" | ||||
| import BaseLayer from "../../Models/BaseLayer" | ||||
| import Img from "../Base/Img" | ||||
| import Title from "../Base/Title" | ||||
| import { GlobalFilter } from "../../Logic/State/MapState" | ||||
|  | @ -20,6 +18,8 @@ import { VariableUiElement } from "../Base/VariableUIElement" | |||
| import { Tag } from "../../Logic/Tags/Tag" | ||||
| import { WayId } from "../../Models/OsmFeature" | ||||
| import { Translation } from "../i18n/Translation" | ||||
| import { Feature } from "geojson"; | ||||
| import { AvailableRasterLayers, RasterLayerPolygon } from "../../Models/RasterLayers"; | ||||
| 
 | ||||
| export default class ConfirmLocationOfPoint extends Combine { | ||||
|     constructor( | ||||
|  | @ -28,7 +28,7 @@ export default class ConfirmLocationOfPoint extends Combine { | |||
|             featureSwitchIsTesting: UIEventSource<boolean> | ||||
|             osmConnection: OsmConnection | ||||
|             featurePipeline: FeaturePipeline | ||||
|             backgroundLayer?: UIEventSource<BaseLayer> | ||||
|             backgroundLayer?: UIEventSource<RasterLayerPolygon | undefined> | ||||
|         }, | ||||
|         filterViewIsOpened: UIEventSource<boolean>, | ||||
|         preset: PresetInfo, | ||||
|  | @ -55,10 +55,10 @@ export default class ConfirmLocationOfPoint extends Combine { | |||
|             const locationSrc = new UIEventSource(zloc) | ||||
| 
 | ||||
|             let backgroundLayer = new UIEventSource( | ||||
|                 state?.backgroundLayer?.data ?? AvailableBaseLayers.osmCarto | ||||
|                 state?.backgroundLayer?.data ?? AvailableRasterLayers.osmCarto | ||||
|             ) | ||||
|             if (preset.preciseInput.preferredBackground) { | ||||
|                 const defaultBackground = AvailableBaseLayers.SelectBestLayerAccordingTo( | ||||
|                 const defaultBackground = AvailableRasterLayers.SelectBestLayerAccordingTo( | ||||
|                     locationSrc, | ||||
|                     new UIEventSource<string | string[]>(preset.preciseInput.preferredBackground) | ||||
|                 ) | ||||
|  | @ -66,10 +66,10 @@ export default class ConfirmLocationOfPoint extends Combine { | |||
|                 backgroundLayer.setData(defaultBackground.data) | ||||
|             } | ||||
| 
 | ||||
|             let snapToFeatures: UIEventSource<{ feature: any }[]> = undefined | ||||
|             let snapToFeatures: UIEventSource<Feature[]> = undefined | ||||
|             let mapBounds: UIEventSource<BBox> = undefined | ||||
|             if (preset.preciseInput.snapToLayers && preset.preciseInput.snapToLayers.length > 0) { | ||||
|                 snapToFeatures = new UIEventSource<{ feature: any }[]>([]) | ||||
|                 snapToFeatures = new UIEventSource< Feature[]>([]) | ||||
|                 mapBounds = new UIEventSource<BBox>(undefined) | ||||
|             } | ||||
| 
 | ||||
|  | @ -105,13 +105,13 @@ export default class ConfirmLocationOfPoint extends Combine { | |||
|                         Math.max(preset.boundsFactor ?? 0.25, 2) | ||||
|                     ) | ||||
|                     loadedBbox = bbox | ||||
|                     const allFeatures: { feature: any }[] = [] | ||||
|                     const allFeatures: Feature[] = [] | ||||
|                     preset.preciseInput.snapToLayers.forEach((layerId) => { | ||||
|                         console.log("Snapping to", layerId) | ||||
|                         state.featurePipeline | ||||
|                             .GetFeaturesWithin(layerId, bbox) | ||||
|                             ?.forEach((feats) => | ||||
|                                 allFeatures.push(...feats.map((f) => ({ feature: f }))) | ||||
|                                 allFeatures.push(...<any[]>feats) | ||||
|                             ) | ||||
|                     }) | ||||
|                     console.log("Snapping to", allFeatures) | ||||
|  |  | |||
							
								
								
									
										7
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								test.ts
									
										
									
									
									
								
							|  | @ -1,20 +1,17 @@ | |||
| import SvelteUIElement from "./UI/Base/SvelteUIElement" | ||||
| import MaplibreMap from "./UI/Map/MaplibreMap.svelte" | ||||
| import { ImmutableStore, UIEventSource } from "./Logic/UIEventSource" | ||||
| import { UIEventSource } from "./Logic/UIEventSource" | ||||
| import { MapLibreAdaptor } from "./UI/Map/MapLibreAdaptor" | ||||
| import { AvailableRasterLayers, RasterLayerPolygon } from "./Models/RasterLayers" | ||||
| import type { Map as MlMap } from "maplibre-gl" | ||||
| import RasterLayerPicker from "./UI/Map/RasterLayerPicker.svelte" | ||||
| import BackgroundLayerResetter from "./Logic/Actors/BackgroundLayerResetter" | ||||
| import { ShowDataLayer } from "./UI/Map/ShowDataLayer" | ||||
| import StaticFeatureSource from "./Logic/FeatureSource/Sources/StaticFeatureSource" | ||||
| import { Layer } from "leaflet" | ||||
| import LayerConfig from "./Models/ThemeConfig/LayerConfig" | ||||
| import * as bench from "./assets/generated/layers/bench.json" | ||||
| import { Utils } from "./Utils" | ||||
| import SimpleFeatureSource from "./Logic/FeatureSource/Sources/SimpleFeatureSource" | ||||
| import { FilterState } from "./Models/FilteredLayer" | ||||
| import { FixedUiElement } from "./UI/Base/FixedUiElement" | ||||
| 
 | ||||
| async function main() { | ||||
|     const mlmap = new UIEventSource<MlMap>(undefined) | ||||
|     const location = new UIEventSource<{ lon: number; lat: number }>({ | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue