diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index d4d6fe8..6b36be5 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -15,6 +15,6 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 18.x + node-version: 20.x cache: 'npm' - run: npm install && npm run prettier-check && npm run build diff --git a/.gitignore b/.gitignore index b733034..cfee3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .vitepress/cache .vitepress/dist +.DS_Store + +node_modules \ No newline at end of file diff --git a/.vitepress/config.mts b/.vitepress/config.mts index f90e729..d671640 100644 --- a/.vitepress/config.mts +++ b/.vitepress/config.mts @@ -3,9 +3,19 @@ import { defineConfig } from "vitepress"; // https://vitepress.dev/reference/site-config export default defineConfig({ title: "Protomaps Docs", - head: [["link", { rel: "icon", type: "image/png", href: "/favicon.png" }]], + head: [ + ["link", { rel: "icon", type: "image/png", href: "/favicon.png" }], + ["link", { rel: "apple-touch-icon", type: "image/jpg", href:"https://protomaps.com//apple-touch-icon.jpg" }], + ["meta", { property: "og:image", content: "https://protomaps.com/docs_opengraph.jpg" }] + ], description: "Technical Documentation for Protomaps", cleanUrls: true, + markdown: { + theme: { + light: 'github-light-high-contrast', + dark: 'github-dark-high-contrast' + } + }, themeConfig: { logo: "/logo.svg", // https://vitepress.dev/reference/default-theme-config @@ -24,6 +34,7 @@ export default defineConfig({ items: [ { text: "What is Protomaps?", link: "/" }, { text: "Getting Started", link: "/guide/getting-started" }, + { text: "Security and Privacy", link: "/guide/security-privacy" }, ], }, { @@ -54,7 +65,8 @@ export default defineConfig({ { text: "AWS", link: "/deploy/aws" }, { text: "Cloudflare", link: "/deploy/cloudflare" }, { text: "Google Cloud", link: "/deploy/google-cloud" }, - { text: "Server (Caddy)", link: "/deploy/server" }, + { text: "Azure", link: "/deploy/azure" }, + { text: "Server", link: "/deploy/server" }, ], }, { @@ -63,10 +75,11 @@ export default defineConfig({ items: [ { text: "Downloads", link: "/basemaps/downloads" }, { text: "Basemap Layers", link: "/basemaps/layers" }, - { text: "Basemap Styles", link: "/basemaps/styles" }, + { text: "Basemap Flavors", link: "/basemaps/flavors" }, + { text: "Basemap Localization", link: "/basemaps/localization" }, + { text: "Building Tiles", link: "/basemaps/build" }, { text: "MapLibre GL", link: "/basemaps/maplibre" }, { text: "Leaflet", link: "/basemaps/leaflet" }, - { text: "OpenLayers", link: "/basemaps/openlayers" }, ], }, ], @@ -74,7 +87,7 @@ export default defineConfig({ socialLinks: [ { icon: "github", link: "https://github.com/protomaps" }, { icon: "mastodon", link: "https://mapstodon.space/@protomaps" }, - { icon: "twitter", link: "https://twitter.com/protomaps" }, + { icon: "bluesky", link: "https://bsky.app/profile/protomaps.com" }, ], search: { diff --git a/basemaps/build.md b/basemaps/build.md new file mode 100644 index 0000000..50d3a2c --- /dev/null +++ b/basemaps/build.md @@ -0,0 +1,64 @@ +# Building a custom basemap + +The Protomaps Basemap based on OpenStreetMap data is provided as a [free daily planet build](/basemaps/downloads), which can be downloaded in full, or extracted into sub-pyramids for certain areas. + +The pipeline to generate this daily basemap [is open source](https://github.com/protomaps/basemaps/tree/main/tiles) and based on the [Planetiler](https://github.com/onthegomap/planetiler) Java tiling engine. It can be run for your local city or country in minutes, or in about two hours for the planet on a high-end desktop or server. + +Advantages to generating basemaps yourself include: + +* **Data** - Build tiles from specific OpenStreetMap snapshots, such as up-to-the-minute data from [SliceOSM](https://slice.openstreetmap.us). +* **Customization** - modify the Java code to include custom tags. +* **Clipping** - build a custom, focused area map. Extracting an area from the daily planet build will include extra data in low zoom tiles, like in the below illustration: + +![extract vs clip](./extract_vs_clip.png) + +## Build a local map + +To start you will need: + +* a [Java Runtime Environment version 21+](https://github.com/onthegomap/planetiler/blob/main/CONTRIBUTING.md) and [Maven](https://maven.apache.org/install.html) installed. + +* An OpenStreetMap extract that covers your area of interest, such as an on-demand download from [SliceOSM](https://slice.openstreetmap.us) or a pre-generated download from [Geofabrik Downloads](https://download.geofabrik.de). + +* A GeoJSON administrative boundary for Łódź, Poland downloaded from the [Who's On First Spelunker](https://spelunker.whosonfirst.org/id/101913783). [Link to lodz.geojson](https://spelunker.whosonfirst.org/id/101913783/geojson) + +### Generate the map + +1. Create a checkout of the `basemaps` project and build the JAR. + +```sh +git clone https://github.com/protomaps/basemaps +cd basemaps/tiles +mvn clean package +``` + +2. Place your input OSM data into `data/sources` and run the tile generation JAR: + +```sh +cp my_area.osm.pbf data/sources/my_area.osm.pbf +java -jar target/protomaps-basemap-HEAD-with-deps.jar --clip=lodz.geojson --area=my_area --download +``` + +This will also download resources such as pre-processed OSM water and land polygons, [Natural Earth](https://naturalearthdata.com), and datasets for language support and ranking. + +3. Drag-and-drop your output `.pmtiles` to the [Basemaps Viewer at maps.protomaps.com](https://maps.protomaps.com): + +![extract vs clip](./lodz_viewer.png) + +## Build the planet + +The recommended system requirements for building a planet tileset in < 3 hours are: + +* CPU: As many CPU cores as possible. Recommended: Intel Core i9 series, AMD Ryzen 9 series, AWS `c7gd.8xlarge` or equivalent. +* RAM: 64GB of RAM. +* Storage: At least 1TB of NVMe SSD storage, or attached instance store on a VPS (not network-attached storage) + +Building the planet works the same way as before, but provide a Planet file from [planet.openstreetmap.org](http://planet.openstreetmap.org) as the `--area` argument, or `--osm_file` with a complete path and `--bounds=planet`. + +```sh +java -Xmx20g -jar target/protomaps-basemap-HEAD-with-deps.jar --nodemap-type=array --osm_path=/data/planet-latest.osm.pbf --output=/data/planet.pmtiles --bounds=planet --tmpdir=/var/scratch +``` + +* `-Xmx20g`: Give the Java runtime environment 20GB of heap space. +* `--nodemap-type=array`: a build option best for planet tile generation. +* `--tmpdir=/var/scratch`: ensure there is at least 512GB of scratch space. diff --git a/basemaps/downloads.md b/basemaps/downloads.md index 78dd317..4e66601 100644 --- a/basemaps/downloads.md +++ b/basemaps/downloads.md @@ -18,18 +18,34 @@ Please note that **URLs may change** and hotlinking to these downloads are disco ## Current Version -The Version 3 Protomaps basemap daily build channel is available at [maps.protomaps.com/builds](https://maps.protomaps.com/builds). +The Version 4 Protomaps basemap daily build channel is available at [maps.protomaps.com/builds](https://maps.protomaps.com/builds). This is compatible with `@protomaps/basemaps` style v4.0.0 and newer. + +[BLAKE3](https://github.com/BLAKE3-team/BLAKE3/releases/) hashes are provided for daily builds. Use `b3sum` to verify the integrity of your downloaded file. A mirror in the AWS `us-west-2` is available on [Source Cooperative (beta)](https://beta.source.coop) at the [protomaps/openstreetmap](https://beta.source.coop/repositories/protomaps/openstreetmap/) repository. This mirrors the most recent daily build only. +### Build History + +The daily builds bucket retains: + +* All builds for the past week. +* Weekly monday builds for the past month. +* The latest build for each version (major + minor + patch) beyond that. + ## Partial Downloads To download a cutout of a specific region, rather than the entire world map, see the CLI's [extract command](/pmtiles/cli#extract). If you don't need all 16 zoom levels of detail, use the `--maxzoom` option of `pmtiles extract`. Each additional zoom level roughly doubles the size of the file. -## Previous Version +## Terrain + +### Mapterhorn + +The [Mapterhorn](http://mapterhorn.com) project distributes Terrarium-encoded RGB tiles aggregated from multiple global data sources in PMTiles format. Download the full `.pmtiles` or get a partial download with `pmtiles extract` at the [Mapterhorn Data Access documentation](https://mapterhorn.com/data-access/). + +### Tilezen Joerd (legacy) -The version 2 basemap is `protomaps-basemap-opensource-20230408.pmtiles` +The [AWS Registry of Open Data](https://registry.opendata.aws/terrain-tiles/) hosts Terrarium-encoded RGB tiles generated by the [Joerd](https://github.com/tilezen/joerd) project. Below is a link of zooms 0 to 12 of this tileset, provided as-is. See the [Joerd docs](https://github.com/tilezen/joerd/blob/master/docs/attribution.md) for attribution requirements. -[https://r2-public.protomaps.com/protomaps-sample-datasets/protomaps-basemap-opensource-20230408.pmtiles](https://r2-public.protomaps.com/protomaps-sample-datasets/protomaps-basemap-opensource-20230408.pmtiles) +[terrarium-z12.pmtiles](https://r2-public.protomaps.com/protomaps-sample-datasets/terrarium-z12.pmtiles) [(preview)](https://pmtiles.io/?url=https%3A%2F%2Fr2-public.protomaps.com%2Fprotomaps-sample-datasets%2Fterrarium-z12.pmtiles#map=0.7/0/0) diff --git a/basemaps/extract_vs_clip.png b/basemaps/extract_vs_clip.png new file mode 100644 index 0000000..597ff95 Binary files /dev/null and b/basemaps/extract_vs_clip.png differ diff --git a/basemaps/flavors.md b/basemaps/flavors.md new file mode 100644 index 0000000..e725290 --- /dev/null +++ b/basemaps/flavors.md @@ -0,0 +1,59 @@ +--- +title: Basemap Flavors +outline: deep +--- + + + +# Basemap Flavors + +These examples use the preferred [MapLibre GL JS](/basemaps/maplibre) library. + +The `Flavor` TypeScript interface is the preferred way to customize the basemap style. See the shape of the interface at the [@protomaps/basemaps TypeScript docs](https://maps.protomaps.com/typedoc/interfaces/Flavor.html). + +A `Flavor` is a plain object of color definitions and optional properties such as font names, landcover shades and POI properties. You can define a `Flavor` yourself for a custom style, similar to a text editor color scheme, or use one of the default named flavors as a base. + +## Default Flavors + +These flavors are included as part of the `@protomaps/basemaps` package. + +### light + +A general-purpose basemap with icons. + + + +### dark + +A general-purpose basemap with icons. + + + +### white + +A flavor for data visualization. + + + +### grayscale + +A flavor for data visualization. + + + +### black + +A flavor for data visualization. + + + +## Overriding Defaults + +Use [ES6 spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) to override any part of the Flavor object. For example, to color buildings red: + +```ts +import { namedFlavor } from "@protomaps/basemaps" +let flavor = {...namedFlavor("light"),buildings:"red"} +``` diff --git a/basemaps/layers.md b/basemaps/layers.md index 433dda0..7267585 100644 --- a/basemaps/layers.md +++ b/basemaps/layers.md @@ -2,101 +2,410 @@ title: Basemap Layers outline: deep --- + # Basemap Layers -OpenStreetMap layers documentation. +The Protomaps basemap is built on [OpenStreetMap](https://openstreetmap.org) and [Natural Earth](https://naturalearthdata.com) data. It does not include all data and tags from OSM; instead it is designed to strike a balance between tile size and completeness, for use as a general-purpose context map. + +The organization of layers and tags is derived from the [open source Tilezen project](https://tilezen.readthedocs.io/en/latest/layers/). The scope of contents and choice of data inclusion at certain zoom levels is intended to mirror the reference implementations of Tilezen styles such as [Bubble Wrap](https://tangrams.github.io/bubble-wrap/). -::: warning -This section is under construction. +The current version is **Version 4**. -For the previous version of the layers, see [Layers Version 2](/basemaps/layers_v2) -::: +## Common Tags - +| Key | Values | Description | +| -------------------------------------------------- | ------- | ------------------------------------------ | +| `name`, `name*`, `name:*`, `pgf:name:*`, `script*` | string | see [Localization](/basemaps/localization) | +| `sort_rank` | integer | Importance ranking used for rendering | +| `min_zoom` | integer | Suggested zoom level to limit display | ## boundaries -| Key | Values | Description | -| ---------------------- | ----------------------------------------- | ----------- | -| `pmap:kind` | `country`, `region`, `county`, `locality` | | -| `pmap:kind_detail` | | | -| `pmap:min_admin_level` | | | -| `pmap:brk_a3` | | | -| `disputed` | boolean | | + + +| Key | Values | Description | +| ------------- | ----------------------------------------- | --------------------------------- | +| `kind` | `country`, `region`, `county`, `locality` | | +| `kind_detail` | integer | the minimum admin_level from OSM | +| `brk_a3` | | `brk_a3` value from Natural Earth | +| `disputed` | boolean | | ## buildings + -Buildings from OpenStreetMap. +Buildings and address points from OpenStreetMap. z0-14 contains merged buildings, even disconnected ones. z15+ contains individual OSM equivalent buildings. + +| Key | Values | Description | +| ------------------ | :--------------------------------------: | -----------------------------------------------------------: | +| `kind` | `address`, `building`, `building_part` | Whether it is an address point, whole building or one part. | +| `addr_housenumber` | string | Address number for `kind=address`. | +| `height` | number | May be quantized at low zoom levels. | +| `min_height` | number | May be quantized at low zoom levels. | +| `layer` | integer | Layer position relative to other buildings. | -| Key | Values | Description | -| ------------ | :---------------------------: | -------------------------------------------: | -| `pmap:kind` | `building`, `building_part` | Whether it is a whole building or one part. | -| `height` | number | May be quantized at low zoom levels. | -| `min_height` | number | May be quantized at low zoom levels. | -| `layer` | integer | Layer position relative to other buildings. | ## earth + + Polygons from the Natural Earth 50m `land` theme for z0-z4, 10m for z5, preprocessed land polygons from [OSMCoastline](https://osmdata.openstreetmap.de) for z6+. -| Key | Values | Description | -| ----------- | :-------: | -----------: | -| `pmap:kind` | `earth` | | +| Key | Values | Description | +| ------ | :-----: | ----------: | +| `kind` | `earth` | | -## landuse +## landcover -`kind` + -## natural +Polygons from the Daylight distribution's [landcover](https://daylightmap.org/2023/10/11/landcover.html) theme, for z0-z7. - +| Key | Values | Description | +| ------ | :---------------------------------------------------------------------------: | ----------: | +| `kind` | `barren`, `farmland`, `forest`, `glacier`, `grassland`, `scrub`, `urban_area` | | -## physical_line +_NOTE: It's recommended to pair with **natural** layer polygons in from OpenStreetMap at mid- and high-zooms._ -::: warning -physical_line will be deprecated in v4.0. -::: +## landuse -## physical_point + + +Polygons from OpenStreetMap, from a curated subset of `aeroway`, `amenity`, `area:aeroway`, `boundary`, `highway`, `landuse`, `leisure`, `man_made`, `natural`, `place`, `railway`, `tourism` tags, for all zooms. + +| Key | Values | Description | +| ------- | :-------: | ----------------------------------: | +| `kind` | See below | | +| `sport` | string | Which sports are played on a pitch. | + +### Kinds + +| Kind | +| ------------------- | +| `aerodrome` | +| `attraction` | +| `bare_rock` | +| `beach` | +| `cafe` | +| `camp_site` | +| `cemetery` | +| `college` | +| `commercial` | +| `dog_park` | +| `farmland` | +| `farmyard` | +| `footway` | +| `forest` | +| `garden` | +| `glacier` | +| `golf_course` | +| `grass` | +| `grocery` | +| `hospital` | +| `hotel` | +| `industrial` | +| `kindergarten` | +| `library` | +| `marina` | +| `meadow` | +| `military` | +| `national_park` | +| `nature_reserve` | +| `neighbourhood` | +| `orchard` | +| `other` | +| `park` | +| `pedestrian` | +| `pier` | +| `pitch` | +| `platform` | +| `playground` | +| `post_office` | +| `protected_area` | +| `railway` | +| `recreation_ground` | +| `residential` | +| `runway` | +| `sand` | +| `school` | +| `scrub` | +| `stadium` | +| `supermarket` | +| `taxiway` | +| `townhall` | +| `university` | +| `wetland` | +| `wood` | +| `zoo` | -::: warning -physical_point will be deprecated in v4.0. -::: +## places +Points from OpenStreetMap and Natural Earth, from a curated subset of place tags, for all zooms. -## places + -`kind` +| Key | Values | Description | +| ----------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ----------: | +| `kind` | `country`, `region`, `locality`, `macrohood`, `neighbourhood` | | +| `kind_detail` | `allotments`, `city`, `country`, `farm`, `hamlet`, `hamlet`, `isolated_dwelling`, `locality`, `neighbourhood`, `province`, `quarter`, `scientific_station`, `state`, `town`, `village` | | +| `capital` | string | | +| `population` | int | | +| `population_rank` | int | | +| `wikidata` | string | | ## pois -`kind` +Points from OpenStreetMap, from a curated subset of aeroway, amenity, attraction, boundary, craft, highway, historic, landuse, leisure, natural, railway, shop, tourism tags, for all zooms. + + + +| Key | Values | Description | +| ---------- | :-------: | ----------: | +| `kind` | See below | | +| `cuisine` | string | | +| `religion` | string | | +| `sport` | string | | +| `iata` | string | | + +_NOTE: The list of kind values is not comprehensive as some raw OSM tag values are passed through in the current version._ + +### Kinds + +| kind | icon | +| ------------------------ | ------------------------------------------------ | +| `aerodrome` | | +| `adult_gaming_centre` | | +| `airfield` | | +| `alpine_hut` | | +| `amusement_ride` | | +| `animal` | | +| `art` | | +| `artwork` | | +| `atm` | | +| `attraction` | | +| `atv` | | +| `baby_hatch` | | +| `bakery` | | +| `bbq` | | +| `beach` | | +| `beauty` | | +| `bed_and_breakfast` | | +| `bench` | | +| `bicycle_parking` | | +| `bicycle_rental` | | +| `bicycle_repair_station` | | +| `boat_storage` | | +| `bookmaker` | | +| `books` | | +| `bureau_de_change` | | +| `bus_stop` | | +| `butcher` | | +| `cafe` | | +| `camp_site` | | +| `car_parts` | | +| `car_rental` | | +| `car_repair` | | +| `car_sharing` | | +| `car_wash` | | +| `car` | | +| `carousel` | | +| `cemetery` | | +| `chalet` | | +| `charging_station` | | +| `childcare` | | +| `clinic` | | +| `clothes` | | +| `college` | | +| `computer` | | +| `convenience` | | +| `customs` | | +| `dentist` | | +| `district` | | +| `doctors` | | +| `dog_park` | | +| `drinking_water` | | +| `emergency_phone` | | +| `fashion` | | +| `firepit` | | +| `fire_station` | | +| `fishing` | | +| `florist` | | +| `forest` | | +| `fuel` | | +| `gambling` | | +| `garden_centre` | | +| `gift` | | +| `golf_course` | | +| `golf` | | +| `greengrocer` | | +| `grocery` | | +| `guest_house` | | +| `hairdresser` | | +| `hanami` | | +| `harbourmaster` | | +| `hifi` | | +| `hospital` | | +| `hostel` | | +| `hotel` | | +| `hunting_stand` | | +| `information` | | +| `jewelry` | | +| `karaoke_box` | | +| `karaoke` | | +| `landmark` | | +| `library` | | +| `life_ring` | | +| `lottery` | | +| `marina` | | +| `maze` | | +| `memorial` | | +| `military` | | +| `mobile_phone` | | +| `money_transfer` | | +| `motorcycle_parking` | | +| `motorcycle` | | +| `national_park` | | +| `nature_reserve` | | +| `naval_base` | | +| `newsagent` | | +| `optician` | | +| `park` | | +| `parking` | | +| `peak` | | +| `perfumery` | | +| `picnic_site` | | +| `picnic_table` | | +| `pitch` | | +| `playground` | | +| `post_box` | | +| `post_office` | | +| `ranger_station` | | +| `recycling` | | +| `roller_coaster` | | +| `sanitary_dump_station` | | +| `school` | | +| `scuba_diving` | | +| `shelter` | | +| `ship_chandler` | | +| `shower` | | +| `slipway` | | +| `snowmobile` | | +| `social_facility` | | +| `stadium` | | +| `station` | | +| `stationery` | | +| `studio` | | +| `summer_toboggan` | | +| `supermarket` | | +| `swimming_area` | | +| `taxi` | | +| `telephone` | | +| `tobacco` | | +| `toilets` | | +| `townhall` | | +| `trail_riding_station` | | +| `travel_agency` | | +| `university` | | +| `viewpoint` | | +| `waste_basket` | | +| `waste_disposal` | | +| `water_point` | | +| `water_slide` | | +| `watering_place` | | +| `wayside_cross` | | +| `wilderness_hut` | | +| `zoo` | | ## roads -`kind` +Linear transportation features designed for movement, including highways, streets, +railways and piers from OpenStreetMap. This layer represents built infrastructure including railways. Refer to the [transit](#transit) layer for passenger services. + + + +| Key | Values | Description | +| -------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | ----------: | +| `kind` | See kinds below | | +| `kind_detail` | `motorway`, `motorway_link`, `trunk`, `trunk_link`, `primary`, `primary_link`, `secondary`, `secondary_link`, `tertiary`, `tertiary_link`, `residential`, `service`, `unclassified`, `road`, `raceway`, `pedestrian`, `track`, `path`, `cycleway`, `bridleway`, `steps`, `corridor`, `sidewalk`, `crossing`, `driveway`, `parking_aisle`, `alley`, `drive-through`, `emergency_access`, `utility`, `irrigation`, `slipway`, `cable_car`, `pier`, `runway`, `taxiway`, `disused`, `funicular`, `light_rail`, `miniature`, `monorail`, `narrow_gauge`, `preserved`, `subway`, `tram` | | +| `ref` | string | | +| `shield_text_length` | int | | +| `network` | string | | +| `oneway` | string | | +| `service` | `siding`, `crossover`, `yard` | | +| `is_link` | boolean | | +| `is_tunnel` | boolean | | +| `is_bridge` | boolean | | + +### Kinds + +| kind | +| ------------ | +| `highway` | +| `major_road` | +| `minor_road` | +| `path` | +| `aerialway` | +| `ferry` | +| `pier` | +| `rail` | +| `aeroway` | ## transit -`kind` +Lines representing scheduled passenger services suitable for rendering on the map, even at lower zoom levels. For physical infrastructure, like highways and railways, see the [roads](#roads) layer. + +This layer is currently empty. + +| Key | Values | Description | +| ------------- | :----: | ----------: | +| `kind_detail` | | | +| `ref` | string | | +| `network` | string | | +| `layer` | int | | +| `route` | string | | +| `service` | string | | ## water -Polygons from the Natural Earth 50m `lakes` and `ocean` themes for z0-z4, 10m for z5, preprocessed land polygons from [OSMCoastline](https://osmdata.openstreetmap.de) for z6+. + + +* Polygons, lines and point labels from OpenStreetMap. +* Polygons from the Natural Earth 50m `lakes` and `ocean` themes for z0-z4, 10m for z5, preprocessed land polygons from [OSMCoastline](https://osmdata.openstreetmap.de) for z6+. -| Key | Values | Description | -| ------------------ | :------------------------------------------: | -----------: | -| `pmap:kind` | `water`, `lake`, `playa`, `ocean`, `other` | | -| `pmap:kind_detail` | | | -| `reservoir` | | | -| `alkaline` | | | -| `intermittent` | | | -| `bridge` | | | -| `tunnel` | | | -| `layer` | | | +| Key | Values | Description | +| -------------- | :---------------------------------------------------------------------------------------------: | ----------: | +| `kind` | `water`, `lake`, `playa`, `ocean`, `other` | | +| `kind_detail` | `basin`, `canal`, `ditch`, `dock`, `drain`, `lake`, `reservoir`, `river`, `riverbank`, `stream` | | +| `reservoir` | boolean | | +| `alkaline` | boolean | | +| `intermittent` | boolean | | +| `bridge` | string | | +| `tunnel` | string | | +| `layer` | int | | diff --git a/basemaps/leaflet.md b/basemaps/leaflet.md index 80962c6..267ccb6 100644 --- a/basemaps/leaflet.md +++ b/basemaps/leaflet.md @@ -8,18 +8,23 @@ outline: deep The simplest way to include a map in your application via script includes tag: ```js -// check for the latest version on github... - + ``` -## Themes +To use with a bundler: -The `theme` option must be one of `light`, `dark`, `white`, `grayscale`, `black`. +``` +npm add protomaps-leaflet +``` + +## Customization + +The `flavor` option must be one of `light`, `dark`, `white`, `grayscale`, `black`. -This will assume the set of basemap layers described at [Basemap Layers](/basemaps/layers). +The `lang` option can be one of the [supported languages](/basemaps/localization). diff --git a/basemaps/localization.md b/basemaps/localization.md new file mode 100644 index 0000000..b271ae6 --- /dev/null +++ b/basemaps/localization.md @@ -0,0 +1,300 @@ +--- +title: Basemap Localization +outline: deep +--- + + +# Basemap Localization + +Protomaps has several localization options for names used in text labels. + + + +## Local Names + +Protomaps follows OpenStreetMaps's convention where a features's primary name value is is the most common name in the local language(s). + +In practice, this is most often a single name value like: + +- `London` the locality is represented as a simple key, value pair: `name` = `London` + +However, many places have more than one common local languages and Protomaps passes thru OpenStreetMap's convention of concatenating multiple names with a `/` or `-` deliminator into a single name value, like: + +- `Switzerland` the country is represented as a complex key, value pair: `name` = `Schweiz/Suisse/Svizzera/Svizra` + +For transnational places involving many countries and languages, like `sea` features, the default name value can get quite long and unwiedly! + +### `name`, `name2`, and `name3` + +A script or writing system is the way how languages are written. For example, English uses the Latin script, Greek uses the Greek script, and Chinese uses the Han script. + +If a name from OpenStreetMap, which is the de-facto primary local name, contains text in more than one script, then Protomaps breaks up the name into segments. There can be up to 3 segments: `name`, `name2`, and `name3`. Each segment should have a unique script. + +Protomaps stores the scripts used for `name`, `name2`, and `name3` in separate script tags called `script`, `script2`, and `script3`. + +If `script*` is not present on a name, then it means that the name uses the `Latin` script. + +Sometimes segmentation into single scripts fails due for example inconsistent usage of alphabets. In that case `script` is set to `Mixed`. + +In Japanese, the `Han`, `Hiragana`, and `Katakana` scripts are often mixed in one name. Should any two of these scripts appear in a name we set `script` to `Mixed-Japanese`. + +Let us look at some examples: + +#### Zürich +``` +name = Zürich +(script absent) +(name2 absent) +(script2 absent) +(name3 absent) +(script3 absent) +``` + +The OpenStreetMap name for "Zürich" only uses the Latin script so we export `name` and but omit `script` (implying the script of the `name` is `Latin`). + +#### 香港 Hong Kong +``` +name = 香港 +script = Han +name2 = Hong Kong +(script2 absent) +(name3 absent) +(script3 absent) +``` + +The OpenStreetMap name for Hong Kong is "香港 Hong Kong". We break this up into `name` and `name2` in Protomaps. Since the script of `name2` is `Latin`, the `script2` tag is omitted. The script of `name` is `Han` which is encoded in `script`. + +#### Casablanca ⵜⵉⴳⵎⵉ ⵜⵓⵎⵍⵉⵍⵜ الدار البيضاء +``` +name = Casablanca +(script absent) +name2 = ⵜⵉⴳⵎⵉ ⵜⵓⵎⵍⵉⵍⵜ +script2 = Tifinagh +name3 = الدار البيضاء +script3 = Arabic +``` + +Casablanca in OpenStreetMap is stored as "Casablanca ⵜⵉⴳⵎⵉ ⵜⵓⵎⵍⵉⵍⵜ الدار البيضاء". In Protomaps we break this label up into 3 parts. Since the text in `name` uses the `Latin` script, we omit the `script` tag. The other two parts use the Tifinagh and Arabic script. + +## Translated Names + +Protomaps supports name translations for 41 languages. Translated names are stored with a `name:{language_code}` formatting like OpenStreetMap. + +More than 100 countries recognize 2 or more official languages – and some like Bolivia, India, and South Africa recognize more than 10 official languages each! + +A single official language is used in most remaining countries. There are a few countries where no official language has been designated – like in the United States. + +Going back to our London example, English is the predominant (unofficial) language in the United Kingdom: + +- `name:en` = `London` + +Extending our London example, many other languages include [exonym and endonym](https://simple.wikipedia.org/wiki/Exonym_and_endonym#:~:text=An%20exonym%20is%20a%20name,place%20and%20language%20call%20themselves.) values in both Latin script and non-Latin scripts: + +- `name:ar` = `لندن` +- `name:de` = `London` +- `name:es` = `Londres` +- `name:fr` = `Londres` +- `name:it` = `Londra` +- `name:pt` = `Londres` +- `name:zh-Hans` = `伦敦` +- `name:zh-Hant` = `倫敦` +- _... many other localized values..._ + +Going back to our Switzerland example, each of the official languages would have a specific language name value (in this case German `de`, French `fr`, Italian `it`, and Romansh `rm`), like: + +- `name:de` = `Schweiz` +- `name:fr` = `Suisse` +- `name:it` = `Svizzera` +- `name:rm` = `Svizra` +- _... many other localized values..._ + +Extending our Switzerland example with exonym and endonym from other languages: + +- `name:ar` = `سويسرا` +- `name:en` = `Switzerland` +- `name:es` = `Switzerland` +- `name:pt` = `Suíça` +- `name:zh-Hans` = `瑞士` +- `name:zh-Hant` = `瑞士` +- _... many other localized values..._ + + +### List of Supported Languages + +| Language | Native Name | `name:*` Tag | Script | +| ----- | ----- | ----- | ----- | +| Arabic | اَلْعَرَبِيَّةُ | `name:ar` | `Arabic` | +| Bulgarian | български | `name:bg` | `Cyrillic` | +| Chinese (Simplified) | 中文 汉语 | `name:zh-Hans` | `Han` | +| Chinese (Traditional) | 中文 漢語 | `name:zh-Hant` | `Han` | +| Croatian | hrvatski | `name:hr` | `Latin` | +| Czech | čeština | `name:cs` | `Latin` | +| Danish | dansk | `name:da` | `Latin` | +| Dutch | Nederlands | `name:nl` | `Latin` | +| English | English | `name:en` | `Latin` | +| Estonian | eesti keel | `name:et` | `Latin` | +| Finnish | suomi | `name:fi` | `Latin` | +| French | français | `name:fr` | `Latin` | +| German | Deutsch | `name:de` | `Latin` | +| Greek | Νέα Ελληνικά | `name:el` | `Greek` | +| Hebrew | עברית | `name:he` | `Hebrew` | +| Hindi | हिन्दी | `name:hi` | `Devanagari` | +| Hungarian | magyar | `name:hu` | `Latin` | +| Indonesian | bahasa Indonesia | `name:id` | `Latin` | +| Irish | Gaeilge | `name:ga` | `Latin` | +| Italian | italiano | `name:it` | `Latin` | +| Japanese | 日本語 | `name:ja` | `Han`, `Katakana`, `Hiragana`, `Mixed-Japanese` | +| Korean | 한국어 | `name:ko` | `Hangul` | +| Latvian | latviešu valoda | `name:lv` | `Latin` | +| Lithuanian | lietuvių kalba | `name:lt` | `Latin` | +| Maltese | lingwa Maltija | `name:mt` | `Latin` | +| Marathi | मराठी | `name:mr` | `Devanagari` | +| Nepali | नेपाली | `name:ne` | `Devanagari` | +| Norwegian | norsk | `name:no` | `Latin` | +| Persian | فارسی | `name:fa` | `Arabic` | +| Polish | Język polski | `name:pl` | `Latin` | +| Portuguese | português | `name:pt` | `Latin` | +| Romanian | român | `name:ro` | `Latin` | +| Russian | русский язык | `name:ru` | `Cyrillic` | +| Slovak | slovenský | `name:sk` | `Latin` | +| Slovenian | slovenski | `name:sl` | `Latin` | +| Spanish | español | `name:es` | `Latin` | +| Swedish | svenska | `name:sv` | `Latin` | +| Turkish | Türkçe | `name:tr` | `Latin` | +| Ukrainian | Українська мова | `name:uk` | `Cyrillic` | +| Urdu | اردو | `name:ur` | `Arabic` | +| Vietnamese | Tiếng Việt | `name:vi` | `Latin` | + +NOTE: `Mixed-Japanese` is a custom `script` value used for labels that contain Hiragana or Katakana mixed with a second or third script. In Japanese, these two scripts often appear in combination with others. + +NOTE 2 : Values in `script*` follow the [Unicode Standard Annex #24: Script Names](https://www.unicode.org/reports/tr24/). + +## Styling + +For each supported language, Protomaps distributes a localized MapLibre style.json file which shows labels in a target language. Country labels are only shown in the target language, place and street labels can have multiple languages. + +The following set of rules is used: + +- Show local names only if they use a different script than the target language +- If the target language is not available, fallback to name:en if the local script is not Latin +- Hide text in scripts that cannot be rendered correctly by MapLibre, such as Khmer or Bengali + +### Example: Milano + +For a map localized to English, we only use `name:en = Milan` since the local `name = Milano` uses the Latin script which is used in English as well. The label would be: + +``` +Milan +``` + +For a map localized to Greek, we would use `name:el = Μιλάνο` in the first line and since that is a different script from Latin, we would also include the local `name = Milano` in the second line: + +``` +Μιλάνο +Milano +``` + +## Positioned glyph font `pgf:name:*` values + +Protomaps adds additional names for a small set of language scripts, currently just the `Devanagari` script used for Hindi (`name:hi` and `pgf:name:hi`) and related languages. + +Rendering text in web browsers works for almost all languages and scripts and feels like magic. However, specialized map renderers like MapLibre have to reimplement text rendering and text layout which is complicated when text needs to be curved along linear map features instead of placed only horizontally or vertically. MapLibre normally assumes a one-to-one mapping between glyphs and Unicode codepoints that also exist in MapLibre font files (aka "font stacks") to accomplish the layout for a large but limited number of scripts. Plugins have been developed to extend MapLibre for **right-to-left** scripts like Arabic and Hebrew, and MapLibre has built-in support for **CJK scripts** like Chinese, Japanese, and Korean. + +To facilitate Protomap's support of additional, non-supported scripts in MapLibre (like the Devanagari script used by the Hindi language), Protomaps exports names with "positioned glyphs" so MapLibre can use codepoints as indices of positioned glyphs in an additional custom "font stack". While the raw `pgf:name:*` values look like gibberish when inspecting the raw values, they render correctly in MapLibre to the end user. + +See more: + +- [Traditional MapLibre Text Rendering](https://oliverwipfli.ch/about-text-rendering-in-maplibre-2023-10-17/) +- [Devanagari Positioned Glyph Fonts](https://oliverwipfli.ch/devanagari-in-the-protomaps-basemap-with-a-positioned-glyph-font-for-maplibre-2024-06-30/) + + +#### MapLibre supported scripts and languages + +| Script | Languages | +| ------- | ---------| +| `Latin` | AFRIKAANS, ALBANIAN, AZERBAIJANI (also `Cyrillic`, `Arabic`), BASQUE, BOSNIAN (also `Cyrillic`), , CATALAN, CROATIAN, CZECH, DANISH, DUTCH, ENGLISH, ENGLISH (AUSTRALIAN), ENGLISH (GREAT BRITAIN), ESTONIAN, FINNISH, FILIPINO, FRENCH, FRENCH (CANADA), GALICIAN, GERMAN, HUNGARIAN, ICELANDIC, INDONESIAN, ITALIAN, KAZAKH (also `Latin`, `Arabic`, `Cyrillic`), LATVIAN, LITHUANIAN, MALAY (also `Arabic`, `Thai`), NORWEGIAN, POLISH, PORTUGUESE, PORTUGUESE (BRAZIL), PORTUGUESE (PORTUGAL), ROMANIAN, SERBIAN (also `Cyrillic`), SLOVAK (also `Cyrillic`), SLOVENIAN, SPANISH, SPANISH (LATIN AMERICA), SWAHILI, SWEDISH, TURKISH, UZBEK (also `Cyrillic`, `Arabic`), VIETNAMESE, ZULU | +| `Arabic` | ARABIC, FARSI, URDU, KAZAKH (also `Cyrillic`, `Latin`), KYRGYZ (also `Cyrillic`) | +| `Cyrillic` | BELARUSIAN, BULGARIAN (also `Latin`), KAZAKH (also `Latin`, `Arabic`), KYRGYZ (also `Arabic`), MACEDONIAN, MONGOLIAN, RUSSIAN, SERBIAN (also `Latin`), UKRAINIAN | +| `Han` | CHINESE, CHINESE (SIMPLIFIED), CHINESE (HONG KONG), CHINESE (TRADITIONAL) | +| `Amharic` | AMHARIC | +| `Armenian` | ARMENIAN | +| `Hangul` | KOREAN | +| `Hebrew` | HEBREW | +| `Japanese` | JAPANESE | +| `Georgian` | GEORGIAN | +| `Greek` | GREEK | +| `Mongolian` | MONGOLIAN (also `Cyrillic`) | + +NOTE: Right-to-left scripts and languages like Arabic and Hebrew requires a special [RTL text MapLibre plugin](https://maplibre.org/maplibre-gl-js/docs/examples/mapbox-gl-rtl-text/). + +#### MapLibre partial support + +Requires paired positioned glyph font [font stack](https://maplibre.org/maplibre-style-spec/glyphs/) paired with `pgf:name:*` values. The PGF fontstacks used by the Protomaps basemaps are available at https://github.com/protomaps/basemaps-assets/tree/main/fonts. + +| Script | Languages | +| ------- | ---------| +| `Devanagari` | HINDI, MARATHI, NEPALI | + +#### MapLibre no support + +| Script | Languages | +| ------- | ---------| +| `Gujarati` | GUJARATI | +| `Kannada` | KANNADA | +| `Bengali` | BENGALI | +| `Burmese` | BURMESE | +| `Khmer` | KHMER | +| `Lao` | LAO | +| `Malayalam` | MALAYALAM | +| `Punjabi` | PUNJABI | +| `Sinhalese` | SINHALESE | +| `Tamil` | TAMIL | +| `Telugu` | TELUGU | +| `Thai` | THAI + +_NOTE: This is a partial listing of scripts and languages._ + +These non-supported MapLibre languages are primarily found in India and countries in south-east Asia. + +## Dual Language Labels + +With the data present in the tiles it is possible to create dual language labels, i.e., labels in two target languages. + +For example, to localize a map to Dutch (nl) and French (fr), one can use the following json snippet in a MapLibre Style: + +```json +"text-field": [ + "case", + [ + "all", + ["has", "name:nl"], + ["has", "name:fr"], + ], + // both languages are present + [ + "case", + ["==", ["get", "name:nl"], ["get", "name:fr"]], + // both languages are identical, only show one + ["get", "name:nl"], + // languages not identical, show both + [ + "format", + ["get", "name:nl"], {}, + "\n", {}, + ["get", "name:fr"], {}, + ], + ], + [ + "all", + ["!", ["has", "name:nl"]], + ["!", ["has", "name:fr"]], + ], + // none of the languages is present, use default + ["get", "name"], + // only one language is present + ["coalesce", "name:nl", "name:fr"], +] +``` + diff --git a/basemaps/lodz_viewer.png b/basemaps/lodz_viewer.png new file mode 100644 index 0000000..af61681 Binary files /dev/null and b/basemaps/lodz_viewer.png differ diff --git a/basemaps/maplibre.md b/basemaps/maplibre.md index cf5823a..1cf7a2a 100644 --- a/basemaps/maplibre.md +++ b/basemaps/maplibre.md @@ -5,20 +5,58 @@ outline: deep # Basemaps for MapLibre +## Assets -The `protomaps-themes-base` NPM module contains basemap layer definitions compatible with OpenStreetMap downloads from Protomaps. +To render a full basemap, you'll need not only a style and a tileset, but also MapLibre [fontstack](https://maplibre.org/maplibre-style-spec/glyphs/) and [spritesheet](https://maplibre.org/maplibre-style-spec/sprite/) assets. + +The assets referenced by the `glyphs` and `sprite` style properties can be downloaded as ZIP files at the [basemaps-assets](http://github.com/protomaps/basemaps-assets) repository, if you need to host them yourself or offline. + +### Fonts + +The `glyphs` key references a URL hosting pre-compiled fontstacks, required for displaying text labels in MapLibre. Fontstacks can be created with the [font-maker](https://github.com/maplibre/font-maker) tool. + +```js +glyphs:'https://protomaps.github.io/basemaps-assets/fonts/%7Bfontstack%7D/%7Brange%7D.pbf' +``` + +When a style layer defines a `text-font` like `Noto Sans Regular`, this will create requests for a URL like `https://protomaps.github.io/basemaps-assets/fonts/Noto%20Sans%20Regular/0-255.pbf`. + + +You can view a list of available fonts [in the GitHub repository](https://github.com/protomaps/basemaps-assets/tree/main/fonts). + +### Sprites + +The `sprite` key references a URL specific to one of [the default flavors](/basemaps/flavors): + +```js +sprite: "https://protomaps.github.io/basemaps-assets/sprites/v4/light" +``` + +These are required for townspots, highway shields and point of interest icons. + +## Loading styles as JSON + +Because [MapLibre styles](https://maplibre.org/maplibre-style-spec/) are JSON documents, the simplest way to define a style in your application is with static JSON. You can use the `Get style JSON` feature of [maps.protomaps.com](https://maps.protomaps.com) to generate static JSON for a specific flavor and style package version. + +## Creating styles programatically + +For more control and less code, you can add use the [`@protomaps/basemaps`](https://www.npmjs.com/package/@protomaps/basemaps) NPM package as a dependency. + +### Using the npm package ```bash -npm install protomaps-themes-base +npm install @protomaps/basemaps ``` + ```js -import layers from 'protomaps-themes-base'; +import { layers, namedFlavor } from '@protomaps/basemaps'; ``` ```js style: { - version:8, + version: 8, glyphs:'https://protomaps.github.io/basemaps-assets/fonts/%7Bfontstack%7D/%7Brange%7D.pbf', + sprite: "https://protomaps.github.io/basemaps-assets/sprites/v4/light", sources: { "protomaps": { type: "vector", @@ -27,21 +65,26 @@ style: { attribution: 'Protomaps © OpenStreetMap' } }, - layers: layers("protomaps","light") + layers: layers("protomaps",namedFlavor("light"),{lang:"en"}) } ``` -the default export from `protomaps-themes-base` is a function that takes 2 arguments: +the `layers` from `@protomaps/basemaps` is a function that takes 3 arguments: -* the source name of the basemap. +* the source name of the basemap, like `protomaps` in the `sources` example above. -* the theme, one of `light`, `dark`, `white`, `black`, `grayscale` or `debug`. +* A [flavor object](/basemaps/flavors); the defaults can be fetched `namedFlavor` with `light`, `dark`, `white`, `black`, `grayscale`. -## Fonts +* An options object: to display labels. pass a `lang` key. Pass `labelsOnly` to display only labels. -The fonts referenced by the `glyphs` style key can be downloaded as a ZIP at the [basemaps-assets](http://github.com/protomaps/basemaps-assets) GitHub repository. +### Using a CDN -Valid font names are: `Noto Sans Regular`, `Noto Sans Medium`, `Noto Sans Italic` +Loading the `@protomaps/basemaps` package from NPM will define the `basemaps` global variable. -Prior to version 2.0.0-alpha.3, the Glyphs URL was `https://cdn.protomaps.com/fonts/pbf/{fontstack}/{range}.pbf`. +```html + +``` +```js +layers: basemaps.layers("protomaps",basemaps.namedFlavor("light"),{lang:"en"}) +```` diff --git a/basemaps/openlayers.md b/basemaps/openlayers.md deleted file mode 100644 index 24005b1..0000000 --- a/basemaps/openlayers.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Basemaps for OpenLayers -outline: deep ---- - -# Basemaps for OpenLayers - -::: warning -This section is under construction. -::: \ No newline at end of file diff --git a/basemaps/styles.md b/basemaps/styles.md deleted file mode 100644 index ba5263a..0000000 --- a/basemaps/styles.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Basemap Styles -outline: deep ---- - -# Basemap Styles - -::: warning -This section is under construction. -::: \ No newline at end of file diff --git a/components/CostCalculator.vue b/components/CostCalculator.vue index b251b03..5cd69bb 100644 --- a/components/CostCalculator.vue +++ b/components/CostCalculator.vue @@ -40,14 +40,17 @@ const hostedCost = computed(() => { const cf = computed(() => { const obj = { - workerInvocationCost: (tileRequests.value / 1000 / 1000) * 0.5, + workerInvocationCost: (tileRequests.value / 1000 / 1000) * 0.3, planCost: 5, storageRequestCost: (tileRequests.value / 1000 / 1000) * (1 - cacheHitRate.value) * 0.36, storageCost: storedGB.value * 0.015, }; obj.total = - obj.workerInvocationCost + obj.planCost + obj.storageCost + obj.storageCost; + obj.workerInvocationCost + + obj.planCost + + obj.storageRequestCost + + obj.storageCost; return obj; }); @@ -79,13 +82,14 @@ const cfShow = ref(false);