isard 1.5.0 → 1.6.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/CHANGELOG.md +165 -1
- package/README.md +3 -2
- package/dist/basemap/furniture.d.ts +8 -0
- package/dist/basemap/furniture.js +26 -0
- package/dist/basemap/furniture.js.map +1 -0
- package/dist/basemap/trees.d.ts +35 -8
- package/dist/basemap/trees.js +105 -52
- package/dist/basemap/trees.js.map +1 -1
- package/dist/basemap/vectorstyle.d.ts +9 -3
- package/dist/basemap/vectorstyle.js +5 -6
- package/dist/basemap/vectorstyle.js.map +1 -1
- package/dist/basemap/vectortiles/context.d.ts +3 -0
- package/dist/basemap/vectortiles/context.js.map +1 -1
- package/dist/basemap/vectortiles/extrusions.d.ts +4 -0
- package/dist/basemap/vectortiles/extrusions.js +17 -2
- package/dist/basemap/vectortiles/extrusions.js.map +1 -1
- package/dist/basemap/vectortiles/labels.d.ts +3 -0
- package/dist/basemap/vectortiles/labels.js +42 -17
- package/dist/basemap/vectortiles/labels.js.map +1 -1
- package/dist/basemap/vectortiles/lamps.d.ts +23 -0
- package/dist/basemap/vectortiles/lamps.js +90 -0
- package/dist/basemap/vectortiles/lamps.js.map +1 -0
- package/dist/basemap/vectortiles/requests.d.ts +4 -0
- package/dist/basemap/vectortiles/requests.js +15 -2
- package/dist/basemap/vectortiles/requests.js.map +1 -1
- package/dist/basemap/vectortiles/trees.d.ts +9 -0
- package/dist/basemap/vectortiles/trees.js +114 -29
- package/dist/basemap/vectortiles/trees.js.map +1 -1
- package/dist/basemap/vectortiles/vectors.d.ts +17 -0
- package/dist/basemap/vectortiles/vectors.js +72 -8
- package/dist/basemap/vectortiles/vectors.js.map +1 -1
- package/dist/basemap/vectortiles.d.ts +26 -6
- package/dist/basemap/vectortiles.js +43 -10
- package/dist/basemap/vectortiles.js.map +1 -1
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +12 -10
- package/dist/bind/layers.js +1 -0
- package/dist/bind/layers.js.map +1 -1
- package/dist/data/collada.d.ts +19 -0
- package/dist/data/collada.js +319 -0
- package/dist/data/collada.js.map +1 -0
- package/dist/data/ifc.d.ts +100 -0
- package/dist/data/ifc.js +372 -0
- package/dist/data/ifc.js.map +1 -0
- package/dist/decoder.worker.js +5 -5
- package/dist/decoder.worker.js.map +3 -3
- package/dist/formats.d.ts +7 -2
- package/dist/formats.js +7 -2
- package/dist/formats.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_grid_bg.wasm +0 -0
- package/dist/isard_tess_bg.wasm +0 -0
- package/dist/layers/extrusions.d.ts +10 -0
- package/dist/layers/extrusions.js +28 -2
- package/dist/layers/extrusions.js.map +1 -1
- package/dist/layers/layers.d.ts +12 -0
- package/dist/layers/layers.js +44 -1
- package/dist/layers/layers.js.map +1 -1
- package/dist/layers/photos.d.ts +48 -0
- package/dist/layers/photos.js +140 -0
- package/dist/layers/photos.js.map +1 -0
- package/dist/layers/symbols.d.ts +5 -1
- package/dist/layers/symbols.js +111 -32
- package/dist/layers/symbols.js.map +1 -1
- package/dist/layers/trees.d.ts +28 -0
- package/dist/layers/trees.js +51 -0
- package/dist/layers/trees.js.map +1 -0
- package/dist/layers/vectors.d.ts +28 -2
- package/dist/layers/vectors.js +81 -7
- package/dist/layers/vectors.js.map +1 -1
- package/dist/map/layer-spec.d.ts +3 -0
- package/dist/map/layer-spec.js +2 -0
- package/dist/map/layer-spec.js.map +1 -1
- package/dist/map.d.ts +8 -0
- package/dist/map.js +15 -2
- package/dist/map.js.map +1 -1
- package/dist/panoramax.d.ts +49 -0
- package/dist/panoramax.js +71 -0
- package/dist/panoramax.js.map +1 -0
- package/dist/react/Layer.d.ts +1 -0
- package/dist/react/Layer.js.map +1 -1
- package/dist/react/VectorGeometry.d.ts +5 -0
- package/dist/react/VectorGeometry.js +12 -4
- package/dist/react/VectorGeometry.js.map +1 -1
- package/dist/util/gltf.d.ts +9 -0
- package/dist/util/gltf.js +27 -0
- package/dist/util/gltf.js.map +1 -0
- package/dist/util/roofs.d.ts +10 -0
- package/dist/util/roofs.js +30 -0
- package/dist/util/roofs.js.map +1 -0
- package/dist/wasm/isard.d.ts +56 -17
- package/dist/wasm/isard.js +128 -18
- package/dist/wasm/isard_core.d.ts +44 -17
- package/dist/wasm/isard_core.js +104 -18
- package/dist/wasm/isard_tess.d.ts +6 -3
- package/dist/wasm/isard_tess.js +27 -4
- package/dist/workers/basemap/geometry.d.ts +38 -22
- package/dist/workers/basemap/labels.d.ts +14 -1
- package/dist/workers/basemap/lamps.d.ts +10 -0
- package/dist/workers/basemap/trees.d.ts +3 -1
- package/dist/workers/basemap.worker.d.ts +43 -3
- package/dist/workers/basemap.worker.js +14 -2
- package/dist/workers/basemap.worker.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,172 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
Every notable change of `isard
|
|
3
|
+
Every notable change of `isard`. The format follows [Keep a Changelog](https://keepachangelog.com), the
|
|
4
4
|
versions [Semantic Versioning](https://semver.org) (before 1.0.0, a minor version may change an API).
|
|
5
5
|
|
|
6
|
+
## [1.6.0] - 2026-10-26
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- IFC models, further: each storey meshed when asked (`storey.load()`, `storey.elements`): a large model's storeys
|
|
11
|
+
one at a time, those in view only; `model.place`, where the model stands, from its `IfcMapConversion` in a projected
|
|
12
|
+
CRS isard knows (the conversion's rotation and scale, the project's unit, the grid's convergence) or else its site's
|
|
13
|
+
latitude and longitude turned by its true north; `ModelLayer.setHighlight(feature, color)` tints a feature (an IFC
|
|
14
|
+
element picked). The IFC models example meshes its storeys one after the other, places FZK-Haus by its true north and
|
|
15
|
+
highlights the element clicked; the georeferenced BIM scene example (TypeScript and React): buildingSMART's scene, one
|
|
16
|
+
IFC file per discipline, each placed by its own map conversion, fitting together.
|
|
17
|
+
- IFC models (BIM): `loadIfc(url | bytes)` of `isard/formats` reads an IFC file with web-ifc (ThatOpen, MPL-2.0;
|
|
18
|
+
fetched on first use from jsDelivr, or `webIfc`: a folder of yours) in a worker of its own: each storey a glTF binary
|
|
19
|
+
for `addModels`, each element a feature of it (its IFC class, name, storey), its properties on demand
|
|
20
|
+
(`model.properties(element)`: attributes, property and quantity sets), its site (`IfcSite`'s latitude and
|
|
21
|
+
longitude). A model with features (`_BATCHID`, `EXT_mesh_features`) is picked by feature: the hit's `index` is the
|
|
22
|
+
element under the point. The IFC models example (TypeScript and React): the KIT's FZK-Haus at its site in Karlsruhe
|
|
23
|
+
and buildingSMART's Duplex, storey by storey, an element's properties on a click.
|
|
24
|
+
- COLLADA models (BIM and CAD exports): `loadCollada(url)` and `parseCollada(text, images)` of `isard/formats` read a
|
|
25
|
+
`.dae` into a glTF binary for `addModels({ data })`: its meshes where its scene's nodes put them, in metres and turned
|
|
26
|
+
from its up axis to glTF's, its materials' colors, transparencies and textures. The examples' new BIM section: A
|
|
27
|
+
BIM building (iTowns' sample building on the IGN's orthophotos and relief, in TypeScript and React), and Inside a
|
|
28
|
+
shopping mall moved there.
|
|
29
|
+
- Panoramax, the open street-level photos of the IGN and OpenStreetMap France: `panoramaxStyle()` gives its MapLibre
|
|
30
|
+
style (its sequences and a dot at each photo, drawn as any style by `vectorTiles().vectors()`), `panoramaxPicture(id)`
|
|
31
|
+
a photo's data from its STAC API (where and when, its heading, its field of view, its images, its producer and
|
|
32
|
+
licence, the photos before and after it), `panoramaxPhoto` the photo for `addPhoto`. `map.addPhoto` stands any photo
|
|
33
|
+
where it was taken, facing its way (a glTF of the photo made by the page: flat on a frame across its field of view, a
|
|
34
|
+
360° one on a band round its camera, each pixel where the camera saw it); from its place (`setFirstPerson`) it lies
|
|
35
|
+
over the buildings it shows. The Panoramax example (TypeScript and React): a dot clicked, its photo in 3D, the photos
|
|
36
|
+
before and after it, the eye in its place with the photo left of a line dragged and the 3D map right of it.
|
|
37
|
+
- `labels({ occluded: true })`: the labels hidden by buildings another `vectorTiles()` raises (a `<VectorGeometry>` of
|
|
38
|
+
the same style, as in the React examples).
|
|
39
|
+
- Street lamps: `tiles.lamps()` places them along the style's streets (30 m apart, every other one on the other side,
|
|
40
|
+
as far from the middle as the street's class says), their heads lit at night; `ModelLayer.setGlow(from, color)`
|
|
41
|
+
lights any model from a height up at night (an additive pass of the model layer). The 3D vector examples show them.
|
|
42
|
+
About 0.3 KB gzipped more for the basemap worker.
|
|
43
|
+
- `<VectorGeometry roofs facades>` in React (the roofs make the layer anew, the facades do not); `{ type: 'trees' }`
|
|
44
|
+
for `map.add` and `<Layer>` (`map.addTrees`, its handle a `ModelLayer`).
|
|
45
|
+
- Landmarks: in `vectors()`, a building holding a theatre, a museum, a place of worship, a castle, a monument, an
|
|
46
|
+
attraction or a town hall (OpenMapTiles' points of interest in its tile) has no office windows, and is floodlit at
|
|
47
|
+
night (a warm light from the foot of its walls fading up them, each face as lit as it faces the lights): the Opéra
|
|
48
|
+
Garnier no longer reads as offices in Paris by night. About 0.1 KB gzipped more for the basemap worker.
|
|
49
|
+
- The trees simplified far away instead of thinned: `trees()` draws every tree in full near the camera and, farther,
|
|
50
|
+
a simplified model (a few faces: some 30 triangles instead of 100), thinned four times more gently, up to three times
|
|
51
|
+
as many as the full ones (`treeModel` and `coniferModel` take `far`); the forest stays dense to the horizon.
|
|
52
|
+
- The models' instances placed by the GPU: uploaded once (until they or the relief under them change), each put in its
|
|
53
|
+
east-north-up frame by the vertex shader, instead of each one's matrix made on the main thread at every frame the
|
|
54
|
+
view moved. The trees example: four times as many trees for 3.6 ms a frame (2.7 for a quarter of them before).
|
|
55
|
+
- Trees of two kinds: `trees()` grows conifers among the broadleaved trees by their wood's data (OpenStreetMap's
|
|
56
|
+
`leaf_type`, PLAN IGN's `nature`; OpenMapTiles' forests a third conifers), drawn on a layer that goes with the one
|
|
57
|
+
returned (`coniferModel`, `TreeColors.conifer`); `map.addTrees({ data })` stands trees at the points of a source that
|
|
58
|
+
has them (a city's street trees), conifers by their leaf type or genus, scaled to their height.
|
|
59
|
+
- The buildings' facades: `vectors({ facades: true })`, `addExtrusions({ facades: true })` (`VectorLayer.setFacades`)
|
|
60
|
+
draw the windows on the walls, a grid of bays and floors along each wall and up from its foot, glass by day (some
|
|
61
|
+
panes lighter, some darker), the same windows lit at night; far away, the walls' even tone. The 3D vector examples
|
|
62
|
+
show them. About 0.7 KB gzipped more for the engines, no frame cost measured.
|
|
63
|
+
- The labels hidden by the buildings, as Mapbox GL's Standard style hides them: `labels()` of a `vectorTiles()` that
|
|
64
|
+
raises its buildings (`vectors()` with a `fill-extrusion` layer, or `extrusions()`) hides a label whole when a
|
|
65
|
+
building, a tree or a model stands before its anchor, and lifts a label in a building onto its roof (its style's
|
|
66
|
+
`fill-extrusion-height`). `addSymbols({ occluded: true })` for any symbol layer. The solid scene's depth is read at
|
|
67
|
+
five pixels around each label's anchor (taken from the sun's shadows when they drew it, no cost, else drawn once a
|
|
68
|
+
frame), the label hidden where three stand nearer than it by more than some metres: no wavering on a roof or
|
|
69
|
+
between close walls. About 1.1 KB gzipped more for the engines, 0.5 KB for the basemap worker.
|
|
70
|
+
- `addExtrusions({ roof, roofHeight })`: the extrusion layers' roofs, as `vectors()` builds them: flat by default, one
|
|
71
|
+
of OpenStreetMap's `roof:shape` per building (hipped, gabled, pyramidal, mansard; the others as the nearest of them),
|
|
72
|
+
or `generated` from its outline; their height as their slopes make it unless given. Changing them with `setStyle`
|
|
73
|
+
builds the blocks again. `VectorTiles.extrusions({ roofs })` makes them as `vectors()` does (`'data'`,
|
|
74
|
+
`'generated'`, `'flat'` by default). The buildings example generates the BD TOPO's roofs.
|
|
75
|
+
- `vectors({ roofs })`: the buildings' roofs, flat by default; as their data says when the tiles have it (`roof:shape`:
|
|
76
|
+
hipped, gabled, pyramidal, mansard; `roof:height`), or generated from their outline (`'generated'`: hipped or gabled
|
|
77
|
+
under 450 m², a mansard under 3000 m², flat past that and for courtyards). A roof is the lower envelope of planes
|
|
78
|
+
rising from its outline's edges, built over the whole building and cut to each tile (its ridges go on across the
|
|
79
|
+
tiles), fitted into the building's height. A concave outline (an L, a T, an H) is cut into wings where a wall carried
|
|
80
|
+
on from an inward corner meets it, each wing roofed and closed by a gable against the next, their eaves level (a
|
|
81
|
+
narrower wing's ridge lower); past six wings, flat. The 3D vector examples use the generated roofs. About 8 KB gzipped more
|
|
82
|
+
for the engines and the tessellation module.
|
|
83
|
+
- `vectors()`: the lines' and buildings' patterns (`line-pattern` as tall as the line, repeated along it;
|
|
84
|
+
`fill-extrusion-pattern` on the roofs as the fills' and along the walls), and the fills' patterns over the relief
|
|
85
|
+
(the ground under each pixel from its depth, drawn once a frame when a patterned layer needs it; on the globe, their
|
|
86
|
+
average color still).
|
|
87
|
+
- `vectors()`: the lines' `line-blur` (each feature's, their edges fading over it) and the fills' and lines'
|
|
88
|
+
translations (`fill-translate`, `line-translate`, turning with the map unless `*-translate-anchor` is `viewport`;
|
|
89
|
+
the fills picked where they are drawn).
|
|
90
|
+
- `vectors()`: the style's circle layers, their points drawn as circles facing the screen (`circle-color`,
|
|
91
|
+
`circle-radius`, `circle-stroke-width` and `circle-stroke-color` with their opacities; picked by feature), and the
|
|
92
|
+
fills' patterns (`fill-pattern`, `background-pattern`) from the style's sprite, anchored to the world and fading from
|
|
93
|
+
one zoom's to the next's as MapLibre's (over the relief, a pattern's average color). The sprite's images go to the
|
|
94
|
+
workers only for the raster path.
|
|
95
|
+
- `vectors()`: the lines joined as their `line-join` says (`miter`, MapLibre's default, bevelled past
|
|
96
|
+
`line-miter-limit`; `bevel`; `round`, the only join before) and offset by `line-offset` (each feature's own,
|
|
97
|
+
following the zoom; the ends of the pieces moved along their miters, so that offset lines still meet). Each line
|
|
98
|
+
piece carries the directions of the line around it, 8 bytes more; about 2 KB gzipped more for the engines, 0.6 KB
|
|
99
|
+
for the tessellation module.
|
|
100
|
+
|
|
101
|
+
- Texts along lines follow their bends (`placement: 'line'`, a vector style's `symbol-placement: line`): each glyph
|
|
102
|
+
placed along the line from the anchor and turned with it, read left to right, its own box in the collision grid; not
|
|
103
|
+
shown round a bend sharper than 45° between two glyphs or off the line's ends; on one line of text. A vector
|
|
104
|
+
basemap's texts along lines repeat every `symbol-spacing`. Labels fade in and out (300 ms), keeping their opacity
|
|
105
|
+
as their tiles come again. About 4 KB gzipped more for the engines.
|
|
106
|
+
- The labels' collisions worked out again every 300 ms while the map moves (and at once when it stops), as MapLibre's:
|
|
107
|
+
in between the labels shown follow the map, their boxes as they were. The collision grid in cells of 16 pixels,
|
|
108
|
+
reaching past the screen. A vector basemap's main thread as before its texts along lines (1.7 ms a frame over the
|
|
109
|
+
3D vector example's drag).
|
|
110
|
+
- GRIB2 packed with CCSDS (data template 5.42), as Météo-France's AROME and ECMWF's open data come: `map.readGrids`
|
|
111
|
+
decodes it in the grid module (CCSDS 121.0-B, as libaec codes it; tested against ecCodes, fuzzed). About 2.4 KB
|
|
112
|
+
gzipped more for the grid module. The example Wind over France (AROME every 2.5 km through the hours of a run), in
|
|
113
|
+
TypeScript and React.
|
|
114
|
+
|
|
115
|
+
### Changed
|
|
116
|
+
|
|
117
|
+
- The examples regrouped by what they show: Getting started, Data layers, Basemaps and terrain, 3D city (the vector
|
|
118
|
+
maps), 3D data (3D Tiles, point clouds, models, panels, three.js), Street level (panoramas, Panoramax), BIM and
|
|
119
|
+
indoor (IFC, COLLADA, a shopping mall), Flows, Analysis and comparison.
|
|
120
|
+
- Zooming a pitched 3D city with Panoramax over it jerked: a far tile's buildings (10 MB and more) went to the GPU in
|
|
121
|
+
one upload, tens of milliseconds, and Panoramax's sequences (a point every few metres, most segments under a pixel,
|
|
122
|
+
each drawn as wide as the line) loaded the GPU until it stalled the page. A large tile's blocks now go a part at a
|
|
123
|
+
time over several frames (2 MB a part, the tile drawn once they all are there, the one it replaces until then), and
|
|
124
|
+
the lines are simplified in the workers to a quarter of a pixel at the tile's zoom (no change on screen). Zooming
|
|
125
|
+
the Panoramax example: 4 frames over 25 ms a zoom instead of 12, the long tasks' time divided by 2.5; the other 3D
|
|
126
|
+
vector maps as before (vector-3d: no frame over 25 ms). The Panoramax example's line between the photo and the 3D
|
|
127
|
+
map is dragged (it followed the cursor).
|
|
128
|
+
- Lines and circles (of `vectors()`, `addLines`, `addCircles`) drawn after buildings, trees or models are hidden
|
|
129
|
+
behind them on a flat map too, as Mapbox GL's buildings hide its lines and circles (in relief they already were by
|
|
130
|
+
the hills); a second style over a 3D city (Panoramax's) no longer shows through its buildings.
|
|
131
|
+
- The sun's light takes the color of its altitude (nearly white high up, golden under 15°, orange at the horizon) and
|
|
132
|
+
the shadows the sky's bluer light, as dark as their opacity; the shadows soften far from the camera (their samples
|
|
133
|
+
spreading up to three times as wide).
|
|
134
|
+
- `vectors()`: a filter reading the zoom holds as MapLibre evaluates it, at the whole zoom under the camera's, not at
|
|
135
|
+
the level of the tile drawn (drawn from half a level under it, a tile of level 15 showed `['>=', ['zoom'], 15]`
|
|
136
|
+
from 14.5): each feature styled with the zooms its filter holds over, which the engine checks at the camera's zoom.
|
|
137
|
+
- At night, the ground is darker where the buildings around hide the sky: the streets and courtyards read under the
|
|
138
|
+
roofs, which kept the same blue (the sun's map drawn from straight above, its heights giving each pixel's share of
|
|
139
|
+
the sky within 25 metres). Two depth passes more a frame at night, as by day with shadows.
|
|
140
|
+
|
|
141
|
+
### Fixed
|
|
142
|
+
|
|
143
|
+
- The floodlit landmarks flickered at night as the view moved: the lights were drawn a hair nearer than the walls
|
|
144
|
+
they light, so a wall just behind another (the parts of a monument inside one another) caught light in streaks that
|
|
145
|
+
came and went. The blocks' lights are now drawn only on the surfaces drawn (`invariant gl_Position`, depth `EQUAL`):
|
|
146
|
+
at the Opéra Garnier, a third of the pixels changing as the view moves by a quarter pixel.
|
|
147
|
+
- A paint property set as a `vectors()` style loads (`setPaintProperty` right after `vectors()`, or `paint` of a
|
|
148
|
+
`<VectorGeometry>`) was lost: the tiles cut under the former style before it came were never restyled.
|
|
149
|
+
- Paris by night flickered as the view moved: the parts of a landmark's building (the Opéra Garnier's stage tower,
|
|
150
|
+
the Louvre's wings) were not landmarks unless they held its point of interest, and their dark walls with lit windows
|
|
151
|
+
fought the floodlit walls along them; a building inside a landmark's, or holding its middle, is now one too (a
|
|
152
|
+
neighbour against its wall is not). The lit windows, bright points on dark walls, sparkled far away where they shrank
|
|
153
|
+
to a pixel: they now fade from bays of 6 pixels to 2 (the glass by day as before), a faint even glow in their place.
|
|
154
|
+
- `map.rebuildLayer` (a `<Layer>` or a bound layer made anew) moves the new layer's companions with it (the
|
|
155
|
+
conifers of `addTrees`), and no longer places it under the old one's companions, removed with it.
|
|
156
|
+
- Zooming in a 3D vector map jerked as tiles came in: their meshes were all uploaded as they arrived, several in one
|
|
157
|
+
frame (copying their buffers to the GPU, tens of milliseconds each), and the frames after waited on the GPU.
|
|
158
|
+
`vectors()` now uploads them over several frames, 4 ms a frame (a tile out of view still drawn until its
|
|
159
|
+
replacements are uploaded): zooming in and out of the 3D vector examples, 0 to 3 frames over 25 ms instead of 5 to 27.
|
|
160
|
+
- `vectors()` over the relief with no raster layer under it (`basemap: 'none'`): its fills showed nowhere, the shadow
|
|
161
|
+
volumes they are drawn with finding no ground in the depth buffer. The relief's ground is now drawn (its depth
|
|
162
|
+
alone) when no raster layer draws it first, over the tiles a raster layer would draw (#42).
|
|
163
|
+
- Zooming jerked and tiles blinked out: `vectors()` dropped a tile out of view once the tiles its own update asked for
|
|
164
|
+
were there, not those an earlier update was still waiting for, leaving a hole for a frame or more; the labels of new
|
|
165
|
+
tiles (thousands of features past the source's deepest level, shaped again at each whole zoom) held the main thread
|
|
166
|
+
up to 200 ms. A tile out of view now stays drawn until every tile of the view is there, and the labels are shaped a
|
|
167
|
+
slice at a time, a frame let through every 6 ms: zooming in and out of the 3D vector example, no frame over 50 ms
|
|
168
|
+
(217 before), two long tasks instead of thirteen.
|
|
169
|
+
|
|
6
170
|
## [1.5.0] - 2026-10-24
|
|
7
171
|
|
|
8
172
|
### Added
|
package/README.md
CHANGED
|
@@ -179,8 +179,9 @@ More in [Develop and release](https://ideal-adventure-zqn6y6p.pages.github.io/gu
|
|
|
179
179
|
|
|
180
180
|
## Roadmap
|
|
181
181
|
|
|
182
|
-
The whole MapLibre style drawn as vectors, a 3D vector map to walk through,
|
|
183
|
-
buildings, more of the models' files), several projections
|
|
182
|
+
The whole MapLibre style drawn as vectors, a 3D vector map to walk through, Panoramax's street-level photos on the map
|
|
183
|
+
and at street level, fluids on the globe (wakes behind the buildings, more of the models' files), several projections
|
|
184
|
+
on the globe, and smaller items: see
|
|
184
185
|
[Roadmap](https://ideal-adventure-zqn6y6p.pages.github.io/guide/roadmap).
|
|
185
186
|
|
|
186
187
|
## Licence
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The street furniture of a vector map (`VectorTiles.lamps`): a street lamp made here as a glTF binary (no file to
|
|
3
|
+
* download), its pole and its head flat-shaded, the head lit at night (`ModelLayer.setGlow` from `LAMP_HEAD` up).
|
|
4
|
+
*/
|
|
5
|
+
/** Metres from a lamp's foot to its head: the part lit at night */
|
|
6
|
+
export declare const LAMP_HEAD = 4.6;
|
|
7
|
+
/** A street lamp as a glTF binary, some 5 metres high: a thin pole, a lantern on top */
|
|
8
|
+
export declare const lampModel: () => Uint8Array<ArrayBuffer>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The street furniture of a vector map (`VectorTiles.lamps`): a street lamp made here as a glTF binary (no file to
|
|
3
|
+
* download), its pole and its head flat-shaded, the head lit at night (`ModelLayer.setGlow` from `LAMP_HEAD` up).
|
|
4
|
+
*/
|
|
5
|
+
import { glb, revolve } from "./trees.js";
|
|
6
|
+
/** Colors of a street lamp (linear RGBA, as glTF's `baseColorFactor`): Paris's dark green cast iron */
|
|
7
|
+
const POLE = [0.04, 0.07, 0.05, 1];
|
|
8
|
+
const HEAD = [0.55, 0.52, 0.42, 1];
|
|
9
|
+
/** Metres from a lamp's foot to its head: the part lit at night */
|
|
10
|
+
export const LAMP_HEAD = 4.6;
|
|
11
|
+
/** A street lamp as a glTF binary, some 5 metres high: a thin pole, a lantern on top */
|
|
12
|
+
export const lampModel = () => {
|
|
13
|
+
const pole = revolve([
|
|
14
|
+
[0, 0.14],
|
|
15
|
+
[0.6, 0.1],
|
|
16
|
+
[LAMP_HEAD, 0.06],
|
|
17
|
+
], 5);
|
|
18
|
+
const head = revolve([
|
|
19
|
+
[LAMP_HEAD, 0.12],
|
|
20
|
+
[4.95, 0.32],
|
|
21
|
+
[5.25, 0.26],
|
|
22
|
+
[5.45, 0],
|
|
23
|
+
], 6);
|
|
24
|
+
return glb([pole, head], [POLE, HEAD]);
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=furniture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"furniture.js","sourceRoot":"","sources":["../../src/basemap/furniture.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,uGAAuG;AACvG,MAAM,IAAI,GAAqC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACrE,MAAM,IAAI,GAAqC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAErE,mEAAmE;AACnE,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAE7B,wFAAwF;AACxF,MAAM,CAAC,MAAM,SAAS,GAAG,GAA4B,EAAE;IACrD,MAAM,IAAI,GAAG,OAAO,CAClB;QACE,CAAC,CAAC,EAAE,IAAI,CAAC;QACT,CAAC,GAAG,EAAE,GAAG,CAAC;QACV,CAAC,SAAS,EAAE,IAAI,CAAC;KAClB,EACD,CAAC,CACF,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAClB;QACE,CAAC,SAAS,EAAE,IAAI,CAAC;QACjB,CAAC,IAAI,EAAE,IAAI,CAAC;QACZ,CAAC,IAAI,EAAE,IAAI,CAAC;QACZ,CAAC,IAAI,EAAE,CAAC,CAAC;KACV,EACD,CAAC,CACF,CAAC;IAEF,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACzC,CAAC,CAAC","sourcesContent":["/**\n * The street furniture of a vector map (`VectorTiles.lamps`): a street lamp made here as a glTF binary (no file to\n * download), its pole and its head flat-shaded, the head lit at night (`ModelLayer.setGlow` from `LAMP_HEAD` up).\n */\n\nimport { glb, revolve } from './trees.ts';\n\n/** Colors of a street lamp (linear RGBA, as glTF's `baseColorFactor`): Paris's dark green cast iron */\nconst POLE: [number, number, number, number] = [0.04, 0.07, 0.05, 1];\nconst HEAD: [number, number, number, number] = [0.55, 0.52, 0.42, 1];\n\n/** Metres from a lamp's foot to its head: the part lit at night */\nexport const LAMP_HEAD = 4.6;\n\n/** A street lamp as a glTF binary, some 5 metres high: a thin pole, a lantern on top */\nexport const lampModel = (): Uint8Array<ArrayBuffer> => {\n const pole = revolve(\n [\n [0, 0.14],\n [0.6, 0.1],\n [LAMP_HEAD, 0.06],\n ],\n 5,\n );\n const head = revolve(\n [\n [LAMP_HEAD, 0.12],\n [4.95, 0.32],\n [5.25, 0.26],\n [5.45, 0],\n ],\n 6,\n );\n\n return glb([pole, head], [POLE, HEAD]);\n};\n"]}
|
package/dist/basemap/trees.d.ts
CHANGED
|
@@ -1,20 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The trees of a vector map (`VectorTiles.trees`):
|
|
3
|
-
*
|
|
2
|
+
* The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a
|
|
3
|
+
* broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by
|
|
4
|
+
* default, and the share of conifers in a wood from its data.
|
|
4
5
|
*/
|
|
6
|
+
import type { Value } from './mvt.ts';
|
|
5
7
|
import type { StyleLayer } from './vectorstyle.ts';
|
|
6
|
-
/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank, kind (0 broadleaved, 1
|
|
9
|
+
* conifer) */
|
|
10
|
+
export declare const TREE_NUMBERS = 6;
|
|
11
|
+
/** Colors of the trunk, of the broadleaved crown and of the conifers' (linear RGBA, as glTF's `baseColorFactor`) */
|
|
9
12
|
export interface TreeColors {
|
|
10
13
|
trunk: [number, number, number, number];
|
|
11
14
|
crown: [number, number, number, number];
|
|
15
|
+
conifer: [number, number, number, number];
|
|
12
16
|
}
|
|
17
|
+
/** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the
|
|
18
|
+
* top when its radius is 0; the triangles' positions and normals, one normal per face */
|
|
19
|
+
export declare const revolve: (rings: [height: number, radius: number][], sides?: number) => {
|
|
20
|
+
positions: number[];
|
|
21
|
+
normals: number[];
|
|
22
|
+
};
|
|
23
|
+
/** Parts flat-shaded in their colors as a glTF binary: one mesh of a primitive each, its front +Z
|
|
24
|
+
* (`ModelInstance.heading` turns it), standing on its origin */
|
|
25
|
+
export declare const glb: (parts: {
|
|
26
|
+
positions: number[];
|
|
27
|
+
normals: number[];
|
|
28
|
+
}[], colors: TreeColors[keyof TreeColors][]) => Uint8Array<ArrayBuffer>;
|
|
13
29
|
/**
|
|
14
|
-
* A tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors
|
|
15
|
-
*
|
|
30
|
+
* A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the
|
|
31
|
+
* same simplified for far away, a few faces (some 30 triangles instead of 100)
|
|
16
32
|
*/
|
|
17
|
-
export declare const treeModel: (colors?: Partial<TreeColors
|
|
33
|
+
export declare const treeModel: (colors?: Partial<TreeColors>, far?: boolean) => Uint8Array<ArrayBuffer>;
|
|
34
|
+
/**
|
|
35
|
+
* A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one
|
|
36
|
+
* pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)
|
|
37
|
+
*/
|
|
38
|
+
export declare const coniferModel: (colors?: Partial<TreeColors>, far?: boolean) => Uint8Array<ArrayBuffer>;
|
|
18
39
|
/**
|
|
19
40
|
* Whether trees grow on a style layer by default: the woods and forests of the style's fills (OpenMapTiles'
|
|
20
41
|
* `landcover` wood, PLAN IGN's forests) and the grass of its parks and gardens; not the wooded relief of PLAN IGN,
|
|
@@ -24,3 +45,9 @@ export declare const treeModel: (colors?: Partial<TreeColors>) => Uint8Array<Arr
|
|
|
24
45
|
export declare const isWoodland: (layer: StyleLayer) => boolean;
|
|
25
46
|
/** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */
|
|
26
47
|
export declare const treeSpacing: (layer: StyleLayer) => number;
|
|
48
|
+
/**
|
|
49
|
+
* The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,
|
|
50
|
+
* mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third
|
|
51
|
+
* conifers and its other woods some, the grass of parks none
|
|
52
|
+
*/
|
|
53
|
+
export declare const coniferShare: (properties: Record<string, Value>) => number;
|
package/dist/basemap/trees.js
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The trees of a vector map (`VectorTiles.trees`):
|
|
3
|
-
*
|
|
2
|
+
* The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a
|
|
3
|
+
* broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by
|
|
4
|
+
* default, and the share of conifers in a wood from its data.
|
|
4
5
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import { bounds, glbOf } from "../util/gltf.js";
|
|
7
|
+
/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank, kind (0 broadleaved, 1
|
|
8
|
+
* conifer) */
|
|
9
|
+
export const TREE_NUMBERS = 6;
|
|
10
|
+
/** Sides of the trunk and of the crown near the view; of the crown far away (a pyramid), of the trunk there */
|
|
8
11
|
const SIDES = 7;
|
|
12
|
+
const FAR_SIDES = 4;
|
|
13
|
+
const FAR_TRUNK_SIDES = 3;
|
|
9
14
|
const DEFAULT_COLORS = {
|
|
10
15
|
trunk: [0.2, 0.12, 0.07, 1],
|
|
11
16
|
crown: [0.12, 0.27, 0.08, 1],
|
|
17
|
+
conifer: [0.05, 0.16, 0.08, 1],
|
|
12
18
|
};
|
|
13
19
|
/** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the
|
|
14
20
|
* top when its radius is 0; the triangles' positions and normals, one normal per face */
|
|
15
|
-
const revolve = (rings) => {
|
|
21
|
+
export const revolve = (rings, sides = SIDES) => {
|
|
16
22
|
const at = (k, [h, r]) => {
|
|
17
|
-
const a = (k /
|
|
23
|
+
const a = (k / sides) * Math.PI * 2;
|
|
18
24
|
return [Math.cos(a) * r, h, Math.sin(a) * r];
|
|
19
25
|
};
|
|
20
26
|
const positions = [];
|
|
@@ -34,7 +40,7 @@ const revolve = (rings) => {
|
|
|
34
40
|
};
|
|
35
41
|
rings.slice(1).forEach((ring, i) => {
|
|
36
42
|
const below = rings[i] ?? ring;
|
|
37
|
-
Array.from({ length:
|
|
43
|
+
Array.from({ length: sides }, (_, k) => k).forEach((k) => {
|
|
38
44
|
const [a, b] = [at(k, below), at(k + 1, below)];
|
|
39
45
|
const [c, d] = [at(k, ring), at(k + 1, ring)];
|
|
40
46
|
// Counter-clockwise seen from outside
|
|
@@ -45,37 +51,15 @@ const revolve = (rings) => {
|
|
|
45
51
|
// The bottom closed: seen from below
|
|
46
52
|
const base = rings[0];
|
|
47
53
|
if (base && base[1] > 0) {
|
|
48
|
-
Array.from({ length:
|
|
54
|
+
Array.from({ length: sides }, (_, k) => k).forEach((k) => {
|
|
49
55
|
face([0, base[0], 0], at(k, base), at(k + 1, base));
|
|
50
56
|
});
|
|
51
57
|
}
|
|
52
58
|
return { positions, normals };
|
|
53
59
|
};
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return { min: axes.map((v) => Math.min(...v)), max: axes.map((v) => Math.max(...v)) };
|
|
58
|
-
};
|
|
59
|
-
/**
|
|
60
|
-
* A tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`, one mesh of two primitives,
|
|
61
|
-
* its front +Z (`ModelInstance.heading` turns it), standing on its origin
|
|
62
|
-
*/
|
|
63
|
-
export const treeModel = (colors = {}) => {
|
|
64
|
-
const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };
|
|
65
|
-
const parts = [
|
|
66
|
-
revolve([
|
|
67
|
-
[0, 0.28],
|
|
68
|
-
[3.2, 0.2],
|
|
69
|
-
]),
|
|
70
|
-
revolve([
|
|
71
|
-
[2.4, 0.6],
|
|
72
|
-
[3.6, 2.4],
|
|
73
|
-
[5.6, 2.9],
|
|
74
|
-
[7.8, 2.3],
|
|
75
|
-
[9.4, 1.1],
|
|
76
|
-
[10.2, 0],
|
|
77
|
-
]),
|
|
78
|
-
];
|
|
60
|
+
/** Parts flat-shaded in their colors as a glTF binary: one mesh of a primitive each, its front +Z
|
|
61
|
+
* (`ModelInstance.heading` turns it), standing on its origin */
|
|
62
|
+
export const glb = (parts, colors) => {
|
|
79
63
|
// The buffer: each part's positions then normals, 4-byte floats
|
|
80
64
|
const floats = parts.flatMap((p) => [...p.positions, ...p.normals]);
|
|
81
65
|
const bin = new Float32Array(floats);
|
|
@@ -100,30 +84,81 @@ export const treeModel = (colors = {}) => {
|
|
|
100
84
|
primitives: parts.map((_, i) => ({ attributes: { POSITION: i * 2, NORMAL: i * 2 + 1 }, material: i })),
|
|
101
85
|
},
|
|
102
86
|
],
|
|
103
|
-
materials:
|
|
87
|
+
materials: colors.map((color) => ({
|
|
104
88
|
pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },
|
|
105
89
|
})),
|
|
106
90
|
accessors,
|
|
107
91
|
bufferViews: views,
|
|
108
92
|
buffers: [{ byteLength: bin.byteLength }],
|
|
109
93
|
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
94
|
+
return glbOf(gltf, new Uint8Array(bin.buffer));
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the
|
|
98
|
+
* same simplified for far away, a few faces (some 30 triangles instead of 100)
|
|
99
|
+
*/
|
|
100
|
+
export const treeModel = (colors = {}, far = false) => {
|
|
101
|
+
const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };
|
|
102
|
+
if (far) {
|
|
103
|
+
const stem = revolve([
|
|
104
|
+
[0, 0.3],
|
|
105
|
+
[3, 0.22],
|
|
106
|
+
], FAR_TRUNK_SIDES);
|
|
107
|
+
const top = revolve([
|
|
108
|
+
[2.4, 0.8],
|
|
109
|
+
[5.6, 2.9],
|
|
110
|
+
[10.2, 0],
|
|
111
|
+
], FAR_SIDES);
|
|
112
|
+
return glb([stem, top], [trunk, crown]);
|
|
113
|
+
}
|
|
114
|
+
const parts = [
|
|
115
|
+
revolve([
|
|
116
|
+
[0, 0.28],
|
|
117
|
+
[3.2, 0.2],
|
|
118
|
+
]),
|
|
119
|
+
revolve([
|
|
120
|
+
[2.4, 0.6],
|
|
121
|
+
[3.6, 2.4],
|
|
122
|
+
[5.6, 2.9],
|
|
123
|
+
[7.8, 2.3],
|
|
124
|
+
[9.4, 1.1],
|
|
125
|
+
[10.2, 0],
|
|
126
|
+
]),
|
|
127
|
+
];
|
|
128
|
+
return glb(parts, [trunk, crown]);
|
|
129
|
+
};
|
|
130
|
+
/** A cone of the conifers' crown: from `base` metres up, `radius` wide, to its point at `top` */
|
|
131
|
+
const cone = (base, radius, top) => revolve([
|
|
132
|
+
[base, radius],
|
|
133
|
+
[top, 0],
|
|
134
|
+
]);
|
|
135
|
+
/**
|
|
136
|
+
* A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one
|
|
137
|
+
* pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)
|
|
138
|
+
*/
|
|
139
|
+
export const coniferModel = (colors = {}, far = false) => {
|
|
140
|
+
const { trunk, conifer } = { ...DEFAULT_COLORS, ...colors };
|
|
141
|
+
if (far) {
|
|
142
|
+
const stem = revolve([
|
|
143
|
+
[0, 0.24],
|
|
144
|
+
[2, 0.18],
|
|
145
|
+
], FAR_TRUNK_SIDES);
|
|
146
|
+
const top = revolve([
|
|
147
|
+
[1.4, 2.3],
|
|
148
|
+
[11, 0],
|
|
149
|
+
], FAR_SIDES);
|
|
150
|
+
return glb([stem, top], [trunk, conifer]);
|
|
151
|
+
}
|
|
152
|
+
const tiers = [cone(1.4, 2.4, 5.4), cone(3.6, 1.9, 8), cone(6, 1.3, 11)];
|
|
153
|
+
const crown = {
|
|
154
|
+
positions: tiers.flatMap((t) => t.positions),
|
|
155
|
+
normals: tiers.flatMap((t) => t.normals),
|
|
156
|
+
};
|
|
157
|
+
const stem = revolve([
|
|
158
|
+
[0, 0.24],
|
|
159
|
+
[2, 0.18],
|
|
160
|
+
]);
|
|
161
|
+
return glb([stem, crown], [trunk, conifer]);
|
|
127
162
|
};
|
|
128
163
|
/** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */
|
|
129
164
|
const isGrass = (layer) => layer['source-layer'] === 'landcover' && /grass/i.test(layer.id);
|
|
@@ -138,4 +173,22 @@ export const isWoodland = (layer) => layer.type === 'fill' &&
|
|
|
138
173
|
(/wood|forest|for[eê]t/i.test(layer.id) || isGrass(layer));
|
|
139
174
|
/** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */
|
|
140
175
|
export const treeSpacing = (layer) => (isGrass(layer) ? 25 : 9);
|
|
176
|
+
/**
|
|
177
|
+
* The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,
|
|
178
|
+
* mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third
|
|
179
|
+
* conifers and its other woods some, the grass of parks none
|
|
180
|
+
*/
|
|
181
|
+
export const coniferShare = (properties) => {
|
|
182
|
+
const leaf = properties.leaf_type;
|
|
183
|
+
const nature = typeof properties.nature === 'string' ? properties.nature : '';
|
|
184
|
+
if (leaf === 'needleleaved' || /conif/i.test(nature))
|
|
185
|
+
return 1;
|
|
186
|
+
if (leaf === 'broadleaved' || /feuillu/i.test(nature))
|
|
187
|
+
return 0;
|
|
188
|
+
if (leaf === 'mixed' || /mixte/i.test(nature))
|
|
189
|
+
return 0.5;
|
|
190
|
+
if (properties.class === 'wood')
|
|
191
|
+
return properties.subclass === 'forest' ? 0.35 : 0.15;
|
|
192
|
+
return 0;
|
|
193
|
+
};
|
|
141
194
|
//# sourceMappingURL=trees.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trees.js","sourceRoot":"","sources":["../../src/basemap/trees.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The trees of a vector map (`VectorTiles.trees`): a low-poly tree made here as a glTF binary (no file to download),\n * its trunk and its crown flat-shaded in their colors, and the style layers they grow on by default.\n */\n\nimport type { StyleLayer } from './vectorstyle.ts';\n\n/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank */\nexport const TREE_NUMBERS = 5;\n\n/** A point or a vector: x, y, z */\ntype Vec3 = [number, number, number];\n\n/** Sides of the trunk and of the crown */\nconst SIDES = 7;\n\n/** Colors of the trunk and of the crown (linear RGBA, as glTF's `baseColorFactor`) */\nexport interface TreeColors {\n trunk: [number, number, number, number];\n crown: [number, number, number, number];\n}\n\nconst DEFAULT_COLORS: TreeColors = {\n trunk: [0.2, 0.12, 0.07, 1],\n crown: [0.12, 0.27, 0.08, 1],\n};\n\n/** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the\n * top when its radius is 0; the triangles' positions and normals, one normal per face */\nconst revolve = (rings: [height: number, radius: number][]): { positions: number[]; normals: number[] } => {\n const at = (k: number, [h, r]: [number, number]): Vec3 => {\n const a = (k / SIDES) * Math.PI * 2;\n\n return [Math.cos(a) * r, h, Math.sin(a) * r];\n };\n const positions: number[] = [];\n const normals: number[] = [];\n const face = (a: Vec3, b: Vec3, c: Vec3) => {\n const u: Vec3 = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];\n const v: Vec3 = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];\n const n: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const length = Math.hypot(...n);\n\n // A degenerate face (two points at the apex) is left out\n if (length === 0) return;\n positions.push(...a, ...b, ...c);\n [0, 1, 2].forEach(() => {\n normals.push(n[0] / length, n[1] / length, n[2] / length);\n });\n };\n\n rings.slice(1).forEach((ring, i) => {\n const below = rings[i] ?? ring;\n\n Array.from({ length: SIDES }, (_, k) => k).forEach((k) => {\n const [a, b] = [at(k, below), at(k + 1, below)];\n const [c, d] = [at(k, ring), at(k + 1, ring)];\n\n // Counter-clockwise seen from outside\n face(a, c, b);\n face(b, c, d);\n });\n });\n // The bottom closed: seen from below\n const base = rings[0];\n\n if (base && base[1] > 0) {\n Array.from({ length: SIDES }, (_, k) => k).forEach((k) => {\n face([0, base[0], 0], at(k, base), at(k + 1, base));\n });\n }\n\n return { positions, normals };\n};\n\n/** Lowest and highest of interleaved x, y, z (glTF needs them on positions) */\nconst bounds = (xyz: number[]): { min: number[]; max: number[] } => {\n const axes = [0, 1, 2].map((a) => xyz.filter((_, i) => i % 3 === a));\n\n return { min: axes.map((v) => Math.min(...v)), max: axes.map((v) => Math.max(...v)) };\n};\n\n/**\n * A tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`, one mesh of two primitives,\n * its front +Z (`ModelInstance.heading` turns it), standing on its origin\n */\nexport const treeModel = (colors: Partial<TreeColors> = {}): Uint8Array<ArrayBuffer> => {\n const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };\n const parts = [\n revolve([\n [0, 0.28],\n [3.2, 0.2],\n ]),\n revolve([\n [2.4, 0.6],\n [3.6, 2.4],\n [5.6, 2.9],\n [7.8, 2.3],\n [9.4, 1.1],\n [10.2, 0],\n ]),\n ];\n // The buffer: each part's positions then normals, 4-byte floats\n const floats = parts.flatMap((p) => [...p.positions, ...p.normals]);\n const bin = new Float32Array(floats);\n const views = parts.flatMap((p, i) => {\n const before = parts.slice(0, i).reduce((n, q) => n + (q.positions.length + q.normals.length) * 4, 0);\n\n return [\n { buffer: 0, byteOffset: before, byteLength: p.positions.length * 4, target: 34962 },\n { buffer: 0, byteOffset: before + p.positions.length * 4, byteLength: p.normals.length * 4, target: 34962 },\n ];\n });\n const accessors = parts.flatMap((p, i) => [\n { bufferView: i * 2, componentType: 5126, count: p.positions.length / 3, type: 'VEC3', ...bounds(p.positions) },\n { bufferView: i * 2 + 1, componentType: 5126, count: p.normals.length / 3, type: 'VEC3' },\n ]);\n const gltf = {\n asset: { version: '2.0', generator: 'isard' },\n scene: 0,\n scenes: [{ nodes: [0] }],\n nodes: [{ mesh: 0 }],\n meshes: [\n {\n primitives: parts.map((_, i) => ({ attributes: { POSITION: i * 2, NORMAL: i * 2 + 1 }, material: i })),\n },\n ],\n materials: [trunk, crown].map((color) => ({\n pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },\n })),\n accessors,\n bufferViews: views,\n buffers: [{ byteLength: bin.byteLength }],\n };\n // The chunks padded to 4 bytes: the JSON with spaces, the binary with zeros\n const json = new TextEncoder().encode(JSON.stringify(gltf));\n const jsonLength = Math.ceil(json.length / 4) * 4;\n const binLength = Math.ceil(bin.byteLength / 4) * 4;\n const out = new Uint8Array(12 + 8 + jsonLength + 8 + binLength);\n const view = new DataView(out.buffer);\n\n view.setUint32(0, 0x46546c67, true);\n view.setUint32(4, 2, true);\n view.setUint32(8, out.length, true);\n view.setUint32(12, jsonLength, true);\n view.setUint32(16, 0x4e4f534a, true);\n out.fill(0x20, 20, 20 + jsonLength);\n out.set(json, 20);\n view.setUint32(20 + jsonLength, binLength, true);\n view.setUint32(24 + jsonLength, 0x004e4942, true);\n out.set(new Uint8Array(bin.buffer), 28 + jsonLength);\n\n return out;\n};\n\n/** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */\nconst isGrass = (layer: StyleLayer): boolean => layer['source-layer'] === 'landcover' && /grass/i.test(layer.id);\n\n/**\n * Whether trees grow on a style layer by default: the woods and forests of the style's fills (OpenMapTiles'\n * `landcover` wood, PLAN IGN's forests) and the grass of its parks and gardens; not the wooded relief of PLAN IGN,\n * which repeats its forests, nor OpenMapTiles' `park` layer (protected areas and historic sites: a river's banks\n * among them)\n */\nexport const isWoodland = (layer: StyleLayer): boolean =>\n layer.type === 'fill' &&\n layer['source-layer'] !== 'oro_relief' &&\n (/wood|forest|for[eê]t/i.test(layer.id) || isGrass(layer));\n\n/** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */\nexport const treeSpacing = (layer: StyleLayer): number => (isGrass(layer) ? 25 : 9);\n"]}
|
|
1
|
+
{"version":3,"file":"trees.js","sourceRoot":"","sources":["../../src/basemap/trees.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAIhD;cACc;AACd,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAK9B,+GAA+G;AAC/G,MAAM,KAAK,GAAG,CAAC,CAAC;AAChB,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,eAAe,GAAG,CAAC,CAAC;AAS1B,MAAM,cAAc,GAAe;IACjC,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3B,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5B,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;CAC/B,CAAC;AAEF;yFACyF;AACzF,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,KAAyC,EACzC,KAAK,GAAG,KAAK,EAC+B,EAAE;IAC9C,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAmB,EAAQ,EAAE;QACvD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;QAEpC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC;IACF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,CAAO,EAAE,CAAO,EAAE,CAAO,EAAE,EAAE;QACzC,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,GAAS,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClG,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QAEhC,yDAAyD;QACzD,IAAI,MAAM,KAAK,CAAC;YAAE,OAAO;QACzB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;YACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAE/B,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAE9C,sCAAsC;YACtC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,qCAAqC;IACrC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAEtB,IAAI,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACvD,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC,CAAC;AAEF;gEACgE;AAChE,MAAM,CAAC,MAAM,GAAG,GAAG,CACjB,KAAmD,EACnD,MAAsC,EACb,EAAE;IAC3B,gEAAgE;IAChE,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,MAAM,GAAG,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;QAEtG,OAAO;YACL,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;YACpF,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE;SAC5G,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;QAC/G,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE;KAC1F,CAAC,CAAC;IACH,MAAM,IAAI,GAAG;QACX,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE;QAC7C,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACpB,MAAM,EAAE;YACN;gBACE,UAAU,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;aACvG;SACF;QACD,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAChC,oBAAoB,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE;SACxF,CAAC,CAAC;QACH,SAAS;QACT,WAAW,EAAE,KAAK;QAClB,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC;KAC1C,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,EAAE,IAAI,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,SAA8B,EAAE,EAAE,GAAG,GAAG,KAAK,EAA2B,EAAE;IAClG,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAE1D,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,OAAO,CAClB;YACE,CAAC,CAAC,EAAE,GAAG,CAAC;YACR,CAAC,CAAC,EAAE,IAAI,CAAC;SACV,EACD,eAAe,CAChB,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CACjB;YACE,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,IAAI,EAAE,CAAC,CAAC;SACV,EACD,SAAS,CACV,CAAC;QAEF,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,OAAO,CAAC;YACN,CAAC,CAAC,EAAE,IAAI,CAAC;YACT,CAAC,GAAG,EAAE,GAAG,CAAC;SACX,CAAC;QACF,OAAO,CAAC;YACN,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,IAAI,EAAE,CAAC,CAAC;SACV,CAAC;KACH,CAAC;IAEF,OAAO,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF,iGAAiG;AACjG,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,MAAc,EAAE,GAAW,EAAE,EAAE,CACzD,OAAO,CAAC;IACN,CAAC,IAAI,EAAE,MAAM,CAAC;IACd,CAAC,GAAG,EAAE,CAAC,CAAC;CACT,CAAC,CAAC;AAEL;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,SAA8B,EAAE,EAAE,GAAG,GAAG,KAAK,EAA2B,EAAE;IACrG,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;IAE5D,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,IAAI,GAAG,OAAO,CAClB;YACE,CAAC,CAAC,EAAE,IAAI,CAAC;YACT,CAAC,CAAC,EAAE,IAAI,CAAC;SACV,EACD,eAAe,CAChB,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CACjB;YACE,CAAC,GAAG,EAAE,GAAG,CAAC;YACV,CAAC,EAAE,EAAE,CAAC,CAAC;SACR,EACD,SAAS,CACV,CAAC;QAEF,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG;QACZ,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5C,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;KACzC,CAAC;IACF,MAAM,IAAI,GAAG,OAAO,CAAC;QACnB,CAAC,CAAC,EAAE,IAAI,CAAC;QACT,CAAC,CAAC,EAAE,IAAI,CAAC;KACV,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9C,CAAC,CAAC;AAEF,6FAA6F;AAC7F,MAAM,OAAO,GAAG,CAAC,KAAiB,EAAW,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,KAAK,WAAW,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAEjH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAiB,EAAW,EAAE,CACvD,KAAK,CAAC,IAAI,KAAK,MAAM;IACrB,KAAK,CAAC,cAAc,CAAC,KAAK,YAAY;IACtC,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AAE7D,mGAAmG;AACnG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAiB,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEpF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,UAAiC,EAAU,EAAE;IACxE,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,CAAC;IAClC,MAAM,MAAM,GAAG,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9E,IAAI,IAAI,KAAK,cAAc,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAC;IAC/D,IAAI,IAAI,KAAK,aAAa,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,CAAC,CAAC;IAChE,IAAI,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,GAAG,CAAC;IAC1D,IAAI,UAAU,CAAC,KAAK,KAAK,MAAM;QAAE,OAAO,UAAU,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvF,OAAO,CAAC,CAAC;AACX,CAAC,CAAC","sourcesContent":["/**\n * The trees of a vector map (`VectorTiles.trees`): low-poly trees made here as glTF binaries (no file to download), a\n * broadleaved one and a conifer, their trunk and crown flat-shaded in their colors; the style layers they grow on by\n * default, and the share of conifers in a wood from its data.\n */\n\nimport { bounds, glbOf } from '../util/gltf.ts';\nimport type { Value } from './mvt.ts';\nimport type { StyleLayer } from './vectorstyle.ts';\n\n/** Numbers of a tree in the workers' answer: longitude, latitude, scale, heading, rank, kind (0 broadleaved, 1\n * conifer) */\nexport const TREE_NUMBERS = 6;\n\n/** A point or a vector: x, y, z */\ntype Vec3 = [number, number, number];\n\n/** Sides of the trunk and of the crown near the view; of the crown far away (a pyramid), of the trunk there */\nconst SIDES = 7;\nconst FAR_SIDES = 4;\nconst FAR_TRUNK_SIDES = 3;\n\n/** Colors of the trunk, of the broadleaved crown and of the conifers' (linear RGBA, as glTF's `baseColorFactor`) */\nexport interface TreeColors {\n trunk: [number, number, number, number];\n crown: [number, number, number, number];\n conifer: [number, number, number, number];\n}\n\nconst DEFAULT_COLORS: TreeColors = {\n trunk: [0.2, 0.12, 0.07, 1],\n crown: [0.12, 0.27, 0.08, 1],\n conifer: [0.05, 0.16, 0.08, 1],\n};\n\n/** A solid of revolution around the vertical (glTF +Y up), flat-shaded: rings of (height, radius), a point at the\n * top when its radius is 0; the triangles' positions and normals, one normal per face */\nexport const revolve = (\n rings: [height: number, radius: number][],\n sides = SIDES,\n): { positions: number[]; normals: number[] } => {\n const at = (k: number, [h, r]: [number, number]): Vec3 => {\n const a = (k / sides) * Math.PI * 2;\n\n return [Math.cos(a) * r, h, Math.sin(a) * r];\n };\n const positions: number[] = [];\n const normals: number[] = [];\n const face = (a: Vec3, b: Vec3, c: Vec3) => {\n const u: Vec3 = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];\n const v: Vec3 = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];\n const n: Vec3 = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];\n const length = Math.hypot(...n);\n\n // A degenerate face (two points at the apex) is left out\n if (length === 0) return;\n positions.push(...a, ...b, ...c);\n [0, 1, 2].forEach(() => {\n normals.push(n[0] / length, n[1] / length, n[2] / length);\n });\n };\n\n rings.slice(1).forEach((ring, i) => {\n const below = rings[i] ?? ring;\n\n Array.from({ length: sides }, (_, k) => k).forEach((k) => {\n const [a, b] = [at(k, below), at(k + 1, below)];\n const [c, d] = [at(k, ring), at(k + 1, ring)];\n\n // Counter-clockwise seen from outside\n face(a, c, b);\n face(b, c, d);\n });\n });\n // The bottom closed: seen from below\n const base = rings[0];\n\n if (base && base[1] > 0) {\n Array.from({ length: sides }, (_, k) => k).forEach((k) => {\n face([0, base[0], 0], at(k, base), at(k + 1, base));\n });\n }\n\n return { positions, normals };\n};\n\n/** Parts flat-shaded in their colors as a glTF binary: one mesh of a primitive each, its front +Z\n * (`ModelInstance.heading` turns it), standing on its origin */\nexport const glb = (\n parts: { positions: number[]; normals: number[] }[],\n colors: TreeColors[keyof TreeColors][],\n): Uint8Array<ArrayBuffer> => {\n // The buffer: each part's positions then normals, 4-byte floats\n const floats = parts.flatMap((p) => [...p.positions, ...p.normals]);\n const bin = new Float32Array(floats);\n const views = parts.flatMap((p, i) => {\n const before = parts.slice(0, i).reduce((n, q) => n + (q.positions.length + q.normals.length) * 4, 0);\n\n return [\n { buffer: 0, byteOffset: before, byteLength: p.positions.length * 4, target: 34962 },\n { buffer: 0, byteOffset: before + p.positions.length * 4, byteLength: p.normals.length * 4, target: 34962 },\n ];\n });\n const accessors = parts.flatMap((p, i) => [\n { bufferView: i * 2, componentType: 5126, count: p.positions.length / 3, type: 'VEC3', ...bounds(p.positions) },\n { bufferView: i * 2 + 1, componentType: 5126, count: p.normals.length / 3, type: 'VEC3' },\n ]);\n const gltf = {\n asset: { version: '2.0', generator: 'isard' },\n scene: 0,\n scenes: [{ nodes: [0] }],\n nodes: [{ mesh: 0 }],\n meshes: [\n {\n primitives: parts.map((_, i) => ({ attributes: { POSITION: i * 2, NORMAL: i * 2 + 1 }, material: i })),\n },\n ],\n materials: colors.map((color) => ({\n pbrMetallicRoughness: { baseColorFactor: color, metallicFactor: 0, roughnessFactor: 1 },\n })),\n accessors,\n bufferViews: views,\n buffers: [{ byteLength: bin.byteLength }],\n };\n return glbOf(gltf, new Uint8Array(bin.buffer));\n};\n\n/**\n * A broadleaved tree as a glTF binary, about 10 metres high: a trunk and a rounded crown in `colors`; `far`: the\n * same simplified for far away, a few faces (some 30 triangles instead of 100)\n */\nexport const treeModel = (colors: Partial<TreeColors> = {}, far = false): Uint8Array<ArrayBuffer> => {\n const { trunk, crown } = { ...DEFAULT_COLORS, ...colors };\n\n if (far) {\n const stem = revolve(\n [\n [0, 0.3],\n [3, 0.22],\n ],\n FAR_TRUNK_SIDES,\n );\n const top = revolve(\n [\n [2.4, 0.8],\n [5.6, 2.9],\n [10.2, 0],\n ],\n FAR_SIDES,\n );\n\n return glb([stem, top], [trunk, crown]);\n }\n\n const parts = [\n revolve([\n [0, 0.28],\n [3.2, 0.2],\n ]),\n revolve([\n [2.4, 0.6],\n [3.6, 2.4],\n [5.6, 2.9],\n [7.8, 2.3],\n [9.4, 1.1],\n [10.2, 0],\n ]),\n ];\n\n return glb(parts, [trunk, crown]);\n};\n\n/** A cone of the conifers' crown: from `base` metres up, `radius` wide, to its point at `top` */\nconst cone = (base: number, radius: number, top: number) =>\n revolve([\n [base, radius],\n [top, 0],\n ]);\n\n/**\n * A conifer as a glTF binary, about 11 metres high: a trunk and three cones one over the other in `colors`; `far`: one\n * pyramid on a trunk of three faces for far away (some 17 triangles instead of 63)\n */\nexport const coniferModel = (colors: Partial<TreeColors> = {}, far = false): Uint8Array<ArrayBuffer> => {\n const { trunk, conifer } = { ...DEFAULT_COLORS, ...colors };\n\n if (far) {\n const stem = revolve(\n [\n [0, 0.24],\n [2, 0.18],\n ],\n FAR_TRUNK_SIDES,\n );\n const top = revolve(\n [\n [1.4, 2.3],\n [11, 0],\n ],\n FAR_SIDES,\n );\n\n return glb([stem, top], [trunk, conifer]);\n }\n const tiers = [cone(1.4, 2.4, 5.4), cone(3.6, 1.9, 8), cone(6, 1.3, 11)];\n const crown = {\n positions: tiers.flatMap((t) => t.positions),\n normals: tiers.flatMap((t) => t.normals),\n };\n const stem = revolve([\n [0, 0.24],\n [2, 0.18],\n ]);\n\n return glb([stem, crown], [trunk, conifer]);\n};\n\n/** Whether a style layer is OpenMapTiles' grass (the lawns of parks and gardens among it) */\nconst isGrass = (layer: StyleLayer): boolean => layer['source-layer'] === 'landcover' && /grass/i.test(layer.id);\n\n/**\n * Whether trees grow on a style layer by default: the woods and forests of the style's fills (OpenMapTiles'\n * `landcover` wood, PLAN IGN's forests) and the grass of its parks and gardens; not the wooded relief of PLAN IGN,\n * which repeats its forests, nor OpenMapTiles' `park` layer (protected areas and historic sites: a river's banks\n * among them)\n */\nexport const isWoodland = (layer: StyleLayer): boolean =>\n layer.type === 'fill' &&\n layer['source-layer'] !== 'oro_relief' &&\n (/wood|forest|for[eê]t/i.test(layer.id) || isGrass(layer));\n\n/** Default spacing of the trees of a layer (metres): close in woods and forests, apart on grass */\nexport const treeSpacing = (layer: StyleLayer): number => (isGrass(layer) ? 25 : 9);\n\n/**\n * The share of conifers in a wood from its properties: OpenStreetMap's `leaf_type` (needleleaved, broadleaved,\n * mixed), PLAN IGN's `nature` (« conifères », « feuillus », « mixte »); without them, OpenMapTiles' forests a third\n * conifers and its other woods some, the grass of parks none\n */\nexport const coniferShare = (properties: Record<string, Value>): number => {\n const leaf = properties.leaf_type;\n const nature = typeof properties.nature === 'string' ? properties.nature : '';\n\n if (leaf === 'needleleaved' || /conif/i.test(nature)) return 1;\n if (leaf === 'broadleaved' || /feuillu/i.test(nature)) return 0;\n if (leaf === 'mixed' || /mixte/i.test(nature)) return 0.5;\n if (properties.class === 'wood') return properties.subclass === 'forest' ? 0.35 : 0.15;\n\n return 0;\n};\n"]}
|
|
@@ -70,10 +70,15 @@ export interface LabelCandidate {
|
|
|
70
70
|
lat: number;
|
|
71
71
|
/** On a line: the direction there (degrees of longitude and latitude) */
|
|
72
72
|
along?: [number, number];
|
|
73
|
+
/** A text along a line: the line around it (longitudes and latitudes interleaved), as long before it as after it,
|
|
74
|
+
* for the text to follow its bends */
|
|
75
|
+
path?: number[];
|
|
73
76
|
/** Its text runs along the line (`symbol-placement: line`, `text-rotation-alignment` not `viewport`) */
|
|
74
77
|
textAlong?: boolean;
|
|
75
78
|
textOptional?: boolean;
|
|
76
79
|
icon?: CandidateIcon;
|
|
80
|
+
/** Metres over the ground: a point in a building of the style's, on its roof */
|
|
81
|
+
height?: number;
|
|
77
82
|
font: string;
|
|
78
83
|
size: Json;
|
|
79
84
|
color: string;
|
|
@@ -100,10 +105,11 @@ export declare const css: ([r, g, b, a]: [number, number, number, number]) => st
|
|
|
100
105
|
export declare const isExpression: (e: unknown) => e is Json[];
|
|
101
106
|
export declare const evaluate: (e: Json, ctx: Context) => unknown;
|
|
102
107
|
/** The kind of geometry a style layer is drawn with as vectors (`vectors()`: backgrounds as fills, extrusions raised
|
|
103
|
-
* into blocks); undefined for the others (symbols,
|
|
104
|
-
|
|
105
|
-
export declare const vectorKind: (layer: StyleLayer) => "fill" | "line" | "extrusion" | undefined;
|
|
108
|
+
* into blocks, circles); undefined for the others (symbols, rasters) */
|
|
109
|
+
export declare const vectorKind: (layer: StyleLayer) => "fill" | "line" | "extrusion" | "circle" | undefined;
|
|
106
110
|
export declare const filter: (f: Json | undefined, ctx: Context) => boolean;
|
|
111
|
+
/** Whether an expression reads the zoom (a filter that does holds at some zooms only) */
|
|
112
|
+
export declare const usesZoom: (e: Json | undefined) => boolean;
|
|
107
113
|
/** Whether a value depends on the feature (else only on the zoom, evaluated once per tile) */
|
|
108
114
|
export declare const isFeatureDependent: (e: Json | undefined) => boolean;
|
|
109
115
|
/** A `{token}` text field (or an expression) to the text of a feature */
|