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
package/src/style/SideStyle.js
CHANGED
|
@@ -1,205 +1,212 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Style } from '../core/Style.js'
|
|
5
|
-
|
|
6
|
-
/** @typedef {{ x:number, y:number, or:"v"|"h", c1:(import('../core/Dataset').Cell)|undefined, c2:(import('../core/Dataset').Cell)|undefined }} Side */
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {function(Array.<Side>,number, number):*} SideViewScale */
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @module style
|
|
13
|
-
* @author Julien Gaffuri
|
|
14
|
-
*/
|
|
15
|
-
export class SideStyle extends Style {
|
|
16
|
-
/** @param {object} opts */
|
|
17
|
-
constructor(opts = {}) {
|
|
18
|
-
super(opts)
|
|
19
|
-
|
|
20
|
-
/** A function returning the color of a cell side.
|
|
21
|
-
* @type {function(Side, number, number, object):string} */
|
|
22
|
-
this.color = opts.color || ((side, resolution, z, sideViewScale) => '#EA6BAC')
|
|
23
|
-
|
|
24
|
-
/** A function returning the width of a cell side, in geo unit
|
|
25
|
-
* @type {function(Side, number, number, object):number} */
|
|
26
|
-
this.width = opts.width || ((side, resolution, z, sideViewScale) => resolution / 5)
|
|
27
|
-
|
|
28
|
-
/** A function returning the length of a cell side, in geo unit
|
|
29
|
-
* @type {function(Side, number, number, object):number} */
|
|
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
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
38
|
-
* @param {number} resolution
|
|
39
|
-
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
40
|
-
*/
|
|
41
|
-
draw(cells, geoCanvas, resolution) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
//build sides
|
|
50
|
-
|
|
51
|
-
/** @type {Array.<Side>} */
|
|
52
|
-
const sides = SideStyle.buildSides(cells, resolution)
|
|
53
|
-
if (sides.length == 0) return
|
|
54
|
-
|
|
55
|
-
//get side view scale
|
|
56
|
-
const viewScale = this.viewScale ? this.viewScale(sides, resolution, z) : undefined
|
|
57
|
-
|
|
58
|
-
//draw sides
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const r2 = resolution * 0.5
|
|
62
|
-
for (let side of sides) {
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
*
|
|
124
|
-
* @param {
|
|
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
|
-
sides.push({
|
|
161
|
-
or: 'h',
|
|
162
|
-
x: c2.x + r2,
|
|
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
|
-
c1:
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
5
|
+
|
|
6
|
+
/** @typedef {{ x:number, y:number, or:"v"|"h", c1:(import('../core/Dataset').Cell)|undefined, c2:(import('../core/Dataset').Cell)|undefined }} Side */
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {function(Array.<Side>,number, number):*} SideViewScale */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @module style
|
|
13
|
+
* @author Julien Gaffuri
|
|
14
|
+
*/
|
|
15
|
+
export class SideStyle extends Style {
|
|
16
|
+
/** @param {object} opts */
|
|
17
|
+
constructor(opts = {}) {
|
|
18
|
+
super(opts)
|
|
19
|
+
|
|
20
|
+
/** A function returning the color of a cell side.
|
|
21
|
+
* @type {function(Side, number, number, object):string} */
|
|
22
|
+
this.color = opts.color || ((side, resolution, z, sideViewScale) => '#EA6BAC')
|
|
23
|
+
|
|
24
|
+
/** A function returning the width of a cell side, in geo unit
|
|
25
|
+
* @type {function(Side, number, number, object):number} */
|
|
26
|
+
this.width = opts.width || ((side, resolution, z, sideViewScale) => resolution / 5)
|
|
27
|
+
|
|
28
|
+
/** A function returning the length of a cell side, in geo unit
|
|
29
|
+
* @type {function(Side, number, number, object):number} */
|
|
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
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
38
|
+
* @param {number} resolution
|
|
39
|
+
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
40
|
+
*/
|
|
41
|
+
draw(cells, geoCanvas, resolution) {
|
|
42
|
+
//filter
|
|
43
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
44
|
+
|
|
45
|
+
//
|
|
46
|
+
const z = geoCanvas.view.z
|
|
47
|
+
const ctx = geoCanvas.offscreenCtx
|
|
48
|
+
|
|
49
|
+
//build sides
|
|
50
|
+
|
|
51
|
+
/** @type {Array.<Side>} */
|
|
52
|
+
const sides = SideStyle.buildSides(cells, resolution)
|
|
53
|
+
if (sides.length == 0) return
|
|
54
|
+
|
|
55
|
+
//get side view scale
|
|
56
|
+
const viewScale = this.viewScale ? this.viewScale(sides, resolution, z) : undefined
|
|
57
|
+
|
|
58
|
+
//draw sides
|
|
59
|
+
|
|
60
|
+
ctx.lineCap = 'butt'
|
|
61
|
+
const r2 = resolution * 0.5
|
|
62
|
+
for (let side of sides) {
|
|
63
|
+
//color
|
|
64
|
+
/** @type {string|undefined} */
|
|
65
|
+
const col = this.color ? this.color(side, resolution, z, viewScale) : undefined
|
|
66
|
+
if (!col || col == 'none') continue
|
|
67
|
+
|
|
68
|
+
if (this.diamond) {
|
|
69
|
+
//set color
|
|
70
|
+
ctx.fillStyle = col
|
|
71
|
+
|
|
72
|
+
//draw diamond
|
|
73
|
+
const x = side.x,
|
|
74
|
+
y = side.y
|
|
75
|
+
ctx.beginPath()
|
|
76
|
+
ctx.moveTo(x - r2, y)
|
|
77
|
+
ctx.lineTo(x, y + r2)
|
|
78
|
+
ctx.lineTo(x + r2, y)
|
|
79
|
+
ctx.lineTo(x, y - r2)
|
|
80
|
+
ctx.closePath()
|
|
81
|
+
ctx.fill()
|
|
82
|
+
} else {
|
|
83
|
+
//width
|
|
84
|
+
/** @type {number|undefined} */
|
|
85
|
+
const wG = this.width ? this.width(side, resolution, z, viewScale) : undefined
|
|
86
|
+
if (!wG || wG <= 0) continue
|
|
87
|
+
|
|
88
|
+
//length
|
|
89
|
+
/** @type {number|undefined} */
|
|
90
|
+
const lG = this.length ? this.length(side, resolution, z, viewScale) : undefined
|
|
91
|
+
if (!lG || lG <= 0) continue
|
|
92
|
+
const lG2 = lG * 0.5
|
|
93
|
+
|
|
94
|
+
//set width
|
|
95
|
+
ctx.lineWidth = wG
|
|
96
|
+
//set color
|
|
97
|
+
ctx.strokeStyle = col
|
|
98
|
+
|
|
99
|
+
//draw segment with correct orientation
|
|
100
|
+
const x = side.x,
|
|
101
|
+
y = side.y
|
|
102
|
+
ctx.beginPath()
|
|
103
|
+
if (side.or === 'v') {
|
|
104
|
+
ctx.moveTo(x, y - lG2)
|
|
105
|
+
ctx.lineTo(x, y + lG2)
|
|
106
|
+
} else {
|
|
107
|
+
ctx.moveTo(x - lG2, y)
|
|
108
|
+
ctx.lineTo(x + lG2, y)
|
|
109
|
+
}
|
|
110
|
+
ctx.stroke()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//update legends
|
|
115
|
+
this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
* @param {Array.<import('../core/Dataset').Cell>} cells The cells to use to build the sides.
|
|
121
|
+
* @param {number} resolution The cells resolution
|
|
122
|
+
* @param {boolean} withHorizontal Set to true to build horizontal sides, false otherwise.
|
|
123
|
+
* @param {boolean} withVertical Set to true to build vertical sides, false otherwise.
|
|
124
|
+
* @param {boolean} center 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)
|
|
125
|
+
* @returns { Array.<Side> }
|
|
126
|
+
*/
|
|
127
|
+
static buildSides(cells, resolution, withHorizontal = true, withVertical = true, center = true) {
|
|
128
|
+
/** @type { Array.<Side> } */
|
|
129
|
+
const sides = []
|
|
130
|
+
|
|
131
|
+
const r2 = center ? resolution / 2 : 0
|
|
132
|
+
|
|
133
|
+
//make horizontal sides
|
|
134
|
+
//sort cells by x and y
|
|
135
|
+
cells.sort((c1, c2) => (c2.x == c1.x ? c1.y - c2.y : c1.x - c2.x))
|
|
136
|
+
let c1 = cells[0]
|
|
137
|
+
for (let i = 1; i < cells.length; i++) {
|
|
138
|
+
let c2 = cells[i]
|
|
139
|
+
|
|
140
|
+
if (c1.y + resolution == c2.y && c1.x == c2.x)
|
|
141
|
+
//cells in same column and touch along horizontal side
|
|
142
|
+
//make shared side
|
|
143
|
+
sides.push({
|
|
144
|
+
or: 'h',
|
|
145
|
+
x: c1.x + r2,
|
|
146
|
+
y: c2.y,
|
|
147
|
+
c1: c1,
|
|
148
|
+
c2: c2,
|
|
149
|
+
})
|
|
150
|
+
else {
|
|
151
|
+
//cells do not touch along horizontal side
|
|
152
|
+
//make two sides: top one for c1, bottom for c2
|
|
153
|
+
sides.push({
|
|
154
|
+
or: 'h',
|
|
155
|
+
x: c1.x + r2,
|
|
156
|
+
y: c1.y + resolution,
|
|
157
|
+
c1: c1,
|
|
158
|
+
c2: undefined,
|
|
159
|
+
})
|
|
160
|
+
sides.push({
|
|
161
|
+
or: 'h',
|
|
162
|
+
x: c2.x + r2,
|
|
163
|
+
y: c2.y,
|
|
164
|
+
c1: undefined,
|
|
165
|
+
c2: c2,
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
c1 = c2
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
//make vertical sides
|
|
173
|
+
//sort cells by y and x
|
|
174
|
+
cells.sort((c1, c2) => (c2.y == c1.y ? c1.x - c2.x : c1.y - c2.y))
|
|
175
|
+
c1 = cells[0]
|
|
176
|
+
for (let i = 1; i < cells.length; i++) {
|
|
177
|
+
let c2 = cells[i]
|
|
178
|
+
|
|
179
|
+
if (c1.x + resolution == c2.x && c1.y == c2.y)
|
|
180
|
+
//cells in same row and touch along vertical side
|
|
181
|
+
//make shared side
|
|
182
|
+
sides.push({
|
|
183
|
+
or: 'v',
|
|
184
|
+
x: c1.x + resolution,
|
|
185
|
+
y: c1.y + r2,
|
|
186
|
+
c1: c1,
|
|
187
|
+
c2: c2,
|
|
188
|
+
})
|
|
189
|
+
else {
|
|
190
|
+
//cells do not touch along vertical side
|
|
191
|
+
//make two sides: right one for c1, left for c2
|
|
192
|
+
sides.push({
|
|
193
|
+
or: 'v',
|
|
194
|
+
x: c1.x + resolution,
|
|
195
|
+
y: c1.y + r2,
|
|
196
|
+
c1: c1,
|
|
197
|
+
c2: undefined,
|
|
198
|
+
})
|
|
199
|
+
sides.push({
|
|
200
|
+
or: 'v',
|
|
201
|
+
x: c2.x,
|
|
202
|
+
y: c2.y + r2,
|
|
203
|
+
c1: undefined,
|
|
204
|
+
c2: c2,
|
|
205
|
+
})
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
c1 = c2
|
|
209
|
+
}
|
|
210
|
+
return sides
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -1,108 +1,107 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Style } from '../core/Style.js'
|
|
5
|
-
import { makeWebGLCanvas } from '../utils/webGLUtils.js'
|
|
6
|
-
import { WebGLSquareColoringCatAdvanced } from '../utils/WebGLSquareColoringCatAdvanced.js'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Style based on webGL
|
|
10
|
-
* To show cells as colored squares, from categories.
|
|
11
|
-
* All cells are drawn as squares, with the same size
|
|
12
|
-
*
|
|
13
|
-
* @module style
|
|
14
|
-
* @author Julien Gaffuri
|
|
15
|
-
*/
|
|
16
|
-
export class SquareColorCategoryWebGLStyle extends Style {
|
|
17
|
-
/** @param {object} opts */
|
|
18
|
-
constructor(opts) {
|
|
19
|
-
super(opts)
|
|
20
|
-
opts = opts || {}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* A function returning the category code of the cell, for coloring.
|
|
24
|
-
* @type {function(import('../core/Dataset.js').Cell):string} */
|
|
25
|
-
this.code = opts.code
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* The dictionary (code -> color) which gives the color of each category code.
|
|
29
|
-
* @type {object} */
|
|
30
|
-
opts.color = opts.color || undefined
|
|
31
|
-
|
|
32
|
-
/** @type { Array.<string> } */
|
|
33
|
-
const codes = Object.keys(opts.color)
|
|
34
|
-
|
|
35
|
-
/** @type { object } @private */
|
|
36
|
-
this.catToI = {}
|
|
37
|
-
for (let i = 0; i < codes.length; i++) this.catToI[codes[i]] = i + ''
|
|
38
|
-
|
|
39
|
-
/** @type { Array.<string> } @private */
|
|
40
|
-
this.colors = []
|
|
41
|
-
for (const code of codes)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
* @
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* @param {
|
|
57
|
-
* @param {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const
|
|
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
|
-
geoCanvas.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
5
|
+
import { makeWebGLCanvas } from '../utils/webGLUtils.js'
|
|
6
|
+
import { WebGLSquareColoringCatAdvanced } from '../utils/WebGLSquareColoringCatAdvanced.js'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Style based on webGL
|
|
10
|
+
* To show cells as colored squares, from categories.
|
|
11
|
+
* All cells are drawn as squares, with the same size
|
|
12
|
+
*
|
|
13
|
+
* @module style
|
|
14
|
+
* @author Julien Gaffuri
|
|
15
|
+
*/
|
|
16
|
+
export class SquareColorCategoryWebGLStyle extends Style {
|
|
17
|
+
/** @param {object} opts */
|
|
18
|
+
constructor(opts) {
|
|
19
|
+
super(opts)
|
|
20
|
+
opts = opts || {}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A function returning the category code of the cell, for coloring.
|
|
24
|
+
* @type {function(import('../core/Dataset.js').Cell):string} */
|
|
25
|
+
this.code = opts.code
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The dictionary (code -> color) which gives the color of each category code.
|
|
29
|
+
* @type {object} */
|
|
30
|
+
opts.color = opts.color || undefined
|
|
31
|
+
|
|
32
|
+
/** @type { Array.<string> } */
|
|
33
|
+
const codes = Object.keys(opts.color)
|
|
34
|
+
|
|
35
|
+
/** @type { object } @private */
|
|
36
|
+
this.catToI = {}
|
|
37
|
+
for (let i = 0; i < codes.length; i++) this.catToI[codes[i]] = i + ''
|
|
38
|
+
|
|
39
|
+
/** @type { Array.<string> } @private */
|
|
40
|
+
this.colors = []
|
|
41
|
+
for (const code of codes) this.colors.push(opts.color['' + code])
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A function returning the size of the cells, in geographical unit. All cells have the same size.
|
|
45
|
+
* @type {function(number,number):number} */
|
|
46
|
+
this.size = opts.size // (resolution, z) => ...
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @private
|
|
50
|
+
* @type { WebGLSquareColoringCatAdvanced } */
|
|
51
|
+
this.wgp = new WebGLSquareColoringCatAdvanced(this.colors)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {Array.<import("../core/Dataset.js").Cell>} cells
|
|
56
|
+
* @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
|
|
57
|
+
* @param {number} resolution
|
|
58
|
+
*/
|
|
59
|
+
draw(cells, geoCanvas, resolution) {
|
|
60
|
+
//filter
|
|
61
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
62
|
+
|
|
63
|
+
//
|
|
64
|
+
const z = geoCanvas.view.z
|
|
65
|
+
|
|
66
|
+
//add vertice and fragment data
|
|
67
|
+
const r2 = resolution / 2
|
|
68
|
+
let c,
|
|
69
|
+
nb = cells.length
|
|
70
|
+
const verticesBuffer = []
|
|
71
|
+
const iBuffer = []
|
|
72
|
+
for (let i = 0; i < nb; i++) {
|
|
73
|
+
c = cells[i]
|
|
74
|
+
const cat = this.code(c)
|
|
75
|
+
if (cat == undefined) {
|
|
76
|
+
console.log('Unexpected category: ' + cat)
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
79
|
+
/** @type {number} */
|
|
80
|
+
const i_ = this.catToI[cat]
|
|
81
|
+
if (isNaN(+i_)) {
|
|
82
|
+
console.log('Unexpected category index: ' + cat + ' ' + i_)
|
|
83
|
+
continue
|
|
84
|
+
}
|
|
85
|
+
verticesBuffer.push(c.x + r2, c.y + r2)
|
|
86
|
+
iBuffer.push(+i_)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//create canvas and webgl renderer
|
|
90
|
+
const cvWGL = makeWebGLCanvas(geoCanvas.w + '', geoCanvas.h + '')
|
|
91
|
+
if (!cvWGL) {
|
|
92
|
+
console.error('No webGL')
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
//draw
|
|
97
|
+
const sizeGeo = this.size ? this.size(resolution, z) : resolution + 0.2 * z
|
|
98
|
+
this.wgp.draw(cvWGL.gl, verticesBuffer, iBuffer, geoCanvas.getWebGLTransform(), sizeGeo / z)
|
|
99
|
+
|
|
100
|
+
//draw in canvas geo
|
|
101
|
+
geoCanvas.initCanvasTransform()
|
|
102
|
+
geoCanvas.offscreenCtx.drawImage(cvWGL.canvas, 0, 0)
|
|
103
|
+
|
|
104
|
+
//update legends
|
|
105
|
+
this.updateLegends({ style: this, resolution: resolution, z: z })
|
|
106
|
+
}
|
|
107
|
+
}
|