gridviz 3.0.35 → 3.0.37

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 (67) hide show
  1. package/README.md +129 -129
  2. package/dist/gridviz.js +21056 -17487
  3. package/dist/gridviz.min.js +2 -2
  4. package/package.json +74 -74
  5. package/src/button/Button.js +67 -67
  6. package/src/button/FullscreenButton.js +121 -121
  7. package/src/button/ZoomButtons.js +103 -103
  8. package/src/core/Dataset.js +232 -154
  9. package/src/core/Drawable.js +78 -78
  10. package/src/core/GeoCanvas.js +443 -443
  11. package/src/core/Layer.js +23 -23
  12. package/src/core/Legend.js +108 -108
  13. package/src/core/Map.js +650 -568
  14. package/src/core/MultiResolutionDataset.js +93 -93
  15. package/src/core/Style.js +98 -98
  16. package/src/core/Tooltip.js +182 -182
  17. package/src/dataset/COGeo.js +25 -25
  18. package/src/dataset/CSVGrid.js +112 -112
  19. package/src/dataset/GeoTIFF.js +122 -122
  20. package/src/dataset/JSGrid.js +55 -55
  21. package/src/dataset/TiledGrid.js +311 -302
  22. package/src/dataset/worker.js +18 -18
  23. package/src/index.js +79 -79
  24. package/src/layer/BackgroundLayer.js +173 -173
  25. package/src/layer/BackgroundLayerImage.js +81 -81
  26. package/src/layer/BackgroundLayerWMS.js +104 -104
  27. package/src/layer/GeoJSONLayer.js +276 -276
  28. package/src/layer/GridLayer.js +166 -166
  29. package/src/layer/LabelLayer.js +194 -194
  30. package/src/legend/ColorCategoryLegend.js +109 -109
  31. package/src/legend/ColorDiscreteLegend.js +100 -100
  32. package/src/legend/ColorLegend.js +115 -115
  33. package/src/legend/OrientationLegend.js +89 -89
  34. package/src/legend/SizeLegend.js +224 -224
  35. package/src/legend/TernaryLegend.js +302 -302
  36. package/src/style/CompositionStyle.js +291 -291
  37. package/src/style/DotDensityStyle.js +133 -133
  38. package/src/style/ImageStyle.js +100 -100
  39. package/src/style/Interpolator.js +258 -258
  40. package/src/style/IsoFenceStyle.js +217 -217
  41. package/src/style/JoyPlotStyle.js +180 -180
  42. package/src/style/LegoStyle.js +132 -132
  43. package/src/style/MosaicStyle.js +99 -99
  44. package/src/style/NinjaStarStyle.js +102 -102
  45. package/src/style/PillarStyle.js +207 -207
  46. package/src/style/SegmentStyle.js +105 -105
  47. package/src/style/ShadingRayStyle.js +280 -280
  48. package/src/style/ShadingStyle.js +72 -72
  49. package/src/style/ShapeColorSizeStyle.js +147 -147
  50. package/src/style/SideCategoryStyle.js +112 -112
  51. package/src/style/SideStyle.js +217 -217
  52. package/src/style/SideTanakaStyle.js +154 -154
  53. package/src/style/SquareColorCategoryWebGLStyle.js +311 -294
  54. package/src/style/SquareColorWebGLStyle.js +126 -126
  55. package/src/style/StrokeStyle.js +135 -135
  56. package/src/style/TextStyle.js +110 -110
  57. package/src/style/TimeSeriesStyle.js +222 -222
  58. package/src/utils/WebGLRectangleColoring.js +106 -106
  59. package/src/utils/WebGLSquareColoring.js +114 -118
  60. package/src/utils/WebGLSquareColoringAdvanced.js +223 -227
  61. package/src/utils/WebGLSquareColoringKS.js +153 -153
  62. package/src/utils/scale.js +255 -255
  63. package/src/utils/stretching.js +120 -120
  64. package/src/utils/ternary.js +208 -208
  65. package/src/utils/utils.js +125 -125
  66. package/src/utils/webGLUtils.js +178 -73
  67. package/src/utils/zoomUtils.js +142 -142
