itowns 2.44.3-next.35 → 2.44.3-next.36

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.
@@ -42,7 +42,6 @@ function updateElements(context, geometryLayer, elements) {
42
42
  for (const attachedLayer of geometryLayer.attachedLayers) {
43
43
  if (attachedLayer.ready) {
44
44
  attachedLayer.update(context, attachedLayer, sub.element, sub.parent);
45
- attachedLayer.cache.flush();
46
45
  }
47
46
  }
48
47
  } else if (sub.elements) {
@@ -56,7 +55,6 @@ function updateElements(context, geometryLayer, elements) {
56
55
  for (const attachedLayer of geometryLayer.attachedLayers) {
57
56
  if (attachedLayer.ready) {
58
57
  attachedLayer.update(context, attachedLayer, sub.elements[i], sub.parent);
59
- attachedLayer.cache.flush();
60
58
  }
61
59
  }
62
60
  }
@@ -140,7 +138,7 @@ class MainLoop extends EventDispatcher {
140
138
  }
141
139
 
142
140
  // Clear the cache of expired resources
143
- geometryLayer.cache.flush();
141
+
144
142
  view.execFrameRequesters(MAIN_LOOP_EVENTS.AFTER_LAYER_UPDATE, dt, this.#updateLoopRestarted, geometryLayer);
145
143
  }
146
144
  }
@@ -1,10 +1,12 @@
1
1
  import * as THREE from 'three';
2
2
  import { TileGeometry } from "../TileGeometry.js";
3
- import Cache from "../Scheduler/Cache.js";
3
+ import { LRUCache } from 'lru-cache';
4
4
  import { computeBuffers } from "./computeBufferTileGeometry.js";
5
5
  import OBB from "../../Renderer/OBB.js";
6
6
  const cacheBuffer = new Map();
7
- const cacheTile = new Cache();
7
+ const cacheTile = new LRUCache({
8
+ max: 500
9
+ });
8
10
 
