gridviz 2.0.38 → 2.0.39

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 (58) hide show
  1. package/README.md +119 -119
  2. package/dist/gridviz.js +7488 -7530
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +78 -78
  5. package/src/App.js +698 -698
  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 +103 -103
  10. package/src/GeoCanvas.js +419 -419
  11. package/src/LabelLayer.js +190 -190
  12. package/src/Layer.js +92 -92
  13. package/src/Legend.js +86 -86
  14. package/src/LineLayer.js +150 -150
  15. package/src/Style.js +114 -114
  16. package/src/Tooltip.js +168 -168
  17. package/src/dataset/COGeo.js +24 -24
  18. package/src/dataset/CSVGrid.js +104 -104
  19. package/src/dataset/GeoTIFF.js +127 -127
  20. package/src/dataset/GridTile.js +41 -41
  21. package/src/dataset/ParquetGrid.js +122 -122
  22. package/src/dataset/TiledGrid.js +296 -296
  23. package/src/index.js +177 -177
  24. package/src/legend/ColorCategoryLegend.js +124 -124
  25. package/src/legend/ColorDiscreteLegend.js +105 -105
  26. package/src/legend/ColorLegend.js +125 -125
  27. package/src/legend/SegmentOrientationLegend.js +87 -87
  28. package/src/legend/SegmentWidthLegend.js +97 -97
  29. package/src/legend/SizeLegend.js +141 -141
  30. package/src/style/CompositionStyle.js +300 -300
  31. package/src/style/ContourStyle.js +54 -54
  32. package/src/style/DotDensityStyle.js +156 -156
  33. package/src/style/JoyPlotStyle.js +135 -135
  34. package/src/style/KernelSmoothingOldStyle.js +221 -221
  35. package/src/style/KernelSmoothingStyle.js +115 -115
  36. package/src/style/KernelSmoothingWGLStyle.js +130 -130
  37. package/src/style/LegoStyle.js +112 -112
  38. package/src/style/MosaicStyle.js +107 -107
  39. package/src/style/NinjaStarStyle.js +124 -124
  40. package/src/style/PillarStyle.js +230 -230
  41. package/src/style/SegmentStyle.js +142 -142
  42. package/src/style/ShapeColorSizeStyle.js +126 -126
  43. package/src/style/SideCatStyle.js +172 -172
  44. package/src/style/SideStyle.js +218 -218
  45. package/src/style/SquareColorCatWGLStyle.js +120 -120
  46. package/src/style/SquareColorWGLStyle.js +146 -146
  47. package/src/style/StrokeStyle.js +131 -131
  48. package/src/style/TanakaStyle.js +160 -160
  49. package/src/style/TextStyle.js +132 -132
  50. package/src/utils/Utils.js +35 -35
  51. package/src/utils/WebGLRectangleColoring.js +106 -106
  52. package/src/utils/WebGLSquareColoring.js +118 -118
  53. package/src/utils/WebGLSquareColoringAdvanced.js +230 -230
  54. package/src/utils/WebGLSquareColoringCatAdvanced.js +133 -133
  55. package/src/utils/WebGLSquareColoringKS.js +153 -153
  56. package/src/utils/stretching.js +131 -131
  57. package/src/utils/webGLUtils.js +71 -71
  58. package/src/utils/zoomUtils.js +142 -142
