gridviz 3.0.28 → 3.0.29

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gridviz",
3
- "version": "3.0.28",
3
+ "version": "3.0.29",
4
4
  "description": "Visualization tool for gridded statistics",
5
5
  "keywords": [
6
6
  "statistics",
package/src/index.js CHANGED
@@ -24,10 +24,9 @@ export { TextStyle } from './style/TextStyle.js'
24
24
  export { PillarStyle } from './style/PillarStyle.js'
25
25
  export { SideStyle } from './style/SideStyle.js'
26
26
  export { ShadingStyle } from './style/ShadingStyle.js'
27
- //export { ContourStyle } from './style/ContourStyle.js'
28
27
  export { SideCategoryStyle } from './style/SideCategoryStyle.js'
29
28
  export { DotDensityStyle } from './style/DotDensityStyle.js'
30
- export { TanakaStyle } from './style/TanakaStyle.js'
29
+ export { SideTanakaStyle } from './style/SideTanakaStyle.js'
31
30
  export { LegoStyle } from './style/LegoStyle.js'
32
31
  export { SquareColorWebGLStyle } from './style/SquareColorWebGLStyle.js'
33
32
  export { SquareColorCategoryWebGLStyle } from './style/SquareColorCategoryWebGLStyle.js'
@@ -1,10 +1,14 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
- import { TanakaStyle } from './TanakaStyle.js'
4
+ //import { TanakaStyle } from './SideTanakaStyle___OLD.js'
5
5
  import { StrokeStyle } from './StrokeStyle.js'
6
6
  import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.js'
7
7
  import { Style } from '../core/Style.js'
8
+ //import { SideStyle } from './SideStyle.js'
9
+ import { classifier as clFun, colorClassifier as cclFun } from '../utils/scale.js'
10
+ import { SideTanakaStyle } from './SideTanakaStyle.js'
11
+
8
12
 
9
13
  /**
10
14
  * @module style
@@ -30,12 +34,30 @@ export class LegoStyle {
30
34
  //"#eee" //whithe
31
35
  ]*/
32
36
 
33
- opts.colDark = opts.colDark || '#333'
34
- opts.colBright = opts.colBright || '#aaa'
35
- opts.widthFactor = opts.widthFactor || 0.12
37
+ opts.colorDark = opts.colorDark || '#333'
38
+ opts.colorBright = opts.colorBright || '#aaa'
39
+
40
+ //make classifier
41
+ const classifier = clFun(breaks)
42
+ const classifier2 = cell => classifier(value(cell))
43
+ //make colors table
44
+ const colorsDict = {}
45
+ for (let i = 0; i < colors.length; i++) colorsDict[i + ''] = colors[i]
46
+
47
+ //make cell fill style
48
+ const cellStyle = new SquareColorCategoryWebGLStyle({
49
+ code: classifier2,
50
+ color: colorsDict,
51
+ })
52
+
53
+ //make tanaka side style
54
+ const tanakaStyle = new SideTanakaStyle({
55
+ classifier: () => classifier2,
56
+ colorDark : opts.colorDark,
57
+ colorBright : opts.colorBright,
58
+ diamond: opts.diamond,
59
+ })
36
60
 
37
- //reuse tanaka as basis
38
- const ts = TanakaStyle.get(value, breaks, colors, opts)
39
61
  //style to show limits between pieces
40
62
  const sst = new StrokeStyle({
41
63
  strokeColor: () => '#666',
@@ -44,9 +66,9 @@ export class LegoStyle {
44
66
  })
45
67
 
46
68
  return [
47
- ts[0],
69
+ cellStyle,
48
70
  sst,
49
- ts[1],
71
+ tanakaStyle,
50
72
  new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright, filter: opts.filter }),
51
73
  ]
52
74
  }
@@ -3,7 +3,9 @@
3
3
 
4
4
  import { SideStyle } from './SideStyle.js'
5
5
  import { max } from 'd3-array'
6
- import { exponentialScale } from '../utils/stretching.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
+
7
9
 