9
11
  /**
10
12
  * Reference to a tile's extent with rigid transformations.
@@ -19,7 +21,8 @@ export function newTileGeometry(builder, params) {
19
21
  } = builder.computeShareableExtent(params.extent);
20
22
  const south = shareableExtent.south.toFixed(6);
21
23
  const bufferKey = `${builder.crs}_${params.disableSkirt ? 0 : 1}_${params.segments}`;
22
- let promiseGeometry = cacheTile.get(south, params.level, bufferKey);
24
+ const key = `s${south}l${params.level}bK${bufferKey}`;
25
+ let promiseGeometry = cacheTile.get(key);
23
26
 
24
27
  // build geometry if doesn't exist
25
28
  if (!promiseGeometry) {
@@ -27,7 +30,7 @@ export function newTileGeometry(builder, params) {
27
30
  promiseGeometry = new Promise(r => {
28
31
  resolve = r;
29
32
  });
30
- cacheTile.set(promiseGeometry, south, params.level, bufferKey);
33
+ cacheTile.set(key, promiseGeometry);
31
34
  params.extent = shareableExtent;
32
35
  params.center = builder.center(params.extent).clone();
33
36
  // Read previously cached values (index and uv.wgs84 only
@@ -63,7 +66,7 @@ export function newTileGeometry(builder, params) {
63
66
  };
64
67
  const geometry = new TileGeometry(builder, params, gpuBuffers);
65
68
  geometry.OBB = new OBB(geometry.boundingBox.min, geometry.boundingBox.max);
66
- geometry.initRefCount(cacheTile, [south, params.level, bufferKey]);
69
+ geometry.initRefCount(cacheTile, key);
67
70
  resolve(geometry);
68
71
  return Promise.resolve({
69
72
  geometry,
@@ -1,5 +1,3 @@
1
- let entry;
2
-
3
1
  /**
4
2
  * Cache policies for flushing. Those policies can be used when something is
5
3
  * [set]{@link Cache.set} into the Cache, as the lifetime property.
@@ -16,241 +14,4 @@ export const CACHE_POLICIES = {
16
14
  INFINITE: Infinity,
17
15
  TEXTURE: 900000,
18
16
  GEOMETRY: 900000
19
- };
20
-
21
- /**
22
- * This is a copy of the Map object, except that it also store a value for last
23
- * time used. This value is used for cache expiration mechanism.
24
- *
25
- * @example
26
- * import Cache, { CACHE_POLICIES } from 'Core/Scheduler/Cache';
27
- *
28
- * const cache = new Cache(CACHE_POLICIES.TEXTURE)
29
- * cache.set({ bar: 1 }, 'foo');
30
- * cache.set({ bar: 32 }, 'foo', 'toto');
31
- *
32
- * cache.get('foo');
33
- *
34
- * cache.delete('foo');
35
- *
36
- * cache.clear();
37
- *
38
- * cache.flush();
39
- */
40
- class Cache {
41
- /**
42
- * @param {number} [lifetime=CACHE_POLICIES.INFINITE] The cache expiration time for all values.
43
- */
44
- constructor() {
45
- let lifetime = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : CACHE_POLICIES.INFINITE;
46
- this.lifeTime = lifetime;
47
- this.lastTimeFlush = Date.now();
48
- this.data = new Map();
49
- }
50
-
51
- /**
52
- * Returns the entry related to the specified key, content in array, from the cache.
53
- * The array contents one to three key.
54
- * The last time used property of the entry is updated to extend the longevity of the
55
- * entry.
56
- *
57
- * @param {string[]|number[]} keyArray key array ([key0, key1, key3])
58
- *
59
- * @return {Object}
60
- */
61
-
62
- getByArray(keyArray) {
63
- return this.get(keyArray[0], keyArray[1], keyArray[2]);
64
- }
65
-
66
- /**
67
- * Adds or updates an entry with specified keys array ([key0, key1, key3]).
68
- * Caution: it overrides any existing entry already set at this/those key/s.
69
- *
70
- * @param {Object} value to add in cache
71
- * @param {string[]|number[]} keyArray key array ([key0, key1, key3])
72
- *
73
- * @return {Object} the added value
74
- */
75
- setByArray(value, keyArray) {
76
- return this.set(value, keyArray[0], keyArray[1], keyArray[2]);
77
- }
78
-
79
- /**
80
- * Returns the entry related to the specified key from the cache. The last
81
- * time used property of the entry is updated to extend the longevity of the
82
- * entry.
83
- *
84
- * @param {string|number} key1
85
- * @param {string|number} [key2]
86
- * @param {string|number} [key3]
87
- *
88
- * @return {Object}
89
- */
90
- get(key1, key2, key3) {
91
- const entry_1 = this.data.get(key1);
92
- if (entry_1 == undefined) {
93
- return;
94
- }
95
- if (entry_1.lastTimeUsed != undefined) {
96
- entry = entry_1;
97
- } else {
98
- const entry_2 = entry_1.get(key2);
99
- if (entry_2 == undefined) {
100
- return;
101
- }
102
- if (entry_2.lastTimeUsed != undefined) {
103
- entry = entry_2;
104
- } else {
105
- const entry_3 = entry_2.get(key3);
106
- if (entry_3 == undefined) {
107
- return;
108
- }
109
- entry = entry_3;
110
- }
111
- }
112
- if (entry.value) {
113
- entry.lastTimeUsed = Date.now();
114
- return entry.value;
115
- }
116
- }
117
-
118
- /**
119
- * Adds or updates an entry with specified keys (up to 3).
120
- * Caution: it overrides any existing entry already set at this/those key/s.
121
- *
122
- *
123
- * @param {Object} value to add in cache
124
- * @param {string|number} key1
125
- * @param {string|number} [key2]
126
- * @param {string|number} [key3]
127
- *
128
- * @return {Object} the added value
129
- */
130
- set(value, key1, key2, key3) {
131
- entry = {
132
- value,
133
- lastTimeUsed: Date.now()
134
- };
135
- if (key2 == undefined) {
136
- this.data.set(key1, entry);
137
- return value;
138
- }
139
- if (!this.data.get(key1)) {
140
- this.data.set(key1, new Map());
141
- }
142
- const entry_map = this.data.get(key1);
143
- if (key3 == undefined) {
144
- entry_map.set(key2, entry);
145
- return value;
146
- }
147
- if (!entry_map.get(key2)) {
148
- entry_map.set(key2, new Map());
149
- }
150
- entry_map.get(key2).set(key3, entry);
151
- return value;
152
- }
153
-
154
- /**
155
- * Deletes the specified entry from the cache.
156
- *
157
- * @param {string|number} key1
158
- * @param {string|number} [key2]
159
- * @param {string|number} [key3]
160
- */
161
- delete(key1, key2, key3) {
162
- const entry_1 = this.data.get(key1);
163
- if (entry_1 === undefined) {
164
- return;
165
- }
166
- if (entry_1.lastTimeUsed != undefined) {
167
- delete this.data.get(key1);
168
- this.data.delete(key1);
169
- } else {
170
- const entry_2 = entry_1.get(key2);
171
- if (entry_2 === undefined) {
172
- return;
173
- }
174
- if (entry_2.lastTimeUsed != undefined) {
175
- delete entry_1.get(key2);
176
- entry_1.delete(key2);
177
- if (entry_1.size == 0) {
178
- this.data.delete(key1);
179
- }
180
- } else {
181
- const entry_3 = entry_2.get(key3);
182
- if (entry_3 === undefined) {
183
- return;
184
- }
185
- delete entry_2.get(key3);
186
- entry_2.delete(key3);
187
- if (entry_2.size == 0) {
188
- entry_1.delete(key2);
189
- if (entry_1.size == 0) {
190
- this.data.delete(key1);
191
- }
192
- }
193
- }
194
- }
195
- }
196
-
197
- /**
198
- * Removes all entries of the cache.
199
- *
200
- */
201
- clear() {
202
- this.data.clear();
203
- }
204
-
205
- /**
206
- * Flush the cache: entries that have been present for too long since the
207
- * last time they were used, are removed from the cache. By default, the
208
- * time is the current time, but the interval can be reduced by doing
209
- * something like `Cache.flush(Date.now() - reductionTime)`. If you want to
210
- * clear the whole cache, use {@link Cache.clear} instead.
211
- *
212
- * @param {number} [time=Date.now()]
213
- */
214
- flush() {
215
- let time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Date.now();
216
- if (this.lifeTime == CACHE_POLICIES.INFINITE || this.lifeTime > time - this.lastTimeFlush || !this.data.size) {
217
- return;
218
- }
219
- this.lastTimeFlush = Infinity;
220
- this.data.forEach((v1, i) => {
221
- if (this.lifeTime < time - v1.lastTimeUsed) {
222
- delete this.data.get(i);
223
- this.data.delete(i);
224
- } else {
225
- v1.forEach((v2, j) => {
226
- if (this.lifeTime < time - v2.lastTimeUsed) {
227
- delete v1.get(j);
228
- v1.delete(j);
229
- } else {
230
- v2.forEach((v3, k) => {
231
- if (this.lifeTime < time - v3.lastTimeUsed) {
232
- delete v2.get(k);
233
- v2.delete(k);
234
- } else {
235
- // Work for the moment because all flushed caches have 3 key!
236
- this.lastTimeFlush = Math.min(this.lastTimeFlush, v3.lastTimeUsed);
237
- }
238
- });
239
- if (!v2.size) {
240
- delete v1.get(j);
241
- v1.delete(j);
242
- }
243
- }
244
- });
245
- if (!v1.size) {
246
- delete this.data.get(i);
247
- this.data.delete(i);
248
- }
249
- }
250
- });
251
- if (this.data.size == 0) {
252
- this.lastTimeFlush = Date.now();
253
- }
254
- }
255
- }
256
- export default Cache;
17
+ };
package/lib/Core/Style.js CHANGED
@@ -1,11 +1,13 @@
1
- import Cache from "./Scheduler/Cache.js";
1
+ import { LRUCache } from 'lru-cache';
2
2
  import Fetcher from "../Provider/Fetcher.js";
