forked from MapComplete/MapComplete
		
	Feature: second iteration of clustering
This commit is contained in:
		
							parent
							
								
									8360ab9a8b
								
							
						
					
					
						commit
						5bc8f11d24
					
				
					 3 changed files with 25 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -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++
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue