gridviz 2.1.16 → 3.0.0
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 +2 -3
- package/dist/gridviz.js +4971 -5654
- package/dist/gridviz.min.js +1 -1
- package/package.json +3 -2
- package/src/button/Button.js +14 -15
- package/src/button/FullscreenButton.js +14 -14
- package/src/button/ZoomButtons.js +2 -2
- package/src/{DatasetComponent.js → core/Dataset.js} +33 -12
- package/src/core/Drawable.js +60 -0
- package/src/{GeoCanvas.js → core/GeoCanvas.js} +65 -155
- package/src/core/Layer.js +24 -0
- package/src/{Legend.js → core/Legend.js} +24 -1
- package/src/core/Map.js +460 -0
- package/src/core/MultiResolutionDataset.js +96 -0
- package/src/core/Style.js +84 -0
- package/src/dataset/COGeo.js +5 -5
- package/src/dataset/CSVGrid.js +43 -41
- package/src/dataset/GeoTIFF.js +9 -14
- package/src/dataset/{LGrid.js → JSGrid.js} +9 -10
- package/src/dataset/TiledGrid.js +68 -45
- package/src/index.js +22 -29
- package/src/{BackgroundLayer.js → layer/BackgroundLayer.js} +27 -52
- package/src/{BackgroundLayerWMS.js → layer/BackgroundLayerWMS.js} +21 -45
- package/src/{LineLayer.js → layer/GeoJSONLayer.js} +22 -23
- package/src/layer/GridLayer.js +140 -0
- package/src/{LabelLayer.js → layer/LabelLayer.js} +25 -23
- package/src/legend/ColorCategoryLegend.js +9 -24
- package/src/legend/ColorDiscreteLegend.js +20 -24
- package/src/legend/ColorLegend.js +21 -33
- package/src/legend/OrientationLegend.js +90 -0
- package/src/legend/SizeLegend.js +153 -72
- package/src/style/CompositionStyle.js +71 -84
- package/src/style/ContourStyle.js +2 -36
- package/src/style/DotDensityStyle.js +50 -73
- package/src/style/IsoFenceStyle.js +59 -70
- package/src/style/JoyPlotStyle.js +41 -48
- package/src/style/LegoStyle.js +4 -4
- package/src/style/MosaicStyle.js +30 -39
- package/src/style/NinjaStarStyle.js +45 -68
- package/src/style/PillarStyle.js +70 -93
- package/src/style/SegmentStyle.js +37 -75
- package/src/style/ShapeColorSizeStyle.js +49 -98
- package/src/style/SideCategoryStyle.js +112 -0
- package/src/style/SideStyle.js +99 -133
- package/src/style/{SquareColorCatWGLStyle.js → SquareColorCategoryWebGLStyle.js} +28 -41
- package/src/style/{SquareColorWGLStyle.js → SquareColorWebGLStyle.js} +28 -49
- package/src/style/StrokeStyle.js +43 -70
- package/src/style/TanakaStyle.js +34 -132
- package/src/style/TextStyle.js +43 -64
- package/src/style/TimeSeriesStyle.js +44 -75
- package/src/utils/WebGLSquareColoringAdvanced.js +4 -4
- package/src/utils/scale.js +202 -0
- package/src/utils/stretching.js +86 -129
- package/src/utils/{Utils.js → utils.js} +15 -0
- package/src/utils/webGLUtils.js +4 -5
- package/src/utils/zoomUtils.js +30 -30
- package/src/App.js +0 -760
- package/src/Dataset.js +0 -76
- package/src/Layer.js +0 -103
- package/src/Style.js +0 -131
- package/src/dataset/GridTile.js +0 -41
- package/src/legend/SegmentOrientationLegend.js +0 -87
- package/src/legend/SegmentWidthLegend.js +0 -101
- package/src/style/CompositionStyle_.js +0 -293
- package/src/style/ShapeColorSizeStyle_.js +0 -108
- package/src/style/SideCatStyle.js +0 -172
- /package/src/{Tooltip.js → core/Tooltip.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//@ts-check
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
|
-
import { Style } from '../Style.js'
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
5
5
|
|
|
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.
|
|
@@ -14,129 +14,91 @@ export class SegmentStyle extends Style {
|
|
|
14
14
|
super(opts)
|
|
15
15
|
opts = opts || {}
|
|
16
16
|
|
|
17
|
-
/** A function returning the orientation (in degrees) of the segment representing a cell.
|
|
18
|
-
* @type {function(import("../Dataset").Cell):number} */
|
|
19
|
-
this.orientation = opts.orientation || (() => 0)
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* @type {string} */
|
|
23
|
-
this.colorCol = opts.colorCol
|
|
24
|
-
|
|
25
17
|
/** A function returning the color of the cell segment.
|
|
26
|
-
* @type {function(
|
|
27
|
-
this.color = opts.color || (() =>
|
|
18
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):string} */
|
|
19
|
+
this.color = opts.color || (() => "#EA6BAC") //(c,r,z,vs) => {}
|
|
28
20
|
|
|
29
|
-
/**
|
|
30
|
-
* @type {
|
|
31
|
-
this.
|
|
21
|
+
/** A function returning the width of the segment representing a cell, in geo unit
|
|
22
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
23
|
+
this.width = opts.width || ((cell, resolution) => resolution * 0.1) //(c,r,z,vs) => {}
|
|
32
24
|
|
|
33
25
|
/** A function returning the length of the segment representing a cell, in geo unit
|
|
34
|
-
* @type {function(
|
|
35
|
-
this.length = opts.length
|
|
26
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
27
|
+
this.length = opts.length || ((cell, resolution) => resolution * 0.9) //(c,r,z,vs) => {}
|
|
36
28
|
|
|
37
|
-
/**
|
|
38
|
-
* @type {
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
/** A function returning the width of the segment representing a cell, in geo unit
|
|
42
|
-
* @type {function(number,number,import("../Style").Stat|undefined,number):number} */
|
|
43
|
-
this.width = opts.width
|
|
29
|
+
/** A function returning the orientation (in degrees) of the segment representing a cell.
|
|
30
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
31
|
+
this.orientation = opts.orientation || (() => 180 * Math.random()) //(c,r,z,vs) => {}
|
|
44
32
|
}
|
|
45
33
|
|
|
46
34
|
/**
|
|
47
35
|
* Draw cells as segments.
|
|
48
36
|
*
|
|
49
|
-
* @param {Array.<import("../Dataset").Cell>} cells
|
|
50
|
-
* @param {
|
|
51
|
-
* @param {
|
|
37
|
+
* @param {Array.<import("../core/Dataset").Cell>} cells
|
|
38
|
+
* @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas
|
|
39
|
+
* @param {number} resolution
|
|
52
40
|
*/
|
|
53
|
-
draw(cells,
|
|
41
|
+
draw(cells, geoCanvas, resolution) {
|
|
42
|
+
|
|
54
43
|
//filter
|
|
55
44
|
if (this.filter) cells = cells.filter(this.filter)
|
|
56
45
|
|
|
57
|
-
//
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
let statColor
|
|
61
|
-
if (this.colorCol) {
|
|
62
|
-
//compute color variable statistics
|
|
63
|
-
statColor = Style.getStatistics(cells, (c) => c[this.colorCol], true)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let statLength
|
|
67
|
-
if (this.lengthCol) {
|
|
68
|
-
//if length is used, sort cells by length so that the longests are drawn first
|
|
69
|
-
cells.sort((c1, c2) => c2[this.lengthCol] - c1[this.lengthCol])
|
|
70
|
-
//and compute size variable statistics
|
|
71
|
-
statLength = Style.getStatistics(cells, (c) => c[this.lengthCol], true)
|
|
72
|
-
}
|
|
46
|
+
//
|
|
47
|
+
const z = geoCanvas.view.z
|
|
73
48
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//and compute size variable statistics
|
|
77
|
-
statWidth = Style.getStatistics(cells, (c) => c[this.widthCol], true)
|
|
78
|
-
}
|
|
49
|
+
//get view scale
|
|
50
|
+
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
79
51
|
|
|
80
52
|
//
|
|
81
|
-
|
|
53
|
+
geoCanvas.ctx.lineCap = 'butt'
|
|
82
54
|
|
|
83
55
|
//conversion factor degree -> radian
|
|
84
56
|
const f = Math.PI / 180
|
|
85
57
|
|
|
86
|
-
|
|
87
|
-
cg.setCanvasTransform()
|
|
88
|
-
|
|
89
|
-
for (let c of cells) {
|
|
58
|
+
for (let cell of cells) {
|
|
90
59
|
//color
|
|
91
60
|
/** @type {string|undefined} */
|
|
92
|
-
const col = this.color ? this.color(
|
|
61
|
+
const col = this.color ? this.color(cell, resolution, z, viewScale) : undefined
|
|
93
62
|
if (!col) continue
|
|
94
63
|
|
|
95
64
|
//width
|
|
96
65
|
/** @type {number|undefined} */
|
|
97
|
-
const wG = this.width ? this.width(
|
|
66
|
+
const wG = this.width ? this.width(cell, resolution, z, viewScale) : undefined
|
|
98
67
|
if (!wG || wG < 0) continue
|
|
99
68
|
|
|
100
69
|
//length
|
|
101
70
|
/** @type {number|undefined} */
|
|
102
|
-
const lG = this.length ? this.length(
|
|
71
|
+
const lG = this.length ? this.length(cell, resolution, z, viewScale) : undefined
|
|
103
72
|
if (!lG || lG < 0) continue
|
|
104
73
|
|
|
105
74
|
//orientation (in radian)
|
|
106
75
|
/** @type {number} */
|
|
107
|
-
const or = this.orientation(
|
|
76
|
+
const or = this.orientation(cell, resolution, z, viewScale) * f
|
|
108
77
|
if (or === undefined || isNaN(or)) continue
|
|
109
78
|
|
|
110
79
|
//get offset
|
|
111
|
-
const offset = this.offset(
|
|
80
|
+
const offset = this.offset(cell, resolution, z)
|
|
112
81
|
|
|
113
82
|
//set color and width
|
|
114
|
-
|
|
115
|
-
|
|
83
|
+
geoCanvas.ctx.strokeStyle = col
|
|
84
|
+
geoCanvas.ctx.lineWidth = wG
|
|
116
85
|
|
|
117
86
|
//compute segment centre postition
|
|
118
|
-
const cx =
|
|
119
|
-
const cy =
|
|
87
|
+
const cx = cell.x + resolution / 2 + offset.dx
|
|
88
|
+
const cy = cell.y + resolution / 2 + offset.dy
|
|
120
89
|
|
|
121
90
|
//compute segment direction
|
|
122
91
|
const dx = 0.5 * Math.cos(or) * lG
|
|
123
92
|
const dy = 0.5 * Math.sin(or) * lG
|
|
124
93
|
|
|
125
94
|
//draw segment
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
95
|
+
geoCanvas.ctx.beginPath()
|
|
96
|
+
geoCanvas.ctx.moveTo(cx - dx, cy - dy)
|
|
97
|
+
geoCanvas.ctx.lineTo(cx + dx, cy + dy)
|
|
98
|
+
geoCanvas.ctx.stroke()
|
|
130
99
|
}
|
|
131
100
|
|
|
132
|
-
//update
|
|
133
|
-
this.updateLegends({
|
|
134
|
-
widthFun: this.width,
|
|
135
|
-
r: r,
|
|
136
|
-
zf: zf,
|
|
137
|
-
sColor: statColor,
|
|
138
|
-
//sLength: statLength,
|
|
139
|
-
sWidth: statWidth,
|
|
140
|
-
})
|
|
101
|
+
//update legends
|
|
102
|
+
this.updateLegends({ viewScale: viewScale, resolution: resolution, z: z, cells: cells })
|
|
141
103
|
}
|
|
142
104
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
//@ts-check
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
|
-
import { Style } from '../Style.js'
|
|
5
|
-
import { color } from 'd3-color'
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* A very generic style that shows grid cells with specific color, size and shape.
|
|
@@ -16,137 +15,89 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
16
15
|
super(opts)
|
|
17
16
|
opts = opts || {}
|
|
18
17
|
|
|
19
|
-
/** The name of the column/attribute of the tabular data where to retrieve the variable for color.
|
|
20
|
-
* @type {string} */
|
|
21
|
-
this.colorCol = opts.colorCol
|
|
22
|
-
|
|
23
18
|
/** A function returning the color of the cell.
|
|
24
|
-
* @type {function(
|
|
25
|
-
this.color = opts.color || (() =>
|
|
26
|
-
|
|
27
|
-
/** The name of the column/attribute of the tabular data where to retrieve the variable for size.
|
|
28
|
-
* @type {string} */
|
|
29
|
-
this.sizeCol = opts.sizeCol
|
|
19
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):string} */
|
|
20
|
+
this.color = opts.color || (() => "#EA6BAC") //(c,r,z,vs) => {}
|
|
30
21
|
|
|
31
22
|
/** A function returning the size of a cell in geographical unit.
|
|
32
|
-
* @type {function(
|
|
33
|
-
this.size = opts.size
|
|
23
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
24
|
+
this.size = opts.size || ((cell, resolution) => resolution) //(c,r,z,vs) => {}
|
|
34
25
|
|
|
35
26
|
/** A function returning the shape of a cell.
|
|
36
|
-
* @type {function(import("../Dataset").Cell):import("../Style").Shape} */
|
|
37
|
-
this.shape = opts.shape || (() =>
|
|
38
|
-
|
|
39
|
-
/** The name of the column/attribute of the tabular data where to retrieve the variable for color alpha.
|
|
40
|
-
* @type {string} */
|
|
41
|
-
this.alphaCol = opts.alphaCol
|
|
42
|
-
|
|
43
|
-
/** A function returning the color alpha of the cell.
|
|
44
|
-
* @type {function(number,number,import("../Style").Stat|undefined,number):number} */
|
|
45
|
-
this.alphaF = opts.alphaF
|
|
27
|
+
* @type {function(import("../core/Dataset.js").Cell,number, number,object):import("../core/Style.js").Shape} */
|
|
28
|
+
this.shape = opts.shape || (() => "square") //(c,r,z,vs) => {}
|
|
46
29
|
}
|
|
47
30
|
|
|
48
31
|
/**
|
|
49
|
-
* Draw cells as squares, with various colors and
|
|
50
|
-
*
|
|
51
|
-
* @param {Array.<import("../Dataset").Cell>} cells
|
|
52
|
-
* @param {
|
|
53
|
-
* @param {
|
|
32
|
+
* Draw cells as squares, with various colors and sizes.
|
|
33
|
+
*
|
|
34
|
+
* @param {Array.<import("../core/Dataset.js").Cell>} cells
|
|
35
|
+
* @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
|
|
36
|
+
* @param {number} resolution
|
|
37
|
+
* @override
|
|
54
38
|
*/
|
|
55
|
-
draw(cells,
|
|
39
|
+
draw(cells, geoCanvas, resolution) {
|
|
40
|
+
|
|
56
41
|
//filter
|
|
57
42
|
if (this.filter) cells = cells.filter(this.filter)
|
|
58
43
|
|
|
59
|
-
//zoom
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
let statSize
|
|
63
|
-
if (this.sizeCol) {
|
|
64
|
-
//if size is used, sort cells by size so that the biggest are drawn first
|
|
65
|
-
cells.sort((c1, c2) => c2[this.sizeCol] - c1[this.sizeCol])
|
|
66
|
-
//and compute size variable statistics
|
|
67
|
-
statSize = Style.getStatistics(cells, (c) => c[this.sizeCol], true)
|
|
68
|
-
}
|
|
44
|
+
//zoom
|
|
45
|
+
const z = geoCanvas.view.z
|
|
69
46
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
//compute color variable statistics
|
|
73
|
-
statColor = Style.getStatistics(cells, (c) => c[this.colorCol], true)
|
|
74
|
-
}
|
|
47
|
+
//get view scale
|
|
48
|
+
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
75
49
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
//compute color alpha variable statistics
|
|
79
|
-
statAlpha = Style.getStatistics(cells, (c) => c[this.alphaCol], true)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
//draw with HTML canvas
|
|
83
|
-
//in geo coordinates
|
|
84
|
-
cg.setCanvasTransform()
|
|
85
|
-
|
|
86
|
-
const r2 = r * 0.5
|
|
87
|
-
for (let cell of cells) {
|
|
50
|
+
const r2 = resolution * 0.5
|
|
51
|
+
for (let c of cells) {
|
|
88
52
|
//color
|
|
89
|
-
let col = this.color ? this.color(
|
|
53
|
+
let col = this.color ? this.color(c, resolution, z, viewScale) : "black"
|
|
90
54
|
if (!col || col === 'none') continue
|
|
91
55
|
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const alpha = this.alphaF(cell[this.alphaCol], r, statAlpha, zf)
|
|
96
|
-
if (alpha == 0) continue
|
|
97
|
-
//apply alpha to color col
|
|
98
|
-
const col_ = color(col);
|
|
99
|
-
if (col_) col = `rgba(${col_.r}, ${col_.g}, ${col_.b}, ${alpha})`;
|
|
100
|
-
else console.warn("Could not decode color " + col + " in ShapeColorSizeStyle")
|
|
101
|
-
}
|
|
56
|
+
//size
|
|
57
|
+
const size = this.size ? this.size(c, resolution, z, viewScale) : resolution
|
|
58
|
+
if (!size) continue
|
|
102
59
|
|
|
103
60
|
//shape
|
|
104
|
-
const shape = this.shape ? this.shape(
|
|
61
|
+
const shape = this.shape ? this.shape(c, resolution, z, viewScale) : 'square'
|
|
105
62
|
if (shape === 'none') continue
|
|
106
63
|
|
|
107
|
-
//size
|
|
108
|
-
/** @type {function(number,number,import("../Style").Stat|undefined,number):number} */
|
|
109
|
-
let s_ = this.size || (() => r)
|
|
110
|
-
//size - in geo unit
|
|
111
|
-
const sG = s_(cell[this.sizeCol], r, statSize, zf)
|
|
112
|
-
|
|
113
64
|
//get offset
|
|
114
|
-
const offset = this.offset(
|
|
65
|
+
const offset = this.offset(c, resolution, z)
|
|
115
66
|
|
|
116
|
-
|
|
67
|
+
geoCanvas.ctx.fillStyle = col
|
|
117
68
|
if (shape === 'square') {
|
|
118
69
|
//draw square
|
|
119
|
-
const d =
|
|
120
|
-
|
|
70
|
+
const d = resolution * (1 - size / resolution) * 0.5
|
|
71
|
+
geoCanvas.ctx.fillRect(c.x + d + offset.dx, c.y + d + offset.dy, size, size)
|
|
121
72
|
} else if (shape === 'circle') {
|
|
122
73
|
//draw circle
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
74
|
+
geoCanvas.ctx.beginPath()
|
|
75
|
+
geoCanvas.ctx.arc(c.x + r2 + offset.dx, c.y + r2 + offset.dy, size * 0.5, 0, 2 * Math.PI, false)
|
|
76
|
+
geoCanvas.ctx.fill()
|
|
126
77
|
} else if (shape === 'donut') {
|
|
127
78
|
//draw donut
|
|
128
|
-
const xc =
|
|
129
|
-
yc =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
79
|
+
const xc = c.x + r2 + offset.dx,
|
|
80
|
+
yc = c.y + r2 + offset.dy
|
|
81
|
+
geoCanvas.ctx.beginPath()
|
|
82
|
+
geoCanvas.ctx.moveTo(xc, yc)
|
|
83
|
+
geoCanvas.ctx.arc(xc, yc, r2, 0, 2 * Math.PI)
|
|
84
|
+
geoCanvas.ctx.arc(xc, yc, (1 - size / resolution) * r2, 0, 2 * Math.PI, true)
|
|
85
|
+
geoCanvas.ctx.closePath()
|
|
86
|
+
geoCanvas.ctx.fill()
|
|
136
87
|
} else if (shape === 'diamond') {
|
|
137
|
-
const s2 =
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
88
|
+
const s2 = size * 0.5
|
|
89
|
+
geoCanvas.ctx.beginPath()
|
|
90
|
+
geoCanvas.ctx.moveTo(c.x + r2 - s2, c.y + r2)
|
|
91
|
+
geoCanvas.ctx.lineTo(c.x + r2, c.y + r2 + s2)
|
|
92
|
+
geoCanvas.ctx.lineTo(c.x + r2 + s2, c.y + r2)
|
|
93
|
+
geoCanvas.ctx.lineTo(c.x + r2, c.y + r2 - s2)
|
|
94
|
+
geoCanvas.ctx.fill()
|
|
144
95
|
} else {
|
|
145
96
|
throw new Error('Unexpected shape:' + shape)
|
|
146
97
|
}
|
|
147
98
|
}
|
|
148
99
|
|
|
149
100
|
//update legends
|
|
150
|
-
this.updateLegends({
|
|
101
|
+
this.updateLegends({ viewScale: viewScale, resolution: resolution, z: z, cells: cells })
|
|
151
102
|
}
|
|
152
103
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { SideStyle } from './SideStyle.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A style to show the sides of grid cells based on their different categories.
|
|
8
|
+
*
|
|
9
|
+
* @author Julien Gaffuri
|
|
10
|
+
*/
|
|
11
|
+
export class SideCategoryStyle extends SideStyle {
|
|
12
|
+
/** @param {object} opts */
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
super(opts)
|
|
15
|
+
opts = opts || {}
|
|
16
|
+
|
|
17
|
+
/** A function returning the category code of a cell.
|
|
18
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number):string} */
|
|
19
|
+
this.code = opts.code
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The dictionary (string -> color) which give the color of each category.
|
|
23
|
+
* @type {object} */
|
|
24
|
+
this.color = opts.color
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {Array.<import("../core/Dataset.js").Cell>} cells
|
|
30
|
+
* @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
|
|
31
|
+
* @param {number} resolution
|
|
32
|
+
*/
|
|
33
|
+
draw(cells, geoCanvas, resolution) {
|
|
34
|
+
|
|
35
|
+
//filter
|
|
36
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
37
|
+
|
|
38
|
+
//
|
|
39
|
+
const z = geoCanvas.view.z
|
|
40
|
+
|
|
41
|
+
//build sides
|
|
42
|
+
|
|
43
|
+
/** @type {Array.<import('./SideStyle.js').Side>} */
|
|
44
|
+
const sides = SideStyle.buildSides(cells, resolution)
|
|
45
|
+
if (sides.length == 0) return
|
|
46
|
+
|
|
47
|
+
//get side view scale
|
|
48
|
+
const viewScale = this.viewScale ? this.viewScale(sides, resolution, z) : undefined
|
|
49
|
+
|
|
50
|
+
//draw sides
|
|
51
|
+
|
|
52
|
+
geoCanvas.ctx.lineCap = 'butt'
|
|
53
|
+
for (let side of sides) {
|
|
54
|
+
|
|
55
|
+
//get category codes for both cells
|
|
56
|
+
const code1 = side.c1 ? this.code(side.c1, resolution, z) : undefined
|
|
57
|
+
const code2 = side.c2 ? this.code(side.c2, resolution, z) : undefined
|
|
58
|
+
if (code1 == code2) continue
|
|
59
|
+
|
|
60
|
+
//width
|
|
61
|
+
/** @type {number|undefined} */
|
|
62
|
+
const wG = this.width ? this.width(side, resolution, z, viewScale) : undefined
|
|
63
|
+
if (!wG || wG <= 0) continue
|
|
64
|
+
const w2 = wG * 0.5
|
|
65
|
+
|
|
66
|
+
//set width
|
|
67
|
+
geoCanvas.ctx.lineWidth = wG
|
|
68
|
+
|
|
69
|
+
//draw segment with correct orientation
|
|
70
|
+
if (side.or === 'h') {
|
|
71
|
+
//top line
|
|
72
|
+
if (code2) {
|
|
73
|
+
geoCanvas.ctx.beginPath()
|
|
74
|
+
geoCanvas.ctx.strokeStyle = this.color[code2]
|
|
75
|
+
geoCanvas.ctx.moveTo(side.x, side.y + w2)
|
|
76
|
+
geoCanvas.ctx.lineTo(side.x + resolution, side.y + w2)
|
|
77
|
+
geoCanvas.ctx.stroke()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
//bottom line
|
|
81
|
+
if (code1) {
|
|
82
|
+
geoCanvas.ctx.beginPath()
|
|
83
|
+
geoCanvas.ctx.strokeStyle = this.color[code1]
|
|
84
|
+
geoCanvas.ctx.moveTo(side.x, side.y - w2)
|
|
85
|
+
geoCanvas.ctx.lineTo(side.x + resolution, side.y - w2)
|
|
86
|
+
geoCanvas.ctx.stroke()
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
//right line
|
|
90
|
+
if (code2) {
|
|
91
|
+
geoCanvas.ctx.beginPath()
|
|
92
|
+
geoCanvas.ctx.strokeStyle = this.color[code2]
|
|
93
|
+
geoCanvas.ctx.moveTo(side.x + w2, side.y)
|
|
94
|
+
geoCanvas.ctx.lineTo(side.x + w2, side.y + resolution)
|
|
95
|
+
geoCanvas.ctx.stroke()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
//left line
|
|
99
|
+
if (code1) {
|
|
100
|
+
geoCanvas.ctx.beginPath()
|
|
101
|
+
geoCanvas.ctx.strokeStyle = this.color[code1]
|
|
102
|
+
geoCanvas.ctx.moveTo(side.x - w2, side.y)
|
|
103
|
+
geoCanvas.ctx.lineTo(side.x - w2, side.y + resolution)
|
|
104
|
+
geoCanvas.ctx.stroke()
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
//update legends
|
|
110
|
+
this.updateLegends({ style: this, resolution: resolution, z: z, viewScale: viewScale })
|
|
111
|
+
}
|
|
112
|
+
}
|