itowns 2.44.3-next.3 → 2.44.3-next.31

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.
Files changed (95) hide show
  1. package/CODING.md +1 -1
  2. package/CONTRIBUTORS.md +1 -0
  3. package/dist/debug.js +1 -1
  4. package/dist/debug.js.map +1 -1
  5. package/dist/itowns.js +1 -1
  6. package/dist/itowns.js.LICENSE.txt +0 -2
  7. package/dist/itowns.js.map +1 -1
  8. package/dist/itowns_widgets.js +1 -1
  9. package/dist/itowns_widgets.js.map +1 -1
  10. package/examples/3dtiles_loader.html +109 -45
  11. package/examples/config.json +3 -10
  12. package/examples/entwine_3d_loader.html +3 -1
  13. package/examples/entwine_simple_loader.html +1 -1
  14. package/examples/images/itowns_logo.svg +123 -0
  15. package/examples/js/plugins/COGParser.js +1 -1
  16. package/examples/jsm/OGC3DTilesHelper.js +1 -1
  17. package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
  18. package/examples/source_file_geojson_3d.html +0 -1
  19. package/examples/source_file_kml_raster_usgs.html +0 -1
  20. package/examples/source_stream_wfs_raster.html +0 -7
  21. package/examples/vector_tile_mapbox_raster.html +91 -0
  22. package/lib/Controls/GlobeControls.js +45 -28
  23. package/lib/Controls/StateControl.js +5 -2
  24. package/lib/Converter/Feature2Mesh.js +10 -4
  25. package/lib/Converter/Feature2Texture.js +6 -1
  26. package/lib/Converter/convertToTile.js +3 -8
  27. package/lib/Converter/textureConverter.js +3 -4
  28. package/lib/Core/Deprecated/Undeprecator.js +0 -1
  29. package/lib/Core/Feature.js +1 -2
  30. package/lib/Core/Geographic/Coordinates.js +143 -132
  31. package/lib/Core/Geographic/Crs.js +140 -145
  32. package/lib/Core/Geographic/Extent.js +72 -267
  33. package/lib/Core/Geographic/GeoidGrid.js +1 -1
  34. package/lib/Core/Math/Ellipsoid.js +62 -21
  35. package/lib/Core/Prefab/Globe/Atmosphere.js +4 -8
  36. package/lib/Core/Prefab/Globe/GlobeLayer.js +22 -15
  37. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +111 -0
  38. package/lib/Core/Prefab/GlobeView.js +2 -7
  39. package/lib/Core/Prefab/Planar/PlanarLayer.js +17 -11
  40. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +43 -43
  41. package/lib/Core/Prefab/TileBuilder.js +27 -32
  42. package/lib/Core/Prefab/computeBufferTileGeometry.js +189 -130
  43. package/lib/Core/Style.js +60 -42
  44. package/lib/Core/Tile/Tile.js +219 -0
  45. package/lib/Core/Tile/TileGrid.js +43 -0
  46. package/lib/Core/TileGeometry.js +112 -28
  47. package/lib/Core/TileMesh.js +3 -3
  48. package/lib/Core/View.js +15 -8
  49. package/lib/Layer/C3DTilesLayer.js +20 -16
  50. package/lib/Layer/ColorLayer.js +35 -9
  51. package/lib/Layer/CopcLayer.js +5 -0
  52. package/lib/Layer/ElevationLayer.js +39 -7
  53. package/lib/Layer/EntwinePointTileLayer.js +12 -5
  54. package/lib/Layer/FeatureGeometryLayer.js +20 -6
  55. package/lib/Layer/GeometryLayer.js +42 -11
  56. package/lib/Layer/LabelLayer.js +45 -27
  57. package/lib/Layer/Layer.js +83 -57
  58. package/lib/Layer/OGC3DTilesLayer.js +81 -30
  59. package/lib/Layer/OrientedImageLayer.js +11 -5
  60. package/lib/Layer/PointCloudLayer.js +74 -30
  61. package/lib/Layer/Potree2Layer.js +7 -2
  62. package/lib/Layer/PotreeLayer.js +8 -3
  63. package/lib/Layer/RasterLayer.js +12 -2
  64. package/lib/Layer/TiledGeometryLayer.js +69 -13
  65. package/lib/Main.js +2 -2
  66. package/lib/Parser/GeoJsonParser.js +1 -1
  67. package/lib/Parser/VectorTileParser.js +42 -29
  68. package/lib/Parser/XbilParser.js +14 -2
  69. package/lib/Provider/Fetcher.js +5 -1
  70. package/lib/Provider/URLBuilder.js +22 -11
  71. package/lib/Renderer/Camera.js +1 -1
  72. package/lib/Renderer/Label2DRenderer.js +9 -7
  73. package/lib/Renderer/OBB.js +11 -13
  74. package/lib/Renderer/PointsMaterial.js +1 -1
  75. package/lib/Renderer/RasterTile.js +1 -2
  76. package/lib/Renderer/SphereHelper.js +0 -6
  77. package/lib/Source/CopcSource.js +13 -2
  78. package/lib/Source/EntwinePointTileSource.js +14 -4
  79. package/lib/Source/FileSource.js +1 -4
  80. package/lib/Source/Source.js +1 -4
  81. package/lib/Source/TMSSource.js +10 -9
  82. package/lib/Source/VectorTilesSource.js +32 -22
  83. package/lib/Source/WFSSource.js +15 -10
  84. package/lib/Source/WMSSource.js +56 -18
  85. package/lib/Source/WMTSSource.js +13 -7
  86. package/lib/Utils/CameraUtils.js +1 -1
  87. package/lib/Utils/gui/C3DTilesStyle.js +2 -3
  88. package/lib/Utils/placeObjectOnGround.js +0 -1
  89. package/package.json +13 -6
  90. package/examples/3dtiles_25d.html +0 -120
  91. package/examples/3dtiles_basic.html +0 -94
  92. package/examples/3dtiles_batch_table.html +0 -86
  93. package/examples/3dtiles_ion.html +0 -126
  94. package/examples/3dtiles_pointcloud.html +0 -95
  95. package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
@@ -3,14 +3,52 @@ export function getBufferIndexSize(segments, noSkirt) {
3
3
  const triangles = segments * segments * 2 + (noSkirt ? 0 : 4 * segments * 2);
4
4
  return triangles * 3;
5
5
  }
6
- export default function computeBuffers(params) {
7
- // Create output buffers.
8
- const outBuffers = {
9
- index: null,
10
- position: null,
11
- normal: null,
12
- // 2 UV set per tile: wgs84 (uv[0]) and pm (uv[1])
13
- // - wgs84: 1 texture per tile because tiles are using wgs84 projection
6
+ function getUintArrayConstructor(highestValue) {
7
+ let picked = null;
8
+ if (highestValue < 2 ** 8) {
9
+ picked = Uint8Array;
10
+ } else if (highestValue < 2 ** 16) {
11
+ picked = Uint16Array;
12
+ } else if (highestValue < 2 ** 32) {
13
+ picked = Uint32Array;
14
+ } else {
15
+ throw new Error('Value is too high');
16
+ }
17
+ return picked;
18
+ }
19
+ function allocateIndexBuffer(nVertex, nSeg, params) {
20
+ if (!params.buildIndexAndUv_0) {
21
+ return undefined;
22
+ }
23
+ const indexBufferSize = getBufferIndexSize(nSeg, params.disableSkirt);
24
+ const indexConstructor = getUintArrayConstructor(nVertex);
25
+ const tileLen = indexBufferSize;
26
+ const skirtLen = 4 * nSeg;
27
+ const indexBuffer = new ArrayBuffer((
28
+ // Tile
29
+ tileLen
30
+ // Skirt
31
+ + (params.disableSkirt ? 0 : skirtLen)) * indexConstructor.BYTES_PER_ELEMENT);
32
+ const index = new indexConstructor(indexBuffer);
33
+ const skirt = !params.disableSkirt ? index.subarray(tileLen, tileLen + skirtLen) : undefined;
34
+ return {
35
+ index,
36
+ skirt
37
+ };
38
+ }
39
+ function allocateBuffers(nVertex, nSeg, builder, params) {
40
+ const {
41
+ index,
42
+ skirt
43
+ } = allocateIndexBuffer(nVertex, nSeg, params) ?? {};
44
+ return {
45
+ index,
46
+ skirt,
47
+ position: new Float32Array(nVertex * 3),
48
+ normal: new Float32Array(nVertex * 3),
49
+ // 2 UV set per tile: wgs84 (uv[0]) and pseudo-mercator (pm, uv[1])
50
+ // - wgs84: 1 texture per tile because tiles are using wgs84
51
+ // projection
14
52
  // - pm: use multiple textures per tile.
15
53
  // +-------------------------+
16
54
  // | |
@@ -24,142 +62,157 @@ export default function computeBuffers(params) {
24
62
  // +-------------------------+
25
63
  // * u = wgs84.u
26
64
  // * v = textureid + v in builder texture
27
- uvs: []
65
+ uvs: [params.buildIndexAndUv_0 ? new Float32Array(nVertex * 2) : undefined, builder.computeExtraOffset !== undefined ? new Float32Array(nVertex) : undefined]
66
+ };
67
+ }
68
+ function computeUv0(uv, id, u, v) {
69
+ uv[id * 2 + 0] = u;
70
+ uv[id * 2 + 1] = v;
71
+ }
72
+ function initComputeUv1(value) {
73
+ return (uv, id) => {
74
+ uv[id] = value;
28
75
  };
29
- const computeUvs = [];
30
- const builder = params.builder;
31
- const nSeg = params.segments;
32
- // segments count :
33
- // Tile : (nSeg + 1) * (nSeg + 1)
34
- // Skirt : 8 * (nSeg - 1)
35
- const nVertex = (nSeg + 1) * (nSeg + 1) + (params.disableSkirt ? 0 : 4 * nSeg);
36
- if (nVertex > 2 ** 32) {
76
+ }
77
+ /** Compute buffers describing a tile according to a builder and its params. */
78
+ // TODO: Split this even further into subfunctions
79
+ export function computeBuffers(builder, params) {
80
+ // n seg, n+1 vert + <- skirt, n verts per side
81
+ // <---------------> / |
82
+ // +---+---+---+---+ |
83
+ // | / | / | / | / | | Vertices:
84
+ // +---+---+---+---+ - + tile = (n + 1)^2
85
+ // | / | / | / | / | | skirt = 4n
86
+ // +---+---+---+---+ - +
87
+ // | / | / | / | / | | Segments:
88
+ // +---+---+---+---+ - + tile = 2 * n * (n + 1) + n^2
89
+ // | / | / | / | / | | skirt = 2n * 4
90
+ // +---+---+---+---+ |
91
+ const nSeg = Math.max(2, params.segments);
92
+ const nVertex = nSeg + 1;
93
+ const nTileVertex = nVertex ** 2;
94
+ const nSkirtVertex = params.disableSkirt ? 0 : 4 * nSeg;
95
+ const nTotalVertex = nTileVertex + nSkirtVertex;
96
+
97
+ // Computer should combust before this happens
98
+ if (nTotalVertex > 2 ** 32) {
37
99
  throw new Error('Tile segments count is too big');
38
100
  }
39
- outBuffers.position = new Float32Array(nVertex * 3);
40
- outBuffers.normal = new Float32Array(nVertex * 3);
41
- const uvCount = params.builder.uvCount;
42
- if (uvCount > 1) {
43
- outBuffers.uvs[1] = new Float32Array(nVertex);
44
- }
45
- computeUvs[0] = () => {};
46
- const bufferIndexSize = getBufferIndexSize(nSeg, params.disableSkirt);
47
- if (params.buildIndexAndUv_0) {
48
- if (nVertex < 2 ** 8) {
49
- outBuffers.index = new Uint8Array(bufferIndexSize);
50
- } else if (nVertex < 2 ** 16) {
51
- outBuffers.index = new Uint16Array(bufferIndexSize);
52
- } else if (nVertex < 2 ** 32) {
53
- outBuffers.index = new Uint32Array(bufferIndexSize);
101
+ const outBuffers = allocateBuffers(nTotalVertex, nSeg, builder, params);
102
+ const computeUvs = [params.buildIndexAndUv_0 ? computeUv0 : () => {}];
103
+ params = builder.prepare(params);
104
+ for (let y = 0; y <= nSeg; y++) {
105
+ const v = y / nSeg;
106
+ params.coordinates.y = builder.vProject(v, params.extent);
107
+ if (builder.computeExtraOffset !== undefined) {
108
+ computeUvs[1] = initComputeUv1(builder.computeExtraOffset(params));
54
109
  }
55
- outBuffers.uvs[0] = new Float32Array(nVertex * 2);
56
- computeUvs[0] = (id, u, v) => {
57
- outBuffers.uvs[0][id * 2 + 0] = u;
58
- outBuffers.uvs[0][id * 2 + 1] = v;
59
- };
60
- }
61
- const widthSegments = Math.max(2, Math.floor(nSeg) || 2);
62
- const heightSegments = Math.max(2, Math.floor(nSeg) || 2);
63
- let idVertex = 0;
64
- const vertices = [];
65
- let skirt = [];
66
- const skirtEnd = [];
67
- builder.prepare(params);
68
- for (let y = 0; y <= heightSegments; y++) {
69
- const verticesRow = [];
70
- const v = y / heightSegments;
71
- builder.vProjecte(v, params);
72
- if (uvCount > 1) {
73
- const u = builder.computeUvs[1](params);
74
- computeUvs[1] = id => {
75
- outBuffers.uvs[1][id] = u;
76
- };
77
- }
78
- for (let x = 0; x <= widthSegments; x++) {
79
- const u = x / widthSegments;
80
- const id_m3 = idVertex * 3;
81
- builder.uProjecte(u, params);
82
- const vertex = builder.vertexPosition(params, params.projected);
83
- const normal = builder.vertexNormal(params);
110
+ for (let x = 0; x <= nSeg; x++) {
111
+ const u = x / nSeg;
112
+ const id_m3 = (y * nVertex + x) * 3;
113
+ params.coordinates.x = builder.uProject(u, params.extent);
114
+ const vertex = builder.vertexPosition(params.coordinates);
115
+ const normal = builder.vertexNormal();
84
116
 
85
117
  // move geometry to center world
86
118
  vertex.sub(params.center);
87
119
 
88
120
  // align normal to z axis
89
- if (params.quatNormalToZ) {
90
- vertex.applyQuaternion(params.quatNormalToZ);
91
- normal.applyQuaternion(params.quatNormalToZ);
121
+ // HACK: this check style is not great
122
+ if ('quatNormalToZ' in params) {
123
+ const quat = params.quatNormalToZ;
124
+ vertex.applyQuaternion(quat);
125
+ normal.applyQuaternion(quat);
92
126
  }
93
127
  vertex.toArray(outBuffers.position, id_m3);
94
128
  normal.toArray(outBuffers.normal, id_m3);
95
- for (const computeUv of computeUvs) {
96
- computeUv(idVertex, u, v);
97
- }
98
- if (!params.disableSkirt) {
99
- if (y !== 0 && y !== heightSegments) {
100
- if (x === widthSegments) {
101
- skirt.push(idVertex);
102
- } else if (x === 0) {
103
- skirtEnd.push(idVertex);
104
- }
129
+ for (const [index, computeUv] of computeUvs.entries()) {
130
+ if (computeUv !== undefined) {
131
+ computeUv(outBuffers.uvs[index], y * nVertex + x, u, v);
105
132
  }
106
133
  }
107
- verticesRow.push(idVertex);
108
- idVertex++;
109
- }
110
- vertices.push(verticesRow);
111
- if (y === 0) {
112
- skirt = skirt.concat(verticesRow);
113
- } else if (y === heightSegments) {
114
- skirt = skirt.concat(verticesRow.slice().reverse());
115
134
  }
116
135
  }
117
- if (!params.disableSkirt) {
118
- skirt = skirt.concat(skirtEnd.reverse());
136
+
137
+ // Fill skirt index buffer
138
+ if (params.buildIndexAndUv_0 && !params.disableSkirt) {
139
+ for (let x = 0; x < nVertex; x++) {
140
+ // -------->
141
+ // 0---1---2
142
+ // | / | / | [0-9] = assign order
143
+ // +---+---+
144
+ // | / | / |
145
+ // +---+---+
146
+ outBuffers.skirt[x] = x;
147
+ // +---+---+
148
+ // | / | / | [0-9] = assign order
149
+ // +---+---x x = skipped for now
150
+ // | / | / |
151
+ // 0---1---2
152
+ // <--------
153
+ outBuffers.skirt[2 * nVertex - 2 + x] = nVertex ** 2 - (x + 1);
154
+ }
155
+ for (let y = 1; y < nVertex - 1; y++) {
156
+ // +---+---s |
157
+ // | / | / | | o = stored vertices
158
+ // +---+---o | s = already stored
159
+ // | / | / | |
160
+ // +---+---s v
161
+ outBuffers.skirt[nVertex - 1 + y] = y * nVertex + (nVertex - 1);
162
+ // ^ s---+---+
163
+ // | | / | / | o = stored vertices
164
+ // | o---+---+ s = already stored
165
+ // | | / | / |
166
+ // | s---+---+
167
+ outBuffers.skirt[3 * nVertex - 3 + y] = nVertex * (nVertex - 1 - y);
168
+ }
119
169
  }
120
- function bufferize(va, vb, vc, idVertex) {
121
- outBuffers.index[idVertex + 0] = va;
122
- outBuffers.index[idVertex + 1] = vb;
123
- outBuffers.index[idVertex + 2] = vc;
124
- return idVertex + 3;
170
+
171
+ /** Copy passed indices at the desired index of the output index buffer. */
172
+ function bufferizeTri(id, va, vb, vc) {
173
+ outBuffers.index[id + 0] = va;
174
+ outBuffers.index[id + 1] = vb;
175
+ outBuffers.index[id + 2] = vc;
125
176
  }
126
- let idVertex2 = 0;
127
177
  if (params.buildIndexAndUv_0) {
128
- for (let y = 0; y < heightSegments; y++) {
129
- for (let x = 0; x < widthSegments; x++) {
130
- const v1 = vertices[y][x + 1];
131
- const v2 = vertices[y][x];
132
- const v3 = vertices[y + 1][x];
133
- const v4 = vertices[y + 1][x + 1];
134
- idVertex2 = bufferize(v4, v2, v1, idVertex2);
135
- idVertex2 = bufferize(v4, v3, v2, idVertex2);
178
+ for (let y = 0; y < nSeg; y++) {
179
+ for (let x = 0; x < nSeg; x++) {
180
+ const v1 = y * nVertex + (x + 1);
181
+ const v2 = y * nVertex + x;
182
+ const v3 = (y + 1) * nVertex + x;
183
+ const v4 = (y + 1) * nVertex + (x + 1);
184
+ const id = (y * nSeg + x) * 6;
185
+ bufferizeTri(id, /**/v4, v2, v1);
186
+ bufferizeTri(id + 3, v4, v3, v2);
136
187
  }
137
188
  }
138
189
  }
139
- const iStart = idVertex;
140
190
 
141
- // TODO: WARNING beware skirt's size influences performance
142
- // The size of the skirt is now a ratio of the size of the tile.
143
- // To be perfect it should depend on the real elevation delta but too heavy to compute
144
- if (!params.disableSkirt) {
145
- // We compute the actual size of tile segment to use later for the skirt.
191
+ // PERF: Beware skirt's size influences performance
192
+ // INFO: The size of the skirt is now a ratio of the size of the tile.
193
+ // To be perfect it should depend on the real elevation delta but too heavy
194
+ // to compute
195
+ if (params.buildIndexAndUv_0 && !params.disableSkirt) {
196
+ // We compute the actual size of tile segment to use later for
197
+ // the skirt.
146
198
  const segmentSize = new THREE.Vector3().fromArray(outBuffers.position).distanceTo(new THREE.Vector3().fromArray(outBuffers.position, 3));
147
- let buildIndexSkirt = function () {};
148
- let buildUVSkirt = function () {};
149
- if (params.buildIndexAndUv_0) {
150
- buildIndexSkirt = function (id, v1, v2, v3, v4) {
151
- id = bufferize(v1, v2, v3, id);
152
- id = bufferize(v1, v3, v4, id);
153
- return id;
154
- };
155
- buildUVSkirt = function (id) {
156
- outBuffers.uvs[0][idVertex * 2 + 0] = outBuffers.uvs[0][id * 2 + 0];
157
- outBuffers.uvs[0][idVertex * 2 + 1] = outBuffers.uvs[0][id * 2 + 1];
158
- };
159
- }
160
- for (let i = 0; i < skirt.length; i++) {
161
- const id = skirt[i];
162
- const id_m3 = idVertex * 3;
199
+ const buildSkirt = {
200
+ index: (id, v1, v2, v3, v4) => {
201
+ bufferizeTri(id, v1, v2, v3);
202
+ bufferizeTri(id + 3, v1, v3, v4);
203
+ return id + 6;
204
+ },
205
+ uv: (buf, idTo, idFrom) => {
206
+ buf[idTo * 2 + 0] = buf[idFrom * 2 + 0];
207
+ buf[idTo * 2 + 1] = buf[idFrom * 2 + 1];
208
+ }
209
+ };
210
+
211
+ // Alias for readability
212
+ const start = nTileVertex;
213
+ for (let i = 0; i < outBuffers.skirt.length; i++) {
214
+ const id = outBuffers.skirt[i];
215
+ const id_m3 = (start + i) * 3;
163
216
  const id2_m3 = id * 3;
164
217
  outBuffers.position[id_m3 + 0] = outBuffers.position[id2_m3 + 0] - outBuffers.normal[id2_m3 + 0] * segmentSize;
165
218
  outBuffers.position[id_m3 + 1] = outBuffers.position[id2_m3 + 1] - outBuffers.normal[id2_m3 + 1] * segmentSize;
@@ -167,17 +220,23 @@ export default function computeBuffers(params) {
167
220
  outBuffers.normal[id_m3 + 0] = outBuffers.normal[id2_m3 + 0];
168
221
  outBuffers.normal[id_m3 + 1] = outBuffers.normal[id2_m3 + 1];
169
222
  outBuffers.normal[id_m3 + 2] = outBuffers.normal[id2_m3 + 2];
170
- buildUVSkirt(id);
171
- if (uvCount > 1) {
172
- outBuffers.uvs[1][idVertex] = outBuffers.uvs[1][id];
223
+ buildSkirt.uv(outBuffers.uvs[0], start + i, id);
224
+ if (outBuffers.uvs[1] !== undefined) {
225
+ outBuffers.uvs[1][start + i] = outBuffers.uvs[1][id];
173
226
  }
174
- const idf = (i + 1) % skirt.length;
175
- const v2 = idVertex;
176
- const v3 = idf === 0 ? iStart : idVertex + 1;
177
- const v4 = skirt[idf];
178
- idVertex2 = buildIndexSkirt(idVertex2, id, v2, v3, v4);
179
- idVertex++;
227
+ const idf = (i + 1) % outBuffers.skirt.length;
228
+ const v2 = start + i;
229
+ const v3 = idf === 0 ? start : start + i + 1;
230
+ const v4 = outBuffers.skirt[idf];
231
+ buildSkirt.index(6 * nSeg ** 2 + i * 6, id, v2, v3, v4);
180
232
  }
181
233
  }
182
- return outBuffers;
234
+
235
+ // Dropping skirt view
236
+ return {
237
+ index: outBuffers.index,
238
+ position: outBuffers.position,
239
+ uvs: outBuffers.uvs,
240
+ normal: outBuffers.normal
241
+ };
183
242
  }
package/lib/Core/Style.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FEATURE_TYPES } from "./Feature.js";
2
2
  import Cache from "./Scheduler/Cache.js";
3
3
  import Fetcher from "../Provider/Fetcher.js";
4
- import * as mapbox from '@mapbox/mapbox-gl-style-spec';
4
+ import * as maplibre from '@maplibre/maplibre-gl-style-spec';
5
5
  import { Color } from 'three';
6
6
  import { deltaE } from "../Renderer/Color.js";
7
7
  import Coordinates from "./Geographic/Coordinates.js";
@@ -73,8 +73,8 @@ function rgba2rgb(orig) {
73
73
  }
74
74
  function readVectorProperty(property, options) {
75
75
  if (property != undefined) {
76
- if (mapbox.expression.isExpression(property)) {
77
- return mapbox.expression.createExpression(property, options).value;
76
+ if (maplibre.expression.isExpression(property)) {
77
+ return maplibre.expression.createExpression(property, options).value;
78
78
  } else {
79
79
  return property;
80
80
  }
@@ -90,18 +90,18 @@ async function loadImage(source) {
90
90
  }
91
91
  return (await promise).image;
92
92
  }
93
- function cropImage(img) {
94
- let cropValues = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
95
- width: img.naturalWidth,
96
- height: img.naturalHeight
97
- };
98
- canvas.width = cropValues.width;
99
- canvas.height = cropValues.height;
93
+ function cropImage(img, cropValues) {
94
+ const x = cropValues.x || 0;
95
+ const y = cropValues.y || 0;
96
+ const width = cropValues.width || img.naturalWidth;
97
+ const height = cropValues.height || img.naturalHeight;
98
+ canvas.width = width;
99
+ canvas.height = height;
100
100
  const ctx = canvas.getContext('2d', {
101
101
  willReadFrequently: true
102
102
  });
103
- ctx.drawImage(img, cropValues.x || 0, cropValues.y || 0, cropValues.width, cropValues.height, 0, 0, cropValues.width, cropValues.height);
104
- return ctx.getImageData(0, 0, cropValues.width, cropValues.height);
103
+ ctx.drawImage(img, x, y, width, height, 0, 0, width, height);
104
+ return ctx.getImageData(0, 0, width, height);
105
105
  }
106
106
  function replaceWhitePxl(imgd, color, id) {
107
107
  if (!color) {
@@ -166,7 +166,7 @@ function defineStyleProperty(style, category, parameter, userValue, defaultValue
166
166
  return readExpression(dataValue, style.context);
167
167
  }
168
168
  if (defaultValue instanceof Function) {
169
- return defaultValue(style.context.properties, style.context);
169
+ return defaultValue(style.context.properties, style.context) ?? defaultValue;
170
170
  }
171
171
  return defaultValue;
172
172
  },
@@ -294,15 +294,12 @@ function _addIcon(icon, domElement, opt) {
294
294
  }
295
295
 
296
296
  /**
297
- * An object that can contain any properties (order, zoom, fill, stroke, point,
297
+ * An object that can contain any properties (zoom, fill, stroke, point,
298
298
  * text or/and icon) and sub properties of a Style.<br/>
299
299
  * Used for the instanciation of a {@link Style}.
300
300
  *
301
301
  * @typedef {Object} StyleOptions
302
302
  *
303
- * @property {Number} [order] - Order of the features that will be associated to
304
- * the style. It can helps sorting and prioritizing features if needed.
305
- *
306
303
  * @property {Object} [zoom] - Level on which to display the feature
307
304
  * @property {Number} [zoom.max] - max level
308
305
  * @property {Number} [zoom.min] - min level
@@ -460,8 +457,6 @@ function _addIcon(icon, domElement, opt) {
460
457
  * The first parameter of functions used to set `Style` properties is always an object containing
461
458
  * the properties of the features displayed with the current `Style` instance.
462
459
  *
463
- * @property {Number} order - Order of the features that will be associated to
464
- * the style. It can helps sorting and prioritizing features if needed.
465
460
  * @property {Object} fill - Polygons and fillings style.
466
461
  * @property {String|Function|THREE.Color} fill.color - Defines the main color of the filling. Can be
467
462
  * any [valid color
@@ -611,14 +606,13 @@ function _addIcon(icon, domElement, opt) {
611
606
  class Style {
612
607
  /**
613
608
  * @param {StyleOptions} [params={}] An object that contain any properties
614
- * (order, zoom, fill, stroke, point, text or/and icon)
609
+ * (zoom, fill, stroke, point, text or/and icon)
615
610
  * and sub properties of a Style ({@link StyleOptions}).
616
611
  */
617
612
  constructor() {
618
613
  let params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
619
614
  this.isStyle = true;
620
615
  this.context = new StyleContext();
621
- this.order = params.order || 0;
622
616
  params.zoom = params.zoom || {};
623
617
  params.fill = params.fill || {};
624
618
  params.stroke = params.stroke || {};
@@ -783,14 +777,12 @@ class Style {
783
777
  * set Style from vector tile layer properties.
784
778
  * @param {Object} layer vector tile layer.
785
779
  * @param {Object} sprites vector tile layer.
786
- * @param {Number} [order=0]
787
780
  * @param {Boolean} [symbolToCircle=false]
788
781
  *
789
782
  * @returns {StyleOptions} containing all properties for itowns.Style
790
783
  */
791
784
  static setFromVectorTileLayer(layer, sprites) {
792
- let order = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
793
- let symbolToCircle = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
785
+ let symbolToCircle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
794
786
  const style = {
795
787
  fill: {},
796
788
  stroke: {},
@@ -800,7 +792,6 @@ class Style {
800
792
  };
801
793
  layer.layout = layer.layout || {};
802
794
  layer.paint = layer.paint || {};
803
- style.order = order;
804
795
  if (layer.type === 'fill') {
805
796
  const {
806
797
  color,
@@ -832,7 +823,8 @@ class Style {
832
823
  style.stroke.color = color;
833
824
  style.stroke.opacity = opacity;
834
825
  style.stroke.width = 1.0;
835
- style.stroke.dasharray = [];
826
+ } else {
827
+ style.stroke.width = 0.0;
836
828
  }
837
829
  } else if (layer.type === 'line') {
838
830
  const prepare = readVectorProperty(layer.paint['line-color'], {
@@ -858,6 +850,8 @@ class Style {
858
850
  style.point.opacity = opacity;
859
851
  style.point.radius = readVectorProperty(layer.paint['circle-radius']);
860
852
  } else if (layer.type === 'symbol') {
853
+ // if symbol we shouldn't draw stroke but defaut value is 1.
854
+ style.stroke.width = 0.0;
861
855
  // overlapping order
862
856
  style.text.zOrder = readVectorProperty(layer.layout['symbol-z-order']);
863
857
  if (style.text.zOrder == 'auto') {
@@ -878,7 +872,7 @@ class Style {
878
872
 
879
873
  // content
880
874
  style.text.field = readVectorProperty(layer.layout['text-field']);
881
- style.text.wrap = readVectorProperty(layer.layout['text-max-width']);
875
+ style.text.wrap = readVectorProperty(layer.layout['text-max-width']); // Units ems
882
876
  style.text.spacing = readVectorProperty(layer.layout['text-letter-spacing']);
883
877
  style.text.transform = readVectorProperty(layer.layout['text-transform']);
884
878
  style.text.justify = readVectorProperty(layer.layout['text-justify']);
@@ -905,6 +899,12 @@ class Style {
905
899
  // additional icon
906
900
  const iconImg = readVectorProperty(layer.layout['icon-image']);
907
901
  if (iconImg) {
902
+ const cropValueDefault = {
903
+ x: 0,
904
+ y: 0,
905
+ width: 1,
906
+ height: 1
907
+ };
908
908
  try {
909
909
  style.icon.id = iconImg;
910
910
  if (iconImg.stops) {
@@ -917,9 +917,15 @@ class Style {
917
917
  if (stop[1].includes('{')) {
918
918
  cropValues = function (p) {
919
919
  const id = stop[1].replace(/\{(.+?)\}/g, (a, b) => p[b] || '').trim();
920
- cropValues = sprites[id];
920
+ if (cropValues === undefined) {
921
+ // const warning = `WARNING: "${id}" not found in sprite file`;
922
+ sprites[id] = cropValueDefault; // or return cropValueDefault;
923
+ }
921
924
  return sprites[id];
922
925
  };
926
+ } else if (cropValues === undefined) {
927
+ // const warning = `WARNING: "${stop[1]}" not found in sprite file`;
928
+ cropValues = cropValueDefault;
923
929
  }
924
930
  return [stop[0], cropValues];
925
931
  })
@@ -927,24 +933,33 @@ class Style {
927
933
  style.icon.cropValues = iconCropValue;
928
934
  } else {
929
935
  style.icon.cropValues = sprites[iconImg];
930
- if (iconImg[0].includes('{')) {
936
+ if (iconImg.includes('{')) {
931
937
  style.icon.cropValues = function (p) {
932
938
  const id = iconImg.replace(/\{(.+?)\}/g, (a, b) => p[b] || '').trim();
933
- style.icon.cropValues = sprites[id];
939
+ if (sprites[id] === undefined) {
940
+ // const warning = `WARNING: "${id}" not found in sprite file`;
941
+ sprites[id] = cropValueDefault; // or return cropValueDefault;
942
+ }
934
943
  return sprites[id];
935
944
  };
945
+ } else if (sprites[iconImg] === undefined) {
946
+ // const warning = `WARNING: "${iconImg}" not found in sprite file`;
947
+ style.icon.cropValues = cropValueDefault;
936
948
  }
937
949
  }
938
950
  style.icon.source = sprites.source;
939
- style.icon.size = readVectorProperty(layer.layout['icon-size']) || 1;
951
+ style.icon.size = readVectorProperty(layer.layout['icon-size']) ?? 1;
940
952
  const {
941
953
  color,
942
954
  opacity
943
955
  } = rgba2rgb(readVectorProperty(layer.paint['icon-color'], {
944
956
  type: 'color'
945
957
  }));
946
- style.icon.color = color;
947
- style.icon.opacity = readVectorProperty(layer.paint['icon-opacity']) || opacity !== undefined && opacity;
958
+ // https://docs.mapbox.com/style-spec/reference/layers/#paint-symbol-icon-color
959
+ if (iconImg.sdf) {
960
+ style.icon.color = color;
961
+ }
962
+ style.icon.opacity = readVectorProperty(layer.paint['icon-opacity']) ?? (opacity !== undefined && opacity);
948
963
  } catch (err) {
949
964
  err.message = `VTlayer '${layer.id}': argument sprites must not be null when using layer.layout['icon-image']`;
950
965
  throw err;
@@ -970,28 +985,27 @@ class Style {
970
985
  * @param {Boolean} canBeFilled - true if feature.type == FEATURE_TYPES.POLYGON.
971
986
  */
972
987
  applyToCanvasPolygon(txtrCtx, polygon, invCtxScale, canBeFilled) {
973
- const context = this.context;
974
988
  // draw line or edge of polygon
975
- if (this.stroke) {
989
+ if (this.stroke.width > 0) {
976
990
  // TO DO add possibility of using a pattern (https://github.com/iTowns/itowns/issues/2210)
977
- this._applyStrokeToPolygon(txtrCtx, invCtxScale, polygon, context);
991
+ this._applyStrokeToPolygon(txtrCtx, invCtxScale, polygon);
978
992
  }
979
993
 
980
994
  // fill inside of polygon
981
- if (canBeFilled && this.fill) {
995
+ if (canBeFilled && (this.fill.pattern || this.fill.color)) {
982
996
  // canBeFilled can be move to StyleContext in the later PR
983
- this._applyFillToPolygon(txtrCtx, invCtxScale, polygon, context);
997
+ this._applyFillToPolygon(txtrCtx, invCtxScale, polygon);
984
998
  }
985
999
  }
986
1000
  _applyStrokeToPolygon(txtrCtx, invCtxScale, polygon) {
987
1001
  if (txtrCtx.strokeStyle !== this.stroke.color) {
988
1002
  txtrCtx.strokeStyle = this.stroke.color;
989
1003
  }
990
- const width = (this.stroke.width || 2.0) * invCtxScale;
1004
+ const width = this.stroke.width * invCtxScale;
991
1005
  if (txtrCtx.lineWidth !== width) {
992
1006
  txtrCtx.lineWidth = width;
993
1007
  }
994
- const alpha = this.stroke.opacity == undefined ? 1.0 : this.stroke.opacity;
1008
+ const alpha = this.stroke.opacity;
995
1009
  if (alpha !== txtrCtx.globalAlpha && typeof alpha == 'number') {
996
1010
  txtrCtx.globalAlpha = alpha;
997
1011
  }
@@ -1006,7 +1020,9 @@ class Style {
1006
1020
  // need doc for the txtrCtx.fillStyle.src that seems to always be undefined
1007
1021
  if (this.fill.pattern) {
1008
1022
  let img = this.fill.pattern;
1009
- const cropValues = this.fill.pattern.cropValues;
1023
+ const cropValues = {
1024
+ ...this.fill.pattern.cropValues
1025
+ };
1010
1026
  if (this.fill.pattern.source) {
1011
1027
  img = await loadImage(this.fill.pattern.source);
1012
1028
  }
@@ -1074,7 +1090,9 @@ class Style {
1074
1090
  if (!this.icon.cropValues && !this.icon.color) {
1075
1091
  icon.src = this.icon.source;
1076
1092
  } else {
1077
- const cropValues = this.icon.cropValues;
1093
+ const cropValues = {
1094
+ ...this.icon.cropValues
1095
+ };
1078
1096
  const color = this.icon.color;
1079
1097
  const id = this.icon.id || this.icon.source;
1080
1098
  const img = await loadImage(this.icon.source);