3
3
  import { Color } from 'three';
4
4
  import { deltaE } from "../Renderer/Color.js";
5
5
  import Coordinates from "./Geographic/Coordinates.js";
6
6
  /* babel-plugin-inline-import './StyleChunk/itowns_stroke_single_before.css' */
7
7
  const itowns_stroke_single_before = ".itowns-stroke-single:before {\n display: var(--text_stroke_display);\n content: attr(data-before);\n opacity: 1;\n position: absolute;\n -webkit-text-stroke-width: var(--text_stroke_width);\n -webkit-text-stroke-color: var(--text_stroke_color);\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: -1;\n white-space: inherit;\n overflow-wrap: inherit;\n letter-spacing: inherit;\n text-align: inherit;\n padding: inherit;\n font-family: inherit;\n text-transform: inherit;\n max-width: inherit;\n font-size: inherit;\n}\n";
8
- const cacheStyle = new Cache();
8
+ const cachedImg = new LRUCache({
9
+ max: 500
10
+ });
9
11
  const matrix = document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGMatrix();
10
12
  const canvas = document.createElement('canvas');
11
13
  function baseAltitudeDefault(properties, ctx) {
@@ -37,13 +39,14 @@ export function readExpression(property, ctx) {
37
39
  }
38
40
  return property;
39
41
  }
