2020-09-25 21:58:29 +02:00
import * as editorlayerindex from "../assets/editor-layer-index.json"
import { UIEventSource } from "./UIEventSource" ;
import { GeoOperations } from "./GeoOperations" ;
import { State } from "../State" ;
import { Basemap } from "./Leaflet/Basemap" ;
2020-09-27 01:38:51 +02:00
import { QueryParameters } from "./Web/QueryParameters" ;
2020-09-27 22:48:43 +02:00
import { BaseLayer } from "./BaseLayer" ;
2020-09-25 21:58:29 +02:00
/ * *
* Calculates which layers are available at the current location
* /
export default class AvailableBaseLayers {
2020-09-27 22:48:43 +02:00
2020-09-25 23:00:20 +02:00
2020-09-27 22:48:43 +02:00
public static layerOverview = AvailableBaseLayers . LoadRasterIndex ( ) //.concat(AvailableBaseLayers.LoadStamenIndex());
2020-09-27 01:38:51 +02:00
public availableEditorLayers : UIEventSource < BaseLayer [ ] > ;
2020-09-25 21:58:29 +02:00
constructor ( state : State ) {
const self = this ;
this . availableEditorLayers =
state . locationControl . map (
( currentLocation ) = > {
const currentLayers = self . availableEditorLayers ? . data ;
const newLayers = AvailableBaseLayers . AvailableLayersAt ( currentLocation ? . lon , currentLocation ? . lat ) ;
if ( currentLayers === undefined ) {
return newLayers ;
}
if ( newLayers . length !== currentLayers . length ) {
return newLayers ;
}
for ( let i = 0 ; i < newLayers . length ; i ++ ) {
if ( newLayers [ i ] . name !== currentLayers [ i ] . name ) {
return newLayers ;
}
}
2020-09-27 01:38:51 +02:00
return currentLayers ;
2020-09-25 21:58:29 +02:00
} ) ;
2020-09-27 01:38:51 +02:00
this . availableEditorLayers . addCallbackAndRun ( availableLayers = > {
const layerControl = ( state . bm as Basemap ) . CurrentLayer ;
const currentLayer = layerControl . data . id ;
for ( const availableLayer of availableLayers ) {
if ( availableLayer . id === currentLayer ) {
if ( availableLayer . max_zoom < state . locationControl . data . zoom ) {
break ;
}
if ( availableLayer . min_zoom > state . locationControl . data . zoom ) {
break ;
}
return ; // All good!
}
}
// Oops, we panned out of range for this layer!
console . log ( "AvailableBaseLayers-actor: detected that the current bounds aren't sufficient anymore - reverting to OSM standard" )
2020-09-27 22:48:43 +02:00
layerControl . setData ( Basemap . osmCarto ) ;
2020-09-27 01:38:51 +02:00
} ) ;
const queryParam = QueryParameters . GetQueryParameter ( "background" , State . state . layoutToUse . data . defaultBackground ) ;
2020-09-27 22:48:43 +02:00
queryParam . addCallbackAndRun ( ( selectedId :string ) = > {
2020-09-27 01:38:51 +02:00
console . log ( "Selected layer is " , selectedId )
const available = self . availableEditorLayers . data ;
for ( const layer of available ) {
if ( layer . id === selectedId ) {
2020-09-27 22:48:43 +02:00
state . bm . CurrentLayer . setData ( layer ) ;
2020-09-27 01:38:51 +02:00
}
}
} )
state . bm . CurrentLayer . addCallbackAndRun ( currentLayer = > {
queryParam . setData ( currentLayer . id ) ;
} ) ;
2020-09-25 21:58:29 +02:00
}
2020-09-27 01:38:51 +02:00
public static AvailableLayersAt ( lon : number , lat : number ) : BaseLayer [ ] {
2020-09-27 22:48:43 +02:00
const availableLayers = [ Basemap . osmCarto ]
2020-09-25 21:58:29 +02:00
const globalLayers = [ ] ;
for ( const i in AvailableBaseLayers . layerOverview ) {
const layer = AvailableBaseLayers . layerOverview [ i ] ;
if ( layer . feature . geometry === null ) {
globalLayers . push ( layer ) ;
continue ;
}
if ( lon === undefined || lat === undefined ) {
continue ;
}
if ( GeoOperations . inside ( [ lon , lat ] , layer . feature ) ) {
availableLayers . push ( layer ) ;
}
}
return availableLayers . concat ( globalLayers ) ;
}
2020-09-27 01:38:51 +02:00
private static LoadRasterIndex ( ) : BaseLayer [ ] {
const layers : BaseLayer [ ] = [ ]
2020-09-25 21:58:29 +02:00
// @ts-ignore
const features = editorlayerindex . features ;
for ( const i in features ) {
const layer = features [ i ] ;
const props = layer . properties ;
2020-09-27 01:38:51 +02:00
if ( props . id === "Bing" ) {
2020-09-25 21:58:29 +02:00
// Doesnt work
continue ;
}
2020-09-27 01:38:51 +02:00
2020-09-27 18:45:37 +02:00
if ( props . id === "MAPNIK" ) {
2020-09-27 01:38:51 +02:00
// Already added by default
2020-09-25 21:58:29 +02:00
continue ;
}
2020-09-27 01:38:51 +02:00
if ( props . overlay ) {
2020-09-25 21:58:29 +02:00
continue ;
}
if ( props . url . toLowerCase ( ) . indexOf ( "apikey" ) > 0 ) {
continue ;
}
2020-09-27 18:45:37 +02:00
if ( props . max_zoom < 19 ) {
// We want users to zoom to level 19 when adding a point
// If they are on a layer which hasn't enough precision, they can not zoom far enough. This is confusing, so we don't use this layer
2020-09-25 21:58:29 +02:00
continue ;
}
2020-09-27 18:45:37 +02:00
2020-09-25 23:00:20 +02:00
if ( props . name === undefined ) {
2020-09-27 01:38:51 +02:00
console . warn ( "Editor layer index: name not defined on " , props )
2020-09-25 23:00:20 +02:00
continue
}
2020-09-25 21:58:29 +02:00
const leafletLayer = Basemap . CreateBackgroundLayer (
props . id ,
props . name ,
props . url ,
props . name ,
2020-09-27 18:45:37 +02:00
props . license_url ,
2020-09-25 21:58:29 +02:00
props . max_zoom ,
props . type . toLowerCase ( ) === "wms" ,
props . type . toLowerCase ( ) === "wmts"
)
// Note: if layer.geometry is null, there is global coverage for this layer
layers . push ( {
id : props.id ,
2020-09-27 01:38:51 +02:00
max_zoom : props.max_zoom ? ? 25 ,
min_zoom : props.min_zoom ? ? 1 ,
attribution_url : props.license_url ,
2020-09-25 21:58:29 +02:00
name : props.name ,
2020-09-27 01:38:51 +02:00
layer : leafletLayer ,
feature : layer
2020-09-25 21:58:29 +02:00
} ) ;
}
return layers ;
2020-09-27 22:48:43 +02:00
}
private static LoadStamenIndex ( ) : BaseLayer [ ] {
return [
{
attribution : "Map tiles by <a href=\"http://stamen.com\">Stamen Design</a>, under <a href=\"http://creativecommons.org/licenses/by/3.0\">CC BY 3.0</a>. Data by <a href=\"http://openstreetmap.org\">OpenStreetMap</a>, under <a href=\"http://www.openstreetmap.org/copyright\">ODbL</a>." ,
attribution_url : undefined , // already in the attribution string
feature : null ,
id : "toner" ,
layer :Basemap.ProvidedLayer ( "toner" ) ,
max_zoom : 20 ,
min_zoom :1 ,
name : "Toner"
}
]
2020-09-25 21:58:29 +02:00
}
}