gridviz 3.0.19 → 3.0.21
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 +128 -128
- package/dist/gridviz.js +7875 -7857
- package/dist/gridviz.min.js +1 -1
- package/package.json +74 -74
- package/src/button/ZoomButtons.js +101 -101
- package/src/core/Dataset.js +154 -154
- package/src/core/Drawable.js +78 -60
- package/src/core/GeoCanvas.js +430 -430
- package/src/core/Layer.js +23 -23
- package/src/core/Legend.js +108 -108
- package/src/core/Map.js +516 -516
- package/src/core/MultiResolutionDataset.js +93 -93
- package/src/core/Style.js +98 -98
- package/src/dataset/CSVGrid.js +112 -112
- package/src/dataset/GeoTIFF.js +122 -122
- package/src/dataset/JSGrid.js +55 -55
- package/src/dataset/TiledGrid.js +302 -302
- package/src/dataset/worker.js +18 -18
- package/src/index.js +77 -77
- package/src/layer/BackgroundLayer.js +162 -162
- package/src/layer/BackgroundLayerImage.js +81 -81
- package/src/layer/BackgroundLayerWMS.js +104 -104
- package/src/layer/GeoJSONLayer.js +214 -214
- package/src/layer/GridLayer.js +148 -148
- package/src/layer/LabelLayer.js +194 -194
- package/src/legend/ColorCategoryLegend.js +109 -109
- package/src/legend/ColorDiscreteLegend.js +100 -100
- package/src/legend/ColorLegend.js +115 -115
- package/src/legend/OrientationLegend.js +89 -89
- package/src/legend/SizeLegend.js +224 -224
- package/src/legend/TernaryLegend.js +302 -302
- package/src/style/CompositionStyle.js +291 -291
- package/src/style/DotDensityStyle.js +133 -133
- package/src/style/ImageStyle.js +100 -100
- package/src/style/IsoFenceStyle.js +217 -217
- package/src/style/JoyPlotStyle.js +127 -127
- package/src/style/LegoStyle.js +110 -110
- package/src/style/MosaicStyle.js +99 -99
- package/src/style/NinjaStarStyle.js +102 -102
- package/src/style/PillarStyle.js +207 -207
- package/src/style/SegmentStyle.js +105 -105
- package/src/style/ShapeColorSizeStyle.js +147 -147
- package/src/style/SideCategoryStyle.js +112 -112
- package/src/style/SideStyle.js +212 -212
- package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -135
- package/src/style/TanakaStyle.js +69 -69
- package/src/style/TextStyle.js +110 -110
- package/src/style/TimeSeriesStyle.js +222 -222
- package/src/utils/scale.js +218 -218
- package/src/utils/stretching.js +120 -120
- package/src/utils/ternary.js +208 -208
- package/src/utils/utils.js +58 -58
- package/src/utils/webGLUtils.js +72 -72
package/src/utils/ternary.js
CHANGED
|
@@ -1,208 +1,208 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { interpolateLab } from 'd3-interpolate'
|
|
5
|
-
|
|
6
|
-
export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
|
|
7
|
-
//the three properties
|
|
8
|
-
const p0 = properties[0],
|
|
9
|
-
p1 = properties[1],
|
|
10
|
-
p2 = properties[2]
|
|
11
|
-
|
|
12
|
-
//the classifier center point. sum must be equal to 1
|
|
13
|
-
const [c0, c1, c2] = opts.center || [1 / 3, 1 / 3, 1 / 3]
|
|
14
|
-
|
|
15
|
-
//parameter to decide wether to use mixed classes m0, m1, m2.
|
|
16
|
-
const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
|
|
17
|
-
|
|
18
|
-
//parameter to decide wether to use a central class, and the size of this central class.
|
|
19
|
-
//set to 0 or undefined for not showing any central class. Set to 1 for a central class that contains the mix classes
|
|
20
|
-
const cc = opts.centerCoefficient ? 1 - opts.centerCoefficient : undefined
|
|
21
|
-
|
|
22
|
-
//the output classifier method
|
|
23
|
-
const fun = (c) => {
|
|
24
|
-
//get total
|
|
25
|
-
const tot = totalFunction(c)
|
|
26
|
-
if (!tot) return undefined
|
|
27
|
-
//compute shares
|
|
28
|
-
const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
|
|
29
|
-
|
|
30
|
-
//class 0
|
|
31
|
-
if (s0 >= c0 && s1 <= c1 && s2 <= c2) {
|
|
32
|
-
//central class near class 0
|
|
33
|
-
if (cc != undefined && (s2 - c2) * (c1 - cc * c1) >= (s1 - cc * c1) * (cc * c2 - c2))
|
|
34
|
-
return 'center'
|
|
35
|
-
return '0'
|
|
36
|
-
}
|
|
37
|
-
//class 1
|
|
38
|
-
if (s0 <= c0 && s1 >= c1 && s2 <= c2) {
|
|
39
|
-
//central class near class 1
|
|
40
|
-
if (cc != undefined && (s2 - c2) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c2 - c2))
|
|
41
|
-
return 'center'
|
|
42
|
-
return '1'
|
|
43
|
-
}
|
|
44
|
-
//class 2
|
|
45
|
-
if (s0 <= c0 && s1 <= c1 && s2 >= c2) {
|
|
46
|
-
//central class near class 2
|
|
47
|
-
if (cc != undefined && (s1 - c1) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c1 - c1))
|
|
48
|
-
return 'center'
|
|
49
|
-
return '2'
|
|
50
|
-
}
|
|
51
|
-
//middle class 0 - intersection class 1 and 2
|
|
52
|
-
if (s0 <= c0 && s1 >= c1 && s2 >= c2) {
|
|
53
|
-
//central class
|
|
54
|
-
if (cc != undefined && s0 > cc * c0) return 'center'
|
|
55
|
-
if (withMixedClasses) return 'm12'
|
|
56
|
-
return s1 > s2 ? '1' : '2'
|
|
57
|
-
}
|
|
58
|
-
//middle class 1 - intersection class 0 and 1
|
|
59
|
-
if (s0 >= c0 && s1 <= c1 && s2 >= c2) {
|
|
60
|
-
//central class
|
|
61
|
-
if (cc != undefined && s1 > cc * c1) return 'center'
|
|
62
|
-
if (withMixedClasses) return 'm02'
|
|
63
|
-
return s0 > s2 ? '0' : '2'
|
|
64
|
-
}
|
|
65
|
-
//middle class 2 - intersection class 0 and 1
|
|
66
|
-
if (s0 >= c0 && s1 >= c1 && s2 <= c2) {
|
|
67
|
-
//central class
|
|
68
|
-
if (cc != undefined && s2 > cc * c2) return 'center'
|
|
69
|
-
if (withMixedClasses) return 'm01'
|
|
70
|
-
return s1 > s0 ? '1' : '0'
|
|
71
|
-
}
|
|
72
|
-
//should not happen
|
|
73
|
-
return 'unknown'
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
//attach information to output function
|
|
77
|
-
fun.center = [c0, c1, c2]
|
|
78
|
-
fun.centerCoefficient = opts.centerCoefficient
|
|
79
|
-
|
|
80
|
-
return fun
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const ternaryColorClassifier = (properties, totalFunction, colors, opts = {}) => {
|
|
84
|
-
//the three colors
|
|
85
|
-
const [color0, color1, color2] = colors || ['red', 'green', 'blue']
|
|
86
|
-
|
|
87
|
-
//the color interpolation function
|
|
88
|
-
const colorInterpolation = opts.colorInterpolation || interpolateLab
|
|
89
|
-
|
|
90
|
-
//parameter to decide wether to use mixed classes.
|
|
91
|
-
const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
|
|
92
|
-
//https://d3js.org/d3-interpolate/color
|
|
93
|
-
const mixColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
|
|
94
|
-
//the colors corresponding to the mixed classes
|
|
95
|
-
const [mixColor0, mixColor1, mixColor2] =
|
|
96
|
-
opts.mixedColors || withMixedClasses
|
|
97
|
-
? [
|
|
98
|
-
mixColorFunction(color1, color2),
|
|
99
|
-
mixColorFunction(color0, color2),
|
|
100
|
-
mixColorFunction(color0, color1),
|
|
101
|
-
]
|
|
102
|
-
: []
|
|
103
|
-
|
|
104
|
-
//the central color, used for the central class, if any. The central class is the class of relatively balanced values, around the center point
|
|
105
|
-
const centerColor =
|
|
106
|
-
opts.centerColor || colorInterpolation(mixColorFunction(color0, color1), color2)(0.333)
|
|
107
|
-
|
|
108
|
-
//make classifier
|
|
109
|
-
const classifier = ternaryClassifier(properties, totalFunction, opts)
|
|
110
|
-
|
|
111
|
-
//the output color classifier method
|
|
112
|
-
const fun = (c) => {
|
|
113
|
-
const cla = classifier(c)
|
|
114
|
-
if (cla == '0') return color0
|
|
115
|
-
if (cla == '1') return color1
|
|
116
|
-
if (cla == '2') return color2
|
|
117
|
-
if (cla == 'm12') return mixColor0
|
|
118
|
-
if (cla == 'm02') return mixColor1
|
|
119
|
-
if (cla == 'm01') return mixColor2
|
|
120
|
-
if (cla == 'center') return centerColor
|
|
121
|
-
return opts.defaultColor || 'black'
|
|
122
|
-
}
|
|
123
|
-
fun.center = classifier.center
|
|
124
|
-
fun.centerCoefficient = opts.centerCoefficient
|
|
125
|
-
fun.colors = [color0, color1, color2]
|
|
126
|
-
fun.mixColors = [mixColor0, mixColor1, mixColor2]
|
|
127
|
-
fun.centerColor = centerColor
|
|
128
|
-
fun.classifier = classifier
|
|
129
|
-
|
|
130
|
-
return fun
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
// OLD VERSIONS
|
|
137
|
-
|
|
138
|
-
/*
|
|
139
|
-
const orderedIndexesDec = arr => [...arr.keys()].sort((a, b) => arr[b] - arr[a]);
|
|
140
|
-
const orderedIndexesInc = arr => [...arr.keys()].sort((a, b) => arr[a] - arr[b]);
|
|
141
|
-
|
|
142
|
-
export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
|
|
143
|
-
const lowThreshold = opts.lowThreshold || [1 / 3, 1 / 3, 1 / 3]
|
|
144
|
-
const highThreshold = opts.highThreshold || [2 / 3, 2 / 3, 2 / 3]
|
|
145
|
-
const colors = opts.colors || ["red", "green", "blue"]
|
|
146
|
-
const colorInterpolation = opts.colorInterpolation || interpolateLab
|
|
147
|
-
|
|
148
|
-
//https://d3js.org/d3-interpolate/color
|
|
149
|
-
const middleColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
|
|
150
|
-
const middleColors = opts.middleColors || [middleColorFunction(colors[1], colors[2]), middleColorFunction(colors[0], colors[2]), middleColorFunction(colors[0], colors[1])]
|
|
151
|
-
const centerColor = opts.centerColor || colorInterpolation(middleColors[2], colors[2])(0.333)
|
|
152
|
-
|
|
153
|
-
const high_ = orderedIndexesDec(highThreshold)
|
|
154
|
-
const low_ = orderedIndexesInc(lowThreshold)
|
|
155
|
-
|
|
156
|
-
const p0 = properties[0], p1 = properties[1], p2 = properties[2]
|
|
157
|
-
const fun = c => {
|
|
158
|
-
//get total
|
|
159
|
-
const tot = totalFunction(c)
|
|
160
|
-
if (!tot) return undefined
|
|
161
|
-
//compute shares
|
|
162
|
-
const shares = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
|
|
163
|
-
//return colors
|
|
164
|
-
//start first with the extreme high (triangles): from the larger value (small triangle) to the lower value (large triangle)
|
|
165
|
-
for (let i of high_) if (shares[i] > highThreshold[i]) return colors[i]
|
|
166
|
-
//then draw the extreme low (trapeziums): from the lower value (small trapeziums) to the larger values (large trapezium)
|
|
167
|
-
for (let i of low_) if (shares[i] < lowThreshold[i]) return middleColors[i]
|
|
168
|
-
//else central color
|
|
169
|
-
return centerColor
|
|
170
|
-
}
|
|
171
|
-
fun.lowThreshold = lowThreshold
|
|
172
|
-
fun.highThreshold = highThreshold
|
|
173
|
-
fun.colors = colors
|
|
174
|
-
fun.middleColors = middleColors
|
|
175
|
-
fun.centerColor = centerColor
|
|
176
|
-
fun.lowIndex = low_
|
|
177
|
-
fun.highIndex = high_
|
|
178
|
-
return fun
|
|
179
|
-
}
|
|
180
|
-
*/
|
|
181
|
-
|
|
182
|
-
/*
|
|
183
|
-
export const ternaryClassifier3 = (properties, totalFunction, opts = {}) => {
|
|
184
|
-
const [a01, a12, a20] = opts.thresholds || [1/3, 1/3, 1/3]
|
|
185
|
-
const [c0, c1, c2] = opts.colors || ["red", "green", "blue"]
|
|
186
|
-
const centerColor = opts.centerColor || "gray"
|
|
187
|
-
|
|
188
|
-
const fff = a => a == 1 ? Infinity : a / (1 - a)
|
|
189
|
-
const c01 = fff(a01), c12 = fff(a12), c20 = fff(a20)
|
|
190
|
-
|
|
191
|
-
const p0 = properties[0], p1 = properties[1], p2 = properties[2]
|
|
192
|
-
const fun = c => {
|
|
193
|
-
//get total
|
|
194
|
-
const tot = totalFunction(c)
|
|
195
|
-
if (!tot) return undefined
|
|
196
|
-
//compute shares
|
|
197
|
-
const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
|
|
198
|
-
//return colors
|
|
199
|
-
if (s0 * c01 > s1 && s0 > s2 * c20) return c0
|
|
200
|
-
else if (s1 > s0 * c01 && s1 * c12 > s2) return c1
|
|
201
|
-
else if (s2 * c20 > s0 && s2 > s1 * c12) return c2
|
|
202
|
-
else return centerColor
|
|
203
|
-
}
|
|
204
|
-
fun.colors = [c0, c1, c2]
|
|
205
|
-
fun.centerColor = centerColor
|
|
206
|
-
return fun
|
|
207
|
-
}
|
|
208
|
-
*/
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { interpolateLab } from 'd3-interpolate'
|
|
5
|
+
|
|
6
|
+
export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
|
|
7
|
+
//the three properties
|
|
8
|
+
const p0 = properties[0],
|
|
9
|
+
p1 = properties[1],
|
|
10
|
+
p2 = properties[2]
|
|
11
|
+
|
|
12
|
+
//the classifier center point. sum must be equal to 1
|
|
13
|
+
const [c0, c1, c2] = opts.center || [1 / 3, 1 / 3, 1 / 3]
|
|
14
|
+
|
|
15
|
+
//parameter to decide wether to use mixed classes m0, m1, m2.
|
|
16
|
+
const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
|
|
17
|
+
|
|
18
|
+
//parameter to decide wether to use a central class, and the size of this central class.
|
|
19
|
+
//set to 0 or undefined for not showing any central class. Set to 1 for a central class that contains the mix classes
|
|
20
|
+
const cc = opts.centerCoefficient ? 1 - opts.centerCoefficient : undefined
|
|
21
|
+
|
|
22
|
+
//the output classifier method
|
|
23
|
+
const fun = (c) => {
|
|
24
|
+
//get total
|
|
25
|
+
const tot = totalFunction(c)
|
|
26
|
+
if (!tot) return undefined
|
|
27
|
+
//compute shares
|
|
28
|
+
const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
|
|
29
|
+
|
|
30
|
+
//class 0
|
|
31
|
+
if (s0 >= c0 && s1 <= c1 && s2 <= c2) {
|
|
32
|
+
//central class near class 0
|
|
33
|
+
if (cc != undefined && (s2 - c2) * (c1 - cc * c1) >= (s1 - cc * c1) * (cc * c2 - c2))
|
|
34
|
+
return 'center'
|
|
35
|
+
return '0'
|
|
36
|
+
}
|
|
37
|
+
//class 1
|
|
38
|
+
if (s0 <= c0 && s1 >= c1 && s2 <= c2) {
|
|
39
|
+
//central class near class 1
|
|
40
|
+
if (cc != undefined && (s2 - c2) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c2 - c2))
|
|
41
|
+
return 'center'
|
|
42
|
+
return '1'
|
|
43
|
+
}
|
|
44
|
+
//class 2
|
|
45
|
+
if (s0 <= c0 && s1 <= c1 && s2 >= c2) {
|
|
46
|
+
//central class near class 2
|
|
47
|
+
if (cc != undefined && (s1 - c1) * (c0 - cc * c0) >= (s0 - cc * c0) * (cc * c1 - c1))
|
|
48
|
+
return 'center'
|
|
49
|
+
return '2'
|
|
50
|
+
}
|
|
51
|
+
//middle class 0 - intersection class 1 and 2
|
|
52
|
+
if (s0 <= c0 && s1 >= c1 && s2 >= c2) {
|
|
53
|
+
//central class
|
|
54
|
+
if (cc != undefined && s0 > cc * c0) return 'center'
|
|
55
|
+
if (withMixedClasses) return 'm12'
|
|
56
|
+
return s1 > s2 ? '1' : '2'
|
|
57
|
+
}
|
|
58
|
+
//middle class 1 - intersection class 0 and 1
|
|
59
|
+
if (s0 >= c0 && s1 <= c1 && s2 >= c2) {
|
|
60
|
+
//central class
|
|
61
|
+
if (cc != undefined && s1 > cc * c1) return 'center'
|
|
62
|
+
if (withMixedClasses) return 'm02'
|
|
63
|
+
return s0 > s2 ? '0' : '2'
|
|
64
|
+
}
|
|
65
|
+
//middle class 2 - intersection class 0 and 1
|
|
66
|
+
if (s0 >= c0 && s1 >= c1 && s2 <= c2) {
|
|
67
|
+
//central class
|
|
68
|
+
if (cc != undefined && s2 > cc * c2) return 'center'
|
|
69
|
+
if (withMixedClasses) return 'm01'
|
|
70
|
+
return s1 > s0 ? '1' : '0'
|
|
71
|
+
}
|
|
72
|
+
//should not happen
|
|
73
|
+
return 'unknown'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
//attach information to output function
|
|
77
|
+
fun.center = [c0, c1, c2]
|
|
78
|
+
fun.centerCoefficient = opts.centerCoefficient
|
|
79
|
+
|
|
80
|
+
return fun
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const ternaryColorClassifier = (properties, totalFunction, colors, opts = {}) => {
|
|
84
|
+
//the three colors
|
|
85
|
+
const [color0, color1, color2] = colors || ['red', 'green', 'blue']
|
|
86
|
+
|
|
87
|
+
//the color interpolation function
|
|
88
|
+
const colorInterpolation = opts.colorInterpolation || interpolateLab
|
|
89
|
+
|
|
90
|
+
//parameter to decide wether to use mixed classes.
|
|
91
|
+
const withMixedClasses = opts.withMixedClasses != undefined ? opts.withMixedClasses : true
|
|
92
|
+
//https://d3js.org/d3-interpolate/color
|
|
93
|
+
const mixColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
|
|
94
|
+
//the colors corresponding to the mixed classes
|
|
95
|
+
const [mixColor0, mixColor1, mixColor2] =
|
|
96
|
+
opts.mixedColors || withMixedClasses
|
|
97
|
+
? [
|
|
98
|
+
mixColorFunction(color1, color2),
|
|
99
|
+
mixColorFunction(color0, color2),
|
|
100
|
+
mixColorFunction(color0, color1),
|
|
101
|
+
]
|
|
102
|
+
: []
|
|
103
|
+
|
|
104
|
+
//the central color, used for the central class, if any. The central class is the class of relatively balanced values, around the center point
|
|
105
|
+
const centerColor =
|
|
106
|
+
opts.centerColor || colorInterpolation(mixColorFunction(color0, color1), color2)(0.333)
|
|
107
|
+
|
|
108
|
+
//make classifier
|
|
109
|
+
const classifier = ternaryClassifier(properties, totalFunction, opts)
|
|
110
|
+
|
|
111
|
+
//the output color classifier method
|
|
112
|
+
const fun = (c) => {
|
|
113
|
+
const cla = classifier(c)
|
|
114
|
+
if (cla == '0') return color0
|
|
115
|
+
if (cla == '1') return color1
|
|
116
|
+
if (cla == '2') return color2
|
|
117
|
+
if (cla == 'm12') return mixColor0
|
|
118
|
+
if (cla == 'm02') return mixColor1
|
|
119
|
+
if (cla == 'm01') return mixColor2
|
|
120
|
+
if (cla == 'center') return centerColor
|
|
121
|
+
return opts.defaultColor || 'black'
|
|
122
|
+
}
|
|
123
|
+
fun.center = classifier.center
|
|
124
|
+
fun.centerCoefficient = opts.centerCoefficient
|
|
125
|
+
fun.colors = [color0, color1, color2]
|
|
126
|
+
fun.mixColors = [mixColor0, mixColor1, mixColor2]
|
|
127
|
+
fun.centerColor = centerColor
|
|
128
|
+
fun.classifier = classifier
|
|
129
|
+
|
|
130
|
+
return fun
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
// OLD VERSIONS
|
|
137
|
+
|
|
138
|
+
/*
|
|
139
|
+
const orderedIndexesDec = arr => [...arr.keys()].sort((a, b) => arr[b] - arr[a]);
|
|
140
|
+
const orderedIndexesInc = arr => [...arr.keys()].sort((a, b) => arr[a] - arr[b]);
|
|
141
|
+
|
|
142
|
+
export const ternaryClassifier = (properties, totalFunction, opts = {}) => {
|
|
143
|
+
const lowThreshold = opts.lowThreshold || [1 / 3, 1 / 3, 1 / 3]
|
|
144
|
+
const highThreshold = opts.highThreshold || [2 / 3, 2 / 3, 2 / 3]
|
|
145
|
+
const colors = opts.colors || ["red", "green", "blue"]
|
|
146
|
+
const colorInterpolation = opts.colorInterpolation || interpolateLab
|
|
147
|
+
|
|
148
|
+
//https://d3js.org/d3-interpolate/color
|
|
149
|
+
const middleColorFunction = (color1, color2) => colorInterpolation(color1, color2)(0.5)
|
|
150
|
+
const middleColors = opts.middleColors || [middleColorFunction(colors[1], colors[2]), middleColorFunction(colors[0], colors[2]), middleColorFunction(colors[0], colors[1])]
|
|
151
|
+
const centerColor = opts.centerColor || colorInterpolation(middleColors[2], colors[2])(0.333)
|
|
152
|
+
|
|
153
|
+
const high_ = orderedIndexesDec(highThreshold)
|
|
154
|
+
const low_ = orderedIndexesInc(lowThreshold)
|
|
155
|
+
|
|
156
|
+
const p0 = properties[0], p1 = properties[1], p2 = properties[2]
|
|
157
|
+
const fun = c => {
|
|
158
|
+
//get total
|
|
159
|
+
const tot = totalFunction(c)
|
|
160
|
+
if (!tot) return undefined
|
|
161
|
+
//compute shares
|
|
162
|
+
const shares = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
|
|
163
|
+
//return colors
|
|
164
|
+
//start first with the extreme high (triangles): from the larger value (small triangle) to the lower value (large triangle)
|
|
165
|
+
for (let i of high_) if (shares[i] > highThreshold[i]) return colors[i]
|
|
166
|
+
//then draw the extreme low (trapeziums): from the lower value (small trapeziums) to the larger values (large trapezium)
|
|
167
|
+
for (let i of low_) if (shares[i] < lowThreshold[i]) return middleColors[i]
|
|
168
|
+
//else central color
|
|
169
|
+
return centerColor
|
|
170
|
+
}
|
|
171
|
+
fun.lowThreshold = lowThreshold
|
|
172
|
+
fun.highThreshold = highThreshold
|
|
173
|
+
fun.colors = colors
|
|
174
|
+
fun.middleColors = middleColors
|
|
175
|
+
fun.centerColor = centerColor
|
|
176
|
+
fun.lowIndex = low_
|
|
177
|
+
fun.highIndex = high_
|
|
178
|
+
return fun
|
|
179
|
+
}
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
export const ternaryClassifier3 = (properties, totalFunction, opts = {}) => {
|
|
184
|
+
const [a01, a12, a20] = opts.thresholds || [1/3, 1/3, 1/3]
|
|
185
|
+
const [c0, c1, c2] = opts.colors || ["red", "green", "blue"]
|
|
186
|
+
const centerColor = opts.centerColor || "gray"
|
|
187
|
+
|
|
188
|
+
const fff = a => a == 1 ? Infinity : a / (1 - a)
|
|
189
|
+
const c01 = fff(a01), c12 = fff(a12), c20 = fff(a20)
|
|
190
|
+
|
|
191
|
+
const p0 = properties[0], p1 = properties[1], p2 = properties[2]
|
|
192
|
+
const fun = c => {
|
|
193
|
+
//get total
|
|
194
|
+
const tot = totalFunction(c)
|
|
195
|
+
if (!tot) return undefined
|
|
196
|
+
//compute shares
|
|
197
|
+
const [s0, s1, s2] = [+c[p0] / tot, +c[p1] / tot, +c[p2] / tot]
|
|
198
|
+
//return colors
|
|
199
|
+
if (s0 * c01 > s1 && s0 > s2 * c20) return c0
|
|
200
|
+
else if (s1 > s0 * c01 && s1 * c12 > s2) return c1
|
|
201
|
+
else if (s2 * c20 > s0 && s2 > s1 * c12) return c2
|
|
202
|
+
else return centerColor
|
|
203
|
+
}
|
|
204
|
+
fun.colors = [c0, c1, c2]
|
|
205
|
+
fun.centerColor = centerColor
|
|
206
|
+
return fun
|
|
207
|
+
}
|
|
208
|
+
*/
|
package/src/utils/utils.js
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Get the class id from a value and class break values
|
|
6
|
-
*
|
|
7
|
-
* @param {number} v the value
|
|
8
|
-
* @param {Array.<number>} breaks the breaks
|
|
9
|
-
* @returns The class id, from 0 to breaks.length
|
|
10
|
-
* @deprecated use getClassifier instead.
|
|
11
|
-
*/
|
|
12
|
-
export function getClass(v, breaks) {
|
|
13
|
-
if (!breaks) return
|
|
14
|
-
if (breaks.length == 0) return 0
|
|
15
|
-
if (v <= breaks[0]) return 0
|
|
16
|
-
for (let i = 1; i < breaks.length; i++) if (breaks[i - 1] < v && v <= breaks[i]) return i
|
|
17
|
-
return breaks.length
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
//take 'nice' value (power of ten, or multiple)
|
|
21
|
-
export function nice(v, multiples = [8, 6, 5, 4, 2.5, 2]) {
|
|
22
|
-
//compute bigger power of ten below
|
|
23
|
-
const v_ = Math.pow(10, Math.floor(Math.log10(v)))
|
|
24
|
-
for (let multiple of multiples) if (v_ * multiple <= v) return v_ * multiple
|
|
25
|
-
return v_
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/*
|
|
29
|
-
//no longer used
|
|
30
|
-
export function loadImage(src) {
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
const img = new Image();
|
|
33
|
-
img.onload = function () { resolve(img); };
|
|
34
|
-
img.onerror = function () { reject(new Error('Error loading image')); };
|
|
35
|
-
img.src = src;
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
*/
|
|
39
|
-
|
|
40
|
-
/*
|
|
41
|
-
export let monitor = false
|
|
42
|
-
|
|
43
|
-
let previousDate
|
|
44
|
-
export function monitorDuration(message) {
|
|
45
|
-
const nowDate = Date.now()
|
|
46
|
-
|
|
47
|
-
//first call
|
|
48
|
-
if (!previousDate) {
|
|
49
|
-
previousDate = nowDate
|
|
50
|
-
console.log(previousDate, message)
|
|
51
|
-
return
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const d = nowDate - previousDate
|
|
55
|
-
previousDate = nowDate
|
|
56
|
-
console.log(d, message)
|
|
57
|
-
}
|
|
58
|
-
*/
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the class id from a value and class break values
|
|
6
|
+
*
|
|
7
|
+
* @param {number} v the value
|
|
8
|
+
* @param {Array.<number>} breaks the breaks
|
|
9
|
+
* @returns The class id, from 0 to breaks.length
|
|
10
|
+
* @deprecated use getClassifier instead.
|
|
11
|
+
*/
|
|
12
|
+
export function getClass(v, breaks) {
|
|
13
|
+
if (!breaks) return
|
|
14
|
+
if (breaks.length == 0) return 0
|
|
15
|
+
if (v <= breaks[0]) return 0
|
|
16
|
+
for (let i = 1; i < breaks.length; i++) if (breaks[i - 1] < v && v <= breaks[i]) return i
|
|
17
|
+
return breaks.length
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
//take 'nice' value (power of ten, or multiple)
|
|
21
|
+
export function nice(v, multiples = [8, 6, 5, 4, 2.5, 2]) {
|
|
22
|
+
//compute bigger power of ten below
|
|
23
|
+
const v_ = Math.pow(10, Math.floor(Math.log10(v)))
|
|
24
|
+
for (let multiple of multiples) if (v_ * multiple <= v) return v_ * multiple
|
|
25
|
+
return v_
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
//no longer used
|
|
30
|
+
export function loadImage(src) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const img = new Image();
|
|
33
|
+
img.onload = function () { resolve(img); };
|
|
34
|
+
img.onerror = function () { reject(new Error('Error loading image')); };
|
|
35
|
+
img.src = src;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
export let monitor = false
|
|
42
|
+
|
|
43
|
+
let previousDate
|
|
44
|
+
export function monitorDuration(message) {
|
|
45
|
+
const nowDate = Date.now()
|
|
46
|
+
|
|
47
|
+
//first call
|
|
48
|
+
if (!previousDate) {
|
|
49
|
+
previousDate = nowDate
|
|
50
|
+
console.log(previousDate, message)
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const d = nowDate - previousDate
|
|
55
|
+
previousDate = nowDate
|
|
56
|
+
console.log(d, message)
|
|
57
|
+
}
|
|
58
|
+
*/
|