40
- async function loadImage(source) {
41
- let promise = cacheStyle.get(source, 'null');
42
+ async function loadImage(url) {
43
+ const imgUrl = url.split('?')[0];
44
+ let promise = cachedImg.get(imgUrl);
42
45
  if (!promise) {
43
- promise = Fetcher.texture(source, {
46
+ promise = Fetcher.texture(url, {
44
47
  crossOrigin: 'anonymous'
45
48
  });
46
- cacheStyle.set(promise, source, 'null');
49
+ cachedImg.set(imgUrl, promise);
47
50
  }
48
51
  return (await promise).image;
49
52
  }
@@ -64,7 +67,7 @@ function replaceWhitePxl(imgd, color, id) {
64
67
  if (!color) {
65
68
  return imgd;
66
69
  }
67
- const imgdColored = cacheStyle.get(id, color);
70
+ const imgdColored = cachedImg.get(`${id}_${color}`);
68
71
  if (!imgdColored) {
69
72
  const pix = imgd.data;
70
73
  const newColor = new Color(color);
@@ -75,7 +78,7 @@ function replaceWhitePxl(imgd, color, id) {
75
78
  pix[i + 1] = pix[i + 1] * d + newColor.g * 255 * (1 - d);
76
79
  pix[i + 2] = pix[i + 2] * d + newColor.b * 255 * (1 - d);
77
80
  }
78
- cacheStyle.set(imgd, id, color);
81
+ cachedImg.set(`${id}_${color}`, imgd);
79
82
  return imgd;
80
83
  }
81
84
  return imgdColored;
@@ -71,7 +71,7 @@ export class TileGeometry extends THREE.BufferGeometry {
71
71
  * @param cacheTile - The [Cache] used to store this geometry.
72
72
  * @param keys - The [south, level, epsg] key of this geometry.
73
73
  */
74
- initRefCount(cacheTile, keys) {
74
+ initRefCount(cacheTile, key) {
75
75
  if (this._refCount !== null) {
76
76
  return;
77
77
  }
@@ -87,7 +87,7 @@ export class TileGeometry extends THREE.BufferGeometry {
87
87
  // (in THREE.WebGLBindingStates code).
88
88
  this.index = null;
89
89
  delete this.attributes.uv;
90
- cacheTile.delete(...keys);
90
+ cacheTile.delete(key);
91
91
  super.dispose();
92
92
  // THREE.BufferGeometry.prototype.dispose.call(this);
93
93
  }
@@ -2,7 +2,7 @@ import * as THREE from 'three';
2
2
  import { STRATEGY_MIN_NETWORK_TRAFFIC } from "./LayerUpdateStrategy.js";
3
3
  import InfoLayer from "./InfoLayer.js";
4
4
  import Source from "../Source/Source.js";
5
- import Cache from "../Core/Scheduler/Cache.js";
5
+ import { LRUCache } from 'lru-cache';
6
6
  import Style from "../Core/Style.js";
7
7
 
8
8
  /**
@@ -195,7 +195,12 @@ class Layer extends THREE.EventDispatcher {
195
195
  /**
196
196
  * @type {Cache}
197
197
  */
198
- this.cache = new Cache(cacheLifeTime);
198
+ this.cache = new LRUCache({
199
+ max: 500,
200
+ ...(cacheLifeTime !== Infinity && {
201
+ ttl: cacheLifeTime
202
+ })
203
+ });
199
204
  this.mergeFeatures = mergeFeatures;
200
205
  }
201
206
  addInitializationStep() {
@@ -267,13 +272,13 @@ class Layer extends THREE.EventDispatcher {
267
272
  return data;
268
273
  }
269
274
  getData(from, to) {
270
- const key = this.source.requestToKey(this.source.isVectorSource ? to : from);
271
- let data = this.cache.getByArray(key);
275
+ const key = this.source.getDataKey(this.source.isVectorSource ? to : from);
276
+ let data = this.cache.get(key);
272
277
  if (!data) {
273
278
  data = this.source.loadData(from, this).then(feat => this.convert(feat, to), err => {
274
279
  throw err;
275
280
  });
276
- this.cache.setByArray(data, key);
281
+ this.cache.set(key, data);
277
282
  }
278
283
  return data;
279
284
  }
@@ -1,5 +1,5 @@
1
1
  import Source from "./Source.js";
2
- import Cache from "../Core/Scheduler/Cache.js";
2
+ import { LRUCache } from 'lru-cache';
3
3
 
4
4
  /**
5
5
  * An object defining the source of a single resource to get from a direct
@@ -133,8 +133,10 @@ class FileSource extends Source {
133
133
  this.fetchedData = f;
134
134
  });
135
135
  } else if (source.features) {
136
- this._featuresCaches[source.features.crs] = new Cache();
137
- this._featuresCaches[source.features.crs].setByArray(Promise.resolve(source.features), [0]);
136
+ this._featuresCaches[source.features.crs] = new LRUCache({
137
+ max: 500
138
+ });
139
+ this._featuresCaches[source.features.crs].set(0, Promise.resolve(source.features));
138
140
  }
139
141
  this.whenReady.then(() => this.fetchedData);
140
142
  this.zoom = {
@@ -148,14 +150,14 @@ class FileSource extends Source {
148
150
  onLayerAdded(options) {
149
151
  options.in = this;
150
152
  super.onLayerAdded(options);
151
- let features = this._featuresCaches[options.out.crs].getByArray([0]);
153
+ let features = this._featuresCaches[options.out.crs].get(0);
152
154
  if (!features) {
153
155
  options.out.buildExtent = this.crs != 'EPSG:4978';
154
156
  if (options.out.buildExtent) {
155
157
  options.out.forcedExtentCrs = options.out.crs != 'EPSG:4978' ? options.out.crs : this.crs;
156
158
  }
157
159
  features = this.parser(this.fetchedData, options);
158
- this._featuresCaches[options.out.crs].setByArray(features, [0]);
160
+ this._featuresCaches[options.out.crs].set(0, features);
159
161
  }
160
162
  features.then(data => {
161
163
  if (data.extent) {
@@ -177,7 +179,7 @@ class FileSource extends Source {
177
179
  * @return {FeatureCollection|Texture} The parsed data.
178
180
  */
179
181
  loadData(extent, out) {
180
- return this._featuresCaches[out.crs].getByArray([0]);
182
+ return this._featuresCaches[out.crs].get(0);
181
183
  }
182
184
  extentInsideLimit(extent) {
183
185
  return this.extent.intersectsExtent(extent);
@@ -41,8 +41,8 @@ class OrientedImageSource extends Source {
41
41
  urlFromExtent(imageInfo) {
42
42
  return this.imageUrl(imageInfo.cameraId, imageInfo.panoId);
43
43
  }
44
- requestToKey(image) {
45
- return [image.cameraId, image.panoId];
44
+ getDataKey(image) {
45
+ return `c${image.cameraId}p${image.panoId}`;
46
46
  }
47
47
 
48
48
  /**
@@ -8,38 +8,17 @@ import GTXParser from "../Parser/GTXParser.js";
8
8
  import ISGParser from "../Parser/ISGParser.js";
9
9
  import VectorTileParser from "../Parser/VectorTileParser.js";
10
10
  import Fetcher from "../Provider/Fetcher.js";
11
- import Cache from "../Core/Scheduler/Cache.js";
11
+ // import Cache from 'Core/Scheduler/Cache';
12
+ import { LRUCache } from 'lru-cache';
12
13
 
13
14
  /** @private */
14
15
  export const supportedParsers = new Map([['application/geo+json', GeoJsonParser.parse], ['application/json', GeoJsonParser.parse], ['application/kml', KMLParser.parse], ['application/gpx', GpxParser.parse], ['application/x-protobuf;type=mapbox-vector', VectorTileParser.parse], ['application/gtx', GTXParser.parse], ['application/isg', ISGParser.parse], ['application/gdf', GDFParser.parse]]);
15
16
  const noCache = {
16
- getByArray: () => {},
17
- setByArray: a => a,
17
+ get: () => {},
18
+ set: a => a,
18
19
  clear: () => {}
19
20
  };
20
21
 
21
- /**
22
- * @property {string} crs - data crs projection.
23
- * @property {boolean} isInverted - This option is to be set to the
24
- * correct value, true or false (default being false), if the computation of
25
- * the coordinates needs to be inverted to same scheme as OSM, Google Maps
26
- * or other system. See [this link](
27
- * https://alastaira.wordpress.com/2011/07/06/converting-tms-tile-coordinates-to-googlebingosm-tile-coordinates)
28
- * for more informations.
29
- *
30
- */
31
- class InformationsData {
32
- constructor(options) {
33
- if (options.projection) {
34
- console.warn('Source projection parameter is deprecated, use crs instead.');
35
- options.crs = options.crs || options.projection;
36
- }
37
- if (options.crs) {
38
- CRS.isValid(options.crs);
39
- }
40
- this.crs = options.crs;
41
- }
42
- }
43
22
  /**
44
23
  * This interface describes parsing options.
45
24
  * @typedef {Object} ParsingOptions
@@ -93,13 +72,20 @@ let uid = 0;
93
72
  * depending on the current fetched tile for example</li>
94
73
  * </ul>
95
74
  */
96
- class Source extends InformationsData {
75
+ class Source {
97
76
  /**
98
77
  * @param {Object} source - An object that can contain all properties of a
99
78
  * Source. Only the `url` property is mandatory.
100
79
  */
101
80
  constructor(source) {
102
- super(source);
81
+ if (source.projection) {
82
+ console.warn('Source projection parameter is deprecated, use crs instead.');
83
+ source.crs = source.crs || source.projection;
84
+ }
85
+ if (source.crs) {
86
+ CRS.isValid(source.crs);
87
+ }
88
+ this.crs = source.crs;
103
89
  this.isSource = true;
104
90
  if (!source.url) {
105
91
  throw new Error('New Source: url is required');
@@ -141,8 +127,8 @@ class Source extends InformationsData {
141
127
  urlFromExtent() {
142
128
  throw new Error('In extended Source, you have to implement the method urlFromExtent!');
143
129
  }
144
- requestToKey(extent) {
145
- return [extent.zoom, extent.row, extent.col];
130
+ getDataKey(extent) {
131
+ return `z${extent.zoom}r${extent.row}c${extent.col}`;
146
132
  }
147
133
 
148
134
  /**
@@ -155,23 +141,18 @@ class Source extends InformationsData {
155
141
  */
156
142
  loadData(extent, out) {
157
143
  const cache = this._featuresCaches[out.crs];
158
- const key = this.requestToKey(extent);
144
+ const key = this.getDataKey(extent);
145
+ // console.log('Source.loadData', key);
159
146
  // try to get parsed data from cache
160
- let features = cache.getByArray(key);
147
+ let features = cache.get(key);
161
148
  if (!features) {
162
149
  // otherwise fetch/parse the data
163
- features = cache.setByArray(this.fetcher(this.urlFromExtent(extent), this.networkOptions).then(file => this.parser(file, {
150
+ features = this.fetcher(this.urlFromExtent(extent), this.networkOptions).then(file => this.parser(file, {
164
151
  out,
165
152
  in: this,
166
153
  extent
167
- })).catch(err => this.handlingError(err)), key);
168
- if (this.onParsedFile) {
169
- features.then(feat => {
170
- this.onParsedFile(feat);
171
- console.warn('Source.onParsedFile was deprecated');
172
- return feat;
173
- });
174
- }
154
+ })).catch(err => this.handlingError(err));
155
+ cache.set(key, features);
175
156
  }
176
157
  return features;
177
158
  }
@@ -187,7 +168,9 @@ class Source extends InformationsData {
187
168
  // Cache feature only if it's vector data, the feature are cached in source.
188
169
  // It's not necessary to cache raster in Source,
189
170
  // because it's already cached on layer.
190
- this._featuresCaches[options.out.crs] = this.isVectorSource ? new Cache() : noCache;
171
+ this._featuresCaches[options.out.crs] = this.isVectorSource ? new LRUCache({
172
+ max: 500
173
+ }) : noCache;
191
174
  }
192
175
  }
193
176
 
@@ -164,23 +164,17 @@ class VectorTilesSource extends TMSSource {
164
164
  }
165
165
  loadData(extent, out) {
166
166
  const cache = this._featuresCaches[out.crs];
167
- const key = this.requestToKey(extent);
167
+ const key = this.getDataKey(extent);
168
168
  // try to get parsed data from cache
169
- let features = cache.getByArray(key);
169
+ let features = cache.get(key);
170
170
  if (!features) {
171
171
  // otherwise fetch/parse the data
172
- features = cache.setByArray(Promise.all(this.urls.map(url => this.fetcher(this.urlFromExtent(extent, url), this.networkOptions).then(file => this.parser(file, {
172
+ features = Promise.all(this.urls.map(url => this.fetcher(this.urlFromExtent(extent, url), this.networkOptions).then(file => this.parser(file, {
173
173
  out,
174
174
  in: this,
175
175
  extent
176
- })))).then(collections => mergeCollections(collections)).catch(err => this.handlingError(err)), key);
177
- if (this.onParsedFile) {
178
- features.then(feat => {
179
- this.onParsedFile(feat);
180
- console.warn('Source.onParsedFile was deprecated');
181
- return feat;
182
- });
183
- }
176
+ })))).then(collections => mergeCollections(collections)).catch(err => this.handlingError(err));
177
+ cache.set(key, features);
184
178
  }
185
179
  return features;
186
180
  }
@@ -152,11 +152,11 @@ class WFSSource extends Source {
152
152
  }
153
153
  return super.handlingError(err);
154
154
  }
155
- requestToKey(extent) {
155
+ getDataKey(extent) {
156
156
  if (extent.isTile) {
157
- return super.requestToKey(extent);
157
+ return super.getDataKey(extent);
158
158
  } else {
159
- return [extent.zoom, extent.south, extent.west];
159
+ return `z${extent.zoom}s${extent.south}w${extent.west}`;
160
160
  }
161
161
  }
162
162
  urlFromExtent(extentOrTile) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itowns",
3
- "version": "2.44.3-next.35",
3
+ "version": "2.44.3-next.36",
4
4
  "description": "A JS/WebGL framework for 3D geospatial data visualization",
5
5
  "type": "module",
6
6
  "main": "lib/Main.js",
@@ -66,6 +66,7 @@
66
66
  "copc": "^0.0.6",
67
67
  "earcut": "^3.0.0",
68
68
  "js-priority-queue": "^0.1.5",
69
+ "lru-cache": "^11.0.1",
69
70
  "pbf": "^4.0.1",
70
71
  "shpjs": "^6.1.0",
71
72
  "threads": "^1.7.0"