gridviz 3.0.19 → 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 (55) hide show
  1. package/README.md +128 -128
  2. package/dist/gridviz.js +7861 -7861
  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 -430
  9. package/src/core/Layer.js +23 -23
  10. package/src/core/Legend.js +108 -108
  11. package/src/core/Map.js +516 -516
  12. package/src/core/MultiResolutionDataset.js +93 -93
  13. package/src/core/Style.js +98 -98
  14. package/src/dataset/CSVGrid.js +112 -112
  15. package/src/dataset/GeoTIFF.js +122 -122
  16. package/src/dataset/JSGrid.js +55 -55
  17. package/src/dataset/TiledGrid.js +302 -302
  18. package/src/dataset/worker.js +18 -18
  19. package/src/index.js +77 -77
  20. package/src/layer/BackgroundLayer.js +162 -162
  21. package/src/layer/BackgroundLayerImage.js +81 -81
  22. package/src/layer/BackgroundLayerWMS.js +104 -104
  23. package/src/layer/GeoJSONLayer.js +214 -214
  24. package/src/layer/GridLayer.js +148 -148
  25. package/src/layer/LabelLayer.js +194 -194
  26. package/src/legend/ColorCategoryLegend.js +109 -109
  27. package/src/legend/ColorDiscreteLegend.js +100 -100
  28. package/src/legend/ColorLegend.js +115 -115
  29. package/src/legend/OrientationLegend.js +89 -89
  30. package/src/legend/SizeLegend.js +224 -224
  31. package/src/legend/TernaryLegend.js +302 -302
  32. package/src/style/CompositionStyle.js +291 -291
  33. package/src/style/DotDensityStyle.js +133 -133
  34. package/src/style/ImageStyle.js +100 -100
  35. package/src/style/IsoFenceStyle.js +217 -217
  36. package/src/style/JoyPlotStyle.js +127 -127
  37. package/src/style/LegoStyle.js +110 -110
  38. package/src/style/MosaicStyle.js +99 -99
  39. package/src/style/NinjaStarStyle.js +102 -102
  40. package/src/style/PillarStyle.js +207 -207
  41. package/src/style/SegmentStyle.js +105 -105
  42. package/src/style/ShapeColorSizeStyle.js +147 -147
  43. package/src/style/SideCategoryStyle.js +112 -112
  44. package/src/style/SideStyle.js +212 -212
  45. package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
  46. package/src/style/SquareColorWebGLStyle.js +126 -126
  47. package/src/style/StrokeStyle.js +135 -135
  48. package/src/style/TanakaStyle.js +69 -69
  49. package/src/style/TextStyle.js +110 -110
  50. package/src/style/TimeSeriesStyle.js +222 -222
  51. package/src/utils/scale.js +218 -218
  52. package/src/utils/stretching.js +120 -120
  53. package/src/utils/ternary.js +208 -208
  54. package/src/utils/utils.js +58 -58
  55. 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
+ }