isard 0.0.0-stage → 0.2.1
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/CHANGELOG.md +176 -0
- package/LICENSE +21 -0
- package/README.md +150 -2
- package/dist/basemap.worker.d.ts +76 -0
- package/dist/basemap.worker.js +4 -0
- package/dist/basemap.worker.js.map +13 -0
- package/dist/basemaps.d.ts +48 -0
- package/dist/basemaps.js +97 -0
- package/dist/basemaps.js.map +1 -0
- package/dist/color.d.ts +8 -0
- package/dist/color.js +98 -0
- package/dist/color.js.map +1 -0
- package/dist/controls.d.ts +43 -0
- package/dist/controls.js +115 -0
- package/dist/controls.js.map +1 -0
- package/dist/decoder.worker.js +6 -0
- package/dist/decoder.worker.js.map +12 -0
- package/dist/decoders.d.ts +27 -0
- package/dist/decoders.js +109 -0
- package/dist/decoders.js.map +1 -0
- package/dist/equirectangular.d.ts +35 -0
- package/dist/equirectangular.js +143 -0
- package/dist/equirectangular.js.map +1 -0
- package/dist/extrusions.d.ts +79 -0
- package/dist/extrusions.js +224 -0
- package/dist/extrusions.js.map +1 -0
- package/dist/features.d.ts +159 -0
- package/dist/features.js +387 -0
- package/dist/features.js.map +1 -0
- package/dist/geoplateforme.d.ts +35 -0
- package/dist/geoplateforme.js +56 -0
- package/dist/geoplateforme.js.map +1 -0
- package/dist/glyphs.d.ts +104 -0
- package/dist/glyphs.js +383 -0
- package/dist/glyphs.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction.d.ts +53 -0
- package/dist/interaction.js +259 -0
- package/dist/interaction.js.map +1 -0
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/layers.d.ts +103 -0
- package/dist/layers.js +290 -0
- package/dist/layers.js.map +1 -0
- package/dist/loader.d.ts +30 -0
- package/dist/loader.js +102 -0
- package/dist/loader.js.map +1 -0
- package/dist/map.d.ts +211 -0
- package/dist/map.js +1222 -0
- package/dist/map.js.map +1 -0
- package/dist/mvt.d.ts +19 -0
- package/dist/mvt.js +231 -0
- package/dist/mvt.js.map +1 -0
- package/dist/overlay.d.ts +118 -0
- package/dist/overlay.js +334 -0
- package/dist/overlay.js.map +1 -0
- package/dist/protocol.d.ts +30 -0
- package/dist/protocol.js +2 -0
- package/dist/protocol.js.map +1 -0
- package/dist/style.d.ts +7 -0
- package/dist/style.js +130 -0
- package/dist/style.js.map +1 -0
- package/dist/symbols.d.ts +61 -0
- package/dist/symbols.js +238 -0
- package/dist/symbols.js.map +1 -0
- package/dist/terrain.d.ts +14 -0
- package/dist/terrain.js +56 -0
- package/dist/terrain.js.map +1 -0
- package/dist/types.d.ts +312 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/vectorstyle.d.ts +83 -0
- package/dist/vectorstyle.js +518 -0
- package/dist/vectorstyle.js.map +1 -0
- package/dist/vectortiles.d.ts +124 -0
- package/dist/vectortiles.js +523 -0
- package/dist/vectortiles.js.map +1 -0
- package/dist/wasm/isard.d.ts +612 -0
- package/dist/wasm/isard.js +2623 -0
- package/dist/wasm/isard_core.d.ts +469 -0
- package/dist/wasm/isard_core.js +2385 -0
- package/package.json +49 -4
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/mvt.ts", "../src/color.ts", "../src/vectorstyle.ts", "../src/basemap.worker.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Mapbox Vector Tiles (MVT 2.1) decoding: layers of features with their properties and geometry, in tile units\n * (`extent`, usually 4096 across). Points are lists of points, lines lists of lines, polygons lists of rings (the\n * outer ones clockwise in tile coordinates, y down, holes the other way round, as the specification says).\n */\n\nexport type Value = string | number | boolean;\n\nexport interface TileFeature {\n /** 1 point, 2 line, 3 polygon */\n type: 1 | 2 | 3;\n properties: Record<string, Value>;\n /** Point lists: x0, y0, x1, y1… in tile units */\n geometry: number[][];\n}\n\nexport interface TileLayer {\n extent: number;\n features: TileFeature[];\n}\n\n/** Protobuf reader of a buffer range */\nclass Pbf {\n pos: number;\n constructor(\n private readonly buf: Uint8Array,\n start = 0,\n readonly end = buf.length,\n ) {\n this.pos = start;\n }\n /** An unsigned varint, approximated beyond 2^53; all its bytes are read (up to 10), so the next field is right */\n varint(): number {\n let value = 0;\n for (let shift = 0; shift < 70; shift += 7) {\n const b = this.buf[this.pos++] ?? 0;\n value += (b & 0x7f) * 2 ** shift;\n if (b < 0x80) break;\n }\n return value;\n }\n /** A signed 64-bit varint (two's complement: a negative value takes 10 bytes) */\n int64(): number {\n let lo = 0;\n let hi = 0;\n for (let i = 0; i < 10; i += 1) {\n const b = this.buf[this.pos++] ?? 0;\n const bits = b & 0x7f;\n // Bits 0-27 in the low word, bits 28-31 split, the rest in the high word\n if (i < 4) lo |= bits << (7 * i);\n else if (i === 4) {\n lo |= (bits & 0x0f) << 28;\n hi |= bits >> 4;\n } else hi |= bits << (7 * i - 32);\n if (b < 0x80) break;\n }\n // The high word signed: values from 2^63 up are negative\n return (hi | 0) * 2 ** 32 + (lo >>> 0);\n }\n sint(): number {\n const v = this.varint();\n return v % 2 === 1 ? -(v + 1) / 2 : v / 2;\n }\n /** A length-delimited field as a sub-reader */\n sub(): Pbf {\n const n = this.varint();\n // A length past the end (a truncated tile) stops at the end\n const end = Math.min(this.pos + n, this.end);\n const r = new Pbf(this.buf, this.pos, end);\n this.pos = end;\n return r;\n }\n string(): string {\n const n = this.varint();\n const end = Math.min(this.pos + n, this.end);\n const s = decoder.decode(this.buf.subarray(this.pos, end));\n this.pos = end;\n return s;\n }\n float(): number {\n const v = this.pos + 4 <= this.end ? this.view().getFloat32(this.pos, true) : 0;\n this.pos += 4;\n return v;\n }\n double(): number {\n const v = this.pos + 8 <= this.end ? this.view().getFloat64(this.pos, true) : 0;\n this.pos += 8;\n return v;\n }\n private view(): DataView {\n return new DataView(this.buf.buffer, this.buf.byteOffset, this.buf.byteLength);\n }\n skip(wire: number): void {\n if (wire === 0) this.varint();\n else if (wire === 1) this.pos += 8;\n else if (wire === 2) this.pos += this.varint();\n else if (wire === 5) this.pos += 4;\n }\n get more(): boolean {\n return this.pos < this.end;\n }\n}\n\nconst decoder = new TextDecoder();\n\nfunction value(p: Pbf): Value {\n let v: Value = '';\n while (p.more) {\n const tag = p.varint();\n switch (tag >> 3) {\n case 1:\n v = p.string();\n break;\n case 2:\n v = p.float();\n break;\n case 3:\n v = p.double();\n break;\n case 4:\n v = p.int64();\n break;\n case 5:\n v = p.varint();\n break;\n case 6:\n v = p.sint();\n break;\n case 7:\n v = p.varint() !== 0;\n break;\n default:\n p.skip(tag & 7);\n }\n }\n return v;\n}\n\n/** Point lists of a geometry's commands (MoveTo, LineTo, ClosePath) */\nfunction geometry(p: Pbf): number[][] {\n const out: number[][] = [];\n let current: number[] | undefined;\n let [x, y] = [0, 0];\n while (p.more) {\n const command = p.varint();\n const id = command & 7;\n const count = command >> 3;\n if (id === 7) {\n // ClosePath: back to the first point\n if (current && current.length >= 2) current.push(current[0] ?? 0, current[1] ?? 0);\n continue;\n }\n // A count past the end (a truncated geometry) stops there\n for (let i = 0; i < count && p.more; i += 1) {\n x += p.sint();\n y += p.sint();\n if (id === 1) {\n current = [];\n out.push(current);\n }\n current?.push(x, y);\n }\n }\n return out;\n}\n\n/** Decodes a tile; only the layers in `wanted` (all if undefined) */\nexport function decode(bytes: Uint8Array, wanted?: Set<string>): Map<string, TileLayer> {\n const layers = new Map<string, TileLayer>();\n const tile = new Pbf(bytes);\n while (tile.more) {\n const tag = tile.varint();\n if (tag >> 3 !== 3) {\n tile.skip(tag & 7);\n continue;\n }\n const l = tile.sub();\n let name = '';\n let extent = 4096;\n const keys: string[] = [];\n const values: Value[] = [];\n const raw: Pbf[] = [];\n while (l.more) {\n const t = l.varint();\n switch (t >> 3) {\n case 1:\n name = l.string();\n break;\n case 2:\n raw.push(l.sub());\n break;\n case 3:\n keys.push(l.string());\n break;\n case 4:\n values.push(value(l.sub()));\n break;\n case 5:\n extent = l.varint();\n break;\n default:\n l.skip(t & 7);\n }\n }\n if (wanted && !wanted.has(name)) continue;\n const features: TileFeature[] = [];\n for (const f of raw) {\n let type: 1 | 2 | 3 = 1;\n const properties: Record<string, Value> = {};\n let geom: number[][] = [];\n while (f.more) {\n const t = f.varint();\n switch (t >> 3) {\n case 2: {\n const tags = f.sub();\n while (tags.more) {\n const k = keys[tags.varint()];\n const v = values[tags.varint()];\n if (k !== undefined && v !== undefined) properties[k] = v;\n }\n break;\n }\n case 3:\n type = Math.min(3, Math.max(1, f.varint())) as 1 | 2 | 3;\n break;\n case 4:\n geom = geometry(f.sub());\n break;\n default:\n f.skip(t & 7);\n }\n }\n features.push({ type, properties, geometry: geom });\n }\n layers.set(name, { extent, features });\n }\n return layers;\n}\n",
|
|
6
|
+
"/**\n * CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma\n * or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use\n * it too.\n */\n\nexport type Rgba = [r: number, g: number, b: number, a: number];\n\n/** The CSS named colors, as name and `rrggbb` pairs */\nconst NAMES =\n 'aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 ' +\n 'black 000000 blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 ' +\n 'chartreuse 7fff00 chocolate d2691e coral ff7f50 cornflowerblue 6495ed cornsilk fff8dc crimson dc143c ' +\n 'cyan 00ffff darkblue 00008b darkcyan 008b8b darkgoldenrod b8860b darkgray a9a9a9 darkgreen 006400 ' +\n 'darkgrey a9a9a9 darkkhaki bdb76b darkmagenta 8b008b darkolivegreen 556b2f darkorange ff8c00 darkorchid 9932cc ' +\n 'darkred 8b0000 darksalmon e9967a darkseagreen 8fbc8f darkslateblue 483d8b darkslategray 2f4f4f ' +\n 'darkslategrey 2f4f4f darkturquoise 00ced1 darkviolet 9400d3 deeppink ff1493 deepskyblue 00bfff dimgray 696969 ' +\n 'dimgrey 696969 dodgerblue 1e90ff firebrick b22222 floralwhite fffaf0 forestgreen 228b22 fuchsia ff00ff ' +\n 'gainsboro dcdcdc ghostwhite f8f8ff gold ffd700 goldenrod daa520 gray 808080 green 008000 greenyellow adff2f ' +\n 'grey 808080 honeydew f0fff0 hotpink ff69b4 indianred cd5c5c indigo 4b0082 ivory fffff0 khaki f0e68c ' +\n 'lavender e6e6fa lavenderblush fff0f5 lawngreen 7cfc00 lemonchiffon fffacd lightblue add8e6 lightcoral f08080 ' +\n 'lightcyan e0ffff lightgoldenrodyellow fafad2 lightgray d3d3d3 lightgreen 90ee90 lightgrey d3d3d3 ' +\n 'lightpink ffb6c1 lightsalmon ffa07a lightseagreen 20b2aa lightskyblue 87cefa lightslategray 778899 ' +\n 'lightslategrey 778899 lightsteelblue b0c4de lightyellow ffffe0 lime 00ff00 limegreen 32cd32 linen faf0e6 ' +\n 'magenta ff00ff maroon 800000 mediumaquamarine 66cdaa mediumblue 0000cd mediumorchid ba55d3 ' +\n 'mediumpurple 9370db mediumseagreen 3cb371 mediumslateblue 7b68ee mediumspringgreen 00fa9a ' +\n 'mediumturquoise 48d1cc mediumvioletred c71585 midnightblue 191970 mintcream f5fffa mistyrose ffe4e1 ' +\n 'moccasin ffe4b5 navajowhite ffdead navy 000080 oldlace fdf5e6 olive 808000 olivedrab 6b8e23 orange ffa500 ' +\n 'orangered ff4500 orchid da70d6 palegoldenrod eee8aa palegreen 98fb98 paleturquoise afeeee ' +\n 'palevioletred db7093 papayawhip ffefd5 peachpuff ffdab9 peru cd853f pink ffc0cb plum dda0dd ' +\n 'powderblue b0e0e6 purple 800080 rebeccapurple 663399 red ff0000 rosybrown bc8f8f royalblue 4169e1 ' +\n 'saddlebrown 8b4513 salmon fa8072 sandybrown f4a460 seagreen 2e8b57 seashell fff5ee sienna a0522d ' +\n 'silver c0c0c0 skyblue 87ceeb slateblue 6a5acd slategray 708090 slategrey 708090 snow fffafa ' +\n 'springgreen 00ff7f steelblue 4682b4 tan d2b48c teal 008080 thistle d8bfd8 tomato ff6347 turquoise 40e0d0 ' +\n 'violet ee82ee wheat f5deb3 white ffffff whitesmoke f5f5f5 yellow ffff00 yellowgreen 9acd32';\n\nlet named: Map<string, string> | undefined;\n\nfunction namedHex(name: string): string | undefined {\n if (!named) {\n named = new Map();\n const words = NAMES.split(' ');\n for (let i = 0; i + 1 < words.length; i += 2) named.set(words[i] as string, words[i + 1] as string);\n }\n return named.get(name);\n}\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 0);\n\nfunction hex(digits: string): Rgba | undefined {\n if (!/^[0-9a-f]+$/.test(digits) || ![3, 4, 6, 8].includes(digits.length)) return undefined;\n const full = digits.length <= 4 ? [...digits].map((h) => h + h).join('') : digits;\n const v = (i: number) => Number.parseInt(full.slice(i, i + 2), 16) / 255;\n return [v(0), v(2), v(4), full.length === 8 ? v(6) : 1];\n}\n\n/** An alpha: a number from 0 to 1 or a percentage */\nfunction alpha(p: string | undefined): number {\n if (p === undefined) return 1;\n return clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));\n}\n\nfunction hsl(h: number, s: number, l: number): [number, number, number] {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const hue = (t: number) => {\n const u = ((t % 1) + 1) % 1;\n if (u < 1 / 6) return p + (q - p) * 6 * u;\n if (u < 1 / 2) return q;\n if (u < 2 / 3) return p + (q - p) * (2 / 3 - u) * 6;\n return p;\n };\n return [hue(h + 1 / 3), hue(h), hue(h - 1 / 3)];\n}\n\n/** A CSS color to RGBA 0-1; undefined if it is not one */\nexport function parseCssColor(value: unknown): Rgba | undefined {\n if (typeof value !== 'string') return undefined;\n const c = value.trim().toLowerCase();\n if (c.startsWith('#')) return hex(c.slice(1));\n if (c === 'transparent') return [0, 0, 0, 0];\n const name = namedHex(c);\n if (name) return hex(name);\n const match = /^(rgba?|hsla?)\\(([^)]*)\\)$/.exec(c);\n if (!match?.[1] || match[2] === undefined) return undefined;\n const parts = match[2].split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3 || parts.slice(0, 3).some((p) => Number.isNaN(Number.parseFloat(p)))) return undefined;\n const a = alpha(parts[3]);\n if (match[1].startsWith('rgb')) {\n const channel = (p: string) => clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);\n return [channel(parts[0] as string), channel(parts[1] as string), channel(parts[2] as string), a];\n }\n const h = Number.parseFloat(parts[0] as string) / 360;\n const [r, g, b] = hsl(\n h,\n clamp(Number.parseFloat(parts[1] as string) / 100),\n clamp(Number.parseFloat(parts[2] as string) / 100),\n );\n return [r, g, b, a];\n}\n",
|
|
7
|
+
"/**\n * The parts of the MapLibre style specification a vector basemap needs, evaluated on the page: filters (legacy\n * `[\"==\", \"key\", value]` forms and expressions), property values given as constants, legacy functions (`{ stops }`\n * of zoom or of a property: exponential, interval, categorical, identity) or expressions (`get`, `has`, `concat`,\n * `interpolate`, `step`, `match`, `case`, `coalesce`, comparisons, `all`, `any`, `!`, `in`, `zoom`, arithmetic,\n * `format`, conversions and assertions, `upcase`, `downcase`, `literal`…; others give null, with a warning), colors\n * interpolated in RGBA, `{token}` text fields.\n */\nimport { parseCssColor } from './color.ts';\nimport type { TileFeature, Value } from './mvt.ts';\n\nexport type Json = null | boolean | number | string | Json[] | { [key: string]: Json };\n\nexport interface StyleLayer {\n id: string;\n type: string;\n source?: string;\n 'source-layer'?: string;\n minzoom?: number;\n maxzoom?: number;\n filter?: Json;\n layout?: Record<string, Json>;\n paint?: Record<string, Json>;\n}\n\nexport interface Style {\n version: number;\n sources: Record<\n string,\n { type: string; tiles?: string[]; url?: string; maxzoom?: number; minzoom?: number; tileSize?: number }\n >;\n layers: StyleLayer[];\n glyphs?: string;\n sprite?: string;\n}\n\n/** A raster source of a style: its tile URL, its deepest level and the CSS pixels of its tiles (MapLibre's\n * `tileSize`: 512 by default) */\nexport interface RasterSource {\n tiles: string;\n maxzoom: number;\n tileSize: number;\n}\n\n/** A label to shape and place, in style terms evaluated at the tile's zoom */\nexport interface LabelCandidate {\n /** Index of its style layer: higher ones are placed first */\n layer: number;\n text: string;\n lon: number;\n lat: number;\n /** Along a line: the direction there (degrees of longitude and latitude) */\n along?: [number, number];\n font: string;\n size: Json;\n color: string;\n haloColor: string;\n haloWidth: number;\n anchor: string;\n offset: [number, number];\n maxWidth: number;\n lineHeight: number;\n overlap: boolean;\n}\n\n/** What expressions see of a feature */\nexport interface Context {\n zoom: number;\n properties: Record<string, Value>;\n /** 'Point', 'LineString' or 'Polygon' */\n type: string;\n}\n\nconst TYPES = ['Unknown', 'Point', 'LineString', 'Polygon'];\n\nexport function context(feature: TileFeature, zoom: number): Context {\n return { zoom, properties: feature.properties, type: TYPES[feature.type] ?? 'Unknown' };\n}\n\n// ── Colors ──\n\n/** A color to RGBA 0-1, undefined if it is not one */\nexport function color(value: unknown): [number, number, number, number] | undefined {\n return parseCssColor(value);\n}\n\nexport function css([r, g, b, a]: [number, number, number, number]): string {\n return `rgba(${Math.round(r * 255)},${Math.round(g * 255)},${Math.round(b * 255)},${a})`;\n}\n\n// ── Interpolation ──\n\n/** Factor between two stops: linear, or exponential of `base` */\nfunction factor(x: number, x0: number, x1: number, base = 1): number {\n const d = x1 - x0;\n if (d === 0) return 0;\n const t = x - x0;\n return base === 1 ? t / d : (base ** t - 1) / (base ** d - 1);\n}\n\nfunction mix(a: unknown, b: unknown, t: number): unknown {\n if (typeof a === 'number' && typeof b === 'number') return a + (b - a) * t;\n const ca = color(a);\n const cb = color(b);\n if (ca && cb)\n return css(\n [0, 1, 2, 3].map((i) => (ca[i] ?? 0) + ((cb[i] ?? 0) - (ca[i] ?? 0)) * t) as [number, number, number, number],\n );\n if (Array.isArray(a) && Array.isArray(b)) return a.map((v, i) => mix(v, b[i], t));\n return t < 0.5 ? a : b;\n}\n\n// ── Legacy functions ──\n\ninterface LegacyFunction {\n stops: [Json, Json][];\n base?: number;\n type?: string;\n property?: string;\n default?: Json;\n}\n\nfunction isFunction(v: Json): v is { [key: string]: Json } & LegacyFunction {\n return typeof v === 'object' && v !== null && !Array.isArray(v) && Array.isArray((v as { stops?: Json }).stops);\n}\n\nfunction legacy(f: LegacyFunction, ctx: Context): unknown {\n const input = f.property === undefined ? ctx.zoom : ctx.properties[f.property];\n const stops = f.stops;\n const type =\n f.type ?? (f.property === undefined || typeof stops[0]?.[0] === 'number' ? 'exponential' : 'categorical');\n if (type === 'identity') return input ?? f.default;\n if (type === 'categorical') return stops.find(([k]) => k === input)?.[1] ?? f.default;\n if (typeof input !== 'number' || !stops.length) return f.default ?? stops[0]?.[1];\n // Zoom-and-property stops ({ zoom, value } keys) are taken at their zoom only\n const key = (s: [Json, Json]) =>\n typeof s[0] === 'object' && s[0] !== null ? Number((s[0] as { zoom?: number }).zoom) : Number(s[0]);\n const first = stops[0];\n if (!first) return f.default;\n if (input <= key(first)) return first[1];\n for (let i = 1; i < stops.length; i += 1) {\n const [s0, s1] = [stops[i - 1], stops[i]];\n if (!s0 || !s1) continue;\n if (input < key(s1)) {\n if (type === 'interval') return s0[1];\n return mix(s0[1], s1[1], factor(input, key(s0), key(s1), f.base ?? 1));\n }\n }\n return stops.at(-1)?.[1];\n}\n\n// ── Expressions ──\n\nfunction get(ctx: Context, key: unknown): unknown {\n if (key === '$type') return ctx.type;\n return typeof key === 'string' ? ctx.properties[key] : undefined;\n}\n\n/** The operators `evaluate` knows */\nconst OPERATORS = new Set([\n 'literal',\n 'zoom',\n 'get',\n 'has',\n '!has',\n 'properties',\n 'id',\n 'geometry-type',\n 'concat',\n 'format',\n 'image',\n 'number-format',\n 'to-number',\n 'to-string',\n 'to-boolean',\n 'to-color',\n 'number',\n 'string',\n 'boolean',\n 'typeof',\n 'length',\n 'at',\n 'upcase',\n 'downcase',\n 'coalesce',\n '!',\n 'all',\n 'any',\n '==',\n '!=',\n '<',\n '<=',\n '>',\n '>=',\n 'in',\n 'case',\n 'match',\n 'step',\n 'interpolate',\n 'interpolate-hcl',\n 'interpolate-lab',\n 'rgb',\n 'rgba',\n '+',\n '-',\n '*',\n '/',\n '%',\n '^',\n 'min',\n 'max',\n 'abs',\n 'round',\n 'floor',\n 'ceil',\n 'sqrt',\n 'ln',\n 'log10',\n 'log2',\n 'pi',\n 'e',\n]);\n\n/** Whether a value is an expression (an array starting with a known operator), not a literal array */\nexport function isExpression(e: unknown): e is Json[] {\n return Array.isArray(e) && typeof e[0] === 'string' && OPERATORS.has(e[0]);\n}\n\n/** Operators already warned about */\nconst warned = new Set<string>();\n\nconst str = (v: unknown) => (v === undefined || v === null ? '' : String(v));\n\nexport function evaluate(e: Json, ctx: Context): unknown {\n if (isFunction(e)) return legacy(e, ctx);\n if (!Array.isArray(e)) return e;\n const [op, ...args] = e;\n if (typeof op !== 'string') return e;\n const ev = (i: number) => evaluate(args[i] ?? null, ctx);\n const num = (i: number) => Number(ev(i));\n const nums = () => args.map((_, i) => num(i));\n switch (op) {\n case 'literal':\n return args[0];\n case 'zoom':\n return ctx.zoom;\n case 'get':\n return get(ctx, ev(0));\n case 'has':\n return get(ctx, ev(0)) !== undefined;\n case '!has':\n return get(ctx, ev(0)) === undefined;\n case 'properties':\n return ctx.properties;\n case 'id':\n return null;\n case 'geometry-type':\n return ctx.type;\n case 'concat':\n return args.map((_, i) => str(ev(i))).join('');\n case 'format':\n // Its text sections, the options of each (objects) left out\n return args.map((a, i) => (a !== null && typeof a === 'object' && !Array.isArray(a) ? '' : str(ev(i)))).join('');\n case 'image':\n return ev(0);\n case 'number-format': {\n const options = (args[1] ?? {}) as {\n locale?: string;\n 'min-fraction-digits'?: number;\n 'max-fraction-digits'?: number;\n };\n const n = num(0);\n if (!Number.isFinite(n)) return '';\n return n.toLocaleString(options.locale, {\n minimumFractionDigits: options['min-fraction-digits'],\n maximumFractionDigits: options['max-fraction-digits'],\n });\n }\n case 'to-number': {\n for (let i = 0; i < args.length; i += 1) {\n const v = ev(i);\n const n = typeof v === 'string' && v.trim() === '' ? Number.NaN : Number(v);\n if (v !== null && v !== undefined && !Number.isNaN(n)) return n;\n }\n return 0;\n }\n case 'to-string':\n return str(ev(0));\n case 'to-boolean': {\n const v = ev(0);\n return !(v === '' || v === 0 || v === false || v === null || v === undefined || Number.isNaN(v));\n }\n case 'to-color':\n case 'number':\n case 'string':\n case 'boolean': {\n // Assertions: the first value of the type, else the last one\n const types: Record<string, (v: unknown) => boolean> = {\n 'to-color': (v) => color(v) !== undefined,\n number: (v) => typeof v === 'number',\n string: (v) => typeof v === 'string',\n boolean: (v) => typeof v === 'boolean',\n };\n for (let i = 0; i < args.length; i += 1) {\n const v = ev(i);\n if (types[op]?.(v)) return v;\n }\n return args.length ? ev(args.length - 1) : null;\n }\n case 'typeof': {\n const v = ev(0);\n if (v === null || v === undefined) return 'null';\n return Array.isArray(v) ? 'array' : typeof v;\n }\n case 'length': {\n const v = ev(0);\n return typeof v === 'string' || Array.isArray(v) ? v.length : 0;\n }\n case 'at': {\n const v = ev(1);\n return Array.isArray(v) ? (v[num(0)] ?? null) : null;\n }\n case 'upcase':\n return str(ev(0)).toUpperCase();\n case 'downcase':\n return str(ev(0)).toLowerCase();\n case 'coalesce':\n for (let i = 0; i < args.length; i += 1) {\n const v = ev(i);\n if (v !== undefined && v !== null) return v;\n }\n return null;\n case '!':\n return !ev(0);\n case 'all':\n return args.every((_, i) => Boolean(ev(i)));\n case 'any':\n return args.some((_, i) => Boolean(ev(i)));\n case '==':\n return ev(0) === ev(1);\n case '!=':\n return ev(0) !== ev(1);\n case '<':\n return (ev(0) as number) < (ev(1) as number);\n case '<=':\n return (ev(0) as number) <= (ev(1) as number);\n case '>':\n return (ev(0) as number) > (ev(1) as number);\n case '>=':\n return (ev(0) as number) >= (ev(1) as number);\n case 'in': {\n const haystack = ev(1);\n const needle = ev(0);\n if (typeof haystack === 'string') return haystack.includes(String(needle));\n return Array.isArray(haystack) && haystack.includes(needle as Json);\n }\n case 'case': {\n for (let i = 0; i + 1 < args.length; i += 2) if (ev(i)) return ev(i + 1);\n return ev(args.length - 1);\n }\n case 'match': {\n const input = ev(0);\n for (let i = 1; i + 1 < args.length; i += 2) {\n const label = args[i];\n if (Array.isArray(label) ? label.includes(input as Json) : label === input) return ev(i + 1);\n }\n return ev(args.length - 1);\n }\n case 'step': {\n const input = num(0);\n let out = ev(1);\n for (let i = 2; i + 1 < args.length; i += 2) {\n if (input >= Number(args[i])) out = ev(i + 1);\n else break;\n }\n return out;\n }\n case 'interpolate':\n case 'interpolate-hcl':\n case 'interpolate-lab': {\n const kind = args[0];\n const input = num(1);\n const base = Array.isArray(kind) && kind[0] === 'exponential' ? Number(kind[1]) : 1;\n const stops: [number, Json][] = [];\n for (let i = 2; i + 1 < args.length; i += 2) stops.push([Number(args[i]), args[i + 1] ?? null]);\n const first = stops[0];\n if (!first) return null;\n if (input <= first[0]) return evaluate(first[1], ctx);\n for (let i = 1; i < stops.length; i += 1) {\n const [s0, s1] = [stops[i - 1], stops[i]];\n if (s0 && s1 && input < s1[0])\n return mix(evaluate(s0[1], ctx), evaluate(s1[1], ctx), factor(input, s0[0], s1[0], base));\n }\n return evaluate(stops.at(-1)?.[1] ?? null, ctx);\n }\n case 'rgb':\n case 'rgba':\n return css([num(0) / 255, num(1) / 255, num(2) / 255, args.length > 3 ? num(3) : 1]);\n case '+':\n return nums().reduce((a, b) => a + b, 0);\n case '*':\n return nums().reduce((a, b) => a * b, 1);\n case '-':\n return args.length === 1 ? -num(0) : num(0) - num(1);\n case '/':\n return num(0) / num(1);\n case '%':\n return num(0) % num(1);\n case '^':\n return num(0) ** num(1);\n case 'min':\n return Math.min(...nums());\n case 'max':\n return Math.max(...nums());\n case 'abs':\n return Math.abs(num(0));\n case 'round':\n // Half away from zero, as MapLibre\n return Math.sign(num(0)) * Math.round(Math.abs(num(0)));\n case 'floor':\n return Math.floor(num(0));\n case 'ceil':\n return Math.ceil(num(0));\n case 'sqrt':\n return Math.sqrt(num(0));\n case 'ln':\n return Math.log(num(0));\n case 'log10':\n return Math.log10(num(0));\n case 'log2':\n return Math.log2(num(0));\n case 'pi':\n return Math.PI;\n case 'e':\n return Math.E;\n default:\n // Unsupported: no value (a filter drops the feature, a property takes its default)\n if (!warned.has(op)) {\n warned.add(op);\n console.warn(`isard: the style expression \"${op}\" is not supported`);\n }\n return null;\n }\n}\n\n// ── Filters ──\n\nconst LEGACY_COMPARISONS = new Set(['==', '!=', '<', '<=', '>', '>=']);\n\n/** Whether a filter (not `all`, `any`, `none`) is in the legacy form: `[\"==\", \"key\", value]`, `[\"in\", \"key\", a, b]`,\n * `[\"has\", \"key\"]`; a key and literal values, as MapLibre tells them from expressions */\nfunction isLegacyLeaf(f: Json[]): boolean {\n const [op, a, ...rest] = f;\n if (typeof op !== 'string' || typeof a !== 'string' || rest.some(Array.isArray)) return false;\n if (LEGACY_COMPARISONS.has(op)) return f.length === 3;\n if (op === 'in') return f.length !== 3 || !Array.isArray(f[2]);\n return op === '!in' || op === 'has' || op === '!has';\n}\n\nfunction legacyFilter(f: Json[], ctx: Context): boolean {\n const [op, key, ...rest] = f;\n const v = get(ctx, key);\n switch (op) {\n case '==':\n return v === rest[0];\n case '!=':\n return v !== rest[0];\n case '<':\n return (v as number) < (rest[0] as number);\n case '<=':\n return (v as number) <= (rest[0] as number);\n case '>':\n return (v as number) > (rest[0] as number);\n case '>=':\n return (v as number) >= (rest[0] as number);\n case 'in':\n return rest.includes(v as Json);\n case '!in':\n return !rest.includes(v as Json);\n case 'has':\n return v !== undefined;\n case '!has':\n return v === undefined;\n default:\n return true;\n }\n}\n\ntype Test = (ctx: Context) => boolean;\n\n/** Compiled filters, by filter object */\nconst compiled = new WeakMap<Json[], Test>();\n\n/** A filter as a function: `all`, `any`, `none` of their parts, each part legacy or an expression (they may mix) */\nfunction compile(f: Json): Test {\n if (!Array.isArray(f)) return () => Boolean(f);\n const hit = compiled.get(f);\n if (hit) return hit;\n let test: Test;\n const op = f[0];\n if (op === 'all' || op === 'any' || op === 'none') {\n const parts = f.slice(1).map(compile);\n if (op === 'all') test = (ctx) => parts.every((p) => p(ctx));\n else if (op === 'any') test = (ctx) => parts.some((p) => p(ctx));\n else test = (ctx) => !parts.some((p) => p(ctx));\n } else if (isLegacyLeaf(f)) {\n test = (ctx) => legacyFilter(f, ctx);\n } else {\n test = (ctx) => Boolean(evaluate(f, ctx));\n }\n compiled.set(f, test);\n return test;\n}\n\nexport function filter(f: Json | undefined, ctx: Context): boolean {\n if (f === undefined || f === null) return true;\n return compile(f)(ctx);\n}\n\n/** Whether a value depends on the feature (else only on the zoom, evaluated once per tile) */\nexport function isFeatureDependent(e: Json | undefined): boolean {\n if (e !== undefined && isFunction(e)) return e.property !== undefined;\n if (!Array.isArray(e)) return false;\n if (['get', 'has', '!has', 'geometry-type', 'properties', 'id'].includes(e[0] as string)) return true;\n return e.some((x) => isFeatureDependent(x));\n}\n\n/** A `{token}` text field (or an expression) to the text of a feature */\nexport function text(field: Json | undefined, ctx: Context): string {\n if (field === undefined || field === null) return '';\n if (typeof field === 'string') {\n return field.replace(/\\{([^}]+)\\}/g, (_, key: string) => {\n const v = ctx.properties[key];\n return v === undefined ? '' : String(v);\n });\n }\n const v = evaluate(field, ctx);\n if (Array.isArray(v)) {\n // A `format` value: its strings\n return v.filter((x) => typeof x === 'string').join('');\n }\n return v === undefined || v === null ? '' : String(v);\n}\n\n/** The font of a label from the first of its `text-font`: a family without its weight takes the regular one */\nexport function labelFont(font: string): string {\n return /Regular|Bold|Italic|Semibold|Light|Medium|Black/.test(font) ? font : `${font} Regular`;\n}\n\n/**\n * A value of the zoom only (an expression: `interpolate`, `step` of `[\"zoom\"]`) as stops `[[zoom, value], …]` for the\n * engine, which interpolates them linearly: evaluated at its own stops and at the whole zooms between (an exponential\n * curve followed closely), a step kept sharp just before its threshold\n */\nexport function zoomStops(e: Json): [number, number][] {\n const zooms = new Set<number>();\n const walk = (x: Json) => {\n if (!Array.isArray(x)) return;\n const zoomInput = (input: Json | undefined) => Array.isArray(input) && input[0] === 'zoom';\n if ((x[0] === 'interpolate' || x[0] === 'interpolate-hcl' || x[0] === 'interpolate-lab') && zoomInput(x[2])) {\n for (let i = 3; i < x.length; i += 2) zooms.add(Number(x[i]));\n } else if (x[0] === 'step' && zoomInput(x[1])) {\n for (let i = 3; i < x.length; i += 2) {\n const t = Number(x[i]);\n zooms.add(t);\n zooms.add(t - 0.01);\n }\n }\n for (const y of x) walk(y);\n };\n walk(e);\n const finite = [...zooms].filter(Number.isFinite);\n if (finite.length === 0) finite.push(0);\n const [lo, hi] = [Math.min(...finite), Math.max(...finite)];\n for (let z = Math.ceil(lo); z <= Math.floor(hi); z += 1) finite.push(z);\n return [...new Set(finite)]\n .sort((a, b) => a - b)\n .map((zoom) => [zoom, Number(evaluate(e, { zoom, properties: {}, type: 'Unknown' }))]);\n}\n",
|
|
8
|
+
"/**\n * Worker of the vector basemaps: fetches and decodes vector tiles (kept for the tiles that share them), draws their\n * fills, lines and circles with a MapLibre style into images (Canvas 2D, off the main thread) for the raster pool,\n * with the style's raster layers under them, and lists the label candidates of the style's symbol layers for the page\n * to shape and place. Extrusions are drawn flat, as fills.\n *\n * A raster tile of level z covers 256 CSS pixels at map zoom z - 1 (MapLibre's 512 px convention): it is drawn from\n * the vector tile of level z - 1 (or the deepest one the source has), with the style at that zoom.\n */\nimport { decode, type TileFeature, type TileLayer } from './mvt.ts';\nimport {\n type Context,\n color,\n context,\n css,\n evaluate,\n filter,\n isExpression,\n isFeatureDependent,\n type Json,\n type LabelCandidate,\n labelFont,\n type RasterSource,\n type StyleLayer,\n text,\n zoomStops,\n} from './vectorstyle.ts';\n\nexport type { LabelCandidate, RasterSource };\n\n/** Fetch priority of a request (`fetch`'s `priority`, a hint to the browser) */\nexport type Priority = 'high' | 'low' | 'auto';\n\n/** A tile's image or labels, asked of a worker */\nexport type BasemapWork =\n | { type: 'render'; key: string; z: number; x: number; y: number; size: number; priority?: Priority }\n | { type: 'labels'; key: string; z: number; x: number; y: number; priority?: Priority };\n\nexport type BasemapRequest =\n | {\n type: 'init';\n /** Renderers by key: each draws its own layers of the same source */\n key: string;\n tiles: string;\n maxzoom: number;\n layers: StyleLayer[];\n /** The style's raster sources, by name, for its raster layers */\n rasters?: Record<string, RasterSource>;\n /** The style's sprite, for the fill patterns (loaded once by the page) */\n sprite?: Sprite;\n /** Workers of the pool: each keeps its share of the decoded tiles */\n workers?: number;\n }\n | (BasemapWork & { id: number })\n | { type: 'abort'; id: number }\n /** A renderer no longer used: forgotten */\n | { type: 'drop'; key: string };\n\nexport type BasemapResponse =\n | { id: number; image: ImageBitmap }\n | { id: number; missing: true }\n | { id: number; error: string }\n | { id: number; labels: LabelCandidate[] };\n\ninterface Renderer {\n tiles: string;\n maxzoom: number;\n layers: StyleLayer[];\n rasters: Record<string, RasterSource>;\n sprite: Sprite | undefined;\n /** Fill patterns by icon name, cut from the sprite once */\n patterns: Map<string, OffscreenCanvas | undefined>;\n}\n\nexport interface Sprite {\n image: ImageBitmap;\n icons: Record<string, { x: number; y: number; width: number; height: number; pixelRatio?: number }>;\n}\n\nconst renderers = new Map<string, Renderer>();\n/** Decoded tiles by URL, the most recent last */\nconst cache = new Map<string, Promise<Map<string, TileLayer> | undefined>>();\n/** Decoded tiles kept by the pool, shared among its workers (a vector tile always goes to the same worker): some\n * 2 MB each */\nconst CACHE = 96;\n/** This worker's share, set by the renderers */\nlet cacheSize = CACHE;\n\n/** The decoded tiles one worker of `workers` keeps */\nexport function cacheShare(workers: number): number {\n return Math.max(16, Math.ceil(CACHE / Math.max(1, workers)));\n}\n/** Requests in progress, and those of them aborted (both forgotten once answered) */\nconst active = new Set<number>();\nconst aborted = new Set<number>();\n\n/** Images of the raster sources by URL, the most recent last */\nconst images = new Map<string, Promise<ImageBitmap | undefined>>();\nconst IMAGES = 64;\n\n/** An image of a raster source (shared by every renderer); undefined where the source has none */\nfunction image(url: string, priority: Priority = 'auto'): Promise<ImageBitmap | undefined> {\n const hit = images.get(url);\n if (hit) {\n images.delete(url);\n images.set(url, hit);\n return hit;\n }\n const pending = (async () => {\n const init: PriorityInit = { priority };\n const response = await fetch(url, init);\n if (response.status === 404 || response.status === 204) return undefined;\n if (!response.ok) throw new Error(`${url}: ${response.status}`);\n return createImageBitmap(await response.blob());\n })();\n pending.catch(() => images.delete(url));\n images.set(url, pending);\n while (images.size > IMAGES) {\n const [oldest, evicted] = images.entries().next().value ?? [];\n if (oldest === undefined || evicted === undefined) break;\n images.delete(oldest);\n // Freed once settled, after the renders that awaited it have drawn it (they draw without awaiting again)\n evicted.then(\n (bitmap) => setTimeout(() => bitmap?.close(), 0),\n () => undefined,\n );\n }\n return pending;\n}\n\n/** `RequestInit` with the fetch priority, which the TypeScript DOM library may not know yet */\ntype PriorityInit = RequestInit & { priority?: Priority };\n\n/** A vector tile, decoded (shared by every renderer of its URL); the first request's priority fetches it */\nfunction tile(url: string, priority: Priority = 'auto'): Promise<Map<string, TileLayer> | undefined> {\n const hit = cache.get(url);\n if (hit) {\n cache.delete(url);\n cache.set(url, hit);\n return hit;\n }\n const pending = (async () => {\n for (let attempt = 0; ; attempt += 1) {\n const init: PriorityInit = { priority };\n const response = await fetch(url, init);\n if (response.status === 404 || response.status === 204) return undefined;\n if (response.ok) {\n // Every layer: renderers of other subsets share the tile\n return decode(new Uint8Array(await response.arrayBuffer()));\n }\n if (attempt >= 2) throw new Error(`${url}: ${response.status}`);\n await new Promise((r) => setTimeout(r, 400 * (attempt + 1)));\n }\n })();\n pending.catch(() => cache.delete(url));\n cache.set(url, pending);\n while (cache.size > cacheSize) {\n const oldest = cache.keys().next().value;\n if (oldest === undefined) break;\n cache.delete(oldest);\n }\n return pending;\n}\n\n/** The vector tile to draw a raster tile from, and where the raster tile lies in it (tile units) */\nfunction source(r: Renderer, z: number, x: number, y: number) {\n const vz = Math.max(0, Math.min(z - 1, r.maxzoom));\n const d = z - vz;\n const n = 2 ** Math.max(0, d);\n const [vx, vy] = d >= 0 ? [Math.floor(x / n), Math.floor(y / n)] : [x, y];\n const url = r.tiles.replace('{z}', String(vz)).replace('{x}', String(vx)).replace('{y}', String(vy));\n // Fraction of the vector tile covered, and the offset in it\n const part = 1 / n;\n return { url, vz, vx, vy, part, ox: (x % n) * part, oy: (y % n) * part };\n}\n\nconst value = (layer: StyleLayer, group: 'paint' | 'layout', key: string, ctx: Context, fallback: unknown) => {\n const v = layer[group]?.[key];\n if (v === undefined) return fallback;\n // An array that is not an expression is a literal value (`text-font`, `text-offset`, `line-dasharray`)\n const out = Array.isArray(v) && !isExpression(v) ? v : evaluate(v, ctx);\n return out === undefined || out === null ? fallback : out;\n};\n\n/** A color with an opacity, for the canvas */\nfunction paint(c: unknown, opacity: number): string {\n const rgba = color(c) ?? [0, 0, 0, 1];\n return css([rgba[0], rgba[1], rgba[2], rgba[3] * opacity]);\n}\n\nfunction shown(layer: StyleLayer, zoom: number): boolean {\n if (layer.layout?.visibility === 'none') return false;\n return zoom >= (layer.minzoom ?? 0) && zoom < (layer.maxzoom ?? 24);\n}\n\n/** The image of a fill pattern, cut from the sprite on first use */\nfunction patternImage(r: Renderer, name: string): OffscreenCanvas | undefined {\n if (r.patterns.has(name)) return r.patterns.get(name);\n const icon = r.sprite?.icons[name];\n let image: OffscreenCanvas | undefined;\n if (r.sprite && icon && icon.width > 0 && icon.height > 0) {\n image = new OffscreenCanvas(icon.width, icon.height);\n image\n .getContext('2d')\n ?.drawImage(r.sprite.image, icon.x, icon.y, icon.width, icon.height, 0, 0, icon.width, icon.height);\n }\n r.patterns.set(name, image);\n return image;\n}\n\n/** Canvases free for the next tiles, by size: one per tile being drawn at most */\nconst canvases = new Map<number, OffscreenCanvas[]>();\n\n/** A blank canvas of `size` pixels and its context, from the free ones if any */\nfunction takeCanvas(size: number): { canvas: OffscreenCanvas; g: OffscreenCanvasRenderingContext2D } {\n const canvas = canvases.get(size)?.pop() ?? new OffscreenCanvas(size, size);\n // A canvas on the CPU: its pixels are read back here, in the worker, not on the main thread at the upload\n const g = canvas.getContext('2d', { willReadFrequently: true });\n if (!g) throw new Error('no 2D context');\n // The state a former tile left\n g.setTransform(1, 0, 0, 1, 0, 0);\n g.globalAlpha = 1;\n g.setLineDash([]);\n g.clearRect(0, 0, size, size);\n return { canvas, g };\n}\n\nfunction giveCanvas(canvas: OffscreenCanvas): void {\n const free = canvases.get(canvas.width) ?? [];\n canvases.set(canvas.width, free);\n if (free.length < 4) free.push(canvas);\n}\n\n/**\n * The image of a drawn canvas, its alpha straight (the engine blends straight alpha). An opaque tile (a background\n * of full opacity, as a basemap's) is moved out of the canvas as it is, premultiplied and straight being the same\n * there; another one is read back unpremultiplied, copied\n */\nexport function tileImage(\n canvas: OffscreenCanvas,\n g: OffscreenCanvasRenderingContext2D,\n opaque: boolean,\n): Promise<ImageBitmap> {\n if (opaque) return Promise.resolve(canvas.transferToImageBitmap());\n return createImageBitmap(g.getImageData(0, 0, canvas.width, canvas.height), { premultiplyAlpha: 'none' });\n}\n\nasync function render(r: Renderer, z: number, x: number, y: number, size: number, id: number, priority?: Priority) {\n const s = source(r, z, x, y);\n const layers = await tile(s.url, priority);\n if (aborted.has(id)) return undefined;\n const { canvas, g } = takeCanvas(size);\n try {\n return await draw(r, s, layers, canvas, g, z, x, y, size, id, priority);\n } finally {\n giveCanvas(canvas);\n }\n}\n\nasync function draw(\n r: Renderer,\n s: ReturnType<typeof source>,\n layers: Map<string, TileLayer> | undefined,\n canvas: OffscreenCanvas,\n g: OffscreenCanvasRenderingContext2D,\n z: number,\n x: number,\n y: number,\n size: number,\n id: number,\n priority?: Priority,\n) {\n const sprite = r.sprite;\n const zoom = Math.max(0, z - 1);\n // CSS pixels to canvas pixels: the tile is 256 CSS pixels across at its zoom\n const px = size / 256;\n let drawn = false;\n /** A background of full opacity covers the tile: every pixel stays opaque */\n let opaque = false;\n for (const layer of r.layers) {\n if (!shown(layer, zoom)) continue;\n const zctx: Context = { zoom, properties: {}, type: 'Unknown' };\n if (layer.type === 'background') {\n const fill = value(layer, 'paint', 'background-color', zctx, '#000');\n const opacity = Number(value(layer, 'paint', 'background-opacity', zctx, 1));\n g.fillStyle = paint(fill, opacity);\n g.fillRect(0, 0, size, size);\n if ((color(fill) ?? [0, 0, 0, 1])[3] * opacity >= 1) opaque = true;\n drawn = true;\n continue;\n }\n if (layer.type === 'raster') {\n const source = layer.source === undefined ? undefined : r.rasters[layer.source];\n if (!source) continue;\n // The canvas covers the Web Mercator tile (z, x, y): a source tile of 512 px covers it from a level coarser\n const rz = Math.max(0, Math.min(z - (source.tileSize >= 512 ? 1 : 0), source.maxzoom));\n const n = 2 ** (z - rz);\n const url = source.tiles\n .replace('{z}', String(rz))\n .replace('{x}', String(Math.floor(x / n)))\n .replace('{y}', String(Math.floor(y / n)));\n const picture = await image(url, priority).catch(() => undefined);\n if (aborted.has(id)) return undefined;\n if (!picture) continue;\n const [w, h] = [picture.width / n, picture.height / n];\n g.globalAlpha = Number(value(layer, 'paint', 'raster-opacity', zctx, 1));\n g.drawImage(picture, (x % n) * w, (y % n) * h, w, h, 0, 0, size, size);\n g.globalAlpha = 1;\n drawn = true;\n continue;\n }\n const data = layers?.get(layer['source-layer'] ?? '');\n if (!data) continue;\n // Tile units to canvas pixels\n const k = size / (data.extent * s.part);\n const [ox, oy] = [s.ox * data.extent, s.oy * data.extent];\n const path = (f: TileFeature, close: boolean) => {\n g.beginPath();\n for (const line of f.geometry) {\n for (let i = 0; i + 1 < line.length; i += 2) {\n const [lx, ly] = [((line[i] ?? 0) - ox) * k, ((line[i + 1] ?? 0) - oy) * k];\n if (i === 0) g.moveTo(lx, ly);\n else g.lineTo(lx, ly);\n }\n if (close) g.closePath();\n }\n };\n // Values that only depend on the zoom are evaluated once for the layer\n const dependent = new Map<string, boolean>();\n const get = (group: 'paint' | 'layout', key: string, ctx: Context, fallback: unknown) => {\n let d = dependent.get(key);\n if (d === undefined) {\n d = isFeatureDependent(layer[group]?.[key]);\n dependent.set(key, d);\n }\n return value(layer, group, key, d ? ctx : zctx, fallback);\n };\n for (const f of data.features) {\n const ctx = context(f, zoom);\n if (!filter(layer.filter, ctx)) continue;\n if (layer.type === 'fill-extrusion' && f.type === 3) {\n // Flat, seen from above: its color\n path(f, true);\n g.fillStyle = paint(\n get('paint', 'fill-extrusion-color', ctx, '#000'),\n Number(get('paint', 'fill-extrusion-opacity', ctx, 1)),\n );\n g.fill('evenodd');\n drawn = true;\n } else if (layer.type === 'fill' && f.type === 3) {\n const opacity = Number(get('paint', 'fill-opacity', ctx, 1));\n const pattern = get('paint', 'fill-pattern', ctx, undefined);\n path(f, true);\n const icon = typeof pattern === 'string' ? sprite?.icons[pattern] : undefined;\n const image = icon && patternImage(r, pattern as string);\n if (icon && image) {\n const p = g.createPattern(image, 'repeat');\n if (p) {\n p.setTransform(new DOMMatrix().scale(px / (icon.pixelRatio ?? 1)));\n g.globalAlpha = opacity;\n g.fillStyle = p;\n g.fill('evenodd');\n g.globalAlpha = 1;\n }\n } else {\n g.fillStyle = paint(get('paint', 'fill-color', ctx, '#000'), opacity);\n g.fill('evenodd');\n const outline = get('paint', 'fill-outline-color', ctx, undefined);\n if (outline !== undefined) {\n g.strokeStyle = paint(outline, opacity);\n g.lineWidth = px;\n g.setLineDash([]);\n g.stroke();\n }\n }\n drawn = true;\n } else if (layer.type === 'line' && f.type !== 1) {\n const width = Number(get('paint', 'line-width', ctx, 1));\n if (width <= 0) continue;\n // A gap: two lines on either side of it, drawn as one wide line (the casing of a road, its inside drawn over)\n const gap = Number(get('paint', 'line-gap-width', ctx, 0));\n g.strokeStyle = paint(get('paint', 'line-color', ctx, '#000'), Number(get('paint', 'line-opacity', ctx, 1)));\n g.lineWidth = (gap > 0 ? gap + 2 * width : width) * px;\n g.lineCap = String(get('layout', 'line-cap', ctx, 'butt')) as CanvasLineCap;\n g.lineJoin = String(get('layout', 'line-join', ctx, 'miter')) as CanvasLineJoin;\n const dash = get('paint', 'line-dasharray', ctx, undefined);\n g.setLineDash(Array.isArray(dash) ? dash.map((d) => Number(d) * width * px) : []);\n path(f, f.type === 3);\n g.stroke();\n drawn = true;\n } else if (layer.type === 'circle' && f.type === 1) {\n const radius = Number(get('paint', 'circle-radius', ctx, 5)) * px;\n g.fillStyle = paint(get('paint', 'circle-color', ctx, '#000'), Number(get('paint', 'circle-opacity', ctx, 1)));\n const stroke = Number(get('paint', 'circle-stroke-width', ctx, 0)) * px;\n g.strokeStyle = paint(\n get('paint', 'circle-stroke-color', ctx, '#000'),\n Number(get('paint', 'circle-stroke-opacity', ctx, 1)),\n );\n g.lineWidth = stroke;\n for (const point of f.geometry) {\n for (let i = 0; i + 1 < point.length; i += 2) {\n g.beginPath();\n g.arc(((point[i] ?? 0) - ox) * k, ((point[i + 1] ?? 0) - oy) * k, radius, 0, 2 * Math.PI);\n g.fill();\n if (stroke > 0) g.stroke();\n }\n }\n drawn = true;\n }\n }\n }\n if (!drawn && !layers) return null;\n return tileImage(canvas, g, opaque);\n}\n\n/** A text written over its icon (a road shield's number: no halo, centered on it, no offset): icons are not drawn, and\n * without its icon the text would float unreadable; such a layer is left out */\nfunction onIcon(layer: StyleLayer): boolean {\n const { layout = {}, paint = {} } = layer;\n return (\n layout['icon-image'] !== undefined &&\n paint['text-halo-width'] === undefined &&\n paint['text-halo-color'] === undefined &&\n layout['text-offset'] === undefined &&\n (layout['text-anchor'] ?? 'center') === 'center'\n );\n}\n\n/** Longitude and latitude of a point of tile (z, x, y) in tile units */\nfunction lonLat(z: number, x: number, y: number, extent: number, px: number, py: number): [number, number] {\n const n = 2 ** z;\n const mx = (x + px / extent) / n;\n const my = (y + py / extent) / n;\n return [mx * 360 - 180, (Math.atan(Math.sinh(Math.PI * (1 - 2 * my))) * 180) / Math.PI];\n}\n\nasync function labels(\n r: Renderer,\n z: number,\n x: number,\n y: number,\n id: number,\n priority?: Priority,\n): Promise<LabelCandidate[]> {\n const url = r.tiles.replace('{z}', String(z)).replace('{x}', String(x)).replace('{y}', String(y));\n const layers = await tile(url, priority);\n if (!layers || aborted.has(id)) return [];\n const out: LabelCandidate[] = [];\n // The text size of a layer when it depends on the zoom only: legacy stops as they are, an expression as stops\n const sizes = new Map<StyleLayer, Json>();\n const sizeOf = (layer: StyleLayer): Json => {\n let s = sizes.get(layer);\n if (s === undefined) {\n const v = layer.layout?.['text-size'] ?? 16;\n s = isExpression(v) ? zoomStops(v) : v;\n sizes.set(layer, s);\n }\n return s;\n };\n r.layers.forEach((layer, index) => {\n if (layer.type !== 'symbol' || !shown(layer, z) || layer.layout?.['text-field'] === undefined) return;\n if (onIcon(layer)) return;\n const data = layers.get(layer['source-layer'] ?? '');\n if (!data) return;\n const placement = layer.layout?.['symbol-placement'] === 'line' ? 'line' : 'point';\n for (const f of data.features) {\n const ctx = context(f, z);\n if (!filter(layer.filter, ctx)) continue;\n let t = text(layer.layout?.['text-field'], ctx).trim();\n if (!t) continue;\n const transform = value(layer, 'layout', 'text-transform', ctx, 'none');\n if (transform === 'uppercase') t = t.toUpperCase();\n else if (transform === 'lowercase') t = t.toLowerCase();\n const fonts = value(layer, 'layout', 'text-font', ctx, ['Noto Sans Regular']);\n const font = labelFont(Array.isArray(fonts) && typeof fonts[0] === 'string' ? fonts[0] : 'Noto Sans Regular');\n const offset = value(layer, 'layout', 'text-offset', ctx, [0, 0]);\n const base = {\n layer: index,\n text: t,\n font,\n // Zoom stops are kept for the engine; a value of the feature evaluated here\n size: isFeatureDependent(layer.layout?.['text-size'])\n ? Number(value(layer, 'layout', 'text-size', ctx, 16))\n : sizeOf(layer),\n color: String(value(layer, 'paint', 'text-color', ctx, '#000')),\n haloColor: String(value(layer, 'paint', 'text-halo-color', ctx, 'rgba(0,0,0,0)')),\n haloWidth: Number(value(layer, 'paint', 'text-halo-width', ctx, 0)),\n anchor: String(value(layer, 'layout', 'text-anchor', ctx, 'center')),\n offset: (Array.isArray(offset) ? [Number(offset[0] ?? 0), Number(offset[1] ?? 0)] : [0, 0]) as [number, number],\n maxWidth: Number(value(layer, 'layout', 'text-max-width', ctx, 10)),\n lineHeight: Number(value(layer, 'layout', 'text-line-height', ctx, 1.2)),\n overlap: Boolean(value(layer, 'layout', 'text-allow-overlap', ctx, false)),\n };\n if (f.type === 1) {\n for (const point of f.geometry) {\n for (let i = 0; i + 1 < point.length; i += 2) {\n const [px, py] = [point[i] ?? 0, point[i + 1] ?? 0];\n // Points in the buffer belong to the neighbouring tile\n if (px < 0 || py < 0 || px >= data.extent || py >= data.extent) continue;\n const [lon, lat] = lonLat(z, x, y, data.extent, px, py);\n out.push({ ...base, lon, lat });\n }\n }\n } else {\n // The middle of the longest line inside the tile, along it\n let best: number[] | undefined;\n let bestLength = 0;\n for (const line of f.geometry) {\n let length = 0;\n for (let i = 2; i + 1 < line.length; i += 2) {\n length += Math.hypot((line[i] ?? 0) - (line[i - 2] ?? 0), (line[i + 1] ?? 0) - (line[i - 1] ?? 0));\n }\n if (length > bestLength) {\n bestLength = length;\n best = line;\n }\n }\n if (!best || bestLength < data.extent / 32) continue;\n let rest = bestLength / 2;\n for (let i = 2; i + 1 < best.length; i += 2) {\n const [ax, ay, bx, by] = [best[i - 2] ?? 0, best[i - 1] ?? 0, best[i] ?? 0, best[i + 1] ?? 0];\n const d = Math.hypot(bx - ax, by - ay);\n if (d >= rest && d > 0) {\n const [px, py] = [ax + ((bx - ax) * rest) / d, ay + ((by - ay) * rest) / d];\n if (px < 0 || py < 0 || px >= data.extent || py >= data.extent) break;\n const [lon, lat] = lonLat(z, x, y, data.extent, px, py);\n const [lon1, lat1] = lonLat(z, x, y, data.extent, bx, by);\n const [lon0, lat0] = lonLat(z, x, y, data.extent, ax, ay);\n out.push({ ...base, lon, lat, ...(placement === 'line' ? { along: [lon1 - lon0, lat1 - lat0] } : {}) });\n break;\n }\n rest -= d;\n }\n }\n }\n });\n return out;\n}\n\nconst post = (message: BasemapResponse, transfer: Transferable[] = []) =>\n (self as unknown as Worker).postMessage(message, transfer);\n\nself.onmessage = async ({ data }: MessageEvent<BasemapRequest>) => {\n if (data.type === 'init') {\n if (data.workers !== undefined) cacheSize = cacheShare(data.workers);\n renderers.set(data.key, {\n tiles: data.tiles,\n maxzoom: data.maxzoom,\n layers: data.layers,\n rasters: data.rasters ?? {},\n sprite: data.sprite,\n patterns: new Map(),\n });\n return;\n }\n if (data.type === 'drop') {\n // Its copy of the sprite\n renderers.get(data.key)?.sprite?.image.close();\n renderers.delete(data.key);\n return;\n }\n if (data.type === 'abort') {\n // An abort that arrives after the answer is ignored\n if (active.has(data.id)) aborted.add(data.id);\n return;\n }\n active.add(data.id);\n const r = renderers.get(data.key);\n try {\n if (!r) throw new Error(`no renderer ${data.key}`);\n if (data.type === 'render') {\n const image = await render(r, data.z, data.x, data.y, data.size, data.id, data.priority);\n if (image) post({ id: data.id, image }, [image]);\n else post({ id: data.id, missing: true });\n } else {\n post({ id: data.id, labels: await labels(r, data.z, data.x, data.y, data.id, data.priority) });\n }\n } catch (error) {\n post({ id: data.id, error: String(error) });\n } finally {\n active.delete(data.id);\n aborted.delete(data.id);\n }\n};\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "01D6BC7A49684B7264756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** The basemaps by name: OpenFreeMap's vector styles (OpenStreetMap data, worldwide) and the Géoplateforme's (IGN,
|
|
2
|
+
* France), the credits of the sources, and the relief of each body */
|
|
3
|
+
import { IGN_ATTRIBUTION } from './geoplateforme.ts';
|
|
4
|
+
import type { Basemap, BasemapName, RasterOptions } from './types.ts';
|
|
5
|
+
export { IGN_ATTRIBUTION };
|
|
6
|
+
/** The raster basemaps of the Géoplateforme (WMTS, Web Mercator), crediting the IGN */
|
|
7
|
+
export declare const BASEMAPS: Record<'ign-plan' | 'ign-plan-grey' | 'ign-ortho', RasterOptions>;
|
|
8
|
+
/** A basemap by its current name: a former one is warned about once, then taken under its new name */
|
|
9
|
+
export declare function basemapName(basemap: Basemap): BasemapName;
|
|
10
|
+
/** Credits of OpenFreeMap's basemaps, as its TileJSON gives them */
|
|
11
|
+
export declare const OPENFREEMAP_ATTRIBUTION: string;
|
|
12
|
+
/** Credits of the Terrain Tiles of AWS's open data registry (Mapzen's Terrarium tiles) and of their sources */
|
|
13
|
+
export declare const TERRAIN_TILES_ATTRIBUTION = "<a href=\"https://github.com/tilezen/joerd/blob/master/docs/attribution.md\">Terrain Tiles</a> (Mapzen, AWS)";
|
|
14
|
+
/** IGN hillshade, grey on transparent, zooms 6 to 17 */
|
|
15
|
+
export declare const HILLSHADE: RasterOptions;
|
|
16
|
+
/** IGN terrain model (RGE ALTI and its fill-ins, France), raw altitudes in metres from the Géoplateforme WMS */
|
|
17
|
+
export declare const TERRAIN_URL: string;
|
|
18
|
+
/** The relief of the Moon and Mars by default: NASA's Trek image services (ArcGIS), raw 32-bit altitudes in metres
|
|
19
|
+
* asked for in the body's Mercator, with their credits. The Moon: LOLA's global model, 128 pixels per degree (237 m);
|
|
20
|
+
* Mars: MOLA's, 128 and 64 pixels per degree merged (463 m), above the areoid */
|
|
21
|
+
export declare const BODY_TERRAINS: {
|
|
22
|
+
readonly moon: {
|
|
23
|
+
readonly url: "https://trek.nasa.gov/moon/trekarcgis/rest/services/LRO_LOLA_DEM_Global_128ppd_v04/ImageServer";
|
|
24
|
+
readonly maxZoom: 8;
|
|
25
|
+
readonly attribution: "<a href=\"https://trek.nasa.gov/moon/\">NASA Moon Trek</a>: LOLA terrain model, NASA/GSFC/MIT";
|
|
26
|
+
};
|
|
27
|
+
readonly mars: {
|
|
28
|
+
readonly url: "https://trek.nasa.gov/mars/trekarcgis/rest/services/mola128_mola64_merge_90Nto90S_SimpleC_clon0/ImageServer";
|
|
29
|
+
readonly maxZoom: 8;
|
|
30
|
+
readonly attribution: "<a href=\"https://trek.nasa.gov/mars/\">NASA Mars Trek</a>: MOLA terrain model, NASA/JPL/GSFC";
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/** An ArcGIS image service (a URL ending in `/ImageServer`) */
|
|
34
|
+
export declare const IMAGE_SERVER: RegExp;
|
|
35
|
+
/**
|
|
36
|
+
* The `exportImage` template of an ArcGIS image service for the relief: 256 × 256 raw 32-bit floats (`bsq`, followed
|
|
37
|
+
* by its validity mask) of the box `{bbox}` in the Mercator of the body. On the Earth, Web Mercator (EPSG:3857);
|
|
38
|
+
* elsewhere, a Mercator on the sphere of `radius` metres (Web Mercator's own formulas), given in WKT.
|
|
39
|
+
*/
|
|
40
|
+
export declare function imageServerTerrain(url: string, earth: boolean, radius: number): string;
|
|
41
|
+
/** The Earth's relief for `terrain: true`: the Terrain Tiles of AWS's open data registry, worldwide (SRTM, EU-DEM,
|
|
42
|
+
* GMTED… merged by Mapzen), Terrarium PNGs of 256 px to level 14, altitudes above the mean sea level */
|
|
43
|
+
export declare const TERRAIN_TILES: {
|
|
44
|
+
readonly url: "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png";
|
|
45
|
+
readonly maxZoom: 14;
|
|
46
|
+
};
|
|
47
|
+
/** Sea color of each basemap, for the globe under the tiles (polar caps), RGB 0-1 */
|
|
48
|
+
export declare const SEA: Record<BasemapName, [r: number, g: number, b: number]>;
|
package/dist/basemaps.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** The basemaps by name: OpenFreeMap's vector styles (OpenStreetMap data, worldwide) and the Géoplateforme's (IGN,
|
|
2
|
+
* France), the credits of the sources, and the relief of each body */
|
|
3
|
+
import { geoplateformeWmts, IGN_ATTRIBUTION } from "./geoplateforme.js";
|
|
4
|
+
export { IGN_ATTRIBUTION };
|
|
5
|
+
const PLAN = 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2';
|
|
6
|
+
/** The raster basemaps of the Géoplateforme (WMTS, Web Mercator), crediting the IGN */
|
|
7
|
+
export const BASEMAPS = {
|
|
8
|
+
'ign-plan': geoplateformeWmts(PLAN),
|
|
9
|
+
'ign-plan-grey': geoplateformeWmts(PLAN, { saturation: 0 }),
|
|
10
|
+
'ign-ortho': geoplateformeWmts('ORTHOIMAGERY.ORTHOPHOTOS', { format: 'image/jpeg' }),
|
|
11
|
+
};
|
|
12
|
+
/** The former names of the Géoplateforme basemaps, still accepted */
|
|
13
|
+
const LEGACY = {
|
|
14
|
+
plan: 'ign-plan',
|
|
15
|
+
'plan-grey': 'ign-plan-grey',
|
|
16
|
+
ortho: 'ign-ortho',
|
|
17
|
+
'plan-vector': 'ign-plan-vector',
|
|
18
|
+
'plan-grey-vector': 'ign-plan-grey-vector',
|
|
19
|
+
};
|
|
20
|
+
const warned = new Set();
|
|
21
|
+
/** A basemap by its current name: a former one is warned about once, then taken under its new name */
|
|
22
|
+
export function basemapName(basemap) {
|
|
23
|
+
const renamed = LEGACY[basemap];
|
|
24
|
+
if (!renamed)
|
|
25
|
+
return basemap;
|
|
26
|
+
if (!warned.has(basemap)) {
|
|
27
|
+
warned.add(basemap);
|
|
28
|
+
console.warn(`isard: the basemap '${basemap}' is deprecated, it is now named '${renamed}'`);
|
|
29
|
+
}
|
|
30
|
+
return renamed;
|
|
31
|
+
}
|
|
32
|
+
/** Credits of OpenFreeMap's basemaps, as its TileJSON gives them */
|
|
33
|
+
export const OPENFREEMAP_ATTRIBUTION = '<a href="https://openfreemap.org">OpenFreeMap</a> <a href="https://www.openmaptiles.org/">© OpenMapTiles</a> ' +
|
|
34
|
+
'Data from <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>';
|
|
35
|
+
/** Credits of the Terrain Tiles of AWS's open data registry (Mapzen's Terrarium tiles) and of their sources */
|
|
36
|
+
export const TERRAIN_TILES_ATTRIBUTION = '<a href="https://github.com/tilezen/joerd/blob/master/docs/attribution.md">Terrain Tiles</a> (Mapzen, AWS)';
|
|
37
|
+
/** IGN hillshade, grey on transparent, zooms 6 to 17 */
|
|
38
|
+
export const HILLSHADE = geoplateformeWmts('IGNF_ELEVATION.ELEVATIONGRIDCOVERAGE.SHADOW', {
|
|
39
|
+
minZoom: 6,
|
|
40
|
+
maxZoom: 17,
|
|
41
|
+
});
|
|
42
|
+
/** IGN terrain model (RGE ALTI and its fill-ins, France), raw altitudes in metres from the Géoplateforme WMS */
|
|
43
|
+
export const TERRAIN_URL = 'https://data.geopf.fr/wms-r/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&LAYERS=ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES' +
|
|
44
|
+
'&STYLES=&CRS=EPSG:3857&BBOX={bbox}&WIDTH=256&HEIGHT=256&FORMAT=image/x-bil;bits=32';
|
|
45
|
+
/** The relief of the Moon and Mars by default: NASA's Trek image services (ArcGIS), raw 32-bit altitudes in metres
|
|
46
|
+
* asked for in the body's Mercator, with their credits. The Moon: LOLA's global model, 128 pixels per degree (237 m);
|
|
47
|
+
* Mars: MOLA's, 128 and 64 pixels per degree merged (463 m), above the areoid */
|
|
48
|
+
export const BODY_TERRAINS = {
|
|
49
|
+
moon: {
|
|
50
|
+
url: 'https://trek.nasa.gov/moon/trekarcgis/rest/services/LRO_LOLA_DEM_Global_128ppd_v04/ImageServer',
|
|
51
|
+
maxZoom: 8,
|
|
52
|
+
attribution: '<a href="https://trek.nasa.gov/moon/">NASA Moon Trek</a>: LOLA terrain model, NASA/GSFC/MIT',
|
|
53
|
+
},
|
|
54
|
+
mars: {
|
|
55
|
+
url: 'https://trek.nasa.gov/mars/trekarcgis/rest/services/mola128_mola64_merge_90Nto90S_SimpleC_clon0/ImageServer',
|
|
56
|
+
maxZoom: 8,
|
|
57
|
+
attribution: '<a href="https://trek.nasa.gov/mars/">NASA Mars Trek</a>: MOLA terrain model, NASA/JPL/GSFC',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
/** An ArcGIS image service (a URL ending in `/ImageServer`) */
|
|
61
|
+
export const IMAGE_SERVER = /\/ImageServer\/?$/;
|
|
62
|
+
/**
|
|
63
|
+
* The `exportImage` template of an ArcGIS image service for the relief: 256 × 256 raw 32-bit floats (`bsq`, followed
|
|
64
|
+
* by its validity mask) of the box `{bbox}` in the Mercator of the body. On the Earth, Web Mercator (EPSG:3857);
|
|
65
|
+
* elsewhere, a Mercator on the sphere of `radius` metres (Web Mercator's own formulas), given in WKT.
|
|
66
|
+
*/
|
|
67
|
+
export function imageServerTerrain(url, earth, radius) {
|
|
68
|
+
const crs = earth
|
|
69
|
+
? '3857'
|
|
70
|
+
: encodeURIComponent(JSON.stringify({
|
|
71
|
+
wkt: `PROJCS["Mercator",GEOGCS["GCS",DATUM["D",SPHEROID["S",${radius},0]],PRIMEM["Reference_Meridian",0],` +
|
|
72
|
+
'UNIT["Degree",0.0174532925199433]],PROJECTION["Mercator"],PARAMETER["False_Easting",0],' +
|
|
73
|
+
'PARAMETER["False_Northing",0],PARAMETER["Central_Meridian",0],PARAMETER["Standard_Parallel_1",0],' +
|
|
74
|
+
'UNIT["Meter",1]]',
|
|
75
|
+
}));
|
|
76
|
+
return (`${url.replace(/\/$/, '')}/exportImage?f=image&format=bsq&pixelType=F32&size=256,256` +
|
|
77
|
+
`&bboxSR=${crs}&imageSR=${crs}&bbox={bbox}`);
|
|
78
|
+
}
|
|
79
|
+
/** The Earth's relief for `terrain: true`: the Terrain Tiles of AWS's open data registry, worldwide (SRTM, EU-DEM,
|
|
80
|
+
* GMTED… merged by Mapzen), Terrarium PNGs of 256 px to level 14, altitudes above the mean sea level */
|
|
81
|
+
export const TERRAIN_TILES = {
|
|
82
|
+
url: 'https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png',
|
|
83
|
+
maxZoom: 14,
|
|
84
|
+
};
|
|
85
|
+
/** Sea color of each basemap, for the globe under the tiles (polar caps), RGB 0-1 */
|
|
86
|
+
export const SEA = {
|
|
87
|
+
'osm-positron': [0.761, 0.784, 0.792],
|
|
88
|
+
'osm-liberty': [0.62, 0.741, 1],
|
|
89
|
+
'osm-bright': [0.682, 0.812, 0.886],
|
|
90
|
+
'ign-plan': [0.667, 0.835, 0.914],
|
|
91
|
+
'ign-plan-grey': [0.792, 0.792, 0.792],
|
|
92
|
+
'ign-plan-vector': [0.667, 0.835, 0.914],
|
|
93
|
+
'ign-plan-grey-vector': [0.792, 0.792, 0.792],
|
|
94
|
+
'ign-ortho': [0.039, 0.231, 0.349],
|
|
95
|
+
none: [0.85, 0.85, 0.83],
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=basemaps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basemaps.js","sourceRoot":"","sources":["../src/basemaps.ts"],"names":[],"mappings":"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","sourcesContent":["/** The basemaps by name: OpenFreeMap's vector styles (OpenStreetMap data, worldwide) and the Géoplateforme's (IGN,\n * France), the credits of the sources, and the relief of each body */\nimport { geoplateformeWmts, IGN_ATTRIBUTION } from './geoplateforme.ts';\nimport type { Basemap, BasemapName, LegacyBasemap, RasterOptions } from './types.ts';\n\nexport { IGN_ATTRIBUTION };\n\nconst PLAN = 'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2';\n\n/** The raster basemaps of the Géoplateforme (WMTS, Web Mercator), crediting the IGN */\nexport const BASEMAPS: Record<'ign-plan' | 'ign-plan-grey' | 'ign-ortho', RasterOptions> = {\n 'ign-plan': geoplateformeWmts(PLAN),\n 'ign-plan-grey': geoplateformeWmts(PLAN, { saturation: 0 }),\n 'ign-ortho': geoplateformeWmts('ORTHOIMAGERY.ORTHOPHOTOS', { format: 'image/jpeg' }),\n};\n\n/** The former names of the Géoplateforme basemaps, still accepted */\nconst LEGACY: Record<LegacyBasemap, BasemapName> = {\n plan: 'ign-plan',\n 'plan-grey': 'ign-plan-grey',\n ortho: 'ign-ortho',\n 'plan-vector': 'ign-plan-vector',\n 'plan-grey-vector': 'ign-plan-grey-vector',\n};\nconst warned = new Set<string>();\n\n/** A basemap by its current name: a former one is warned about once, then taken under its new name */\nexport function basemapName(basemap: Basemap): BasemapName {\n const renamed = LEGACY[basemap as LegacyBasemap];\n if (!renamed) return basemap as BasemapName;\n if (!warned.has(basemap)) {\n warned.add(basemap);\n console.warn(`isard: the basemap '${basemap}' is deprecated, it is now named '${renamed}'`);\n }\n return renamed;\n}\n\n/** Credits of OpenFreeMap's basemaps, as its TileJSON gives them */\nexport const OPENFREEMAP_ATTRIBUTION =\n '<a href=\"https://openfreemap.org\">OpenFreeMap</a> <a href=\"https://www.openmaptiles.org/\">© OpenMapTiles</a> ' +\n 'Data from <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a>';\n\n/** Credits of the Terrain Tiles of AWS's open data registry (Mapzen's Terrarium tiles) and of their sources */\nexport const TERRAIN_TILES_ATTRIBUTION =\n '<a href=\"https://github.com/tilezen/joerd/blob/master/docs/attribution.md\">Terrain Tiles</a> (Mapzen, AWS)';\n\n/** IGN hillshade, grey on transparent, zooms 6 to 17 */\nexport const HILLSHADE: RasterOptions = geoplateformeWmts('IGNF_ELEVATION.ELEVATIONGRIDCOVERAGE.SHADOW', {\n minZoom: 6,\n maxZoom: 17,\n});\n\n/** IGN terrain model (RGE ALTI and its fill-ins, France), raw altitudes in metres from the Géoplateforme WMS */\nexport const TERRAIN_URL =\n 'https://data.geopf.fr/wms-r/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&LAYERS=ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES' +\n '&STYLES=&CRS=EPSG:3857&BBOX={bbox}&WIDTH=256&HEIGHT=256&FORMAT=image/x-bil;bits=32';\n\n/** The relief of the Moon and Mars by default: NASA's Trek image services (ArcGIS), raw 32-bit altitudes in metres\n * asked for in the body's Mercator, with their credits. The Moon: LOLA's global model, 128 pixels per degree (237 m);\n * Mars: MOLA's, 128 and 64 pixels per degree merged (463 m), above the areoid */\nexport const BODY_TERRAINS = {\n moon: {\n url: 'https://trek.nasa.gov/moon/trekarcgis/rest/services/LRO_LOLA_DEM_Global_128ppd_v04/ImageServer',\n maxZoom: 8,\n attribution: '<a href=\"https://trek.nasa.gov/moon/\">NASA Moon Trek</a>: LOLA terrain model, NASA/GSFC/MIT',\n },\n mars: {\n url: 'https://trek.nasa.gov/mars/trekarcgis/rest/services/mola128_mola64_merge_90Nto90S_SimpleC_clon0/ImageServer',\n maxZoom: 8,\n attribution: '<a href=\"https://trek.nasa.gov/mars/\">NASA Mars Trek</a>: MOLA terrain model, NASA/JPL/GSFC',\n },\n} as const;\n\n/** An ArcGIS image service (a URL ending in `/ImageServer`) */\nexport const IMAGE_SERVER = /\\/ImageServer\\/?$/;\n\n/**\n * The `exportImage` template of an ArcGIS image service for the relief: 256 × 256 raw 32-bit floats (`bsq`, followed\n * by its validity mask) of the box `{bbox}` in the Mercator of the body. On the Earth, Web Mercator (EPSG:3857);\n * elsewhere, a Mercator on the sphere of `radius` metres (Web Mercator's own formulas), given in WKT.\n */\nexport function imageServerTerrain(url: string, earth: boolean, radius: number): string {\n const crs = earth\n ? '3857'\n : encodeURIComponent(\n JSON.stringify({\n wkt:\n `PROJCS[\"Mercator\",GEOGCS[\"GCS\",DATUM[\"D\",SPHEROID[\"S\",${radius},0]],PRIMEM[\"Reference_Meridian\",0],` +\n 'UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Mercator\"],PARAMETER[\"False_Easting\",0],' +\n 'PARAMETER[\"False_Northing\",0],PARAMETER[\"Central_Meridian\",0],PARAMETER[\"Standard_Parallel_1\",0],' +\n 'UNIT[\"Meter\",1]]',\n }),\n );\n return (\n `${url.replace(/\\/$/, '')}/exportImage?f=image&format=bsq&pixelType=F32&size=256,256` +\n `&bboxSR=${crs}&imageSR=${crs}&bbox={bbox}`\n );\n}\n\n/** The Earth's relief for `terrain: true`: the Terrain Tiles of AWS's open data registry, worldwide (SRTM, EU-DEM,\n * GMTED… merged by Mapzen), Terrarium PNGs of 256 px to level 14, altitudes above the mean sea level */\nexport const TERRAIN_TILES = {\n url: 'https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png',\n maxZoom: 14,\n} as const;\n\n/** Sea color of each basemap, for the globe under the tiles (polar caps), RGB 0-1 */\nexport const SEA: Record<BasemapName, [r: number, g: number, b: number]> = {\n 'osm-positron': [0.761, 0.784, 0.792],\n 'osm-liberty': [0.62, 0.741, 1],\n 'osm-bright': [0.682, 0.812, 0.886],\n 'ign-plan': [0.667, 0.835, 0.914],\n 'ign-plan-grey': [0.792, 0.792, 0.792],\n 'ign-plan-vector': [0.667, 0.835, 0.914],\n 'ign-plan-grey-vector': [0.792, 0.792, 0.792],\n 'ign-ortho': [0.039, 0.231, 0.349],\n none: [0.85, 0.85, 0.83],\n};\n"]}
|
package/dist/color.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma
|
|
3
|
+
* or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use
|
|
4
|
+
* it too.
|
|
5
|
+
*/
|
|
6
|
+
export type Rgba = [r: number, g: number, b: number, a: number];
|
|
7
|
+
/** A CSS color to RGBA 0-1; undefined if it is not one */
|
|
8
|
+
export declare function parseCssColor(value: unknown): Rgba | undefined;
|
package/dist/color.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma
|
|
3
|
+
* or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use
|
|
4
|
+
* it too.
|
|
5
|
+
*/
|
|
6
|
+
/** The CSS named colors, as name and `rrggbb` pairs */
|
|
7
|
+
const NAMES = 'aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 ' +
|
|
8
|
+
'black 000000 blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 ' +
|
|
9
|
+
'chartreuse 7fff00 chocolate d2691e coral ff7f50 cornflowerblue 6495ed cornsilk fff8dc crimson dc143c ' +
|
|
10
|
+
'cyan 00ffff darkblue 00008b darkcyan 008b8b darkgoldenrod b8860b darkgray a9a9a9 darkgreen 006400 ' +
|
|
11
|
+
'darkgrey a9a9a9 darkkhaki bdb76b darkmagenta 8b008b darkolivegreen 556b2f darkorange ff8c00 darkorchid 9932cc ' +
|
|
12
|
+
'darkred 8b0000 darksalmon e9967a darkseagreen 8fbc8f darkslateblue 483d8b darkslategray 2f4f4f ' +
|
|
13
|
+
'darkslategrey 2f4f4f darkturquoise 00ced1 darkviolet 9400d3 deeppink ff1493 deepskyblue 00bfff dimgray 696969 ' +
|
|
14
|
+
'dimgrey 696969 dodgerblue 1e90ff firebrick b22222 floralwhite fffaf0 forestgreen 228b22 fuchsia ff00ff ' +
|
|
15
|
+
'gainsboro dcdcdc ghostwhite f8f8ff gold ffd700 goldenrod daa520 gray 808080 green 008000 greenyellow adff2f ' +
|
|
16
|
+
'grey 808080 honeydew f0fff0 hotpink ff69b4 indianred cd5c5c indigo 4b0082 ivory fffff0 khaki f0e68c ' +
|
|
17
|
+
'lavender e6e6fa lavenderblush fff0f5 lawngreen 7cfc00 lemonchiffon fffacd lightblue add8e6 lightcoral f08080 ' +
|
|
18
|
+
'lightcyan e0ffff lightgoldenrodyellow fafad2 lightgray d3d3d3 lightgreen 90ee90 lightgrey d3d3d3 ' +
|
|
19
|
+
'lightpink ffb6c1 lightsalmon ffa07a lightseagreen 20b2aa lightskyblue 87cefa lightslategray 778899 ' +
|
|
20
|
+
'lightslategrey 778899 lightsteelblue b0c4de lightyellow ffffe0 lime 00ff00 limegreen 32cd32 linen faf0e6 ' +
|
|
21
|
+
'magenta ff00ff maroon 800000 mediumaquamarine 66cdaa mediumblue 0000cd mediumorchid ba55d3 ' +
|
|
22
|
+
'mediumpurple 9370db mediumseagreen 3cb371 mediumslateblue 7b68ee mediumspringgreen 00fa9a ' +
|
|
23
|
+
'mediumturquoise 48d1cc mediumvioletred c71585 midnightblue 191970 mintcream f5fffa mistyrose ffe4e1 ' +
|
|
24
|
+
'moccasin ffe4b5 navajowhite ffdead navy 000080 oldlace fdf5e6 olive 808000 olivedrab 6b8e23 orange ffa500 ' +
|
|
25
|
+
'orangered ff4500 orchid da70d6 palegoldenrod eee8aa palegreen 98fb98 paleturquoise afeeee ' +
|
|
26
|
+
'palevioletred db7093 papayawhip ffefd5 peachpuff ffdab9 peru cd853f pink ffc0cb plum dda0dd ' +
|
|
27
|
+
'powderblue b0e0e6 purple 800080 rebeccapurple 663399 red ff0000 rosybrown bc8f8f royalblue 4169e1 ' +
|
|
28
|
+
'saddlebrown 8b4513 salmon fa8072 sandybrown f4a460 seagreen 2e8b57 seashell fff5ee sienna a0522d ' +
|
|
29
|
+
'silver c0c0c0 skyblue 87ceeb slateblue 6a5acd slategray 708090 slategrey 708090 snow fffafa ' +
|
|
30
|
+
'springgreen 00ff7f steelblue 4682b4 tan d2b48c teal 008080 thistle d8bfd8 tomato ff6347 turquoise 40e0d0 ' +
|
|
31
|
+
'violet ee82ee wheat f5deb3 white ffffff whitesmoke f5f5f5 yellow ffff00 yellowgreen 9acd32';
|
|
32
|
+
let named;
|
|
33
|
+
function namedHex(name) {
|
|
34
|
+
if (!named) {
|
|
35
|
+
named = new Map();
|
|
36
|
+
const words = NAMES.split(' ');
|
|
37
|
+
for (let i = 0; i + 1 < words.length; i += 2)
|
|
38
|
+
named.set(words[i], words[i + 1]);
|
|
39
|
+
}
|
|
40
|
+
return named.get(name);
|
|
41
|
+
}
|
|
42
|
+
const clamp = (v) => (Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 0);
|
|
43
|
+
function hex(digits) {
|
|
44
|
+
if (!/^[0-9a-f]+$/.test(digits) || ![3, 4, 6, 8].includes(digits.length))
|
|
45
|
+
return undefined;
|
|
46
|
+
const full = digits.length <= 4 ? [...digits].map((h) => h + h).join('') : digits;
|
|
47
|
+
const v = (i) => Number.parseInt(full.slice(i, i + 2), 16) / 255;
|
|
48
|
+
return [v(0), v(2), v(4), full.length === 8 ? v(6) : 1];
|
|
49
|
+
}
|
|
50
|
+
/** An alpha: a number from 0 to 1 or a percentage */
|
|
51
|
+
function alpha(p) {
|
|
52
|
+
if (p === undefined)
|
|
53
|
+
return 1;
|
|
54
|
+
return clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));
|
|
55
|
+
}
|
|
56
|
+
function hsl(h, s, l) {
|
|
57
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
58
|
+
const p = 2 * l - q;
|
|
59
|
+
const hue = (t) => {
|
|
60
|
+
const u = ((t % 1) + 1) % 1;
|
|
61
|
+
if (u < 1 / 6)
|
|
62
|
+
return p + (q - p) * 6 * u;
|
|
63
|
+
if (u < 1 / 2)
|
|
64
|
+
return q;
|
|
65
|
+
if (u < 2 / 3)
|
|
66
|
+
return p + (q - p) * (2 / 3 - u) * 6;
|
|
67
|
+
return p;
|
|
68
|
+
};
|
|
69
|
+
return [hue(h + 1 / 3), hue(h), hue(h - 1 / 3)];
|
|
70
|
+
}
|
|
71
|
+
/** A CSS color to RGBA 0-1; undefined if it is not one */
|
|
72
|
+
export function parseCssColor(value) {
|
|
73
|
+
if (typeof value !== 'string')
|
|
74
|
+
return undefined;
|
|
75
|
+
const c = value.trim().toLowerCase();
|
|
76
|
+
if (c.startsWith('#'))
|
|
77
|
+
return hex(c.slice(1));
|
|
78
|
+
if (c === 'transparent')
|
|
79
|
+
return [0, 0, 0, 0];
|
|
80
|
+
const name = namedHex(c);
|
|
81
|
+
if (name)
|
|
82
|
+
return hex(name);
|
|
83
|
+
const match = /^(rgba?|hsla?)\(([^)]*)\)$/.exec(c);
|
|
84
|
+
if (!match?.[1] || match[2] === undefined)
|
|
85
|
+
return undefined;
|
|
86
|
+
const parts = match[2].split(/[\s,/]+/).filter(Boolean);
|
|
87
|
+
if (parts.length < 3 || parts.slice(0, 3).some((p) => Number.isNaN(Number.parseFloat(p))))
|
|
88
|
+
return undefined;
|
|
89
|
+
const a = alpha(parts[3]);
|
|
90
|
+
if (match[1].startsWith('rgb')) {
|
|
91
|
+
const channel = (p) => clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);
|
|
92
|
+
return [channel(parts[0]), channel(parts[1]), channel(parts[2]), a];
|
|
93
|
+
}
|
|
94
|
+
const h = Number.parseFloat(parts[0]) / 360;
|
|
95
|
+
const [r, g, b] = hsl(h, clamp(Number.parseFloat(parts[1]) / 100), clamp(Number.parseFloat(parts[2]) / 100));
|
|
96
|
+
return [r, g, b, a];
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=color.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.js","sourceRoot":"","sources":["../src/color.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * CSS colors to RGBA 0-1: `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()` and `rgba()`, `hsl()` and `hsla()` (comma\n * or space syntax, `/` before the alpha, percentages), the CSS named colors and `transparent`. No DOM: the workers use\n * it too.\n */\n\nexport type Rgba = [r: number, g: number, b: number, a: number];\n\n/** The CSS named colors, as name and `rrggbb` pairs */\nconst NAMES =\n 'aliceblue f0f8ff antiquewhite faebd7 aqua 00ffff aquamarine 7fffd4 azure f0ffff beige f5f5dc bisque ffe4c4 ' +\n 'black 000000 blanchedalmond ffebcd blue 0000ff blueviolet 8a2be2 brown a52a2a burlywood deb887 cadetblue 5f9ea0 ' +\n 'chartreuse 7fff00 chocolate d2691e coral ff7f50 cornflowerblue 6495ed cornsilk fff8dc crimson dc143c ' +\n 'cyan 00ffff darkblue 00008b darkcyan 008b8b darkgoldenrod b8860b darkgray a9a9a9 darkgreen 006400 ' +\n 'darkgrey a9a9a9 darkkhaki bdb76b darkmagenta 8b008b darkolivegreen 556b2f darkorange ff8c00 darkorchid 9932cc ' +\n 'darkred 8b0000 darksalmon e9967a darkseagreen 8fbc8f darkslateblue 483d8b darkslategray 2f4f4f ' +\n 'darkslategrey 2f4f4f darkturquoise 00ced1 darkviolet 9400d3 deeppink ff1493 deepskyblue 00bfff dimgray 696969 ' +\n 'dimgrey 696969 dodgerblue 1e90ff firebrick b22222 floralwhite fffaf0 forestgreen 228b22 fuchsia ff00ff ' +\n 'gainsboro dcdcdc ghostwhite f8f8ff gold ffd700 goldenrod daa520 gray 808080 green 008000 greenyellow adff2f ' +\n 'grey 808080 honeydew f0fff0 hotpink ff69b4 indianred cd5c5c indigo 4b0082 ivory fffff0 khaki f0e68c ' +\n 'lavender e6e6fa lavenderblush fff0f5 lawngreen 7cfc00 lemonchiffon fffacd lightblue add8e6 lightcoral f08080 ' +\n 'lightcyan e0ffff lightgoldenrodyellow fafad2 lightgray d3d3d3 lightgreen 90ee90 lightgrey d3d3d3 ' +\n 'lightpink ffb6c1 lightsalmon ffa07a lightseagreen 20b2aa lightskyblue 87cefa lightslategray 778899 ' +\n 'lightslategrey 778899 lightsteelblue b0c4de lightyellow ffffe0 lime 00ff00 limegreen 32cd32 linen faf0e6 ' +\n 'magenta ff00ff maroon 800000 mediumaquamarine 66cdaa mediumblue 0000cd mediumorchid ba55d3 ' +\n 'mediumpurple 9370db mediumseagreen 3cb371 mediumslateblue 7b68ee mediumspringgreen 00fa9a ' +\n 'mediumturquoise 48d1cc mediumvioletred c71585 midnightblue 191970 mintcream f5fffa mistyrose ffe4e1 ' +\n 'moccasin ffe4b5 navajowhite ffdead navy 000080 oldlace fdf5e6 olive 808000 olivedrab 6b8e23 orange ffa500 ' +\n 'orangered ff4500 orchid da70d6 palegoldenrod eee8aa palegreen 98fb98 paleturquoise afeeee ' +\n 'palevioletred db7093 papayawhip ffefd5 peachpuff ffdab9 peru cd853f pink ffc0cb plum dda0dd ' +\n 'powderblue b0e0e6 purple 800080 rebeccapurple 663399 red ff0000 rosybrown bc8f8f royalblue 4169e1 ' +\n 'saddlebrown 8b4513 salmon fa8072 sandybrown f4a460 seagreen 2e8b57 seashell fff5ee sienna a0522d ' +\n 'silver c0c0c0 skyblue 87ceeb slateblue 6a5acd slategray 708090 slategrey 708090 snow fffafa ' +\n 'springgreen 00ff7f steelblue 4682b4 tan d2b48c teal 008080 thistle d8bfd8 tomato ff6347 turquoise 40e0d0 ' +\n 'violet ee82ee wheat f5deb3 white ffffff whitesmoke f5f5f5 yellow ffff00 yellowgreen 9acd32';\n\nlet named: Map<string, string> | undefined;\n\nfunction namedHex(name: string): string | undefined {\n if (!named) {\n named = new Map();\n const words = NAMES.split(' ');\n for (let i = 0; i + 1 < words.length; i += 2) named.set(words[i] as string, words[i + 1] as string);\n }\n return named.get(name);\n}\n\nconst clamp = (v: number) => (Number.isFinite(v) ? Math.max(0, Math.min(1, v)) : 0);\n\nfunction hex(digits: string): Rgba | undefined {\n if (!/^[0-9a-f]+$/.test(digits) || ![3, 4, 6, 8].includes(digits.length)) return undefined;\n const full = digits.length <= 4 ? [...digits].map((h) => h + h).join('') : digits;\n const v = (i: number) => Number.parseInt(full.slice(i, i + 2), 16) / 255;\n return [v(0), v(2), v(4), full.length === 8 ? v(6) : 1];\n}\n\n/** An alpha: a number from 0 to 1 or a percentage */\nfunction alpha(p: string | undefined): number {\n if (p === undefined) return 1;\n return clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p));\n}\n\nfunction hsl(h: number, s: number, l: number): [number, number, number] {\n const q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n const p = 2 * l - q;\n const hue = (t: number) => {\n const u = ((t % 1) + 1) % 1;\n if (u < 1 / 6) return p + (q - p) * 6 * u;\n if (u < 1 / 2) return q;\n if (u < 2 / 3) return p + (q - p) * (2 / 3 - u) * 6;\n return p;\n };\n return [hue(h + 1 / 3), hue(h), hue(h - 1 / 3)];\n}\n\n/** A CSS color to RGBA 0-1; undefined if it is not one */\nexport function parseCssColor(value: unknown): Rgba | undefined {\n if (typeof value !== 'string') return undefined;\n const c = value.trim().toLowerCase();\n if (c.startsWith('#')) return hex(c.slice(1));\n if (c === 'transparent') return [0, 0, 0, 0];\n const name = namedHex(c);\n if (name) return hex(name);\n const match = /^(rgba?|hsla?)\\(([^)]*)\\)$/.exec(c);\n if (!match?.[1] || match[2] === undefined) return undefined;\n const parts = match[2].split(/[\\s,/]+/).filter(Boolean);\n if (parts.length < 3 || parts.slice(0, 3).some((p) => Number.isNaN(Number.parseFloat(p)))) return undefined;\n const a = alpha(parts[3]);\n if (match[1].startsWith('rgb')) {\n const channel = (p: string) => clamp(p.endsWith('%') ? Number.parseFloat(p) / 100 : Number.parseFloat(p) / 255);\n return [channel(parts[0] as string), channel(parts[1] as string), channel(parts[2] as string), a];\n }\n const h = Number.parseFloat(parts[0] as string) / 360;\n const [r, g, b] = hsl(\n h,\n clamp(Number.parseFloat(parts[1] as string) / 100),\n clamp(Number.parseFloat(parts[2] as string) / 100),\n );\n return [r, g, b, a];\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { GeoMap } from './map.ts';
|
|
2
|
+
export type ControlPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
3
|
+
export interface Control {
|
|
4
|
+
/** Builds the control's element; the map puts it in its corner */
|
|
5
|
+
onAdd(map: GeoMap): HTMLElement;
|
|
6
|
+
/** Cleans up (listeners); the map removes the element */
|
|
7
|
+
onRemove(map: GeoMap): void;
|
|
8
|
+
}
|
|
9
|
+
export interface NavigationOptions {
|
|
10
|
+
/** Zoom in and out buttons (default true) */
|
|
11
|
+
showZoom?: boolean;
|
|
12
|
+
/** Compass turning with the bearing; a click faces north and levels the view (default true) */
|
|
13
|
+
showCompass?: boolean;
|
|
14
|
+
/** The compass also tilts with the pitch (default false) */
|
|
15
|
+
visualizePitch?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Zoom buttons and compass */
|
|
18
|
+
export declare class NavigationControl implements Control {
|
|
19
|
+
private readonly options;
|
|
20
|
+
private stopListening;
|
|
21
|
+
constructor(options?: NavigationOptions);
|
|
22
|
+
onAdd(map: GeoMap): HTMLElement;
|
|
23
|
+
onRemove(): void;
|
|
24
|
+
}
|
|
25
|
+
/** @deprecated The Géoplateforme's credits, now `IGN_ATTRIBUTION`: the attribution control shows those of the sources
|
|
26
|
+
* in use */
|
|
27
|
+
export declare const DEFAULT_ATTRIBUTION = "<a href=\"https://www.ign.fr/\">\u00A9 IGN</a> \u2013 <a href=\"https://geoservices.ign.fr/\">G\u00E9oplateforme</a>";
|
|
28
|
+
export interface AttributionOptions {
|
|
29
|
+
/** Folded into a small (i) button that shows the text on click (default: when the map is narrower than 640 px) */
|
|
30
|
+
compact?: boolean;
|
|
31
|
+
/** Attributions shown after those of the map's sources, HTML allowed (links open in a new tab) */
|
|
32
|
+
customAttribution?: string | string[];
|
|
33
|
+
}
|
|
34
|
+
/** Credits of the data shown: those of the map's basemap, hillshade and relief (OpenFreeMap and OpenStreetMap, IGN,
|
|
35
|
+
* the Terrain Tiles…, followed as they change), then the page's own */
|
|
36
|
+
export declare class AttributionControl implements Control {
|
|
37
|
+
private readonly options;
|
|
38
|
+
private observer;
|
|
39
|
+
private stopListening;
|
|
40
|
+
constructor(options?: AttributionOptions);
|
|
41
|
+
onAdd(map: GeoMap): HTMLElement;
|
|
42
|
+
onRemove(): void;
|
|
43
|
+
}
|