gridviz 3.0.35 → 3.0.36
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 +129 -129
- package/dist/gridviz.js +17486 -17486
- package/dist/gridviz.min.js +2 -2
- package/package.json +73 -73
- package/src/button/Button.js +67 -67
- package/src/button/FullscreenButton.js +121 -121
- package/src/button/ZoomButtons.js +103 -103
- package/src/core/Dataset.js +154 -154
- package/src/core/Drawable.js +78 -78
- package/src/core/GeoCanvas.js +443 -443
- package/src/core/Layer.js +23 -23
- package/src/core/Legend.js +108 -108
- package/src/core/Map.js +568 -568
- package/src/core/MultiResolutionDataset.js +93 -93
- package/src/core/Style.js +98 -98
- package/src/core/Tooltip.js +182 -182
- package/src/dataset/COGeo.js +25 -25
- 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 +79 -79
- package/src/layer/BackgroundLayer.js +173 -173
- package/src/layer/BackgroundLayerImage.js +81 -81
- package/src/layer/BackgroundLayerWMS.js +104 -104
- package/src/layer/GeoJSONLayer.js +276 -276
- package/src/layer/GridLayer.js +166 -166
- 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/Interpolator.js +258 -258
- package/src/style/IsoFenceStyle.js +217 -217
- package/src/style/JoyPlotStyle.js +180 -180
- package/src/style/LegoStyle.js +132 -132
- 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/ShadingRayStyle.js +280 -280
- package/src/style/ShadingStyle.js +72 -72
- package/src/style/ShapeColorSizeStyle.js +147 -147
- package/src/style/SideCategoryStyle.js +112 -112
- package/src/style/SideStyle.js +217 -217
- package/src/style/SideTanakaStyle.js +154 -154
- package/src/style/SquareColorCategoryWebGLStyle.js +307 -294
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -135
- package/src/style/TextStyle.js +110 -110
- package/src/style/TimeSeriesStyle.js +222 -222
- package/src/utils/WebGLRectangleColoring.js +106 -106
- package/src/utils/WebGLSquareColoring.js +118 -118
- package/src/utils/WebGLSquareColoringAdvanced.js +227 -227
- package/src/utils/WebGLSquareColoringKS.js +153 -153
- package/src/utils/scale.js +255 -255
- package/src/utils/stretching.js +120 -120
- package/src/utils/ternary.js +208 -208
- package/src/utils/utils.js +125 -125
- package/src/utils/webGLUtils.js +73 -73
- package/src/utils/zoomUtils.js +142 -142
package/src/style/PillarStyle.js
CHANGED
|
@@ -1,207 +1,207 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Style } from '../core/Style.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @module style
|
|
8
|
-
* @author Julien Gaffuri
|
|
9
|
-
*/
|
|
10
|
-
export class PillarStyle extends Style {
|
|
11
|
-
/** @param {object} opts */
|
|
12
|
-
constructor(opts) {
|
|
13
|
-
super(opts)
|
|
14
|
-
opts = opts || {}
|
|
15
|
-
|
|
16
|
-
/** A function returning the height of the line representing a cell, in geo unit
|
|
17
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
18
|
-
this.height = opts.height
|
|
19
|
-
|
|
20
|
-
/** A function returning the color of the line representing a cell.
|
|
21
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):string} */
|
|
22
|
-
this.color = opts.color || (() => '#c08c59') //(c,r,z,vs) => {}
|
|
23
|
-
|
|
24
|
-
/** A function returning the width of the line representing a cell, in geo unit
|
|
25
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
26
|
-
this.width = opts.width || ((cell, resolution) => 0.5 * resolution)
|
|
27
|
-
|
|
28
|
-
/** A function returning the width of the line representing a cell, in geo unit
|
|
29
|
-
* @type {function(number, number,object):boolean} */
|
|
30
|
-
this.simple = opts.simple || (() => false)
|
|
31
|
-
|
|
32
|
-
/** @type {number} */
|
|
33
|
-
this.viewHeightFactor = opts.viewHeightFactor || 1.5
|
|
34
|
-
//0,0 is the center
|
|
35
|
-
/** @type {number} */
|
|
36
|
-
this.viewSX = opts.viewSX == undefined ? 0 : opts.viewSX
|
|
37
|
-
/** @type {number} */
|
|
38
|
-
this.viewSY = opts.viewSY == undefined ? -0.5 : opts.viewSY
|
|
39
|
-
|
|
40
|
-
//TODO replace with sun location ?
|
|
41
|
-
/** @type {number} */
|
|
42
|
-
this.shadowDirection =
|
|
43
|
-
opts.shadowDirection == undefined ? (-40.3 * Math.PI) / 180.0 : opts.shadowDirection
|
|
44
|
-
/** @type {number} */
|
|
45
|
-
this.shadowFactor = opts.shadowFactor || 0.3
|
|
46
|
-
/** @type {string} */
|
|
47
|
-
this.shadowColor = opts.shadowColor || '#00000033'
|
|
48
|
-
|
|
49
|
-
/** @type {string} */
|
|
50
|
-
this.outlineCol = opts.outlineCol || '#FFFFFF'
|
|
51
|
-
/** @type {number} */
|
|
52
|
-
this.outlineWidthPix = opts.outlineWidthPix == undefined ? 0.5 : opts.outlineWidthPix
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Draw cells as segments.
|
|
57
|
-
*
|
|
58
|
-
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
59
|
-
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
60
|
-
* @param {number} resolution
|
|
61
|
-
*/
|
|
62
|
-
draw(cells, geoCanvas, resolution) {
|
|
63
|
-
//filter
|
|
64
|
-
if (this.filter) cells = cells.filter(this.filter)
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
const z = geoCanvas.view.z
|
|
68
|
-
const ctx = geoCanvas.offscreenCtx
|
|
69
|
-
|
|
70
|
-
//get view scale
|
|
71
|
-
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
72
|
-
|
|
73
|
-
//get view center geo position
|
|
74
|
-
const cvx = geoCanvas.view.x + this.viewSX * geoCanvas.w * z
|
|
75
|
-
const cvy = geoCanvas.view.y + this.viewSY * geoCanvas.h * z
|
|
76
|
-
//get view height
|
|
77
|
-
const H = this.viewHeightFactor * (geoCanvas.w + geoCanvas.h) * 0.5 * z
|
|
78
|
-
|
|
79
|
-
//sort cells by y and x
|
|
80
|
-
//const distToViewCenter = (c) => { const dx = cvx - c.x, dy = cvy - c.y; return Math.sqrt(dx * dx + dy * dy) }
|
|
81
|
-
cells.sort((c1, c2) => 100000000 * (c2.y - c1.y) + c1.x - c2.x)
|
|
82
|
-
|
|
83
|
-
//get simple information
|
|
84
|
-
const simple = this.simple(resolution, z, viewScale)
|
|
85
|
-
|
|
86
|
-
ctx.lineCap = simple ? 'butt' : 'round'
|
|
87
|
-
|
|
88
|
-
//draw shadows
|
|
89
|
-
ctx.strokeStyle = this.shadowColor
|
|
90
|
-
ctx.fillStyle = this.shadowColor
|
|
91
|
-
for (let cell of cells) {
|
|
92
|
-
//width
|
|
93
|
-
/** @type {number|undefined} */
|
|
94
|
-
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
95
|
-
if (!wG || wG < 0) continue
|
|
96
|
-
|
|
97
|
-
//height
|
|
98
|
-
/** @type {number|undefined} */
|
|
99
|
-
const hG = this.height ? this.height(cell, resolution, z, viewScale) : undefined
|
|
100
|
-
if (!hG || hG < 0) continue
|
|
101
|
-
|
|
102
|
-
//get offset
|
|
103
|
-
//TODO use that
|
|
104
|
-
//const offset = this.offset(c, resolution, z)
|
|
105
|
-
|
|
106
|
-
//set width
|
|
107
|
-
ctx.lineWidth = wG
|
|
108
|
-
|
|
109
|
-
//compute cell center postition
|
|
110
|
-
const cx = cell.x + resolution / 2
|
|
111
|
-
const cy = cell.y + resolution / 2
|
|
112
|
-
const ls = hG * this.shadowFactor
|
|
113
|
-
|
|
114
|
-
//draw segment
|
|
115
|
-
ctx.beginPath()
|
|
116
|
-
ctx.moveTo(cx, cy)
|
|
117
|
-
ctx.lineTo(cx + ls * Math.cos(this.shadowDirection), cy + ls * Math.sin(this.shadowDirection))
|
|
118
|
-
ctx.stroke()
|
|
119
|
-
|
|
120
|
-
/*
|
|
121
|
-
if (this.simple) {
|
|
122
|
-
//draw base circle
|
|
123
|
-
cg.ctx.beginPath();
|
|
124
|
-
cg.ctx.arc(
|
|
125
|
-
cx, cy,
|
|
126
|
-
wG * 0.5,
|
|
127
|
-
0, 2 * Math.PI, false);
|
|
128
|
-
//cg.ctx.stroke();
|
|
129
|
-
cg.ctx.fill();
|
|
130
|
-
}*/
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
//draw pillars
|
|
134
|
-
for (let cell of cells) {
|
|
135
|
-
//color
|
|
136
|
-
/** @type {string|undefined} */
|
|
137
|
-
const col = this.color ? this.color(cell, resolution, z, viewScale) : undefined
|
|
138
|
-
if (!col) continue
|
|
139
|
-
|
|
140
|
-
//width
|
|
141
|
-
/** @type {number|undefined} */
|
|
142
|
-
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
143
|
-
if (!wG || wG < 0) continue
|
|
144
|
-
|
|
145
|
-
//height
|
|
146
|
-
/** @type {number|undefined} */
|
|
147
|
-
const hG = this.height ? this.height(cell, resolution, z, viewScale) : undefined
|
|
148
|
-
if (!hG || hG < 0) continue
|
|
149
|
-
|
|
150
|
-
//get offset
|
|
151
|
-
//TODO use that
|
|
152
|
-
//const offset = this.offset(c, resolution, z)
|
|
153
|
-
|
|
154
|
-
//compute cell center postition
|
|
155
|
-
const cx = cell.x + resolution / 2
|
|
156
|
-
const cy = cell.y + resolution / 2
|
|
157
|
-
|
|
158
|
-
//compute angle
|
|
159
|
-
const dx = cx - cvx,
|
|
160
|
-
dy = cy - cvy
|
|
161
|
-
const a = Math.atan2(dy, dx)
|
|
162
|
-
const D = Math.sqrt(dx * dx + dy * dy)
|
|
163
|
-
const d = (D * hG) / (H - hG)
|
|
164
|
-
|
|
165
|
-
if (simple) {
|
|
166
|
-
//draw segment
|
|
167
|
-
ctx.strokeStyle = col
|
|
168
|
-
ctx.lineWidth = wG
|
|
169
|
-
ctx.beginPath()
|
|
170
|
-
ctx.moveTo(cx, cy)
|
|
171
|
-
ctx.lineTo(cx + d * Math.cos(a), cy + d * Math.sin(a))
|
|
172
|
-
ctx.stroke()
|
|
173
|
-
} else {
|
|
174
|
-
//draw background segment
|
|
175
|
-
ctx.strokeStyle = this.outlineCol
|
|
176
|
-
ctx.lineWidth = wG + 2 * this.outlineWidthPix * z
|
|
177
|
-
ctx.beginPath()
|
|
178
|
-
ctx.moveTo(cx, cy)
|
|
179
|
-
ctx.lineTo(cx + d * Math.cos(a), cy + d * Math.sin(a))
|
|
180
|
-
ctx.stroke()
|
|
181
|
-
|
|
182
|
-
//draw segment
|
|
183
|
-
ctx.strokeStyle = col
|
|
184
|
-
ctx.lineWidth = wG
|
|
185
|
-
ctx.beginPath()
|
|
186
|
-
ctx.moveTo(cx, cy)
|
|
187
|
-
ctx.lineTo(cx + d * Math.cos(a), cy + d * Math.sin(a))
|
|
188
|
-
ctx.stroke()
|
|
189
|
-
|
|
190
|
-
//draw top circle
|
|
191
|
-
ctx.strokeStyle = this.outlineCol
|
|
192
|
-
//cg.ctx.fillStyle = "#c08c59"
|
|
193
|
-
ctx.lineWidth = this.outlineWidthPix * z
|
|
194
|
-
ctx.beginPath()
|
|
195
|
-
ctx.arc(cx + d * Math.cos(a), cy + d * Math.sin(a), wG * 0.5, 0, 2 * Math.PI, false)
|
|
196
|
-
ctx.stroke()
|
|
197
|
-
//cg.ctx.fill();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
//in case...
|
|
202
|
-
ctx.lineCap = 'butt'
|
|
203
|
-
|
|
204
|
-
//update legends
|
|
205
|
-
this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
|
|
206
|
-
}
|
|
207
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module style
|
|
8
|
+
* @author Julien Gaffuri
|
|
9
|
+
*/
|
|
10
|
+
export class PillarStyle extends Style {
|
|
11
|
+
/** @param {object} opts */
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
super(opts)
|
|
14
|
+
opts = opts || {}
|
|
15
|
+
|
|
16
|
+
/** A function returning the height of the line representing a cell, in geo unit
|
|
17
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
18
|
+
this.height = opts.height
|
|
19
|
+
|
|
20
|
+
/** A function returning the color of the line representing a cell.
|
|
21
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):string} */
|
|
22
|
+
this.color = opts.color || (() => '#c08c59') //(c,r,z,vs) => {}
|
|
23
|
+
|
|
24
|
+
/** A function returning the width of the line representing a cell, in geo unit
|
|
25
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
26
|
+
this.width = opts.width || ((cell, resolution) => 0.5 * resolution)
|
|
27
|
+
|
|
28
|
+
/** A function returning the width of the line representing a cell, in geo unit
|
|
29
|
+
* @type {function(number, number,object):boolean} */
|
|
30
|
+
this.simple = opts.simple || (() => false)
|
|
31
|
+
|
|
32
|
+
/** @type {number} */
|
|
33
|
+
this.viewHeightFactor = opts.viewHeightFactor || 1.5
|
|
34
|
+
//0,0 is the center
|
|
35
|
+
/** @type {number} */
|
|
36
|
+
this.viewSX = opts.viewSX == undefined ? 0 : opts.viewSX
|
|
37
|
+
/** @type {number} */
|
|
38
|
+
this.viewSY = opts.viewSY == undefined ? -0.5 : opts.viewSY
|
|
39
|
+
|
|
40
|
+
//TODO replace with sun location ?
|
|
41
|
+
/** @type {number} */
|
|
42
|
+
this.shadowDirection =
|
|
43
|
+
opts.shadowDirection == undefined ? (-40.3 * Math.PI) / 180.0 : opts.shadowDirection
|
|
44
|
+
/** @type {number} */
|
|
45
|
+
this.shadowFactor = opts.shadowFactor || 0.3
|
|
46
|
+
/** @type {string} */
|
|
47
|
+
this.shadowColor = opts.shadowColor || '#00000033'
|
|
48
|
+
|
|
49
|
+
/** @type {string} */
|
|
50
|
+
this.outlineCol = opts.outlineCol || '#FFFFFF'
|
|
51
|
+
/** @type {number} */
|
|
52
|
+
this.outlineWidthPix = opts.outlineWidthPix == undefined ? 0.5 : opts.outlineWidthPix
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Draw cells as segments.
|
|
57
|
+
*
|
|
58
|
+
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
59
|
+
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
60
|
+
* @param {number} resolution
|
|
61
|
+
*/
|
|
62
|
+
draw(cells, geoCanvas, resolution) {
|
|
63
|
+
//filter
|
|
64
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
65
|
+
|
|
66
|
+
//
|
|
67
|
+
const z = geoCanvas.view.z
|
|
68
|
+
const ctx = geoCanvas.offscreenCtx
|
|
69
|
+
|
|
70
|
+
//get view scale
|
|
71
|
+
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
72
|
+
|
|
73
|
+
//get view center geo position
|
|
74
|
+
const cvx = geoCanvas.view.x + this.viewSX * geoCanvas.w * z
|
|
75
|
+
const cvy = geoCanvas.view.y + this.viewSY * geoCanvas.h * z
|
|
76
|
+
//get view height
|
|
77
|
+
const H = this.viewHeightFactor * (geoCanvas.w + geoCanvas.h) * 0.5 * z
|
|
78
|
+
|
|
79
|
+
//sort cells by y and x
|
|
80
|
+
//const distToViewCenter = (c) => { const dx = cvx - c.x, dy = cvy - c.y; return Math.sqrt(dx * dx + dy * dy) }
|
|
81
|
+
cells.sort((c1, c2) => 100000000 * (c2.y - c1.y) + c1.x - c2.x)
|
|
82
|
+
|
|
83
|
+
//get simple information
|
|
84
|
+
const simple = this.simple(resolution, z, viewScale)
|
|
85
|
+
|
|
86
|
+
ctx.lineCap = simple ? 'butt' : 'round'
|
|
87
|
+
|
|
88
|
+
//draw shadows
|
|
89
|
+
ctx.strokeStyle = this.shadowColor
|
|
90
|
+
ctx.fillStyle = this.shadowColor
|
|
91
|
+
for (let cell of cells) {
|
|
92
|
+
//width
|
|
93
|
+
/** @type {number|undefined} */
|
|
94
|
+
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
95
|
+
if (!wG || wG < 0) continue
|
|
96
|
+
|
|
97
|
+
//height
|
|
98
|
+
/** @type {number|undefined} */
|
|
99
|
+
const hG = this.height ? this.height(cell, resolution, z, viewScale) : undefined
|
|
100
|
+
if (!hG || hG < 0) continue
|
|
101
|
+
|
|
102
|
+
//get offset
|
|
103
|
+
//TODO use that
|
|
104
|
+
//const offset = this.offset(c, resolution, z)
|
|
105
|
+
|
|
106
|
+
//set width
|
|
107
|
+
ctx.lineWidth = wG
|
|
108
|
+
|
|
109
|
+
//compute cell center postition
|
|
110
|
+
const cx = cell.x + resolution / 2
|
|
111
|
+
const cy = cell.y + resolution / 2
|
|
112
|
+
const ls = hG * this.shadowFactor
|
|
113
|
+
|
|
114
|
+
//draw segment
|
|
115
|
+
ctx.beginPath()
|
|
116
|
+
ctx.moveTo(cx, cy)
|
|
117
|
+
ctx.lineTo(cx + ls * Math.cos(this.shadowDirection), cy + ls * Math.sin(this.shadowDirection))
|
|
118
|
+
ctx.stroke()
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
if (this.simple) {
|
|
122
|
+
//draw base circle
|
|
123
|
+
cg.ctx.beginPath();
|
|
124
|
+
cg.ctx.arc(
|
|
125
|
+
cx, cy,
|
|
126
|
+
wG * 0.5,
|
|
127
|
+
0, 2 * Math.PI, false);
|
|
128
|
+
//cg.ctx.stroke();
|
|
129
|
+
cg.ctx.fill();
|
|
130
|
+
}*/
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
//draw pillars
|
|
134
|
+
for (let cell of cells) {
|
|
135
|
+
//color
|
|
136
|
+
/** @type {string|undefined} */
|
|
137
|
+
const col = this.color ? this.color(cell, resolution, z, viewScale) : undefined
|
|
138
|
+
if (!col) continue
|
|
139
|
+
|
|
140
|
+
//width
|
|
141
|
+
/** @type {number|undefined} */
|
|
142
|
+
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
143
|
+
if (!wG || wG < 0) continue
|
|
144
|
+
|
|
145
|
+
//height
|
|
146
|
+
/** @type {number|undefined} */
|
|
147
|
+
const hG = this.height ? this.height(cell, resolution, z, viewScale) : undefined
|
|
148
|
+
if (!hG || hG < 0) continue
|
|
149
|
+
|
|
150
|
+
//get offset
|
|
151
|
+
//TODO use that
|
|
152
|
+
//const offset = this.offset(c, resolution, z)
|
|
153
|
+
|
|
154
|
+
//compute cell center postition
|
|
155
|
+
const cx = cell.x + resolution / 2
|
|
156
|
+
const cy = cell.y + resolution / 2
|
|
157
|
+
|
|
158
|
+
//compute angle
|
|
159
|
+
const dx = cx - cvx,
|
|
160
|
+
dy = cy - cvy
|
|
161
|
+
const a = Math.atan2(dy, dx)
|
|
162
|
+
const D = Math.sqrt(dx * dx + dy * dy)
|
|
163
|
+
const d = (D * hG) / (H - hG)
|
|
164
|
+
|
|
165
|
+
if (simple) {
|
|
166
|
+
//draw segment
|
|
167
|
+
ctx.strokeStyle = col
|
|
168
|
+
ctx.lineWidth = wG
|
|
169
|
+
ctx.beginPath()
|
|
170
|
+
ctx.moveTo(cx, cy)
|
|
171
|
+
ctx.lineTo(cx + d * Math.cos(a), cy + d * Math.sin(a))
|
|
172
|
+
ctx.stroke()
|
|
173
|
+
} else {
|
|
174
|
+
//draw background segment
|
|
175
|
+
ctx.strokeStyle = this.outlineCol
|
|
176
|
+
ctx.lineWidth = wG + 2 * this.outlineWidthPix * z
|
|
177
|
+
ctx.beginPath()
|
|
178
|
+
ctx.moveTo(cx, cy)
|
|
179
|
+
ctx.lineTo(cx + d * Math.cos(a), cy + d * Math.sin(a))
|
|
180
|
+
ctx.stroke()
|
|
181
|
+
|
|
182
|
+
//draw segment
|
|
183
|
+
ctx.strokeStyle = col
|
|
184
|
+
ctx.lineWidth = wG
|
|
185
|
+
ctx.beginPath()
|
|
186
|
+
ctx.moveTo(cx, cy)
|
|
187
|
+
ctx.lineTo(cx + d * Math.cos(a), cy + d * Math.sin(a))
|
|
188
|
+
ctx.stroke()
|
|
189
|
+
|
|
190
|
+
//draw top circle
|
|
191
|
+
ctx.strokeStyle = this.outlineCol
|
|
192
|
+
//cg.ctx.fillStyle = "#c08c59"
|
|
193
|
+
ctx.lineWidth = this.outlineWidthPix * z
|
|
194
|
+
ctx.beginPath()
|
|
195
|
+
ctx.arc(cx + d * Math.cos(a), cy + d * Math.sin(a), wG * 0.5, 0, 2 * Math.PI, false)
|
|
196
|
+
ctx.stroke()
|
|
197
|
+
//cg.ctx.fill();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//in case...
|
|
202
|
+
ctx.lineCap = 'butt'
|
|
203
|
+
|
|
204
|
+
//update legends
|
|
205
|
+
this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
|
|
206
|
+
}
|
|
207
|
+
}
|
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Style } from '../core/Style.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* A style where each cell is represented by a segment whose length, width, color and orientation can vary according to statistical values.
|
|
8
|
-
*
|
|
9
|
-
* @module style
|
|
10
|
-
* @author Julien Gaffuri
|
|
11
|
-
*/
|
|
12
|
-
export class SegmentStyle extends Style {
|
|
13
|
-
/** @param {object} opts */
|
|
14
|
-
constructor(opts) {
|
|
15
|
-
super(opts)
|
|
16
|
-
opts = opts || {}
|
|
17
|
-
|
|
18
|
-
/** A function returning the color of the cell segment.
|
|
19
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):string} */
|
|
20
|
-
this.color = opts.color || (() => '#EA6BAC') //(c,r,z,vs) => {}
|
|
21
|
-
|
|
22
|
-
/** A function returning the width of the segment representing a cell, in geo unit
|
|
23
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
24
|
-
this.width = opts.width || ((cell, resolution) => resolution * 0.1) //(c,r,z,vs) => {}
|
|
25
|
-
|
|
26
|
-
/** A function returning the length of the segment representing a cell, in geo unit
|
|
27
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
28
|
-
this.length = opts.length || ((cell, resolution) => resolution * 0.9) //(c,r,z,vs) => {}
|
|
29
|
-
|
|
30
|
-
/** A function returning the orientation (in degrees) of the segment representing a cell.
|
|
31
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
32
|
-
this.orientation = opts.orientation || (() => 180 * Math.random()) //(c,r,z,vs) => {}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Draw cells as segments.
|
|
37
|
-
*
|
|
38
|
-
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
39
|
-
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
40
|
-
* @param {number} resolution
|
|
41
|
-
*/
|
|
42
|
-
draw(cells, geoCanvas, resolution) {
|
|
43
|
-
//filter
|
|
44
|
-
if (this.filter) cells = cells.filter(this.filter)
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
const z = geoCanvas.view.z
|
|
48
|
-
const ctx = geoCanvas.offscreenCtx
|
|
49
|
-
|
|
50
|
-
//get view scale
|
|
51
|
-
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
52
|
-
|
|
53
|
-
//
|
|
54
|
-
ctx.lineCap = 'butt'
|
|
55
|
-
|
|
56
|
-
//conversion factor degree -> radian
|
|
57
|
-
const f = Math.PI / 180
|
|
58
|
-
|
|
59
|
-
for (let cell of cells) {
|
|
60
|
-
//color
|
|
61
|
-
/** @type {string|undefined} */
|
|
62
|
-
const col = this.color ? this.color(cell, resolution, z, viewScale) : undefined
|
|
63
|
-
if (!col) continue
|
|
64
|
-
|
|
65
|
-
//width
|
|
66
|
-
/** @type {number|undefined} */
|
|
67
|
-
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
68
|
-
if (!wG || wG < 0) continue
|
|
69
|
-
|
|
70
|
-
//length
|
|
71
|
-
/** @type {number|undefined} */
|
|
72
|
-
const lG = this.length ? this.length(cell, resolution, z, viewScale) : undefined
|
|
73
|
-
if (!lG || lG < 0) continue
|
|
74
|
-
|
|
75
|
-
//orientation (in radian)
|
|
76
|
-
/** @type {number} */
|
|
77
|
-
const or = this.orientation(cell, resolution, z, viewScale) * f
|
|
78
|
-
if (or === undefined || isNaN(or)) continue
|
|
79
|
-
|
|
80
|
-
//get offset
|
|
81
|
-
const offset = this.offset(cell, resolution, z)
|
|
82
|
-
|
|
83
|
-
//set color and width
|
|
84
|
-
ctx.strokeStyle = col
|
|
85
|
-
ctx.lineWidth = wG
|
|
86
|
-
|
|
87
|
-
//compute segment center postition
|
|
88
|
-
const cx = cell.x + resolution / 2 + offset.dx
|
|
89
|
-
const cy = cell.y + resolution / 2 + offset.dy
|
|
90
|
-
|
|
91
|
-
//compute segment direction
|
|
92
|
-
const dx = 0.5 * Math.cos(or) * lG
|
|
93
|
-
const dy = 0.5 * Math.sin(or) * lG
|
|
94
|
-
|
|
95
|
-
//draw segment
|
|
96
|
-
ctx.beginPath()
|
|
97
|
-
ctx.moveTo(cx - dx, cy - dy)
|
|
98
|
-
ctx.lineTo(cx + dx, cy + dy)
|
|
99
|
-
ctx.stroke()
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
//update legends
|
|
103
|
-
this.updateLegends({ viewScale: viewScale, resolution: resolution, z: z, cells: cells })
|
|
104
|
-
}
|
|
105
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A style where each cell is represented by a segment whose length, width, color and orientation can vary according to statistical values.
|
|
8
|
+
*
|
|
9
|
+
* @module style
|
|
10
|
+
* @author Julien Gaffuri
|
|
11
|
+
*/
|
|
12
|
+
export class SegmentStyle extends Style {
|
|
13
|
+
/** @param {object} opts */
|
|
14
|
+
constructor(opts) {
|
|
15
|
+
super(opts)
|
|
16
|
+
opts = opts || {}
|
|
17
|
+
|
|
18
|
+
/** A function returning the color of the cell segment.
|
|
19
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):string} */
|
|
20
|
+
this.color = opts.color || (() => '#EA6BAC') //(c,r,z,vs) => {}
|
|
21
|
+
|
|
22
|
+
/** A function returning the width of the segment representing a cell, in geo unit
|
|
23
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
24
|
+
this.width = opts.width || ((cell, resolution) => resolution * 0.1) //(c,r,z,vs) => {}
|
|
25
|
+
|
|
26
|
+
/** A function returning the length of the segment representing a cell, in geo unit
|
|
27
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
28
|
+
this.length = opts.length || ((cell, resolution) => resolution * 0.9) //(c,r,z,vs) => {}
|
|
29
|
+
|
|
30
|
+
/** A function returning the orientation (in degrees) of the segment representing a cell.
|
|
31
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
32
|
+
this.orientation = opts.orientation || (() => 180 * Math.random()) //(c,r,z,vs) => {}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Draw cells as segments.
|
|
37
|
+
*
|
|
38
|
+
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
39
|
+
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
40
|
+
* @param {number} resolution
|
|
41
|
+
*/
|
|
42
|
+
draw(cells, geoCanvas, resolution) {
|
|
43
|
+
//filter
|
|
44
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
45
|
+
|
|
46
|
+
//
|
|
47
|
+
const z = geoCanvas.view.z
|
|
48
|
+
const ctx = geoCanvas.offscreenCtx
|
|
49
|
+
|
|
50
|
+
//get view scale
|
|
51
|
+
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
52
|
+
|
|
53
|
+
//
|
|
54
|
+
ctx.lineCap = 'butt'
|
|
55
|
+
|
|
56
|
+
//conversion factor degree -> radian
|
|
57
|
+
const f = Math.PI / 180
|
|
58
|
+
|
|
59
|
+
for (let cell of cells) {
|
|
60
|
+
//color
|
|
61
|
+
/** @type {string|undefined} */
|
|
62
|
+
const col = this.color ? this.color(cell, resolution, z, viewScale) : undefined
|
|
63
|
+
if (!col) continue
|
|
64
|
+
|
|
65
|
+
//width
|
|
66
|
+
/** @type {number|undefined} */
|
|
67
|
+
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
68
|
+
if (!wG || wG < 0) continue
|
|
69
|
+
|
|
70
|
+
//length
|
|
71
|
+
/** @type {number|undefined} */
|
|
72
|
+
const lG = this.length ? this.length(cell, resolution, z, viewScale) : undefined
|
|
73
|
+
if (!lG || lG < 0) continue
|
|
74
|
+
|
|
75
|
+
//orientation (in radian)
|
|
76
|
+
/** @type {number} */
|
|
77
|
+
const or = this.orientation(cell, resolution, z, viewScale) * f
|
|
78
|
+
if (or === undefined || isNaN(or)) continue
|
|
79
|
+
|
|
80
|
+
//get offset
|
|
81
|
+
const offset = this.offset(cell, resolution, z)
|
|
82
|
+
|
|
83
|
+
//set color and width
|
|
84
|
+
ctx.strokeStyle = col
|
|
85
|
+
ctx.lineWidth = wG
|
|
86
|
+
|
|
87
|
+
//compute segment center postition
|
|
88
|
+
const cx = cell.x + resolution / 2 + offset.dx
|
|
89
|
+
const cy = cell.y + resolution / 2 + offset.dy
|
|
90
|
+
|
|
91
|
+
//compute segment direction
|
|
92
|
+
const dx = 0.5 * Math.cos(or) * lG
|
|
93
|
+
const dy = 0.5 * Math.sin(or) * lG
|
|
94
|
+
|
|
95
|
+
//draw segment
|
|
96
|
+
ctx.beginPath()
|
|
97
|
+
ctx.moveTo(cx - dx, cy - dy)
|
|
98
|
+
ctx.lineTo(cx + dx, cy + dy)
|
|
99
|
+
ctx.stroke()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//update legends
|
|
103
|
+
this.updateLegends({ viewScale: viewScale, resolution: resolution, z: z, cells: cells })
|
|
104
|
+
}
|
|
105
|
+
}
|