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