@@ -1,295 +1,312 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../core/Style.js'
5
- import { initShaderProgram, createShader, makeWebGLCanvas } from '../utils/webGLUtils.js'
6
- import { color } from 'd3-color'
7
-
8
- /**
9
- * Style based on webGL
10
- * To show cells as colored squares, from categories.
11
- * All cells are drawn as squares, with the same size
12
- *
13
- * @module style
14
- * @author Julien Gaffuri
15
- */
16
- export class SquareColorCategoryWebGLStyle extends Style {
17
- /** @param {object} opts */
18
- constructor(opts) {
19
- super(opts)
20
- opts = opts || {}
21
-
22
- /**
23
- * A function returning the category code of the cell, for coloring.
24
- * @type {function(import('../core/Dataset.js').Cell, number, number, viewScale):string} */
25
- this.code = opts.code // (c, resolution, z, viewScale) => "code1"
26
-
27
- /**
28
- * The dictionary (code -> color) which gives the color of each category code.
29
- * @type {object} */
30
- opts.color = opts.color || undefined
31
-
32
- /** @type { Array.<string> } */
33
- const codes = Object.keys(opts.color)
34
-
35
- /** @type { object } @private */
36
- this.catToI = {}
37
- for (let i = 0; i < codes.length; i++) this.catToI[codes[i]] = i + ''
38
-
39
- /** @type { Array.<string> } @private */
40
- this.colors = []
41
- for (const code of codes) this.colors.push(opts.color['' + code])
42
-
43
- /**
44
- * A function returning the size of the cells, in geographical unit. All cells have the same size.
45
- * @type {function(number,number):number} */
46
- this.size = opts.size // (resolution, z) => ...
47
-
48
- /** * @type {{canvas:HTMLCanvasElement, gl:WebGLRenderingContext, width:number, height:number }}*/
49
- this.cvWGL = undefined
50
- this.programm = undefined
51
-
52
- this.x = undefined
53
- this.y = undefined
54
- this.z = undefined
55
- this.cellsNb = undefined
56
- }
57
-
58
- init(w, h) {
59
- this.cvWGL = makeWebGLCanvas(w + '', h + '')
60
- if (!this.cvWGL) { console.error('No webGL'); return }
61
-
62
- const gl = this.cvWGL.gl
63
-
64
- //draw
65
- const vectorShader = `
66
- attribute vec2 pos;
67
- uniform float sizePix;
68
- uniform mat3 mat;
69
- attribute float i;
70
- varying float vi;
71
- void main() {
72
- gl_Position = vec4(mat * vec3(pos, 1.0), 1.0);
73
- gl_PointSize = sizePix;
74
- vi = i;
75
- }`
76
- /** @type {WebGLShader} */
77
- const vShader = createShader(gl, gl.VERTEX_SHADER, vectorShader)
78
-
79
- const fragmentShader = `
80
- precision highp float;
81
- varying float vi;
82
- uniform sampler2D colorLUT;
83
- uniform float lutSize;
84
- void main(void) {
85
- float idx = floor(vi + 0.5);
86
- float u = (idx + 0.5) / lutSize;
87
- gl_FragColor = texture2D(colorLUT, vec2(u, 0.5));
88
- }`
89
- /** @type {WebGLShader} */
90
- const fShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShader)
91
-
92
- /** @type {WebGLProgram} */
93
- this.program = initShaderProgram(gl, vShader, fShader)
94
- gl.useProgram(this.program)
95
- }
96
-
97
- bindColors() {
98
- const gl = this.cvWGL.gl
99
- const lutSize = this.colors.length;
100
- const lutData = new Uint8Array(lutSize * 4); // RGBA for each entry
101
-
102
- // Fill lutData with your color values (e.g., rainbow, grayscale, etc.)
103
- for (let i = 0; i < lutSize; i++) {
104
- const c = color(this.colors[i])
105
- lutData[i * 4] = +c.r; // R
106
- lutData[i * 4 + 1] = c.g; // G
107
- lutData[i * 4 + 2] = c.b; // B
108
- lutData[i * 4 + 3] = c?.opacity * 255; // A
109
- }
110
-
111
- // Create and bind texture
112
- const lutTexture = gl.createTexture();
113
- gl.bindTexture(gl.TEXTURE_2D, lutTexture);
114
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, lutSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, lutData);
115
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
116
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
117
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
118
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
119
-
120
- // Get uniform locations
121
- const uColorLUT = gl.getUniformLocation(this.program, 'colorLUT');
122
- const uLutSize = gl.getUniformLocation(this.program, 'lutSize');
123
-
124
- // Set uniform values
125
- gl.uniform1i(uColorLUT, 0); // Texture unit 0
126
- gl.uniform1f(uLutSize, lutSize);
127
-
128
- // Bind the texture to texture unit 0
129
- gl.activeTexture(gl.TEXTURE0);
130
- gl.bindTexture(gl.TEXTURE_2D, lutTexture);
131
- }
132
-
133
- bindVertices(cells, resolution, z, viewScale) {
134
- const gl = this.cvWGL.gl
135
- //add vertice and fragment data
136
- const r2 = resolution / 2
137
- let c, nb = cells.length
138
- const verticesBuffer = []
139
- const iBuffer = []
140
- for (let i = 0; i < nb; i++) {
141
- c = cells[i]
142
- const cat = this.code(c, resolution, z, viewScale)
143
- if (cat == undefined) {
144
- //console.log('Unexpected category: ' + cat)
145
- continue
146
- }
147
- const i_ = this.catToI[cat]
148
- if (isNaN(+i_)) {
149
- console.log('Unexpected category index: ' + cat + ' ' + i_)
150
- continue
151
- }
152
- verticesBuffer.push(c.x + r2, c.y + r2)
153
- iBuffer.push(+i_)
154
- }
155
-
156
- //bind vertice data
157
- gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer())
158
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(verticesBuffer), gl.STATIC_DRAW)
159
- const position = gl.getAttribLocation(this.program, 'pos')
160
- gl.vertexAttribPointer(
161
- position,
162
- 2, //numComponents
163
- gl.FLOAT, //type
164
- false, //normalise
165
- 0, //stride
166
- 0 //offset
167
- )
168
- gl.enableVertexAttribArray(position)
169
-
170
- //i data
171
- gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer())
172
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(iBuffer), gl.STATIC_DRAW)
173
- const i = gl.getAttribLocation(this.program, 'i')
174
- gl.vertexAttribPointer(i, 1, gl.FLOAT, false, 0, 0)
175
- gl.enableVertexAttribArray(i)
176
- }
177
-
178
-
179
-
180
- // check if the vertices have to be bound again
181
- mapContentChanged(v, cellsNb) {
182
- if (v.x == this.x && v.y == this.y && v.z == this.z && this.cellsNb == cellsNb) return false
183
- this.x = v.x
184
- this.y = v.y
185
- this.z = v.z
186
- this.cellsNb = cellsNb
187
- return true
188
- }
189
-
190
-
191
- /**
192
- * @param {Array.<import("../core/Dataset.js").Cell>} cells
193
- * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
194
- * @param {number} resolution
195
- */
196
- draw(cells, geoCanvas, resolution) {
197
- //filter
198
- if (this.filter) cells = cells.filter(this.filter)
199
-
200
- //
201
- const z = geoCanvas.view.z
202
-
203
- //get view scale
204
- const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
205
-
206
- //create canvas and webgl renderer
207
- if (!this.cvWGL || geoCanvas.w != this.cvWGL.width || geoCanvas.h != this.cvWGL.height) {
208
- this.init(geoCanvas.w, geoCanvas.h)
209
- this.bindColors()
210
- }
211
- const gl = this.cvWGL.gl
212
- const canvas = this.cvWGL.canvas
213
-
214
- //bind sizePix
215
- const sizePix = this.size ? this.size(resolution, z) / z : resolution / z + 0.2
216
- gl.uniform1f(gl.getUniformLocation(this.program, 'sizePix'), 1.0 * sizePix)
217
-
218
- //
219
- if (this.mapContentChanged(geoCanvas.view, cells.length))
220
- //bind vertices
221
- this.bindVertices(cells, resolution, z, viewScale)
222
- //transformation
223
- gl.uniformMatrix3fv(gl.getUniformLocation(this.program, 'mat'), false, new Float32Array(geoCanvas.getWebGLTransform()))
224
-
225
- // Enable the depth test
226
- //gl.enable(gl.DEPTH_TEST);
227
- // Clear the color buffer bit
228
- gl.clear(gl.COLOR_BUFFER_BIT)
229
- // Set the view port
230
- //gl.viewport(0, 0, cg.w, cg.h);
231
-
232
- gl.drawArrays(gl.POINTS, 0, cells.length)
233
-
234
- //draw in canvas geo
235
- geoCanvas.initCanvasTransform()
236
- geoCanvas.offscreenCtx.drawImage(canvas, 0, 0)
237
-
238
- //update legends
239
- this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
240
- }
241
- }
242
-
243
-
244
-
245
- // early tests for webgl2 migration
246
-
247
- /*
248
- function getVectorShader2() {
249
- return `
250
- #version 300 es
251
- precision highp float;
252
-
253
- in vec2 pos;
254
- in int i;
255
-
256
- uniform float sizePix;
257
- uniform mat3 mat;
258
-
259
- flat out int vi;
260
-
261
- void main() {
262
- gl_Position = vec4(mat * vec3(pos, 1.0), 1.0);
263
- gl_PointSize = sizePix;
264
- vi = i;
265
- }
266
- `
267
- }
268
-
269
-
270
- function getFragmentShader2(colors) {
271
-
272
- //prepare fragment shader code
273
- //declare the uniform and other variables
274
- const out = []
275
- out.push('#version 300 es\nprecision highp float;\nflat in int vi;\n')
276
-
277
- //add color uniforms
278
- //uniform vec4 colors[12];
279
- out.push('uniform vec4 colors[')
280
- out.push(colors.length)
281
- out.push('];\n')
282
-
283
- out.push('out vec4 fragColor;\n')
284
-
285
- //start the main function
286
- //void main() { fragColor = colors[clamp(vi, 0, 11)]; }
287
- out.push('void main() { fragColor = colors[vi]; }\n')
288
-
289
- /** Fragment shader program
290
- const fshString = out.join('')
291
- console.log(fshString)
292
- return fshString
293
- }
294
-
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../core/Style.js'
5
+ import { getSharedWebGLCanvas, getProgram, getBuffer, bufferOwner } from '../utils/webGLUtils.js'
6
+ import { color } from 'd3-color'
7
+
8
+ const VERTEX_SHADER = `
9
+ attribute vec2 pos;
10
+ uniform float sizePix;
11
+ uniform mat3 mat;
12
+ attribute float i;
13
+ varying float vi;
14
+ void main() {
15
+ gl_Position = vec4(mat * vec3(pos, 1.0), 1.0);
16
+ gl_PointSize = sizePix;
17
+ vi = i;
18
+ }`
19
+
20
+ const FRAGMENT_SHADER = `
21
+ precision highp float;
22
+ varying float vi;
23
+ uniform sampler2D colorLUT;
24
+ uniform float lutSize;
25
+ void main(void) {
26
+ float idx = floor(vi + 0.5);
27
+ float u = (idx + 0.5) / lutSize;
28
+ gl_FragColor = texture2D(colorLUT, vec2(u, 0.5));
29
+ }`
30
+
31
+ // names of the buffers this style fills in the shared context (getBuffer)
32
+ const POSITION_BUFFER = 'SquareColorCategoryWebGLStyle.pos'
33
+ const INDEX_BUFFER = 'SquareColorCategoryWebGLStyle.i'
34
+
35
+ /**
36
+ * Style based on webGL
37
+ * To show cells as colored squares, from categories.
38
+ * All cells are drawn as squares, with the same size
39
+ *
40
+ * @module style
41
+ * @author Julien Gaffuri
42
+ */
43
+ export class SquareColorCategoryWebGLStyle extends Style {
44
+ /** @param {object} opts */
45
+ constructor(opts) {
46
+ super(opts)
47
+ opts = opts || {}
48
+
49
+ /**
50
+ * A function returning the category code of the cell, for coloring.
51
+ * @type {function(import('../core/Dataset.js').Cell, number, number, viewScale):string} */
52
+ this.code = opts.code // (c, resolution, z, viewScale) => "code1"
53
+
54
+ /**
55
+ * The dictionary (code -> color) which gives the color of each category code.
56
+ * @type {object} */
57
+ opts.color = opts.color || undefined
58
+
59
+ /** @type { Array.<string> } */
60
+ const codes = Object.keys(opts.color)
61
+
62
+ /** @type { object } @private */
63
+ this.catToI = {}
64
+ for (let i = 0; i < codes.length; i++) this.catToI[codes[i]] = i + ''
65
+
66
+ /** @type { Array.<string> } @private */
67
+ this.colors = []
68
+ for (const code of codes) this.colors.push(opts.color['' + code])
69
+
70
+ /**
71
+ * A function returning the size of the cells, in geographical unit. All cells have the same size.
72
+ * @type {function(number,number):number} */
73
+ this.size = opts.size // (resolution, z) => ...
74
+
75
+ /** The shared WebGL canvas this style last drew into (getSharedWebGLCanvas)
76
+ * @type {{canvas:HTMLCanvasElement, gl:WebGLRenderingContext, width:number, height:number }}*/
77
+ this.cvWGL = undefined
78
+ /** @type {WebGLRenderingContext|undefined} */
79
+ this.gl = undefined
80
+ this.program = undefined
81
+ this.lutTexture = undefined
82
+ /** Number of points in the shared buffers, for drawArrays */
83
+ this.pointsNb = 0
84
+
85
+ this.x = undefined
86
+ this.y = undefined
87
+ this.z = undefined
88
+ this.cellsNb = undefined
89
+ }
90
+
91
+ /**
92
+ * Binds this style's program, colour lookup texture and uniforms in the shared WebGL
93
+ * context (getSharedWebGLCanvas): compiled once per context, so a new style instance
94
+ * (e.g. a setting change rebuilding the style) costs no new context or program.
95
+ * @returns {boolean} true when the context is new to this style (its data must be re-uploaded)
96
+ */
97
+ init(w, h) {
98
+ this.cvWGL = getSharedWebGLCanvas(w, h)
99
+ const gl = this.cvWGL.gl
100
+ const contextChanged = this.gl !== gl
101
+ if (contextChanged) {
102
+ this.gl = gl
103
+ this.program = getProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER)
104
+ this.lutTexture = undefined
105
+ }
106
+ gl.useProgram(this.program)
107
+ this.bindColors()
108
+ return contextChanged
109
+ }
110
+
111
+ bindColors() {
112
+ const gl = this.cvWGL.gl
113
+ const lutSize = this.colors.length
114
+
115
+ // created once per style and context
116
+ if (!this.lutTexture) {
117
+ const lutData = new Uint8Array(lutSize * 4) // RGBA for each entry
118
+ for (let i = 0; i < lutSize; i++) {
119
+ const c = color(this.colors[i])
120
+ lutData[i * 4] = +c.r
121
+ lutData[i * 4 + 1] = c.g
122
+ lutData[i * 4 + 2] = c.b
123
+ lutData[i * 4 + 3] = c?.opacity * 255
124
+ }
125
+ this.lutTexture = gl.createTexture()
126
+ gl.bindTexture(gl.TEXTURE_2D, this.lutTexture)
127
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, lutSize, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, lutData)
128
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
129
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
130
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
131
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
132
+ }
133
+
134
+ gl.uniform1i(gl.getUniformLocation(this.program, 'colorLUT'), 0) // Texture unit 0
135
+ gl.uniform1f(gl.getUniformLocation(this.program, 'lutSize'), lutSize)
136
+ gl.activeTexture(gl.TEXTURE0)
137
+ gl.bindTexture(gl.TEXTURE_2D, this.lutTexture)
138
+ }
139
+
140
+ /**
141
+ * Fills the shared position and colour index buffers with the cells to draw.
142
+ * @returns {number} the number of points uploaded (cells without a category are left out)
143
+ */
144
+ bindVertices(cells, resolution, z, viewScale) {
145
+ const gl = this.cvWGL.gl
146
+ //add vertice and fragment data
147
+ const r2 = resolution / 2
148
+ let c,
149
+ nb = cells.length
150
+ const verticesBuffer = new Float32Array(2 * nb)
151
+ const iBuffer = new Float32Array(nb)
152
+ let n = 0
153
+ for (let i = 0; i < nb; i++) {
154
+ c = cells[i]
155
+ const cat = this.code(c, resolution, z, viewScale)
156
+ if (cat == undefined) {
157
+ //console.log('Unexpected category: ' + cat)
158
+ continue
159
+ }
160
+ const i_ = this.catToI[cat]
161
+ if (isNaN(+i_)) {
162
+ console.log('Unexpected category index: ' + cat + ' ' + i_)
163
+ continue
164
+ }
165
+ verticesBuffer[2 * n] = c.x + r2
166
+ verticesBuffer[2 * n + 1] = c.y + r2
167
+ iBuffer[n] = +i_
168
+ n++
169
+ }
170
+
171
+ gl.bindBuffer(gl.ARRAY_BUFFER, getBuffer(gl, POSITION_BUFFER))
172
+ gl.bufferData(gl.ARRAY_BUFFER, verticesBuffer.subarray(0, 2 * n), gl.DYNAMIC_DRAW)
173
+ gl.bindBuffer(gl.ARRAY_BUFFER, getBuffer(gl, INDEX_BUFFER))
174
+ gl.bufferData(gl.ARRAY_BUFFER, iBuffer.subarray(0, n), gl.DYNAMIC_DRAW)
175
+ bufferOwner(gl, POSITION_BUFFER, this)
176
+ return n
177
+ }
178
+
179
+ /** Points the program's attributes at the shared buffers (whatever another style left bound). */
180
+ bindAttributes() {
181
+ const gl = this.cvWGL.gl
182
+ const position = gl.getAttribLocation(this.program, 'pos')
183
+ gl.bindBuffer(gl.ARRAY_BUFFER, getBuffer(gl, POSITION_BUFFER))
184
+ gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0)
185
+ gl.enableVertexAttribArray(position)
186
+ const i = gl.getAttribLocation(this.program, 'i')
187
+ gl.bindBuffer(gl.ARRAY_BUFFER, getBuffer(gl, INDEX_BUFFER))
188
+ gl.vertexAttribPointer(i, 1, gl.FLOAT, false, 0, 0)
189
+ gl.enableVertexAttribArray(i)
190
+ }
191
+
192
+ // check if the vertices have to be bound again
193
+ mapContentChanged(v, cellsNb) {
194
+ if (v.x == this.x && v.y == this.y && v.z == this.z && this.cellsNb == cellsNb) return false
195
+ this.x = v.x
196
+ this.y = v.y
197
+ this.z = v.z
198
+ this.cellsNb = cellsNb
199
+ return true
200
+ }
201
+
202
+
203
+ /**
204
+ * @param {Array.<import("../core/Dataset.js").Cell>} cells
205
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
206
+ * @param {number} resolution
207
+ */
208
+ draw(cells, geoCanvas, resolution) {
209
+ //filter
210
+ if (this.filter) cells = cells.filter(this.filter)
211
+
212
+ //
213
+ const z = geoCanvas.view.z
214
+
215
+ //get view scale
216
+ const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
217
+
218
+ //bind this style's program in the shared WebGL context
219
+ const contextChanged = this.init(geoCanvas.w, geoCanvas.h)
220
+ const gl = this.cvWGL.gl
221
+ const canvas = this.cvWGL.canvas
222
+
223
+ //bind sizePix
224
+ const sizePix = this.size ? this.size(resolution, z) / z : resolution / z + 0.2
225
+ gl.uniform1f(gl.getUniformLocation(this.program, 'sizePix'), 1.0 * sizePix)
226
+
227
+ // mapContentChanged() is a cheap proxy for "did the content change", based on view
228
+ // x/y/z and cell count alone. The upload is also needed when the shared buffers
229
+ // hold another style's data (bufferOwner), or the context is new to this style
230
+ // (e.g. replaced after being lost).
231
+ const contentChanged = this.mapContentChanged(geoCanvas.view, cells.length)
232
+ if (contentChanged || contextChanged || bufferOwner(gl, POSITION_BUFFER) !== this)
233
+ this.pointsNb = this.bindVertices(cells, resolution, z, viewScale)
234
+ this.bindAttributes()
235
+
236
+ //transformation
237
+ gl.uniformMatrix3fv(
238
+ gl.getUniformLocation(this.program, 'mat'),
239
+ false,
240
+ new Float32Array(geoCanvas.getWebGLTransform())
241
+ )
242
+
243
+ // Clear the color buffer bit
244
+ gl.clearColor(0, 0, 0, 0)
245
+ gl.clear(gl.COLOR_BUFFER_BIT)
246
+
247
+ // only the points actually uploaded: cells without a category are left out, and
248
+ // drawing past the end of the buffer is a WebGL error that draws nothing at all
249
+ gl.drawArrays(gl.POINTS, 0, this.pointsNb)
250
+
251
+ //draw in canvas geo
252
+ geoCanvas.initCanvasTransform()
253
+ geoCanvas.offscreenCtx.drawImage(canvas, 0, 0)
254
+
255
+ //update legends
256
+ this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
257
+ }
258
+ }
259
+
260
+
261
+
262
+ // early tests for webgl2 migration
263
+
264
+ /*
265
+ function getVectorShader2() {
266
+ return `
267
+ #version 300 es
268
+ precision highp float;
269
+
270
+ in vec2 pos;
271
+ in int i;
272
+
273
+ uniform float sizePix;
274
+ uniform mat3 mat;
275
+
276
+ flat out int vi;
277
+
278
+ void main() {
279
+ gl_Position = vec4(mat * vec3(pos, 1.0), 1.0);
280
+ gl_PointSize = sizePix;
281
+ vi = i;
282
+ }
283
+ `
284
+ }
285
+
286
+
287
+ function getFragmentShader2(colors) {
288
+
289
+ //prepare fragment shader code
290
+ //declare the uniform and other variables
291
+ const out = []
292
+ out.push('#version 300 es\nprecision highp float;\nflat in int vi;\n')
293
+
294
+ //add color uniforms
295
+ //uniform vec4 colors[12];
296
+ out.push('uniform vec4 colors[')
297
+ out.push(colors.length)
298
+ out.push('];\n')
299
+
300
+ out.push('out vec4 fragColor;\n')
301
+
302
+ //start the main function
303
+ //void main() { fragColor = colors[clamp(vi, 0, 11)]; }
304
+ out.push('void main() { fragColor = colors[vi]; }\n')
305
+
306
+ /** Fragment shader program
307
+ const fshString = out.join('')
308
+ console.log(fshString)
309
+ return fshString
310
+ }
311
+
295
312
  */