Remove generate cache scripts
This commit is contained in:
parent
8cf65c7bf5
commit
f3db4b34c9
17 changed files with 444 additions and 8231 deletions
|
@ -22,10 +22,14 @@
|
|||
"render": {
|
||||
"en": "POI with image"
|
||||
},
|
||||
"mappings": [{
|
||||
"mappings": [
|
||||
{
|
||||
"if": "name~*",
|
||||
"then": {"*": "name"}
|
||||
}]
|
||||
"then": {
|
||||
"*": "name"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": {
|
||||
"en": "Items with at least one image"
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
"description": "Special layer which shows `count`",
|
||||
"source": "special",
|
||||
"title": {
|
||||
"render": {"en": "Summary"}
|
||||
"render": {
|
||||
"en": "Summary"
|
||||
}
|
||||
},
|
||||
"tagRenderings": [
|
||||
"all_tags"
|
||||
|
|
|
@ -44,5 +44,4 @@
|
|||
"ghost_bike"
|
||||
],
|
||||
"widenFactor": 5
|
||||
|
||||
}
|
||||
|
|
|
@ -7100,6 +7100,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"souvenir_note": {
|
||||
"tagRenderings": {
|
||||
"designs": {
|
||||
"freeform": {
|
||||
"placeholder": "Nombre de dissenys (p. e. 5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"speed_camera": {
|
||||
"description": "Capa que mostra càmeres de velocitat",
|
||||
"name": "Càmera de velocitat",
|
||||
|
|
|
@ -7396,6 +7396,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"souvenir_note": {
|
||||
"tagRenderings": {
|
||||
"designs": {
|
||||
"freeform": {
|
||||
"placeholder": "Počet vzorů (např. 5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"speed_camera": {
|
||||
"description": "Vrstva zobrazující rychlostní radary",
|
||||
"name": "Rychlostní radar",
|
||||
|
|
|
@ -8563,6 +8563,15 @@
|
|||
"render": "Geschwindigkeitsreduzierte Straße"
|
||||
}
|
||||
},
|
||||
"souvenir_note": {
|
||||
"tagRenderings": {
|
||||
"designs": {
|
||||
"freeform": {
|
||||
"placeholder": "Motivanzahl (z.B. 5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"speed_camera": {
|
||||
"description": "Ebene mit Blitzern",
|
||||
"name": "Blitzer",
|
||||
|
|
|
@ -5658,6 +5658,12 @@
|
|||
"render": "Information board"
|
||||
}
|
||||
},
|
||||
"item_with_image": {
|
||||
"name": "Items with at least one image",
|
||||
"title": {
|
||||
"render": "POI with image"
|
||||
}
|
||||
},
|
||||
"kerbs": {
|
||||
"description": "A layer showing kerbs.",
|
||||
"filter": {
|
||||
|
@ -6993,6 +6999,101 @@
|
|||
"render": "Playground"
|
||||
}
|
||||
},
|
||||
"playground_equipment": {
|
||||
"description": "Layer showing playground equipment",
|
||||
"name": "Playground equipment",
|
||||
"presets": {
|
||||
"0": {
|
||||
"description": "An exact type is asked later",
|
||||
"title": "a playground device"
|
||||
}
|
||||
},
|
||||
"tagRenderings": {
|
||||
"type": {
|
||||
"freeform": {
|
||||
"placeholder": "Type of device"
|
||||
},
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This is a swing"
|
||||
},
|
||||
"1": {
|
||||
"then": "This is a structure consisting of several connected playground devices"
|
||||
},
|
||||
"2": {
|
||||
"then": "This is a slide"
|
||||
},
|
||||
"3": {
|
||||
"then": "This is a sand pit"
|
||||
},
|
||||
"4": {
|
||||
"then": "This is a spring rider"
|
||||
},
|
||||
"5": {
|
||||
"then": "This is a climbing frame"
|
||||
},
|
||||
"6": {
|
||||
"then": "This is a seesaw"
|
||||
},
|
||||
"7": {
|
||||
"then": "This is a playhouse"
|
||||
},
|
||||
"8": {
|
||||
"then": "This is a roundabout"
|
||||
},
|
||||
"9": {
|
||||
"then": "This is a basket swing"
|
||||
},
|
||||
"10": {
|
||||
"then": "This is a zip wire"
|
||||
},
|
||||
"11": {
|
||||
"then": "This is a horizontal bar"
|
||||
},
|
||||
"12": {
|
||||
"then": "This is a hopscotch"
|
||||
},
|
||||
"13": {
|
||||
"then": "This is a splash pad"
|
||||
},
|
||||
"14": {
|
||||
"then": "This is a climbing wall"
|
||||
},
|
||||
"15": {
|
||||
"then": "This is a map"
|
||||
},
|
||||
"16": {
|
||||
"then": "This is a bridge (either as a standalone device or as part of a larger structure)"
|
||||
},
|
||||
"17": {
|
||||
"then": "This is a bouncy cushion"
|
||||
},
|
||||
"18": {
|
||||
"then": "This is an activity panel"
|
||||
},
|
||||
"19": {
|
||||
"then": "This is a teen shelter"
|
||||
},
|
||||
"20": {
|
||||
"then": "This is a funnel used to play with funnel ball"
|
||||
},
|
||||
"21": {
|
||||
"then": "This is a spinning circle"
|
||||
}
|
||||
},
|
||||
"question": "What kind of device is this?",
|
||||
"render": "This is a {playground}"
|
||||
},
|
||||
"wheelchair-access": {
|
||||
"override": {
|
||||
"question": "Is this device accessible by wheelchair?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": "Playground device"
|
||||
}
|
||||
},
|
||||
"postboxes": {
|
||||
"description": "The layer showing postboxes.",
|
||||
"name": "Postboxes",
|
||||
|
@ -7007,6 +7108,43 @@
|
|||
},
|
||||
"postoffices": {
|
||||
"description": "A layer showing post offices.",
|
||||
"filter": {
|
||||
"1": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Offers letter posting"
|
||||
}
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Offers parcel posting"
|
||||
}
|
||||
}
|
||||
},
|
||||
"3": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Offers pickup of missed parcels"
|
||||
}
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Accepts pickup of parcels sent here"
|
||||
}
|
||||
}
|
||||
},
|
||||
"5": {
|
||||
"options": {
|
||||
"0": {
|
||||
"question": "Sells stamps"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": "Post offices",
|
||||
"presets": {
|
||||
"0": {
|
||||
|
@ -8563,6 +8701,125 @@
|
|||
"render": "Slow road"
|
||||
}
|
||||
},
|
||||
"souvenir_coin": {
|
||||
"description": "Layer showing machines selling souvenir coins",
|
||||
"name": "Souvenir Coin Machines",
|
||||
"presets": {
|
||||
"0": {
|
||||
"description": "Add a machine selling souvenir coins",
|
||||
"title": "a souvenir coin machine"
|
||||
}
|
||||
},
|
||||
"tagRenderings": {
|
||||
"charge": {
|
||||
"freeform": {
|
||||
"placeholder": "Cost (e.g. 2 EUR)"
|
||||
},
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "A souvenir coin costs 2 euro"
|
||||
}
|
||||
},
|
||||
"question": "How much does a souvenir coin cost?",
|
||||
"render": "A souvenir coins costs {charge}"
|
||||
},
|
||||
"designs": {
|
||||
"override": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This machine has one design available"
|
||||
},
|
||||
"1": {
|
||||
"then": "This machine has two designs available"
|
||||
},
|
||||
"2": {
|
||||
"then": "This machine has three designs available"
|
||||
},
|
||||
"3": {
|
||||
"then": "This machine has four designs available"
|
||||
}
|
||||
},
|
||||
"render": "This machine has {coin:design_count} designs available"
|
||||
}
|
||||
},
|
||||
"indoor": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This machine is located indoors."
|
||||
},
|
||||
"1": {
|
||||
"then": "This machine is located outdoors."
|
||||
}
|
||||
},
|
||||
"question": "Is this machine located indoors?"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": "Souvenir Coin Machine"
|
||||
}
|
||||
},
|
||||
"souvenir_note": {
|
||||
"description": "Layer showing machines selling souvenir banknotes",
|
||||
"name": "Souvenir Banknote Machines",
|
||||
"presets": {
|
||||
"0": {
|
||||
"description": "Add a machine selling souvenir banknotes",
|
||||
"title": "a souvenir banknote machine"
|
||||
}
|
||||
},
|
||||
"tagRenderings": {
|
||||
"charge": {
|
||||
"freeform": {
|
||||
"placeholder": "Cost (e.g. 2 EUR)"
|
||||
},
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "A souvenir note costs 2 euro"
|
||||
},
|
||||
"1": {
|
||||
"then": "A souvenir note costs 3 euro"
|
||||
}
|
||||
},
|
||||
"question": "How much does a souvenir note cost?",
|
||||
"render": "A souvenir note costs {charge}"
|
||||
},
|
||||
"designs": {
|
||||
"freeform": {
|
||||
"placeholder": "Number of designs (e.g. 5)"
|
||||
},
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This machine has one design available."
|
||||
},
|
||||
"1": {
|
||||
"then": "This machine has two designs available."
|
||||
},
|
||||
"2": {
|
||||
"then": "This machine has three designs available."
|
||||
},
|
||||
"3": {
|
||||
"then": "This machine has four designs available."
|
||||
}
|
||||
},
|
||||
"question": "How many designs are available?",
|
||||
"render": "This machine has {note:design_count} designs available."
|
||||
},
|
||||
"indoor": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This machine is located indoors."
|
||||
},
|
||||
"1": {
|
||||
"then": "This machine is located outdoors."
|
||||
}
|
||||
},
|
||||
"question": "Is this machine located indoors?"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": "Souvenir Banknote Machine"
|
||||
}
|
||||
},
|
||||
"speed_camera": {
|
||||
"description": "Layer showing speed cameras",
|
||||
"name": "Speed Camera",
|
||||
|
@ -9063,6 +9320,11 @@
|
|||
"render": "Stripclub"
|
||||
}
|
||||
},
|
||||
"summary": {
|
||||
"title": {
|
||||
"render": "Summary"
|
||||
}
|
||||
},
|
||||
"surveillance_camera": {
|
||||
"description": "This layer shows surveillance cameras and allows a contributor to update information and add new cameras",
|
||||
"name": "Surveillance camera's",
|
||||
|
|
|
@ -4023,6 +4023,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"souvenir_note": {
|
||||
"tagRenderings": {
|
||||
"designs": {
|
||||
"freeform": {
|
||||
"placeholder": "Número de diseños (por ejemplo, 5)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"speed_camera": {
|
||||
"description": "Capa con cámaras de velocidad",
|
||||
"name": "Cámara de velocidad",
|
||||
|
|
|
@ -6065,6 +6065,33 @@
|
|||
"render": "Speeltuin"
|
||||
}
|
||||
},
|
||||
"playground_equipment": {
|
||||
"tagRenderings": {
|
||||
"type": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Dit is een schommel"
|
||||
},
|
||||
"3": {
|
||||
"then": "Dit is een zandbak"
|
||||
},
|
||||
"4": {
|
||||
"then": "Dit is een veertoestel"
|
||||
},
|
||||
"5": {
|
||||
"then": "Dit is een klimrek"
|
||||
},
|
||||
"6": {
|
||||
"then": "Dit is een wipwap"
|
||||
},
|
||||
"11": {
|
||||
"then": "Dit is een rekstok"
|
||||
}
|
||||
},
|
||||
"question": "Wat voor speeltoestel is dit?"
|
||||
}
|
||||
}
|
||||
},
|
||||
"postboxes": {
|
||||
"description": "Deze laag toont brievenbussen.",
|
||||
"name": "Brievenbussen",
|
||||
|
|
|
@ -810,6 +810,71 @@
|
|||
"description": "A <b>ghost bike</b> is a memorial for a cyclist who died in a traffic accident, in the form of a white bicycle placed permanently near the accident location.<br/><br/>On this map, one can see all the ghost bikes which are known by OpenStreetMap. Is a ghost bike missing? Everyone can add or update information here - you only need to have a (free) OpenStreetMap account. <p>There exists an <a href='https://masto.bike/@ghostbikebot' target='_blank'>automated account on Mastodon which posts a monthly overview of ghost bikes worldwide</a></p>",
|
||||
"title": "Ghost bikes"
|
||||
},
|
||||
"ghostsigns": {
|
||||
"description": "A map showing disused signs on buildings",
|
||||
"layers": {
|
||||
"0": {
|
||||
"description": "Layer showing disused signs on buildings",
|
||||
"name": "Ghost Signs",
|
||||
"presets": {
|
||||
"0": {
|
||||
"title": "a ghost sign"
|
||||
}
|
||||
},
|
||||
"tagRenderings": {
|
||||
"brand": {
|
||||
"freeform": {
|
||||
"placeholder": "Business name"
|
||||
},
|
||||
"question": "For what business was this sign made?",
|
||||
"render": "This sign was made for: {brand}"
|
||||
},
|
||||
"historic": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This is a ghost sign"
|
||||
},
|
||||
"1": {
|
||||
"then": "This is not a ghost sign, answering this will hide the sign from the map"
|
||||
}
|
||||
},
|
||||
"question": "Is this a ghost sign?",
|
||||
"questionHint": "Is this sign for a business that no longer exists or no longer being maintained?"
|
||||
},
|
||||
"inscription": {
|
||||
"freeform": {
|
||||
"placeholder": "Text on the sign"
|
||||
},
|
||||
"question": "What is the text on the sign?",
|
||||
"render": "The text on the sign is: {inscription}"
|
||||
}
|
||||
},
|
||||
"title": {
|
||||
"render": "Ghost Sign"
|
||||
}
|
||||
},
|
||||
"1": {
|
||||
"override": {
|
||||
"+tagRenderings": {
|
||||
"0": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This is a ghost sign"
|
||||
},
|
||||
"1": {
|
||||
"then": "This is not a ghost sign"
|
||||
}
|
||||
},
|
||||
"question": "Is this a ghost sign?",
|
||||
"questionHint": "Is this sign for a business that no longer exists or no longer being maintained?"
|
||||
}
|
||||
},
|
||||
"name": "All advertentie wall paintings"
|
||||
}
|
||||
}
|
||||
},
|
||||
"title": "Ghost Signs"
|
||||
},
|
||||
"grb": {
|
||||
"description": "This theme is an attempt to help automating the GRB import.",
|
||||
"layers": {
|
||||
|
@ -886,6 +951,10 @@
|
|||
"description": "On this map, publicly accessible indoor places are shown",
|
||||
"title": "Indoors"
|
||||
},
|
||||
"items_with_image": {
|
||||
"description": "A map showing all items on OSM which have an image. This theme is a very bad fit for MapComplete as someone is not able to directly add a picture. However, this theme is mostly here to include this all into the database, which'll allow this to quickly fetch images nearby for other features",
|
||||
"title": "All items with images"
|
||||
},
|
||||
"kerbs_and_crossings": {
|
||||
"description": "A map showing kerbs and crossings.",
|
||||
"layers": {
|
||||
|
@ -1262,6 +1331,32 @@
|
|||
},
|
||||
"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.",
|
||||
"layers": {
|
||||
"3": {
|
||||
"override": {
|
||||
"+tagRenderings": {
|
||||
"0": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "This shop is a post partner"
|
||||
},
|
||||
"1": {
|
||||
"then": "This shop is not a post partner"
|
||||
}
|
||||
},
|
||||
"question": "Is this shop a post partner?"
|
||||
}
|
||||
},
|
||||
"=presets": {
|
||||
"0": {
|
||||
"description": "If a shop is not yet on the map and is a post partner, you can add it here.",
|
||||
"title": "a missing shop that is a post partner"
|
||||
}
|
||||
},
|
||||
"description": "Add a new post partner to the map in an existing shop"
|
||||
}
|
||||
}
|
||||
},
|
||||
"shortDescription": "A map showing postboxes and post offices",
|
||||
"title": "Postbox and Post Office Map"
|
||||
},
|
||||
|
|
|
@ -721,6 +721,15 @@
|
|||
"description": "Een <b>Witte Fiets</b> of <b>Spookfiets</b> is een aandenken aan een fietser die bij een verkeersongeval om het leven kwam. Het gaat om een fiets die volledig wit is geschilderd en in de buurt van het ongeval werd geinstalleerd.<br/><br/>Op deze kaart zie je alle witte fietsen die door OpenStreetMap gekend zijn. Ontbreekt er een Witte Fiets of wens je informatie aan te passen? Meld je dan aan met een (gratis) OpenStreetMap account.",
|
||||
"title": "Witte Fietsen"
|
||||
},
|
||||
"ghostsigns": {
|
||||
"layers": {
|
||||
"1": {
|
||||
"override": {
|
||||
"name": "Alle adverterende muurschilderingen"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"grb": {
|
||||
"description": "Dit thema helpt het GRB importeren.",
|
||||
"layers": {
|
||||
|
|
|
@ -60,8 +60,6 @@
|
|||
"reset:translations": "vite-node scripts/generateTranslations.ts -- --ignore-weblate",
|
||||
"generate:layouts": "vite-node scripts/generateLayouts.ts",
|
||||
"generate:docs": "rm -rf Docs/Themes/* && rm -rf Docs/Layers/* && rm -rf Docs/TagInfo && mkdir Docs/TagInfo && vite-node scripts/generateDocs.ts && vite-node scripts/generateTaginfoProjectFiles.ts",
|
||||
"generate:cache:speelplekken": "npm run generate:layeroverview && vite-node scripts/generateCache.ts -- speelplekken 14 ../MapComplete-data/speelplekken_cache/ 51.20 4.35 51.09 4.56",
|
||||
"generate:cache:natuurpunt": "npm run generate:layeroverview && vite-node scripts/generateCache.ts -- natuurpunt 12 ../MapComplete-data/natuurpunt_cache/ 50.40 2.1 51.54 6.4 --generate-point-overview nature_reserve,visitor_information_centre",
|
||||
"generate:layeroverview": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts",
|
||||
"velopark": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts -- --force --themes=velopark --layers=bike_parking,maproulette_challenge",
|
||||
"generate:mapcomplete-changes-theme": "export NODE_OPTIONS=\"--max-old-space-size=8192\" && vite-node scripts/generateLayerOverview.ts -- --generate-change-map",
|
||||
|
|
|
@ -1,571 +0,0 @@
|
|||
/**
|
||||
* Generates a collection of geojson files based on an overpass query for a given theme
|
||||
*/
|
||||
import { Utils } from "../src/Utils"
|
||||
import { Overpass } from "../src/Logic/Osm/Overpass"
|
||||
import { existsSync, readFileSync, writeFileSync } from "fs"
|
||||
import { TagsFilter } from "../src/Logic/Tags/TagsFilter"
|
||||
import { Or } from "../src/Logic/Tags/Or"
|
||||
import { AllKnownLayouts } from "../src/Customizations/AllKnownLayouts"
|
||||
import * as OsmToGeoJson from "osmtogeojson"
|
||||
import MetaTagging from "../src/Logic/MetaTagging"
|
||||
import { UIEventSource } from "../src/Logic/UIEventSource"
|
||||
import { TileRange, Tiles } from "../src/Models/TileRange"
|
||||
import LayoutConfig from "../src/Models/ThemeConfig/LayoutConfig"
|
||||
import ScriptUtils from "./ScriptUtils"
|
||||
import PerLayerFeatureSourceSplitter from "../src/Logic/FeatureSource/PerLayerFeatureSourceSplitter"
|
||||
import FilteredLayer from "../src/Models/FilteredLayer"
|
||||
import StaticFeatureSource from "../src/Logic/FeatureSource/Sources/StaticFeatureSource"
|
||||
import Constants from "../src/Models/Constants"
|
||||
import { GeoOperations } from "../src/Logic/GeoOperations"
|
||||
import SimpleMetaTaggers, { ReferencingWaysMetaTagger } from "../src/Logic/SimpleMetaTagger"
|
||||
import FilteringFeatureSource from "../src/Logic/FeatureSource/Sources/FilteringFeatureSource"
|
||||
import { Feature } from "geojson"
|
||||
import { BBox } from "../src/Logic/BBox"
|
||||
import { FeatureSource } from "../src/Logic/FeatureSource/FeatureSource"
|
||||
import OsmObjectDownloader from "../src/Logic/Osm/OsmObjectDownloader"
|
||||
import FeaturePropertiesStore from "../src/Logic/FeatureSource/Actors/FeaturePropertiesStore"
|
||||
|
||||
ScriptUtils.fixUtils()
|
||||
|
||||
function createOverpassObject(theme: LayoutConfig, backend: string) {
|
||||
let filters: TagsFilter[] = []
|
||||
let extraScripts: string[] = []
|
||||
for (const layer of theme.layers) {
|
||||
if (typeof layer === "string") {
|
||||
throw "A layer was not expanded!"
|
||||
}
|
||||
if (layer.doNotDownload) {
|
||||
continue
|
||||
}
|
||||
if (!layer.source) {
|
||||
continue
|
||||
}
|
||||
if (layer.source.geojsonSource) {
|
||||
// This layer defines a geoJson-source
|
||||
// SHould it be cached?
|
||||
if (layer.source.isOsmCacheLayer !== true) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
filters.push(layer.source.osmTags)
|
||||
}
|
||||
filters = Utils.NoNull(filters)
|
||||
extraScripts = Utils.NoNull(extraScripts)
|
||||
if (filters.length + extraScripts.length === 0) {
|
||||
throw "Nothing to download! The theme doesn't declare anything to download"
|
||||
}
|
||||
return new Overpass(new Or(filters), extraScripts, backend, new UIEventSource<number>(60))
|
||||
}
|
||||
|
||||
function rawJsonName(targetDir: string, x: number, y: number, z: number): string {
|
||||
return targetDir + "_" + z + "_" + x + "_" + y + ".json"
|
||||
}
|
||||
|
||||
function geoJsonName(targetDir: string, x: number, y: number, z: number): string {
|
||||
return targetDir + "_" + z + "_" + x + "_" + y + ".geojson"
|
||||
}
|
||||
|
||||
/// Downloads the given tilerange from overpass and saves them to disk
|
||||
async function downloadRaw(
|
||||
targetdir: string,
|
||||
r: TileRange,
|
||||
theme: LayoutConfig
|
||||
): Promise<{ failed: number; skipped: number }> {
|
||||
let downloaded = 0
|
||||
let failed = 0
|
||||
let skipped = 0
|
||||
const startTime = new Date().getTime()
|
||||
for (let x = r.xstart; x <= r.xend; x++) {
|
||||
for (let y = r.ystart; y <= r.yend; y++) {
|
||||
downloaded++
|
||||
const filename = rawJsonName(targetdir, x, y, r.zoomlevel)
|
||||
if (existsSync(filename)) {
|
||||
console.log("Already exists (not downloading again): ", filename)
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
const runningSeconds = (new Date().getTime() - startTime) / 1000
|
||||
const resting = failed + (r.total - downloaded)
|
||||
const perTile = runningSeconds / (downloaded - skipped)
|
||||
const estimated = Math.floor(resting * perTile)
|
||||
console.log(
|
||||
"total: ",
|
||||
downloaded,
|
||||
"/",
|
||||
r.total,
|
||||
"failed: ",
|
||||
failed,
|
||||
"skipped: ",
|
||||
skipped,
|
||||
"running time: ",
|
||||
Utils.toHumanTime(runningSeconds) + "s",
|
||||
"estimated left: ",
|
||||
Utils.toHumanTime(estimated),
|
||||
"(" + Math.floor(perTile) + "s/tile)"
|
||||
)
|
||||
|
||||
const boundsArr = Tiles.tile_bounds(r.zoomlevel, x, y)
|
||||
const bounds = {
|
||||
north: Math.max(boundsArr[0][0], boundsArr[1][0]),
|
||||
south: Math.min(boundsArr[0][0], boundsArr[1][0]),
|
||||
east: Math.max(boundsArr[0][1], boundsArr[1][1]),
|
||||
west: Math.min(boundsArr[0][1], boundsArr[1][1]),
|
||||
}
|
||||
const overpass = createOverpassObject(
|
||||
theme,
|
||||
Constants.defaultOverpassUrls[failed % Constants.defaultOverpassUrls.length]
|
||||
)
|
||||
const url = overpass.buildQuery(
|
||||
"[bbox:" +
|
||||
bounds.south +
|
||||
"," +
|
||||
bounds.west +
|
||||
"," +
|
||||
bounds.north +
|
||||
"," +
|
||||
bounds.east +
|
||||
"]"
|
||||
)
|
||||
|
||||
try {
|
||||
const json = await Utils.downloadJson(url)
|
||||
if ((<string>json.remark ?? "").startsWith("runtime error")) {
|
||||
console.error("Got a runtime error: ", json.remark)
|
||||
failed++
|
||||
} else if (json.elements.length === 0) {
|
||||
console.log("Got an empty response! Writing anyway")
|
||||
}
|
||||
|
||||
console.log(
|
||||
"Got the response - writing ",
|
||||
json.elements.length,
|
||||
" elements to ",
|
||||
filename
|
||||
)
|
||||
writeFileSync(filename, JSON.stringify(json, null, " "))
|
||||
} catch (err) {
|
||||
console.log(url)
|
||||
console.log(
|
||||
"Could not download - probably hit the rate limit; waiting a bit. (" + err + ")"
|
||||
)
|
||||
failed++
|
||||
await ScriptUtils.sleep(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { failed: failed, skipped: skipped }
|
||||
}
|
||||
|
||||
/*
|
||||
* Downloads extra geojson sources and returns the features.
|
||||
* Extra geojson layers should not be tiled
|
||||
*/
|
||||
async function downloadExtraData(theme: LayoutConfig) /* : any[] */ {
|
||||
const allFeatures: any[] = []
|
||||
for (const layer of theme.layers) {
|
||||
if (!layer.source?.geojsonSource) {
|
||||
continue
|
||||
}
|
||||
const source = layer.source.geojsonSource
|
||||
if (layer.source.isOsmCacheLayer !== undefined && layer.source.isOsmCacheLayer !== false) {
|
||||
// Cached layers are not considered here
|
||||
continue
|
||||
}
|
||||
if (source.startsWith("https://api.openstreetmap.org/api/0.6/notes.json")) {
|
||||
// We ignore map notes
|
||||
continue
|
||||
}
|
||||
console.log("Downloading extra data: ", source)
|
||||
await Utils.downloadJson(source).then((json) => allFeatures.push(...json.features))
|
||||
}
|
||||
return allFeatures
|
||||
}
|
||||
|
||||
function loadAllTiles(
|
||||
targetdir: string,
|
||||
r: TileRange,
|
||||
theme: LayoutConfig,
|
||||
extraFeatures: any[]
|
||||
): FeatureSource {
|
||||
let allFeatures = [...extraFeatures]
|
||||
let processed = 0
|
||||
for (let x = r.xstart; x <= r.xend; x++) {
|
||||
for (let y = r.ystart; y <= r.yend; y++) {
|
||||
processed++
|
||||
const filename = rawJsonName(targetdir, x, y, r.zoomlevel)
|
||||
console.log(" Loading and processing", processed, "/", r.total, filename)
|
||||
if (!existsSync(filename)) {
|
||||
console.error("Not found - and not downloaded. Run this script again!: " + filename)
|
||||
continue
|
||||
}
|
||||
|
||||
// We read the raw OSM-file and convert it to a geojson
|
||||
const rawOsm = JSON.parse(readFileSync(filename, { encoding: "utf8" }))
|
||||
|
||||
// Create and save the geojson file - which is the main chunk of the data
|
||||
const geojson = OsmToGeoJson.default(rawOsm)
|
||||
console.log(" which as", geojson.features.length, "features")
|
||||
|
||||
allFeatures.push(...geojson.features)
|
||||
}
|
||||
}
|
||||
return StaticFeatureSource.fromGeojson(allFeatures)
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all the tiles into memory from disk
|
||||
*/
|
||||
async function sliceToTiles(
|
||||
allFeatures: FeatureSource,
|
||||
theme: LayoutConfig,
|
||||
targetdir: string,
|
||||
pointsOnlyLayers: string[],
|
||||
clip: boolean,
|
||||
targetzoomLevel: number = 9
|
||||
) {
|
||||
const skippedLayers = new Set<string>()
|
||||
|
||||
const indexedFeatures: Map<string, any> = new Map<string, any>()
|
||||
let indexisBuilt = false
|
||||
const osmObjectDownloader = new OsmObjectDownloader()
|
||||
|
||||
function buildIndex() {
|
||||
for (const f of allFeatures.features.data) {
|
||||
indexedFeatures.set(f.properties.id, f)
|
||||
}
|
||||
indexisBuilt = true
|
||||
}
|
||||
|
||||
function getFeatureById(id) {
|
||||
if (!indexisBuilt) {
|
||||
buildIndex()
|
||||
}
|
||||
return indexedFeatures.get(id)
|
||||
}
|
||||
|
||||
const flayers: FilteredLayer[] = theme.layers.map((l) => new FilteredLayer(l))
|
||||
const perLayer = new PerLayerFeatureSourceSplitter(flayers, allFeatures)
|
||||
for (const [layerId, source] of perLayer.perLayer) {
|
||||
const layer = flayers.find((flayer) => flayer.layerDef.id === layerId).layerDef
|
||||
const targetZoomLevel = layer.source.geojsonZoomLevel ?? targetzoomLevel
|
||||
|
||||
if (layer.source.geojsonSource && layer.source.isOsmCacheLayer !== true) {
|
||||
console.log("Skipping layer ", layerId, ": not a caching layer")
|
||||
skippedLayers.add(layer.id)
|
||||
continue
|
||||
}
|
||||
const flayer: FilteredLayer = new FilteredLayer(layer)
|
||||
console.log(
|
||||
"Handling layer ",
|
||||
layerId,
|
||||
"which has",
|
||||
source.features.data.length,
|
||||
"features"
|
||||
)
|
||||
if (source.features.data.length === 0) {
|
||||
continue
|
||||
}
|
||||
const featureProperties: FeaturePropertiesStore = new FeaturePropertiesStore(source)
|
||||
|
||||
MetaTagging.addMetatags(
|
||||
source.features.data,
|
||||
{
|
||||
getFeaturesWithin: (_) => {
|
||||
return <any>[allFeatures.features.data]
|
||||
},
|
||||
getFeatureById: getFeatureById,
|
||||
},
|
||||
layer,
|
||||
theme,
|
||||
osmObjectDownloader,
|
||||
featureProperties,
|
||||
{
|
||||
includeDates: false,
|
||||
includeNonDates: true,
|
||||
evaluateStrict: 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(250)
|
||||
}
|
||||
|
||||
const createdTiles = []
|
||||
// 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
|
||||
const features = source.features.data
|
||||
const perBbox = GeoOperations.spreadIntoBboxes(features, targetZoomLevel)
|
||||
|
||||
for (let [tileIndex, features] of perBbox) {
|
||||
const bbox = BBox.fromTileIndex(tileIndex).asGeoJson({})
|
||||
console.log("Got tile:", tileIndex, layer.id)
|
||||
if (features.length === 0) {
|
||||
continue
|
||||
}
|
||||
const filteredTile = new FilteringFeatureSource(
|
||||
flayer,
|
||||
new StaticFeatureSource(features)
|
||||
)
|
||||
console.log(
|
||||
"Tile " +
|
||||
layer.id +
|
||||
"." +
|
||||
tileIndex +
|
||||
" contains " +
|
||||
filteredTile.features.data.length +
|
||||
" features after filtering (" +
|
||||
features.length +
|
||||
") features before"
|
||||
)
|
||||
if (filteredTile.features.data.length === 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
let strictlyCalculated = 0
|
||||
let featureCount = 0
|
||||
|
||||
for (const feature of features) {
|
||||
// Some cleanup
|
||||
|
||||
if (layer.calculatedTags !== undefined) {
|
||||
// Evaluate all the calculated tags strictly
|
||||
const calculatedTagKeys = layer.calculatedTags.map((ct) => ct[0])
|
||||
featureCount++
|
||||
const props = feature.properties
|
||||
for (const calculatedTagKey of calculatedTagKeys) {
|
||||
const strict = props[calculatedTagKey]
|
||||
|
||||
if (props.hasOwnProperty(calculatedTagKey)) {
|
||||
delete props[calculatedTagKey]
|
||||
}
|
||||
|
||||
props[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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
delete feature["bbox"]
|
||||
}
|
||||
|
||||
if (clip) {
|
||||
console.log("Clipping features")
|
||||
features = [].concat(
|
||||
...features.map((f: Feature) => GeoOperations.clipWith(<any>f, bbox))
|
||||
)
|
||||
}
|
||||
// Lets save this tile!
|
||||
const [z, x, y] = Tiles.tile_from_index(tileIndex)
|
||||
// console.log("Writing tile ", z, x, y, layerId)
|
||||
const targetPath = geoJsonName(targetdir + "_" + layerId, x, y, z)
|
||||
createdTiles.push(tileIndex)
|
||||
// This is the geojson file containing all features for this tile
|
||||
writeFileSync(
|
||||
targetPath,
|
||||
JSON.stringify(
|
||||
{
|
||||
type: "FeatureCollection",
|
||||
features,
|
||||
},
|
||||
null,
|
||||
" "
|
||||
)
|
||||
)
|
||||
console.log("Written tile", targetPath, "with", filteredTile.features.data.length)
|
||||
}
|
||||
|
||||
// All the tiles are written at this point
|
||||
// Only thing left to do is to create the index
|
||||
const path = targetdir + "_" + layerId + "_" + targetZoomLevel + "_overview.json"
|
||||
const perX = {}
|
||||
createdTiles
|
||||
.map((i) => Tiles.tile_from_index(i))
|
||||
.forEach(([z, x, y]) => {
|
||||
const key = "" + x
|
||||
if (perX[key] === undefined) {
|
||||
perX[key] = []
|
||||
}
|
||||
perX[key].push(y)
|
||||
})
|
||||
console.log("Written overview: ", path, "with ", createdTiles.length, "tiles")
|
||||
writeFileSync(path, JSON.stringify(perX))
|
||||
|
||||
// And, if needed, to create a points-only layer
|
||||
if (pointsOnlyLayers.indexOf(layer.id) >= 0) {
|
||||
const filtered = new FilteringFeatureSource(flayer, source)
|
||||
const features = filtered.features.data
|
||||
|
||||
const points = features.map((feature) => GeoOperations.centerpoint(feature))
|
||||
console.log("Writing points overview for ", layerId)
|
||||
const targetPath = targetdir + "_" + layerId + "_points.geojson"
|
||||
// This is the geojson file containing all features for this tile
|
||||
writeFileSync(
|
||||
targetPath,
|
||||
JSON.stringify(
|
||||
{
|
||||
type: "FeatureCollection",
|
||||
features: points,
|
||||
},
|
||||
null,
|
||||
" "
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function main(args: string[]) {
|
||||
console.log("Cache builder started with args ", args.join(" "))
|
||||
ReferencingWaysMetaTagger.enabled = false
|
||||
if (args.length < 6) {
|
||||
console.error(
|
||||
"Expected arguments are: theme zoomlevel targetdirectory lat0 lon0 lat1 lon1 [--generate-point-overview layer-name,layer-name,...] [--force-zoom-level z] [--clip]" +
|
||||
"--force-zoom-level causes non-cached-layers to be donwnloaded\n" +
|
||||
"--clip will erase parts of the feature falling outside of the bounding box"
|
||||
)
|
||||
return
|
||||
}
|
||||
const themeName = args[0]
|
||||
const zoomlevel = Number(args[1])
|
||||
console.log(
|
||||
"Target zoomlevel for the tiles is",
|
||||
zoomlevel,
|
||||
"; this can be overridden by the individual layers"
|
||||
)
|
||||
|
||||
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 lon0 = Number(args[4])
|
||||
const lat1 = Number(args[5])
|
||||
const lon1 = Number(args[6])
|
||||
const clip = args.indexOf("--clip") >= 0
|
||||
|
||||
if (isNaN(lat0)) {
|
||||
throw "The first number (a latitude) is not a valid number"
|
||||
}
|
||||
|
||||
if (isNaN(lon0)) {
|
||||
throw "The second number (a longitude) is not a valid number"
|
||||
}
|
||||
if (isNaN(lat1)) {
|
||||
throw "The third number (a latitude) is not a valid number"
|
||||
}
|
||||
|
||||
if (isNaN(lon1)) {
|
||||
throw "The fourth number (a longitude) is not a valid number"
|
||||
}
|
||||
|
||||
const tileRange = Tiles.TileRangeBetween(zoomlevel, lat0, lon0, lat1, lon1)
|
||||
|
||||
if (isNaN(tileRange.total)) {
|
||||
throw "Something has gone wrong: tilerange is NAN"
|
||||
}
|
||||
|
||||
if (tileRange.total === 0) {
|
||||
console.log("Tilerange has zero tiles - this is probably an error")
|
||||
return
|
||||
}
|
||||
|
||||
const theme = AllKnownLayouts.allKnownLayouts.get(themeName)
|
||||
if (theme === undefined) {
|
||||
const keys = Array.from(AllKnownLayouts.allKnownLayouts.keys())
|
||||
console.error("The theme " + themeName + " was not found; try one of ", keys)
|
||||
return
|
||||
}
|
||||
|
||||
theme.layers = theme.layers.filter(
|
||||
(l) =>
|
||||
Constants.priviliged_layers.indexOf(<any>l.id) < 0 && !l.id.startsWith("note_import_")
|
||||
)
|
||||
console.log("Layers to download:", theme.layers.map((l) => l.id).join(", "))
|
||||
|
||||
let generatePointLayersFor = []
|
||||
if (args[7] == "--generate-point-overview") {
|
||||
if (args[8] === undefined) {
|
||||
throw "--generate-point-overview needs a list of layers to generate the overview for (or * for all)"
|
||||
} else if (args[8] === "*") {
|
||||
generatePointLayersFor = theme.layers.map((l) => l.id)
|
||||
} else {
|
||||
generatePointLayersFor = args[8].split(",")
|
||||
}
|
||||
console.log(
|
||||
"Also generating a point overview for layers ",
|
||||
generatePointLayersFor.join(",")
|
||||
)
|
||||
}
|
||||
{
|
||||
const index = args.indexOf("--force-zoom-level")
|
||||
if (index >= 0) {
|
||||
const forcedZoomLevel = Number(args[index + 1])
|
||||
for (const layer of theme.layers) {
|
||||
layer.source.geojsonSource = "https://127.0.0.1/cache_{layer}_{z}_{x}_{y}.geojson"
|
||||
layer.source.isOsmCacheLayer = true
|
||||
layer.source.geojsonZoomLevel = forcedZoomLevel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let failed = 0
|
||||
do {
|
||||
try {
|
||||
const cachingResult = await downloadRaw(targetdir, tileRange, theme)
|
||||
failed = cachingResult.failed
|
||||
if (failed > 0) {
|
||||
await ScriptUtils.sleep(30000)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return
|
||||
}
|
||||
} while (failed > 0)
|
||||
|
||||
const extraFeatures = await downloadExtraData(theme)
|
||||
const allFeaturesSource = loadAllTiles(targetdir, tileRange, theme, extraFeatures)
|
||||
await sliceToTiles(allFeaturesSource, theme, targetdir, generatePointLayersFor, clip, zoomlevel)
|
||||
}
|
||||
|
||||
let args = [...process.argv]
|
||||
if (!args[1]?.endsWith("test/TestAll.ts")) {
|
||||
args.splice(0, 2)
|
||||
try {
|
||||
main(args)
|
||||
.then(() => console.log("All done!"))
|
||||
.catch((e) => console.error("Error building cache:", e))
|
||||
} catch (e) {
|
||||
console.error("Error building cache:", e)
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
# npm run generate:layeroverview
|
||||
cd ../..
|
||||
ts-node scripts/generateCache.ts postal_codes 8 /home/pietervdvn/Downloads/postal_codes 49.69606181911566 2.373046875 51.754240074033525 6.459960937499999 --generate-point-overview '*' --force-zoom-level 1
|
|
@ -655,6 +655,7 @@
|
|||
{"properties":{"name":"Greene County Orthoimagery (2022)","id":"Greene_OH_2022","url":"https://gis.greenecountyohio.gov/webgis2/rest/services/Aerials/Aerial_2022_Summer/MapServer/export?f=image&format=jpg&bbox={bbox}&bboxSR={wkid}&imageSR={wkid}&size={width},{height}&foo={proj}","attribution":{"required":false,"text":"Greene County, State of Ohio","url":"https://www.greenecountyohio.gov/"},"type":"wms","category":"historicphoto","max_zoom":23},"type":"Feature","geometry":{"coordinates":[[[-84.06204,39.85653],[-84.06161,39.84285],[-84.09735,39.84244],[-84.09652,39.80807],[-84.10545,39.80796],[-84.10369,39.73247],[-84.11258,39.73232],[-84.11066,39.64998],[-84.11956,39.64987],[-84.11781,39.57439],[-84.07344,39.575],[-84.07331,39.56812],[-83.98463,39.56928],[-83.98449,39.56243],[-83.91357,39.56331],[-83.91348,39.55645],[-83.79816,39.55778],[-83.79803,39.55092],[-83.70942,39.55188],[-83.70928,39.54499],[-83.66497,39.54548],[-83.66565,39.58664],[-83.65678,39.58673],[-83.65801,39.66223],[-83.64915,39.66231],[-83.65042,39.73781],[-83.64149,39.73789],[-83.64215,39.77907],[-83.69556,39.7785],[-83.69568,39.7854],[-83.73124,39.78501],[-83.73132,39.79188],[-83.75818,39.79169],[-83.75813,39.7985],[-83.82043,39.79775],[-83.82102,39.82521],[-83.8565,39.82479],[-83.85655,39.83164],[-83.93679,39.83069],[-83.93727,39.85129],[-84.02625,39.85016],[-84.02643,39.85702],[-84.06204,39.85653]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Putnam County Orthoimagery (2023)","id":"Licking_OH_2023","url":"https://apps.lickingcounty.gov/arcgis/rest/services/Basemaps/Imagery2023/MapServer/export?f=image&format=jpg&bbox={bbox}&bboxSR={wkid}&imageSR={wkid}&size={width},{height}&foo={proj}","attribution":{"required":false,"text":"Licking County, State of Ohio","url":"https://lickingcounty.gov/"},"type":"wms","category":"photo","max_zoom":23},"type":"Feature","geometry":{"coordinates":[[[-82.47752,40.24575],[-82.47607,40.2645],[-82.75072,40.27696],[-82.77362,39.97606],[-82.77941,39.97638],[-82.78238,39.93973],[-82.47333,39.92498],[-82.46314,39.93058],[-82.41846,39.92745],[-82.41897,39.92258],[-82.30121,39.91614],[-82.23414,39.9133],[-82.23164,39.95129],[-82.19885,39.95022],[-82.18284,40.23866],[-82.28095,40.24019],[-82.28094,40.2393],[-82.32857,40.23967],[-82.47752,40.24575]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Mercer County Orthoimagery (2021)","id":"Mercer_OH_2021","url":"https://gis.mercercountyohio.org/arcgis/rest/services/aerials/2021Aerials/ImageServer/WMTS/tile/1.0.0/aerials_2021Aerials/default/default028mm/{zoom}/{y}/{x}","attribution":{"required":false,"text":"Mercer County, State of Ohio","url":"https://www.mercercountyohio.org/"},"type":"tms","category":"photo","max_zoom":23},"type":"Feature","geometry":{"coordinates":[[[-84.80424,40.73458],[-84.80284,40.69342],[-84.81186,40.69324],[-84.804,40.46686],[-84.81308,40.46674],[-84.80896,40.34988],[-84.71927,40.35184],[-84.71892,40.34491],[-84.42307,40.35047],[-84.42324,40.35727],[-84.44126,40.35714],[-84.44143,40.36381],[-84.45019,40.36355],[-84.45482,40.50767],[-84.44538,40.50806],[-84.45259,40.73477],[-84.7681,40.72801],[-84.76828,40.73549],[-84.80424,40.73458]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Miami County Orthoimagery (2023)","id":"Miami_OH_2023","url":"https://tiles.arcgis.com/tiles/nKtC7LOvnaEyn6u8/arcgis/rest/services/Miami_Aerial_2023/MapServer/tile/{zoom}/{y}/{x}","attribution":{"required":false,"text":"Miami County, State of Ohio","url":"https://www.co.miami.oh.us/"},"type":"tms","category":"photo","max_zoom":21},"type":"Feature","geometry":{"coordinates":[[[-84.42878,39.91291],[-84.17028,39.91669],[-84.16969,39.88947],[-84.16083,39.88947],[-84.16062,39.88267],[-84.12498,39.88313],[-84.12484,39.87631],[-84.04463,39.87734],[-84.0458,39.92545],[-84.03683,39.92554],[-84.03851,40.00101],[-84.0295,40.00116],[-84.0314,40.08344],[-84.02244,40.08361],[-84.02417,40.15903],[-84.0152,40.15916],[-84.01573,40.18657],[-84.05152,40.18617],[-84.05172,40.19301],[-84.1501,40.19178],[-84.15016,40.1985],[-84.21292,40.19764],[-84.21305,40.20454],[-84.43671,40.20111],[-84.43642,40.18733],[-84.44533,40.18725],[-84.44515,40.18033],[-84.43621,40.18047],[-84.42878,39.91291]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Montgomery County Orthoimagery (2022)","id":"Montgomery_OH_2022","url":"https://gis.mcohio.org/arcgis/rest/services/AUDGIS_MrSID/MapServer/export?f=image&format=jpg&layers=show:0&bbox={bbox}&bboxSR={wkid}&imageSR={wkid}&size={width},{height}&foo={proj}","attribution":{"required":false,"text":"Montgomery County, State of Ohio","url":"https://www.mcohio.org/"},"type":"wms","category":"photo","max_zoom":21},"type":"Feature","geometry":{"coordinates":[[[-84.48184,39.58592],[-84.36654,39.58782],[-84.3575,39.58113],[-84.35686,39.55709],[-84.34356,39.5573],[-84.33985,39.58481],[-84.25116,39.58618],[-84.10894,39.5745],[-84.10981,39.61224],[-84.07863,39.61276],[-84.07897,39.62969],[-84.09699,39.62962],[-84.09682,39.63286],[-84.10532,39.6328],[-84.10635,39.66049],[-84.10189,39.66042],[-84.10343,39.71531],[-84.09871,39.71537],[-84.09966,39.75313],[-84.09081,39.75313],[-84.0918,39.79436],[-84.08283,39.79452],[-84.08343,39.8151],[-84.08781,39.81506],[-84.08785,39.81839],[-84.09236,39.81846],[-84.09249,39.82864],[-84.08807,39.82868],[-84.08828,39.83563],[-84.07043,39.83593],[-84.07039,39.83237],[-84.0526,39.83263],[-84.05291,39.8464],[-84.04845,39.84647],[-84.04932,39.88417],[-84.07146,39.88379],[-84.12764,39.90026],[-84.16098,39.89976],[-84.16184,39.92725],[-84.49139,39.92218],[-84.48184,39.58592]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Ohio Statewide Imagery Program","id":"OSIP","url":"https://geo1.oit.ohio.gov/arcgis/services/OSIP/OSIPIII_MostCurrent/ImageServer/WMSServer?LAYERS=0&STYLES=&CRS={proj}&BBOX={bbox}&FORMAT=image/jpeg&WIDTH={width}&HEIGHT={height}&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap","attribution":{"required":false,"text":"Ohio Statewide Imagery Program","url":"https://das.ohio.gov/technology-and-strategy/ogrip/projects/osip"},"type":"wms","category":"photo","min_zoom":8,"max_zoom":20},"type":"Feature","geometry":{"coordinates":[[[-83.1356,41.75081],[-83.13438,41.64959],[-83.44737,41.76038],[-84.82898,41.70637],[-84.84471,39.08477],[-84.74086,39.11164],[-84.64015,39.05545],[-84.49223,39.07255],[-84.34117,38.99922],[-84.22157,38.7812],[-84.08624,38.75421],[-83.9635,38.76403],[-83.74635,38.63385],[-83.65193,38.61172],[-83.54178,38.69283],[-83.46625,38.64614],[-83.39387,38.64368],[-83.30575,38.58466],[-83.14524,38.59942],[-83.00676,38.71002],[-82.91235,38.73212],[-82.8494,38.56006],[-82.73925,38.53545],[-82.57875,38.39745],[-82.29865,38.43198],[-82.26718,38.57236],[-82.16017,38.58712],[-82.16647,38.72475],[-82.19794,38.78856],[-82.12555,38.8278],[-82.11611,38.92336],[-82.02799,38.99922],[-81.9084,38.93315],[-81.95875,38.89397],[-81.9021,38.85477],[-81.73216,38.9258],[-81.72586,39.19461],[-81.54333,39.26288],[-81.515,39.35054],[-81.45521,39.38704],[-81.38912,39.31159],[-81.19399,39.37974],[-80.85095,39.625],[-80.58973,40.2812],[-80.58344,40.49933],[-80.6275,40.59021],[-80.51105,40.62127],[-80.50161,41.99939],[-81.10587,41.84484],[-81.39541,41.7369],[-81.72901,41.52048],[-82.0217,41.53462],[-82.49063,41.40492],[-82.68575,41.50634],[-82.64799,41.62408],[-82.75184,41.63584],[-82.76758,41.73925],[-82.8494,41.7463],[-82.89032,41.69462],[-82.89032,41.54404],[-82.95011,41.54404],[-83.0796,41.62936],[-83.08101,41.7511],[-83.1356,41.75081]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Ohio Statewide Imagery Program 1-Foot","id":"OSIP_1ft","url":"https://geo1.oit.ohio.gov/arcgis/services/OSIP/osip_best_avail_1ft/ImageServer/WMSServer?LAYERS=0&STYLES=&CRS={proj}&BBOX={bbox}&FORMAT=image/jpeg&WIDTH={width}&HEIGHT={height}&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap","attribution":{"required":false,"text":"Ohio Statewide Imagery Program","url":"https://das.ohio.gov/technology-and-strategy/ogrip/projects/osip"},"type":"wms","category":"photo","min_zoom":8,"max_zoom":20},"type":"Feature","geometry":{"coordinates":[[[-83.1356,41.75081],[-83.13438,41.64959],[-83.44737,41.76038],[-84.82898,41.70637],[-84.84471,39.08477],[-84.74086,39.11164],[-84.64015,39.05545],[-84.49223,39.07255],[-84.34117,38.99922],[-84.22157,38.7812],[-84.08624,38.75421],[-83.9635,38.76403],[-83.74635,38.63385],[-83.65193,38.61172],[-83.54178,38.69283],[-83.46625,38.64614],[-83.39387,38.64368],[-83.30575,38.58466],[-83.14524,38.59942],[-83.00676,38.71002],[-82.91235,38.73212],[-82.8494,38.56006],[-82.73925,38.53545],[-82.57875,38.39745],[-82.29865,38.43198],[-82.26718,38.57236],[-82.16017,38.58712],[-82.16647,38.72475],[-82.19794,38.78856],[-82.12555,38.8278],[-82.11611,38.92336],[-82.02799,38.99922],[-81.9084,38.93315],[-81.95875,38.89397],[-81.9021,38.85477],[-81.73216,38.9258],[-81.72586,39.19461],[-81.54333,39.26288],[-81.515,39.35054],[-81.45521,39.38704],[-81.38912,39.31159],[-81.19399,39.37974],[-80.85095,39.625],[-80.58973,40.2812],[-80.58344,40.49933],[-80.6275,40.59021],[-80.51105,40.62127],[-80.50161,41.99939],[-81.10587,41.84484],[-81.39541,41.7369],[-81.72901,41.52048],[-82.0217,41.53462],[-82.49063,41.40492],[-82.68575,41.50634],[-82.64799,41.62408],[-82.75184,41.63584],[-82.76758,41.73925],[-82.8494,41.7463],[-82.89032,41.69462],[-82.89032,41.54404],[-82.95011,41.54404],[-83.0796,41.62936],[-83.08101,41.7511],[-83.1356,41.75081]]],"type":"Polygon"}},
|
||||
|
@ -754,7 +755,7 @@
|
|||
{"properties":{"name":"Rio Mosaico 2019","id":"rio2019","url":"https://pgeo3.rio.rj.gov.br/arcgis/services/Imagens/Mosaico_2019/ImageServer/WMSServer?FORMAT=image/png&TRANSPARENT=TRUE&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap&LAYERS=0&STYLES=&CRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}","attribution":{"text":"Instituto Pereira Passos - Prefeitura da Cidade do Rio de Janeiro","url":"https://www.rio.rj.gov.br/web/ipp"},"type":"wms","category":"photo","min_zoom":4,"best":true},"type":"Feature","geometry":{"coordinates":[[[-43.59375,-23.09163],[-43.49213,-23.09163],[-43.49043,-23.05158],[-43.42965,-23.04994],[-43.42958,-23.03186],[-43.42655,-23.02912],[-43.35517,-23.02925],[-43.35275,-23.0322],[-43.35273,-23.04931],[-43.32336,-23.05052],[-43.32046,-23.07079],[-43.27378,-23.07079],[-43.27156,-23.05116],[-43.24219,-23.04994],[-43.24219,-23.02902],[-43.23053,-23.02917],[-43.22783,-23.03186],[-43.22776,-23.09163],[-43.11654,-23.09163],[-43.11722,-23.03416],[-43.14502,-23.03414],[-43.1481,-23.03106],[-43.14754,-22.98957],[-43.11653,-22.98732],[-43.11722,-22.90906],[-43.14502,-22.90904],[-43.14805,-22.90629],[-43.14923,-22.86457],[-43.14741,-22.82414],[-43.14433,-22.82106],[-43.08564,-22.82104],[-43.08564,-22.72164],[-43.16528,-22.72227],[-43.1653,-22.73907],[-43.16696,-22.7417],[-43.19618,-22.74253],[-43.1962,-22.76033],[-43.19771,-22.76284],[-43.25866,-22.76343],[-43.25873,-22.78092],[-43.26176,-22.78367],[-43.41453,-22.78622],[-43.41511,-22.80369],[-43.42776,-22.80537],[-43.45873,-22.80481],[-43.46052,-22.80212],[-43.46123,-22.78622],[-43.55392,-22.78749],[-43.5541,-22.79474],[-43.55793,-22.8019],[-43.5704,-22.80269],[-43.57864,-22.81028],[-43.58017,-22.81603],[-43.59306,-22.81851],[-43.59375,-22.84646],[-43.72215,-22.84891],[-43.73108,-22.85144],[-43.73374,-22.85711],[-43.75373,-22.85651],[-43.75466,-22.86261],[-43.75861,-22.86767],[-43.78738,-22.87297],[-43.78944,-22.87424],[-43.78951,-22.8854],[-43.79156,-22.8879],[-43.8121,-22.88817],[-43.8121,-22.93182],[-43.80039,-22.93188],[-43.78897,-22.93578],[-43.78326,-22.94066],[-43.77767,-22.94095],[-43.76014,-22.95055],[-43.75786,-22.98804],[-43.72977,-22.98767],[-43.72766,-22.99051],[-43.72696,-23.00888],[-43.69775,-23.00989],[-43.69606,-23.04994],[-43.68379,-23.0512],[-43.68033,-23.06129],[-43.68026,-23.07079],[-43.60544,-23.07086],[-43.60269,-23.07389],[-43.60267,-23.091],[-43.59375,-23.09163]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Rio Mosaico 2022","id":"rio2022","url":"https://pgeo3.rio.rj.gov.br/arcgis/services/Imagens/Mosaico_2022/ImageServer/WMSServer?FORMAT=image/png&TRANSPARENT=TRUE&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap&LAYERS=0&STYLES=&CRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}","attribution":{"text":"Instituto Pereira Passos - Prefeitura da Cidade do Rio de Janeiro","url":"https://www.rio.rj.gov.br/web/ipp"},"type":"wms","category":"photo","min_zoom":4},"type":"Feature","geometry":{"coordinates":[[[-43.59375,-23.09163],[-43.49213,-23.09163],[-43.49043,-23.05158],[-43.42965,-23.04994],[-43.42958,-23.03186],[-43.42655,-23.02912],[-43.35517,-23.02925],[-43.35275,-23.0322],[-43.35273,-23.04931],[-43.32336,-23.05052],[-43.32046,-23.07079],[-43.27378,-23.07079],[-43.27156,-23.05116],[-43.24219,-23.04994],[-43.24219,-23.02902],[-43.23053,-23.02917],[-43.22783,-23.03186],[-43.22776,-23.09163],[-43.11654,-23.09163],[-43.11722,-23.03416],[-43.14502,-23.03414],[-43.1481,-23.03106],[-43.14754,-22.98957],[-43.11653,-22.98732],[-43.11722,-22.90906],[-43.14502,-22.90904],[-43.14805,-22.90629],[-43.14923,-22.86457],[-43.14741,-22.82414],[-43.14433,-22.82106],[-43.08564,-22.82104],[-43.08564,-22.72164],[-43.16528,-22.72227],[-43.1653,-22.73907],[-43.16696,-22.7417],[-43.19618,-22.74253],[-43.1962,-22.76033],[-43.19771,-22.76284],[-43.25866,-22.76343],[-43.25873,-22.78092],[-43.26176,-22.78367],[-43.41453,-22.78622],[-43.41511,-22.80369],[-43.42776,-22.80537],[-43.45873,-22.80481],[-43.46052,-22.80212],[-43.46123,-22.78622],[-43.55392,-22.78749],[-43.5541,-22.79474],[-43.55793,-22.8019],[-43.5704,-22.80269],[-43.57864,-22.81028],[-43.58017,-22.81603],[-43.59306,-22.81851],[-43.59375,-22.84646],[-43.72215,-22.84891],[-43.73108,-22.85144],[-43.73374,-22.85711],[-43.75373,-22.85651],[-43.75466,-22.86261],[-43.75861,-22.86767],[-43.78738,-22.87297],[-43.78944,-22.87424],[-43.78951,-22.8854],[-43.79156,-22.8879],[-43.8121,-22.88817],[-43.8121,-22.93182],[-43.80039,-22.93188],[-43.78897,-22.93578],[-43.78326,-22.94066],[-43.77767,-22.94095],[-43.76014,-22.95055],[-43.75786,-22.98804],[-43.72977,-22.98767],[-43.72766,-22.99051],[-43.72696,-23.00888],[-43.69775,-23.00989],[-43.69606,-23.04994],[-43.68379,-23.0512],[-43.68033,-23.06129],[-43.68026,-23.07079],[-43.60544,-23.07086],[-43.60269,-23.07389],[-43.60267,-23.091],[-43.59375,-23.09163]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Jaraguá do Sul Ortomosaico 2020","id":"jaragua-do-sul-2020","url":"https://www.jaraguadosul.sc.gov.br/geo/ortomosaico2020/{zoom}/{x}/{y}.png","attribution":{"text":"Prefeitura de Jaraguá do Sul, SC","url":"https://sistemas.jaraguadosul.sc.gov.br/index.php?class=GeoWelcomeView"},"type":"tms","category":"photo","max_zoom":19},"type":"Feature","geometry":{"coordinates":[[[-49.25368,-26.26563],[-49.17549,-26.31065],[-49.16931,-26.35804],[-49.19403,-26.38449],[-49.19266,-26.42016],[-49.21051,-26.43676],[-49.21806,-26.47733],[-49.22562,-26.48471],[-49.24621,-26.48901],[-49.29634,-26.54185],[-49.30595,-26.58054],[-49.28106,-26.61953],[-49.23798,-26.61922],[-49.20433,-26.62966],[-49.17824,-26.61615],[-49.1645,-26.65237],[-49.13292,-26.64316],[-49.10408,-26.61063],[-49.10133,-26.58177],[-49.0876,-26.57993],[-49.08554,-26.55168],[-49.0567,-26.54615],[-49.05121,-26.51912],[-49.03404,-26.52219],[-49.01756,-26.51298],[-49.01138,-26.48287],[-49.02511,-26.45643],[-49.09515,-26.39863],[-49.10545,-26.39371],[-49.10477,-26.36972],[-49.13635,-26.33219],[-49.13841,-26.30265],[-49.16725,-26.26571],[-49.16725,-26.21336],[-49.19128,-26.21274],[-49.23454,-26.23061],[-49.23386,-26.25524],[-49.25368,-26.26563]]],"type":"Polygon"}},
|
||||
{"properties":{"name":"Bing Maps Aerial","id":"Bing","url":"https://ecn.t1.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=14296&pr=odbl&n=f","type":"bing","category":"photo","min_zoom":1,"max_zoom":22},"type":"Feature","geometry":null},
|
||||
{"properties":{"name":"Bing Maps Aerial","id":"Bing","url":"https://ecn.t1.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=14307&pr=odbl&n=f","type":"bing","category":"photo","min_zoom":1,"max_zoom":22},"type":"Feature","geometry":null},
|
||||
{"properties":{"name":"CyclOSM","id":"cyclosm","url":"https://{switch:a,b,c}.tile-cyclosm.openstreetmap.fr/cyclosm/{zoom}/{x}/{y}.png","attribution":{"text":"Rendering: CyclOSM (hosted by OpenStreetMap France) © Map data OpenStreetMap contributors","url":"https://www.cyclosm.org/"},"type":"tms","category":"osmbasedmap","max_zoom":20},"type":"Feature","geometry":null},
|
||||
{"properties":{"name":"Esri World Imagery","id":"EsriWorldImagery","url":"https://{switch:services,server}.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/{zoom}/{y}/{x}","attribution":{"required":true,"text":"Terms & Feedback","url":"https://wiki.openstreetmap.org/wiki/Esri"},"type":"tms","category":"photo","max_zoom":22,"default":true},"type":"Feature","geometry":null},
|
||||
{"properties":{"name":"Esri World Imagery (Clarity) Beta","id":"EsriWorldImageryClarity","url":"https://clarity.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/MapServer/tile/{zoom}/{y}/{x}","attribution":{"required":true,"text":"Terms & Feedback","url":"https://wiki.openstreetmap.org/wiki/Esri"},"type":"tms","category":"photo","max_zoom":22,"default":true},"type":"Feature","geometry":null},
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue