itowns 2.44.3-next.32 → 2.44.3-next.34

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.
@@ -16,14 +16,17 @@ function getUintArrayConstructor(highestValue) {
16
16
  }
17
17
  return picked;
18
18
  }
19
- function allocateIndexBuffer(nVertex, nSeg, params) {
20
- if (!params.buildIndexAndUv_0) {
21
- return undefined;
22
- }
19
+ function allocateIndexBuffer(nVertex, nSeg, params, cache) {
23
20
  const indexBufferSize = getBufferIndexSize(nSeg, params.disableSkirt);
24
21
  const indexConstructor = getUintArrayConstructor(nVertex);
25
22
  const tileLen = indexBufferSize;
26
23
  const skirtLen = 4 * nSeg;
24
+ if (cache !== undefined) {
25
+ return {
26
+ index: cache,
27
+ skirt: cache.subarray(tileLen, tileLen + skirtLen)
28
+ };
29
+ }
27
30
  const indexBuffer = new ArrayBuffer((
28
31
  // Tile
29
32
  tileLen
@@ -36,11 +39,11 @@ function allocateIndexBuffer(nVertex, nSeg, params) {
36
39
  skirt
37
40
  };
38
41
  }
39
- function allocateBuffers(nVertex, nSeg, builder, params) {
42
+ function allocateBuffers(nVertex, nSeg, builder, params, cache) {
40
43
  const {
41
44
  index,
42
45
  skirt
43
- } = allocateIndexBuffer(nVertex, nSeg, params) ?? {};
46
+ } = allocateIndexBuffer(nVertex, nSeg, params, cache?.index);
44
47
  return {
45
48
  index,
46
49
  skirt,
@@ -62,7 +65,7 @@ function allocateBuffers(nVertex, nSeg, builder, params) {
62
65
  // +-------------------------+
63
66
  // * u = wgs84.u
64
67
  // * v = textureid + v in builder texture
65
- uvs: [params.buildIndexAndUv_0 ? new Float32Array(nVertex * 2) : undefined, builder.computeExtraOffset !== undefined ? new Float32Array(nVertex) : undefined]
68
+ uvs: [cache?.uv ?? new Float32Array(nVertex * 2), builder.computeExtraOffset !== undefined ? new Float32Array(nVertex) : undefined]
66
69
  };
67
70
  }
68
71
  function computeUv0(uv, id, u, v) {
@@ -76,7 +79,7 @@ function initComputeUv1(value) {
76
79
  }
77
80
  /** Compute buffers describing a tile according to a builder and its params. */
78
81
  // TODO: Split this even further into subfunctions
79
- export function computeBuffers(builder, params) {
82
+ export function computeBuffers(builder, params, cache) {
80
83
  // n seg, n+1 vert + <- skirt, n verts per side
81
84
  // <---------------> / |
82
85
  // +---+---+---+---+ |
@@ -98,8 +101,8 @@ export function computeBuffers(builder, params) {
98
101
  if (nTotalVertex > 2 ** 32) {
99
102
  throw new Error('Tile segments count is too big');
100
103
  }
101
- const outBuffers = allocateBuffers(nTotalVertex, nSeg, builder, params);
102
- const computeUvs = [params.buildIndexAndUv_0 ? computeUv0 : () => {}];
104
+ const outBuffers = allocateBuffers(nTotalVertex, nSeg, builder, params, cache);
105
+ const computeUvs = [cache === undefined ? computeUv0 : () => {}];
103
106
  params = builder.prepare(params);
104
107
  for (let y = 0; y <= nSeg; y++) {
105
108
  const v = y / nSeg;
@@ -135,7 +138,7 @@ export function computeBuffers(builder, params) {
135
138
  }
136
139
 
137
140
  // Fill skirt index buffer
138
- if (params.buildIndexAndUv_0 && !params.disableSkirt) {
141
+ if (cache === undefined && !params.disableSkirt) {
139
142
  for (let x = 0; x < nVertex; x++) {
140
143
  // -------->
141
144
  // 0---1---2
@@ -174,7 +177,7 @@ export function computeBuffers(builder, params) {
174
177
  outBuffers.index[id + 1] = vb;
175
178
  outBuffers.index[id + 2] = vc;
176
179
  }
177
- if (params.buildIndexAndUv_0) {
180
+ if (cache === undefined) {
178
181
  for (let y = 0; y < nSeg; y++) {
179
182
  for (let x = 0; x < nSeg; x++) {
180
183
  const v1 = y * nVertex + (x + 1);
@@ -192,11 +195,11 @@ export function computeBuffers(builder, params) {
192
195
  // INFO: The size of the skirt is now a ratio of the size of the tile.
193
196
  // To be perfect it should depend on the real elevation delta but too heavy
194
197
  // to compute
195
- if (params.buildIndexAndUv_0 && !params.disableSkirt) {
198
+ if (!params.disableSkirt) {
196
199
  // We compute the actual size of tile segment to use later for
197
200
  // the skirt.
198
201
  const segmentSize = new THREE.Vector3().fromArray(outBuffers.position).distanceTo(new THREE.Vector3().fromArray(outBuffers.position, 3));
199
- const buildSkirt = {
202
+ const buildSkirt = cache === undefined ? {
200
203
  index: (id, v1, v2, v3, v4) => {
201
204
  bufferizeTri(id, v1, v2, v3);
202
205
  bufferizeTri(id + 3, v1, v3, v4);
@@ -206,6 +209,9 @@ export function computeBuffers(builder, params) {
206
209
  buf[idTo * 2 + 0] = buf[idFrom * 2 + 0];
207
210
  buf[idTo * 2 + 1] = buf[idFrom * 2 + 1];
208
211
  }
212
+ } : {
213
+ index: () => {},
214
+ uv: () => {}
209
215
  };
210
216
 
211
217
  // Alias for readability
@@ -10,7 +10,7 @@ const r = {
10
10
  col: 0,
11
11
  invDiff: 0
12
12
  };
13
- function _rowColfromParent(/** @type {Tile} */tile, /** @type {number} */zoom) {
13
+ function _rowColfromParent(tile, zoom) {
14
14
  const diffLevel = tile.zoom - zoom;
15
15
  const diff = 2 ** diffLevel;
16
16
  r.invDiff = 1 / diff;
@@ -18,17 +18,18 @@ function _rowColfromParent(/** @type {Tile} */tile, /** @type {number} */zoom) {
18
18
  r.col = (tile.col - tile.col % diff) * r.invDiff;
19
19
  return r;
20
20
  }
21
- const _extent = new Extent('EPSG:4326', [0, 0, 0, 0]);
22
- const _extent2 = new Extent('EPSG:4326', [0, 0, 0, 0]);
21
+ const _extent = new Extent('EPSG:4326');
22
+ const _extent2 = new Extent('EPSG:4326');
23
23
  const _c = new Coordinates('EPSG:4326', 0, 0);
24
24
  class Tile {
25
25
  /**
26
- * Tile is a geographical bounding rectangle defined by zoom, row and column.
26
+ * A tile is a geographical bounding rectangle uniquely defined by its zoom,
27
+ * row and column.
27
28
  *
28
- * @param {String} crs projection of limit values.
29
- * @param {number} [zoom=0] zoom value
30
- * @param {number} [row=0] row value
31
- * @param {number} [col=0] column value
29
+ * @param crs - projection of limit values.
30
+ * @param zoom - `zoom` value. Default is 0.
31
+ * @param row - `row` value. Default is 0.
32
+ * @param col - `column` value. Default is 0.
32
33
  */
33
34
  constructor(crs) {
34
35
  let zoom = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
@@ -42,22 +43,21 @@ class Tile {
42
43
  }
43
44
 
44
45
  /**
45
- * Clone this tile
46
- * @return {Tile} cloned tile
46
+ * Returns a new tile with the same bounds and crs as this one.
47
47
  */
48
48
  clone() {
49
49
  return new Tile(this.crs, this.zoom, this.row, this.col);
50
50
  }
51
51
 
52
52
  /**
53
- * Convert tile to the specified extent.
54
- * @param {string} crs the projection of destination.
55
- * @param {Extent} target copy the destination to target.
56
- * @return {Extent}
53
+ * Converts this tile to the specified extent.
54
+ * @param crs - target's projection.
55
+ * @param target - The target to store the projected extent. If this not
56
+ * provided a new extent will be created.
57
57
  */
58
- toExtent(crs, target) {
58
+ toExtent(crs) {
59
+ let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new Extent('EPSG:4326');
59
60
  CRS.isValid(crs);
60
- target = target || new Extent('EPSG:4326', [0, 0, 0, 0]);
61
61
  const {
62
62
  epsg,
63
63
  globalExtent,
@@ -70,16 +70,13 @@ class Tile {
70
70
  target.south = globalExtent.south + _dimensionTile.y * (countTiles.y - this.row - 1);
71
71
  target.north = target.south + _dimensionTile.y;
72
72
  target.crs = epsg;
73
- target.zoom = this.zoom;
74
73
  return crs == epsg ? target : target.as(crs, target);
75
74
  }
76
75
 
77
76
  /**
78
- * Return true if `tile` is inside this tile.
77
+ * Checks whether another tile is inside this tile.
79
78
  *
80
- * @param {Tile} tile the tile to check
81
- *
82
- * @return {boolean}
79
+ * @param extent - the tile to check.
83
80
  */
84
81
  isInside(tile) {
85
82
  if (this.zoom == tile.zoom) {
@@ -87,36 +84,35 @@ class Tile {
87
84
  } else if (this.zoom < tile.zoom) {
88
85
  return false;
89
86
  } else {
90
- _rowColfromParent(this, tile.zoom);
87
+ const r = _rowColfromParent(this, tile.zoom);
91
88
  return r.row == tile.row && r.col == tile.col;
92
89
  }
93
90
  }
94
91
 
95
92
  /**
96
- * Return the translation and scale to transform this tile to input tile.
93
+ * Returns the translation and scale to transform this tile to the input
94
+ * tile.
97
95
  *
98
- * @param {Tile} tile input tile
99
- * @param {THREE.Vector4} target copy the result to target.
100
- * @return {THREE.Vector4} {x: translation on west-east, y: translation on south-north, z: scale on west-east, w: scale on south-north}
96
+ * @param tile - the input tile.
97
+ * @param target - copy the result to target.
101
98
  */
102
99
  offsetToParent(tile) {
103
100
  let target = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new THREE.Vector4();
104
101
  if (this.crs != tile.crs) {
105
102
  throw new Error('unsupported mix');
106
103
  }
107
- _rowColfromParent(this, tile.zoom);
104
+ const r = _rowColfromParent(this, tile.zoom);
108
105
  return target.set(this.col * r.invDiff - r.col, this.row * r.invDiff - r.row, r.invDiff, r.invDiff);
109
106
  }
110
107
 
111
108
  /**
112
- * Return parent tile with input level
109
+ * Returns the parent tile at the given level.
113
110
  *
114
- * @param {number} levelParent level of parent.
115
- * @return {Tile}
111
+ * @param levelParent - the level of the parent tile.
116
112
  */
117
113
  tiledExtentParent(levelParent) {
118
114
  if (levelParent && levelParent < this.zoom) {
119
- _rowColfromParent(this, levelParent);
115
+ const r = _rowColfromParent(this, levelParent);
120
116
  return new Tile(this.crs, levelParent, r.row, r.col);
121
117
  } else {
122
118
  return this;
@@ -124,13 +120,11 @@ class Tile {
124
120
  }
125
121
 
126
122
  /**
127
- * Set zoom, row and column values
128
- *
129
- * @param {number} [zoom=0] zoom value
130
- * @param {number} [row=0] row value
131
- * @param {number} [col=0] column value
123
+ * Sets zoom, row and column values.
132
124
  *
133
- * @return {Tile}
125
+ * @param zoom - zoom value.
126
+ * @param row - row value.
127
+ * @param col - column value.
134
128
  */
135
129
  set() {
136
130
  let zoom = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
@@ -143,9 +137,8 @@ class Tile {
143
137
  }
144
138
 
145
139
  /**
146
- * Copy to this tile to input tile.
147
- * @param {Tile} tile
148
- * @return {Tile} copied extent
140
+ * Copies the passed tile to this tile.
141
+ * @param tile - tile to copy.
149
142
  */
150
143
  copy(tile) {
151
144
  this.crs = tile.crs;
@@ -154,20 +147,13 @@ class Tile {
154
147
 
155
148
  /**
156
149
  * Return values of tile in string, separated by the separator input.
157
- * @param {string} separator
158
- * @return {string}
150
+ * @param separator - string separator
159
151
  */
160
152
  toString() {
161
153
  let separator = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
162
154
  return `${this.zoom}${separator}${this.row}${separator}${this.col}`;
163
155
  }
164
156
  }
165
-
166
- /**
167
- * @param {Extent} e
168
- * @param {string} tms
169
- * @returns {Tile[]}
170
- */
171
157
  export function tiledCovering(e, tms) {
172
158
  if (e.crs == 'EPSG:4326' && tms == 'EPSG:3857') {
173
159
  const WMTS_PM = [];
@@ -179,7 +165,7 @@ export function tiledCovering(e, tms) {
179
165
  } = getInfoTms(tms);
180
166
  extent.clampByExtent(globalExtent);
181
167
  extent.planarDimensions(_dimensionTile);
182
- const zoom = e.zoom + 1 || Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
168
+ const zoom = Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
183
169
  const countTiles = getCountTiles(tms, zoom);
184
170
  const center = extent.center(_c);
185
171
  _tmsCoord.x = center.x - globalExtent.west;
@@ -203,12 +189,14 @@ export function tiledCovering(e, tms) {
203
189
  const center = e.center(_c);
204
190
  e.planarDimensions(_dimensionTile);
205
191
  // Each level has 2^n * 2^n tiles...
206
- // ... so we count how many tiles of the same width as tile we can fit in the layer
192
+ // ... so we count how many tiles of the same width as tile we can fit
193
+ // in the layer
207
194
  // ... 2^zoom = tilecount => zoom = log2(tilecount)
208
195
  const zoom = Math.floor(Math.log2(Math.round(globalDimension.x / (_dimensionTile.x * sTs.x))));
209
196
  const countTiles = getCountTiles(tms, zoom);
210
197
 
211
- // Now that we have computed zoom, we can deduce x and y (or row / column)
198
+ // Now that we have computed zoom, we can deduce x and y (or row /
199
+ // column)
212
200
  _tmsCoord.x = center.x - globalExtent.west;
213
201
  _tmsCoord.y = isInverted ? globalExtent.north - center.y : center.y - globalExtent.south;
214
202
  _tmsCoord.divide(globalDimension).multiply(countTiles).floor();
@@ -13,13 +13,19 @@ globalExtentTMS.set('EPSG:4326', extent4326);
13
13
  const extent3857 = extent4326.as('EPSG:3857');
14
14
  extent3857.clampSouthNorth(extent3857.west, extent3857.east);
15
15
  globalExtentTMS.set('EPSG:3857', extent3857);
16
- schemeTiles.set('default', new THREE.Vector2(1, 1));
17
- schemeTiles.set('EPSG:3857', schemeTiles.get('default'));
16
+ const defaultScheme = new THREE.Vector2(1, 1);
17
+ schemeTiles.set('EPSG:3857', defaultScheme);
18
18
  schemeTiles.set('EPSG:4326', new THREE.Vector2(2, 1));
19
- export function getInfoTms(/** @type {string} */crs) {
19
+
20
+ // TODO: For now we can only have a single TMS grid per proj4 identifier.
21
+ // This causes TMS identifier to be proj4 identifier.
22
+ export function getInfoTms(crs) {
20
23
  const globalExtent = globalExtentTMS.get(crs);
24
+ if (!globalExtent) {
25
+ throw new Error(`The tile matrix set ${crs} is not defined.`);
26
+ }
21
27
  const globalDimension = globalExtent.planarDimensions(_dim);
22
- const sTs = schemeTiles.get(crs) || schemeTiles.get('default');
28
+ const sTs = schemeTiles.get(crs) ?? defaultScheme;
23
29
  // The isInverted parameter is to be set to the correct value, true or false
24
30
  // (default being false) if the computation of the coordinates needs to be
25
31
  // inverted to match the same scheme as OSM, Google Maps or other system.
@@ -35,8 +41,8 @@ export function getInfoTms(/** @type {string} */crs) {
35
41
  isInverted
36
42
  };
37
43
  }
38
- export function getCountTiles(/** @type {string} */crs, /** @type {number} */zoom) {
39
- const sTs = schemeTiles.get(crs) || schemeTiles.get('default');
44
+ export function getCountTiles(crs, zoom) {
45
+ const sTs = schemeTiles.get(crs) || defaultScheme;
40
46
  const count = 2 ** zoom;
41
47
  _countTiles.set(count, count).multiply(sTs);
42
48
  return _countTiles;
@@ -141,24 +141,39 @@ class OGC3DTilesLayer extends GeometryLayer {
141
141
  * @param {String} id - unique layer id.
142
142
  * @param {Object} config - layer specific configuration
143
143
  * @param {OGC3DTilesSource} config.source - data source configuration
144
- * @param {String} [config.pntsMode= PNTS_MODE.COLOR] Point cloud coloring mode (passed to {@link PointsMaterial}).
144
+ * @param {String} [config.pntsMode = PNTS_MODE.COLOR] Point cloud coloring mode (passed to {@link PointsMaterial}).
145
145
  * Only 'COLOR' or 'CLASSIFICATION' are possible. COLOR uses RGB colors of the points,
146
146
  * CLASSIFICATION uses a classification property of the batch table to color points.
147
- * @param {ClassificationScheme} [config.classificationScheme] {@link PointsMaterial} classification scheme
148
- * @param {String} [config.pntsShape= PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
147
+ * @param {ClassificationScheme} [config.classificationScheme = ClassificationScheme.DEFAULT] {@link PointsMaterial} classification scheme
148
+ * @param {String} [config.pntsShape = PNTS_SHAPE.CIRCLE] Point cloud point shape. Only 'CIRCLE' or 'SQUARE' are possible.
149
149
  * (passed to {@link PointsMaterial}).
150
- * @param {String} [config.pntsSizeMode= PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
150
+ * @param {String} [config.pntsSizeMode = PNTS_SIZE_MODE.VALUE] {@link PointsMaterial} Point cloud size mode (passed to {@link PointsMaterial}).
151
151
  * Only 'VALUE' or 'ATTENUATED' are possible. VALUE use constant size, ATTENUATED compute size depending on distance
152
152
  * from point to camera.
153
- * @param {Number} [config.pntsMinAttenuatedSize=3] Minimum scale used by 'ATTENUATED' size mode.
154
- * @param {Number} [config.pntsMaxAttenuatedSize=10] Maximum scale used by 'ATTENUATED' size mode.
153
+ * @param {Number} [config.pntsMinAttenuatedSize = 3] Minimum scale used by 'ATTENUATED' size mode.
154
+ * @param {Number} [config.pntsMaxAttenuatedSize = 10] Maximum scale used by 'ATTENUATED' size mode.
155
155
  */
156
156
  constructor(id, config) {
157
- super(id, new THREE.Group(), {
158
- source: config.source
159
- });
157
+ const {
158
+ pntsMode = PNTS_MODE.COLOR,
159
+ pntsShape = PNTS_SHAPE.CIRCLE,
160
+ classification = ClassificationScheme.DEFAULT,
161
+ pntsSizeMode = PNTS_SIZE_MODE.VALUE,
162
+ pntsMinAttenuatedSize = 3,
163
+ pntsMaxAttenuatedSize = 10,
164
+ ...geometryLayerConfig
165
+ } = config;
166
+ super(id, new THREE.Group(), geometryLayerConfig);
160
167
  this.isOGC3DTilesLayer = true;
161
- this._handlePointsMaterialConfig(config);
168
+ // Store points material config so they can be used later to substitute points tiles material
169
+ // by our own PointsMaterial. These properties should eventually be managed through the Style API
170
+ // (see https://github.com/iTowns/itowns/issues/2336)
171
+ this.pntsMode = pntsMode;
172
+ this.pntsShape = pntsShape;
173
+ this.classification = classification;
174
+ this.pntsSizeMode = pntsSizeMode;
175
+ this.pntsMinAttenuatedSize = pntsMinAttenuatedSize;
176
+ this.pntsMaxAttenuatedSize = pntsMaxAttenuatedSize;
162
177
  this.tilesRenderer = new TilesRenderer(this.source.url);
163
178
  if (config.source.isOGC3DTilesIonSource) {
164
179
  this.tilesRenderer.registerPlugin(new CesiumIonAuthPlugin({
@@ -197,21 +212,6 @@ class OGC3DTilesLayer extends GeometryLayer {
197
212
  }
198
213
  }
199
214
 
200
- /**
201
- * Store points material config so they can be used later to substitute points tiles material by our own PointsMaterial
202
- * These properties should eventually be managed through the Style API (see https://github.com/iTowns/itowns/issues/2336)
203
- * @param {Object} config - points material configuration as passed to the layer constructor.
204
- * @private
205
- */
206
- _handlePointsMaterialConfig(config) {
207
- this.pntsMode = config.pntsMode ?? PNTS_MODE.COLOR;
208
- this.pntsShape = config.pntsShape ?? PNTS_SHAPE.CIRCLE;
209
- this.classification = config.classification ?? ClassificationScheme.DEFAULT;
210
- this.pntsSizeMode = config.pntsSizeMode ?? PNTS_SIZE_MODE.VALUE;
211
- this.pntsMinAttenuatedSize = config.pntsMinAttenuatedSize || 3;
212
- this.pntsMaxAttenuatedSize = config.pntsMaxAttenuatedSize || 10;
213
- }
214
-
215
215
  /**
216
216
  * Sets the lruCache and download and parse queues so they are shared amongst
217
217
  * all tilesets from a same {@link View} view.
@@ -121,7 +121,7 @@ class Source extends InformationsData {
121
121
  this.whenReady = Promise.resolve();
122
122
  this._featuresCaches = {};
123
123
  if (source.extent && !source.extent.isExtent) {
124
- this.extent = new Extent(this.crs, source.extent);
124
+ this.extent = new Extent(this.crs).setFromExtent(source.extent);
125
125
  } else {
126
126
  this.extent = source.extent;
127
127
  }
@@ -1,7 +1,7 @@
1
1
  import Source from "./Source.js";
2
2
  import URLBuilder from "../Provider/URLBuilder.js";
3
3
  import Extent from "../Core/Geographic/Extent.js";
4
- const _extent = new Extent('EPSG:4326', [0, 0, 0, 0]);
4
+ const _extent = new Extent('EPSG:4326');
5
5
 
6
6
  /**
7
7
  * An object defining the source of resources to get from a
@@ -2,7 +2,7 @@ import Source from "./Source.js";
2
2
  import URLBuilder from "../Provider/URLBuilder.js";
3
3
  import Extent from "../Core/Geographic/Extent.js";
4
4
  import * as CRS from "../Core/Geographic/Crs.js";
5
- const _extent = new Extent('EPSG:4326', [0, 0, 0, 0]);
5
+ const _extent = new Extent('EPSG:4326');
6
6
 
7
7
  /**
8
8
  * Proj provides an optional param to define axis order and orientation for a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itowns",
3
- "version": "2.44.3-next.32",
3
+ "version": "2.44.3-next.34",
4
4
  "description": "A JS/WebGL framework for 3D geospatial data visualization",
5
5
  "type": "module",
6
6
  "main": "lib/Main.js",