forked from MapComplete/MapComplete
		
	Update of latlon2country and use its async interface; small refactoring of simplemetagging, improvements to cacheBuilder which respects isShown and calculated tags now
This commit is contained in:
		
							parent
							
								
									e053e9f279
								
							
						
					
					
						commit
						9cfb7fbe68
					
				
					 14 changed files with 417 additions and 4320 deletions
				
			
		
							
								
								
									
										3
									
								
								.vscode/settings.json
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
										
									
									
										vendored
									
									
								
							|  | @ -1,3 +0,0 @@ | ||||||
| { |  | ||||||
|   "files.eol": "\n" |  | ||||||
| } |  | ||||||
|  | @ -68,7 +68,7 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | ||||||
|         const features: { feature: any; freshness: Date }[] = this.upstream.features.data; |         const features: { feature: any; freshness: Date }[] = this.upstream.features.data; | ||||||
|         const newFeatures = features.filter((f) => { |         const newFeatures = features.filter((f) => { | ||||||
| 
 | 
 | ||||||
|             self.registerCallback(f.feature, layer.layerDef) |             self.registerCallback(f.feature) | ||||||
| 
 | 
 | ||||||
|             if ( |             if ( | ||||||
|                 this.state.selectedElement.data?.id === f.feature.id || |                 this.state.selectedElement.data?.id === f.feature.id || | ||||||
|  | @ -105,15 +105,18 @@ export default class FilteringFeatureSource implements FeatureSourceForLayer, Ti | ||||||
|         this._is_dirty.setData(false) |         this._is_dirty.setData(false) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private registerCallback(feature: any, layer: LayerConfig) { |     private registerCallback(feature: any) { | ||||||
|         const src = this.state.allElements.addOrGetElement(feature) |         const src = this.state?.allElements?.addOrGetElement(feature) | ||||||
|  |         if(src == undefined){ | ||||||
|  |             return | ||||||
|  |         } | ||||||
|         if (this._alreadyRegistered.has(src)) { |         if (this._alreadyRegistered.has(src)) { | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|         this._alreadyRegistered.add(src) |         this._alreadyRegistered.add(src) | ||||||
| 
 | 
 | ||||||
|             const self = this; |             const self = this; | ||||||
|             src.addCallbackAndRunD(isShown => { |             src.addCallbackAndRunD(_ => { | ||||||
|                 self._is_dirty.setData(true) |                 self._is_dirty.setData(true) | ||||||
|             }) |             }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -86,6 +86,10 @@ export default class TiledFeatureSource implements Tiled, IndexedFeatureSource, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static createHierarchy(features: FeatureSource, options?: TiledFeatureSourceOptions): TiledFeatureSource { |     public static createHierarchy(features: FeatureSource, options?: TiledFeatureSourceOptions): TiledFeatureSource { | ||||||
|  |         options = { | ||||||
|  |             ...options, | ||||||
|  |             layer: features["layer"] ?? options.layer | ||||||
|  |         } | ||||||
|         const root = new TiledFeatureSource(0, 0, 0, null, options) |         const root = new TiledFeatureSource(0, 0, 0, null, options) | ||||||
|         features.features?.addCallbackAndRunD(feats => root.addFeatures(feats)) |         features.features?.addCallbackAndRunD(feats => root.addFeatures(feats)) | ||||||
|         return root; |         return root; | ||||||
|  | @ -200,6 +204,6 @@ export interface TiledFeatureSourceOptions { | ||||||
|      * Setting 'dontEnforceMinZoomLevel' will still allow bigger zoom levels for those features |      * Setting 'dontEnforceMinZoomLevel' will still allow bigger zoom levels for those features | ||||||
|      */ |      */ | ||||||
|     readonly dontEnforceMinZoom?: boolean, |     readonly dontEnforceMinZoom?: boolean, | ||||||
|     readonly registerTile?: (tile: TiledFeatureSource & Tiled) => void, |     readonly registerTile?: (tile: TiledFeatureSource & FeatureSourceForLayer & Tiled) => void, | ||||||
|     readonly layer?: FilteredLayer |     readonly layer?: FilteredLayer | ||||||
| } | } | ||||||
|  | @ -25,8 +25,7 @@ export class GeoOperations { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static centerpointCoordinates(feature: any): [number, number] { |     static centerpointCoordinates(feature: any): [number, number] { | ||||||
|         // @ts-ignore
 |         return <[number, number]> turf.center(feature).geometry.coordinates; | ||||||
|         return turf.center(feature).geometry.coordinates; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -35,7 +34,7 @@ export class GeoOperations { | ||||||
|      * @param lonlat1 |      * @param lonlat1 | ||||||
|      */ |      */ | ||||||
|     static distanceBetween(lonlat0: [number, number], lonlat1: [number, number]) { |     static distanceBetween(lonlat0: [number, number], lonlat1: [number, number]) { | ||||||
|         return turf.distance(lonlat0, lonlat1) * 1000 |         return turf.distance(lonlat0, lonlat1, {units: "meters"}) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | @ -196,8 +195,8 @@ export class GeoOperations { | ||||||
| 
 | 
 | ||||||
|     static buffer(feature: any, bufferSizeInMeter: number) { |     static buffer(feature: any, bufferSizeInMeter: number) { | ||||||
|         return turf.buffer(feature, bufferSizeInMeter / 1000, { |         return turf.buffer(feature, bufferSizeInMeter / 1000, { | ||||||
|             units: 'kilometers' |             units:'kilometers' | ||||||
|         }) |         } ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static bbox(feature: any) { |     static bbox(feature: any) { | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| import SimpleMetaTagger from "./SimpleMetaTagger"; | import SimpleMetaTaggers from "./SimpleMetaTagger"; | ||||||
| import {ExtraFuncParams, ExtraFunctions} from "./ExtraFunctions"; | import {ExtraFuncParams, ExtraFunctions} from "./ExtraFunctions"; | ||||||
| import LayerConfig from "../Models/ThemeConfig/LayerConfig"; | import LayerConfig from "../Models/ThemeConfig/LayerConfig"; | ||||||
| import State from "../State"; | import State from "../State"; | ||||||
|  | @ -33,9 +33,8 @@ export default class MetaTagging { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 |         const metatagsToApply: SimpleMetaTaggers[] = [] | ||||||
|         const metatagsToApply: SimpleMetaTagger [] = [] |         for (const metatag of SimpleMetaTaggers.metatags) { | ||||||
|         for (const metatag of SimpleMetaTagger.metatags) { |  | ||||||
|             if (metatag.includesDates) { |             if (metatag.includesDates) { | ||||||
|                 if (options.includeDates ?? true) { |                 if (options.includeDates ?? true) { | ||||||
|                     metatagsToApply.push(metatag) |                     metatagsToApply.push(metatag) | ||||||
|  | @ -59,19 +58,23 @@ export default class MetaTagging { | ||||||
|             let somethingChanged = false |             let somethingChanged = false | ||||||
|             for (const metatag of metatagsToApply) { |             for (const metatag of metatagsToApply) { | ||||||
|                 try { |                 try { | ||||||
|  |                     // @ts-ignore
 | ||||||
|                     if (!metatag.keys.some(key => feature.properties[key] === undefined)) { |                     if (!metatag.keys.some(key => feature.properties[key] === undefined)) { | ||||||
|                         // All keys are already defined, we probably already ran this one
 |                         // All keys are already defined, we probably already ran this one
 | ||||||
|                         continue |                         continue | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|  |                     // @ts-ignore
 | ||||||
|                     if (metatag.isLazy) { |                     if (metatag.isLazy) { | ||||||
|                         somethingChanged = true; |                         somethingChanged = true; | ||||||
| 
 | 
 | ||||||
|  |                         // @ts-ignore
 | ||||||
|                         metatag.applyMetaTagsOnFeature(feature, freshness, layer) |                         metatag.applyMetaTagsOnFeature(feature, freshness, layer) | ||||||
|                          |                          | ||||||
|                     } else { |                     } else { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |                         // @ts-ignore
 | ||||||
|                         const newValueAdded = metatag.applyMetaTagsOnFeature(feature, freshness, layer) |                         const newValueAdded = metatag.applyMetaTagsOnFeature(feature, freshness, layer) | ||||||
|                         /* Note that the expression: |                         /* Note that the expression: | ||||||
|                         * `somethingChanged = newValueAdded || metatag.applyMetaTagsOnFeature(feature, freshness)` |                         * `somethingChanged = newValueAdded || metatag.applyMetaTagsOnFeature(feature, freshness)` | ||||||
|  | @ -83,6 +86,7 @@ export default class MetaTagging { | ||||||
|                         somethingChanged = newValueAdded || somethingChanged |                         somethingChanged = newValueAdded || somethingChanged | ||||||
|                     } |                     } | ||||||
|                 } catch (e) { |                 } catch (e) { | ||||||
|  |                     // @ts-ignore
 | ||||||
|                     console.error("Could not calculate metatag for ", metatag.keys.join(","), ":", e, e.stack) |                     console.error("Could not calculate metatag for ", metatag.keys.join(","), ":", e, e.stack) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  | @ -117,8 +121,9 @@ export default class MetaTagging { | ||||||
|             const func = new Function("feat", "return " + code + ";"); |             const func = new Function("feat", "return " + code + ";"); | ||||||
| 
 | 
 | ||||||
|             const f = (feature: any) => { |             const f = (feature: any) => { | ||||||
|                 delete feature.properties[key] |  | ||||||
|                  |                  | ||||||
|  |                  | ||||||
|  |                 delete feature.properties[key] | ||||||
|                 Object.defineProperty(feature.properties, key, { |                 Object.defineProperty(feature.properties, key, { | ||||||
|                     configurable: true, |                     configurable: true, | ||||||
|                     enumerable: false, // By setting this as not enumerable, the localTileSaver will _not_ calculate this
 |                     enumerable: false, // By setting this as not enumerable, the localTileSaver will _not_ calculate this
 | ||||||
|  | @ -149,7 +154,6 @@ export default class MetaTagging { | ||||||
| 
 | 
 | ||||||
|                     } |                     } | ||||||
|                 }) |                 }) | ||||||
| 
 |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,18 +7,92 @@ import BaseUIElement from "../UI/BaseUIElement"; | ||||||
| import Title from "../UI/Base/Title"; | import Title from "../UI/Base/Title"; | ||||||
| import {FixedUiElement} from "../UI/Base/FixedUiElement"; | import {FixedUiElement} from "../UI/Base/FixedUiElement"; | ||||||
| import LayerConfig from "../Models/ThemeConfig/LayerConfig"; | import LayerConfig from "../Models/ThemeConfig/LayerConfig"; | ||||||
|  | import {CountryCoder} from "latlon2country" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| const cardinalDirections = { | export class SimpleMetaTagger  { | ||||||
|  |     public readonly keys: string[]; | ||||||
|  |     public readonly doc: string; | ||||||
|  |     public readonly isLazy: boolean; | ||||||
|  |     public readonly includesDates: boolean | ||||||
|  |     public readonly applyMetaTagsOnFeature: (feature: any, freshness: Date, layer: LayerConfig) => boolean; | ||||||
|  | 
 | ||||||
|  |     /*** | ||||||
|  |      * A function that adds some extra data to a feature | ||||||
|  |      * @param docs: what does this extra data do? | ||||||
|  |      * @param f: apply the changes. Returns true if something changed | ||||||
|  |      */ | ||||||
|  |     constructor(docs: { keys: string[], doc: string, includesDates?: boolean, isLazy?: boolean, cleanupRetagger?: boolean }, | ||||||
|  |                 f: ((feature: any, freshness: Date, layer: LayerConfig) => boolean)) { | ||||||
|  |         this.keys = docs.keys; | ||||||
|  |         this.doc = docs.doc; | ||||||
|  |         this.isLazy = docs.isLazy | ||||||
|  |         this.applyMetaTagsOnFeature = f; | ||||||
|  |         this.includesDates = docs.includesDates ?? false; | ||||||
|  |         if (!docs.cleanupRetagger) { | ||||||
|  |             for (const key of docs.keys) { | ||||||
|  |                 if (!key.startsWith('_') && key.toLowerCase().indexOf("theme") < 0) { | ||||||
|  |                     throw `Incorrect metakey ${key}: it should start with underscore (_)` | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class CountryTagger extends SimpleMetaTagger { | ||||||
|  |     private static readonly coder = new CountryCoder("https://pietervdvn.github.io/latlon2country/"); | ||||||
|  | 
 | ||||||
|  |     public runningTasks: Set<any>; | ||||||
|  |      | ||||||
|  |     constructor() { | ||||||
|  |         const runningTasks=  new Set<any>(); | ||||||
|  |         super | ||||||
|  |         ( | ||||||
|  |             { | ||||||
|  |                 keys: ["_country"], | ||||||
|  |                 doc: "The country code of the property (with latlon2country)", | ||||||
|  |                 includesDates: false | ||||||
|  |             }, | ||||||
|  |             ((feature, _) => { | ||||||
|  |                 let centerPoint: any = GeoOperations.centerpoint(feature); | ||||||
|  |                 const lat = centerPoint.geometry.coordinates[1]; | ||||||
|  |                 const lon = centerPoint.geometry.coordinates[0]; | ||||||
|  |                 runningTasks.add(feature) | ||||||
|  |                 CountryTagger.coder.GetCountryCodeAsync(lon, lat).then( | ||||||
|  |                     countries => { | ||||||
|  |                         runningTasks.delete(feature) | ||||||
|  |                         try { | ||||||
|  |                             const oldCountry = feature.properties["_country"]; | ||||||
|  |                             feature.properties["_country"] = countries[0].trim().toLowerCase(); | ||||||
|  |                             if (oldCountry !== feature.properties["_country"]) { | ||||||
|  |                                 const tagsSource = State.state?.allElements?.getEventSourceById(feature.properties.id); | ||||||
|  |                                 tagsSource?.ping(); | ||||||
|  |                             } | ||||||
|  |                         } catch (e) { | ||||||
|  |                             console.warn(e) | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 ).catch(_ => { | ||||||
|  |                     runningTasks.delete(feature) | ||||||
|  |                 }) | ||||||
|  |                 return false; | ||||||
|  |             }) | ||||||
|  |         ) | ||||||
|  |             this.runningTasks   = runningTasks; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default class SimpleMetaTaggers { | ||||||
|  | 
 | ||||||
|  |     private static readonly cardinalDirections = { | ||||||
|         N: 0, NNE: 22.5, NE: 45, ENE: 67.5, |         N: 0, NNE: 22.5, NE: 45, ENE: 67.5, | ||||||
|         E: 90, ESE: 112.5, SE: 135, SSE: 157.5, |         E: 90, ESE: 112.5, SE: 135, SSE: 157.5, | ||||||
|         S: 180, SSW: 202.5, SW: 225, WSW: 247.5, |         S: 180, SSW: 202.5, SW: 225, WSW: 247.5, | ||||||
|         W: 270, WNW: 292.5, NW: 315, NNW: 337.5 |         W: 270, WNW: 292.5, NW: 315, NNW: 337.5 | ||||||
| } |     } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| export default class SimpleMetaTagger { |  | ||||||
|     public static coder: any; |  | ||||||
|     public static readonly objectMetaInfo = new SimpleMetaTagger( |     public static readonly objectMetaInfo = new SimpleMetaTagger( | ||||||
|         { |         { | ||||||
|             keys: ["_last_edit:contributor", |             keys: ["_last_edit:contributor", | ||||||
|  | @ -92,7 +166,7 @@ export default class SimpleMetaTagger { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             return SimpleMetaTagger.removeBothTagging(feature.properties) |             return SimpleMetaTaggers.removeBothTagging(feature.properties) | ||||||
|         }) |         }) | ||||||
|     ) |     ) | ||||||
|     private static surfaceArea = new SimpleMetaTagger( |     private static surfaceArea = new SimpleMetaTagger( | ||||||
|  | @ -197,32 +271,7 @@ export default class SimpleMetaTagger { | ||||||
|             return true; |             return true; | ||||||
|         }) |         }) | ||||||
|     ) |     ) | ||||||
|     private static country = new SimpleMetaTagger( |     public static country = new CountryTagger() | ||||||
|         { |  | ||||||
|             keys: ["_country"], |  | ||||||
|             doc: "The country code of the property (with latlon2country)", |  | ||||||
|             includesDates: false |  | ||||||
|         }, |  | ||||||
|         ((feature, _) => { |  | ||||||
|             let centerPoint: any = GeoOperations.centerpoint(feature); |  | ||||||
|             const lat = centerPoint.geometry.coordinates[1]; |  | ||||||
|             const lon = centerPoint.geometry.coordinates[0]; |  | ||||||
| 
 |  | ||||||
|             SimpleMetaTagger.coder?.GetCountryCodeFor(lon, lat, (countries: string[]) => { |  | ||||||
|                 try { |  | ||||||
|                     const oldCountry = feature.properties["_country"]; |  | ||||||
|                     feature.properties["_country"] = countries[0].trim().toLowerCase(); |  | ||||||
|                     if (oldCountry !== feature.properties["_country"]) { |  | ||||||
|                         const tagsSource = State.state.allElements.getEventSourceById(feature.properties.id); |  | ||||||
|                         tagsSource.ping(); |  | ||||||
|                     } |  | ||||||
|                 } catch (e) { |  | ||||||
|                     console.warn(e) |  | ||||||
|                 } |  | ||||||
|             }) |  | ||||||
|             return false; |  | ||||||
|         }) |  | ||||||
|     ) |  | ||||||
|     private static isOpen = new SimpleMetaTagger( |     private static isOpen = new SimpleMetaTagger( | ||||||
|         { |         { | ||||||
|             keys: ["_isOpen", "_isOpen:description"], |             keys: ["_isOpen", "_isOpen:description"], | ||||||
|  | @ -319,7 +368,7 @@ export default class SimpleMetaTagger { | ||||||
|             if (direction === undefined) { |             if (direction === undefined) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|             const n = cardinalDirections[direction] ?? Number(direction); |             const n = SimpleMetaTaggers.cardinalDirections[direction] ?? Number(direction); | ||||||
|             if (isNaN(n)) { |             if (isNaN(n)) { | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|  | @ -333,6 +382,7 @@ export default class SimpleMetaTagger { | ||||||
|         }) |         }) | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|     private static currentTime = new SimpleMetaTagger( |     private static currentTime = new SimpleMetaTagger( | ||||||
|         { |         { | ||||||
|             keys: ["_now:date", "_now:datetime", "_loaded:date", "_loaded:_datetime"], |             keys: ["_now:date", "_now:datetime", "_loaded:date", "_loaded:_datetime"], | ||||||
|  | @ -361,49 +411,24 @@ export default class SimpleMetaTagger { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     public static metatags = [ |     public static metatags: SimpleMetaTagger[] = [ | ||||||
|         SimpleMetaTagger.latlon, |         SimpleMetaTaggers.latlon, | ||||||
|         SimpleMetaTagger.layerInfo, |         SimpleMetaTaggers.layerInfo, | ||||||
|         SimpleMetaTagger.surfaceArea, |         SimpleMetaTaggers.surfaceArea, | ||||||
|         SimpleMetaTagger.lngth, |         SimpleMetaTaggers.lngth, | ||||||
|         SimpleMetaTagger.canonicalize, |         SimpleMetaTaggers.canonicalize, | ||||||
|         SimpleMetaTagger.country, |         SimpleMetaTaggers.country, | ||||||
|         SimpleMetaTagger.isOpen, |         SimpleMetaTaggers.isOpen, | ||||||
|         SimpleMetaTagger.directionSimplified, |         SimpleMetaTaggers.directionSimplified, | ||||||
|         SimpleMetaTagger.currentTime, |         SimpleMetaTaggers.currentTime, | ||||||
|         SimpleMetaTagger.objectMetaInfo, |         SimpleMetaTaggers.objectMetaInfo, | ||||||
|         SimpleMetaTagger.noBothButLeftRight |         SimpleMetaTaggers.noBothButLeftRight | ||||||
| 
 | 
 | ||||||
|     ]; |     ]; | ||||||
|     public readonly keys: string[]; |  | ||||||
|     public readonly doc: string; |  | ||||||
|     public readonly isLazy: boolean; |  | ||||||
|     public readonly includesDates: boolean |  | ||||||
|     public readonly applyMetaTagsOnFeature: (feature: any, freshness: Date, layer: LayerConfig) => boolean; |  | ||||||
| 
 | 
 | ||||||
|     public static readonly lazyTags: string[] = [].concat(...SimpleMetaTagger.metatags.filter(tagger => tagger.isLazy) |     public static readonly lazyTags: string[] = [].concat(...SimpleMetaTaggers.metatags.filter(tagger => tagger.isLazy) | ||||||
|         .map(tagger => tagger.keys)); |         .map(tagger => tagger.keys)); | ||||||
| 
 | 
 | ||||||
|     /*** |  | ||||||
|      * A function that adds some extra data to a feature |  | ||||||
|      * @param docs: what does this extra data do? |  | ||||||
|      * @param f: apply the changes. Returns true if something changed |  | ||||||
|      */ |  | ||||||
|     constructor(docs: { keys: string[], doc: string, includesDates?: boolean, isLazy?: boolean, cleanupRetagger?: boolean }, |  | ||||||
|                 f: ((feature: any, freshness: Date, layer: LayerConfig) => boolean)) { |  | ||||||
|         this.keys = docs.keys; |  | ||||||
|         this.doc = docs.doc; |  | ||||||
|         this.isLazy = docs.isLazy |  | ||||||
|         this.applyMetaTagsOnFeature = f; |  | ||||||
|         this.includesDates = docs.includesDates ?? false; |  | ||||||
|         if (!docs.cleanupRetagger) { |  | ||||||
|             for (const key of docs.keys) { |  | ||||||
|                 if (!key.startsWith('_') && key.toLowerCase().indexOf("theme") < 0) { |  | ||||||
|                     throw `Incorrect metakey ${key}: it should start with underscore (_)` |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Edits the given object to rewrite 'both'-tagging into a 'left-right' tagging scheme. |      * Edits the given object to rewrite 'both'-tagging into a 'left-right' tagging scheme. | ||||||
|  | @ -494,7 +519,7 @@ export default class SimpleMetaTagger { | ||||||
| 
 | 
 | ||||||
|         subElements.push(new Title("Metatags calculated by MapComplete", 2)) |         subElements.push(new Title("Metatags calculated by MapComplete", 2)) | ||||||
|         subElements.push(new FixedUiElement("The following values are always calculated, by default, by MapComplete and are available automatically on all elements in every theme")) |         subElements.push(new FixedUiElement("The following values are always calculated, by default, by MapComplete and are available automatically on all elements in every theme")) | ||||||
|         for (const metatag of SimpleMetaTagger.metatags) { |         for (const metatag of SimpleMetaTaggers.metatags) { | ||||||
|             subElements.push( |             subElements.push( | ||||||
|                 new Title(metatag.keys.join(", "), 3), |                 new Title(metatag.keys.join(", "), 3), | ||||||
|                 metatag.doc, |                 metatag.doc, | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ | ||||||
|     { |     { | ||||||
|       "id": "render_crab", |       "id": "render_crab", | ||||||
|       "render": { |       "render": { | ||||||
|         "nl": "Volgens het CRAB ligt hier <b>{STRAATNM}</b> {HUISNR} (label: {_HNRLABEL})" |         "nl": "Volgens het CRAB ligt hier <b>{STRAATNM}</b> {HUISNR} (label: {HNRLABEL})" | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
|  |  | ||||||
|  | @ -370,8 +370,8 @@ | ||||||
|                         "_embedding_street!:={STRAATNM}" |                         "_embedding_street!:={STRAATNM}" | ||||||
|                       ] |                       ] | ||||||
|                     }, |                     }, | ||||||
|                     {    "#": "Matches the embedding GRB object", |                     { | ||||||
| 
 |                       "#": "Matches the embedding GRB object", | ||||||
|                       "or": [ |                       "or": [ | ||||||
|                         "_embedding_nr_grb!:={HUISNR}", |                         "_embedding_nr_grb!:={HUISNR}", | ||||||
|                         "_embedding_street_grb!:={STRAATNM}" |                         "_embedding_street_grb!:={STRAATNM}" | ||||||
|  | @ -453,14 +453,13 @@ | ||||||
|           "render": "{import_button(OSM-buildings,building=$building;man_made=$man_made; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber; building:min_level=$_building:min_level, Upload this building to OpenStreetMap)}", |           "render": "{import_button(OSM-buildings,building=$building;man_made=$man_made; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber; building:min_level=$_building:min_level, Upload this building to OpenStreetMap)}", | ||||||
|           "mappings": [ |           "mappings": [ | ||||||
|             { |             { | ||||||
|               "if": {"and": |               "if": { | ||||||
|               [ |                 "and": [ | ||||||
|                   "_overlaps_with!=", |                   "_overlaps_with!=", | ||||||
|                   "_osm_obj:addr:street=", |                   "_osm_obj:addr:street=", | ||||||
|                   "_osm_obj:addr:housenumber=", |                   "_osm_obj:addr:housenumber=", | ||||||
|                   "addr:street~*", |                   "addr:street~*", | ||||||
|                   "addr:housenumber~*" |                   "addr:housenumber~*" | ||||||
| 
 |  | ||||||
|                 ] |                 ] | ||||||
|               }, |               }, | ||||||
|               "then": "{import_button(OSM-buildings,building=$_target_building_type; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber, Replace the geometry in OpenStreetMap and add the address,,,_osm_obj:id)}" |               "then": "{import_button(OSM-buildings,building=$_target_building_type; source:geometry:date=$_grb_date; source:geometry:ref=$_grb_ref; addr:street=$addr:street; addr:housenumber=$addr:housenumber, Replace the geometry in OpenStreetMap and add the address,,,_osm_obj:id)}" | ||||||
|  | @ -578,7 +577,8 @@ | ||||||
|             "centroid" |             "centroid" | ||||||
|           ] |           ] | ||||||
|         }, |         }, | ||||||
|         { "width": { |         { | ||||||
|  |           "width": { | ||||||
|             "render": 5, |             "render": 5, | ||||||
|             "mappings": [ |             "mappings": [ | ||||||
|               { |               { | ||||||
|  | @ -592,7 +592,7 @@ | ||||||
|             "mappings": [ |             "mappings": [ | ||||||
|               { |               { | ||||||
|                 "if": "_imported=yes", |                 "if": "_imported=yes", | ||||||
|                 "then":"#00ff00" |                 "then": "#00ff00" | ||||||
|               }, |               }, | ||||||
|               { |               { | ||||||
|                 "if": { |                 "if": { | ||||||
|  |  | ||||||
							
								
								
									
										146
									
								
								assets/themes/postal_codes.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								assets/themes/postal_codes.json
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,146 @@ | ||||||
|  | { | ||||||
|  |   "id": "postal_codes", | ||||||
|  |   "title": { | ||||||
|  |     "en": "Postal codes" | ||||||
|  |   }, | ||||||
|  |   "shortDescription": { | ||||||
|  |     "en": "Postal codes" | ||||||
|  |   }, | ||||||
|  |   "description": { | ||||||
|  |     "en": "Postal codes" | ||||||
|  |   }, | ||||||
|  |   "language": [ | ||||||
|  |     "en" | ||||||
|  |   ], | ||||||
|  |   "maintainer": "", | ||||||
|  |   "icon": "./assets/svg/bug.svg", | ||||||
|  |   "version": "0", | ||||||
|  |   "startLat": 0, | ||||||
|  |   "startLon": 0, | ||||||
|  |   "startZoom": 1, | ||||||
|  |   "widenFactor": 0.05, | ||||||
|  |   "socialImage": "", | ||||||
|  |   "layers": [ | ||||||
|  |     { | ||||||
|  |       "id": "postal_codes", | ||||||
|  |       "name": { | ||||||
|  |         "en": "postal codes" | ||||||
|  |       }, | ||||||
|  |       "minzoom": 12, | ||||||
|  |       "title": { | ||||||
|  |         "render": { | ||||||
|  |           "en": "Postal code {postal_code}" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "description": {}, | ||||||
|  |       "tagRenderings": [ | ||||||
|  |         { | ||||||
|  |           "id": "postal_code", | ||||||
|  |           "render": { | ||||||
|  |             "en": "The postal code is {postal_code}" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ], | ||||||
|  |       "presets": [], | ||||||
|  |       "source": { | ||||||
|  |         "isOsmCache": true, | ||||||
|  |         "geoJson": "http://127.0.0.1:8080/postal_codes_postal_codes_{z}_{x}_{y}.geojson", | ||||||
|  |         "geoJsonZoomLevel": 1, | ||||||
|  |         "osmTags": { | ||||||
|  |           "or": [ | ||||||
|  |             "boundary=postal_code", | ||||||
|  |             { | ||||||
|  |               "and": [ | ||||||
|  |                 "bounary=administrative", | ||||||
|  |                 "postal_code~*" | ||||||
|  |               ] | ||||||
|  |             } | ||||||
|  |           ] | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "mapRendering": [ | ||||||
|  |         { | ||||||
|  |           "icon": { | ||||||
|  |             "render": "./assets/svg/bug.svg" | ||||||
|  |           }, | ||||||
|  |           "iconSize": { | ||||||
|  |             "render": "40,40,center" | ||||||
|  |           }, | ||||||
|  |           "location": [ | ||||||
|  |             "point", | ||||||
|  |             "centroid" | ||||||
|  |           ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           "color": { | ||||||
|  |             "render": "#00f" | ||||||
|  |           }, | ||||||
|  |           "width": { | ||||||
|  |             "render": "8" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ], | ||||||
|  |       "isShown": { | ||||||
|  |         "render": "yes", | ||||||
|  |         "mappings": [{ | ||||||
|  |           "if" :"_country!=be", | ||||||
|  |           "then": "no" | ||||||
|  |         }] | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       "id": "town_halls", | ||||||
|  |       "name": { | ||||||
|  |         "en": "town halls" | ||||||
|  |       }, | ||||||
|  |       "minzoom": 12, | ||||||
|  |       "title": { | ||||||
|  |         "render": { | ||||||
|  |           "en": "Town halls" | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       "calculatedTags": [ | ||||||
|  |         "_postal_code=feat.overlapWith('postal_codes')[0]?.feat?.properties?.postal_code" | ||||||
|  |       ], | ||||||
|  |       "description": {}, | ||||||
|  |       "tagRenderings": [ | ||||||
|  |       ], | ||||||
|  |       "presets": [], | ||||||
|  |       "source": { | ||||||
|  |         "isOsmCache": true, | ||||||
|  |         "geoJson": "http://127.0.0.1:8080/postal_codes_town_hall_{z}_{x}_{y}.geojson", | ||||||
|  |         "geoJsonZoomLevel": 1, | ||||||
|  |         "osmTags": "amenity=townhall" | ||||||
|  |       }, | ||||||
|  |       "mapRendering": [ | ||||||
|  |         { | ||||||
|  |           "icon": { | ||||||
|  |             "render": "./assets/svg/bug.svg" | ||||||
|  |           }, | ||||||
|  |           "iconSize": { | ||||||
|  |             "render": "40,40,center" | ||||||
|  |           }, | ||||||
|  |           "location": [ | ||||||
|  |             "point", | ||||||
|  |             "centroid" | ||||||
|  |           ] | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |           "color": { | ||||||
|  |             "render": "#00f" | ||||||
|  |           }, | ||||||
|  |           "width": { | ||||||
|  |             "render": "8" | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       ], | ||||||
|  |       "isShown": { | ||||||
|  |         "render": "yes", | ||||||
|  |         "mappings": [{ | ||||||
|  |           "if" :"_country!=be", | ||||||
|  |           "then": "no" | ||||||
|  |         }] | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | } | ||||||
							
								
								
									
										4
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -3,8 +3,6 @@ import {QueryParameters} from "./Logic/Web/QueryParameters"; | ||||||
| import Combine from "./UI/Base/Combine"; | import Combine from "./UI/Base/Combine"; | ||||||
| import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers"; | import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers"; | ||||||
| import MinimapImplementation from "./UI/Base/MinimapImplementation"; | import MinimapImplementation from "./UI/Base/MinimapImplementation"; | ||||||
| import CountryCoder from "latlon2country/index"; |  | ||||||
| import SimpleMetaTagger from "./Logic/SimpleMetaTagger"; |  | ||||||
| import {Utils} from "./Utils"; | import {Utils} from "./Utils"; | ||||||
| import AllThemesGui from "./UI/AllThemesGui"; | import AllThemesGui from "./UI/AllThemesGui"; | ||||||
| import DetermineLayout from "./Logic/DetermineLayout"; | import DetermineLayout from "./Logic/DetermineLayout"; | ||||||
|  | @ -14,12 +12,10 @@ import State from "./State"; | ||||||
| import AvailableBaseLayersImplementation from "./Logic/Actors/AvailableBaseLayersImplementation"; | import AvailableBaseLayersImplementation from "./Logic/Actors/AvailableBaseLayersImplementation"; | ||||||
| import ShowOverlayLayerImplementation from "./UI/ShowDataLayer/ShowOverlayLayerImplementation"; | import ShowOverlayLayerImplementation from "./UI/ShowDataLayer/ShowOverlayLayerImplementation"; | ||||||
| import {DefaultGuiState} from "./UI/DefaultGuiState"; | import {DefaultGuiState} from "./UI/DefaultGuiState"; | ||||||
| import {Browser} from "leaflet"; |  | ||||||
| 
 | 
 | ||||||
| // Workaround for a stupid crash: inject some functions which would give stupid circular dependencies or crash the other nodejs scripts running from console
 | // Workaround for a stupid crash: inject some functions which would give stupid circular dependencies or crash the other nodejs scripts running from console
 | ||||||
| MinimapImplementation.initialize() | MinimapImplementation.initialize() | ||||||
| AvailableBaseLayers.implement(new AvailableBaseLayersImplementation()) | AvailableBaseLayers.implement(new AvailableBaseLayersImplementation()) | ||||||
| SimpleMetaTagger.coder = new CountryCoder("https://pietervdvn.github.io/latlon2country/"); |  | ||||||
| ShowOverlayLayerImplementation.Implement(); | ShowOverlayLayerImplementation.Implement(); | ||||||
| // Miscelleanous
 | // Miscelleanous
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1032,6 +1032,24 @@ | ||||||
|         "shortDescription": "A map with playgrounds", |         "shortDescription": "A map with playgrounds", | ||||||
|         "title": "Playgrounds" |         "title": "Playgrounds" | ||||||
|     }, |     }, | ||||||
|  |     "postal_codes": { | ||||||
|  |         "description": "Postal codes", | ||||||
|  |         "layers": { | ||||||
|  |             "0": { | ||||||
|  |                 "name": "postal codes", | ||||||
|  |                 "tagRenderings": { | ||||||
|  |                     "postal_code": { | ||||||
|  |                         "render": "The postal code is {postal_code}" | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 "title": { | ||||||
|  |                     "render": "Postal code {postal_code}" | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "shortDescription": "Postal codes", | ||||||
|  |         "title": "Postal codes" | ||||||
|  |     }, | ||||||
|     "postboxes": { |     "postboxes": { | ||||||
|         "description": "On this map you can find and add data of post offices and post boxes. You can use this map to find where you can mail your next postcard! :)<br/>Spotted an error or is a post box missing? You can edit this map with a free OpenStreetMap account. ", |         "description": "On this map you can find and add data of post offices and post boxes. You can use this map to find where you can mail your next postcard! :)<br/>Spotted an error or is a post box missing? You can edit this map with a free OpenStreetMap account. ", | ||||||
|         "layers": { |         "layers": { | ||||||
|  |  | ||||||
							
								
								
									
										4215
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										4215
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -77,7 +77,7 @@ | ||||||
|     "idb-keyval": "^6.0.3", |     "idb-keyval": "^6.0.3", | ||||||
|     "jquery": "^3.6.0", |     "jquery": "^3.6.0", | ||||||
|     "jspdf": "^2.3.1", |     "jspdf": "^2.3.1", | ||||||
|     "latlon2country": "^1.1.3", |     "latlon2country": "^1.2.3", | ||||||
|     "leaflet": "^1.7.1", |     "leaflet": "^1.7.1", | ||||||
|     "leaflet-polylineoffset": "^1.1.1", |     "leaflet-polylineoffset": "^1.1.1", | ||||||
|     "leaflet-providers": "^1.13.0", |     "leaflet-providers": "^1.13.0", | ||||||
|  |  | ||||||
|  | @ -21,7 +21,9 @@ import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSou | ||||||
| import TiledFeatureSource from "../Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource"; | import TiledFeatureSource from "../Logic/FeatureSource/TiledFeatureSource/TiledFeatureSource"; | ||||||
| import Constants from "../Models/Constants"; | import Constants from "../Models/Constants"; | ||||||
| import {GeoOperations} from "../Logic/GeoOperations"; | import {GeoOperations} from "../Logic/GeoOperations"; | ||||||
| 
 | import SimpleMetaTaggers from "../Logic/SimpleMetaTagger"; | ||||||
|  | import FilteringFeatureSource from "../Logic/FeatureSource/Sources/FilteringFeatureSource"; | ||||||
|  | import Loc from "../Models/Loc"; | ||||||
| 
 | 
 | ||||||
| ScriptUtils.fixUtils() | ScriptUtils.fixUtils() | ||||||
| 
 | 
 | ||||||
|  | @ -177,12 +179,15 @@ function loadAllTiles(targetdir: string, r: TileRange, theme: LayoutConfig, extr | ||||||
|  * Load all the tiles into memory from disk |  * Load all the tiles into memory from disk | ||||||
|  */ |  */ | ||||||
| function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relationsTracker: RelationsTracker, targetdir: string, pointsOnlyLayers: string[]) { | function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relationsTracker: RelationsTracker, targetdir: string, pointsOnlyLayers: string[]) { | ||||||
|     function handleLayer(source: FeatureSourceForLayer) { |     const skippedLayers = new Set<string>() | ||||||
|  | 
 | ||||||
|  |     async function handleLayer(source: FeatureSourceForLayer) { | ||||||
|         const layer = source.layer.layerDef; |         const layer = source.layer.layerDef; | ||||||
|         const targetZoomLevel = layer.source.geojsonZoomLevel ?? 0 |         const targetZoomLevel = layer.source.geojsonZoomLevel ?? 0 | ||||||
| 
 | 
 | ||||||
|         const layerId = layer.id |         const layerId = layer.id | ||||||
|         if (layer.source.isOsmCacheLayer !== true) { |         if (layer.source.isOsmCacheLayer !== true) { | ||||||
|  |             skippedLayers.add(layer.id) | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         console.log("Handling layer ", layerId, "which has", source.features.data.length, "features") |         console.log("Handling layer ", layerId, "which has", source.features.data.length, "features") | ||||||
|  | @ -202,6 +207,13 @@ function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relations | ||||||
|                 includeNonDates: true |                 includeNonDates: true | ||||||
|             }); |             }); | ||||||
|          |          | ||||||
|  |          | ||||||
|  | 
 | ||||||
|  |         while (SimpleMetaTaggers.country.runningTasks.size > 0) { | ||||||
|  |             console.log("Still waiting for ", SimpleMetaTaggers.country.runningTasks.size," features which don't have a country yet") | ||||||
|  |             await ScriptUtils.sleep(1) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         const createdTiles = [] |         const createdTiles = [] | ||||||
|         // At this point, we have all the features of the entire area.
 |         // At this point, we have all the features of the entire area.
 | ||||||
|         // However, we want to export them per tile of a fixed size, so we use a dynamicTileSOurce to split it up
 |         // However, we want to export them per tile of a fixed size, so we use a dynamicTileSOurce to split it up
 | ||||||
|  | @ -210,23 +222,57 @@ function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relations | ||||||
|             maxZoomLevel: targetZoomLevel, |             maxZoomLevel: targetZoomLevel, | ||||||
|             maxFeatureCount: undefined, |             maxFeatureCount: undefined, | ||||||
|             registerTile: tile => { |             registerTile: tile => { | ||||||
|  |                 const tileIndex = tile.tileIndex; | ||||||
|                 if (tile.features.data.length === 0) { |                 if (tile.features.data.length === 0) { | ||||||
|                     return |                     return | ||||||
|                 } |                 } | ||||||
|                 for (const feature of tile.features.data) { |                 | ||||||
|  |                 const filteredTile = new FilteringFeatureSource({ | ||||||
|  |                   locationControl:  new UIEventSource<Loc>(undefined), | ||||||
|  |                     allElements: undefined, | ||||||
|  |                     selectedElement: new UIEventSource<any>(undefined) | ||||||
|  |                 }, | ||||||
|  |                     tileIndex, | ||||||
|  |                     tile, | ||||||
|  |                     new UIEventSource<any>(undefined) | ||||||
|  |                     ) | ||||||
|  | 
 | ||||||
|  |                 if (filteredTile.features.data.length === 0) { | ||||||
|  |                     return | ||||||
|  |                 } | ||||||
|  |                 let strictlyCalculated = 0 | ||||||
|  |                 let featureCount = 0 | ||||||
|  |                 for (const feature of filteredTile.features.data) { | ||||||
|                     // Some cleanup
 |                     // Some cleanup
 | ||||||
|                     delete feature.feature["bbox"] |                     delete feature.feature["bbox"] | ||||||
|  |                      | ||||||
|  |                     if(tile.layer.layerDef.calculatedTags !== undefined){ | ||||||
|  |                          | ||||||
|  |                     // Evaluate all the calculated tags strictly
 | ||||||
|  |                     const calculatedTagKeys = tile.layer.layerDef.calculatedTags.map(ct => ct[0]) | ||||||
|  |                     featureCount++ | ||||||
|  |                     for (const calculatedTagKey of calculatedTagKeys) { | ||||||
|  |                         const strict =  feature.feature.properties[calculatedTagKey] | ||||||
|  |                         feature.feature.properties[calculatedTagKey] =strict | ||||||
|  |                         strictlyCalculated ++; | ||||||
|  |                         if(strictlyCalculated % 100 === 0){ | ||||||
|  |                             console.log("Strictly calculated ", strictlyCalculated, "values for tile",tileIndex,": now at ", featureCount,"/",filteredTile.features.data.length, "examle value: ", strict) | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     } | ||||||
|  |                      | ||||||
|                 } |                 } | ||||||
|                 // Lets save this tile!
 |                 // Lets save this tile!
 | ||||||
|                 const [z, x, y] = Tiles.tile_from_index(tile.tileIndex) |                 const [z, x, y] = Tiles.tile_from_index(tileIndex) | ||||||
|                 // console.log("Writing tile ", z, x, y, layerId)
 |                 // console.log("Writing tile ", z, x, y, layerId)
 | ||||||
|                 const targetPath = geoJsonName(targetdir + "_" + layerId, x, y, z) |                 const targetPath = geoJsonName(targetdir + "_" + layerId, x, y, z) | ||||||
|                 createdTiles.push(tile.tileIndex) |                 createdTiles.push(tileIndex) | ||||||
|                 // This is the geojson file containing all features for this tile
 |                 // This is the geojson file containing all features for this tile
 | ||||||
|                 writeFileSync(targetPath, JSON.stringify({ |                 writeFileSync(targetPath, JSON.stringify({ | ||||||
|                     type: "FeatureCollection", |                     type: "FeatureCollection", | ||||||
|                     features: tile.features.data.map(f => f.feature) |                     features: filteredTile.features.data.map(f => f.feature) | ||||||
|                 }, null, " ")) |                 }, null, " ")) | ||||||
|  |                 console.log("Written tile", targetPath,"with", filteredTile.features.data.length) | ||||||
|             } |             } | ||||||
|         }) |         }) | ||||||
| 
 | 
 | ||||||
|  | @ -267,18 +313,31 @@ function sliceToTiles(allFeatures: FeatureSource, theme: LayoutConfig, relations | ||||||
|         handleLayer, |         handleLayer, | ||||||
|         allFeatures |         allFeatures | ||||||
|     ) |     ) | ||||||
|  | 
 | ||||||
|  |     const skipped = Array.from(skippedLayers) | ||||||
|  |     if (skipped.length > 0) { | ||||||
|  |         console.warn("Did not save any cache files for layers " + skipped.join(", ") + " as these didn't set the flag `isOsmCache` to true") | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| async function main(args: string[]) { | async function main(args: string[]) { | ||||||
| 
 | 
 | ||||||
|     if (args.length == 0) { |     console.log("Cache builder started with args ", args.join(", ")) | ||||||
|         console.error("Expected arguments are: theme zoomlevel targetdirectory lat0 lon0 lat1 lon1 [--generate-point-overview layer-name,layer-name,...]") |     if (args.length < 6) { | ||||||
|  |         console.error("Expected arguments are: theme zoomlevel targetdirectory lat0 lon0 lat1 lon1 [--generate-point-overview layer-name,layer-name,...]\n" + | ||||||
|  |             "Note: a new directory named <theme> will be created in targetdirectory") | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     const themeName = args[0] |     const themeName = args[0] | ||||||
|     const zoomlevel = Number(args[1]) |     const zoomlevel = Number(args[1]) | ||||||
|  | 
 | ||||||
|     const targetdir = args[2] + "/" + themeName |     const targetdir = args[2] + "/" + themeName | ||||||
|  |     if (!existsSync(args[2])) { | ||||||
|  |         console.log("Directory not found") | ||||||
|  |         throw "The directory " + args[2] + "does not exist" | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const lat0 = Number(args[3]) |     const lat0 = Number(args[3]) | ||||||
|     const lon0 = Number(args[4]) |     const lon0 = Number(args[4]) | ||||||
|     const lat1 = Number(args[5]) |     const lat1 = Number(args[5]) | ||||||
|  | @ -292,6 +351,11 @@ async function main(args: string[]) { | ||||||
| 
 | 
 | ||||||
|     const tileRange = Tiles.TileRangeBetween(zoomlevel, lat0, lon0, lat1, lon1) |     const tileRange = Tiles.TileRangeBetween(zoomlevel, lat0, lon0, lat1, lon1) | ||||||
| 
 | 
 | ||||||
|  |     if (tileRange.total === 0) { | ||||||
|  |         console.log("Tilerange has zero tiles - this is probably an error") | ||||||
|  |         return | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     const theme = AllKnownLayouts.allKnownLayouts.get(themeName) |     const theme = AllKnownLayouts.allKnownLayouts.get(themeName) | ||||||
|     if (theme === undefined) { |     if (theme === undefined) { | ||||||
|         const keys = [] |         const keys = [] | ||||||
|  | @ -321,5 +385,9 @@ async function main(args: string[]) { | ||||||
| 
 | 
 | ||||||
| let args = [...process.argv] | let args = [...process.argv] | ||||||
| args.splice(0, 2) | args.splice(0, 2) | ||||||
| main(args); | try { | ||||||
|  |     main(args).catch(e => console.error("Error building cache:", e)); | ||||||
|  | } catch (e) { | ||||||
|  |     console.error("Error building cache:", e) | ||||||
|  | } | ||||||
| console.log("All done!") | console.log("All done!") | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue