diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d393fdc28..624cc913b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -266,7 +266,7 @@ Additionally, **`refsByWayName`** is an object mapping way names to text that ca `refsByWayName` only works if there is no `ref` tag and the expression in the `routeConcurrency` function in layer/highway_shield.js includes the `name` property in the image name. The network needs to be listed as an input value that causes the `match` expression to append `name` to the image name. -When using `overrideByRef` or `refsByWayName`, make sure to add a line to the bottom section of this page explaining why it is necessary, as they are only intended for use in special cases. +When using `overrideByRef` or `refsByWayName`, make sure to add a line to the Special Cases section of this page explaining why it is necessary, as they are only intended for use in special cases. ### Banners @@ -321,3 +321,34 @@ To test with a list of all the supported networks in the style this line can be https://github.com/ZeLonewolf/openstreetmap-americana/blob/581e1e5d97f5745c1bf764689439d93403888505/src/shieldtest.js#L200-L201 This results in a very long page and can be quite slow or even crash the browser tab. + +## Points of Interest + +A "point of interest" or POI is any feature on the map represented by an icon on the map. + +### Categories + +POIs are broken down into the following broad categories, in order to constrain the number of colors shown on the map. Some features may not cleanly fit into one category or another. Contributors should consider other POIs in the category to determine which category is the best fit. + +- **Geographic Place Names**: labels associated with `place=` tags, for countries, cities, locations, etc. +- **Infrastructure**: features associated with public infrastructure, health, safety, or government. +- **Consumer**: businesses that provide services to the public, such as shops and restaurants. +- **Outdoor**: parks, nature reserves, and other outdoorsy features. +- **Attraction**: places where people go for entertainment, leisure, or curiosity. +- **Transportation**: places where people can access forms of transportation, such as airports, train stations, bus stops, and other public transit. + +### Color Scheme + +For consistency, POI icons should use the following color palette: + +| Category | Scheme | Color | RGB | Hex triplet | +| ---------------------- | --------------- | --------------------------------------------------------------------------- | ----------- | ----------- | +| Geographic Place Names | N/A | Black | 0 0 0 | #000000 | +| Infrastructure | Pantone 294 | Blue | 0 63 135 | #003f87 | +| Consumer | UTexas Orange | Orange | 191 87 0 | #bf5700 | +| Outdoor | | TBD (green?) | | | +| Attraction | | TBD (brown?) | | | +| Transportation | Medium Purple C | Purple | 78 0 142 | #4e008e | +| Knockout | | Lt Grayish Orange | 249 245 240 | #f9f5f0 | + +POIs without a background fill should have a 2px stroke using the "knockout" color above. diff --git a/dev/americana.gpl b/dev/americana.gpl index 0baf61589..9357ccc3c 100644 --- a/dev/americana.gpl +++ b/dev/americana.gpl @@ -10,5 +10,6 @@ Name: americana.gpl 196 214 0 Yellow-Green 223 70 97 Pink 243 143 0 Orange +186 82 5 Consumer POI Orange 255 205 0 Yellow 255 255 255 White diff --git a/doc-img/background.svg b/doc-img/background.svg new file mode 100644 index 000000000..d67350c0c --- /dev/null +++ b/doc-img/background.svg @@ -0,0 +1,3 @@ + + + diff --git a/doc-img/pantone_medium_purple_c.svg b/doc-img/pantone_medium_purple_c.svg new file mode 100644 index 000000000..524589b04 --- /dev/null +++ b/doc-img/pantone_medium_purple_c.svg @@ -0,0 +1,3 @@ + + + diff --git a/doc-img/texas_orange.svg b/doc-img/texas_orange.svg new file mode 100644 index 000000000..e4b96620b --- /dev/null +++ b/doc-img/texas_orange.svg @@ -0,0 +1,3 @@ + + + diff --git a/icons/airport.svg b/icons/airport.svg deleted file mode 100644 index b43510b3f..000000000 --- a/icons/airport.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/icons/poi_coffee_cup.svg b/icons/poi_coffee_cup.svg new file mode 100644 index 000000000..defeb2415 --- /dev/null +++ b/icons/poi_coffee_cup.svg @@ -0,0 +1,4 @@ + + + + diff --git a/icons/poi_health_cross.svg b/icons/poi_health_cross.svg new file mode 100644 index 000000000..c3a2b88fa --- /dev/null +++ b/icons/poi_health_cross.svg @@ -0,0 +1,4 @@ + + + + diff --git a/icons/poi_hospital.svg b/icons/poi_hospital.svg new file mode 100644 index 000000000..b866837ed --- /dev/null +++ b/icons/poi_hospital.svg @@ -0,0 +1,4 @@ + + + + diff --git a/icons/poi_martini_glass.svg b/icons/poi_martini_glass.svg new file mode 100644 index 000000000..5c4cba00b --- /dev/null +++ b/icons/poi_martini_glass.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/icons/military_airport.svg b/icons/poi_military_plane.svg similarity index 63% rename from icons/military_airport.svg rename to icons/poi_military_plane.svg index ded091132..4429823ed 100644 --- a/icons/military_airport.svg +++ b/icons/poi_military_plane.svg @@ -1,3 +1,3 @@ - + diff --git a/icons/poi_p.svg b/icons/poi_p.svg new file mode 100644 index 000000000..33b1c0ff6 --- /dev/null +++ b/icons/poi_p.svg @@ -0,0 +1,3 @@ + + + diff --git a/icons/poi_plane.svg b/icons/poi_plane.svg new file mode 100644 index 000000000..2af1cb35d --- /dev/null +++ b/icons/poi_plane.svg @@ -0,0 +1,3 @@ + + + diff --git a/icons/poi_square_dot.svg b/icons/poi_square_dot.svg new file mode 100644 index 000000000..0d62cb0e0 --- /dev/null +++ b/icons/poi_square_dot.svg @@ -0,0 +1,3 @@ + + + diff --git a/package-lock.json b/package-lock.json index e23071176..54505e758 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1432,6 +1432,19 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3482,6 +3495,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -4674,6 +4695,16 @@ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -6195,6 +6226,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/scripts/taginfo_template.json b/scripts/taginfo_template.json index c5b07b539..7cb977024 100644 --- a/scripts/taginfo_template.json +++ b/scripts/taginfo_template.json @@ -129,7 +129,7 @@ "object_types": ["node", "area"], "description": "Military air bases are marked by a fighter jet.", "doc_url": "https://openmaptiles.org/schema/#class", - "icon_url": "https://raw.githubusercontent.com/ZeLonewolf/openstreetmap-americana/main/icons/military_airport.svg" + "icon_url": "https://raw.githubusercontent.com/ZeLonewolf/openstreetmap-americana/main/icons/poi_military_plane.svg" }, { "key": "aerodrome:type", @@ -144,7 +144,7 @@ "object_types": ["node", "area"], "description": "Military air bases are marked by a fighter jet.", "doc_url": "https://openmaptiles.org/schema/#class", - "icon_url": "https://raw.githubusercontent.com/ZeLonewolf/openstreetmap-americana/main/icons/military_airport.svg" + "icon_url": "https://raw.githubusercontent.com/ZeLonewolf/openstreetmap-americana/main/icons/poi_military_plane.svg" }, { "key": "military", @@ -152,7 +152,7 @@ "object_types": ["node", "area"], "description": "Military air bases are marked by a fighter jet.", "doc_url": "https://openmaptiles.org/schema/#class", - "icon_url": "https://raw.githubusercontent.com/ZeLonewolf/openstreetmap-americana/main/icons/military_airport.svg" + "icon_url": "https://raw.githubusercontent.com/ZeLonewolf/openstreetmap-americana/main/icons/poi_military_plane.svg" }, { "key": "aeroway", diff --git a/src/constants/color.js b/src/constants/color.js index bba97b525..e574b411b 100644 --- a/src/constants/color.js +++ b/src/constants/color.js @@ -25,12 +25,14 @@ export const airportOutline = "hsl(250, 41%, 79%)"; export const airportRunway = "hsl(250, 41%, 79%)"; export const airportLabel = "hsl(250, 71%, 29%)"; -export const shields = { +//TODO - rename this variable to "palette" +export const palette = { black: "black", blue: "#003f87", // Pantone 294 brown: "#693f23", // Pantone 469 green: "#006747", // Pantone 342 orange: "#f38f00", // Pantone 152 + texas_orange: "#bf5700", // UTexas Orange pink: "#df4661", // Pantone 198 purple: "#6d2077", // Pantone 259 red: "#bf2033", // Pantone 187 @@ -39,6 +41,20 @@ export const shields = { yellow_green: "#c4d600", // Pantone 382 }; +export const shields = { + black: palette.black, + blue: palette.blue, // Pantone 294 + brown: palette.brown, // Pantone 469 + green: palette.green, // Pantone 342 + orange: palette.orange, // Pantone 152 + pink: palette.pink, // Pantone 198 + purple: palette.purple, // Pantone 259 + red: palette.red, // Pantone 187 + white: palette.white, + yellow: palette.yellow, // Pantone 116 + yellow_green: palette.yellow_green, // Pantone 382 +}; + export const railwayTunnelFill = "hsl(0, 0%, 90%)"; export const railFill = "hsl(0, 0%, 60%)"; @@ -48,3 +64,19 @@ export const lightRailFill = "hsl(0, 0%, 50%)"; export const tramFill = "hsl(0, 0%, 60%)"; export const monorailFill = "hsl(0, 0%, 50%)"; export const funicularFill = "hsl(0, 0%, 50%)"; + +export const hue = { + tollRoad: 48, + park: 136, + water: 211, + transport: 273, + borderCasing: 281, +}; + +export const poi = { + infrastructure: palette.blue, + consumer: palette.texas_orange, + //outdoor: + //attraction: + transportation: `hsl(${hue.transport}, 100%, 28%)`, +}; diff --git a/src/js/legend_config.js b/src/js/legend_config.js index 2b32a7a21..02e9170e3 100644 --- a/src/js/legend_config.js +++ b/src/js/legend_config.js @@ -8,6 +8,7 @@ import * as ConstructionLayers from "../layer/construction.js"; import * as HighwayExitLayers from "../layer/highway_exit.js"; import * as RailLayers from "../layer/rail.js"; import * as AerowayLayers from "../layer/aeroway.js"; +import * as POILayers from "../layer/poi.js"; import * as ParkLayers from "../layer/park.js"; import * as BuildingLayers from "../layer/building.js"; import * as WaterLayers from "../layer/water.js"; @@ -43,6 +44,10 @@ export const sections = [ name: "Aviation", entries: AerowayLayers.legendEntries, }, + { + name: "Points of interest", + entries: POILayers.legendEntries, + }, { name: "Structures", entries: BuildingLayers.legendEntries, diff --git a/src/layer/aeroway.js b/src/layer/aeroway.js index 9af7a5859..b0232d988 100644 --- a/src/layer/aeroway.js +++ b/src/layer/aeroway.js @@ -15,8 +15,8 @@ const iconLayout = { "match", ["get", "class"], "military", - "military_airport", - "airport", + "poi_military_plane", + "poi_plane", ], "text-anchor": "bottom", "text-variable-anchor": [ diff --git a/src/layer/index.js b/src/layer/index.js index 8276ac008..18d13e407 100644 --- a/src/layer/index.js +++ b/src/layer/index.js @@ -11,6 +11,7 @@ import * as lyrLanduse from "./landuse.js"; import * as lyrOneway from "./oneway.js"; import * as lyrPark from "./park.js"; import * as lyrPlace from "./place.js"; +import * as lyrPoi from "./poi.js"; import * as lyrRail from "./rail.js"; import * as lyrRoad from "./road.js"; import * as lyrTransportationLabel from "./transportation_label.js"; @@ -218,6 +219,8 @@ export function build(locales) { lyrHighwayExit.exits, + lyrPoi.poi, + lyrPlace.state, lyrPlace.village, lyrPlace.town, diff --git a/src/layer/poi.js b/src/layer/poi.js new file mode 100644 index 000000000..9d090a537 --- /dev/null +++ b/src/layer/poi.js @@ -0,0 +1,111 @@ +import * as label from "../constants/label.js"; +import * as Color from "../constants/color.js"; + +var iconDefs = { + bar: ["bar", "beer", "pub"], + coffee: ["cafe"], + hospital: "hospital", + medical: ["doctors", "clinic"], + parking: "parking", +}; + +export const poi = { + id: "poi", + type: "symbol", + paint: { + "text-halo-color": Color.backgroundFill, + "text-halo-width": 1.5, + "icon-halo-width": 0.4, + "text-halo-blur": 1, + "icon-halo-blur": 0.2, + "text-color": [ + "match", + ["get", "subclass"], + [...iconDefs.bar, ...iconDefs.coffee], + Color.poi.consumer, + ["hospital", "parking"], + Color.poi.infrastructure, + Color.poi.infrastructure, + ], + }, + filter: [ + ">=", + ["zoom"], + [ + "match", + ["get", "subclass"], + "hospital", + 15, + [...iconDefs.bar, ...iconDefs.coffee], + 16, + ["clinic", "doctors", "parking"], + 17, + 99, + ], + ], + layout: { + "text-font": ["OpenHistorical"], + "icon-optional": false, + "text-size": { + base: 1.0, + stops: [ + [15, 10], + [17, 12], + ], + }, + "icon-image": [ + "match", + ["get", "subclass"], + iconDefs.bar, + "poi_martini_glass", + iconDefs.coffee, + "poi_coffee_cup", + iconDefs.medical, + "poi_health_cross", + iconDefs.hospital, + "poi_hospital", + iconDefs.parking, + "poi_p", + "poi_square_dot", //icon for generic POI, not currently used + ], + "icon-size": 1.0, + "text-field": label.localizedName, + "text-variable-anchor": ["left", "right", "bottom"], + "text-justify": "auto", + "text-radial-offset": 1.2, + "text-max-width": 5, + "icon-padding": 0, + "text-padding": 0, + "icon-allow-overlap": false, + }, + source: "openmaptiles", + "source-layer": "poi", +}; + +export const legendEntries = [ + { + description: "Hospital", + layers: [poi.id], + filter: ["==", ["get", "subclass"], iconDefs.hospital], + }, + { + description: "Doctor's office or clinic", + layers: [poi.id], + filter: ["in", ["get", "subclass"], ["literal", iconDefs.medical]], + }, + { + description: "Coffee shop", + layers: [poi.id], + filter: ["in", ["get", "subclass"], ["literal", iconDefs.coffee]], + }, + { + description: "Bar or pub", + layers: [poi.id], + filter: ["in", ["get", "subclass"], ["literal", iconDefs.bar]], + }, + { + description: "Parking", + layers: [poi.id], + filter: ["==", ["get", "subclass"], iconDefs.parking], + }, +];