gridviz 2.1.17 → 3.0.1

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 +2 -3
  2. package/dist/gridviz.js +8659 -9294
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +3 -2
  5. package/src/button/Button.js +14 -15
  6. package/src/button/FullscreenButton.js +14 -14
  7. package/src/button/ZoomButtons.js +2 -2
  8. package/src/{DatasetComponent.js → core/Dataset.js} +33 -13
  9. package/src/core/Drawable.js +60 -0
  10. package/src/{GeoCanvas.js → core/GeoCanvas.js} +65 -155
  11. package/src/core/Layer.js +24 -0
  12. package/src/{Legend.js → core/Legend.js} +24 -1
  13. package/src/core/Map.js +474 -0
  14. package/src/core/MultiResolutionDataset.js +96 -0
  15. package/src/core/Style.js +84 -0
  16. package/src/dataset/COGeo.js +5 -5
  17. package/src/dataset/CSVGrid.js +43 -41
  18. package/src/dataset/GeoTIFF.js +9 -14
  19. package/src/dataset/{LGrid.js → JSGrid.js} +9 -11
  20. package/src/dataset/TiledGrid.js +68 -45
  21. package/src/index.js +22 -29
  22. package/src/{BackgroundLayer.js → layer/BackgroundLayer.js} +27 -52
  23. package/src/{BackgroundLayerWMS.js → layer/BackgroundLayerWMS.js} +21 -45
  24. package/src/{LineLayer.js → layer/GeoJSONLayer.js} +22 -23
  25. package/src/layer/GridLayer.js +160 -0
  26. package/src/{LabelLayer.js → layer/LabelLayer.js} +25 -23
  27. package/src/legend/ColorCategoryLegend.js +9 -24
  28. package/src/legend/ColorDiscreteLegend.js +20 -24
  29. package/src/legend/ColorLegend.js +21 -33
  30. package/src/legend/OrientationLegend.js +90 -0
  31. package/src/legend/SizeLegend.js +153 -72
  32. package/src/style/CompositionStyle.js +71 -84
  33. package/src/style/ContourStyle.js +2 -36
  34. package/src/style/DotDensityStyle.js +50 -73
  35. package/src/style/IsoFenceStyle.js +59 -70
  36. package/src/style/JoyPlotStyle.js +41 -48
  37. package/src/style/LegoStyle.js +4 -4
  38. package/src/style/MosaicStyle.js +30 -39
  39. package/src/style/NinjaStarStyle.js +45 -68
  40. package/src/style/PillarStyle.js +70 -93
  41. package/src/style/SegmentStyle.js +37 -75
  42. package/src/style/ShapeColorSizeStyle.js +49 -98
  43. package/src/style/SideCategoryStyle.js +112 -0
  44. package/src/style/SideStyle.js +99 -133
  45. package/src/style/{SquareColorCatWGLStyle.js → SquareColorCategoryWebGLStyle.js} +28 -41
  46. package/src/style/{SquareColorWGLStyle.js → SquareColorWebGLStyle.js} +28 -49
  47. package/src/style/StrokeStyle.js +43 -70
  48. package/src/style/TanakaStyle.js +34 -132
  49. package/src/style/TextStyle.js +43 -64
  50. package/src/style/TimeSeriesStyle.js +44 -75
  51. package/src/utils/WebGLSquareColoringAdvanced.js +4 -4
  52. package/src/utils/scale.js +217 -0
  53. package/src/utils/stretching.js +86 -129
  54. package/src/utils/{Utils.js → utils.js} +15 -0
  55. package/src/utils/webGLUtils.js +4 -5
  56. package/src/utils/zoomUtils.js +30 -30
  57. package/src/App.js +0 -760
  58. package/src/Dataset.js +0 -76
  59. package/src/Layer.js +0 -103
  60. package/src/Style.js +0 -131
  61. package/src/dataset/GridTile.js +0 -41
  62. package/src/legend/SegmentOrientationLegend.js +0 -87
  63. package/src/legend/SegmentWidthLegend.js +0 -101
  64. package/src/style/CompositionStyle_.js +0 -293
  65. package/src/style/ShapeColorSizeStyle_.js +0 -108
  66. package/src/style/SideCatStyle.js +0 -172
  67. /package/src/{Tooltip.js → core/Tooltip.js} +0 -0
@@ -2,171 +2,128 @@
2
2
  'use strict'
3
3
 
4
4
 
