@mailwoman/cartographer 9.4.0 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/base/buildings.ts +3 -4
- package/lib/base/composition.ts +23 -13
- package/lib/base/layers.ts +9 -3
- package/lib/base/theme.ts +22 -13
- package/lib/{bdc/index.ts → bdc.ts} +15 -109
- package/lib/coverage.ts +73 -0
- package/lib/index.ts +6 -6
- package/lib/planetary/layers.ts +63 -18
- package/lib/planetary/sources.ts +10 -7
- package/lib/planetary/style.ts +12 -6
- package/lib/{race-dots/index.ts → race-dots.ts} +19 -20
- package/lib/styles/fonts.ts +19 -8
- package/lib/styles/layers.ts +3 -3
- package/lib/styles/sources.ts +4 -3
- package/lib/{tiger/index.ts → tiger.ts} +3 -2
- package/out/base/buildings.d.ts.map +1 -1
- package/out/base/buildings.js +3 -4
- package/out/base/buildings.js.map +1 -1
- package/out/base/composition.d.ts +18 -8
- package/out/base/composition.d.ts.map +1 -1
- package/out/base/composition.js +13 -9
- package/out/base/composition.js.map +1 -1
- package/out/base/layers.d.ts +1 -1
- package/out/base/layers.d.ts.map +1 -1
- package/out/base/layers.js +9 -3
- package/out/base/layers.js.map +1 -1
- package/out/base/theme.d.ts +9 -5
- package/out/base/theme.d.ts.map +1 -1
- package/out/base/theme.js +21 -13
- package/out/base/theme.js.map +1 -1
- package/out/{base/index.d.ts → base.d.ts} +1 -1
- package/out/base.d.ts.map +1 -0
- package/out/{base/index.js → base.js} +1 -1
- package/out/base.js.map +1 -0
- package/out/{bdc/index.d.ts → bdc.d.ts} +8 -7
- package/out/bdc.d.ts.map +1 -0
- package/out/{bdc/index.js → bdc.js} +9 -102
- package/out/bdc.js.map +1 -0
- package/out/coverage.d.ts +44 -0
- package/out/coverage.d.ts.map +1 -0
- package/out/coverage.js +63 -0
- package/out/coverage.js.map +1 -0
- package/out/{hspa/index.d.ts → hspa.d.ts} +1 -1
- package/out/hspa.d.ts.map +1 -0
- package/out/{hspa/index.js → hspa.js} +1 -1
- package/out/hspa.js.map +1 -0
- package/out/index.d.ts +6 -6
- package/out/index.d.ts.map +1 -1
- package/out/index.js +6 -6
- package/out/index.js.map +1 -1
- package/out/planetary/layers.d.ts +40 -12
- package/out/planetary/layers.d.ts.map +1 -1
- package/out/planetary/layers.js +44 -17
- package/out/planetary/layers.js.map +1 -1
- package/out/planetary/sources.d.ts +7 -6
- package/out/planetary/sources.d.ts.map +1 -1
- package/out/planetary/sources.js +8 -5
- package/out/planetary/sources.js.map +1 -1
- package/out/planetary/style.d.ts +7 -4
- package/out/planetary/style.d.ts.map +1 -1
- package/out/planetary/style.js +5 -4
- package/out/planetary/style.js.map +1 -1
- package/out/{planetary/index.js → planetary.d.ts} +1 -1
- package/out/planetary.d.ts.map +1 -0
- package/out/{planetary/index.d.ts → planetary.js} +1 -1
- package/out/planetary.js.map +1 -0
- package/out/race-dots.d.ts +70 -0
- package/out/race-dots.d.ts.map +1 -0
- package/out/race-dots.js +69 -0
- package/out/race-dots.js.map +1 -0
- package/out/styles/fonts.d.ts +17 -8
- package/out/styles/fonts.d.ts.map +1 -1
- package/out/styles/fonts.js +17 -8
- package/out/styles/fonts.js.map +1 -1
- package/out/styles/layers.d.ts.map +1 -1
- package/out/styles/layers.js +3 -3
- package/out/styles/layers.js.map +1 -1
- package/out/styles/sources.d.ts.map +1 -1
- package/out/styles/sources.js +3 -2
- package/out/styles/sources.js.map +1 -1
- package/out/{styles/index.d.ts → styles.d.ts} +1 -1
- package/out/styles.d.ts.map +1 -0
- package/out/{styles/index.js → styles.js} +1 -1
- package/out/styles.js.map +1 -0
- package/out/{tiger/index.d.ts → tiger.d.ts} +4 -3
- package/out/tiger.d.ts.map +1 -0
- package/out/{tiger/index.js → tiger.js} +4 -3
- package/out/tiger.js.map +1 -0
- package/out/tiles/api.d.ts.map +1 -1
- package/out/{tiles/index.d.ts → tiles.d.ts} +1 -1
- package/out/tiles.d.ts.map +1 -0
- package/out/{tiles/index.js → tiles.js} +1 -1
- package/out/tiles.js.map +1 -0
- package/out/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +14 -99
- package/lib/coverage/index.ts +0 -88
- package/out/base/index.d.ts.map +0 -1
- package/out/base/index.js.map +0 -1
- package/out/bdc/index.d.ts.map +0 -1
- package/out/bdc/index.js.map +0 -1
- package/out/coverage/index.d.ts +0 -59
- package/out/coverage/index.d.ts.map +0 -1
- package/out/coverage/index.js +0 -78
- package/out/coverage/index.js.map +0 -1
- package/out/hspa/index.d.ts.map +0 -1
- package/out/hspa/index.js.map +0 -1
- package/out/planetary/index.d.ts.map +0 -1
- package/out/planetary/index.js.map +0 -1
- package/out/race-dots/index.d.ts +0 -72
- package/out/race-dots/index.d.ts.map +0 -1
- package/out/race-dots/index.js +0 -70
- package/out/race-dots/index.js.map +0 -1
- package/out/styles/index.d.ts.map +0 -1
- package/out/styles/index.js.map +0 -1
- package/out/tiger/index.d.ts.map +0 -1
- package/out/tiger/index.js.map +0 -1
- package/out/tiles/index.d.ts.map +0 -1
- package/out/tiles/index.js.map +0 -1
- /package/lib/{base/index.ts → base.ts} +0 -0
- /package/lib/{hspa/index.ts → hspa.ts} +0 -0
- /package/lib/{planetary/index.ts → planetary.ts} +0 -0
- /package/lib/{styles/index.ts → styles.ts} +0 -0
- /package/lib/{tiles/index.ts → tiles.ts} +0 -0
package/lib/base/buildings.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
} from "@maplibre/maplibre-gl-style-spec"
|
|
12
12
|
|
|
13
13
|
import { MailwomanBaseTileSetID } from "#base/theme"
|
|
14
|
-
import {
|
|
14
|
+
import { MAP_FONT_REGULAR } from "#styles/fonts"
|
|
15
15
|
import { LayerID } from "#styles/layers"
|
|
16
16
|
|
|
17
17
|
const BuildingLayerID = LayerID.bind(null, "buildings")
|
|
@@ -80,8 +80,7 @@ export const BuildingLayers: LayerSpecification[] = [
|
|
|
80
80
|
"fill-extrusion-vertical-gradient": false,
|
|
81
81
|
"fill-extrusion-translate-anchor": "map",
|
|
82
82
|
"fill-extrusion-opacity": 1,
|
|
83
|
-
// top of the band = full building height
|
|
84
|
-
// "fill-extrusion-height": popHeight(buildingHeight()),
|
|
83
|
+
// top of the band = full building height "fill-extrusion-height": popHeight(buildingHeight()),
|
|
85
84
|
// // base of the band = full height minus the cap thickness (clamped ≥ 0)
|
|
86
85
|
// "fill-extrusion-base": popHeight([ "max", [ "-", buildingHeight(), ROOF_CAP ], 0 ]),
|
|
87
86
|
"fill-extrusion-height": popHeight(["+", buildingHeight(), ROOF_GAP, ROOF_CAP]),
|
|
@@ -115,7 +114,7 @@ export const BuildingLayers: LayerSpecification[] = [
|
|
|
115
114
|
"text-field": ["to-string", ["id"]],
|
|
116
115
|
"text-offset": [0, 0],
|
|
117
116
|
"text-anchor": "center",
|
|
118
|
-
"text-font": [
|
|
117
|
+
"text-font": [MAP_FONT_REGULAR],
|
|
119
118
|
},
|
|
120
119
|
|
|
121
120
|
paint: {
|
package/lib/base/composition.ts
CHANGED
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
} from "#styles/layers"
|
|
17
17
|
import type { TileSetSourceRecord } from "#styles/sources"
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
// #endregion
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
// #region Spec Creators
|
|
22
22
|
|
|
23
23
|
export function createLightSpec(spec?: Partial<LightSpecification>): LightSpecification {
|
|
24
24
|
return {
|
|
@@ -46,19 +46,23 @@ export function createSkySpec(spec?: Partial<SkySpecification>): SkySpecificatio
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
// #endregion
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
// #region Style Composition
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
|
-
* The glyph host every style composed here reads fonts from.
|
|
55
|
-
*
|
|
54
|
+
* The glyph host every style composed here reads fonts from.
|
|
55
|
+
*
|
|
56
|
+
* The Protomaps font set, mirrored under the public bucket so a style never
|
|
57
|
+
* depends on an upstream host at render time.
|
|
56
58
|
*/
|
|
57
59
|
export const PROTOMAPS_GLYPHS_URL = "https://public.mailwoman.ai/protomaps/fonts/{fontstack}/{range}.pbf"
|
|
58
60
|
|
|
59
61
|
/**
|
|
60
|
-
* The Earth sprite.
|
|
61
|
-
*
|
|
62
|
+
* The Earth sprite.
|
|
63
|
+
*
|
|
64
|
+
* It must match the basemap schema version: the v4 sprite includes the icons the v4 theme's
|
|
65
|
+
* layers reference by name, so a style over a different basemap version needs a different sprite.
|
|
62
66
|
*/
|
|
63
67
|
export const PROTOMAPS_SPRITE_URL = "https://public.mailwoman.ai/protomaps/sprites/v4/light"
|
|
64
68
|
|
|
@@ -69,16 +73,22 @@ export interface StyleSpecificationComposition {
|
|
|
69
73
|
sky?: Partial<SkySpecification>
|
|
70
74
|
terrain?: Partial<TerrainSpecification>
|
|
71
75
|
/**
|
|
72
|
-
* The layer list every `layers` entry inserts into.
|
|
73
|
-
*
|
|
76
|
+
* The layer list every `layers` entry inserts into.
|
|
77
|
+
*
|
|
78
|
+
* Earth's basemap layers by default.
|
|
79
|
+
* A body with no roads, water or buildings brings its own.
|
|
74
80
|
*/
|
|
75
81
|
baseLayers?: LayerSpecification[]
|
|
76
82
|
/**
|
|
77
|
-
* The `hillshade` source.
|
|
83
|
+
* The `hillshade` source.
|
|
84
|
+
*
|
|
85
|
+
* Earth's terrarium DEM by default; `null` adds no such source.
|
|
78
86
|
*/
|
|
79
87
|
hillshadeSource?: SourceSpecification | null
|
|
80
88
|
/**
|
|
81
|
-
* The sprite URL.
|
|
89
|
+
* The sprite URL.
|
|
90
|
+
*
|
|
91
|
+
* Earth's Protomaps v4 sprite by default; `null` omits the key, for a style with no icons.
|
|
82
92
|
*/
|
|
83
93
|
sprite?: string | null
|
|
84
94
|
glyphs?: string
|
|
@@ -146,4 +156,4 @@ export class StyleSpecificationComposer {
|
|
|
146
156
|
}
|
|
147
157
|
}
|
|
148
158
|
|
|
149
|
-
|
|
159
|
+
// #endregion
|
package/lib/base/layers.ts
CHANGED
|
@@ -18,9 +18,15 @@ import { LayerID } from "#styles/layers"
|
|
|
18
18
|
export const HillsLayerID = LayerID(HillshadeTileSetID, "hills")
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
* Splits `layers()` into non-label
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* Splits `layers()` into non-label and label groups.
|
|
22
|
+
*
|
|
23
|
+
* The interval between base geometry and labels holds the footprints.
|
|
24
|
+
* It also holds water outlines and hillshade.
|
|
25
|
+
*
|
|
26
|
+
* `@protomaps/basemaps@5.x` doesn't expose a `noLabels` helper.
|
|
27
|
+
* `labelsOnly: true` gives only the label layers.
|
|
28
|
+
*
|
|
29
|
+
* The full list minus that set yields the non-label group.
|
|
24
30
|
*/
|
|
25
31
|
const allBaseLayers = layers(MailwomanBaseTileSetID, MailwomanBaseFlavor, { lang: "en" })
|
|
26
32
|
const labelLayers = layers(MailwomanBaseTileSetID, MailwomanBaseFlavor, { lang: "en", labelsOnly: true })
|
package/lib/base/theme.ts
CHANGED
|
@@ -6,25 +6,34 @@
|
|
|
6
6
|
|
|
7
7
|
import { type Flavor, namedFlavor } from "@protomaps/basemaps"
|
|
8
8
|
|
|
9
|
+
import { MAP_FONT_ITALIC, MAP_FONT_MEDIUM, MAP_FONT_REGULAR } from "#styles/fonts"
|
|
9
10
|
import { TileSetSourceID } from "#styles/sources"
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
|
-
* Identifier for the Mailwoman base tileset.
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* Identifier for the Mailwoman base tileset.
|
|
14
|
+
*
|
|
15
|
+
* Matches the R2 object basename (`nexus-assets/tiles/basemap-v4.pmtiles`).
|
|
16
|
+
* `tiles.mailwoman.ai/basemap-v4.json` returns its tilejson,
|
|
17
|
+
* `tiles.mailwoman.ai/basemap-v4/{z}/{x}/{y}.mvt` returns vector tiles.
|
|
15
18
|
*/
|
|
16
19
|
export const MailwomanBaseTileSetID = TileSetSourceID("basemap-v4")
|
|
17
20
|
|
|
18
21
|
const darkFlavor = namedFlavor("dark")
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
|
-
* The Mailwoman theme for Protomaps via MapLibre.
|
|
22
|
-
*
|
|
24
|
+
* The Mailwoman theme for Protomaps via MapLibre.
|
|
25
|
+
*
|
|
26
|
+
* Keys follow `@protomaps/basemaps@5.x` which targets the v4 tile schema
|
|
27
|
+
* (`["==","kind","..."]` filters), matching the basemap-v4 PMTiles on R2.
|
|
23
28
|
*/
|
|
24
29
|
export const MailwomanBaseFlavor: Flavor = {
|
|
25
30
|
...darkFlavor,
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
regular: MAP_FONT_REGULAR,
|
|
33
|
+
bold: MAP_FONT_MEDIUM,
|
|
34
|
+
italic: MAP_FONT_ITALIC,
|
|
35
|
+
|
|
36
|
+
// #region Base
|
|
28
37
|
background: "hsl(0deg 10% 5%)",
|
|
29
38
|
earth: "hsl(0deg 10% 5%)",
|
|
30
39
|
|
|
@@ -51,8 +60,8 @@ export const MailwomanBaseFlavor: Flavor = {
|
|
|
51
60
|
zoo: "#222323",
|
|
52
61
|
military: "#242323",
|
|
53
62
|
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
// #endregion
|
|
64
|
+
// #region Tunnel
|
|
56
65
|
tunnel_other_casing: "#141414",
|
|
57
66
|
tunnel_minor_casing: "#141414",
|
|
58
67
|
tunnel_link_casing: "#141414",
|
|
@@ -64,10 +73,10 @@ export const MailwomanBaseFlavor: Flavor = {
|
|
|
64
73
|
tunnel_major: "#292929",
|
|
65
74
|
tunnel_highway: "#292929",
|
|
66
75
|
|
|
67
|
-
|
|
76
|
+
// #endregion
|
|
68
77
|
buildings: "#111111",
|
|
69
78
|
|
|
70
|
-
|
|
79
|
+
// #region Casing
|
|
71
80
|
minor_service_casing: "#1f1f1f",
|
|
72
81
|
minor_casing: "#1f1f1f",
|
|
73
82
|
link_casing: "#1f1f1f",
|
|
@@ -83,11 +92,11 @@ export const MailwomanBaseFlavor: Flavor = {
|
|
|
83
92
|
highway_casing_early: "#1f1f1f",
|
|
84
93
|
highway: "hsl(36deg 10% 50%)",
|
|
85
94
|
|
|
86
|
-
|
|
95
|
+
// #endregion
|
|
87
96
|
railway: "#000000",
|
|
88
97
|
boundaries: "hsl(240deg 100% 90%)",
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
// #region Bridges
|
|
91
100
|
bridges_other_casing: "#2b2b2b",
|
|
92
101
|
bridges_minor_casing: "#1f1f1f",
|
|
93
102
|
bridges_link_casing: "#1f1f1f",
|
|
@@ -99,7 +108,7 @@ export const MailwomanBaseFlavor: Flavor = {
|
|
|
99
108
|
bridges_major: "#3d3d3d",
|
|
100
109
|
bridges_highway: "#474747",
|
|
101
110
|
|
|
102
|
-
|
|
111
|
+
// #endregion
|
|
103
112
|
|
|
104
113
|
ocean_label: "#717784",
|
|
105
114
|
subplace_label: "hsl(50deg 50% 70%)",
|
|
@@ -47,13 +47,14 @@ export type BaseBDCLayerSpecification<T> = T extends BDCLayerSpecificationInput
|
|
|
47
47
|
: never
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* The three builders below take a spec
|
|
50
|
+
* The three builders below take a spec without the source fields and return one with them filled in.
|
|
51
51
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
52
|
+
* These are specific assertions.
|
|
53
|
+
* Each avoids `unknown`.
|
|
54
|
+
*
|
|
55
|
+
* TypeScript cannot verify that because TypeScript cannot verify that `Omit<T, K>` plus
|
|
56
|
+
* the omitted keys reconstitutes `T` — a `<T>(…): T` builder could only reach its return
|
|
57
|
+
* type by defeating the checker, covering the `id`, `minzoom` and `maxzoom` values too.
|
|
57
58
|
*/
|
|
58
59
|
type BDCLayerBuilderInput = BaseBDCLayerSpecification<BDCLayerSpecificationInput>
|
|
59
60
|
|
|
@@ -101,9 +102,6 @@ const GIGABIT_BROADBAND_SPEED = 1000
|
|
|
101
102
|
export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
102
103
|
{
|
|
103
104
|
afterID: "earth",
|
|
104
|
-
// metadata: {
|
|
105
|
-
// queryable: false,
|
|
106
|
-
// },
|
|
107
105
|
id: "blocks-underserved",
|
|
108
106
|
layout: {
|
|
109
107
|
visibility: "none",
|
|
@@ -112,43 +110,19 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
112
110
|
source: BDCTileSetID,
|
|
113
111
|
type: "fill",
|
|
114
112
|
filter: [
|
|
115
|
-
// ---
|
|
116
113
|
"all",
|
|
117
114
|
["in", 50, ["get", "technology_codes"]], // Fiber only
|
|
118
115
|
[">", ["get", "land_area_sqm"], 0],
|
|
119
|
-
// ["==", ["get", "UR"], "R"],
|
|
120
116
|
],
|
|
121
117
|
paint: {
|
|
122
|
-
// "fill-extrusion-height": [
|
|
123
|
-
// // Our extrusion height represents the magnitude of broadband underservice,
|
|
124
|
-
// // e.g. How many people are underserved per square meter of land area.
|
|
125
|
-
// "let",
|
|
126
|
-
// "population_density",
|
|
127
|
-
// ["/", ["to-number", ["get", "population"]], ["to-number", ["get", "land_area_sqm"]]],
|
|
128
|
-
// ["*", ["var", "population_density"], 10000],
|
|
129
|
-
// ],
|
|
130
118
|
"fill-color": "hsl(60deg, 100%, 50%)",
|
|
131
119
|
"fill-opacity": [
|
|
132
|
-
// Underserved areas are emphasized to their level importance,
|
|
133
|
-
// relative to the impact of the underservice.
|
|
134
120
|
"let",
|
|
135
121
|
"internet_speed_impact",
|
|
136
122
|
["/", ["to-number", ["get", "average_download_speed"]], GIGABIT_BROADBAND_SPEED],
|
|
137
|
-
[
|
|
138
|
-
// ---
|
|
139
|
-
"interpolate",
|
|
140
|
-
["linear"],
|
|
141
|
-
["var", "internet_speed_impact"],
|
|
142
|
-
0,
|
|
143
|
-
0.1,
|
|
144
|
-
1,
|
|
145
|
-
0.5,
|
|
146
|
-
],
|
|
123
|
+
["interpolate", ["linear"], ["var", "internet_speed_impact"], 0, 0.1, 1, 0.5],
|
|
147
124
|
],
|
|
148
125
|
},
|
|
149
|
-
// layout: {
|
|
150
|
-
// visibility: "none",
|
|
151
|
-
// },
|
|
152
126
|
},
|
|
153
127
|
|
|
154
128
|
{
|
|
@@ -163,7 +137,6 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
163
137
|
"source-layer": `bdc_${TIGERLevel.Block}`,
|
|
164
138
|
source: BDCTileSetID,
|
|
165
139
|
type: "line",
|
|
166
|
-
// filter: [">=", ["get", "ALAND"], 0],
|
|
167
140
|
minzoom: 9,
|
|
168
141
|
paint: {
|
|
169
142
|
"line-color": "#000",
|
|
@@ -180,13 +153,7 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
180
153
|
"source-layer": `bdc_${TIGERLevel.Block}`,
|
|
181
154
|
source: BDCTileSetID,
|
|
182
155
|
type: "symbol",
|
|
183
|
-
filter: [
|
|
184
|
-
// ---
|
|
185
|
-
"all",
|
|
186
|
-
// ["in", 50, ["get", "technology_codes"]], // Fiber only
|
|
187
|
-
[">", ["get", "land_area_sqm"], 0],
|
|
188
|
-
// ["==", ["get", "UR"], "R"],
|
|
189
|
-
],
|
|
156
|
+
filter: ["all", [">", ["get", "land_area_sqm"], 0]],
|
|
190
157
|
paint: {
|
|
191
158
|
"text-color": "black",
|
|
192
159
|
"text-halo-color": "white",
|
|
@@ -208,13 +175,7 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
208
175
|
...createBDCLayer({
|
|
209
176
|
id: "coverage-fiber-label",
|
|
210
177
|
beforeID: "places_subplace",
|
|
211
|
-
filter: [
|
|
212
|
-
// ---
|
|
213
|
-
|
|
214
|
-
"all",
|
|
215
|
-
["==", ["get", "provider_id"], 131_425],
|
|
216
|
-
// ["in", 50, ["get", "technology_codes"]],
|
|
217
|
-
],
|
|
178
|
+
filter: ["all", ["==", ["get", "provider_id"], 131_425]],
|
|
218
179
|
type: "symbol",
|
|
219
180
|
layout: {
|
|
220
181
|
visibility: "none",
|
|
@@ -224,13 +185,8 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
224
185
|
" Mbps",
|
|
225
186
|
],
|
|
226
187
|
"text-size": [
|
|
227
|
-
// ---
|
|
228
188
|
"let",
|
|
229
189
|
"multiplier",
|
|
230
|
-
// We scale the text size based on the average download speed.
|
|
231
|
-
// By default, we're no smaller than 14, Any speed above the gigabit threshold
|
|
232
|
-
// acts as a multiplier for the text size.
|
|
233
|
-
// ---
|
|
234
190
|
["/", ["get", "average_download_speed"], GIGABIT_BROADBAND_SPEED / 4],
|
|
235
191
|
["+", 14, ["var", "multiplier"]],
|
|
236
192
|
],
|
|
@@ -246,7 +202,6 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
246
202
|
paint: {
|
|
247
203
|
"text-halo-width": 2,
|
|
248
204
|
"text-halo-color": [
|
|
249
|
-
// ---
|
|
250
205
|
"interpolate",
|
|
251
206
|
["exponential", 0.5],
|
|
252
207
|
["get", "average_download_speed"],
|
|
@@ -258,7 +213,6 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
258
213
|
],
|
|
259
214
|
|
|
260
215
|
"text-color": [
|
|
261
|
-
// ---
|
|
262
216
|
"interpolate",
|
|
263
217
|
["exponential", 0.25],
|
|
264
218
|
["get", "average_download_speed"],
|
|
@@ -287,22 +241,7 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
287
241
|
paint: {
|
|
288
242
|
"line-color": "#ff009c",
|
|
289
243
|
|
|
290
|
-
"line-width": [
|
|
291
|
-
"interpolate",
|
|
292
|
-
["exponential", 1.6],
|
|
293
|
-
["zoom"],
|
|
294
|
-
// ---
|
|
295
|
-
3,
|
|
296
|
-
0,
|
|
297
|
-
6,
|
|
298
|
-
1.1,
|
|
299
|
-
12,
|
|
300
|
-
1.6,
|
|
301
|
-
15,
|
|
302
|
-
5,
|
|
303
|
-
18,
|
|
304
|
-
15,
|
|
305
|
-
],
|
|
244
|
+
"line-width": ["interpolate", ["exponential", 1.6], ["zoom"], 3, 0, 6, 1.1, 12, 1.6, 15, 5, 18, 15],
|
|
306
245
|
},
|
|
307
246
|
layout: {
|
|
308
247
|
"line-cap": "round",
|
|
@@ -312,12 +251,7 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
312
251
|
...createBDCLayer({
|
|
313
252
|
afterID: "earth",
|
|
314
253
|
id: "coverage-fiber-heat",
|
|
315
|
-
filter: [
|
|
316
|
-
// ---
|
|
317
|
-
|
|
318
|
-
"all",
|
|
319
|
-
["==", ["get", "provider_id"], 131_425],
|
|
320
|
-
],
|
|
254
|
+
filter: ["all", ["==", ["get", "provider_id"], 131_425]],
|
|
321
255
|
minzoom: 10,
|
|
322
256
|
type: "heatmap",
|
|
323
257
|
layout: {
|
|
@@ -325,7 +259,6 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
325
259
|
},
|
|
326
260
|
paint: {
|
|
327
261
|
"heatmap-color": [
|
|
328
|
-
// ---
|
|
329
262
|
"interpolate",
|
|
330
263
|
["linear"],
|
|
331
264
|
["heatmap-density"],
|
|
@@ -334,22 +267,8 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
334
267
|
}).flat(),
|
|
335
268
|
],
|
|
336
269
|
|
|
337
|
-
"heatmap-radius": [
|
|
338
|
-
|
|
339
|
-
"interpolate",
|
|
340
|
-
["linear"],
|
|
341
|
-
["zoom"],
|
|
342
|
-
10,
|
|
343
|
-
5,
|
|
344
|
-
15,
|
|
345
|
-
20,
|
|
346
|
-
],
|
|
347
|
-
"heatmap-weight": [
|
|
348
|
-
// ---
|
|
349
|
-
"*",
|
|
350
|
-
["get", "land_area_sqm"],
|
|
351
|
-
0.00001,
|
|
352
|
-
],
|
|
270
|
+
"heatmap-radius": ["interpolate", ["linear"], ["zoom"], 10, 5, 15, 20],
|
|
271
|
+
"heatmap-weight": ["*", ["get", "land_area_sqm"], 0.00001],
|
|
353
272
|
},
|
|
354
273
|
}),
|
|
355
274
|
|
|
@@ -381,30 +300,17 @@ export const BroadbandDataCollectionLayers: BDCLayerSpecificationInput[] = [
|
|
|
381
300
|
source: "composite",
|
|
382
301
|
"source-layer": "DataCentersCombined20220921",
|
|
383
302
|
layout: {
|
|
384
|
-
// visibility: "none",
|
|
385
303
|
"text-field": ["get", "Category"],
|
|
386
304
|
"text-size": 12,
|
|
387
305
|
"text-anchor": "top",
|
|
388
306
|
"text-offset": [0, 0.5],
|
|
389
|
-
// "text-allow-overlap": true,
|
|
390
307
|
"text-font": ["Fira Code Regular"],
|
|
391
308
|
},
|
|
392
309
|
paint: {
|
|
393
310
|
"text-color": "#fff",
|
|
394
311
|
"text-halo-color": "#fb8429",
|
|
395
312
|
"text-halo-width": 1,
|
|
396
|
-
"text-opacity": [
|
|
397
|
-
// We fade out the outline at higher zoom levels
|
|
398
|
-
"interpolate",
|
|
399
|
-
["linear"],
|
|
400
|
-
["zoom"],
|
|
401
|
-
1,
|
|
402
|
-
0.01,
|
|
403
|
-
6,
|
|
404
|
-
0.5,
|
|
405
|
-
16,
|
|
406
|
-
1,
|
|
407
|
-
],
|
|
313
|
+
"text-opacity": ["interpolate", ["linear"], ["zoom"], 1, 0.01, 6, 0.5, 16, 1],
|
|
408
314
|
},
|
|
409
315
|
},
|
|
410
316
|
]
|
package/lib/coverage.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Sister Software.
|
|
3
|
+
* @license AGPL-3.0
|
|
4
|
+
* @author Teffen Ellis, et al.
|
|
5
|
+
*
|
|
6
|
+
* Address-coverage overlays rendered from the `mailwoman coverage build` H3 tile set. Each cell
|
|
7
|
+
* supplies optimistic (`fog_opt`) and observed-coverage (`fog`) values. The demo exposes both as
|
|
8
|
+
* default-off layers. Tiles are served from `coverage-v5.pmtiles`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { FillLayerSpecification, VectorSourceSpecification } from "@maplibre/maplibre-gl-style-spec"
|
|
12
|
+
|
|
13
|
+
import { TileSetSourceID } from "#styles/sources"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* MapLibre source ID for the v5 coverage tiles.
|
|
17
|
+
* Keep it aligned with the archive and layer specs.
|
|
18
|
+
*/
|
|
19
|
+
export const CoverageTileSetID = TileSetSourceID("coverage-v5")
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Source-layer name stored in the coverage archive.
|
|
23
|
+
*/
|
|
24
|
+
export const COVERAGE_SOURCE_LAYER = "coverage"
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Near-black indigo used to mark unknown or unsurveyed areas.
|
|
28
|
+
*/
|
|
29
|
+
export const COVERAGE_FOG_COLOR = "#663399" // Rebecca Purple
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Maximum opacity for an uncovered cell.
|
|
33
|
+
*/
|
|
34
|
+
export const COVERAGE_MAX_FOG_OPACITY = 0.9
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* IDs for the optimistic and observed-coverage layers.
|
|
38
|
+
*/
|
|
39
|
+
export const CoverageLayerID = {
|
|
40
|
+
optimistic: "coverage-opt-fog",
|
|
41
|
+
honest: "coverage-honest-fog",
|
|
42
|
+
} as const
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create a vector source from its TileJSON URL.
|
|
46
|
+
*/
|
|
47
|
+
export function createCoverageSource(url: string): VectorSourceSpecification {
|
|
48
|
+
return { type: "vector", url }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function fogFill(id: string, fogProperty: "fog" | "fog_opt"): FillLayerSpecification {
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
type: "fill",
|
|
55
|
+
source: CoverageTileSetID,
|
|
56
|
+
"source-layer": COVERAGE_SOURCE_LAYER,
|
|
57
|
+
// Keep coverage overlays hidden until selected.
|
|
58
|
+
layout: { visibility: "none" },
|
|
59
|
+
paint: {
|
|
60
|
+
"fill-color": COVERAGE_FOG_COLOR,
|
|
61
|
+
// Rows without coverage values render as clear.
|
|
62
|
+
"fill-opacity": ["*", ["coalesce", ["to-number", ["get", fogProperty]], 0], COVERAGE_MAX_FOG_OPACITY],
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The two hidden fog layers, added beneath place labels by the demo.
|
|
69
|
+
*/
|
|
70
|
+
export const CoverageLayers: FillLayerSpecification[] = [
|
|
71
|
+
fogFill(CoverageLayerID.optimistic, "fog_opt"),
|
|
72
|
+
fogFill(CoverageLayerID.honest, "fog"),
|
|
73
|
+
]
|
package/lib/index.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* @author Teffen Ellis, et al.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
export * from "#base
|
|
8
|
-
export * from "#bdc
|
|
9
|
-
export * from "#hspa
|
|
10
|
-
export * from "#styles
|
|
11
|
-
export * from "#tiger
|
|
12
|
-
export * from "#tiles
|
|
7
|
+
export * from "#base"
|
|
8
|
+
export * from "#bdc"
|
|
9
|
+
export * from "#hspa"
|
|
10
|
+
export * from "#styles"
|
|
11
|
+
export * from "#tiger"
|
|
12
|
+
export * from "#tiles"
|