package/src/LabelLayer.js CHANGED
@@ -1,190 +1,190 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { csv } from 'd3-fetch'
5
-
6
- /** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
7
- * @typedef {{name: string, x:number, y:number }} Label */
8
-
9
- /**
10
- * A (generic) layer for placename labels, to be shown on top of the grid layers.
11
- * The input is a CSV file with the position (x, y) of the labels and name + some other info on the label importance.
12
- * If the label data is not in the expected format or in the same CRS as the grid, it can be corrected with the "preprocess" function.
13
- * The selection of the label, their style (font, weight, etc.) and color can be specified depending on their importance and the zoom level.
14
- *
15
- * @author Joseph Davies, Julien Gaffuri
16
- */
17
- export class LabelLayer {
18
- /**
19
- * @param {object} opts
20
- */
21
- constructor(opts) {
22
- opts = opts || {}
23
-
24
- /**
25
- * The URL of the label data, as CSV file.
26
- * The file should contain the information for each label such as the text, the position and other information for the display of the label according to the zoom level.
27
- * If necessary, this data can be reformated with the 'preprocess' parameter.
28
- * @private
29
- * @type {string} */
30
- this.url = opts.url
31
-
32
- /** Specify if and how a label should be drawn, depending on its importance and the zoom level.
33
- * @private
34
- * @type {function(Label,number):string} */
35
- this.style = opts.style || (() => 'bold 1em Arial')
36
-
37
- /** Specify the label color, depending on its importance and the zoom level.
38
- * @private
39
- * @type {function(Label,number):string} */
40
- this.color = opts.color || (opts.dark ? () => '#ddd' : () => '#222')
41
-
42
- /** Specify the label halo color, depending on its importance and the zoom level.
43
- * @private
44
- * @type {function(Label,number):string} */
45
- this.haloColor = opts.haloColor || (opts.dark ? () => '#000000BB' : () => '#FFFFFFBB')
46
-
47
- /** Specify the label halo width, depending on its importance and the zoom level.
48
- * @private
49
- * @type {function(Label,number):number} */
50
- this.haloWidth = opts.haloWidth || (() => 4)
51
-
52
- /** The anchor where to draw the text, from label position. See HTML-canvas textAlign property.
53
- * "left" || "right" || "center" || "start" || "end"
54
- * @private
55
- * @type {CanvasTextAlign} */
56
- this.textAlign = opts.textAlign || 'start'
57
-
58
- /**
59
- * @private
60
- * @type {Array.<number>} */
61
- this.offsetPix = opts.offsetPix || [5, 5]
62
-
63
- /**
64
- * A preprocess to run on each label after loading.
65
- * It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
66
- * Return false if the label should not be kept.
67
- * @private
68
- * @type {function(Label):boolean} */
69
- this.preprocess = opts.preprocess
70
-
71
- /**
72
- * @private
73
- * @type {Array.<Label> | undefined} */
74
- this.labels = undefined
75
-
76
- /**
77
- * @private
78
- * @type {string} */
79
- this.loadingStatus = 'notLoaded'
80
- }
81
-
82
- /**
83
- * Draw the label layer.
84
- *
85
- * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
86
- * @returns {void}
87
- */
88
- draw(cg) {
89
- //load labels, if not done yet.
90
- if (!this.labels) {
91
- this.load(cg.redraw)
92
- return
93
- }
94
-
95
- //zoom factor
96
- const zf = cg.getZf()
97
-
98
- //text align
99
- cg.ctx.textAlign = this.textAlign || 'start'
100
-
101
- //line join and cap
102
- cg.ctx.lineJoin = 'bevel' //|| "round" || "miter";
103
- cg.ctx.lineCap = 'butt' //|| "round" || "square";
104
-
105
- //draw in pix coordinates
106
- cg.initCanvasTransform()
107
-
108
- //draw labels, one by one
109
- for (const lb of this.labels) {
110
- //get label style
111
- const st = this.style(lb, zf)
112
- if (!st) continue
113
- cg.ctx.font = st
114
-
115
- //check label within the view, to be drawn
116
- if (!cg.toDraw(lb)) continue
117
-
118
- //position
119
- const xP = cg.geoToPixX(lb.x) + this.offsetPix[0]
120
- const yP = cg.geoToPixY(lb.y) - this.offsetPix[1]
121
-
122
- //label stroke, for the halo
123
- if (this.haloColor && this.haloWidth) {
124
- const hc = this.haloColor(lb, zf)
125
- const hw = this.haloWidth(lb, zf)
126
- if (hc && hw && hw > 0) {
127
- cg.ctx.strokeStyle = hc
128
- cg.ctx.lineWidth = hw
129
- cg.ctx.strokeText(lb.name, xP, yP)
130
- }
131
- }
132
-
133
- //label fill
134
- if (this.color) {
135
- const col = this.color(lb, zf)
136
- if (col) {
137
- cg.ctx.fillStyle = col
138
- cg.ctx.fillText(lb.name, xP, yP)
139
- }
140
- }
141
- }
142
- }
143
-
144
- /**
145
- * Load data for labels, from URL this.url
146
- * @param {function():void} callback
147
- * @private
148
- */
149
- async load(callback) {
150
- if (!this.url) {
151
- console.log('Failed loading labels: No URL specified. ' + this.url)
152
- this.loadingStatus = 'failed'
153
- this.labels = []
154
- return
155
- }
156
-
157
- //check if data already loaded
158
- if (this.loadingStatus != 'notLoaded') return
159
-
160
- //load data
161
- this.loadingStatus = 'loading'
162
-
163
- try {
164
- /** @type { Array.<Label> } */
165
- const data = await csv(this.url)
166
-
167
- //preprocess/filter
168
- if (this.preprocess) {
169
- this.labels = []
170
- for (const c of data) {
171
- const b = this.preprocess(c)
172
- if (b == false) continue
173
- this.labels.push(c)
174
- }
175
- } else {
176
- //store labels
177
- this.labels = data
178
- }
179
-
180
- this.loadingStatus = 'loaded'
181
-
182
- //redraw
183
- if (callback) callback()
184
- } catch (error) {
185
- console.log('Failed loading labels from ' + this.url)
186
- this.labels = []
187
- this.loadingStatus = 'failed'
188
- }
189
- }
190
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { csv } from 'd3-fetch'
5
+
6
+ /** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
7
+ * @typedef {{name: string, x:number, y:number }} Label */
8
+
9
+ /**
10
+ * A (generic) layer for placename labels, to be shown on top of the grid layers.
11
+ * The input is a CSV file with the position (x, y) of the labels and name + some other info on the label importance.
12
+ * If the label data is not in the expected format or in the same CRS as the grid, it can be corrected with the "preprocess" function.
13
+ * The selection of the label, their style (font, weight, etc.) and color can be specified depending on their importance and the zoom level.
14
+ *
15
+ * @author Joseph Davies, Julien Gaffuri
16
+ */
17
+ export class LabelLayer {
18
+ /**
19
+ * @param {object} opts
20
+ */
21
+ constructor(opts) {
22
+ opts = opts || {}
23
+
24
+ /**
25
+ * The URL of the label data, as CSV file.
26
+ * The file should contain the information for each label such as the text, the position and other information for the display of the label according to the zoom level.
27
+ * If necessary, this data can be reformated with the 'preprocess' parameter.
28
+ * @private
29
+ * @type {string} */
30
+ this.url = opts.url
31
+
32
+ /** Specify if and how a label should be drawn, depending on its importance and the zoom level.
33
+ * @private
34
+ * @type {function(Label,number):string} */
35
+ this.style = opts.style || (() => 'bold 1em Arial')
36
+
37
+ /** Specify the label color, depending on its importance and the zoom level.
38
+ * @private
39
+ * @type {function(Label,number):string} */
40
+ this.color = opts.color || (opts.dark ? () => '#ddd' : () => '#222')
41
+
42
+ /** Specify the label halo color, depending on its importance and the zoom level.
43
+ * @private
44
+ * @type {function(Label,number):string} */
45
+ this.haloColor = opts.haloColor || (opts.dark ? () => '#000000BB' : () => '#FFFFFFBB')
46
+
47
+ /** Specify the label halo width, depending on its importance and the zoom level.
48
+ * @private
49
+ * @type {function(Label,number):number} */
50
+ this.haloWidth = opts.haloWidth || (() => 4)
51
+
52
+ /** The anchor where to draw the text, from label position. See HTML-canvas textAlign property.
53
+ * "left" || "right" || "center" || "start" || "end"
54
+ * @private
55
+ * @type {CanvasTextAlign} */
56
+ this.textAlign = opts.textAlign || 'start'
57
+
58
+ /**
59
+ * @private
60
+ * @type {Array.<number>} */
61
+ this.offsetPix = opts.offsetPix || [5, 5]
62
+
63
+ /**
64
+ * A preprocess to run on each label after loading.
65
+ * It can be used to apply some specific treatment before, format the label data, project coordinates, etc.
66
+ * Return false if the label should not be kept.
67
+ * @private
68
+ * @type {function(Label):boolean} */
69
+ this.preprocess = opts.preprocess
70
+
71
+ /**
72
+ * @private
73
+ * @type {Array.<Label> | undefined} */
74
+ this.labels = undefined
75
+
76
+ /**
77
+ * @private
78
+ * @type {string} */
79
+ this.loadingStatus = 'notLoaded'
80
+ }
81
+
82
+ /**
83
+ * Draw the label layer.
84
+ *
85
+ * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
86
+ * @returns {void}
87
+ */
88
+ draw(cg) {
89
+ //load labels, if not done yet.
90
+ if (!this.labels) {
91
+ this.load(cg.redraw)
92
+ return
93
+ }
94
+
95
+ //zoom factor
96
+ const zf = cg.getZf()
97
+
98
+ //text align
99
+ cg.ctx.textAlign = this.textAlign || 'start'
100
+
101
+ //line join and cap
102
+ cg.ctx.lineJoin = 'bevel' //|| "round" || "miter";
103
+ cg.ctx.lineCap = 'butt' //|| "round" || "square";
104
+
105
+ //draw in pix coordinates
106
+ cg.initCanvasTransform()
107
+
108
+ //draw labels, one by one
109
+ for (const lb of this.labels) {
110
+ //get label style
111
+ const st = this.style(lb, zf)
112
+ if (!st) continue
113
+ cg.ctx.font = st
114
+
115
+ //check label within the view, to be drawn
116
+ if (!cg.toDraw(lb)) continue
117
+
118
+ //position
119
+ const xP = cg.geoToPixX(lb.x) + this.offsetPix[0]
120
+ const yP = cg.geoToPixY(lb.y) - this.offsetPix[1]
121
+
122
+ //label stroke, for the halo
123
+ if (this.haloColor && this.haloWidth) {
124
+ const hc = this.haloColor(lb, zf)
125
+ const hw = this.haloWidth(lb, zf)
126
+ if (hc && hw && hw > 0) {
127
+ cg.ctx.strokeStyle = hc
128
+ cg.ctx.lineWidth = hw
129
+ cg.ctx.strokeText(lb.name, xP, yP)
130
+ }
131
+ }
132
+
133
+ //label fill
134
+ if (this.color) {
135
+ const col = this.color(lb, zf)
136
+ if (col) {
137
+ cg.ctx.fillStyle = col
138
+ cg.ctx.fillText(lb.name, xP, yP)
139
+ }
140
+ }
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Load data for labels, from URL this.url
146
+ * @param {function():void} callback
147
+ * @private
148
+ */
149
+ async load(callback) {
150
+ if (!this.url) {
151
+ console.log('Failed loading labels: No URL specified. ' + this.url)
152
+ this.loadingStatus = 'failed'
153
+ this.labels = []
154
+ return
155
+ }
156
+
157
+ //check if data already loaded
158
+ if (this.loadingStatus != 'notLoaded') return
159
+
160
+ //load data
161
+ this.loadingStatus = 'loading'
162
+
163
+ try {
164
+ /** @type { Array.<Label> } */
165
+ const data = await csv(this.url)
166
+
167
+ //preprocess/filter
168
+ if (this.preprocess) {
169
+ this.labels = []
170
+ for (const c of data) {
171
+ const b = this.preprocess(c)
172
+ if (b == false) continue
173
+ this.labels.push(c)
174
+ }
175
+ } else {
176
+ //store labels
177
+ this.labels = data
178
+ }
179
+
180
+ this.loadingStatus = 'loaded'
181
+
182
+ //redraw
183
+ if (callback) callback()
184
+ } catch (error) {
185
+ console.log('Failed loading labels from ' + this.url)
186
+ this.labels = []
187
+ this.loadingStatus = 'failed'
188
+ }
189
+ }
190
+ }
package/src/Layer.js CHANGED
@@ -1,92 +1,92 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- /**
5
- * A layer, which specifies a dataset to be shown with specified styles.
6
- *
7
- * @author Joseph Davies, Julien Gaffuri
8
- */
9
- export class Layer {
10
- /**
11
- * @param {import("./Dataset").Dataset} dataset The multi resolution dataset to show.
12
- * @param {Array.<import("./Style").Style>} styles The styles, ordered in drawing order.
13
- * @param {{visible?:boolean,minZoom?:number,maxZoom?:number,pixNb?:number,cellInfoHTML?:function(import("./Dataset").Cell):string}} opts
14
- * minZoom: The minimum zoom level when to show the layer. maxZoom: The maximum zoom level when to show the layer
15
- */
16
- constructor(dataset, styles, opts = {}) {
17
- opts = opts || {}
18
-
19
- /** @type {import("./Dataset").Dataset} */
20
- this.dataset = dataset
21
- /** @type {Array.<import("./Style").Style>} */
22
- this.styles = styles
23
-
24
- /** An attribute to specify if a layer should be drawn or not
25
- * @type {boolean} */
26
- this.visible = opts.visible == false ? false : true
27
-
28
- /** The minimum zoom factor: Below this level, the layer is not shown.
29
- * @type {number} */
30
- this.minZoom = opts.minZoom || 0
31
-
32
- /** The maximum zoom factor: Above this level, the layer is not shown.
33
- * @type {number} */
34
- this.maxZoom = opts.maxZoom || Infinity
35
-
36
- //ensure acceptable values for the zoom limits.
37
- if (this.minZoom >= this.maxZoom)
38
- throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
39
-
40
- /** Unit: number of pixels
41
- * @type {number} */
42
- this.pixNb = opts.pixNb || 3
43
-
44
- /**
45
- * The function returning cell information as HTML.
46
- * This is typically used for tooltip information.
47
- * @type {function(import("./Dataset").Cell, number):string} */
48
- this.cellInfoHTML = opts.cellInfoHTML || Layer.defaultCellInfoHTML
49
- }
50
-
51
- /**
52
- * Return the relevant dataset component for a specified zoom factor.
53
- *
54
- * @param {number} zf
55
- * @returns {import("./DatasetComponent").DatasetComponent|undefined}
56
- * */
57
- getDatasetComponent(zf) {
58
- if (zf < this.minZoom || zf > this.maxZoom) return
59
-
60
- //special case whith single component dataset
61
- if (this.dataset.datasetComponents.length == 1) return this.dataset.datasetComponents[0]
62
-
63
- const rs = this.dataset.resolutions
64
- let i = 0
65
- let z = rs[i] / this.pixNb
66
- while (z < zf && i < rs.length) {
67
- i++
68
- z = rs[i] / this.pixNb
69
- }
70
- //if (i == 0) return this.dataset.datasetComponents[0];
71
- //return this.dataset.datasetComponents[i - 1];
72
- if (i == rs.length) return this.dataset.datasetComponents[rs.length - 1]
73
- return this.dataset.datasetComponents[i]
74
- }
75
-
76
- /**
77
- * The default function returning cell information as HTML.
78
- * This is typically used for tooltip information.
79
- *
80
- * @param {import("./Dataset").Cell} cell
81
- * @returns {string}
82
- */
83
- static defaultCellInfoHTML(cell) {
84
- const buf = []
85
- for (const key of Object.keys(cell)) {
86
- if (key === 'x') continue
87
- if (key === 'y') continue
88
- buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
89
- }
90
- return buf.join('')
91
- }
92
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ /**
5
+ * A layer, which specifies a dataset to be shown with specified styles.
6
+ *
7
+ * @author Joseph Davies, Julien Gaffuri
8
+ */
9
+ export class Layer {
10
+ /**
11
+ * @param {import("./Dataset").Dataset} dataset The multi resolution dataset to show.
12
+ * @param {Array.<import("./Style").Style>} styles The styles, ordered in drawing order.
13
+ * @param {{visible?:boolean,minZoom?:number,maxZoom?:number,pixNb?:number,cellInfoHTML?:function(import("./Dataset").Cell):string}} opts
14
+ * minZoom: The minimum zoom level when to show the layer. maxZoom: The maximum zoom level when to show the layer
15
+ */
16
+ constructor(dataset, styles, opts = {}) {
17
+ opts = opts || {}
18
+
19
+ /** @type {import("./Dataset").Dataset} */
20
+ this.dataset = dataset
21
+ /** @type {Array.<import("./Style").Style>} */
22
+ this.styles = styles
23
+
24
+ /** An attribute to specify if a layer should be drawn or not
25
+ * @type {boolean} */
26
+ this.visible = opts.visible == false ? false : true
27
+
28
+ /** The minimum zoom factor: Below this level, the layer is not shown.
29
+ * @type {number} */
30
+ this.minZoom = opts.minZoom || 0
31
+
32
+ /** The maximum zoom factor: Above this level, the layer is not shown.
33
+ * @type {number} */
34
+ this.maxZoom = opts.maxZoom || Infinity
35
+
36
+ //ensure acceptable values for the zoom limits.
37
+ if (this.minZoom >= this.maxZoom)
38
+ throw new Error('Unexpected zoom limits for layer. Zoom min should be smaller than zoom max.')
39
+
40
+ /** Unit: number of pixels
41
+ * @type {number} */
42
+ this.pixNb = opts.pixNb || 3
43
+
44
+ /**
45
+ * The function returning cell information as HTML.
46
+ * This is typically used for tooltip information.
47
+ * @type {function(import("./Dataset").Cell, number):string} */
48
+ this.cellInfoHTML = opts.cellInfoHTML || Layer.defaultCellInfoHTML
49
+ }
50
+
51
+ /**
52
+ * Return the relevant dataset component for a specified zoom factor.
53
+ *
54
+ * @param {number} zf
55
+ * @returns {import("./DatasetComponent").DatasetComponent|undefined}
56
+ * */
57
+ getDatasetComponent(zf) {
58
+ if (zf < this.minZoom || zf > this.maxZoom) return
59
+
60
+ //special case whith single component dataset
61
+ if (this.dataset.datasetComponents.length == 1) return this.dataset.datasetComponents[0]
62
+
63
+ const rs = this.dataset.resolutions
64
+ let i = 0
65
+ let z = rs[i] / this.pixNb
66
+ while (z < zf && i < rs.length) {
67
+ i++
68
+ z = rs[i] / this.pixNb
69
+ }
70
+ //if (i == 0) return this.dataset.datasetComponents[0];
71
+ //return this.dataset.datasetComponents[i - 1];
72
+ if (i == rs.length) return this.dataset.datasetComponents[rs.length - 1]
73
+ return this.dataset.datasetComponents[i]
74
+ }
75
+
76
+ /**
77
+ * The default function returning cell information as HTML.
78
+ * This is typically used for tooltip information.
79
+ *
80
+ * @param {import("./Dataset").Cell} cell
81
+ * @returns {string}
82
+ */
83
+ static defaultCellInfoHTML(cell) {
84
+ const buf = []
85
+ for (const key of Object.keys(cell)) {
86
+ if (key === 'x') continue
87
+ if (key === 'y') continue
88
+ buf.push('<b>', key, '</b>', ' : ', cell[key], '<br>')
89
+ }
90
+ return buf.join('')
91
+ }
92
+ }