5
+ //TODO invert for circular
6
+ //TODO use Math.sqrt
7
+ //TODO validate
8
+
9
+
5
10
  /**
6
11
  * Some function [0,1]->[0,1] to stretch range of values.
7
12
  * @see https://github.com/eurostat/gridviz/blob/master/docs/reference.md#stretching
8
13
  * @see https://observablehq.com/@jgaffuri/stretching
9
14
  */
10
15
 
16
+ //identity function
17
+ const identity = t => t
18
+ identity.invert = identity
11
19
 
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)
20
+
21
+ /**
22
+ * @param {number} base
23
+ * @returns {function(number):number}
24
+ */
14
25
  export const exponentialScale = (base = 3) => {
15
- if (base == 0) return t => t
26
+ if (base == 0) return identity
16
27
  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)
28
+ const f = t => (Math.exp(t * base) - 1) / a
29
+ f.invert = t => Math.log(a * t + 1) / base
30
+ return f
22
31
  }
23
32
 
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)
33
+ /**
34
+ * @param {number} base
35
+ * @returns {function(number):number}
36
+ */
37
+ export const logarithmicScale = (base = 3) => {
38
+ if (base == 0) return identity
39
+ const a = Math.exp(base), b = 1 - a
40
+ const f = t => 1 - Math.log(a + t * b) / base
41
+ f.invert = t => (Math.exp((1 - t) * base) - a) / b
42
+ return f
35
43
  }
36
44
 
37
45
 
38
46
 
39
47
 
40
48
 
41
-
42
-
43
-
44
- // deprecated
45
-
46
-
47
- /**
48
- * Function [0,1]->[0,1] to stretch range of values.
49
- * Polynomial
50
- *
51
- * @param {number} t The value to stretch, within [0,1]
52
- * @param {number} exponent 1: no stretching. <1: show low values. >1: show high values.
53
- * @returns {number} The stretched value, within [0,1]
54
- */
55
- export const sPow = (t, exponent = 3) => Math.pow(t, exponent)
56
-
57
- /**
58
- * Function [0,1]->[0,1] to stretch range of values.
59
- * Polynomial (reverse)
60
- *
61
- * @param {number} t The value to stretch, within [0,1]
62
- * @param {number} exponent 1: no stretching. <1: show low values. >1: show high values.
63
- * @returns {number} The stretched value, within [0,1]
64
- */
65
- export const sPowRev = (t, exponent = 3) => 1 - Math.pow(1 - t, 1 / exponent)
66
-
67
- /**
68
- * Function [0,1]->[0,1] to stretch range of values.
69
- * Exponential
70
- *
71
- * @param {number} t The value to stretch, within [0,1]
72
- * @param {number} base 0: no stretching. -Inf: show low values. Inf: show high values.
73
- * @returns {number} The stretched value, within [0,1]
74
- */
75
- export const sExp = (t, base = 3) => (base == 0 ? t : (Math.exp(t * base) - 1) / (Math.exp(base) - 1))
76
-
77
49
  /**
78
- * Function [0,1]->[0,1] to stretch range of values.
79
- * Exponential (reverse)
80
- *
81
- * @param {number} t The value to stretch, within [0,1]
82
- * @param {number} base 0: no stretching. -Inf: show low values. Inf: show high values.
83
- * @returns {number} The stretched value, within [0,1]
50
+ * @param {number} exponent
51
+ * @returns {function(number):number}
84
52
  */
85
- export const sExpRev = (t, base = 3) =>
86
- base == 0 ? t : 1 - (1 / base) * Math.log(Math.exp(base) * (1 - t) + t)
53
+ export const powerScale = (exponent = 3) => {
54
+ if (exponent == 1) return identity
55
+ //TODO if (exponent == 0.5) return Math.sqrt
56
+ const f = t => Math.pow(t, exponent)
57
+ const a = 1 / exponent
58
+ f.invert = t => Math.pow(t, a)
59
+ return f
60
+ }
87
61
 
88
62
  /**
89
- * Function [0,1]->[0,1] to stretch range of values.
90
- * Circle, show low values
91
- * NB: sCircleHigh and sCircleLow are inverse functions of each other.
92
- *
93
- * @param {number} t The value to stretch, within [0,1]
94
- * @param {number} alpha 0: no stretching. 1: perfect circle section
95
- * @returns {number} The stretched value, within [0,1]
63
+ * @param {number} exponent
64
+ * @returns {function(number):number}
96
65
  */
