gridviz 3.0.18 → 3.0.20

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 (56) hide show
  1. package/README.md +128 -127
  2. package/dist/gridviz.js +7862 -7819
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +74 -74
  5. package/src/button/ZoomButtons.js +101 -101
  6. package/src/core/Dataset.js +154 -154
  7. package/src/core/Drawable.js +60 -60
  8. package/src/core/GeoCanvas.js +430 -419
  9. package/src/core/Layer.js +23 -23
  10. package/src/core/Legend.js +108 -108
  11. package/src/core/Map.js +516 -503
  12. package/src/core/MultiResolutionDataset.js +93 -93
  13. package/src/core/Style.js +98 -98
  14. package/src/core/Tooltip.js +1 -0
  15. package/src/dataset/CSVGrid.js +112 -112
  16. package/src/dataset/GeoTIFF.js +122 -122
  17. package/src/dataset/JSGrid.js +55 -55
  18. package/src/dataset/TiledGrid.js +302 -289
  19. package/src/dataset/worker.js +18 -18
  20. package/src/index.js +77 -77
  21. package/src/layer/BackgroundLayer.js +162 -162
  22. package/src/layer/BackgroundLayerImage.js +81 -81
  23. package/src/layer/BackgroundLayerWMS.js +104 -104
  24. package/src/layer/GeoJSONLayer.js +214 -214
  25. package/src/layer/GridLayer.js +148 -148
  26. package/src/layer/LabelLayer.js +194 -194
  27. package/src/legend/ColorCategoryLegend.js +109 -109
  28. package/src/legend/ColorDiscreteLegend.js +100 -100
  29. package/src/legend/ColorLegend.js +115 -115
  30. package/src/legend/OrientationLegend.js +89 -89
  31. package/src/legend/SizeLegend.js +224 -224
  32. package/src/legend/TernaryLegend.js +302 -302
  33. package/src/style/CompositionStyle.js +291 -291
  34. package/src/style/DotDensityStyle.js +133 -133
  35. package/src/style/ImageStyle.js +100 -100
  36. package/src/style/IsoFenceStyle.js +217 -217
  37. package/src/style/JoyPlotStyle.js +127 -127
  38. package/src/style/LegoStyle.js +110 -110
  39. package/src/style/MosaicStyle.js +99 -99
  40. package/src/style/NinjaStarStyle.js +102 -102
  41. package/src/style/PillarStyle.js +207 -207
  42. package/src/style/SegmentStyle.js +105 -105
  43. package/src/style/ShapeColorSizeStyle.js +147 -147
  44. package/src/style/SideCategoryStyle.js +112 -112
  45. package/src/style/SideStyle.js +212 -212
  46. package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
  47. package/src/style/SquareColorWebGLStyle.js +126 -126
  48. package/src/style/StrokeStyle.js +135 -135
  49. package/src/style/TanakaStyle.js +69 -69
  50. package/src/style/TextStyle.js +110 -110
  51. package/src/style/TimeSeriesStyle.js +222 -222
  52. package/src/utils/scale.js +218 -218
  53. package/src/utils/stretching.js +120 -120
  54. package/src/utils/ternary.js +208 -203
  55. package/src/utils/utils.js +58 -58
  56. package/src/utils/webGLUtils.js +72 -72
