gridviz 3.0.0 → 3.0.2
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/README.md +36 -33
- package/dist/gridviz.js +528 -229
- package/dist/gridviz.min.js +1 -1
- package/package.json +4 -3
- package/src/button/Button.js +1 -0
- package/src/button/FullscreenButton.js +1 -0
- package/src/button/ZoomButtons.js +1 -0
- package/src/core/Dataset.js +1 -1
- package/src/core/Drawable.js +1 -0
- package/src/core/GeoCanvas.js +1 -0
- package/src/core/Layer.js +1 -0
- package/src/core/Legend.js +1 -0
- package/src/core/Map.js +15 -0
- package/src/core/MultiResolutionDataset.js +1 -0
- package/src/core/Style.js +10 -1
- package/src/core/Tooltip.js +1 -0
- package/src/dataset/COGeo.js +1 -0
- package/src/dataset/CSVGrid.js +1 -0
- package/src/dataset/GeoTIFF.js +1 -0
- package/src/dataset/JSGrid.js +3 -3
- package/src/dataset/TiledGrid.js +1 -0
- package/src/index.js +3 -3
- package/src/layer/BackgroundLayer.js +1 -0
- package/src/layer/BackgroundLayerWMS.js +1 -0
- package/src/layer/GeoJSONLayer.js +1 -0
- package/src/layer/GridLayer.js +21 -0
- package/src/layer/LabelLayer.js +1 -0
- package/src/legend/ColorCategoryLegend.js +1 -0
- package/src/legend/ColorDiscreteLegend.js +2 -0
- package/src/legend/ColorLegend.js +1 -0
- package/src/legend/OrientationLegend.js +1 -0
- package/src/legend/SizeLegend.js +4 -2
- package/src/style/CompositionStyle.js +1 -0
- package/src/style/ContourStyle.js +1 -0
- package/src/style/DotDensityStyle.js +1 -0
- package/src/style/IsoFenceStyle.js +24 -72
- package/src/style/JoyPlotStyle.js +1 -1
- package/src/style/LegoStyle.js +22 -24
- package/src/style/MosaicStyle.js +1 -0
- package/src/style/NinjaStarStyle.js +1 -1
- package/src/style/PillarStyle.js +1 -0
- package/src/style/SegmentStyle.js +1 -0
- package/src/style/ShapeColorSizeStyle.js +1 -0
- package/src/style/SideCategoryStyle.js +1 -0
- package/src/style/SideStyle.js +51 -28
- package/src/style/SquareColorCategoryWebGLStyle.js +4 -3
- package/src/style/SquareColorWebGLStyle.js +1 -0
- package/src/style/StrokeStyle.js +1 -1
- package/src/style/TanakaStyle.js +11 -5
- package/src/style/TextStyle.js +1 -1
- package/src/style/TimeSeriesStyle.js +1 -0
- package/src/utils/scale.js +44 -18
- package/src/utils/stretching.js +4 -0
- package/src/utils/utils.js +2 -1
package/src/style/LegoStyle.js
CHANGED
|
@@ -7,21 +7,18 @@ import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.j
|
|
|
7
7
|
import { Style } from '../core/Style.js'
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
+
* @module style
|
|
10
11
|
* @author Julien Gaffuri
|
|
11
12
|
*/
|
|
12
13
|
export class LegoStyle {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* @param {object} opts
|
|
16
|
-
* @returns {Array.<Style>}
|
|
17
|
-
*/
|
|
18
|
-
static get(col, opts) {
|
|
14
|
+
|
|
15
|
+
static get(value, breaks, colors, opts = {}) {
|
|
19
16
|
opts = opts || {}
|
|
20
17
|
|
|
21
18
|
//the colors
|
|
22
19
|
//http://www.jennyscrayoncollection.com/2021/06/all-current-lego-colors.html
|
|
23
20
|
//https://leonawicz.github.io/legocolors/reference/figures/README-plot-1.png
|
|
24
|
-
opts.colors = opts.colors || [
|
|
21
|
+
/*opts.colors = opts.colors || [
|
|
25
22
|
'#00852b', //darker green
|
|
26
23
|
'#afd246', //light green
|
|
27
24
|
'#fac80a', //dark yellow
|
|
@@ -32,18 +29,18 @@ export class LegoStyle {
|
|
|
32
29
|
'#720012', //dark red
|
|
33
30
|
//"purple",
|
|
34
31
|
//"#eee" //whithe
|
|
35
|
-
]
|
|
32
|
+
]*/
|
|
36
33
|
|
|
37
34
|
opts.colDark = opts.colDark || '#333'
|
|
38
35
|
opts.colBright = opts.colBright || '#aaa'
|
|
39
36
|
opts.widthFactor = opts.widthFactor || 0.12
|
|
40
37
|
|
|
41
38
|
//reuse tanaka as basis
|
|
42
|
-
const ts = TanakaStyle.get(
|
|
39
|
+
const ts = TanakaStyle.get(value, breaks, colors, opts)
|
|
43
40
|
//style to show limits between pieces
|
|
44
41
|
const sst = new StrokeStyle({
|
|
45
42
|
strokeColor: () => '#666',
|
|
46
|
-
strokeWidth: (
|
|
43
|
+
strokeWidth: (c, r, z) => 0.2 * z,
|
|
47
44
|
filter: opts.filter,
|
|
48
45
|
})
|
|
49
46
|
|
|
@@ -56,20 +53,21 @@ export class LegoStyle {
|
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
/**
|
|
59
|
-
* @param {function(
|
|
56
|
+
* @param {function(import('../core/Dataset.js').Cell):string} code
|
|
57
|
+
* @param {object} color
|
|
60
58
|
* @param {object} opts
|
|
61
59
|
* @returns {Array.<Style>}
|
|
62
60
|
*/
|
|
63
|
-
static
|
|
61
|
+
static getCategory(code, color, opts) {
|
|
64
62
|
opts = opts || {}
|
|
65
63
|
|
|
66
64
|
opts.colDark = opts.colDark || '#333'
|
|
67
65
|
opts.colBright = opts.colBright || '#aaa'
|
|
68
66
|
|
|
69
67
|
//
|
|
70
|
-
const s = new SquareColorCategoryWebGLStyle({
|
|
68
|
+
const s = new SquareColorCategoryWebGLStyle({ code: code, color: color })
|
|
71
69
|
//style to show limits between pieces
|
|
72
|
-
const sst = new StrokeStyle({ strokeColor: () => '#666', strokeWidth: (
|
|
70
|
+
const sst = new StrokeStyle({ strokeColor: () => '#666', strokeWidth: (c, r, z) => 0.2 * z })
|
|
73
71
|
|
|
74
72
|
return [s, sst, new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright })]
|
|
75
73
|
}
|
|
@@ -87,26 +85,26 @@ class LegoTopStyle extends Style {
|
|
|
87
85
|
this.colBright = opts.colBright || '#aaa'
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
draw(cells,
|
|
88
|
+
draw(cells, geoCanvas, r) {
|
|
91
89
|
//filter
|
|
92
90
|
if (this.filter) cells = cells.filter(this.filter)
|
|
93
91
|
|
|
94
|
-
|
|
92
|
+
geoCanvas.ctx.lineWidth = 0.6 * geoCanvas.view.z
|
|
95
93
|
|
|
96
94
|
//dark part
|
|
97
|
-
|
|
95
|
+
geoCanvas.ctx.strokeStyle = this.colDark
|
|
98
96
|
for (let c of cells) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
geoCanvas.ctx.beginPath()
|
|
98
|
+
geoCanvas.ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), true)
|
|
99
|
+
geoCanvas.ctx.stroke()
|
|
102
100
|
}
|
|
103
101
|
|
|
104
102
|
//bright part
|
|
105
|
-
|
|
103
|
+
geoCanvas.ctx.strokeStyle = this.colBright
|
|
106
104
|
for (let c of cells) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
geoCanvas.ctx.beginPath()
|
|
106
|
+
geoCanvas.ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), false)
|
|
107
|
+
geoCanvas.ctx.stroke()
|
|
110
108
|
}
|
|
111
109
|
}
|
|
112
110
|
}
|
package/src/style/MosaicStyle.js
CHANGED
package/src/style/PillarStyle.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Style } from '../core/Style.js'
|
|
|
6
6
|
/**
|
|
7
7
|
* A style where each cell is represented by a segment whose length, width, color and orientation can vary according to statistical values.
|
|
8
8
|
*
|
|
9
|
+
* @module style
|
|
9
10
|
* @author Julien Gaffuri
|
|
10
11
|
*/
|
|
11
12
|
export class SegmentStyle extends Style {
|
|
@@ -7,6 +7,7 @@ import { Style } from '../core/Style.js'
|
|
|
7
7
|
* A very generic style that shows grid cells with specific color, size and shape.
|
|
8
8
|
* It can be used to show variables as cell colors, cell size, cell shape, or any combination of the three visual variables.
|
|
9
9
|
*
|
|
10
|
+
* @module style
|
|
10
11
|
* @author Joseph Davies, Julien Gaffuri
|
|
11
12
|
*/
|
|
12
13
|
export class ShapeColorSizeStyle extends Style {
|
package/src/style/SideStyle.js
CHANGED
|
@@ -9,7 +9,7 @@ import { Style } from '../core/Style.js'
|
|
|
9
9
|
* @typedef {function(Array.<Side>,number, number):*} SideViewScale */
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* @module style
|
|
13
13
|
* @author Julien Gaffuri
|
|
14
14
|
*/
|
|
15
15
|
export class SideStyle extends Style {
|
|
@@ -28,6 +28,9 @@ export class SideStyle extends Style {
|
|
|
28
28
|
/** A function returning the length of a cell side, in geo unit
|
|
29
29
|
* @type {function(Side, number, number, object):number} */
|
|
30
30
|
this.length = opts.length || ((side, resolution, z, sideViewScale) => resolution)
|
|
31
|
+
|
|
32
|
+
/** Set to A or true so that the side is drawn as a diamond */
|
|
33
|
+
this.diamond = opts.diamond
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
/**
|
|
@@ -63,31 +66,51 @@ export class SideStyle extends Style {
|
|
|
63
66
|
const col = this.color ? this.color(side, resolution, z, viewScale) : undefined
|
|
64
67
|
if (!col || col == 'none') continue
|
|
65
68
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
//draw segment with correct orientation
|
|
82
|
-
geoCanvas.ctx.beginPath()
|
|
83
|
-
if (side.or === "v") {
|
|
84
|
-
geoCanvas.ctx.moveTo(side.x, side.y + r2 - lG2)
|
|
85
|
-
geoCanvas.ctx.lineTo(side.x, side.y + r2 + lG2)
|
|
69
|
+
if (this.diamond) {
|
|
70
|
+
|
|
71
|
+
//set color
|
|
72
|
+
geoCanvas.ctx.fillStyle = col
|
|
73
|
+
|
|
74
|
+
//draw diamond
|
|
75
|
+
const x = side.x, y = side.y
|
|
76
|
+
geoCanvas.ctx.beginPath()
|
|
77
|
+
geoCanvas.ctx.moveTo(x - r2, y)
|
|
78
|
+
geoCanvas.ctx.lineTo(x, y + r2)
|
|
79
|
+
geoCanvas.ctx.lineTo(x + r2, y)
|
|
80
|
+
geoCanvas.ctx.lineTo(x, y - r2)
|
|
81
|
+
geoCanvas.ctx.closePath()
|
|
82
|
+
geoCanvas.ctx.fill()
|
|
83
|
+
|
|
86
84
|
} else {
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
|
|
86
|
+
//width
|
|
87
|
+
/** @type {number|undefined} */
|
|
88
|
+
const wG = this.width ? this.width(side, resolution, z, viewScale) : undefined
|
|
89
|
+
if (!wG || wG <= 0) continue
|
|
90
|
+
|
|
91
|
+
//length
|
|
92
|
+
/** @type {number|undefined} */
|
|
93
|
+
const lG = this.length ? this.length(side, resolution, z, viewScale) : undefined
|
|
94
|
+
if (!lG || lG <= 0) continue
|
|
95
|
+
const lG2 = lG * 0.5
|
|
96
|
+
|
|
97
|
+
//set width
|
|
98
|
+
geoCanvas.ctx.lineWidth = wG
|
|
99
|
+
//set color
|
|
100
|
+
geoCanvas.ctx.strokeStyle = col
|
|
101
|
+
|
|
102
|
+
//draw segment with correct orientation
|
|
103
|
+
const x = side.x, y = side.y
|
|
104
|
+
geoCanvas.ctx.beginPath()
|
|
105
|
+
if (side.or === "v") {
|
|
106
|
+
geoCanvas.ctx.moveTo(x, y - lG2)
|
|
107
|
+
geoCanvas.ctx.lineTo(x, y + lG2)
|
|
108
|
+
} else {
|
|
109
|
+
geoCanvas.ctx.moveTo(x - lG2, y)
|
|
110
|
+
geoCanvas.ctx.lineTo(x + lG2, y)
|
|
111
|
+
}
|
|
112
|
+
geoCanvas.ctx.stroke()
|
|
89
113
|
}
|
|
90
|
-
geoCanvas.ctx.stroke()
|
|
91
114
|
}
|
|
92
115
|
|
|
93
116
|
//update legends
|
|
@@ -98,18 +121,18 @@ export class SideStyle extends Style {
|
|
|
98
121
|
|
|
99
122
|
/**
|
|
100
123
|
*
|
|
101
|
-
* @param {Array.<import('../core/Dataset').Cell>} cells The cells to use to build the sides.
|
|
124
|
+
* @param {Array.<import('../core/Dataset').Cell>} cells The cells to use to build the sides.
|
|
102
125
|
* @param {number} resolution The cells resolution
|
|
103
126
|
* @param {boolean} withHorizontal Set to true to build horizontal sides, false otherwise.
|
|
104
127
|
* @param {boolean} withVertical Set to true to build vertical sides, false otherwise.
|
|
105
|
-
* @param {boolean}
|
|
128
|
+
* @param {boolean} centre Set to true so that the side coordinate are those of its center point rather than its left/bottom point (the side x,y coordinates are those of the left point for horizontal sides, and of the bottom point for vertical sides)
|
|
106
129
|
* @returns { Array.<Side> }
|
|
107
130
|
*/
|
|
108
|
-
static buildSides(cells, resolution, withHorizontal = true, withVertical = true,
|
|
131
|
+
static buildSides(cells, resolution, withHorizontal = true, withVertical = true, centre = true) {
|
|
109
132
|
/** @type { Array.<Side> } */
|
|
110
133
|
const sides = []
|
|
111
134
|
|
|
112
|
-
const r2 =
|
|
135
|
+
const r2 = centre ? resolution / 2 : 0
|
|
113
136
|
|
|
114
137
|
//make horizontal sides
|
|
115
138
|
//sort cells by x and y
|
|
@@ -10,6 +10,7 @@ import { WebGLSquareColoringCatAdvanced } from '../utils/WebGLSquareColoringCatA
|
|
|
10
10
|
* To show cells as colored squares, from categories.
|
|
11
11
|
* All cells are drawn as squares, with the same size
|
|
12
12
|
*
|
|
13
|
+
* @module style
|
|
13
14
|
* @author Julien Gaffuri
|
|
14
15
|
*/
|
|
15
16
|
export class SquareColorCategoryWebGLStyle extends Style {
|
|
@@ -19,8 +20,8 @@ export class SquareColorCategoryWebGLStyle extends Style {
|
|
|
19
20
|
opts = opts || {}
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
|
-
*
|
|
23
|
-
* @type {string} */
|
|
23
|
+
* A function returning the category code of the cell, for coloring.
|
|
24
|
+
* @type {function(import('../core/Dataset.js').Cell):string} */
|
|
24
25
|
this.code = opts.code
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -71,7 +72,7 @@ export class SquareColorCategoryWebGLStyle extends Style {
|
|
|
71
72
|
const iBuffer = []
|
|
72
73
|
for (let i = 0; i < nb; i++) {
|
|
73
74
|
c = cells[i]
|
|
74
|
-
const cat =
|
|
75
|
+
const cat = this.code(c)
|
|
75
76
|
if (cat == undefined) {
|
|
76
77
|
console.log('Unexpected category: ' + cat)
|
|
77
78
|
continue
|
|
@@ -10,6 +10,7 @@ import { WebGLSquareColoringAdvanced } from '../utils/WebGLSquareColoringAdvance
|
|
|
10
10
|
* To show cells as colored squares, with computation of the colors on GPU side (faster than JavaScript side).
|
|
11
11
|
* Alls squares with the same size
|
|
12
12
|
*
|
|
13
|
+
* @module style
|
|
13
14
|
* @author Julien Gaffuri
|
|
14
15
|
*/
|
|
15
16
|
export class SquareColorWebGLStyle extends Style {
|
package/src/style/StrokeStyle.js
CHANGED
package/src/style/TanakaStyle.js
CHANGED
|
@@ -8,6 +8,7 @@ import { classifier as clFun, colorClassifier as cclFun } from '../utils/scale.j
|
|
|
8
8
|
/**
|
|
9
9
|
* @see https://manifold.net/doc/mfd9/example__tanaka_contours.htm
|
|
10
10
|
*
|
|
11
|
+
* @module style
|
|
11
12
|
* @author Julien Gaffuri
|
|
12
13
|
*/
|
|
13
14
|
export class TanakaStyle {
|
|
@@ -32,15 +33,20 @@ export class TanakaStyle {
|
|
|
32
33
|
return Math.min(minWG + (sideValue - 1) * step, maxWG)
|
|
33
34
|
})
|
|
34
35
|
|
|
35
|
-
//make
|
|
36
|
+
//make classifier
|
|
36
37
|
const classifier = clFun(breaks)
|
|
37
|
-
|
|
38
|
+
//make colors table
|
|
39
|
+
const colorsDict = {};
|
|
40
|
+
for (let i = 0; i < colors.length; i++) colorsDict[i + ""] = colors[i]
|
|
38
41
|
|
|
39
|
-
const cellStyle = new SquareColorCategoryWebGLStyle({
|
|
42
|
+
const cellStyle = new SquareColorCategoryWebGLStyle({
|
|
43
|
+
code: cell => classifier(value(cell)),
|
|
44
|
+
color: colorsDict
|
|
45
|
+
})
|
|
40
46
|
|
|
41
47
|
const getSideValue = (side) => {
|
|
42
|
-
const cl1 = side.c1 ? classifier(value(side.c1)) :
|
|
43
|
-
const cl2 = side.c2 ? classifier(value(side.c2)) :
|
|
48
|
+
const cl1 = side.c1 ? classifier(value(side.c1)) : -1
|
|
49
|
+
const cl2 = side.c2 ? classifier(value(side.c2)) : -1
|
|
44
50
|
return cl1 - cl2
|
|
45
51
|
}
|
|
46
52
|
|
package/src/style/TextStyle.js
CHANGED
package/src/utils/scale.js
CHANGED
|
@@ -13,11 +13,15 @@ import { scaleQuantile } from "d3-scale"
|
|
|
13
13
|
* @typedef {function(number):string} ColorScale */
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @module utils
|
|
18
|
+
*/
|
|
19
|
+
|
|
16
20
|
|
|
17
21
|
/**
|
|
18
|
-
* Generic function for view scale - continuous
|
|
22
|
+
* Generic function for view scale - continuous or discrete
|
|
19
23
|
*
|
|
20
|
-
* @param {{ valueFunction:function(import("../core/Dataset").Cell):number, minValue?:number, minSizePix?:number, maxSizeFactor?:number, range?:[number, number], domain?:[number, number], stretching?:function(number):number }} opts
|
|
24
|
+
* @param {{ valueFunction:function(import("../core/Dataset").Cell):number, minValue?:number, minSizePix?:number, maxSizeFactor?:number, range?:[number, number], domain?:[number, number], stretching?:function(number):number, classNumber?:number}} opts
|
|
21
25
|
* @returns {function(Array.<import("../core/Dataset").Cell>):Scale}
|
|
22
26
|
*/
|
|
23
27
|
export const viewScale = (opts) => {
|
|
@@ -28,21 +32,27 @@ export const viewScale = (opts) => {
|
|
|
28
32
|
const stretching = opts.stretching
|
|
29
33
|
const range_ = opts.range
|
|
30
34
|
const domain_ = opts.domain
|
|
31
|
-
|
|
35
|
+
const classNumber = opts.classNumber
|
|
36
|
+
return (cells, resolution, z) => {
|
|
32
37
|
const domain = domain_ || [minValue, max(cells, valueFunction)]
|
|
33
|
-
const range = range_ || [minSizePix * z,
|
|
38
|
+
const range = range_ || [minSizePix * z, resolution * maxSizeFactor]
|
|
39
|
+
const domainSize = domain[1] - domain[0], domainMin = domain[0]
|
|
40
|
+
const rangeSize = range[1] - range[0], rangeMin = range[0]
|
|
34
41
|
return t => {
|
|
35
42
|
//scale to [0,1]
|
|
36
|
-
t = (t -
|
|
43
|
+
t = (t - domainMin) / domainSize
|
|
37
44
|
//stretch
|
|
38
45
|
if (stretching) t = stretching(t)
|
|
46
|
+
//classify
|
|
47
|
+
if (classNumber) t = t == 1 ? 1 : Math.floor(t * (classNumber)) / (classNumber - 1)
|
|
39
48
|
//scale to range
|
|
40
|
-
return
|
|
49
|
+
return rangeMin + t * rangeSize
|
|
41
50
|
}
|
|
42
51
|
}
|
|
43
52
|
}
|
|
44
53
|
|
|
45
54
|
|
|
55
|
+
|
|
46
56
|
/**
|
|
47
57
|
* Generic function for view scale - quantile
|
|
48
58
|
*
|
|
@@ -55,9 +65,9 @@ export const viewScaleQuantile = (opts) => {
|
|
|
55
65
|
const minSizePix = opts.minSizePix || 1
|
|
56
66
|
const maxSizeFactor = opts.maxSizeFactor || 1
|
|
57
67
|
const scale = scaleQuantile()
|
|
58
|
-
return (cells,
|
|
68
|
+
return (cells, resolution, z) => {
|
|
59
69
|
scale.domain(cells.map(valueFunction))
|
|
60
|
-
const minSizeGeo = minSizePix * z, maxSizeGeo =
|
|
70
|
+
const minSizeGeo = minSizePix * z, maxSizeGeo = resolution * maxSizeFactor
|
|
61
71
|
scale.range(Array.from({ length: classNumber }, (_, i) => minSizeGeo + i * (maxSizeGeo - minSizeGeo) / (classNumber - 1)))
|
|
62
72
|
scale.breaks = scale.quantiles()
|
|
63
73
|
scale.values = scale.range()
|
|
@@ -71,24 +81,30 @@ export const viewScaleQuantile = (opts) => {
|
|
|
71
81
|
|
|
72
82
|
|
|
73
83
|
/**
|
|
74
|
-
* Generic function for color view scale - continuous
|
|
84
|
+
* Generic function for color view scale - continuous or discrete
|
|
75
85
|
*
|
|
76
|
-
* @param {{ valueFunction:function(import("../core/Dataset").Cell):number, colorScale?:function(number):string, stretching?:function(number):number }} opts
|
|
86
|
+
* @param {{ valueFunction:function(import("../core/Dataset").Cell):number, colorScale?:function(number):string, colors?:Array.<string>, stretching?:function(number):number }} opts
|
|
77
87
|
* @returns {function(Array.<import("../core/Dataset").Cell>):ColorScale}
|
|
78
88
|
*/
|
|
79
89
|
export const viewScaleColor = (opts) => {
|
|
80
90
|
const valueFunction = opts.valueFunction
|
|
81
|
-
const colorScale = opts.colorScale || (() => "purple")
|
|
82
91
|
const stretching = opts.stretching
|
|
92
|
+
let colorScale = opts.colorScale || (() => "purple")
|
|
93
|
+
|
|
94
|
+
//discrete colors case: build continuous color scale from discrete ones.
|
|
95
|
+
const nbClass = opts.colors?.length
|
|
96
|
+
if (opts.colors && nbClass)
|
|
97
|
+
colorScale = t => opts.colors[t == 1 ? nbClass - 1 : Math.floor(t * nbClass)]
|
|
98
|
+
|
|
83
99
|
return (cells) => {
|
|
84
100
|
if (cells.length == 0 || !cells) return
|
|
85
101
|
/** @type {[undefined, undefined] | [number, number]} */
|
|
86
102
|
const domain = extent(cells, valueFunction)
|
|
87
103
|
if (domain[0] == undefined) return
|
|
88
|
-
const
|
|
104
|
+
const domainSize = domain[1] - domain[0]
|
|
89
105
|
const scale = t => {
|
|
90
106
|
//scale to [0,1]
|
|
91
|
-
t = (t - domain[0]) /
|
|
107
|
+
t = (t - domain[0]) / domainSize
|
|
92
108
|
//stretch
|
|
93
109
|
if (stretching) t = stretching(t)
|
|
94
110
|
return colorScale(t)
|
|
@@ -96,13 +112,23 @@ export const viewScaleColor = (opts) => {
|
|
|
96
112
|
//function that return the domain value from the [0,1] range.
|
|
97
113
|
scale.invert = t => {
|
|
98
114
|
if (stretching) t = stretching.invert(t)
|
|
99
|
-
return domain[0] + t *
|
|
115
|
+
return domain[0] + t * domainSize
|
|
116
|
+
}
|
|
117
|
+
//discrete colors: return the breaks
|
|
118
|
+
if (opts.colors && nbClass) {
|
|
119
|
+
scale.breaks = []
|
|
120
|
+
for (let i = 1; i < nbClass; i++)
|
|
121
|
+
scale.breaks.push(scale.invert(i / nbClass))
|
|
100
122
|
}
|
|
101
123
|
|
|
102
124
|
return scale;
|
|
103
125
|
}
|
|
104
126
|
}
|
|
105
127
|
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
106
132
|
/**
|
|
107
133
|
* Generic function for color view scale - quantile
|
|
108
134
|
*
|
|
@@ -130,16 +156,16 @@ export const viewScaleColorQuantile = (opts) => {
|
|
|
130
156
|
|
|
131
157
|
|
|
132
158
|
/**
|
|
133
|
-
*
|
|
159
|
+
* Combine view scale functions
|
|
134
160
|
*
|
|
135
161
|
* @param {*} obj
|
|
136
|
-
* @returns
|
|
162
|
+
* @returns {function}
|
|
137
163
|
*/
|
|
138
164
|
export const viewScaleCombination = (obj) => {
|
|
139
165
|
//obj: prop and a function to call
|
|
140
|
-
return (cells,
|
|
166
|
+
return (cells, resolution, z) => {
|
|
141
167
|
const out = {}
|
|
142
|
-
for (const p in obj) { out[p] = obj[p](cells,
|
|
168
|
+
for (const p in obj) { out[p] = obj[p](cells, resolution, z) }
|
|
143
169
|
return out
|
|
144
170
|
}
|
|
145
171
|
}
|
package/src/utils/stretching.js
CHANGED
package/src/utils/utils.js
CHANGED
|
@@ -30,7 +30,7 @@ export function nice(v, multiples = [8, 6, 5, 4, 2.5, 2]) {
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
/*
|
|
34
34
|
export let monitor = false
|
|
35
35
|
|
|
36
36
|
let previousDate
|
|
@@ -48,3 +48,4 @@ export function monitorDuration(message) {
|
|
|
48
48
|
previousDate = nowDate
|
|
49
49
|
console.log(d, message)
|
|
50
50
|
}
|
|
51
|
+
*/
|