gridviz 3.0.34 → 3.0.36

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 +17487 -17471
  3. package/dist/gridviz.min.js +2 -2
  4. package/package.json +73 -73
  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 +154 -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 +568 -552
  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 +302 -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 +307 -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 +118 -118
  60. package/src/utils/WebGLSquareColoringAdvanced.js +227 -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 +73 -73
  67. package/src/utils/zoomUtils.js +142 -142
@@ -1,180 +1,180 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../core/Style.js'
5
- import { cellsToGrid } from '../utils/utils.js'
6
-
7
- /**
8
- * @module style
9
- * @author Julien Gaffuri
10
- */
11
- export class JoyPlotStyle extends Style {
12
- /** @param {object} opts */
13
- constructor(opts) {
14
- super(opts)
15
- opts = opts || {}
16
-
17
- /** A function returning the height of a cell in geographical unit.
18
- * @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
19
- this.height = opts.height || ((c, r) => r * Math.random()) //(c,r,z,vs) => {}
20
-
21
- /**
22
- * @type {function(number,{min:number, max:number},number,number):string} */
23
- this.lineColor = opts.lineColor || ((y, ys, r, z) => '#BBB')
24
- /**
25
- * @type {function(number,{min:number, max:number},number,number):number} */
26
- this.lineWidth = opts.lineWidth || ((y, ys, r, z) => z)
27
- /**
28
- * @type {function(number,{min:number, max:number},number,number):string} */
29
- this.fillColor = opts.fillColor || ((y, ys, r, z) => '#c08c5968')
30
- }
31
-
32
- /**
33
- * @param {Array.<import("../core/Dataset.js").Cell>} cells
34
- * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
35
- * @param {number} resolution
36
- * @override
37
- */
38
- draw(cells, geoCanvas, resolution) {
39
- //filter
40
- if (this.filter) cells = cells.filter(this.filter)
41
-
42
- //
43
- const z = geoCanvas.view.z
44
- const ctx = geoCanvas.offscreenCtx
45
-
46
- //get view scale
47
- const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
48
-
49
- //index cells by y and x
50
- /** @type {object} */
51
- const ind = cellsToGrid(cells, cell => this.height(cell, resolution, z, viewScale))
52
-
53
-
54
- //make grid
55
- /** @type {object} */
56
- /*const grid = cellsToGrid2(cells, resolution, cell => this.height(cell, resolution, z, viewScale))
57
- if (!grid.maxI || !grid.maxJ) return
58
-
59
- //TODO
60
- const ys = { min: grid.y0 + resolution * grid.minI, max: grid.y0 + resolution * grid.maxI }
61
-
62
- //draw lines, row by row, stating from the top
63
- ctx.lineJoin = 'round'
64
- for (let i = grid.minI; i <= grid.maxI; i++) {
65
-
66
- //Get row data
67
- const row = grid[i]
68
- if (!row) continue
69
-
70
- // y of the row
71
- const y = grid.y0 - i * resolution
72
-
73
- //store the previous height
74
- let hG_
75
-
76
- for (let j = grid.minJ; j <= grid.maxJ; j++) {
77
- //get column value
78
- let hG = row[j]
79
- if (!hG) hG = 0
80
-
81
- // x of the cell
82
- const x = grid.x0 + j * resolution
83
-
84
- if (hG || hG_) {
85
- //draw line only when at least one of both values is non-null
86
- //TODO test bezierCurveTo
87
- ctx.lineTo(x + resolution / 2, y + hG)
88
- } else {
89
- //else move the point
90
- ctx.moveTo(x + resolution / 2, y)
91
- }
92
- //store the previous value
93
- hG_ = hG
94
- }
95
- //last point
96
- if (hG_) ctx.lineTo(grid.x0 + resolution * grid.maxJ + resolution / 2, y)
97
-
98
- //draw fill
99
- const fc = this.fillColor(y, ys, resolution, z)
100
- if (fc && fc != 'none') {
101
- ctx.fillStyle = fc
102
- ctx.fill()
103
- }
104
-
105
- //draw line
106
- const lc = this.lineColor(y, ys, resolution, z)
107
- const lw = this.lineWidth(y, ys, resolution, z)
108
- if (lc && lc != 'none' && lw > 0) {
109
- ctx.strokeStyle = lc
110
- ctx.lineWidth = lw
111
- ctx.stroke()
112
- }
113
- }
114
- */
115
-
116
- //compute extent
117
- const e = geoCanvas.extGeo
118
- if (!e) return
119
- const xMin = Math.floor(e.xMin / resolution) * resolution
120
- const xMax = Math.floor(e.xMax / resolution) * resolution
121
- const yMin = Math.floor(e.yMin / resolution) * resolution
122
- const yMax = Math.floor(e.yMax / resolution) * resolution
123
-
124
- const ys = { min: yMin, max: yMax }
125
-
126
- //draw lines, row by row, stating from the top
127
- ctx.lineJoin = 'round'
128
- for (let y = yMax; y >= yMin; y -= resolution) {
129
- //get row
130
- const row = ind[y]
131
-
132
- //no row
133
- if (!row) continue
134
-
135
- //place first point
136
- ctx.beginPath()
137
- ctx.moveTo(xMin - resolution / 2, y)
138
-
139
- //store the previous height
140
- let hG_
141
-
142
- //go through the line cells
143
- for (let x = xMin; x <= xMax; x += resolution) {
144
- //get column value
145
- let hG = row[x]
146
- if (!hG) hG = 0
147
-
148
- if (hG || hG_) {
149
- //draw line only when at least one of both values is non-null
150
- //TODO test bezierCurveTo
151
- ctx.lineTo(x + resolution / 2, y + hG)
152
- } else {
153
- //else move the point
154
- ctx.moveTo(x + resolution / 2, y)
155
- }
156
- //store the previous value
157
- hG_ = hG
158
- }
159
-
160
- //last point
161
- if (hG_) ctx.lineTo(xMax + resolution / 2, y)
162
-
163
- //draw fill
164
- const fc = this.fillColor(y, ys, resolution, z)
165
- if (fc && fc != 'none') {
166
- ctx.fillStyle = fc
167
- ctx.fill()
168
- }
169
-
170
- //draw line
171
- const lc = this.lineColor(y, ys, resolution, z)
172
- const lw = this.lineWidth(y, ys, resolution, z)
173
- if (lc && lc != 'none' && lw > 0) {
174
- ctx.strokeStyle = lc
175
- ctx.lineWidth = lw
176
- ctx.stroke()
177
- }
178
- }
179
- }
180
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../core/Style.js'
5
+ import { cellsToGrid } from '../utils/utils.js'
6
+
7
+ /**
8
+ * @module style
9
+ * @author Julien Gaffuri
10
+ */
11
+ export class JoyPlotStyle extends Style {
12
+ /** @param {object} opts */
13
+ constructor(opts) {
14
+ super(opts)
15
+ opts = opts || {}
16
+
17
+ /** A function returning the height of a cell in geographical unit.
18
+ * @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
19
+ this.height = opts.height || ((c, r) => r * Math.random()) //(c,r,z,vs) => {}
20
+
21
+ /**
22
+ * @type {function(number,{min:number, max:number},number,number):string} */
23
+ this.lineColor = opts.lineColor || ((y, ys, r, z) => '#BBB')
24
+ /**
25
+ * @type {function(number,{min:number, max:number},number,number):number} */
26
+ this.lineWidth = opts.lineWidth || ((y, ys, r, z) => z)
27
+ /**
28
+ * @type {function(number,{min:number, max:number},number,number):string} */
29
+ this.fillColor = opts.fillColor || ((y, ys, r, z) => '#c08c5968')
30
+ }
31
+
32
+ /**
33
+ * @param {Array.<import("../core/Dataset.js").Cell>} cells
34
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
35
+ * @param {number} resolution
36
+ * @override
37
+ */
38
+ draw(cells, geoCanvas, resolution) {
39
+ //filter
40
+ if (this.filter) cells = cells.filter(this.filter)
41
+
42
+ //
43
+ const z = geoCanvas.view.z
44
+ const ctx = geoCanvas.offscreenCtx
45
+
46
+ //get view scale
47
+ const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
48
+
49
+ //index cells by y and x
50
+ /** @type {object} */
51
+ const ind = cellsToGrid(cells, cell => this.height(cell, resolution, z, viewScale))
52
+
53
+
54
+ //make grid
55
+ /** @type {object} */
56
+ /*const grid = cellsToGrid2(cells, resolution, cell => this.height(cell, resolution, z, viewScale))
57
+ if (!grid.maxI || !grid.maxJ) return
58
+
59
+ //TODO
60
+ const ys = { min: grid.y0 + resolution * grid.minI, max: grid.y0 + resolution * grid.maxI }
61
+
62
+ //draw lines, row by row, stating from the top
63
+ ctx.lineJoin = 'round'
64
+ for (let i = grid.minI; i <= grid.maxI; i++) {
65
+
66
+ //Get row data
67
+ const row = grid[i]
68
+ if (!row) continue
69
+
70
+ // y of the row
71
+ const y = grid.y0 - i * resolution
72
+
73
+ //store the previous height
74
+ let hG_
75
+
76
+ for (let j = grid.minJ; j <= grid.maxJ; j++) {
77
+ //get column value
78
+ let hG = row[j]
79
+ if (!hG) hG = 0
80
+
81
+ // x of the cell
82
+ const x = grid.x0 + j * resolution
83
+
84
+ if (hG || hG_) {
85
+ //draw line only when at least one of both values is non-null
86
+ //TODO test bezierCurveTo
87
+ ctx.lineTo(x + resolution / 2, y + hG)
88
+ } else {
89
+ //else move the point
90
+ ctx.moveTo(x + resolution / 2, y)
91
+ }
92
+ //store the previous value
93
+ hG_ = hG
94
+ }
95
+ //last point
96
+ if (hG_) ctx.lineTo(grid.x0 + resolution * grid.maxJ + resolution / 2, y)
97
+
98
+ //draw fill
99
+ const fc = this.fillColor(y, ys, resolution, z)
100
+ if (fc && fc != 'none') {
101
+ ctx.fillStyle = fc
102
+ ctx.fill()
103
+ }
104
+
105
+ //draw line
106
+ const lc = this.lineColor(y, ys, resolution, z)
107
+ const lw = this.lineWidth(y, ys, resolution, z)
108
+ if (lc && lc != 'none' && lw > 0) {
109
+ ctx.strokeStyle = lc
110
+ ctx.lineWidth = lw
111
+ ctx.stroke()
112
+ }
113
+ }
114
+ */
115
+
116
+ //compute extent
117
+ const e = geoCanvas.extGeo
118
+ if (!e) return
119
+ const xMin = Math.floor(e.xMin / resolution) * resolution
120
+ const xMax = Math.floor(e.xMax / resolution) * resolution
121
+ const yMin = Math.floor(e.yMin / resolution) * resolution
122
+ const yMax = Math.floor(e.yMax / resolution) * resolution
123
+
124
+ const ys = { min: yMin, max: yMax }
125
+
126
+ //draw lines, row by row, stating from the top
127
+ ctx.lineJoin = 'round'
128
+ for (let y = yMax; y >= yMin; y -= resolution) {
129
+ //get row
130
+ const row = ind[y]
131
+
132
+ //no row
133
+ if (!row) continue
134
+
135
+ //place first point
136
+ ctx.beginPath()
137
+ ctx.moveTo(xMin - resolution / 2, y)
138
+
139
+ //store the previous height
140
+ let hG_
141
+
142
+ //go through the line cells
143
+ for (let x = xMin; x <= xMax; x += resolution) {
144
+ //get column value
145
+ let hG = row[x]
146
+ if (!hG) hG = 0
147
+
148
+ if (hG || hG_) {
149
+ //draw line only when at least one of both values is non-null
150
+ //TODO test bezierCurveTo
151
+ ctx.lineTo(x + resolution / 2, y + hG)
152
+ } else {
153
+ //else move the point
154
+ ctx.moveTo(x + resolution / 2, y)
155
+ }
156
+ //store the previous value
157
+ hG_ = hG
158
+ }
159
+
160
+ //last point
161
+ if (hG_) ctx.lineTo(xMax + resolution / 2, y)
162
+
163
+ //draw fill
164
+ const fc = this.fillColor(y, ys, resolution, z)
165
+ if (fc && fc != 'none') {
166
+ ctx.fillStyle = fc
167
+ ctx.fill()
168
+ }
169
+
170
+ //draw line
171
+ const lc = this.lineColor(y, ys, resolution, z)
172
+ const lw = this.lineWidth(y, ys, resolution, z)
173
+ if (lc && lc != 'none' && lw > 0) {
174
+ ctx.strokeStyle = lc
175
+ ctx.lineWidth = lw
176
+ ctx.stroke()
177
+ }
178
+ }
179
+ }
180
+ }
@@ -1,132 +1,132 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- //import { TanakaStyle } from './SideTanakaStyle___OLD.js'
5
- import { StrokeStyle } from './StrokeStyle.js'
6
- import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.js'
7
- import { Style } from '../core/Style.js'
8
- //import { SideStyle } from './SideStyle.js'
9
- import { classifier as clFun, colorClassifier as cclFun } from '../utils/scale.js'
10
- import { SideTanakaStyle } from './SideTanakaStyle.js'
11
-
12
-
13
- /**
14
- * @module style
15
- * @author Julien Gaffuri
16
- */
17
- export class LegoStyle {
18
- static get(value, breaks, colors, opts = {}) {
19
- opts = opts || {}
20
-
21
- //the colors
22
- //http://www.jennyscrayoncollection.com/2021/06/all-current-lego-colors.html
23
- //https://leonawicz.github.io/legocolors/reference/figures/README-plot-1.png
24
- /*opts.colors = opts.colors || [
25
- '#00852b', //darker green
26
- '#afd246', //light green
27
- '#fac80a', //dark yellow
28
- '#bb805a', //brown
29
- '#d67923', //mostard
30
- '#cb4e29', //redish
31
- '#b40000', //red
32
- '#720012', //dark red
33
- //"purple",
34
- //"#eee" //whithe
35
- ]*/
36
-
37
- opts.colorDark = opts.colorDark || '#333'
38
- opts.colorBright = opts.colorBright || '#aaa'
39
-
40
- //make classifier
41
- const classifier = clFun(breaks)
42
- const classifier2 = cell => classifier(value(cell))
43
- //make colors table
44
- const colorsDict = {}
45
- for (let i = 0; i < colors.length; i++) colorsDict[i + ''] = colors[i]
46
-
47
- //make cell fill style
48
- const cellStyle = new SquareColorCategoryWebGLStyle({
49
- code: classifier2,
50
- color: colorsDict,
51
- })
52
-
53
- //make tanaka side style
54
- const tanakaStyle = new SideTanakaStyle({
55
- classifier: () => classifier2,
56
- colorDark : opts.colorDark,
57
- colorBright : opts.colorBright,
58
- diamond: opts.diamond,
59
- })
60
-
61
- //style to show limits between pieces
62
- const sst = new StrokeStyle({
63
- strokeColor: () => '#666',
64
- strokeWidth: (c, r, z) => 0.2 * z,
65
- filter: opts.filter,
66
- })
67
-
68
- return [
69
- cellStyle,
70
- sst,
71
- tanakaStyle,
72
- new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright, filter: opts.filter }),
73
- ]
74
- }
75
-
76
- /**
77
- * @param {function(import('../core/Dataset.js').Cell):string} code
78
- * @param {object} color
79
- * @param {object} opts
80
- * @returns {Array.<Style>}
81
- */
82
- static getCategory(code, color, opts) {
83
- opts = opts || {}
84
-
85
- opts.colDark = opts.colDark || '#333'
86
- opts.colBright = opts.colBright || '#aaa'
87
-
88
- //
89
- const s = new SquareColorCategoryWebGLStyle({ code: code, color: color })
90
- //style to show limits between pieces
91
- const sst = new StrokeStyle({ strokeColor: () => '#666', strokeWidth: (c, r, z) => 0.2 * z })
92
-
93
- return [s, sst, new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright })]
94
- }
95
- }
96
-
97
- /**
98
- * A style to draw top circle of lego bricks.
99
- */
100
- class LegoTopStyle extends Style {
101
- /** @param {object|undefined} opts */
102
- constructor(opts) {
103
- super(opts)
104
- opts = opts || {}
105
- this.colDark = opts.colDark || '#333'
106
- this.colBright = opts.colBright || '#aaa'
107
- }
108
-
109
- draw(cells, geoCanvas, r) {
110
- //filter
111
- if (this.filter) cells = cells.filter(this.filter)
112
- const ctx = geoCanvas.offscreenCtx
113
-
114
- ctx.lineWidth = 0.6 * geoCanvas.view.z
115
-
116
- //dark part
117
- ctx.strokeStyle = this.colDark
118
- for (let c of cells) {
119
- ctx.beginPath()
120
- ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), true)
121
- ctx.stroke()
122
- }
123
-
124
- //bright part
125
- ctx.strokeStyle = this.colBright
126
- for (let c of cells) {
127
- ctx.beginPath()
128
- ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), false)
129
- ctx.stroke()
130
- }
131
- }
132
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ //import { TanakaStyle } from './SideTanakaStyle___OLD.js'
5
+ import { StrokeStyle } from './StrokeStyle.js'
6
+ import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.js'
7
+ import { Style } from '../core/Style.js'
8
+ //import { SideStyle } from './SideStyle.js'
9
+ import { classifier as clFun, colorClassifier as cclFun } from '../utils/scale.js'
10
+ import { SideTanakaStyle } from './SideTanakaStyle.js'
11
+
12
+
13
+ /**
14
+ * @module style
15
+ * @author Julien Gaffuri
16
+ */
17
+ export class LegoStyle {
18
+ static get(value, breaks, colors, opts = {}) {
19
+ opts = opts || {}
20
+
21
+ //the colors
22
+ //http://www.jennyscrayoncollection.com/2021/06/all-current-lego-colors.html
23
+ //https://leonawicz.github.io/legocolors/reference/figures/README-plot-1.png
24
+ /*opts.colors = opts.colors || [
25
+ '#00852b', //darker green
26
+ '#afd246', //light green
27
+ '#fac80a', //dark yellow
28
+ '#bb805a', //brown
29
+ '#d67923', //mostard
30
+ '#cb4e29', //redish
31
+ '#b40000', //red
32
+ '#720012', //dark red
33
+ //"purple",
34
+ //"#eee" //whithe
35
+ ]*/
36
+
37
+ opts.colorDark = opts.colorDark || '#333'
38
+ opts.colorBright = opts.colorBright || '#aaa'
39
+
40
+ //make classifier
41
+ const classifier = clFun(breaks)
42
+ const classifier2 = cell => classifier(value(cell))
43
+ //make colors table
44
+ const colorsDict = {}
45
+ for (let i = 0; i < colors.length; i++) colorsDict[i + ''] = colors[i]
46
+
47
+ //make cell fill style
48
+ const cellStyle = new SquareColorCategoryWebGLStyle({
49
+ code: classifier2,
50
+ color: colorsDict,
51
+ })
52
+
53
+ //make tanaka side style
54
+ const tanakaStyle = new SideTanakaStyle({
55
+ classifier: () => classifier2,
56
+ colorDark : opts.colorDark,
57
+ colorBright : opts.colorBright,
58
+ diamond: opts.diamond,
59
+ })
60
+
61
+ //style to show limits between pieces
62
+ const sst = new StrokeStyle({
63
+ strokeColor: () => '#666',
64
+ strokeWidth: (c, r, z) => 0.2 * z,
65
+ filter: opts.filter,
66
+ })
67
+
68
+ return [
69
+ cellStyle,
70
+ sst,
71
+ tanakaStyle,
72
+ new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright, filter: opts.filter }),
73
+ ]
74
+ }
75
+
76
+ /**
77
+ * @param {function(import('../core/Dataset.js').Cell):string} code
78
+ * @param {object} color
79
+ * @param {object} opts
80
+ * @returns {Array.<Style>}
81
+ */
82
+ static getCategory(code, color, opts) {
83
+ opts = opts || {}
84
+
85
+ opts.colDark = opts.colDark || '#333'
86
+ opts.colBright = opts.colBright || '#aaa'
87
+
88
+ //
89
+ const s = new SquareColorCategoryWebGLStyle({ code: code, color: color })
90
+ //style to show limits between pieces
91
+ const sst = new StrokeStyle({ strokeColor: () => '#666', strokeWidth: (c, r, z) => 0.2 * z })
92
+
93
+ return [s, sst, new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright })]
94
+ }
95
+ }
96
+
97
+ /**
98
+ * A style to draw top circle of lego bricks.
99
+ */
100
+ class LegoTopStyle extends Style {
101
+ /** @param {object|undefined} opts */
102
+ constructor(opts) {
103
+ super(opts)
104
+ opts = opts || {}
105
+ this.colDark = opts.colDark || '#333'
106
+ this.colBright = opts.colBright || '#aaa'
107
+ }
108
+
109
+ draw(cells, geoCanvas, r) {
110
+ //filter
111
+ if (this.filter) cells = cells.filter(this.filter)
112
+ const ctx = geoCanvas.offscreenCtx
113
+
114
+ ctx.lineWidth = 0.6 * geoCanvas.view.z
115
+
116
+ //dark part
117
+ ctx.strokeStyle = this.colDark
118
+ for (let c of cells) {
119
+ ctx.beginPath()
120
+ ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), true)
121
+ ctx.stroke()
122
+ }
123
+
124
+ //bright part
125
+ ctx.strokeStyle = this.colBright
126
+ for (let c of cells) {
127
+ ctx.beginPath()
128
+ ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), false)
129
+ ctx.stroke()
130
+ }
131
+ }
132
+ }