gridviz 2.1.14 → 2.1.15

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,6 +1,25 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
+
5
+
6
+ //stretching functions [0,1]=>[0,1]
7
+
8
+ export const powerScale = (exponent = 3) => t => Math.pow(t, exponent)
9
+ export const powerInverseScale = (exponent = 3) => t => 1 - Math.pow(1 - t, 1 / exponent)
10
+ export const exponentialScale = (base = 3) => {
11
+ if (base == 0) return t => t
12
+ const a = (Math.exp(base) - 1)
13
+ return t => (Math.exp(t * base) - 1) / a
14
+ }
15
+ export const logarithmicScale = (base = 3) => {
16
+ if (base == 0) return t => t
17
+ return t => 1 - (1 / base) * Math.log(Math.exp(base) * (1 - t) + t)
18
+ }
19
+
20
+
21
+
22
+
4
23
  /**
5
24
  * Some function [0,1]->[0,1] to stretch range of values.
6
25
  * @see https://github.com/eurostat/gridviz/blob/master/docs/reference.md#stretching
@@ -12,41 +31,41 @@
12
31
  * Polynomial
13
32
  *
14
33
  * @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.
34
+ * @param {number} exponent 1: no stretching. <1: show low values. >1: show high values.
16
35
  * @returns {number} The stretched value, within [0,1]
17
36
  */
18
- export const sPow = (t, alpha = 3) => Math.pow(t, alpha)
37
+ export const sPow = (t, exponent = 3) => Math.pow(t, exponent)
19
38
 
20
39
  /**
21
40
  * Function [0,1]->[0,1] to stretch range of values.
22
41
  * Polynomial (reverse)
23
42
  *
24
43
  * @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.
44
+ * @param {number} exponent 1: no stretching. <1: show low values. >1: show high values.
26
45
  * @returns {number} The stretched value, within [0,1]
27
46
  */
28
- export const sPowRev = (t, alpha = 3) => 1 - Math.pow(1 - t, 1 / alpha)
47
+ export const sPowRev = (t, exponent = 3) => 1 - Math.pow(1 - t, 1 / exponent)
29
48
 
30
49
  /**
31
50
  * Function [0,1]->[0,1] to stretch range of values.
32
51
  * Exponential
33
52
  *
34
53
  * @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.
54
+ * @param {number} base 0: no stretching. -Inf: show low values. Inf: show high values.
36
55
  * @returns {number} The stretched value, within [0,1]
37
56
  */
38
- export const sExp = (t, alpha = 3) => (alpha == 0 ? t : (Math.exp(t * alpha) - 1) / (Math.exp(alpha) - 1))
57
+ export const sExp = (t, base = 3) => (base == 0 ? t : (Math.exp(t * base) - 1) / (Math.exp(base) - 1))
39
58
 
40
59
  /**
41
60
  * Function [0,1]->[0,1] to stretch range of values.
42
61
  * Exponential (reverse)
43
62
  *
44
63
  * @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.
64
+ * @param {number} base 0: no stretching. -Inf: show low values. Inf: show high values.
46
65
  * @returns {number} The stretched value, within [0,1]
47
66
  */
48
- export const sExpRev = (t, alpha = 3) =>
49
- alpha == 0 ? t : 1 - (1 / alpha) * Math.log(Math.exp(alpha) * (1 - t) + t)
67
+ export const sExpRev = (t, base = 3) =>
68
+ base == 0 ? t : 1 - (1 / base) * Math.log(Math.exp(base) * (1 - t) + t)
50
69
 
51
70
  /**
52
71
  * Function [0,1]->[0,1] to stretch range of values.
@@ -82,36 +101,40 @@ export const sCircleHigh = (t, alpha = 0.8) => 1 - sCircleLow(1 - t, alpha)
82
101
  /**
83
102
  * Inverse function of sExp
84
103
  * @param {number} y
85
- * @param {number} alpha
104
+ * @param {number} base
86
105
  * @returns {number}
87
106
  */
88
- export const sExpInverse = (y, alpha = 3) =>
89
- alpha == 0 ? y : (1 / alpha) * Math.log(1 - y + y * Math.exp(alpha))
107
+ export const sExpInverse = (y, base = 3) =>
108
+ base == 0 ? y : (1 / base) * Math.log(1 - y + y * Math.exp(base))
90
109
 
91
110
  /**
92
111
  * Inverse function of sExpRev
93
112
  * @param {number} y
94
- * @param {number} alpha
113
+ * @param {number} base
95
114
  * @returns {number}
96
115
  */
97
- export const sExpRevInverse = (y, alpha = 3) => (Math.exp(-alpha * y) - 1) / (Math.exp(-alpha) - 1)
116
+ export const sExpRevInverse = (y, base = 3) => (Math.exp(-base * y) - 1) / (Math.exp(-base) - 1)
98
117
 
99
118
  /**
100
119
  * Inverse function of sPow
101
120
  * @param {number} y
102
- * @param {number} alpha
121
+ * @param {number} exponent
103
122
  * @returns {number}
104
123
  */
105
124
 
106
- export const sPowInverse = (y, alpha = 3) => Math.pow(y, 1 / alpha)
125
+ export const sPowInverse = (y, exponent = 3) => Math.pow(y, 1 / exponent)
126
+
127
+
128
+
129
+
107
130
 
108
131
  /**
109
132
  * Inverse function of sPowRev
110
133
  * @param {number} y
111
- * @param {number} alpha
134
+ * @param {number} exponent
112
135
  * @returns {number}
113
136
  */
114
- export const sPowRevInverse = (y, alpha = 3) => 1 - Math.pow(1 - y, alpha)
137
+ export const sPowRevInverse = (y, exponent = 3) => 1 - Math.pow(1 - y, exponent)
115
138
 
116
139
  //test code
117
140
  /*