gridviz 2.1.13 → 2.1.14

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 +124 -125
  2. package/dist/gridviz.js +8341 -8339
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +77 -77
  5. package/src/App.js +758 -758
  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 +131 -129
  16. package/src/Tooltip.js +180 -180
  17. package/src/button/Button.js +54 -54
  18. package/src/button/FullscreenButton.js +98 -98
  19. package/src/button/ZoomButtons.js +72 -72
  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 -128
  30. package/src/legend/SegmentOrientationLegend.js +87 -87
  31. package/src/legend/SegmentWidthLegend.js +101 -101
  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 -152
  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 -259
  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,216 +1,216 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../Style.js'
5
-
6
- /** @typedef {{x:number,y:number,or:"v"|"h",value:number}} Side */
7
-
8
- /**
9
- *
10
- * @author Julien Gaffuri
11
- */
12
- export class SideStyle extends Style {
13
- /** @param {object} opts */
14
- constructor(opts) {
15
- super(opts)
16
- opts = opts || {}
17
-
18
- /** The name of the column/attribute of the tabular data where to retrieve the variable for the cell values.
19
- * @type {string} */
20
- this.valueCol = opts.valueCol
21
-
22
- /** A function returning the value of a cell side. This value is computed from the two adjacent cell values.
23
- * For horizontal sides, v1 is the value of the cell below and v2 the value of the cell above.
24
- * For vertical sides, v1 is the value of the cell left and v2 the value of the cell right.
25
- * @type {function(number|undefined,number|undefined,number,import("../Style").Stat|undefined,number):number} */
26
- this.value = opts.value || ((v1, v2, r, s, zf) => 1)
27
-
28
- /** A function returning the color of a cell side.
29
- * @type {function(Side,number,import("../Style").Stat|undefined,number):string} */
30
- this.color = opts.color || (() => '#EA6BAC')
31
-
32
- /** A function returning the width of a cell side, in geo unit
33
- * @type {function(Side,number,import("../Style").Stat|undefined,number):number} */
34
- this.width = opts.width || ((side, r, s, zf) => (r * side.value) / 5)
35
-
36
- /** orientation. Set to 90 to show sides as slope lines for example.
37
- * @type {number} */
38
- this.orientation = opts.orientation || 0
39
-
40
- /** A fill color for the cells.
41
- * @type {function(import("../Dataset").Cell):string} */
42
- this.fillColor = opts.fillColor
43
- }
44
-
45
- /**
46
- * @param {Array.<import("../Dataset").Cell>} cells
47
- * @param {number} r
48
- * @param {import("../GeoCanvas").GeoCanvas} cg
49
- */
50
- draw(cells, r, cg) {
51
- //filter
52
- if (this.filter) cells = cells.filter(this.filter)
53
-
54
- //zoom factor
55
- const zf = cg.getZf()
56
-
57
- //compute stats on cell values
58
- let statValue
59
- if (this.valueCol) {
60
- //compute color variable statistics
61
- statValue = Style.getStatistics(cells, (c) => c[this.valueCol], true)
62
- }
63
-
64
- /** @type {Array.<Side>} */
65
- const sides = []
66
-
67
- //make horizontal sides
68
- //sort cells by x and y
69
- cells.sort((c1, c2) => (c2.x == c1.x ? c1.y - c2.y : c1.x - c2.x))
70
- let c1 = cells[0]
71
- for (let i = 1; i < cells.length; i++) {
72
- let c2 = cells[i]
73
-
74
- if ((c1.y + r == c2.y) && (c1.x == c2.x))
75
- //cells in same column and touch along horizontal side
76
- //make shared side
77
- sides.push({
78
- x: c1.x,
79
- y: c2.y,
80
- or: 'h',
81
- value: this.value(c1[this.valueCol], c2[this.valueCol], r, statValue, zf),
82
- })
83
- else {
84
- //cells do not touch along horizontal side
85
- //make two sides: top one for c1, bottom for c2
86
- sides.push({
87
- x: c1.x,
88
- y: c1.y + r,
89
- or: 'h',
90
- value: this.value(c1[this.valueCol], undefined, r, statValue, zf),
91
- })
92
- sides.push({
93
- x: c2.x,
94
- y: c2.y,
95
- or: 'h',
96
- value: this.value(undefined, c2[this.valueCol], r, statValue, zf),
97
- })
98
- }
99
-
100
- c1 = c2
101
- }
102
-
103
- //make vertical sides
104
- //sort cells by y and x
105
- cells.sort((c1, c2) => (c2.y == c1.y ? c1.x - c2.x : c1.y - c2.y))
106
- c1 = cells[0]
107
- for (let i = 1; i < cells.length; i++) {
108
- let c2 = cells[i]
109
-
110
- if ((c1.x + r == c2.x) && (c1.y == c2.y))
111
- //cells in same row and touch along vertical side
112
- //make shared side
113
- sides.push({
114
- x: c1.x + r,
115
- y: c1.y,
116
- or: 'v',
117
- value: this.value(c1[this.valueCol], c2[this.valueCol], r, statValue, zf),
118
- })
119
- else {
120
- //cells do not touch along vertical side
121
- //make two sides: right one for c1, left for c2
122
- sides.push({
123
- x: c1.x + r,
124
- y: c1.y,
125
- or: 'v',
126
- value: this.value(c1[this.valueCol], undefined, r, statValue, zf),
127
- })
128
- sides.push({
129
- x: c2.x,
130
- y: c2.y,
131
- or: 'v',
132
- value: this.value(undefined, c2[this.valueCol], r, statValue, zf),
133
- })
134
- }
135
-
136
- c1 = c2
137
- }
138
-
139
- //
140
- if (sides.length == 0) return
141
-
142
- //compute stats on sides
143
- const statSides = SideStyle.getSideStatistics(sides, true)
144
-
145
- //draw in geo coordinates
146
- cg.setCanvasTransform()
147
-
148
- //draw cells, if fillColor specified
149
- if (this.fillColor)
150
- for (let c of cells) {
151
- const fc = this.fillColor(c)
152
- if (!fc || fc == 'none') continue
153
- cg.ctx.fillStyle = fc
154
- cg.ctx.fillRect(c.x, c.y, r, r)
155
- }
156
-
157
- //draw sides
158
- cg.ctx.lineCap = 'butt'
159
- const r2 = r / 2
160
- for (let s of sides) {
161
- //color
162
- /** @type {string|undefined} */
163
- const col = this.color ? this.color(s, r, statSides, zf) : undefined
164
- if (!col || col == 'none') continue
165
-
166
- //width
167
- /** @type {number|undefined} */
168
- const wG = this.width ? this.width(s, r, statSides, zf) : undefined
169
- if (!wG || wG <= 0) continue
170
-
171
- //set color and width
172
- cg.ctx.strokeStyle = col
173
- cg.ctx.lineWidth = wG
174
-
175
- //draw segment with correct orientation
176
- cg.ctx.beginPath()
177
- if (this.orientation == 90) {
178
- cg.ctx.moveTo(s.x + r2, s.y + r2)
179
- if (s.or === 'h') cg.ctx.lineTo(s.x + r2, s.y - r2)
180
- else cg.ctx.lineTo(s.x - r2, s.y + r2)
181
- } else {
182
- cg.ctx.moveTo(s.x, s.y)
183
- cg.ctx.lineTo(s.x + (s.or === 'h' ? r : 0), s.y + (s.or === 'v' ? r : 0))
184
- }
185
- cg.ctx.stroke()
186
- }
187
-
188
- //update legends
189
- this.updateLegends({ style: this, r: r, zf: zf })
190
- }
191
-
192
- /**
193
- * Compute some statistics on a value of some sides.
194
- * This is used to define how to draw specifically the sides within the view.
195
- *
196
- * @param {Array.<Side>} sides
197
- * @param {boolean} ignoreZeros
198
- * @returns {import("../Style").Stat | undefined}
199
- */
200
- static getSideStatistics(sides, ignoreZeros) {
201
- if (!sides || sides.length == 0) return undefined
202
- let min = Infinity
203
- let max = -Infinity
204
- //let sum = 0
205
- //let nb = 0
206
- for (const s of sides) {
207
- const v = s.value
208
- if (ignoreZeros && !v) continue
209
- if (v < min) min = v
210
- if (v > max) max = v
211
- //sum += v
212
- //nb++
213
- }
214
- return { min: min, max: max }
215
- }
216
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../Style.js'
5
+
6
+ /** @typedef {{x:number,y:number,or:"v"|"h",value:number}} Side */
7
+
8
+ /**
9
+ *
10
+ * @author Julien Gaffuri
11
+ */
12
+ export class SideStyle extends Style {
13
+ /** @param {object} opts */
14
+ constructor(opts) {
15
+ super(opts)
16
+ opts = opts || {}
17
+
18
+ /** The name of the column/attribute of the tabular data where to retrieve the variable for the cell values.
19
+ * @type {string} */
20
+ this.valueCol = opts.valueCol
21
+
22
+ /** A function returning the value of a cell side. This value is computed from the two adjacent cell values.
23
+ * For horizontal sides, v1 is the value of the cell below and v2 the value of the cell above.
24
+ * For vertical sides, v1 is the value of the cell left and v2 the value of the cell right.
25
+ * @type {function(number|undefined,number|undefined,number,import("../Style").Stat|undefined,number):number} */
26
+ this.value = opts.value || ((v1, v2, r, s, zf) => 1)
27
+
28
+ /** A function returning the color of a cell side.
29
+ * @type {function(Side,number,import("../Style").Stat|undefined,number):string} */
30
+ this.color = opts.color || (() => '#EA6BAC')
31
+
32
+ /** A function returning the width of a cell side, in geo unit
33
+ * @type {function(Side,number,import("../Style").Stat|undefined,number):number} */
34
+ this.width = opts.width || ((side, r, s, zf) => (r * side.value) / 5)
35
+
36
+ /** orientation. Set to 90 to show sides as slope lines for example.
37
+ * @type {number} */
38
+ this.orientation = opts.orientation || 0
39
+
40
+ /** A fill color for the cells.
41
+ * @type {function(import("../Dataset").Cell):string} */
42
+ this.fillColor = opts.fillColor
43
+ }
44
+
45
+ /**
46
+ * @param {Array.<import("../Dataset").Cell>} cells
47
+ * @param {number} r
48
+ * @param {import("../GeoCanvas").GeoCanvas} cg
49
+ */
50
+ draw(cells, r, cg) {
51
+ //filter
52
+ if (this.filter) cells = cells.filter(this.filter)
53
+
54
+ //zoom factor
55
+ const zf = cg.getZf()
56
+
57
+ //compute stats on cell values
58
+ let statValue
59
+ if (this.valueCol) {
60
+ //compute color variable statistics
61
+ statValue = Style.getStatistics(cells, (c) => c[this.valueCol], true)
62
+ }
63
+
64
+ /** @type {Array.<Side>} */
65
+ const sides = []
66
+
67
+ //make horizontal sides
68
+ //sort cells by x and y
69
+ cells.sort((c1, c2) => (c2.x == c1.x ? c1.y - c2.y : c1.x - c2.x))
70
+ let c1 = cells[0]
71
+ for (let i = 1; i < cells.length; i++) {
72
+ let c2 = cells[i]
73
+
74
+ if ((c1.y + r == c2.y) && (c1.x == c2.x))
75
+ //cells in same column and touch along horizontal side
76
+ //make shared side
77
+ sides.push({
78
+ x: c1.x,
79
+ y: c2.y,
80
+ or: 'h',
81
+ value: this.value(c1[this.valueCol], c2[this.valueCol], r, statValue, zf),
82
+ })
83
+ else {
84
+ //cells do not touch along horizontal side
85
+ //make two sides: top one for c1, bottom for c2
86
+ sides.push({
87
+ x: c1.x,
88
+ y: c1.y + r,
89
+ or: 'h',
90
+ value: this.value(c1[this.valueCol], undefined, r, statValue, zf),
91
+ })
92
+ sides.push({
93
+ x: c2.x,
94
+ y: c2.y,
95
+ or: 'h',
96
+ value: this.value(undefined, c2[this.valueCol], r, statValue, zf),
97
+ })
98
+ }
99
+
100
+ c1 = c2
101
+ }
102
+
103
+ //make vertical sides
104
+ //sort cells by y and x
105
+ cells.sort((c1, c2) => (c2.y == c1.y ? c1.x - c2.x : c1.y - c2.y))
106
+ c1 = cells[0]
107
+ for (let i = 1; i < cells.length; i++) {
108
+ let c2 = cells[i]
109
+
110
+ if ((c1.x + r == c2.x) && (c1.y == c2.y))
111
+ //cells in same row and touch along vertical side
112
+ //make shared side
113
+ sides.push({
114
+ x: c1.x + r,
115
+ y: c1.y,
116
+ or: 'v',
117
+ value: this.value(c1[this.valueCol], c2[this.valueCol], r, statValue, zf),
118
+ })
119
+ else {
120
+ //cells do not touch along vertical side
121
+ //make two sides: right one for c1, left for c2
122
+ sides.push({
123
+ x: c1.x + r,
124
+ y: c1.y,
125
+ or: 'v',
126
+ value: this.value(c1[this.valueCol], undefined, r, statValue, zf),
127
+ })
128
+ sides.push({
129
+ x: c2.x,
130
+ y: c2.y,
131
+ or: 'v',
132
+ value: this.value(undefined, c2[this.valueCol], r, statValue, zf),
133
+ })
134
+ }
135
+
136
+ c1 = c2
137
+ }
138
+
139
+ //
140
+ if (sides.length == 0) return
141
+
142
+ //compute stats on sides
143
+ const statSides = SideStyle.getSideStatistics(sides, true)
144
+
145
+ //draw in geo coordinates
146
+ cg.setCanvasTransform()
147
+
148
+ //draw cells, if fillColor specified
149
+ if (this.fillColor)
150
+ for (let c of cells) {
151
+ const fc = this.fillColor(c)
152
+ if (!fc || fc == 'none') continue
153
+ cg.ctx.fillStyle = fc
154
+ cg.ctx.fillRect(c.x, c.y, r, r)
155
+ }
156
+
157
+ //draw sides
158
+ cg.ctx.lineCap = 'butt'
159
+ const r2 = r / 2
160
+ for (let s of sides) {
161
+ //color
162
+ /** @type {string|undefined} */
163
+ const col = this.color ? this.color(s, r, statSides, zf) : undefined
164
+ if (!col || col == 'none') continue
165
+
166
+ //width
167
+ /** @type {number|undefined} */
168
+ const wG = this.width ? this.width(s, r, statSides, zf) : undefined
169
+ if (!wG || wG <= 0) continue
170
+
171
+ //set color and width
172
+ cg.ctx.strokeStyle = col
173
+ cg.ctx.lineWidth = wG
174
+
175
+ //draw segment with correct orientation
176
+ cg.ctx.beginPath()
177
+ if (this.orientation == 90) {
178
+ cg.ctx.moveTo(s.x + r2, s.y + r2)
179
+ if (s.or === 'h') cg.ctx.lineTo(s.x + r2, s.y - r2)
180
+ else cg.ctx.lineTo(s.x - r2, s.y + r2)
181
+ } else {
182
+ cg.ctx.moveTo(s.x, s.y)
183
+ cg.ctx.lineTo(s.x + (s.or === 'h' ? r : 0), s.y + (s.or === 'v' ? r : 0))
184
+ }
185
+ cg.ctx.stroke()
186
+ }
187
+
188
+ //update legends
189
+ this.updateLegends({ style: this, r: r, zf: zf })
190
+ }
191
+
192
+ /**
193
+ * Compute some statistics on a value of some sides.
194
+ * This is used to define how to draw specifically the sides within the view.
195
+ *
196
+ * @param {Array.<Side>} sides
197
+ * @param {boolean} ignoreZeros
198
+ * @returns {import("../Style").Stat | undefined}
199
+ */
200
+ static getSideStatistics(sides, ignoreZeros) {
201
+ if (!sides || sides.length == 0) return undefined
202
+ let min = Infinity
203
+ let max = -Infinity
204
+ //let sum = 0
205
+ //let nb = 0
206
+ for (const s of sides) {
207
+ const v = s.value
208
+ if (ignoreZeros && !v) continue
209
+ if (v < min) min = v
210
+ if (v > max) max = v
211
+ //sum += v
212
+ //nb++
213
+ }
214
+ return { min: min, max: max }
215
+ }
216
+ }
@@ -1,120 +1,120 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../Style.js'
5
- import { makeWebGLCanvas } from '../utils/webGLUtils.js'
6
- import { WebGLSquareColoringCatAdvanced } from '../utils/WebGLSquareColoringCatAdvanced.js'
7
- import { monitor, monitorDuration } from '../utils/Utils.js'
8
-
9
- /**
10
- * Style based on webGL
11
- * To show cells as colored squares, from categories.
12
- * Alls squares with the same size
13
- *
14
- * @author Julien Gaffuri
15
- */
16
- export class SquareColorCatWGLStyle extends Style {
17
- /** @param {object} opts */
18
- constructor(opts) {
19
- super(opts)
20
- opts = opts || {}
21
-
22
- /**
23
- * The name of the column/attribute of the tabular data where to retrieve the category of the cell, for coloring.
24
- * @type {string} */
25
- this.colorCol = opts.colorCol
26
-
27
- /**
28
- * The dictionary (string -> color) which give the color of each category.
29
- * @type {object} */
30
- opts.color = opts.color || undefined
31
-
32
- /** @type { Array.<string> } @private */
33
- const keys = Object.keys(opts.color)
34
-
35
- /** @type { object } @private */
36
- this.catToI = {}
37
- for (let i = 0; i < keys.length; i++) this.catToI[keys[i]] = i + ''
38
-
39
- /** @type { Array.<string> } @private */
40
- this.colors = []
41
- for (let i = 0; i < keys.length; i++) {
42
- this.colors.push(opts.color['' + keys[i]])
43
- }
44
-
45
- /**
46
- * A function returning the size of the cells, in geographical unit. All cells have the same size.
47
- * @type {function(number,number):number} */
48
- this.size = opts.size // (resolution, zf) => ...
49
-
50
- /**
51
- * @private
52
- * @type { WebGLSquareColoringCatAdvanced } */
53
- this.wgp = new WebGLSquareColoringCatAdvanced(this.colors)
54
- }
55
-
56
- /**
57
- * @param {Array.<import("../Dataset").Cell>} cells
58
- * @param {number} r
59
- * @param {import("../GeoCanvas").GeoCanvas} cg
60
- */
61
- draw(cells, r, cg) {
62
- if (monitor) monitorDuration('*** SquareColorCatWGLStyle draw')
63
-
64
- //filter
65
- if (this.filter) cells = cells.filter(this.filter)
66
-
67
- //zoom factor
68
- const zf = cg.getZf()
69
-
70
- //add vertice and fragment data
71
- const r2 = r / 2
72
- let c,
73
- nb = cells.length
74
- const verticesBuffer = []
75
- const iBuffer = []
76
- for (let i = 0; i < nb; i++) {
77
- c = cells[i]
78
- const cat = c[this.colorCol]
79
- if (cat == undefined) {
80
- console.log('Unexpected category: ' + cat)
81
- continue
82
- }
83
- /** @type {number} */
84
- const i_ = this.catToI[cat]
85
- if (isNaN(+i_)) {
86
- console.log('Unexpected category index: ' + cat + ' ' + i_)
87
- continue
88
- }
89
- verticesBuffer.push(c.x + r2, c.y + r2)
90
- iBuffer.push(+i_)
91
- }
92
-
93
- if (monitor) monitorDuration(' webgl program inputs preparation')
94
-
95
- //create canvas and webgl renderer
96
- const cvWGL = makeWebGLCanvas(cg.w + '', cg.h + '')
97
- if (!cvWGL) {
98
- console.error('No webGL')
99
- return
100
- }
101
- if (monitor) monitorDuration(' web GL canvas creation')
102
-
103
- //draw
104
- const sizeGeo = this.size ? this.size(r, zf) : r + 0.2 * zf
105
- this.wgp.draw(cvWGL.gl, verticesBuffer, iBuffer, cg.getWebGLTransform(), sizeGeo / zf)
106
-
107
- if (monitor) monitorDuration(' webgl drawing')
108
-
109
- //draw in canvas geo
110
- cg.initCanvasTransform()
111
- cg.ctx.drawImage(cvWGL.canvas, 0, 0)
112
-
113
- if (monitor) monitorDuration(' canvas drawing')
114
-
115
- //update legends
116
- this.updateLegends({ style: this, r: r, zf: zf })
117
-
118
- if (monitor) monitorDuration('*** SquareColorCatWGLStyle end draw')
119
- }
120
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../Style.js'
5
+ import { makeWebGLCanvas } from '../utils/webGLUtils.js'
6
+ import { WebGLSquareColoringCatAdvanced } from '../utils/WebGLSquareColoringCatAdvanced.js'
7
+ import { monitor, monitorDuration } from '../utils/Utils.js'
8
+
9
+ /**
10
+ * Style based on webGL
11
+ * To show cells as colored squares, from categories.
12
+ * Alls squares with the same size
13
+ *
14
+ * @author Julien Gaffuri
15
+ */
16
+ export class SquareColorCatWGLStyle extends Style {
17
+ /** @param {object} opts */
18
+ constructor(opts) {
19
+ super(opts)
20
+ opts = opts || {}
21
+
22
+ /**
23
+ * The name of the column/attribute of the tabular data where to retrieve the category of the cell, for coloring.
24
+ * @type {string} */
25
+ this.colorCol = opts.colorCol
26
+
27
+ /**
28
+ * The dictionary (string -> color) which give the color of each category.
29
+ * @type {object} */
30
+ opts.color = opts.color || undefined
31
+
32
+ /** @type { Array.<string> } @private */
33
+ const keys = Object.keys(opts.color)
34
+
35
+ /** @type { object } @private */
36
+ this.catToI = {}
37
+ for (let i = 0; i < keys.length; i++) this.catToI[keys[i]] = i + ''
38
+
39
+ /** @type { Array.<string> } @private */
40
+ this.colors = []
41
+ for (let i = 0; i < keys.length; i++) {
42
+ this.colors.push(opts.color['' + keys[i]])
43
+ }
44
+
45
+ /**
46
+ * A function returning the size of the cells, in geographical unit. All cells have the same size.
47
+ * @type {function(number,number):number} */
48
+ this.size = opts.size // (resolution, zf) => ...
49
+
50
+ /**
51
+ * @private
52
+ * @type { WebGLSquareColoringCatAdvanced } */
53
+ this.wgp = new WebGLSquareColoringCatAdvanced(this.colors)
54
+ }
55
+
56
+ /**
57
+ * @param {Array.<import("../Dataset").Cell>} cells
58
+ * @param {number} r
59
+ * @param {import("../GeoCanvas").GeoCanvas} cg
60
+ */
61
+ draw(cells, r, cg) {
62
+ if (monitor) monitorDuration('*** SquareColorCatWGLStyle draw')
63
+
64
+ //filter
65
+ if (this.filter) cells = cells.filter(this.filter)
66
+
67
+ //zoom factor
68
+ const zf = cg.getZf()
69
+
70
+ //add vertice and fragment data
71
+ const r2 = r / 2
72
+ let c,
73
+ nb = cells.length
74
+ const verticesBuffer = []
75
+ const iBuffer = []
76
+ for (let i = 0; i < nb; i++) {
77
+ c = cells[i]
78
+ const cat = c[this.colorCol]
79
+ if (cat == undefined) {
80
+ console.log('Unexpected category: ' + cat)
81
+ continue
82
+ }
83
+ /** @type {number} */
84
+ const i_ = this.catToI[cat]
85
+ if (isNaN(+i_)) {
86
+ console.log('Unexpected category index: ' + cat + ' ' + i_)
87
+ continue
88
+ }
89
+ verticesBuffer.push(c.x + r2, c.y + r2)
90
+ iBuffer.push(+i_)
91
+ }
92
+
93
+ if (monitor) monitorDuration(' webgl program inputs preparation')
94
+
95
+ //create canvas and webgl renderer
96
+ const cvWGL = makeWebGLCanvas(cg.w + '', cg.h + '')
97
+ if (!cvWGL) {
98
+ console.error('No webGL')
99
+ return
100
+ }
101
+ if (monitor) monitorDuration(' web GL canvas creation')
102
+
103
+ //draw
104
+ const sizeGeo = this.size ? this.size(r, zf) : r + 0.2 * zf
105
+ this.wgp.draw(cvWGL.gl, verticesBuffer, iBuffer, cg.getWebGLTransform(), sizeGeo / zf)
106
+
107
+ if (monitor) monitorDuration(' webgl drawing')
108
+
109
+ //draw in canvas geo
110
+ cg.initCanvasTransform()
111
+ cg.ctx.drawImage(cvWGL.canvas, 0, 0)
112
+
113
+ if (monitor) monitorDuration(' canvas drawing')
114
+
115
+ //update legends
116
+ this.updateLegends({ style: this, r: r, zf: zf })
117
+
118
+ if (monitor) monitorDuration('*** SquareColorCatWGLStyle end draw')
119
+ }
120
+ }