forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			121 lines
		
	
	
		
			No EOL
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			No EOL
		
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
 | |
| import FeaturePipeline from "../FeatureSource/FeaturePipeline";
 | |
| import {Tiles} from "../../Models/TileRange";
 | |
| import ShowDataLayer from "../../UI/ShowDataLayer/ShowDataLayer";
 | |
| import {TileHierarchyAggregator} from "../../UI/ShowDataLayer/TileHierarchyAggregator";
 | |
| import ShowTileInfo from "../../UI/ShowDataLayer/ShowTileInfo";
 | |
| import {UIEventSource} from "../UIEventSource";
 | |
| import MapState from "./MapState";
 | |
| import SelectedFeatureHandler from "../Actors/SelectedFeatureHandler";
 | |
| import Hash from "../Web/Hash";
 | |
| 
 | |
| export default class FeaturePipelineState extends MapState {
 | |
| 
 | |
|     /**
 | |
|      * The piece of code which fetches data from various sources and shows it on the background map
 | |
|      */
 | |
|     public readonly featurePipeline: FeaturePipeline;
 | |
|     private readonly featureAggregator: TileHierarchyAggregator;
 | |
| 
 | |
|     constructor(layoutToUse: LayoutConfig) {
 | |
|         super(layoutToUse);
 | |
| 
 | |
|         const clustering = layoutToUse.clustering
 | |
|         this.featureAggregator = TileHierarchyAggregator.createHierarchy(this);
 | |
|         const clusterCounter = this.featureAggregator
 | |
|         const self = this;
 | |
|         this.featurePipeline = new FeaturePipeline(
 | |
|             source => {
 | |
| 
 | |
|                 clusterCounter.addTile(source)
 | |
| 
 | |
|                 // Do show features indicates if the 'showDataLayer' should be shown
 | |
|                 const doShowFeatures = source.features.map(
 | |
|                     f => {
 | |
|                         const z = self.locationControl.data.zoom
 | |
| 
 | |
|                         if (!source.layer.isDisplayed.data) {
 | |
|                             return false;
 | |
|                         }
 | |
| 
 | |
|                         const bounds = self.currentBounds.data
 | |
|                         if (bounds === undefined) {
 | |
|                             // Map is not yet displayed
 | |
|                             return false;
 | |
|                         }
 | |
| 
 | |
|                         if (!source.bbox.overlapsWith(bounds)) {
 | |
|                             // Not within range -> features are hidden
 | |
|                             return false
 | |
|                         }
 | |
| 
 | |
| 
 | |
|                         if (z < source.layer.layerDef.minzoom) {
 | |
|                             // Layer is always hidden for this zoom level
 | |
|                             return false;
 | |
|                         }
 | |
| 
 | |
|                         if (z > clustering.maxZoom) {
 | |
|                             return true
 | |
|                         }
 | |
| 
 | |
|                         if (f.length > clustering.minNeededElements) {
 | |
|                             // This tile alone already has too much features
 | |
|                             return false
 | |
|                         }
 | |
| 
 | |
|                         let [tileZ, tileX, tileY] = Tiles.tile_from_index(source.tileIndex);
 | |
|                         if (tileZ >= z) {
 | |
| 
 | |
|                             while (tileZ > z) {
 | |
|                                 tileZ--
 | |
|                                 tileX = Math.floor(tileX / 2)
 | |
|                                 tileY = Math.floor(tileY / 2)
 | |
|                             }
 | |
| 
 | |
|                             if (clusterCounter.getTile(Tiles.tile_index(tileZ, tileX, tileY))?.totalValue > clustering.minNeededElements) {
 | |
|                                 // To much elements
 | |
|                                 return false
 | |
|                             }
 | |
|                         }
 | |
| 
 | |
| 
 | |
|                         return true
 | |
|                     }, [this.currentBounds, source.layer.isDisplayed]
 | |
|                 )
 | |
| 
 | |
|                 new ShowDataLayer(
 | |
|                     {
 | |
|                         features: source,
 | |
|                         leafletMap: self.leafletMap,
 | |
|                         layerToShow: source.layer.layerDef,
 | |
|                         doShowLayer: doShowFeatures,
 | |
|                         allElements: self.allElements,
 | |
|                         selectedElement: self.selectedElement
 | |
|                     }
 | |
|                 );
 | |
|             }, this
 | |
|         );
 | |
|         new SelectedFeatureHandler(Hash.hash, this)
 | |
|         
 | |
|         this.AddClusteringToMap(this.leafletMap)
 | |
| 
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Adds the cluster-tiles to the given map
 | |
|      * @param leafletMap: a UIEventSource possible having a leaflet map
 | |
|      * @constructor
 | |
|      */
 | |
|     public AddClusteringToMap(leafletMap: UIEventSource<any>) {
 | |
|         const clustering = this.layoutToUse.clustering
 | |
|         new ShowDataLayer({
 | |
|             features: this.featureAggregator.getCountsForZoom(clustering, this.locationControl, clustering.minNeededElements),
 | |
|             leafletMap: leafletMap,
 | |
|             layerToShow: ShowTileInfo.styling,
 | |
|             enablePopups: this.featureSwitchIsDebugging.data,
 | |
|         })
 | |
|     }
 | |
| 
 | |
| 
 | |
| } |