gridviz 2.1.11 → 2.1.13

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 (60) hide show
  1. package/README.md +125 -125
  2. package/dist/gridviz.js +8254 -7887
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +77 -77
  5. package/src/App.js +758 -705
  6. package/src/BackgroundLayer.js +182 -182
  7. package/src/BackgroundLayerWMS.js +131 -131
  8. package/src/Dataset.js +76 -76
  9. package/src/DatasetComponent.js +113 -113
  10. package/src/GeoCanvas.js +420 -420
  11. package/src/LabelLayer.js +190 -190
  12. package/src/Layer.js +103 -103
  13. package/src/Legend.js +86 -86
  14. package/src/LineLayer.js +150 -150
  15. package/src/Style.js +129 -129
  16. package/src/Tooltip.js +180 -180
  17. package/src/button/Button.js +54 -0
  18. package/src/button/FullscreenButton.js +98 -0
  19. package/src/button/ZoomButtons.js +72 -0
  20. package/src/dataset/COGeo.js +24 -24
  21. package/src/dataset/CSVGrid.js +104 -104
  22. package/src/dataset/GeoTIFF.js +127 -127
  23. package/src/dataset/GridTile.js +41 -41
  24. package/src/dataset/LGrid.js +54 -54
  25. package/src/dataset/TiledGrid.js +264 -264
  26. package/src/index.js +71 -71
  27. package/src/legend/ColorCategoryLegend.js +124 -124
  28. package/src/legend/ColorDiscreteLegend.js +103 -103
  29. package/src/legend/ColorLegend.js +128 -124
  30. package/src/legend/SegmentOrientationLegend.js +87 -87
  31. package/src/legend/SegmentWidthLegend.js +101 -97
  32. package/src/legend/SizeLegend.js +141 -141
  33. package/src/style/CompositionStyle.js +300 -300
  34. package/src/style/ContourStyle.js +54 -54
  35. package/src/style/DotDensityStyle.js +156 -156
  36. package/src/style/IsoFenceStyle.js +262 -262
  37. package/src/style/JoyPlotStyle.js +135 -135
  38. package/src/style/LegoStyle.js +112 -112
  39. package/src/style/MosaicStyle.js +107 -107
  40. package/src/style/NinjaStarStyle.js +125 -125
  41. package/src/style/PillarStyle.js +230 -230
  42. package/src/style/SegmentStyle.js +142 -142
  43. package/src/style/ShapeColorSizeStyle.js +152 -126
  44. package/src/style/SideCatStyle.js +172 -172
  45. package/src/style/SideStyle.js +216 -216
  46. package/src/style/SquareColorCatWGLStyle.js +120 -120
  47. package/src/style/SquareColorWGLStyle.js +146 -146
  48. package/src/style/StrokeStyle.js +131 -131
  49. package/src/style/TanakaStyle.js +160 -160
  50. package/src/style/TextStyle.js +132 -132
  51. package/src/style/TimeSeriesStyle.js +259 -250
  52. package/src/utils/Utils.js +35 -35
  53. package/src/utils/WebGLRectangleColoring.js +106 -106
  54. package/src/utils/WebGLSquareColoring.js +118 -118
  55. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  56. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  57. package/src/utils/WebGLSquareColoringKS.js +153 -153
  58. package/src/utils/stretching.js +131 -131
  59. package/src/utils/webGLUtils.js +71 -71
  60. package/src/utils/zoomUtils.js +142 -142
@@ -1,264 +1,264 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- /** @typedef {{ dims: object, crs: string, tileSizeCell: number, originPoint: {x:number,y:number}, resolutionGeo: number, tilingBounds:import("../Dataset").Envelope, format:import("../DatasetComponent").Format }} GridInfo */
5
-
6
- // internal
7
- import { GridTile } from './GridTile.js'
8
- import { App } from '../App.js'
9
- import { DatasetComponent } from '../DatasetComponent.js'
10
- import { monitor, monitorDuration } from '../utils/Utils.js'
11
-
12
- // external
13
- import { json, csv } from 'd3-fetch'
14
-
15
- /**
16
- * A tiled dataset, composed of CSV tiles.
17
- *
18
- * @author Joseph Davies, Julien Gaffuri
19
- */
20
- export class TiledGrid extends DatasetComponent {
21
- /**
22
- * @param {string} url The URL of the dataset.
23
- * @param {App} app The application.
24
- * @param {{preprocess?:(function(import("../Dataset").Cell):boolean) }} opts
25
- */
26
- constructor(url, app, opts = {}) {
27
- super(url, 0, opts)
28
-
29
- /**
30
- * The app being used.
31
- * @type {App}
32
- */
33
- this.app = app
34
-
35
- /**
36
- * The grid info object, from the info.json file.
37
- * @type {GridInfo | undefined}
38
- * @private
39
- * */
40
- this.info = undefined
41
-
42
- /**
43
- * @type {string}
44
- * @private */
45
- this.infoLoadingStatus = 'notLoaded'
46
-
47
- /**
48
- * The cache of the loaded tiles. It is double indexed: by xT and then yT.
49
- * Example: this.cache[xT][yT] returns the tile at [xT][yT] location.
50
- *
51
- * @type {object}
52
- * */
53
- this.cache = {}
54
-
55
- }
56
-
57
- /**
58
- * Load the info.json from the url.
59
- *
60
- * @param {function():void} callback
61
- * @returns this
62
- */
63
- loadInfo(callback) {
64
- if (!this.info && this.infoLoadingStatus === 'notLoaded') {
65
- ; (async () => {
66
- try {
67
- const data = await json(this.url + 'info.json')
68
- this.info = data
69
- this.resolution = data.resolutionGeo
70
- this.infoLoadingStatus = 'loaded'
71
- if (callback) callback()
72
- } catch (error) {
73
- //mark as failed
74
- this.infoLoadingStatus = 'failed'
75
- }
76
- })()
77
- } else if (callback && (this.infoLoadingStatus === 'loaded' || this.infoLoadingStatus === 'failed'))
78
- callback()
79
- return this
80
- }
81
-
82
- /**
83
- * Compute a tiling envelope from a geographical envelope.
84
- * This is the function to use to know which tiles to download for a geographical view.
85
- *
86
- * @param {import("../Dataset").Envelope} e
87
- * @returns {import("../Dataset").Envelope|undefined}
88
- */
89
- getTilingEnvelope(e) {
90
- if (!this.info) {
91
- this.loadInfo(() => { })
92
- return
93
- }
94
-
95
- const po = this.info.originPoint,
96
- r = this.info.resolutionGeo,
97
- s = this.info.tileSizeCell
98
-
99
- return {
100
- xMin: Math.floor((e.xMin - po.x) / (r * s)),
101
- xMax: Math.floor((e.xMax - po.x) / (r * s)),
102
- yMin: Math.floor((e.yMin - po.y) / (r * s)),
103
- yMax: Math.floor((e.yMax - po.y) / (r * s)),
104
- }
105
- }
106
-
107
- /**
108
- * Request data within a geographic envelope.
109
- *
110
- * @param {import("../Dataset").Envelope} extGeo
111
- * @param {function():void} redrawFun
112
- * @returns {this}
113
- */
114
- getData(extGeo, redrawFun) {
115
- //TODO empty cache when it gets too big ?
116
-
117
- //check if info has been loaded
118
- if (!this.info) return this
119
-
120
- //tiles within the scope
121
- /** @type {import("../Dataset").Envelope|undefined} */
122
- const tb = this.getTilingEnvelope(extGeo)
123
- if (!tb) return this
124
-
125
- //grid bounds
126
- /** @type {import("../Dataset").Envelope} */
127
- const gb = this.info.tilingBounds
128
-
129
- for (let xT = Math.max(tb.xMin, gb.xMin); xT <= Math.min(tb.xMax, gb.xMax); xT++) {
130
- for (let yT = Math.max(tb.yMin, gb.yMin); yT <= Math.min(tb.yMax, gb.yMax); yT++) {
131
- //prepare cache
132
- if (!this.cache[xT]) this.cache[xT] = {}
133
-
134
- //check if tile exists in the cache
135
- /** @type {GridTile} */
136
- let tile = this.cache[xT][yT]
137
- if (tile) continue
138
-
139
- //mark tile as loading
140
- this.cache[xT][yT] = "loading";
141
- (async () => {
142
- //request tile
143
- /** @type {Array.<import("../Dataset").Cell>} */
144
- let cells
145
-
146
- try {
147
- /** @type {Array.<import("../Dataset").Cell>} */
148
- // @ts-ignore
149
- const data = await csv(this.url + xT + '/' + yT + '.csv')
150
-
151
- //if (monitor) monitorDuration('*** TiledGrid parse start')
152
-
153
- //preprocess/filter
154
- if (this.preprocess) {
155
- cells = []
156
- for (const c of data) {
157
- const b = this.preprocess(c)
158
- if (b == false) continue
159
- cells.push(c)
160
- }
161
- } else {
162
- cells = data
163
- }
164
-
165
- //if (monitor) monitorDuration('preprocess / filter')
166
- } catch (error) {
167
- //mark as failed
168
- this.cache[xT][yT] = 'failed'
169
- return
170
- }
171
-
172
- //store tile in cache
173
- if (!this.info) {
174
- console.error('Tile info inknown')
175
- return
176
- }
177
- const tile_ = new GridTile(cells, xT, yT, this.info)
178
- this.cache[xT][yT] = tile_
179
-
180
- //if (monitor) monitorDuration('storage')
181
-
182
- //if no redraw is specified, then leave
183
- if (!redrawFun) return
184
-
185
- //check if redraw is really needed, that is if:
186
-
187
- // 1. the dataset belongs to a layer which is visible at the current zoom level
188
- let redraw = false
189
- //go through the layers
190
- const zf = this.app.getZoomFactor()
191
- for (const lay of this.app.layers) {
192
- if (!lay.visible) continue
193
- if (lay.getDatasetComponent(zf) != this) continue
194
- //found one layer. No need to seek more.
195
- redraw = true
196
- break
197
- }
198
- //if (monitor) monitorDuration('check redraw 1')
199
-
200
- if (!redraw) return
201
-
202
- // 2. the tile is within the view, that is its geo envelope intersects the viewer geo envelope.
203
- const env = this.app.updateExtentGeo()
204
- const envT = tile_.extGeo
205
- if (env.xMax <= envT.xMin) return
206
- if (env.xMin >= envT.xMax) return
207
- if (env.yMax <= envT.yMin) return
208
- if (env.yMin >= envT.yMax) return
209
-
210
- //if (monitor) monitorDuration('check redraw 2')
211
- //if (monitor) monitorDuration('*** TiledGrid parse end')
212
-
213
- //redraw
214
- redrawFun()
215
- })()
216
- }
217
- }
218
- return this
219
- }
220
-
221
- /**
222
- * Fill the view cache with all cells which are within a geographical envelope.
223
- * @abstract
224
- * @param {import("../Dataset").Envelope} extGeo
225
- * @returns {void}
226
- */
227
- updateViewCache(extGeo) {
228
- //
229
- this.cellsViewCache = []
230
-
231
- //check if info has been loaded
232
- if (!this.info) return
233
-
234
- //tiles within the scope
235
- /** @type {import("../Dataset").Envelope|undefined} */
236
- const tb = this.getTilingEnvelope(extGeo)
237
- if (!tb) return
238
-
239
- //grid bounds
240
- /** @type {import("../Dataset").Envelope} */
241
- const gb = this.info.tilingBounds
242
-
243
- for (let xT = Math.max(tb.xMin, gb.xMin); xT <= Math.min(tb.xMax, gb.xMax); xT++) {
244
- if (!this.cache[xT]) continue
245
- for (let yT = Math.max(tb.yMin, gb.yMin); yT <= Math.min(tb.yMax, gb.yMax); yT++) {
246
- //get tile
247
- /** @type {GridTile} */
248
- const tile = this.cache[xT][yT]
249
- if (!tile || typeof tile === 'string') continue
250
-
251
- //get cells
252
- //this.cellsViewCache = this.cellsViewCache.concat(tile.cells)
253
-
254
- for (const cell of tile.cells) {
255
- if (+cell.x + this.resolution < extGeo.xMin) continue
256
- if (+cell.x - this.resolution > extGeo.xMax) continue
257
- if (+cell.y + this.resolution < extGeo.yMin) continue
258
- if (+cell.y - this.resolution > extGeo.yMax) continue
259
- this.cellsViewCache.push(cell)
260
- }
261
- }
262
- }
263
- }
264
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ /** @typedef {{ dims: object, crs: string, tileSizeCell: number, originPoint: {x:number,y:number}, resolutionGeo: number, tilingBounds:import("../Dataset").Envelope, format:import("../DatasetComponent").Format }} GridInfo */
5
+
6
+ // internal
7
+ import { GridTile } from './GridTile.js'
8
+ import { App } from '../App.js'
9
+ import { DatasetComponent } from '../DatasetComponent.js'
10
+ import { monitor, monitorDuration } from '../utils/Utils.js'
11
+
12
+ // external
13
+ import { json, csv } from 'd3-fetch'
14
+
15
+ /**
16
+ * A tiled dataset, composed of CSV tiles.
17
+ *
18
+ * @author Joseph Davies, Julien Gaffuri
19
+ */
20
+ export class TiledGrid extends DatasetComponent {
21
+ /**
22
+ * @param {string} url The URL of the dataset.
23
+ * @param {App} app The application.
24
+ * @param {{preprocess?:(function(import("../Dataset").Cell):boolean) }} opts
25
+ */
26
+ constructor(url, app, opts = {}) {
27
+ super(url, 0, opts)
28
+
29
+ /**
30
+ * The app being used.
31
+ * @type {App}
32
+ */
33
+ this.app = app
34
+
35
+ /**
36
+ * The grid info object, from the info.json file.
37
+ * @type {GridInfo | undefined}
38
+ * @private
39
+ * */
40
+ this.info = undefined
41
+
42
+ /**
43
+ * @type {string}
44
+ * @private */
45
+ this.infoLoadingStatus = 'notLoaded'
46
+
47
+ /**
48
+ * The cache of the loaded tiles. It is double indexed: by xT and then yT.
49
+ * Example: this.cache[xT][yT] returns the tile at [xT][yT] location.
50
+ *
51
+ * @type {object}
52
+ * */
53
+ this.cache = {}
54
+
55
+ }
56
+
57
+ /**
58
+ * Load the info.json from the url.
59
+ *
60
+ * @param {function():void} callback
61
+ * @returns this
62
+ */
63
+ loadInfo(callback) {
64
+ if (!this.info && this.infoLoadingStatus === 'notLoaded') {
65
+ ; (async () => {
66
+ try {
67
+ const data = await json(this.url + 'info.json')
68
+ this.info = data
69
+ this.resolution = data.resolutionGeo
70
+ this.infoLoadingStatus = 'loaded'
71
+ if (callback) callback()
72
+ } catch (error) {
73
+ //mark as failed
74
+ this.infoLoadingStatus = 'failed'
75
+ }
76
+ })()
77
+ } else if (callback && (this.infoLoadingStatus === 'loaded' || this.infoLoadingStatus === 'failed'))
78
+ callback()
79
+ return this
80
+ }
81
+
82
+ /**
83
+ * Compute a tiling envelope from a geographical envelope.
84
+ * This is the function to use to know which tiles to download for a geographical view.
85
+ *
86
+ * @param {import("../Dataset").Envelope} e
87
+ * @returns {import("../Dataset").Envelope|undefined}
88
+ */
89
+ getTilingEnvelope(e) {
90
+ if (!this.info) {
91
+ this.loadInfo(() => { })
92
+ return
93
+ }
94
+
95
+ const po = this.info.originPoint,
96
+ r = this.info.resolutionGeo,
97
+ s = this.info.tileSizeCell
98
+
99
+ return {
100
+ xMin: Math.floor((e.xMin - po.x) / (r * s)),
101
+ xMax: Math.floor((e.xMax - po.x) / (r * s)),
102
+ yMin: Math.floor((e.yMin - po.y) / (r * s)),
103
+ yMax: Math.floor((e.yMax - po.y) / (r * s)),
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Request data within a geographic envelope.
109
+ *
110
+ * @param {import("../Dataset").Envelope} extGeo
111
+ * @param {function():void} redrawFun
112
+ * @returns {this}
113
+ */
114
+ getData(extGeo, redrawFun) {
115
+ //TODO empty cache when it gets too big ?
116
+
117
+ //check if info has been loaded
118
+ if (!this.info) return this
119
+
120
+ //tiles within the scope
121
+ /** @type {import("../Dataset").Envelope|undefined} */
122
+ const tb = this.getTilingEnvelope(extGeo)
123
+ if (!tb) return this
124
+
125
+ //grid bounds
126
+ /** @type {import("../Dataset").Envelope} */
127
+ const gb = this.info.tilingBounds
128
+
129
+ for (let xT = Math.max(tb.xMin, gb.xMin); xT <= Math.min(tb.xMax, gb.xMax); xT++) {
130
+ for (let yT = Math.max(tb.yMin, gb.yMin); yT <= Math.min(tb.yMax, gb.yMax); yT++) {
131
+ //prepare cache
132
+ if (!this.cache[xT]) this.cache[xT] = {}
133
+
134
+ //check if tile exists in the cache
135
+ /** @type {GridTile} */
136
+ let tile = this.cache[xT][yT]
137
+ if (tile) continue
138
+
139
+ //mark tile as loading
140
+ this.cache[xT][yT] = "loading";
141
+ (async () => {
142
+ //request tile
143
+ /** @type {Array.<import("../Dataset").Cell>} */
144
+ let cells
145
+
146
+ try {
147
+ /** @type {Array.<import("../Dataset").Cell>} */
148
+ // @ts-ignore
149
+ const data = await csv(this.url + xT + '/' + yT + '.csv')
150
+
151
+ //if (monitor) monitorDuration('*** TiledGrid parse start')
152
+
153
+ //preprocess/filter
154
+ if (this.preprocess) {
155
+ cells = []
156
+ for (const c of data) {
157
+ const b = this.preprocess(c)
158
+ if (b == false) continue
159
+ cells.push(c)
160
+ }
161
+ } else {
162
+ cells = data
163
+ }
164
+
165
+ //if (monitor) monitorDuration('preprocess / filter')
166
+ } catch (error) {
167
+ //mark as failed
168
+ this.cache[xT][yT] = 'failed'
169
+ return
170
+ }
171
+
172
+ //store tile in cache
173
+ if (!this.info) {
174
+ console.error('Tile info inknown')
175
+ return
176
+ }
177
+ const tile_ = new GridTile(cells, xT, yT, this.info)
178
+ this.cache[xT][yT] = tile_
179
+
180
+ //if (monitor) monitorDuration('storage')
181
+
182
+ //if no redraw is specified, then leave
183
+ if (!redrawFun) return
184
+
185
+ //check if redraw is really needed, that is if:
186
+
187
+ // 1. the dataset belongs to a layer which is visible at the current zoom level
188
+ let redraw = false
189
+ //go through the layers
190
+ const zf = this.app.getZoomFactor()
191
+ for (const lay of this.app.layers) {
192
+ if (!lay.visible) continue
193
+ if (lay.getDatasetComponent(zf) != this) continue
194
+ //found one layer. No need to seek more.
195
+ redraw = true
196
+ break
197
+ }
198
+ //if (monitor) monitorDuration('check redraw 1')
199
+
200
+ if (!redraw) return
201
+
202
+ // 2. the tile is within the view, that is its geo envelope intersects the viewer geo envelope.
203
+ const env = this.app.updateExtentGeo()
204
+ const envT = tile_.extGeo
205
+ if (env.xMax <= envT.xMin) return
206
+ if (env.xMin >= envT.xMax) return
207
+ if (env.yMax <= envT.yMin) return
208
+ if (env.yMin >= envT.yMax) return
209
+
210
+ //if (monitor) monitorDuration('check redraw 2')
211
+ //if (monitor) monitorDuration('*** TiledGrid parse end')
212
+
213
+ //redraw
214
+ redrawFun()
215
+ })()
216
+ }
217
+ }
218
+ return this
219
+ }
220
+
221
+ /**
222
+ * Fill the view cache with all cells which are within a geographical envelope.
223
+ * @abstract
224
+ * @param {import("../Dataset").Envelope} extGeo
225
+ * @returns {void}
226
+ */
227
+ updateViewCache(extGeo) {
228
+ //
229
+ this.cellsViewCache = []
230
+
231
+ //check if info has been loaded
232
+ if (!this.info) return
233
+
234
+ //tiles within the scope
235
+ /** @type {import("../Dataset").Envelope|undefined} */
236
+ const tb = this.getTilingEnvelope(extGeo)
237
+ if (!tb) return
238
+
239
+ //grid bounds
240
+ /** @type {import("../Dataset").Envelope} */
241
+ const gb = this.info.tilingBounds
242
+
243
+ for (let xT = Math.max(tb.xMin, gb.xMin); xT <= Math.min(tb.xMax, gb.xMax); xT++) {
244
+ if (!this.cache[xT]) continue
245
+ for (let yT = Math.max(tb.yMin, gb.yMin); yT <= Math.min(tb.yMax, gb.yMax); yT++) {
246
+ //get tile
247
+ /** @type {GridTile} */
248
+ const tile = this.cache[xT][yT]
249
+ if (!tile || typeof tile === 'string') continue
250
+
251
+ //get cells
252
+ //this.cellsViewCache = this.cellsViewCache.concat(tile.cells)
253
+
254
+ for (const cell of tile.cells) {
255
+ if (+cell.x + this.resolution < extGeo.xMin) continue
256
+ if (+cell.x - this.resolution > extGeo.xMax) continue
257
+ if (+cell.y + this.resolution < extGeo.yMin) continue
258
+ if (+cell.y - this.resolution > extGeo.yMax) continue
259
+ this.cellsViewCache.push(cell)
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }