gridviz 3.0.15 → 3.0.16
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 +127 -128
- package/dist/gridviz.js +7959 -7861
- package/dist/gridviz.min.js +1 -1
- package/package.json +74 -74
- package/src/button/ZoomButtons.js +101 -96
- package/src/core/Dataset.js +154 -157
- package/src/core/Drawable.js +60 -61
- package/src/core/GeoCanvas.js +409 -370
- package/src/core/Layer.js +23 -25
- package/src/core/Legend.js +108 -110
- package/src/core/Map.js +495 -495
- package/src/core/MultiResolutionDataset.js +93 -97
- package/src/core/Style.js +98 -99
- package/src/dataset/CSVGrid.js +112 -112
- package/src/dataset/GeoTIFF.js +122 -123
- package/src/dataset/JSGrid.js +55 -54
- package/src/dataset/TiledGrid.js +289 -288
- package/src/dataset/worker.js +18 -0
- package/src/index.js +77 -71
- package/src/layer/BackgroundLayer.js +162 -158
- package/src/layer/BackgroundLayerImage.js +81 -84
- package/src/layer/BackgroundLayerWMS.js +104 -108
- package/src/layer/GeoJSONLayer.js +214 -220
- package/src/layer/GridLayer.js +148 -157
- package/src/layer/LabelLayer.js +194 -193
- package/src/legend/ColorCategoryLegend.js +109 -110
- package/src/legend/ColorDiscreteLegend.js +100 -102
- package/src/legend/ColorLegend.js +115 -118
- package/src/legend/OrientationLegend.js +89 -91
- package/src/legend/SizeLegend.js +224 -224
- package/src/legend/TernaryLegend.js +302 -210
- package/src/style/CompositionStyle.js +291 -288
- package/src/style/DotDensityStyle.js +133 -134
- package/src/style/ImageStyle.js +100 -102
- package/src/style/IsoFenceStyle.js +217 -203
- package/src/style/JoyPlotStyle.js +127 -128
- 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 -208
- package/src/style/SegmentStyle.js +105 -105
- package/src/style/ShapeColorSizeStyle.js +147 -132
- package/src/style/SideCategoryStyle.js +112 -114
- package/src/style/SideStyle.js +212 -205
- package/src/style/SquareColorCategoryWebGLStyle.js +107 -108
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -136
- package/src/style/TanakaStyle.js +69 -68
- package/src/style/TextStyle.js +110 -111
- package/src/style/TimeSeriesStyle.js +222 -229
- package/src/utils/scale.js +218 -228
- package/src/utils/stretching.js +120 -133
- package/src/utils/ternary.js +203 -204
- package/src/utils/utils.js +58 -63
- package/src/utils/webGLUtils.js +72 -70
|
@@ -1,203 +1,217 @@
|
|
|
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
|
-
* @module style
|
|
11
|
-
* @author Julien Gaffuri
|
|
12
|
-
*/
|
|
13
|
-
export class IsoFenceStyle extends Style {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
* @param {
|
|
54
|
-
* @param {
|
|
55
|
-
* @
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
+
* @module style
|
|
11
|
+
* @author Julien Gaffuri
|
|
12
|
+
*/
|
|
13
|
+
export class IsoFenceStyle extends Style {
|
|
14
|
+
/** @param {object} opts */
|
|
15
|
+
constructor(opts) {
|
|
16
|
+
super(opts)
|
|
17
|
+
opts = opts || {}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The dictionary (string -> color) which give the color of each category.
|
|
21
|
+
* @type {object} */
|
|
22
|
+
this.color = opts.color
|
|
23
|
+
|
|
24
|
+
/** A function returning the height of a cell in geographical unit.
|
|
25
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
26
|
+
this.height = opts.height || ((cell, resolution, z, viewScale) => resolution * 0.4)
|
|
27
|
+
|
|
28
|
+
/** The perspective angle, in degree, within [-180,180], from [O,x] axis.
|
|
29
|
+
* @type {number} */
|
|
30
|
+
this.angle = opts.angle != undefined ? opts.angle : 50
|
|
31
|
+
|
|
32
|
+
/** A function returning the corner line stroke style.
|
|
33
|
+
* @type {function(import('../core/Dataset.js').Cell,number,number,number):string} */
|
|
34
|
+
this.cornerLineStrokeColor = opts.cornerLineStrokeColor || ((c, r, z, angle) => '#999')
|
|
35
|
+
|
|
36
|
+
/** A function returning the corner line width.
|
|
37
|
+
* @type {function(import('../core/Dataset.js').Cell,number,number,number):number} */
|
|
38
|
+
this.cornerLineWidth = opts.cornerLineWidth || ((c, r, z, angle) => (angle % 90 == 0 ? 0 : 0.8 * z))
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Show vertical cross-sections.
|
|
42
|
+
* @type {boolean} */
|
|
43
|
+
this.sVert = opts.sVert != undefined ? opts.sVert : true
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Show horizontal cross-sections.
|
|
47
|
+
* @type {boolean} */
|
|
48
|
+
this.sHor = opts.sHor != undefined ? opts.sHor : true
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @param {Array.<import("../core/Dataset.js").Cell>} cells
|
|
53
|
+
* @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
|
|
54
|
+
* @param {number} resolution
|
|
55
|
+
* @override
|
|
56
|
+
*/
|
|
57
|
+
draw(cells, geoCanvas, resolution) {
|
|
58
|
+
//filter
|
|
59
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
60
|
+
|
|
61
|
+
//
|
|
62
|
+
const z = geoCanvas.view.z
|
|
63
|
+
const ctx = geoCanvas.offscreenCtx
|
|
64
|
+
|
|
65
|
+
//get view scale
|
|
66
|
+
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
67
|
+
|
|
68
|
+
//nb categories - used for radar and agepyramid
|
|
69
|
+
const cats = Object.keys(this.color)
|
|
70
|
+
|
|
71
|
+
//half resolution
|
|
72
|
+
const r2 = resolution / 2
|
|
73
|
+
|
|
74
|
+
//get offset
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
const offset = this.offset(undefined, resolution, z),
|
|
77
|
+
dx = offset.dx,
|
|
78
|
+
dy = offset.dy
|
|
79
|
+
|
|
80
|
+
//make sides
|
|
81
|
+
/** @type {Array.<Side>} */
|
|
82
|
+
const sides = SideStyle.buildSides(
|
|
83
|
+
cells,
|
|
84
|
+
resolution,
|
|
85
|
+
this.angle % 180 != 90 && this.sVert,
|
|
86
|
+
this.angle % 180 != 0 && this.sHor
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
//
|
|
90
|
+
if (sides.length == 0) return
|
|
91
|
+
|
|
92
|
+
//angle in radians
|
|
93
|
+
const aRad = (this.angle * Math.PI) / 180,
|
|
94
|
+
cos = Math.cos(aRad),
|
|
95
|
+
sin = Math.sin(aRad)
|
|
96
|
+
|
|
97
|
+
//sort sides so that the back ones are drawn first. This depends on the angle.
|
|
98
|
+
//depending on distance to the reference corner point
|
|
99
|
+
const xCorner = Math.abs(this.angle) < 90 ? geoCanvas.extGeo.xMin : geoCanvas.extGeo.xMax
|
|
100
|
+
const yCorner = this.angle < 0 ? geoCanvas.extGeo.yMax : geoCanvas.extGeo.yMin
|
|
101
|
+
sides.sort(
|
|
102
|
+
(s1, s2) =>
|
|
103
|
+
Math.hypot(s2.x - xCorner, s2.y - yCorner) - Math.hypot(s1.x - xCorner, s1.y - yCorner)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
//prepare function to draw corner line for a cell *c*
|
|
107
|
+
const drawCornerLine = (cell) => {
|
|
108
|
+
if (!cell) return
|
|
109
|
+
//line style
|
|
110
|
+
const lw = this.cornerLineWidth ? this.cornerLineWidth(cell, resolution, z, this.angle) : 0.8 * z
|
|
111
|
+
if (lw == 0) return
|
|
112
|
+
ctx.strokeStyle = this.cornerLineStrokeColor
|
|
113
|
+
? this.cornerLineStrokeColor(cell, resolution, z, this.angle)
|
|
114
|
+
: '#333'
|
|
115
|
+
ctx.lineWidth = lw
|
|
116
|
+
|
|
117
|
+
//height - in geo
|
|
118
|
+
const hG = this.height(cell, resolution, z, viewScale)
|
|
119
|
+
|
|
120
|
+
//draw line
|
|
121
|
+
ctx.beginPath()
|
|
122
|
+
ctx.moveTo(cell.x + r2 + dx, cell.y + r2 + dy)
|
|
123
|
+
ctx.lineTo(cell.x + r2 + hG * cos + dx, cell.y + r2 + hG * sin + dy)
|
|
124
|
+
ctx.stroke()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
//draw sides
|
|
128
|
+
ctx.lineCap = 'round'
|
|
129
|
+
for (let side of sides) {
|
|
130
|
+
const c1 = side.c1,
|
|
131
|
+
c2 = side.c2,
|
|
132
|
+
x = side.x,
|
|
133
|
+
y = side.y
|
|
134
|
+
|
|
135
|
+
//heights - in geo
|
|
136
|
+
const hG1 = c1 ? this.height(c1, resolution, z, viewScale) : 0,
|
|
137
|
+
hG2 = c2 ? this.height(c2, resolution, z, viewScale) : 0
|
|
138
|
+
|
|
139
|
+
//compute totals for both cells
|
|
140
|
+
const total1 = computeTotal(c1, cats),
|
|
141
|
+
total2 = computeTotal(c2, cats)
|
|
142
|
+
if (total1 == 0 && total2 == 0) continue
|
|
143
|
+
|
|
144
|
+
let cumul1 = 0,
|
|
145
|
+
cumul2 = 0
|
|
146
|
+
for (let [column, color] of Object.entries(this.color)) {
|
|
147
|
+
//draw stripe of side s and category column
|
|
148
|
+
|
|
149
|
+
//get values for both cells
|
|
150
|
+
let v1 = c1 ? +c1[column] : 0
|
|
151
|
+
let v2 = c2 ? +c2[column] : 0
|
|
152
|
+
if (v1 == 0 && v2 == 0) continue
|
|
153
|
+
|
|
154
|
+
//compute heights
|
|
155
|
+
const h1 = (hG1 * cumul1) / total1 || 0
|
|
156
|
+
const h1n = (hG1 * (cumul1 + v1)) / total1 || 0
|
|
157
|
+
const h2 = (hG2 * cumul2) / total2 || 0
|
|
158
|
+
const h2n = (hG2 * (cumul2 + v2)) / total2 || 0
|
|
159
|
+
|
|
160
|
+
//make path
|
|
161
|
+
ctx.beginPath()
|
|
162
|
+
if (side.or == 'h') {
|
|
163
|
+
//horizontal side - vertical section
|
|
164
|
+
//bottom left
|
|
165
|
+
ctx.moveTo(x + h1 * cos + dx, y - r2 + h1 * sin + dy)
|
|
166
|
+
//top left
|
|
167
|
+
ctx.lineTo(x + h2 * cos + dx, y + r2 + h2 * sin + dy)
|
|
168
|
+
//top right
|
|
169
|
+
ctx.lineTo(x + h2n * cos + dx, y + r2 + h2n * sin + dy)
|
|
170
|
+
//bottom right
|
|
171
|
+
ctx.lineTo(x + h1n * cos + dx, y - r2 + h1n * sin + dy)
|
|
172
|
+
} else {
|
|
173
|
+
//vertical side - horizontal section
|
|
174
|
+
//bottom left
|
|
175
|
+
ctx.moveTo(x - r2 + h1 * cos + dx, y + h1 * sin + dy)
|
|
176
|
+
//bottom right
|
|
177
|
+
ctx.lineTo(x + r2 + h2 * cos + dx, y + h2 * sin + dy)
|
|
178
|
+
//top right
|
|
179
|
+
ctx.lineTo(x + r2 + h2n * cos + dx, y + h2n * sin + dy)
|
|
180
|
+
//top left
|
|
181
|
+
ctx.lineTo(x - r2 + h1n * cos + dx, y + h1n * sin + dy)
|
|
182
|
+
}
|
|
183
|
+
//cg.ctx.closePath()
|
|
184
|
+
|
|
185
|
+
//fill
|
|
186
|
+
ctx.fillStyle = color
|
|
187
|
+
ctx.fill()
|
|
188
|
+
|
|
189
|
+
cumul1 += v1
|
|
190
|
+
cumul2 += v2
|
|
191
|
+
|
|
192
|
+
//TODO draw only one line
|
|
193
|
+
//draw corner line
|
|
194
|
+
//if (side.or == "h") {
|
|
195
|
+
drawCornerLine(c1)
|
|
196
|
+
drawCornerLine(c2)
|
|
197
|
+
//if (this.angle > 0 && side.or == "h") drawCornerLine(c2)
|
|
198
|
+
//else drawCornerLine(c2)
|
|
199
|
+
//}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//update legends
|
|
204
|
+
this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const computeTotal = (cell, categories) => {
|
|
209
|
+
if (!cell) return 0
|
|
210
|
+
let total = 0
|
|
211
|
+
for (let column of categories) {
|
|
212
|
+
const v = cell[column]
|
|
213
|
+
if (!v) continue
|
|
214
|
+
total += +v
|
|
215
|
+
}
|
|
216
|
+
return total || 0
|
|
217
|
+
}
|