gridviz 2.1.14 → 2.1.16

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.
@@ -0,0 +1,108 @@
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Style } from '../Style.js'
5
+
6
+ /**
7
+ * A very generic style that shows grid cells with specific color, size and shape.
8
+ * It can be used to show variables as cell colors, cell size, cell shape, or any combination of the three visual variables.
9
+ *
10
+ * @author Joseph Davies, Julien Gaffuri
11
+ */
12
+ export class ShapeColorSizeStyle_ extends Style {
13
+ /** @param {object} opts */
14
+ constructor(opts) {
15
+ super(opts)
16
+ opts = opts || {}
17
+
18
+ /** A function returning the view scale.
19
+ * @type {function(Array.<import('../Dataset.js').Cell>,number, number):object} */
20
+ this.viewScale = opts.viewScale //(cells,r,z) => {}
21
+
22
+ /** A function returning the color of the cell.
23
+ * @type {function(import('../Dataset.js').Cell,number, number,object):string} */
24
+ this.color = opts.color //(c,r,z,o) => {}
25
+
26
+ /** A function returning the size of a cell in geographical unit.
27
+ * @type {function(import('../Dataset.js').Cell,number, number,object):number} */
28
+ this.size = opts.size //(c,r,z,o) => {}
29
+
30
+ /** A function returning the shape of a cell.
31
+ * @type {function(import("../Dataset.js").Cell,number, number,object):import("../Style.js").Shape} */
32
+ this.shape = opts.shape //(c,r,z,o) => {}
33
+ }
34
+
35
+ /**
36
+ * Draw cells as squares, with various colors and sizes.
37
+ *
38
+ * @param {Array.<import("../Dataset.js").Cell>} cells
39
+ * @param {number} r
40
+ * @param {import("../GeoCanvas.js").GeoCanvas} cg
41
+ */
42
+ draw(cells, r, cg) {
43
+ //filter
44
+ if (this.filter) cells = cells.filter(this.filter)
45
+
46
+ //zoom factor
47
+ const zf = cg.getZf()
48
+
49
+ //get view scale
50
+ const vc = this.viewScale ? this.viewScale(cells, r, zf) : undefined
51
+
52
+ //draw with HTML canvas in geo coordinates
53
+ cg.setCanvasTransform()
54
+
55
+ const r2 = r * 0.5
56
+ for (let c of cells) {
57
+ //color
58
+ let col = this.color ? this.color(c, r, zf, vc) : "black"
59
+ if (!col || col === 'none') continue
60
+
61
+ //size
62
+ const size = this.size ? this.size(c, r, zf, vc) : r
63
+ if (!size) continue
64
+
65
+ //shape
66
+ const shape = this.shape ? this.shape(c, r, zf, vc) : 'square'
67
+ if (shape === 'none') continue
68
+
69
+ //get offset
70
+ const offset = this.offset(c, r, zf)
71
+
72
+ cg.ctx.fillStyle = col
73
+ if (shape === 'square') {
74
+ //draw square
75
+ const d = r * (1 - size / r) * 0.5
76
+ cg.ctx.fillRect(c.x + d + offset.dx, c.y + d + offset.dy, size, size)
77
+ } else if (shape === 'circle') {
78
+ //draw circle
79
+ cg.ctx.beginPath()
80
+ cg.ctx.arc(c.x + r2 + offset.dx, c.y + r2 + offset.dy, size * 0.5, 0, 2 * Math.PI, false)
81
+ cg.ctx.fill()
82
+ } else if (shape === 'donut') {
83
+ //draw donut
84
+ const xc = c.x + r2 + offset.dx,
85
+ yc = c.y + r2 + offset.dy
86
+ cg.ctx.beginPath()
87
+ cg.ctx.moveTo(xc, yc)
88
+ cg.ctx.arc(xc, yc, r2, 0, 2 * Math.PI)
89
+ cg.ctx.arc(xc, yc, (1 - size / r) * r2, 0, 2 * Math.PI, true)
90
+ cg.ctx.closePath()
91
+ cg.ctx.fill()
92
+ } else if (shape === 'diamond') {
93
+ const s2 = size * 0.5
94
+ cg.ctx.beginPath()
95
+ cg.ctx.moveTo(c.x + r2 - s2, c.y + r2)
96
+ cg.ctx.lineTo(c.x + r2, c.y + r2 + s2)
97
+ cg.ctx.lineTo(c.x + r2 + s2, c.y + r2)
98
+ cg.ctx.lineTo(c.x + r2, c.y + r2 - s2)
99
+ cg.ctx.fill()
100
+ } else {
101
+ throw new Error('Unexpected shape:' + shape)
102
+ }
103
+ }
104
+
105
+ //update legends
106
+ this.updateLegends({ style: this, r: r, zf: zf, viewScale: vc })
107
+ }
108
+ }
@@ -1,52 +1,89 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
+
4
5
  /**
5
6
  * Some function [0,1]->[0,1] to stretch range of values.
6
7
  * @see https://github.com/eurostat/gridviz/blob/master/docs/reference.md#stretching
7
8
  * @see https://observablehq.com/@jgaffuri/stretching
8
9
  */