97
- export const sCircleLow = (t, alpha = 0.8) => {
98
- if (alpha == 0) return t
99
- if (alpha == 1) return Math.sqrt(t * (2 - t))
100
- const a = alpha / (1 - alpha)
101
- return Math.sqrt(1 / (a * a) + t * (2 / a + 2 - t)) - 1 / a
66
+ export const powerInverseScale = (exponent = 3) => {
67
+ if (exponent == 1) return identity
68
+ //TODO if (exponent == 2) return t => 1 - Math.sqrt(1 - t)
69
+ const a = 1 / exponent
70
+ const f = t => 1 - Math.pow(1 - t, a)
71
+ f.invert = t => 1 - Math.pow(1 - t, exponent)
72
+ return f
102
73
  }
103
74
 
104
- /**
105
- * Function [0,1]->[0,1] to stretch range of values.
106
- * Circle, show high values
107
- * NB: sCircleHigh and sCircleLow are inverse functions of each other.
108
- *
109
- * @param {number} t The value to stretch, within [0,1]
110
- * @param {number} alpha 0: no stretching. 1: perfect circle section
111
- * @returns {number} The stretched value, within [0,1]
112
- */
113
- export const sCircleHigh = (t, alpha = 0.8) => 1 - sCircleLow(1 - t, alpha)
114
75
 
115
- /**
116
- * Inverse functions
117
- */
118
76
 
119
- /**
120
- * Inverse function of sExp
121
- * @param {number} y
122
- * @param {number} base
123
- * @returns {number}
124
- */
125
- export const sExpInverse = (y, base = 3) =>
126
- base == 0 ? y : (1 / base) * Math.log(1 - y + y * Math.exp(base))
127
77
 
128
78
  /**
129
- * Inverse function of sExpRev
130
- * @param {number} y
131
- * @param {number} base
132
- * @returns {number}
79
+ * @param {number} circularity
80
+ * @returns {function(number):number}
133
81
  */
134
- export const sExpRevInverse = (y, base = 3) => (Math.exp(-base * y) - 1) / (Math.exp(-base) - 1)
82
+ export const circularScale = (circularity = 0.8) => {
83
+ if (circularity == 0) return identity
84
+ if (circularity == 1) return t => Math.sqrt(t * (2 - t))
85
+ else {
86
+ const a = circularity / (1 - circularity)
87
+ return t => Math.sqrt(1 / (a * a) + t * (2 / a + 2 - t)) - 1 / a
88
+ }
89
+ }
135
90
 
136
91
  /**
137
- * Inverse function of sPow
138
- * @param {number} y
139
- * @param {number} exponent
140
- * @returns {number}
92
+ * @param {number} circularity
93
+ * @returns {function(number):number}
141
94
  */
142
-
143
- export const sPowInverse = (y, exponent = 3) => Math.pow(y, 1 / exponent)
144
-
95
+ export const circularInverseScale = (circularity = 0.8) => {
96
+ if (circularity == 0) return identity
97
+ const f = circularScale(circularity)
98
+ return t => 1 - f(1 - t)
99
+ }
145
100
 
146
101
 
147
102
 
148
103
 
149
- /**
150
- * Inverse function of sPowRev
151
- * @param {number} y
152
- * @param {number} exponent
153
- * @returns {number}
154
- */
155
- export const sPowRevInverse = (y, exponent = 3) => 1 - Math.pow(1 - y, exponent)
156
104
 
157
- //test code
105
+ //test
158
106
  /*
159
- for (let i = 0; i <= 1; i += 0.001) {
160
- //const v = gviz.sExp(gviz.sExpInverse(i));
161
- //const v = gviz.sExpInverse(gviz.sExp(i));
162
- //const v = gviz.sExpRev(gviz.sExpRevInverse(i));
163
- //const v = gviz.sExpRevInverse(gviz.sExpRev(i));
164
- //const v = gviz.sPow(gviz.sPowInverse(i));
165
- //const v = gviz.sPowInverse(gviz.sPow(i));
166
- //const v = gviz.sPowRev(gviz.sPowRevInverse(i));
167
- //const v = gviz.sPowRevInverse(gviz.sPowRev(i));
168
- //const v = gviz.sCircleLow(gviz.sCircleHigh(i));
169
- //const v = gviz.sCircleHigh(gviz.sCircleLow(i));
170
- console.log(i - v)
107
+ const test = (f, fun, a, err = 1e-12) => {
108
+ for (let t = 0; t <= 1; t += 1 / 50) {
109
+ const er = t - f.invert(f(t))
110
+ if (Math.abs(er) < err) continue
111
+ console.log(fun, a, er)
112
+ }
171
113
  }
172
- */
114
+
115
+ for (let fun of [powerScale, powerInverseScale])
116
+ for (let exp = -30; exp <= 50; exp += 1) {
117
+ if (exp == 0) continue
118
+ const f = fun(exp)
119
+ test(f, fun, exp)
120
+ }
121
+
122
+
123
+ for (let fun of [exponentialScale, logarithmicScale])
124
+ for (let base = -20; base <= 20; base += 1) {
125
+ //if (exp == 0) continue
126
+ const f = fun(base)
127
+ test(f, fun, base, 1e-10)
128
+ }
129
+ */
@@ -7,6 +7,7 @@
7
7
  * @param {number} v the value
8
8
  * @param {Array.<number>} breaks the breaks
9
9
  * @returns The class id, from 0 to breaks.length
10
+ * @deprecated use getClassifier instead
10
11
  */
11
12
  export function getClass(v, breaks) {
12
13
  if (!breaks) return
@@ -16,6 +17,20 @@ export function getClass(v, breaks) {
16
17
  return breaks.length
17
18
  }
18
19
 
20
+
21
+
22
+ //take 'nice' value (power of ten, or multiple)
23
+ export function nice(v, multiples = [8, 6, 5, 4, 2.5, 2]) {
24
+ //compute bigger power of ten below
25
+ const v_ = Math.pow(10, Math.floor(Math.log10(v)))
26
+ for (let multiple of multiples)
27
+ if (v_ * multiple <= v) return v_ * multiple
28
+ return v_
29
+ }
30
+
31
+
32
+
33
+
19
34
  export let monitor = false
20
35
 
21
36
  let previousDate
@@ -7,10 +7,11 @@
7
7
  * @param {object} opts
8
8
  * @returns {{canvas:HTMLCanvasElement, gl:WebGLRenderingContext}}
9
9
  */
10
- export function makeWebGLCanvas(width, height, opts) {
10
+ export function makeWebGLCanvas(width, height, opts={}) {
11
11
  const canvas = document.createElement('canvas')
12
12
  canvas.setAttribute('width', width)
13
13
  canvas.setAttribute('height', height)
14
+ /** @type {WebGLRenderingContext} */
14
15
  const gl = canvas.getContext('webgl', opts)
15
16
  if (!gl) {
16
17
  throw new Error('Unable to initialize WebGL. Your browser or machine may not support it.')
@@ -61,10 +62,8 @@ export function createShader(gl, type, ...sources) {
61
62
  export function checkWebGLSupport() {
62
63
  try {
63
64
  const canvas = document.createElement('canvas')
64
- return !!window.WebGLRenderingContext &&
65
- (canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
66
- ? true
67
- : false
65
+ return !!(!!window.WebGLRenderingContext &&
66
+ (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')))
68
67
  } catch (err) {
69
68
  return false
70
69
  }
@@ -4,7 +4,7 @@
4
4
  /**
5
5
  *
6
6
  * @param {import("../App").App} app
7
- * @param {number} zfTarget
7
+ * @param {number} zTarget
8
8
  * @param {number} factor
9
9
  * @param {number} delayMs
10
10
  * @param {function|undefined} callback
@@ -13,7 +13,7 @@
13
13
  */
14
14
  export function zoomTo(
15
15
  app,
16
- zfTarget,
16
+ zTarget,
17
17
  factor = 1.01,
18
18
  delayMs = 0,
19
19
  callback = undefined,
@@ -26,22 +26,22 @@ export function zoomTo(
26
26
  factor = 1.01
27
27
  }
28
28
 
29
- const zfIni = app.getZoomFactor()
30
- if (zfTarget == zfIni) return
31
- if (zfTarget < zfIni) factor = 1 / factor
32
- let zf = zfIni
29
+ const zIni = map.getZoom()
30
+ if (zTarget == zIni) return
31
+ if (zTarget < zIni) factor = 1 / factor
32
+ let z = zIni
33
33
  let timer = setInterval(() => {
34
34
  //compute new zoom level
35
- zf = app.getZoomFactor() * factor
36
- if (zfTarget > zfIni && zf > zfTarget) zf = zfTarget
37
- if (zfTarget < zfIni && zf < zfTarget) zf = zfTarget
35
+ z = map.getZoom() * factor
36
+ if (zTarget > zIni && z > zTarget) z = zTarget
37
+ if (zTarget < zIni && z < zTarget) z = zTarget
38
38
 
39
39
  //set new zoom level
40
- app.setZoomFactor(zf)
41
- app.redraw()
40
+ map.setZoom(z)
41
+ map.redraw()
42
42
 
43
43
  //target reached
44
- if (zf == zfTarget) {
44
+ if (z == zTarget) {
45
45
  clearInterval(timer)
46
46
  //trigger callback, if any
47
47
  if (callback)
@@ -58,7 +58,7 @@ export function zoomTo(
58
58
  * @param {import("../App").App} app
59
59
  * @param {number} xTarget
60
60
  * @param {number} yTarget
61
- * @param {number} zfTarget
61
+ * @param {number} zTarget
62
62
  * @param {number} progressFactorPix
63
63
  * @param {number} delayMs
64
64
  * @param {function|undefined} callback
@@ -69,38 +69,38 @@ export function goToStraight(
69
69
  app,
70
70
  xTarget = NaN,
71
71
  yTarget = NaN,
72
- zfTarget = NaN,
72
+ zTarget = NaN,
73
73
  progressFactorPix = 5,
74
74
  delayMs = 0,
75
75
  callback = undefined,
76
76
  delayBeforeCallBackMs = 0
77
77
  ) {
78
78
  //store initial position/zoom
79
- const zfIni = app.getZoomFactor()
80
- const cIni = app.getGeoCenter()
79
+ const zIni = map.getZoom()
80
+ const cIni = map.getView()
81
81
 
82
82
  //default
83
83
  xTarget = isNaN(xTarget) ? cIni.x : xTarget
84
84
  yTarget = isNaN(yTarget) ? cIni.y : yTarget
85
- zfTarget = isNaN(zfTarget) ? zfIni : zfTarget
85
+ zTarget = isNaN(zTarget) ? zIni : zTarget
86
86
 
87
87
  //prepare for pan
88
88
  const dx = xTarget - cIni.x
89
89
  const dy = yTarget - cIni.y
90
90
  let d = Math.hypot(dx, dy)
91
- const ddx = (progressFactorPix * zfIni * dx) / d
92
- const ddy = (progressFactorPix * zfIni * dy) / d
91
+ const ddx = (progressFactorPix * zIni * dx) / d
92
+ const ddy = (progressFactorPix * zIni * dy) / d
93
93
 
94
94
  //prepare for zoom
95
- let r = zfTarget / zfIni
96
- const n = d / (progressFactorPix * zfIni)
95
+ let r = zTarget / zIni
96
+ const n = d / (progressFactorPix * zIni)
97
97
  const zoomFactor = d > 0 ? Math.pow(r, 1 / n) : Math.pow(r, 1 / 10) //TODO not 10 ?
98
98
 
99
99
  //timer
100
100
  let timer = setInterval(() => {
101
101
  //compute and set new position
102
102
  if (d > 0) {
103
- const c = app.getGeoCenter()
103
+ const c = map.getView()
104
104
  let nx = c.x + ddx
105
105
  let ny = c.y + ddy
106
106
  //if went too far, stop at target values
@@ -108,23 +108,23 @@ export function goToStraight(
108
108
  if (c.x < xTarget && xTarget < nx) nx = xTarget
109
109
  if (ny < yTarget && yTarget < c.y) ny = yTarget
110
110
  if (c.y < yTarget && yTarget < ny) ny = yTarget
111
- app.setGeoCenter({ x: nx, y: ny })
111
+ map.setGeoCenter({ x: nx, y: ny })
112
112
  if (nx == xTarget && ny == yTarget) d = 0
113
113
  }
114
114
 
115
115
  //compute and set new zoom
116
116
  if (r != 1) {
117
- const zf = app.getZoomFactor()
118
- let nzf = zoomFactor * zf
117
+ const z = map.getZoom()
118
+ let nz = zoomFactor * z
119
119
  //if went too far, stop at target values
120
- if (nzf < zfTarget && zfTarget < zf) nzf = zfTarget
121
- if (zf < zfTarget && zfTarget < nzf) nzf = zfTarget
122
- app.setZoomFactor(nzf)
123
- if (nzf == zfTarget) r = 1
120
+ if (nz < zTarget && zTarget < z) nz = zTarget
121
+ if (z < zTarget && zTarget < nz) nz = zTarget
122
+ map.setZoom(nz)
123
+ if (nz == zTarget) r = 1
124
124
  }
125
125
 
126
126
  //redraw
127
- app.redraw()
127
+ map.redraw()
128
128
 
129
129
  //if target reached, stop
130
130
  if (d == 0 && r == 1) {