8
10
  /**
9
11
  * @module style
@@ -28,7 +30,7 @@ export class ShadingStyle extends SideStyle {
28
30
  const elevation = opts.elevation
29
31
 
30
32
  // compute side value as elevation difference and attach to side
31
- const sideValue = (side) => {
33
+ const sideValue = (/** @type {Side} */ side) => {
32
34
  if (!side.c1) side.v = 0
33
35
  else if (!side.c2) side.v = 0
34
36
  else if (!side.c1[elevation]) side.v = 0
@@ -55,7 +57,5 @@ export class ShadingStyle extends SideStyle {
55
57
 
56
58
  this.width = (_, r, z) => opts.width | Math.min(2 * z, r / 3)
57
59
  this.diamond = opts.diamond
58
-
59
60
  }
60
-
61
61
  }
@@ -0,0 +1,142 @@
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
+ * @typedef {function(Array.<Side>,number, number):*} SideViewScale */
11
+
12
+ /**
13
+ * @module style
14
+ * @author Julien Gaffuri
15
+ */
16
+ export class SideTanakaStyle extends Style {
17
+ /** @param {object} opts */
18
+ constructor(opts = {}) {
19
+ super(opts)
20
+
21
+ /** A function returning the cells classifier.
22
+ * The cell classifier is a function that for each cell returns its class number (int).
23
+ */
24
+ this.classifier = opts.classifier || ((cells, resolution, z) => c => 1)
25
+
26
+ /** A function returning the width of a cell side, in geo unit
27
+ * @type {function(Side, number, number, number, object):number} */
28
+ this.width = opts.width || ((side, sideValue, resolution, z, sidesScale) => Math.abs(sideValue) * Math.min(2 * z, resolution / 3))
29
+
30
+ /** A function returning the length of a cell side, in geo unit
31
+ * @type {function(Side, number, number, object):number} */
32
+ this.length = opts.length || ((side, resolution, z, sidesScale) => resolution)
33
+
34
+ // the dark color: for side facing away from light (coming from NW)
35
+ this.colorDark = opts.colorDark || '#111'
36
+ // the bright color: for side facing the light (coming from NW)
37
+ this.colorBright = opts.colorBright || '#ddd'
38
+
39
+ /** Set to A or true so that the side is drawn as a diamond */
40
+ this.diamond = opts.diamond
41
+ }
42
+
43
+ /**
44
+ * @param {Array.<import("../core/Dataset.js").Cell>} cells
45
+ * @param {number} resolution
46
+ * @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
47
+ */
48
+ draw(cells, geoCanvas, resolution) {
49
+ //filter
50
+ if (this.filter) cells = cells.filter(this.filter)
51
+
52
+ //
53
+ const z = geoCanvas.view.z
54
+ const ctx = geoCanvas.offscreenCtx
55
+
56
+ //get cell classifier
57
+ const classifier = this.classifier(cells, resolution, z)
58
+
59
+ //get side value: class change difference
60
+ const getSideValue = (/** @type {{ c1: Side; c2: Side; }} */ side) => {
61
+ const cl1 = side.c1 ? classifier(side.c1) : undefined
62
+ const cl2 = side.c2 ? classifier(side.c2) : undefined
63
+ if (cl1 === undefined && cl2 === undefined) return undefined
64
+ if (cl1 === undefined) return cl2
65
+ if (cl2 === undefined) return -cl1
66
+ return cl2 - cl1
67
+ }
68
+
69
+ //build sides
70
+ //TODO build only those with different codes ?
71
+ /** @type {Array.<Side>} */
72
+ const sides = SideStyle.buildSides(cells, resolution)
73
+ if (sides.length == 0) return
74
+
75
+ //get side view scale
76
+ const viewScale = this.viewScale ? this.viewScale(sides, resolution, z) : undefined
77
+
78
+ //draw sides
79
+ ctx.lineCap = 'butt'
80
+ const r2 = resolution * 0.5
81
+ for (let side of sides) {
82
+
83
+ //get side value
84
+ const v = getSideValue(side)
85
+ if (v === undefined || v === 0) continue
86
+
87
+ //color
88
+ /** @type {string|undefined} */
89
+ const col = ((v < 0 && side.or === 'h') || (v > 0 && side.or === 'v')) ? this.colorBright : this.colorDark
90
+ if (!col || col == 'none') continue
91
+
92
+ if (this.diamond) {
93
+ //set color
94
+ ctx.fillStyle = col
95
+
96
+ //draw diamond
97
+ const x = side.x,
98
+ y = side.y
99
+ ctx.beginPath()
100
+ ctx.moveTo(x - r2, y)
101
+ ctx.lineTo(x, y + r2)
102
+ ctx.lineTo(x + r2, y)
103
+ ctx.lineTo(x, y - r2)
104
+ ctx.closePath()
105
+ ctx.fill()
106
+ } else {
107
+ //width
108
+ /** @type {number|undefined} */
109
+ const wG = this.width ? this.width(side, v, resolution, z, viewScale) : undefined
110
+ if (!wG || wG <= 0) continue
111
+
112
+ //length
113
+ /** @type {number|undefined} */
114
+ const lG = this.length ? this.length(side, resolution, z, viewScale) : undefined
115
+ if (!lG || lG <= 0) continue
116
+ const lG2 = lG * 0.5
117
+
118
+ //set width
119
+ ctx.lineWidth = wG
120
+ //set color
121
+ ctx.strokeStyle = col
122
+
123
+ //draw segment with correct orientation
124
+ const x = side.x,
125
+ y = side.y
126
+ ctx.beginPath()
127
+ if (side.or === 'v') {
128
+ ctx.moveTo(x, y - lG2)
129
+ ctx.lineTo(x, y + lG2)
130
+ } else {
131
+ ctx.moveTo(x - lG2, y)
132
+ ctx.lineTo(x + lG2, y)
133
+ }
134
+ ctx.stroke()
135
+ }
136
+ }
137
+
138
+ //update legends
139
+ this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
140
+ }
141
+
142
+ }
@@ -1,9 +1,6 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
- import { SideStyle } from './SideStyle.js'
5
- import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.js'
6
- import { classifier as clFun, colorClassifier as cclFun } from '../utils/scale.js'
7
4
 
8
5
  /**
9
6
  * @see https://manifold.net/doc/mfd9/example__tanaka_contours.htm
@@ -17,7 +14,7 @@ export class TanakaStyle {
17
14
  * @param {Array.<number>} breaks The break values
18
15
  * @param {Array.<string>} colors The colors, one more than the break values
19
16
  * @param {object} opts
20
- * @returns {Array.<import("../core/Style").Style>}
17
+ * @returns {Array.<import("../core/Style.js").Style>}
21
18
  */
22
19
  static get(value, breaks, colors, opts = {}) {
23
20
  //shadow colors
@@ -168,6 +168,7 @@ export const viewScaleCombination = (obj) => {
168
168
  }
169
169
  }
170
170
 
171
+
171
172
  /**
172
173
  * Return a classifier function from break values.
173
174
  * The classifier function returns the class id (from 0 to breaks.length) from a value to classifiy.
@@ -188,6 +189,20 @@ export function classifier(breaks) {
188
189
  return classifier
189
190
  }
190
191
 
192
+ /**
193
+ * @param {number} min
194
+ * @param {number} max
195
+ * @param {number} nbClass
196
+ */
197
+ export function classifierMinMax(min, max, nbClass) {
198
+ const breaks = []
199
+ const step = (max - min) / nbClass
200
+ for (let i = 1; i < nbClass; i++) breaks.push(min + i * step)
201
+ return classifier(breaks)
202
+ }
203
+
204
+
205
+
191
206
  /**
192
207
  * Return a color classifier function from break values.
193
208
  * The classifier function returns the color from a value to classifiy.
@@ -1,21 +0,0 @@
1
- //@ts-check
2
- 'use strict'
3
-
4
- import { SideStyle } from './SideStyle.js'
5
-
6
- /** @typedef {{x:number,y:number,or:"v"|"h",value:number}} Side */
7
-
8
- /**
9
- *
10
- * @module style
11
- * @author Julien Gaffuri
12
- */
13
- export class ContourStyle extends SideStyle {
14
- /** @param {object} opts */
15
- constructor(opts) {
16
- super(opts)
17
- //opts = opts || {}
18
-
19
- //TODO
20
- }
21
- }