Feature: second iteration of clustering

This commit is contained in:
Pieter Vander Vennet 2025-07-21 22:02:04 +02:00
parent 8360ab9a8b
commit 5bc8f11d24
3 changed files with 25 additions and 5 deletions

View file

@ -8,7 +8,8 @@ import { Utils } from "../../../Utils"
import { TagsFilter } from "../../Tags/TagsFilter"
import { BBox } from "../../BBox"
import { OsmTags } from "../../../Models/OsmFeature"
;("use strict")
("use strict")
/**
* A wrapper around the 'Overpass'-object.
@ -138,7 +139,6 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
return undefined
}
this.runningQuery.setData(true)
console.trace("Overpass feature source: querying geojson")
data = (await overpass.queryGeoJson(bounds))[0]
} catch (e) {
this.retries.data++

View file

@ -15,12 +15,15 @@ export interface ClusteringOptions {
* drop those features and emit a summary tile instead
*/
cutoff?: 20 | number
showSummaryAt?: "tilecenter" | "average"
}
export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>> implements FeatureSource<T> {
public readonly summaryPoints: FeatureSource
private readonly id: string
private readonly showSummaryAt: "tilecenter" | "average"
features: Store<T[]>
/**
@ -35,6 +38,7 @@ export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>>
id: string,
options?: ClusteringOptions) {
this.id = id
this.showSummaryAt = options?.showSummaryAt ?? "average"
const clusterCutoff = options?.dontClusterAboveZoom ?? 17
const doCluster = options?.dontClusterAboveZoom === undefined ? new ImmutableStore(true) : currentZoomlevel.map(zoom => zoom <= clusterCutoff)
const cutoff = options?.cutoff ?? 20
@ -42,6 +46,7 @@ export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>>
currentZoomlevel = currentZoomlevel.stabilized(500)
this.summaryPoints = new StaticFeatureSource(summaryPoints)
this.features = (upstream.features.map(features => {
console.log(">>> Updating features in clusters ", this.id, ":", features)
if (!doCluster.data) {
summaryPoints.set([])
return features
@ -69,8 +74,23 @@ export class ClusteringFeatureSource<T extends Feature<Point> = Feature<Point>>
private createSummaryFeature(features: Feature<Point>[], tileId: number): Feature<Point> {
let lon: number
let lat: number
const [z, x, y] = Tiles.tile_from_index(tileId)
const [lon, lat] = Tiles.centerPointOf(z, x, y)
if (this.showSummaryAt === "tilecenter") {
[lon, lat] = Tiles.centerPointOf(z, x, y)
} else {
let lonSum = 0
let latSum = 0
for (const feature of features) {
const [lon, lat] = feature.geometry.coordinates
lonSum += lon
latSum += lat
}
lon = lonSum / features.length
lat = latSum / features.length
}
return <Feature<Point>>{
type: "Feature",
geometry: {

View file

@ -351,7 +351,6 @@ export default class ShowDataLayer {
drawLines?: true | boolean
}
) {
console.trace("Creating a data layer for", options.layer.id)
this._options = options
this.onDestroy.push(map.addCallbackAndRunD((map) => this.initDrawFeatures(map)))
}
@ -397,7 +396,8 @@ export default class ShowDataLayer {
const clustering = new ClusteringFeatureSource(feats, state.mapProperties.zoom.map(z => z + 2),
options.layer.id,
{
cutoff: 5
cutoff: 2,
showSummaryAt: "tilecenter"
})
new ShowDataLayer(mlmap, {
features: clustering.summaryPoints,