@@ -1,217 +1,217 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { Style } from '../core/Style.js'
5
- import { SideStyle } from './SideStyle.js'
6
-
7
- /** @typedef {{x:number,y:number,or:"v"|"h",c1:import('../core/Dataset.js').Cell|undefined,c2:import('../core/Dataset.js').Cell|undefined}} Side */
8
-
9
- /**
10
- * @module style
11
- * @author Julien Gaffuri
12
- */
13
- export class IsoFenceStyle extends Style {
14
- /** @param {object} opts */
15
- constructor(opts) {
16
- super(opts)
17
- opts = opts || {}
18
-
19
- /**
20
- * The dictionary (string -> color) which give the color of each category.
21
- * @type {object} */
22
- this.color = opts.color
23
-
24
- /** A function returning the height of a cell in geographical unit.
25
- * @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
26
- this.height = opts.height || ((cell, resolution, z, viewScale) => resolution * 0.4)
27
-
28
- /** The perspective angle, in degree, within [-180,180], from [O,x] axis.
29
- * @type {number} */
30
- this.angle = opts.angle != undefined ? opts.angle : 50
31
-
32
- /** A function returning the corner line stroke style.
33
- * @type {function(import('../core/Dataset.js').Cell,number,number,number):string} */
34
- this.cornerLineStrokeColor = opts.cornerLineStrokeColor || ((c, r, z, angle) => '#999')
35
-
36
- /** A function returning the corner line width.
37
- * @type {function(import('../core/Dataset.js').Cell,number,number,number):number} */
38
- this.cornerLineWidth = opts.cornerLineWidth || ((c, r, z, angle) => (angle % 90 == 0 ? 0 : 0.8 * z))
39
-
40
- /**
41
- * Show vertical cross-sections.
42
- * @type {boolean} */
43
- this.sVert = opts.sVert != undefined ? opts.sVert : true
44
-
45
- /**
46
- * Show horizontal cross-sections.
47
- * @type {boolean} */
48
- this.sHor = opts.sHor != undefined ? opts.sHor : true
49
- }
50
-
51
- /**
52
- * @param {Array.<import("../core/Dataset.js").Cell>} cells
53
- * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
54
- * @param {number} resolution
55
- * @override
56
- */
57
- draw(cells, geoCanvas, resolution) {
58
- //filter
59
- if (this.filter) cells = cells.filter(this.filter)
60
-
61
- //
62
- const z = geoCanvas.view.z
63
- const ctx = geoCanvas.offscreenCtx
64
-
65
- //get view scale
66
- const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
67
-
68
- //nb categories - used for radar and agepyramid
69
- const cats = Object.keys(this.color)
70
-
71
- //half resolution
72
- const r2 = resolution / 2
73
-
74
- //get offset
75
- // @ts-ignore
76
- const offset = this.offset(undefined, resolution, z),
77
- dx = offset.dx,
78
- dy = offset.dy
79
-
80
- //make sides
81
- /** @type {Array.<Side>} */
82
- const sides = SideStyle.buildSides(
83
- cells,
84
- resolution,
85
- this.angle % 180 != 90 && this.sVert,
86
- this.angle % 180 != 0 && this.sHor
87
- )
88
-
89
- //
90
- if (sides.length == 0) return
91
-
92
- //angle in radians
93
- const aRad = (this.angle * Math.PI) / 180,
94
- cos = Math.cos(aRad),
95
- sin = Math.sin(aRad)
96
-
97
- //sort sides so that the back ones are drawn first. This depends on the angle.
98
- //depending on distance to the reference corner point
99
- const xCorner = Math.abs(this.angle) < 90 ? geoCanvas.extGeo.xMin : geoCanvas.extGeo.xMax
100
- const yCorner = this.angle < 0 ? geoCanvas.extGeo.yMax : geoCanvas.extGeo.yMin
101
- sides.sort(
102
- (s1, s2) =>
103
- Math.hypot(s2.x - xCorner, s2.y - yCorner) - Math.hypot(s1.x - xCorner, s1.y - yCorner)
104
- )
105
-
106
- //prepare function to draw corner line for a cell *c*
107
- const drawCornerLine = (cell) => {
108
- if (!cell) return
109
- //line style
110
- const lw = this.cornerLineWidth ? this.cornerLineWidth(cell, resolution, z, this.angle) : 0.8 * z
111
- if (lw == 0) return
112
- ctx.strokeStyle = this.cornerLineStrokeColor
113
- ? this.cornerLineStrokeColor(cell, resolution, z, this.angle)
114
- : '#333'
115
- ctx.lineWidth = lw
116
-
117
- //height - in geo
118
- const hG = this.height(cell, resolution, z, viewScale)
119
-
120
- //draw line
121
- ctx.beginPath()
122
- ctx.moveTo(cell.x + r2 + dx, cell.y + r2 + dy)
123
- ctx.lineTo(cell.x + r2 + hG * cos + dx, cell.y + r2 + hG * sin + dy)
124
- ctx.stroke()
125
- }
126
-
127
- //draw sides
128
- ctx.lineCap = 'round'
129
- for (let side of sides) {
130
- const c1 = side.c1,
131
- c2 = side.c2,
132
- x = side.x,
133
- y = side.y
134
-
135
- //heights - in geo
136
- const hG1 = c1 ? this.height(c1, resolution, z, viewScale) : 0,
137
- hG2 = c2 ? this.height(c2, resolution, z, viewScale) : 0
138
-
139
- //compute totals for both cells
140
- const total1 = computeTotal(c1, cats),
141
- total2 = computeTotal(c2, cats)
142
- if (total1 == 0 && total2 == 0) continue
143
-
144
- let cumul1 = 0,
145
- cumul2 = 0
146
- for (let [column, color] of Object.entries(this.color)) {
147
- //draw stripe of side s and category column
148
-
149
- //get values for both cells
150
- let v1 = c1 ? +c1[column] : 0
151
- let v2 = c2 ? +c2[column] : 0
152
- if (v1 == 0 && v2 == 0) continue
153
-
154
- //compute heights
155
- const h1 = (hG1 * cumul1) / total1 || 0
156
- const h1n = (hG1 * (cumul1 + v1)) / total1 || 0
157
- const h2 = (hG2 * cumul2) / total2 || 0
158
- const h2n = (hG2 * (cumul2 + v2)) / total2 || 0
159
-
160
- //make path
161
- ctx.beginPath()
162
- if (side.or == 'h') {
163
- //horizontal side - vertical section
164
- //bottom left
165
- ctx.moveTo(x + h1 * cos + dx, y - r2 + h1 * sin + dy)
166
- //top left
167
- ctx.lineTo(x + h2 * cos + dx, y + r2 + h2 * sin + dy)
168
- //top right
169
- ctx.lineTo(x + h2n * cos + dx, y + r2 + h2n * sin + dy)
170
- //bottom right
171
- ctx.lineTo(x + h1n * cos + dx, y - r2 + h1n * sin + dy)
172
- } else {
173
- //vertical side - horizontal section
174
- //bottom left
175
- ctx.moveTo(x - r2 + h1 * cos + dx, y + h1 * sin + dy)
176
- //bottom right
177
- ctx.lineTo(x + r2 + h2 * cos + dx, y + h2 * sin + dy)
178
- //top right
179
- ctx.lineTo(x + r2 + h2n * cos + dx, y + h2n * sin + dy)
180
- //top left
181
- ctx.lineTo(x - r2 + h1n * cos + dx, y + h1n * sin + dy)
182
- }
183
- //cg.ctx.closePath()
184
-
185
- //fill
186
- ctx.fillStyle = color
187
- ctx.fill()
188
-
189
- cumul1 += v1
190
- cumul2 += v2
191
-
192
- //TODO draw only one line
193
- //draw corner line
194
- //if (side.or == "h") {
195
- drawCornerLine(c1)
196
- drawCornerLine(c2)
197
- //if (this.angle > 0 && side.or == "h") drawCornerLine(c2)
198
- //else drawCornerLine(c2)
199
- //}
200
- }
201
- }
202
-
203
- //update legends
204
- this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
205
- }
206
- }
207
-
208
- const computeTotal = (cell, categories) => {
209
- if (!cell) return 0
210
- let total = 0
211
- for (let column of categories) {
212
- const v = cell[column]
213
- if (!v) continue
214
- total += +v
215
- }
216
- return total || 0
217
- }
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../core/Style.js'
5
+ import { SideStyle } from './SideStyle.js'
6
+
7
+ /** @typedef {{x:number,y:number,or:"v"|"h",c1:import('../core/Dataset.js').Cell|undefined,c2:import('../core/Dataset.js').Cell|undefined}} Side */
8
+
9
+ /**
10
+ * @module style
11
+ * @author Julien Gaffuri
12
+ */
13
+ export class IsoFenceStyle extends Style {
14
+ /** @param {object} opts */
15
+ constructor(opts) {
16
+ super(opts)
17
+ opts = opts || {}
18
+
19
+ /**
20
+ * The dictionary (string -> color) which give the color of each category.
21
+ * @type {object} */
22
+ this.color = opts.color
23
+
24
+ /** A function returning the height of a cell in geographical unit.
25
+ * @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
26
+ this.height = opts.height || ((cell, resolution, z, viewScale) => resolution * 0.4)
27
+
28
+ /** The perspective angle, in degree, within [-180,180], from [O,x] axis.
29
+ * @type {number} */
30
+ this.angle = opts.angle != undefined ? opts.angle : 50
31
+
32
+ /** A function returning the corner line stroke style.
33
+ * @type {function(import('../core/Dataset.js').Cell,number,number,number):string} */
34
+ this.cornerLineStrokeColor = opts.cornerLineStrokeColor || ((c, r, z, angle) => '#999')
35
+
36
+ /** A function returning the corner line width.
37
+ * @type {function(import('../core/Dataset.js').Cell,number,number,number):number} */
38
+ this.cornerLineWidth = opts.cornerLineWidth || ((c, r, z, angle) => (angle % 90 == 0 ? 0 : 0.8 * z))
39
+
40
+ /**
41
+ * Show vertical cross-sections.
42
+ * @type {boolean} */
43
+ this.sVert = opts.sVert != undefined ? opts.sVert : true
44
+
45
+ /**
46
+ * Show horizontal cross-sections.
47
+ * @type {boolean} */
48
+ this.sHor = opts.sHor != undefined ? opts.sHor : true
49
+ }
50
+
51
+ /**
52
+ * @param {Array.<import("../core/Dataset.js").Cell>} cells
53
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
54
+ * @param {number} resolution
55
+ * @override
56
+ */
57
+ draw(cells, geoCanvas, resolution) {
58
+ //filter
59
+ if (this.filter) cells = cells.filter(this.filter)
60
+
61
+ //
62
+ const z = geoCanvas.view.z
63
+ const ctx = geoCanvas.offscreenCtx
64
+
65
+ //get view scale
66
+ const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
67
+
68
+ //nb categories - used for radar and agepyramid
69
+ const cats = Object.keys(this.color)
70
+
71
+ //half resolution
72
+ const r2 = resolution / 2
73
+
74
+ //get offset
75
+ // @ts-ignore
76
+ const offset = this.offset(undefined, resolution, z),
77
+ dx = offset.dx,
78
+ dy = offset.dy
79
+
80
+ //make sides
81
+ /** @type {Array.<Side>} */
82
+ const sides = SideStyle.buildSides(
83
+ cells,
84
+ resolution,
85
+ this.angle % 180 != 90 && this.sVert,
86
+ this.angle % 180 != 0 && this.sHor
87
+ )
88
+
89
+ //
90
+ if (sides.length == 0) return
91
+
92
+ //angle in radians
93
+ const aRad = (this.angle * Math.PI) / 180,
94
+ cos = Math.cos(aRad),
95
+ sin = Math.sin(aRad)
96
+
97
+ //sort sides so that the back ones are drawn first. This depends on the angle.
98
+ //depending on distance to the reference corner point
99
+ const xCorner = Math.abs(this.angle) < 90 ? geoCanvas.extGeo.xMin : geoCanvas.extGeo.xMax
100
+ const yCorner = this.angle < 0 ? geoCanvas.extGeo.yMax : geoCanvas.extGeo.yMin
101
+ sides.sort(
102
+ (s1, s2) =>
103
+ Math.hypot(s2.x - xCorner, s2.y - yCorner) - Math.hypot(s1.x - xCorner, s1.y - yCorner)
104
+ )
105
+
106
+ //prepare function to draw corner line for a cell *c*
107
+ const drawCornerLine = (cell) => {
108
+ if (!cell) return
109
+ //line style
110
+ const lw = this.cornerLineWidth ? this.cornerLineWidth(cell, resolution, z, this.angle) : 0.8 * z
111
+ if (lw == 0) return
112
+ ctx.strokeStyle = this.cornerLineStrokeColor
113
+ ? this.cornerLineStrokeColor(cell, resolution, z, this.angle)
114
+ : '#333'
115
+ ctx.lineWidth = lw
116
+
117
+ //height - in geo
118
+ const hG = this.height(cell, resolution, z, viewScale)
119
+
120
+ //draw line
121
+ ctx.beginPath()
122
+ ctx.moveTo(cell.x + r2 + dx, cell.y + r2 + dy)
123
+ ctx.lineTo(cell.x + r2 + hG * cos + dx, cell.y + r2 + hG * sin + dy)
124
+ ctx.stroke()
125
+ }
126
+
127
+ //draw sides
128
+ ctx.lineCap = 'round'
129
+ for (let side of sides) {
130
+ const c1 = side.c1,
131
+ c2 = side.c2,
132
+ x = side.x,
133
+ y = side.y
134
+
135
+ //heights - in geo
136
+ const hG1 = c1 ? this.height(c1, resolution, z, viewScale) : 0,
137
+ hG2 = c2 ? this.height(c2, resolution, z, viewScale) : 0
138
+
139
+ //compute totals for both cells
140
+ const total1 = computeTotal(c1, cats),
141
+ total2 = computeTotal(c2, cats)
142
+ if (total1 == 0 && total2 == 0) continue
143
+
144
+ let cumul1 = 0,
145
+ cumul2 = 0
146
+ for (let [column, color] of Object.entries(this.color)) {
147
+ //draw stripe of side s and category column
148
+
149
+ //get values for both cells
150
+ let v1 = c1 ? +c1[column] : 0
151
+ let v2 = c2 ? +c2[column] : 0
152
+ if (v1 == 0 && v2 == 0) continue
153
+
154
+ //compute heights
155
+ const h1 = (hG1 * cumul1) / total1 || 0
156
+ const h1n = (hG1 * (cumul1 + v1)) / total1 || 0
157
+ const h2 = (hG2 * cumul2) / total2 || 0
158
+ const h2n = (hG2 * (cumul2 + v2)) / total2 || 0
159
+
160
+ //make path
161
+ ctx.beginPath()
162
+ if (side.or == 'h') {
163
+ //horizontal side - vertical section
164
+ //bottom left
165
+ ctx.moveTo(x + h1 * cos + dx, y - r2 + h1 * sin + dy)
166
+ //top left
167
+ ctx.lineTo(x + h2 * cos + dx, y + r2 + h2 * sin + dy)
168
+ //top right
169
+ ctx.lineTo(x + h2n * cos + dx, y + r2 + h2n * sin + dy)
170
+ //bottom right
171
+ ctx.lineTo(x + h1n * cos + dx, y - r2 + h1n * sin + dy)
172
+ } else {
173
+ //vertical side - horizontal section
174
+ //bottom left
175
+ ctx.moveTo(x - r2 + h1 * cos + dx, y + h1 * sin + dy)
176
+ //bottom right
177
+ ctx.lineTo(x + r2 + h2 * cos + dx, y + h2 * sin + dy)
178
+ //top right
179
+ ctx.lineTo(x + r2 + h2n * cos + dx, y + h2n * sin + dy)
180
+ //top left
181
+ ctx.lineTo(x - r2 + h1n * cos + dx, y + h1n * sin + dy)
182
+ }
183
+ //cg.ctx.closePath()
184
+
185
+ //fill
186
+ ctx.fillStyle = color
187
+ ctx.fill()
188
+
189
+ cumul1 += v1
190
+ cumul2 += v2
191
+
192
+ //TODO draw only one line
193
+ //draw corner line
194
+ //if (side.or == "h") {
195
+ drawCornerLine(c1)
196
+ drawCornerLine(c2)
197
+ //if (this.angle > 0 && side.or == "h") drawCornerLine(c2)
198
+ //else drawCornerLine(c2)
199
+ //}
200
+ }
201
+ }
202
+
203
+ //update legends
204
+ this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
205
+ }
206
+ }
207
+
208
+ const computeTotal = (cell, categories) => {
209
+ if (!cell) return 0
210
+ let total = 0
211
+ for (let column of categories) {
212
+ const v = cell[column]
213
+ if (!v) continue
214
+ total += +v
215
+ }
216
+ return total || 0
217
+ }