9
10
 
11
+
12
+ export const powerScale = (exponent = 3) => t => Math.pow(t, exponent)
13
+ export const powerInverseScale = (exponent = 3) => t => 1 - Math.pow(1 - t, 1 / exponent)
14
+ export const exponentialScale = (base = 3) => {
15
+ if (base == 0) return t => t
16
+ const a = (Math.exp(base) - 1)
17
+ return t => (Math.exp(t * base) - 1) / a
18
+ }
19
+ export const logarithmicScale = (base = 3) => {
20
+ if (base == 0) return t => t
21
+ return t => 1 - (1 / base) * Math.log(Math.exp(base) * (1 - t) + t)
22
+ }
23
+
24
+ export const circularScale = (alpha = 0.8) => {
25
+ if (alpha == 0) return t => t
26
+ if (alpha == 1) return t => Math.sqrt(t * (2 - t))
27
+ else {
28
+ const a = alpha / (1 - alpha)
29
+ return t => Math.sqrt(1 / (a * a) + t * (2 / a + 2 - t)) - 1 / a
30
+ }
31
+ }
32
+ export const circularInverseScale = (alpha = 0.8) => {
33
+ const f = circularScale(alpha)
34
+ return t => 1 - f(1 - t)
35
+ }
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+ // deprecated
45
+
46
+
10
47
  /**
11
48
  * Function [0,1]->[0,1] to stretch range of values.
12
49
  * Polynomial
13
50
  *
14
51
  * @param {number} t The value to stretch, within [0,1]
15
- * @param {number} alpha 1: no stretching. <1: show low values. >1: show high values.
52
+ * @param {number} exponent 1: no stretching. <1: show low values. >1: show high values.
16
53
  * @returns {number} The stretched value, within [0,1]
17
54
  */
18
- export const sPow = (t, alpha = 3) => Math.pow(t, alpha)
55
+ export const sPow = (t, exponent = 3) => Math.pow(t, exponent)
19
56
 
20
57
  /**
21
58
  * Function [0,1]->[0,1] to stretch range of values.
22
59
  * Polynomial (reverse)
23
60
  *
24
61
  * @param {number} t The value to stretch, within [0,1]
25
- * @param {number} alpha 1: no stretching. <1: show low values. >1: show high values.
62
+ * @param {number} exponent 1: no stretching. <1: show low values. >1: show high values.
26
63
  * @returns {number} The stretched value, within [0,1]
27
64
  */
28
- export const sPowRev = (t, alpha = 3) => 1 - Math.pow(1 - t, 1 / alpha)
65
+ export const sPowRev = (t, exponent = 3) => 1 - Math.pow(1 - t, 1 / exponent)
29
66
 
30
67
  /**
31
68
  * Function [0,1]->[0,1] to stretch range of values.
32
69
  * Exponential
33
70
  *
34
71
  * @param {number} t The value to stretch, within [0,1]
35
- * @param {number} alpha 0: no stretching. -Inf: show low values. Inf: show high values.
72
+ * @param {number} base 0: no stretching. -Inf: show low values. Inf: show high values.
36
73
  * @returns {number} The stretched value, within [0,1]
37
74
  */
38
- export const sExp = (t, alpha = 3) => (alpha == 0 ? t : (Math.exp(t * alpha) - 1) / (Math.exp(alpha) - 1))
75
+ export const sExp = (t, base = 3) => (base == 0 ? t : (Math.exp(t * base) - 1) / (Math.exp(base) - 1))
39
76
 
40
77
  /**
41
78
  * Function [0,1]->[0,1] to stretch range of values.
42
79
  * Exponential (reverse)
43
80
  *
44
81
  * @param {number} t The value to stretch, within [0,1]
45
- * @param {number} alpha 0: no stretching. -Inf: show low values. Inf: show high values.
82
+ * @param {number} base 0: no stretching. -Inf: show low values. Inf: show high values.
46
83
  * @returns {number} The stretched value, within [0,1]
47
84
  */
48
- export const sExpRev = (t, alpha = 3) =>
49
- alpha == 0 ? t : 1 - (1 / alpha) * Math.log(Math.exp(alpha) * (1 - t) + t)
85
+ export const sExpRev = (t, base = 3) =>
86
+ base == 0 ? t : 1 - (1 / base) * Math.log(Math.exp(base) * (1 - t) + t)
50
87
 
51
88
  /**
52
89
  * Function [0,1]->[0,1] to stretch range of values.
@@ -82,36 +119,40 @@ export const sCircleHigh = (t, alpha = 0.8) => 1 - sCircleLow(1 - t, alpha)
82
119
  /**
83
120
  * Inverse function of sExp
84
121
  * @param {number} y
85
- * @param {number} alpha
122
+ * @param {number} base
86
123
  * @returns {number}
87
124
  */
88
- export const sExpInverse = (y, alpha = 3) =>
89
- alpha == 0 ? y : (1 / alpha) * Math.log(1 - y + y * Math.exp(alpha))
125
+ export const sExpInverse = (y, base = 3) =>
126
+ base == 0 ? y : (1 / base) * Math.log(1 - y + y * Math.exp(base))
90
127
 
91
128
  /**
92
129
  * Inverse function of sExpRev
93
130
  * @param {number} y
94
- * @param {number} alpha
131
+ * @param {number} base
95
132
  * @returns {number}
96
133
  */
97
- export const sExpRevInverse = (y, alpha = 3) => (Math.exp(-alpha * y) - 1) / (Math.exp(-alpha) - 1)
134
+ export const sExpRevInverse = (y, base = 3) => (Math.exp(-base * y) - 1) / (Math.exp(-base) - 1)
98
135
 
99
136
  /**
100
137
  * Inverse function of sPow
101
138
  * @param {number} y
102
- * @param {number} alpha
139
+ * @param {number} exponent
103
140
  * @returns {number}
104
141
  */
105
142
 
106
- export const sPowInverse = (y, alpha = 3) => Math.pow(y, 1 / alpha)
143
+ export const sPowInverse = (y, exponent = 3) => Math.pow(y, 1 / exponent)
144
+
145
+
146
+
147
+
107
148
 
108
149
  /**
109
150
  * Inverse function of sPowRev
110
151
  * @param {number} y
111
- * @param {number} alpha
152
+ * @param {number} exponent
112
153
  * @returns {number}
113
154
  */
114
- export const sPowRevInverse = (y, alpha = 3) => 1 - Math.pow(1 - y, alpha)
155
+ export const sPowRevInverse = (y, exponent = 3) => 1 - Math.pow(1 - y, exponent)
115
156
 
116
157
  //test code
117
158
  /*