gridviz 3.0.15 → 3.0.16
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/README.md +127 -128
- package/dist/gridviz.js +7959 -7861
- package/dist/gridviz.min.js +1 -1
- package/package.json +74 -74
- package/src/button/ZoomButtons.js +101 -96
- package/src/core/Dataset.js +154 -157
- package/src/core/Drawable.js +60 -61
- package/src/core/GeoCanvas.js +409 -370
- package/src/core/Layer.js +23 -25
- package/src/core/Legend.js +108 -110
- package/src/core/Map.js +495 -495
- package/src/core/MultiResolutionDataset.js +93 -97
- package/src/core/Style.js +98 -99
- package/src/dataset/CSVGrid.js +112 -112
- package/src/dataset/GeoTIFF.js +122 -123
- package/src/dataset/JSGrid.js +55 -54
- package/src/dataset/TiledGrid.js +289 -288
- package/src/dataset/worker.js +18 -0
- package/src/index.js +77 -71
- package/src/layer/BackgroundLayer.js +162 -158
- package/src/layer/BackgroundLayerImage.js +81 -84
- package/src/layer/BackgroundLayerWMS.js +104 -108
- package/src/layer/GeoJSONLayer.js +214 -220
- package/src/layer/GridLayer.js +148 -157
- package/src/layer/LabelLayer.js +194 -193
- package/src/legend/ColorCategoryLegend.js +109 -110
- package/src/legend/ColorDiscreteLegend.js +100 -102
- package/src/legend/ColorLegend.js +115 -118
- package/src/legend/OrientationLegend.js +89 -91
- package/src/legend/SizeLegend.js +224 -224
- package/src/legend/TernaryLegend.js +302 -210
- package/src/style/CompositionStyle.js +291 -288
- package/src/style/DotDensityStyle.js +133 -134
- package/src/style/ImageStyle.js +100 -102
- package/src/style/IsoFenceStyle.js +217 -203
- package/src/style/JoyPlotStyle.js +127 -128
- package/src/style/LegoStyle.js +110 -110
- package/src/style/MosaicStyle.js +99 -99
- package/src/style/NinjaStarStyle.js +102 -102
- package/src/style/PillarStyle.js +207 -208
- package/src/style/SegmentStyle.js +105 -105
- package/src/style/ShapeColorSizeStyle.js +147 -132
- package/src/style/SideCategoryStyle.js +112 -114
- package/src/style/SideStyle.js +212 -205
- package/src/style/SquareColorCategoryWebGLStyle.js +107 -108
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -136
- package/src/style/TanakaStyle.js +69 -68
- package/src/style/TextStyle.js +110 -111
- package/src/style/TimeSeriesStyle.js +222 -229
- package/src/utils/scale.js +218 -228
- package/src/utils/stretching.js +120 -133
- package/src/utils/ternary.js +203 -204
- package/src/utils/utils.js +58 -63
- package/src/utils/webGLUtils.js +72 -70
package/src/dataset/TiledGrid.js
CHANGED
|
@@ -1,288 +1,289 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
/** @typedef {{ dims: object, crs: string, tileSizeCell: number, originPoint: {x:number,y:number}, resolutionGeo: number, tilingBounds:import("../core/GeoCanvas.js").Envelope }} GridInfo */
|
|
5
|
-
|
|
6
|
-
// internal
|
|
7
|
-
import { Dataset } from '../core/Dataset.js'
|
|
8
|
-
//import { monitor, monitorDuration } from '../utils/Utils.js'
|
|
9
|
-
|
|
10
|
-
// external
|
|
11
|
-
import { json, csv } from 'd3-fetch'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A tiled dataset, composed of CSV tiles.
|
|
15
|
-
*
|
|
16
|
-
* @module dataset
|
|
17
|
-
* @author Joseph Davies, Julien Gaffuri
|
|
18
|
-
*/
|
|
19
|
-
export class TiledGrid extends Dataset {
|
|
20
|
-
/**
|
|
21
|
-
* @param {import("../core/Map.js").Map} map The map.
|
|
22
|
-
* @param {string} url The URL of the dataset.
|
|
23
|
-
* @param {{preprocess?:(function(import("../core/Dataset.js").Cell):boolean) }} opts
|
|
24
|
-
*/
|
|
25
|
-
constructor(map, url, opts = {}) {
|
|
26
|
-
super(map, url, 0, opts)
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* The grid info object, from the info.json file.
|
|
30
|
-
* @type {GridInfo | undefined}
|
|
31
|
-
* @private
|
|
32
|
-
* */
|
|
33
|
-
this.info = undefined
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @type {string}
|
|
37
|
-
* @private */
|
|
38
|
-
this.infoLoadingStatus = 'notLoaded'
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* The cache of the loaded tiles. It is double indexed: by xT and then yT.
|
|
42
|
-
* Example: this.cache[xT][yT] returns the tile at [xT][yT] location.
|
|
43
|
-
*
|
|
44
|
-
* @type {object}
|
|
45
|
-
* */
|
|
46
|
-
this.cache = {}
|
|
47
|
-
|
|
48
|
-
//launch loading
|
|
49
|
-
this.loadInfo()
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Load the info.json from the url.
|
|
54
|
-
* @returns this
|
|
55
|
-
*/
|
|
56
|
-
loadInfo() {
|
|
57
|
-
if (!this.info && this.infoLoadingStatus === 'notLoaded') {
|
|
58
|
-
;
|
|
59
|
-
try {
|
|
60
|
-
const data = await json(this.url + 'info.json')
|
|
61
|
-
this.info = data
|
|
62
|
-
this.resolution = data.resolutionGeo
|
|
63
|
-
this.infoLoadingStatus = 'loaded'
|
|
64
|
-
this.map.redraw()
|
|
65
|
-
} catch (error) {
|
|
66
|
-
//mark as failed
|
|
67
|
-
this.infoLoadingStatus = 'failed'
|
|
68
|
-
}
|
|
69
|
-
})()
|
|
70
|
-
} else if (
|
|
71
|
-
this.map.redraw()
|
|
72
|
-
return this
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Compute a tiling envelope from a geographical envelope.
|
|
77
|
-
* This is the function to use to know which tiles to download for a geographical view.
|
|
78
|
-
*
|
|
79
|
-
* @param {import("../core/GeoCanvas.js").Envelope} e
|
|
80
|
-
* @returns {import("../core/GeoCanvas.js").Envelope|undefined}
|
|
81
|
-
*/
|
|
82
|
-
getTilingEnvelope(e) {
|
|
83
|
-
if (!this.info) {
|
|
84
|
-
this.loadInfo()
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const po = this.info.originPoint,
|
|
89
|
-
r = this.info.resolutionGeo,
|
|
90
|
-
s = this.info.tileSizeCell
|
|
91
|
-
|
|
92
|
-
return {
|
|
93
|
-
xMin: Math.floor((e.xMin - po.x) / (r * s)),
|
|
94
|
-
xMax: Math.floor((e.xMax - po.x) / (r * s)),
|
|
95
|
-
yMin: Math.floor((e.yMin - po.y) / (r * s)),
|
|
96
|
-
yMax: Math.floor((e.yMax - po.y) / (r * s)),
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Request data within a geographic envelope.
|
|
102
|
-
*
|
|
103
|
-
* @param {import('../core/GeoCanvas.js').Envelope} extGeo
|
|
104
|
-
* @returns {this}
|
|
105
|
-
*/
|
|
106
|
-
getData(extGeo) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
this.cache[xT][yT]
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
*
|
|
218
|
-
* @
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
if (+cell.
|
|
251
|
-
if (+cell.
|
|
252
|
-
this.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
cell.
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
/** @typedef {{ dims: object, crs: string, tileSizeCell: number, originPoint: {x:number,y:number}, resolutionGeo: number, tilingBounds:import("../core/GeoCanvas.js").Envelope }} GridInfo */
|
|
5
|
+
|
|
6
|
+
// internal
|
|
7
|
+
import { Dataset } from '../core/Dataset.js'
|
|
8
|
+
//import { monitor, monitorDuration } from '../utils/Utils.js'
|
|
9
|
+
|
|
10
|
+
// external
|
|
11
|
+
import { json, csv } from 'd3-fetch'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A tiled dataset, composed of CSV tiles.
|
|
15
|
+
*
|
|
16
|
+
* @module dataset
|
|
17
|
+
* @author Joseph Davies, Julien Gaffuri
|
|
18
|
+
*/
|
|
19
|
+
export class TiledGrid extends Dataset {
|
|
20
|
+
/**
|
|
21
|
+
* @param {import("../core/Map.js").Map} map The map.
|
|
22
|
+
* @param {string} url The URL of the dataset.
|
|
23
|
+
* @param {{preprocess?:(function(import("../core/Dataset.js").Cell):boolean), onlyDrawWhenAllTilesReady:boolean}} opts
|
|
24
|
+
*/
|
|
25
|
+
constructor(map, url, opts = {}) {
|
|
26
|
+
super(map, url, 0, opts)
|
|
27
|
+
this.onlyDrawWhenAllTilesReady = opts.onlyDrawWhenAllTilesReady || false
|
|
28
|
+
/**
|
|
29
|
+
* The grid info object, from the info.json file.
|
|
30
|
+
* @type {GridInfo | undefined}
|
|
31
|
+
* @private
|
|
32
|
+
* */
|
|
33
|
+
this.info = undefined
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @type {string}
|
|
37
|
+
* @private */
|
|
38
|
+
this.infoLoadingStatus = 'notLoaded'
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The cache of the loaded tiles. It is double indexed: by xT and then yT.
|
|
42
|
+
* Example: this.cache[xT][yT] returns the tile at [xT][yT] location.
|
|
43
|
+
*
|
|
44
|
+
* @type {object}
|
|
45
|
+
* */
|
|
46
|
+
this.cache = {}
|
|
47
|
+
|
|
48
|
+
//launch loading
|
|
49
|
+
this.loadInfo()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Load the info.json from the url.
|
|
54
|
+
* @returns this
|
|
55
|
+
*/
|
|
56
|
+
loadInfo() {
|
|
57
|
+
if (!this.info && this.infoLoadingStatus === 'notLoaded') {
|
|
58
|
+
;(async () => {
|
|
59
|
+
try {
|
|
60
|
+
const data = await json(this.url + 'info.json')
|
|
61
|
+
this.info = data
|
|
62
|
+
this.resolution = data.resolutionGeo
|
|
63
|
+
this.infoLoadingStatus = 'loaded'
|
|
64
|
+
this.map.redraw()
|
|
65
|
+
} catch (error) {
|
|
66
|
+
//mark as failed
|
|
67
|
+
this.infoLoadingStatus = 'failed'
|
|
68
|
+
}
|
|
69
|
+
})()
|
|
70
|
+
} else if (this.infoLoadingStatus === 'loaded' || this.infoLoadingStatus === 'failed')
|
|
71
|
+
this.map.redraw()
|
|
72
|
+
return this
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Compute a tiling envelope from a geographical envelope.
|
|
77
|
+
* This is the function to use to know which tiles to download for a geographical view.
|
|
78
|
+
*
|
|
79
|
+
* @param {import("../core/GeoCanvas.js").Envelope} e
|
|
80
|
+
* @returns {import("../core/GeoCanvas.js").Envelope|undefined}
|
|
81
|
+
*/
|
|
82
|
+
getTilingEnvelope(e) {
|
|
83
|
+
if (!this.info) {
|
|
84
|
+
this.loadInfo()
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const po = this.info.originPoint,
|
|
89
|
+
r = this.info.resolutionGeo,
|
|
90
|
+
s = this.info.tileSizeCell
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
xMin: Math.floor((e.xMin - po.x) / (r * s)),
|
|
94
|
+
xMax: Math.floor((e.xMax - po.x) / (r * s)),
|
|
95
|
+
yMin: Math.floor((e.yMin - po.y) / (r * s)),
|
|
96
|
+
yMax: Math.floor((e.yMax - po.y) / (r * s)),
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Request data within a geographic envelope.
|
|
102
|
+
*
|
|
103
|
+
* @param {import('../core/GeoCanvas.js').Envelope} extGeo
|
|
104
|
+
* @returns {this}
|
|
105
|
+
*/
|
|
106
|
+
async getData(extGeo) {
|
|
107
|
+
if (!this.info) return this
|
|
108
|
+
|
|
109
|
+
// Get the tiling envelope and check bounds
|
|
110
|
+
const tb = this.getTilingEnvelope(extGeo)
|
|
111
|
+
if (!tb) return this
|
|
112
|
+
|
|
113
|
+
const { xMin: gbXMin, xMax: gbXMax, yMin: gbYMin, yMax: gbYMax } = this.info.tilingBounds
|
|
114
|
+
|
|
115
|
+
const xMin = Math.max(tb.xMin, gbXMin)
|
|
116
|
+
const xMax = Math.min(tb.xMax, gbXMax)
|
|
117
|
+
const yMin = Math.max(tb.yMin, gbYMin)
|
|
118
|
+
const yMax = Math.min(tb.yMax, gbYMax)
|
|
119
|
+
|
|
120
|
+
// Count the total number of tiles
|
|
121
|
+
const totalTiles = (xMax - xMin + 1) * (yMax - yMin + 1)
|
|
122
|
+
|
|
123
|
+
let processedTiles = 0 // Counter for loaded tiles
|
|
124
|
+
const tilePromises = []
|
|
125
|
+
|
|
126
|
+
// Iterate over tiles within bounds
|
|
127
|
+
for (let xT = xMin; xT <= xMax; xT++) {
|
|
128
|
+
for (let yT = yMin; yT <= yMax; yT++) {
|
|
129
|
+
if (!this.cache[xT]) this.cache[xT] = {}
|
|
130
|
+
|
|
131
|
+
// Skip already loaded or loading tiles
|
|
132
|
+
if (this.cache[xT][yT]) {
|
|
133
|
+
++processedTiles
|
|
134
|
+
continue
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Mark tile as loading
|
|
138
|
+
this.cache[xT][yT] = 'loading'
|
|
139
|
+
|
|
140
|
+
// Prepare the tile request and store it in tilePromises
|
|
141
|
+
tilePromises.push(
|
|
142
|
+
this.loadTile(xT, yT)
|
|
143
|
+
.then((tile) => {
|
|
144
|
+
// Before we increment processedTiles, check if it's the last tile
|
|
145
|
+
const isLastTile = ++processedTiles === totalTiles
|
|
146
|
+
|
|
147
|
+
// Store the tile in the cache
|
|
148
|
+
this.cache[xT][yT] = tile
|
|
149
|
+
|
|
150
|
+
// Pass the isLastTile argument to checkAndRedraw
|
|
151
|
+
this.checkAndRedraw(tile, isLastTile)
|
|
152
|
+
})
|
|
153
|
+
.catch(() => {
|
|
154
|
+
// Mark as failed but allow processing to continue
|
|
155
|
+
this.cache[xT][yT] = 'failed'
|
|
156
|
+
++processedTiles
|
|
157
|
+
})
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Handle all tile promises, including failures
|
|
163
|
+
await Promise.allSettled(tilePromises)
|
|
164
|
+
return this
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async loadTile(xT, yT) {
|
|
168
|
+
try {
|
|
169
|
+
const data = await csv(`${this.url}${xT}/${yT}.csv`)
|
|
170
|
+
|
|
171
|
+
// Preprocess or filter the data if needed
|
|
172
|
+
const cells = this.preprocess ? data.filter((cell) => this.preprocess(cell) !== false) : data
|
|
173
|
+
|
|
174
|
+
if (!this.info) throw new Error('Tile info unknown')
|
|
175
|
+
|
|
176
|
+
return getGridTile(cells, xT, yT, this.info)
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.warn(`Failed to load tile ${xT}, ${yT}:`, error)
|
|
179
|
+
throw error
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
checkAndRedraw(tile, isLastTile) {
|
|
184
|
+
// Check if any visible layer depends on this dataset
|
|
185
|
+
//check if redraw is really needed, that is if:
|
|
186
|
+
// 1. the dataset belongs to a layer which is visible at the current zoom level
|
|
187
|
+
let needsRedraw = false
|
|
188
|
+
//go through the layers
|
|
189
|
+
const z = this.map.getZoom()
|
|
190
|
+
for (const lay of this.map.layers) {
|
|
191
|
+
if (lay.visible && !lay.visible(z)) continue
|
|
192
|
+
if (!lay.getDataset) continue
|
|
193
|
+
if (lay.getDataset(z) != this) continue
|
|
194
|
+
//found one layer. No need to seek more.
|
|
195
|
+
needsRedraw = true
|
|
196
|
+
break
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!needsRedraw) return
|
|
200
|
+
|
|
201
|
+
// Check if tile intersects the current view
|
|
202
|
+
const env = this.map.updateExtentGeo()
|
|
203
|
+
const { xMin, xMax, yMin, yMax } = tile.extGeo
|
|
204
|
+
if (env.xMax <= xMin || env.xMin >= xMax || env.yMax <= yMin || env.yMin >= yMax) return
|
|
205
|
+
|
|
206
|
+
// Trigger redraw
|
|
207
|
+
if (this.onlyDrawWhenAllTilesReady) {
|
|
208
|
+
if (isLastTile) {
|
|
209
|
+
this.map.redraw()
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
this.map.redraw()
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Fill the view cache with all cells which are within a geographical envelope.
|
|
218
|
+
* @abstract
|
|
219
|
+
* @param {import("../core/GeoCanvas.js").Envelope} extGeo
|
|
220
|
+
* @returns {void}
|
|
221
|
+
*/
|
|
222
|
+
updateViewCache(extGeo) {
|
|
223
|
+
//
|
|
224
|
+
this.cellsViewCache = []
|
|
225
|
+
|
|
226
|
+
//check if info has been loaded
|
|
227
|
+
if (!this.info) return
|
|
228
|
+
|
|
229
|
+
//tiles within the scope
|
|
230
|
+
/** @type {import("../core/GeoCanvas.js").Envelope|undefined} */
|
|
231
|
+
const tb = this.getTilingEnvelope(extGeo)
|
|
232
|
+
if (!tb) return
|
|
233
|
+
|
|
234
|
+
//grid bounds
|
|
235
|
+
/** @type {import("../core/GeoCanvas.js").Envelope} */
|
|
236
|
+
const gb = this.info.tilingBounds
|
|
237
|
+
|
|
238
|
+
for (let xT = Math.max(tb.xMin, gb.xMin); xT <= Math.min(tb.xMax, gb.xMax); xT++) {
|
|
239
|
+
if (!this.cache[xT]) continue
|
|
240
|
+
for (let yT = Math.max(tb.yMin, gb.yMin); yT <= Math.min(tb.yMax, gb.yMax); yT++) {
|
|
241
|
+
//get tile
|
|
242
|
+
/** @type {object} */
|
|
243
|
+
const tile = this.cache[xT][yT]
|
|
244
|
+
if (!tile || typeof tile === 'string') continue
|
|
245
|
+
|
|
246
|
+
//get cells
|
|
247
|
+
//this.cellsViewCache = this.cellsViewCache.concat(tile.cells)
|
|
248
|
+
|
|
249
|
+
for (const cell of tile.cells) {
|
|
250
|
+
if (+cell.x + this.resolution < extGeo.xMin) continue
|
|
251
|
+
if (+cell.x - this.resolution > extGeo.xMax) continue
|
|
252
|
+
if (+cell.y + this.resolution < extGeo.yMin) continue
|
|
253
|
+
if (+cell.y - this.resolution > extGeo.yMax) continue
|
|
254
|
+
this.cellsViewCache.push(cell)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function getGridTile(cells, xT, yT, gridInfo) {
|
|
262
|
+
const tile = {}
|
|
263
|
+
|
|
264
|
+
/** @type {Array.<import("../core/Dataset").Cell>} */
|
|
265
|
+
tile.cells = cells
|
|
266
|
+
/** @type {number} */
|
|
267
|
+
tile.x = xT
|
|
268
|
+
/** @type {number} */
|
|
269
|
+
tile.y = yT
|
|
270
|
+
|
|
271
|
+
const r = gridInfo.resolutionGeo
|
|
272
|
+
const s = gridInfo.tileSizeCell
|
|
273
|
+
|
|
274
|
+
/** @type {import("../core/GeoCanvas").Envelope} */
|
|
275
|
+
tile.extGeo = {
|
|
276
|
+
xMin: gridInfo.originPoint.x + r * s * tile.x,
|
|
277
|
+
xMax: gridInfo.originPoint.x + r * s * (tile.x + 1),
|
|
278
|
+
yMin: gridInfo.originPoint.y + r * s * tile.y,
|
|
279
|
+
yMax: gridInfo.originPoint.y + r * s * (tile.y + 1),
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
//convert cell coordinates into geographical coordinates
|
|
283
|
+
for (let cell of tile.cells) {
|
|
284
|
+
cell.x = tile.extGeo.xMin + cell.x * r
|
|
285
|
+
cell.y = tile.extGeo.yMin + cell.y * r
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return tile
|
|
289
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
self.onmessage = function (e) {
|
|
2
|
+
const { type, cells, preprocess } = e.data
|
|
3
|
+
if (type === 'processCells') {
|
|
4
|
+
const result = processCells(cells, preprocess)
|
|
5
|
+
self.postMessage({ type: 'processedCells', result })
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function processCells(cells, preprocess) {
|
|
10
|
+
// If no preprocess function is provided, return the cells as they are
|
|
11
|
+
if (!preprocess) {
|
|
12
|
+
return cells
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Apply preprocess function to each cell if available
|
|
16
|
+
const preprocessedCells = cells.map((cell) => preprocess(cell)).filter((cell) => cell !== false)
|
|
17
|
+
return preprocessedCells
|
|
18
|
+
}
|