forked from MapComplete/MapComplete
		
	First fully working version
This commit is contained in:
		
							parent
							
								
									995f48b97a
								
							
						
					
					
						commit
						1fa66e50f8
					
				
					 8 changed files with 73 additions and 88 deletions
				
			
		| 
						 | 
					@ -47,6 +47,10 @@ HP ProLiant DL360 G7 (1U): 2Rx4 DDR3-memory (PC3)
 | 
				
			||||||
    Intel Xeon X56**
 | 
					    Intel Xeon X56**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Updating data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					`osm2pgsql-replication update -d postgresql://user:password@localhost:5444/osm-poi -- -O flex -S build_db.lua -s --flat-nodes=import-help-file`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Deploying a tile server
 | 
					## Deploying a tile server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,11 +15,12 @@
 | 
				
			||||||
        "point",
 | 
					        "point",
 | 
				
			||||||
        "centroid"
 | 
					        "centroid"
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "iconSize": "25,25",
 | 
					      "iconSize": "40,40",
 | 
				
			||||||
      "label": {
 | 
					      "label": {
 | 
				
			||||||
        "render": "{total}"
 | 
					        "render": "{total}"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "labelCssClasses": "bg-white w-6 h-6 text-lg rounded-full"
 | 
					      "labelCss": "background: #ffffffbb",
 | 
				
			||||||
 | 
					      "labelCssClasses": "w-12 text-lg rounded-xl p-1 px-2"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@
 | 
				
			||||||
      "oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg",
 | 
					      "oauth_secret": "NBWGhWDrD3QDB35xtVuxv4aExnmIt4FA_WgeLtwxasg",
 | 
				
			||||||
      "url": "https://www.openstreetmap.org"
 | 
					      "url": "https://www.openstreetmap.org"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "mvt_layer_server": "http://cache.mapcomplete.org/mvt/public.{type}_{layer}/{z}/{x}/{y}.pbf",
 | 
					    "mvt_layer_server": "https://cache.mapcomplete.org/public.{type}_{layer}/{z}/{x}/{y}.pbf",
 | 
				
			||||||
    "disabled:oauth_credentials": {
 | 
					    "disabled:oauth_credentials": {
 | 
				
			||||||
      "##": "DEV",
 | 
					      "##": "DEV",
 | 
				
			||||||
      "#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/",
 | 
					      "#": "This client-id is registered by 'MapComplete' on https://master.apis.dev.openstreetmap.org/",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,12 +4,13 @@ import { BBox } from "../../BBox"
 | 
				
			||||||
import { FeatureSource } from "../FeatureSource"
 | 
					import { FeatureSource } from "../FeatureSource"
 | 
				
			||||||
import FeatureSourceMerger from "../Sources/FeatureSourceMerger"
 | 
					import FeatureSourceMerger from "../Sources/FeatureSourceMerger"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/***
 | 
					/***
 | 
				
			||||||
 * A tiled source which dynamically loads the required tiles at a fixed zoom level.
 | 
					 * A tiled source which dynamically loads the required tiles at a fixed zoom level.
 | 
				
			||||||
 * A single featureSource will be initialized for every tile in view; which will later be merged into this featureSource
 | 
					 * A single featureSource will be initialized for every tile in view; which will later be merged into this featureSource
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export default class DynamicTileSource<Src extends FeatureSource = FeatureSource> extends FeatureSourceMerger<Src> {
 | 
					export default class DynamicTileSource<
 | 
				
			||||||
 | 
					    Src extends FeatureSource = FeatureSource
 | 
				
			||||||
 | 
					> extends FeatureSourceMerger<Src> {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param zoomlevel If {z} is specified in the source, the 'zoomlevel' will be used as zoomlevel to download from
 | 
					     * @param zoomlevel If {z} is specified in the source, the 'zoomlevel' will be used as zoomlevel to download from
 | 
				
			||||||
| 
						 | 
					@ -28,10 +29,12 @@ export default class DynamicTileSource<Src extends FeatureSource = FeatureSource
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        options?: {
 | 
					        options?: {
 | 
				
			||||||
            isActive?: Store<boolean>
 | 
					            isActive?: Store<boolean>
 | 
				
			||||||
        },
 | 
					            zDiff?: number
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        super()
 | 
					        super()
 | 
				
			||||||
        const loadedTiles = new Set<number>()
 | 
					        const loadedTiles = new Set<number>()
 | 
				
			||||||
 | 
					        const zDiff = options?.zDiff ?? 0
 | 
				
			||||||
        const neededTiles: Store<number[]> = Stores.ListStabilized(
 | 
					        const neededTiles: Store<number[]> = Stores.ListStabilized(
 | 
				
			||||||
            mapProperties.bounds
 | 
					            mapProperties.bounds
 | 
				
			||||||
                .mapD(
 | 
					                .mapD(
 | 
				
			||||||
| 
						 | 
					@ -43,32 +46,32 @@ export default class DynamicTileSource<Src extends FeatureSource = FeatureSource
 | 
				
			||||||
                        if (mapProperties.zoom.data < minzoom) {
 | 
					                        if (mapProperties.zoom.data < minzoom) {
 | 
				
			||||||
                            return undefined
 | 
					                            return undefined
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        const z = Math.floor(zoomlevel.data)
 | 
					                        const z = Math.floor(zoomlevel.data) + zDiff
 | 
				
			||||||
                        const tileRange = Tiles.TileRangeBetween(
 | 
					                        const tileRange = Tiles.TileRangeBetween(
 | 
				
			||||||
                            z,
 | 
					                            z,
 | 
				
			||||||
                            bounds.getNorth(),
 | 
					                            bounds.getNorth(),
 | 
				
			||||||
                            bounds.getEast(),
 | 
					                            bounds.getEast(),
 | 
				
			||||||
                            bounds.getSouth(),
 | 
					                            bounds.getSouth(),
 | 
				
			||||||
                            bounds.getWest(),
 | 
					                            bounds.getWest()
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        if (tileRange.total > 500) {
 | 
					                        if (tileRange.total > 500) {
 | 
				
			||||||
                            console.warn(
 | 
					                            console.warn(
 | 
				
			||||||
                                "Got a really big tilerange, bounds and location might be out of sync",
 | 
					                                "Got a really big tilerange, bounds and location might be out of sync"
 | 
				
			||||||
                            )
 | 
					                            )
 | 
				
			||||||
                            return undefined
 | 
					                            return undefined
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        const needed = Tiles.MapRange(tileRange, (x, y) =>
 | 
					                        const needed = Tiles.MapRange(tileRange, (x, y) =>
 | 
				
			||||||
                            Tiles.tile_index(z, x, y),
 | 
					                            Tiles.tile_index(z, x, y)
 | 
				
			||||||
                        ).filter((i) => !loadedTiles.has(i))
 | 
					                        ).filter((i) => !loadedTiles.has(i))
 | 
				
			||||||
                        if (needed.length === 0) {
 | 
					                        if (needed.length === 0) {
 | 
				
			||||||
                            return undefined
 | 
					                            return undefined
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        return needed
 | 
					                        return needed
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    [options?.isActive, mapProperties.zoom],
 | 
					                    [options?.isActive, mapProperties.zoom]
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
                .stabilized(250),
 | 
					                .stabilized(250)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        neededTiles.addCallbackAndRunD((neededIndexes) => {
 | 
					        neededTiles.addCallbackAndRunD((neededIndexes) => {
 | 
				
			||||||
| 
						 | 
					@ -79,5 +82,3 @@ export default class DynamicTileSource<Src extends FeatureSource = FeatureSource
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,12 +24,13 @@ export class SummaryTileSource extends DynamicTileSource {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        const layersSummed = layers.join("+")
 | 
					        const layersSummed = layers.join("+")
 | 
				
			||||||
 | 
					        const zDiff = 2
 | 
				
			||||||
        super(
 | 
					        super(
 | 
				
			||||||
            zoomRounded,
 | 
					            zoomRounded,
 | 
				
			||||||
            0, // minzoom
 | 
					            0, // minzoom
 | 
				
			||||||
            (tileIndex) => {
 | 
					            (tileIndex) => {
 | 
				
			||||||
                const [z, x, y] = Tiles.tile_from_index(tileIndex)
 | 
					                const [z, x, y] = Tiles.tile_from_index(tileIndex)
 | 
				
			||||||
                const coordinates = Tiles.centerPointOf(z, x, y)
 | 
					                let coordinates = Tiles.centerPointOf(z, x, y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const count = UIEventSource.FromPromiseWithErr(
 | 
					                const count = UIEventSource.FromPromiseWithErr(
 | 
				
			||||||
                    Utils.downloadJson(`${cacheserver}/${layersSummed}/${z}/${x}/${y}.json`)
 | 
					                    Utils.downloadJson(`${cacheserver}/${layersSummed}/${z}/${x}/${y}.json`)
 | 
				
			||||||
| 
						 | 
					@ -50,6 +51,21 @@ export class SummaryTileSource extends DynamicTileSource {
 | 
				
			||||||
                    if (counts === undefined || counts["total"] === 0) {
 | 
					                    if (counts === undefined || counts["total"] === 0) {
 | 
				
			||||||
                        return SummaryTileSource.empty
 | 
					                        return SummaryTileSource.empty
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    const lat = counts["lat"]
 | 
				
			||||||
 | 
					                    const lon = counts["lon"]
 | 
				
			||||||
 | 
					                    const total = Utils.numberWithMetrixPrefix(Number(counts["total"]))
 | 
				
			||||||
 | 
					                    const tileBbox = new BBox(Tiles.tile_bounds_lon_lat(z, x, y))
 | 
				
			||||||
 | 
					                    if (!tileBbox.contains([lon, lat])) {
 | 
				
			||||||
 | 
					                        console.error(
 | 
				
			||||||
 | 
					                            "Average coordinate is outside of bbox!?",
 | 
				
			||||||
 | 
					                            lon,
 | 
				
			||||||
 | 
					                            lat,
 | 
				
			||||||
 | 
					                            tileBbox,
 | 
				
			||||||
 | 
					                            counts
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        coordinates = [lon, lat]
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    return [
 | 
					                    return [
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            type: "Feature",
 | 
					                            type: "Feature",
 | 
				
			||||||
| 
						 | 
					@ -57,6 +73,7 @@ export class SummaryTileSource extends DynamicTileSource {
 | 
				
			||||||
                                id: "summary_" + tileIndex,
 | 
					                                id: "summary_" + tileIndex,
 | 
				
			||||||
                                summary: "yes",
 | 
					                                summary: "yes",
 | 
				
			||||||
                                ...counts,
 | 
					                                ...counts,
 | 
				
			||||||
 | 
					                                total,
 | 
				
			||||||
                                layers: layersSummed,
 | 
					                                layers: layersSummed,
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                            geometry: {
 | 
					                            geometry: {
 | 
				
			||||||
| 
						 | 
					@ -69,7 +86,8 @@ export class SummaryTileSource extends DynamicTileSource {
 | 
				
			||||||
                return new StaticFeatureSource(
 | 
					                return new StaticFeatureSource(
 | 
				
			||||||
                    features.map(
 | 
					                    features.map(
 | 
				
			||||||
                        (f) => {
 | 
					                        (f) => {
 | 
				
			||||||
                            if (z !== zoomRounded.data) {
 | 
					                            console.log("z, zdiff, rounded:", z, zDiff, zoomRounded.data)
 | 
				
			||||||
 | 
					                            if (z - zDiff !== zoomRounded.data) {
 | 
				
			||||||
                                return SummaryTileSource.empty
 | 
					                                return SummaryTileSource.empty
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            return f
 | 
					                            return f
 | 
				
			||||||
| 
						 | 
					@ -79,7 +97,7 @@ export class SummaryTileSource extends DynamicTileSource {
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            mapProperties,
 | 
					            mapProperties,
 | 
				
			||||||
            options
 | 
					            { ...options, zDiff }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -145,7 +145,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false)
 | 
					    public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(layout: LayoutConfig) {
 | 
					    constructor(layout: LayoutConfig, mvtAvailableLayers: Set<string>) {
 | 
				
			||||||
        Utils.initDomPurify()
 | 
					        Utils.initDomPurify()
 | 
				
			||||||
        this.layout = layout
 | 
					        this.layout = layout
 | 
				
			||||||
        this.featureSwitches = new FeatureSwitchState(layout)
 | 
					        this.featureSwitches = new FeatureSwitchState(layout)
 | 
				
			||||||
| 
						 | 
					@ -240,6 +240,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
 | 
				
			||||||
                this.mapProperties,
 | 
					                this.mapProperties,
 | 
				
			||||||
                this.osmConnection.Backend(),
 | 
					                this.osmConnection.Backend(),
 | 
				
			||||||
                (id) => self.layerState.filteredLayers.get(id).isDisplayed,
 | 
					                (id) => self.layerState.filteredLayers.get(id).isDisplayed,
 | 
				
			||||||
 | 
					                mvtAvailableLayers,
 | 
				
			||||||
                this.fullNodeDatabase
 | 
					                this.fullNodeDatabase
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -662,10 +663,11 @@ export default class ThemeViewState implements SpecialVisualizationState {
 | 
				
			||||||
                Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
 | 
					                Constants.priviliged_layers.indexOf(<any>l.id) < 0 &&
 | 
				
			||||||
                l.source.geojsonSource === undefined
 | 
					                l.source.geojsonSource === undefined
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					        const url = new URL(Constants.VectorTileServer)
 | 
				
			||||||
        return new SummaryTileSource(
 | 
					        return new SummaryTileSource(
 | 
				
			||||||
            "http://127.0.0.1:2345",
 | 
					            url.protocol + "//" + url.host + "/summary",
 | 
				
			||||||
            layers.map((l) => l.id),
 | 
					            layers.map((l) => l.id),
 | 
				
			||||||
            this.mapProperties.zoom.map((z) => Math.max(Math.ceil(z) + 1, 0)),
 | 
					            this.mapProperties.zoom.map((z) => Math.max(Math.ceil(z), 0)),
 | 
				
			||||||
            this.mapProperties
 | 
					            this.mapProperties
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										78
									
								
								src/Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										78
									
								
								src/Utils.ts
									
										
									
									
									
								
							| 
						 | 
					@ -1128,42 +1128,6 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
 | 
				
			||||||
        element.click()
 | 
					        element.click()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static ColourNameToHex(color: string): string {
 | 
					 | 
				
			||||||
        return colors[color.toLowerCase()] ?? color
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static HexToColourName(hex: string): string {
 | 
					 | 
				
			||||||
        hex = hex.toLowerCase()
 | 
					 | 
				
			||||||
        if (!hex.startsWith("#")) {
 | 
					 | 
				
			||||||
            return hex
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const c = Utils.color(hex)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let smallestDiff = Number.MAX_VALUE
 | 
					 | 
				
			||||||
        let bestColor = undefined
 | 
					 | 
				
			||||||
        for (const color in colors) {
 | 
					 | 
				
			||||||
            if (!colors.hasOwnProperty(color)) {
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const foundhex = colors[color]
 | 
					 | 
				
			||||||
            if (typeof foundhex !== "string") {
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (foundhex === hex) {
 | 
					 | 
				
			||||||
                return color
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const diff = this.colorDiff(Utils.color(foundhex), c)
 | 
					 | 
				
			||||||
            if (diff > 50) {
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (diff < smallestDiff) {
 | 
					 | 
				
			||||||
                smallestDiff = diff
 | 
					 | 
				
			||||||
                bestColor = color
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return bestColor ?? hex
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Reorders an object: creates a new object where the keys have been added alphabetically
 | 
					     * Reorders an object: creates a new object where the keys have been added alphabetically
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
| 
						 | 
					@ -1204,33 +1168,6 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
 | 
				
			||||||
        return hours + ":" + Utils.TwoDigits(minutes) + ":" + Utils.TwoDigits(seconds)
 | 
					        return hours + ":" + Utils.TwoDigits(minutes) + ":" + Utils.TwoDigits(seconds)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static DisableLongPresses() {
 | 
					 | 
				
			||||||
        // Remove all context event listeners on mobile to prevent long presses
 | 
					 | 
				
			||||||
        window.addEventListener(
 | 
					 | 
				
			||||||
            "contextmenu",
 | 
					 | 
				
			||||||
            (e) => {
 | 
					 | 
				
			||||||
                // Not compatible with IE < 9
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (e.target["nodeName"] === "INPUT") {
 | 
					 | 
				
			||||||
                    return
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                e.preventDefault()
 | 
					 | 
				
			||||||
                return false
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static preventDefaultOnMouseEvent(event: any) {
 | 
					 | 
				
			||||||
        event?.originalEvent?.preventDefault()
 | 
					 | 
				
			||||||
        event?.originalEvent?.stopPropagation()
 | 
					 | 
				
			||||||
        event?.originalEvent?.stopImmediatePropagation()
 | 
					 | 
				
			||||||
        if (event?.originalEvent) {
 | 
					 | 
				
			||||||
            // This is a total workaround, as 'preventDefault' and everything above seems to be not working
 | 
					 | 
				
			||||||
            event.originalEvent["dismissed"] = true
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static HomepageLink(): string {
 | 
					    public static HomepageLink(): string {
 | 
				
			||||||
        if (typeof window === "undefined") {
 | 
					        if (typeof window === "undefined") {
 | 
				
			||||||
            return "https://mapcomplete.org"
 | 
					            return "https://mapcomplete.org"
 | 
				
			||||||
| 
						 | 
					@ -1711,4 +1648,19 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
        return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b)
 | 
					        return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static readonly _metrixPrefixes = ["", "k", "M", "G", "T", "P", "E"]
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Converts a big number (e.g. 1000000) into a rounded postfixed verion (e.g. 1M)
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * Supported metric prefixes are: [k, M, G, T, P, E]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public static numberWithMetrixPrefix(n: number) {
 | 
				
			||||||
 | 
					        let index = 0
 | 
				
			||||||
 | 
					        while (n > 1000) {
 | 
				
			||||||
 | 
					            n = Math.round(n / 1000)
 | 
				
			||||||
 | 
					            index++
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return n + Utils._metrixPrefixes[index]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										15
									
								
								src/index.ts
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/index.ts
									
										
									
									
									
								
							| 
						 | 
					@ -20,9 +20,15 @@ function webgl_support() {
 | 
				
			||||||
        return false
 | 
					        return false
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
async function availableLayers(): Promise<Set<string>> {
 | 
					async function getAvailableLayers(): Promise<Set<string>> {
 | 
				
			||||||
    const status = await Utils.downloadJson(Constants.VectorTileServer + "/status.json")
 | 
					    try {
 | 
				
			||||||
 | 
					        const host = new URL(Constants.VectorTileServer).host
 | 
				
			||||||
 | 
					        const status = await Utils.downloadJson("https://" + host + "/summary/status.json")
 | 
				
			||||||
        return new Set<string>(status.layers)
 | 
					        return new Set<string>(status.layers)
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					        console.error("Could not get MVT available layers due to", e)
 | 
				
			||||||
 | 
					        return new Set<string>()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
async function main() {
 | 
					async function main() {
 | 
				
			||||||
    // @ts-ignore
 | 
					    // @ts-ignore
 | 
				
			||||||
| 
						 | 
					@ -32,9 +38,10 @@ async function main() {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const [layout, availableLayers] = await Promise.all([
 | 
					        const [layout, availableLayers] = await Promise.all([
 | 
				
			||||||
            DetermineLayout.GetLayout(),
 | 
					            DetermineLayout.GetLayout(),
 | 
				
			||||||
            await availableLayers(),
 | 
					            await getAvailableLayers(),
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
        const state = new ThemeViewState(layout)
 | 
					        console.log("The available layers on server are", Array.from(availableLayers))
 | 
				
			||||||
 | 
					        const state = new ThemeViewState(layout, availableLayers)
 | 
				
			||||||
        const main = new SvelteUIElement(ThemeViewGUI, { state })
 | 
					        const main = new SvelteUIElement(ThemeViewGUI, { state })
 | 
				
			||||||
        main.AttachTo("maindiv")
 | 
					        main.AttachTo("maindiv")
 | 
				
			||||||
    } catch (err) {
 | 
					    } catch (err) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue