@abi-software/flatmap-viewer 2.6.0-a.1 → 2.6.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.rst +2 -2
- package/package.json +24 -10
- package/src/controls/annotation.js +27 -10
- package/src/flatmap-viewer.js +50 -2
- package/src/interactions.js +89 -116
- package/src/layers/filter.js +310 -0
- package/src/layers/index.js +132 -45
- package/src/layers/paths3d.js +60 -10
- package/src/main.js +1 -4
- package/src/layers/filter.ts +0 -187
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
|
|
3
|
+
Flatmap viewer and annotation tool
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2019 - 2024 David Brooks
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
you may not use this file except in compliance with the License.
|
|
9
|
+
You may obtain a copy of the License at
|
|
10
|
+
|
|
11
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
|
|
13
|
+
Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
See the License for the specific language governing permissions and
|
|
17
|
+
limitations under the License.
|
|
18
|
+
|
|
19
|
+
******************************************************************************/
|
|
20
|
+
|
|
21
|
+
import Set from 'core-js-pure/actual/set'
|
|
22
|
+
|
|
23
|
+
//==============================================================================
|
|
24
|
+
|
|
25
|
+
export class PropertiesFilter
|
|
26
|
+
{
|
|
27
|
+
#filter
|
|
28
|
+
|
|
29
|
+
constructor(filter=true)
|
|
30
|
+
//======================
|
|
31
|
+
{
|
|
32
|
+
if (filter.constructor !== Object) { // We allow boolean values
|
|
33
|
+
this.#filter = filter
|
|
34
|
+
} else {
|
|
35
|
+
this.#filter = Object.assign({}, filter)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
clear()
|
|
40
|
+
//=====
|
|
41
|
+
{
|
|
42
|
+
if (this.#filter !== true) {
|
|
43
|
+
this.#filter = true
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
expand(filter)
|
|
48
|
+
//============
|
|
49
|
+
{
|
|
50
|
+
if (this.#filter === false) {
|
|
51
|
+
this.#filter = filter
|
|
52
|
+
} else if (this.#filter !== true) {
|
|
53
|
+
const copiedFilter = Object.assign({}, filter)
|
|
54
|
+
this.#filter = { "OR": [this.#filter, copiedFilter] }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
invert()
|
|
59
|
+
//======
|
|
60
|
+
{
|
|
61
|
+
if (this.#filter === false) {
|
|
62
|
+
this.#filter = true
|
|
63
|
+
} else if (this.#filter === true) {
|
|
64
|
+
this.#filter = false
|
|
65
|
+
} else {
|
|
66
|
+
const copiedFilter = Object.assign({}, filter)
|
|
67
|
+
this.#filter = { "NOT": copiedFilter }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getFilter()
|
|
72
|
+
//=========
|
|
73
|
+
{
|
|
74
|
+
return this.#filter
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
makeStyleFilter()
|
|
78
|
+
//===============
|
|
79
|
+
{
|
|
80
|
+
return this.#makeStyleFilter(this.#filter)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
match(properties)
|
|
84
|
+
//===============
|
|
85
|
+
{
|
|
86
|
+
return this.#match(properties, this.#filter)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
narrow(filter)
|
|
90
|
+
//============
|
|
91
|
+
{
|
|
92
|
+
if (this.#filter === true) {
|
|
93
|
+
this.#filter = filter
|
|
94
|
+
} else if (this.#filter !== false) {
|
|
95
|
+
const copiedFilter = Object.assign({}, filter)
|
|
96
|
+
this.#filter = { "AND": [this.#filter, copiedFilter] }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
setFilter(filter)
|
|
101
|
+
//===============
|
|
102
|
+
{
|
|
103
|
+
if (filter.constructor !== Object) {
|
|
104
|
+
this.#filter = filter
|
|
105
|
+
} else {
|
|
106
|
+
this.#filter = Object.assign({}, filter)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#makeStyleFilter(filter)
|
|
111
|
+
//======================
|
|
112
|
+
{
|
|
113
|
+
if (filter.constructor !== Object) {
|
|
114
|
+
return !!filter
|
|
115
|
+
}
|
|
116
|
+
const styleFilter = []
|
|
117
|
+
for (const [key, expr] of Object.entries(filter)) {
|
|
118
|
+
if (key === 'AND' || key === 'OR') {
|
|
119
|
+
if (Array.isArray(expr) && expr.length >= 2) {
|
|
120
|
+
styleFilter.push((key === 'AND') ? 'all' : 'any',
|
|
121
|
+
...expr.map(e => this.#makeStyleFilter(e)))
|
|
122
|
+
} else {
|
|
123
|
+
console.warn(`makeFilter: Invalid ${key} operands: ${expr}`)
|
|
124
|
+
}
|
|
125
|
+
} else if (key === 'HAS') {
|
|
126
|
+
styleFilter.push('has', expr)
|
|
127
|
+
} else if (key === 'NOT') {
|
|
128
|
+
const filterExpr = this.#makeStyleFilter(expr)
|
|
129
|
+
if (Array.isArray(filterExpr)) {
|
|
130
|
+
if (filterExpr.length === 2 && ['has', '!has'].includes(filterExpr[0])) {
|
|
131
|
+
if (filterExpr[0] === 'has') {
|
|
132
|
+
styleFilter.push('!has', filterExpr[1])
|
|
133
|
+
} else {
|
|
134
|
+
styleFilter.push('has', filterExpr[1])
|
|
135
|
+
}
|
|
136
|
+
} else if (filterExpr.length === 3 && ['==', '!='].includes(filterExpr[0])) {
|
|
137
|
+
if (filterExpr[0] === '==') {
|
|
138
|
+
styleFilter.push('!=', filterExpr[1], filterExpr[2])
|
|
139
|
+
} else {
|
|
140
|
+
styleFilter.push('==', filterExpr[1], filterExpr[2])
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
styleFilter.push('!', filterExpr)
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
styleFilter.push(!filterExpr)
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
if (Array.isArray(expr)) {
|
|
150
|
+
styleFilter.push('any', ...expr.map(e => ['==', key, e]))
|
|
151
|
+
} else {
|
|
152
|
+
styleFilter.push('==', key, expr)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return styleFilter
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
#match(properties, filter)
|
|
160
|
+
//========================
|
|
161
|
+
{
|
|
162
|
+
if (filter.constructor !== Object) {
|
|
163
|
+
return !!filter
|
|
164
|
+
}
|
|
165
|
+
for (const [key, expr] of Object.entries(filter)) {
|
|
166
|
+
let matched = true
|
|
167
|
+
if (key === 'AND' || key === 'OR') {
|
|
168
|
+
if (Array.isArray(expr) && expr.length >= 2) {
|
|
169
|
+
const matches = expr.map(e => this.#match(properties, e))
|
|
170
|
+
matched = (key === 'AND') ? matches.reduce((result, match) => result && match, true)
|
|
171
|
+
: matches.reduce((result, match) => result || match, false)
|
|
172
|
+
} else {
|
|
173
|
+
console.warn(`makeFilter: Invalid ${key} operands: ${expr}`)
|
|
174
|
+
}
|
|
175
|
+
} else if (key === 'HAS') {
|
|
176
|
+
matched = (expr in properties)
|
|
177
|
+
} else if (key === 'NOT') {
|
|
178
|
+
matched = !this.#match(properties, expr)
|
|
179
|
+
} else if (key in properties) {
|
|
180
|
+
const value = properties[key]
|
|
181
|
+
if (Array.isArray(value)) {
|
|
182
|
+
if (Array.isArray(expr)) {
|
|
183
|
+
matched = !(new Set(value).isDisjointFrom(new Set(expr)))
|
|
184
|
+
} else {
|
|
185
|
+
matched = value.includes(expr)
|
|
186
|
+
}
|
|
187
|
+
} else if (Array.isArray(expr)) {
|
|
188
|
+
matched = expr.includes(value)
|
|
189
|
+
} else {
|
|
190
|
+
matched = (value === expr)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (!matched) {
|
|
194
|
+
return false
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return true
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
//==============================================================================
|
|
202
|
+
|
|
203
|
+
const testProperties = {
|
|
204
|
+
prop: 1,
|
|
205
|
+
prop1: 5,
|
|
206
|
+
prop2: 11,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function testFilter(filter)
|
|
210
|
+
//=========================
|
|
211
|
+
{
|
|
212
|
+
const featureFilter = new PropertiesFilter(filter)
|
|
213
|
+
console.log(filter, '--->', featureFilter.makeStyleFilter(), featureFilter.match(testProperties))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function testFilters()
|
|
217
|
+
//====================
|
|
218
|
+
{
|
|
219
|
+
/*
|
|
220
|
+
{ HAS: 'prop' } ---> [ 'has', 'prop' ]
|
|
221
|
+
{ prop: 1 } ---> [ '==', 'prop', 1 ]
|
|
222
|
+
{ NOT: { prop: 1 } } ---> [ '!=', 'prop', 1 ]
|
|
223
|
+
{ NOT: { prop: [ 1, 2 ] } } ---> [ '!', [ 'any', [ '==', 'prop', 1 ], [ '==', 'prop', 2 ] ] ]
|
|
224
|
+
{ OR: [ { prop1: 10 }, { prop2: 11 } ] } ---> [ 'any', [ '==', 'prop1', 10 ], [ '==', 'prop2', 11 ] ]
|
|
225
|
+
{ AND: [ { prop1: 10 }, { prop2: 11 } ] } ---> [ 'all', [ '==', 'prop1', 10 ], [ '==', 'prop2', 11 ] ]
|
|
226
|
+
{ OR: [ { AND: [Array] }, { AND: [Array] } ] } ---> [
|
|
227
|
+
'any',
|
|
228
|
+
[ 'all', [ '!=', 'prop1', 10 ], [ '==', 'prop2', 11 ] ],
|
|
229
|
+
[ 'all', [ '==', 'prop3', 10 ], [ '==', 'prop4', 11 ] ]
|
|
230
|
+
]
|
|
231
|
+
{ NOT: { OR: [ [Object], [Object] ] } } ---> [
|
|
232
|
+
'!',
|
|
233
|
+
[ 'any', [ 'all', [Array], [Array] ], [ 'all', [Array], [Array] ] ]
|
|
234
|
+
]
|
|
235
|
+
*/
|
|
236
|
+
|
|
237
|
+
console.log('test properties', testProperties)
|
|
238
|
+
|
|
239
|
+
testFilter({
|
|
240
|
+
"HAS": "prop"
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
testFilter({
|
|
244
|
+
"prop": 1
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
testFilter({
|
|
248
|
+
"NOT": {
|
|
249
|
+
"prop": 1
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
testFilter({
|
|
254
|
+
"prop": [1, 2]
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
testFilter({
|
|
258
|
+
"NOT": {
|
|
259
|
+
"prop": [1, 2]
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
testFilter({
|
|
264
|
+
"OR": [
|
|
265
|
+
{"prop1": 10},
|
|
266
|
+
{"prop2": 11}
|
|
267
|
+
]
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
testFilter({
|
|
271
|
+
"AND": [
|
|
272
|
+
{"prop1": 10},
|
|
273
|
+
{"prop2": 11}
|
|
274
|
+
]
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
testFilter({
|
|
278
|
+
"OR": [{
|
|
279
|
+
"AND": [
|
|
280
|
+
{ "NOT": {"prop1": 10}},
|
|
281
|
+
{"prop2": 11}
|
|
282
|
+
]}, {
|
|
283
|
+
"AND": [
|
|
284
|
+
{"prop3": 10},
|
|
285
|
+
{"prop4": 11}
|
|
286
|
+
]}
|
|
287
|
+
]
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
testFilter({
|
|
291
|
+
"NOT": {
|
|
292
|
+
"OR": [{
|
|
293
|
+
"AND": [
|
|
294
|
+
{"prop1": 10},
|
|
295
|
+
{"prop2": 11}
|
|
296
|
+
]}, {
|
|
297
|
+
"AND": [
|
|
298
|
+
{"prop3": 10},
|
|
299
|
+
{"prop4": 11}
|
|
300
|
+
]}
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
//==============================================================================
|
|
307
|
+
|
|
308
|
+
//testFilters()
|
|
309
|
+
|
|
310
|
+
//==============================================================================
|
package/src/layers/index.js
CHANGED
|
@@ -22,13 +22,14 @@ limitations under the License.
|
|
|
22
22
|
|
|
23
23
|
//==============================================================================
|
|
24
24
|
|
|
25
|
-
import {FeatureFilter} from './filter'
|
|
26
|
-
|
|
27
25
|
import {PATHWAYS_LAYER} from '../pathways.js';
|
|
28
26
|
import * as utils from '../utils.js';
|
|
29
27
|
|
|
30
28
|
import * as style from './styling.js';
|
|
31
29
|
|
|
30
|
+
import {Paths3DLayer} from './paths3d'
|
|
31
|
+
import {PropertiesFilter} from './filter'
|
|
32
|
+
|
|
32
33
|
const FEATURES_LAYER = 'features';
|
|
33
34
|
const RASTER_LAYERS_NAME = 'Background image layer';
|
|
34
35
|
const RASTER_LAYERS_ID = 'background-image-layer';
|
|
@@ -46,11 +47,6 @@ class MapStylingLayers
|
|
|
46
47
|
this.__layers = [];
|
|
47
48
|
this.__layerOptions = options;
|
|
48
49
|
this.__separateLayers = flatmap.options.separateLayers;
|
|
49
|
-
|
|
50
|
-
const f = new FeatureFilter({
|
|
51
|
-
"HAS": "prop"
|
|
52
|
-
})
|
|
53
|
-
console.log(f.makeStyleFilter())
|
|
54
50
|
}
|
|
55
51
|
|
|
56
52
|
get id()
|
|
@@ -71,6 +67,12 @@ class MapStylingLayers
|
|
|
71
67
|
return this.__active;
|
|
72
68
|
}
|
|
73
69
|
|
|
70
|
+
get map()
|
|
71
|
+
//=======
|
|
72
|
+
{
|
|
73
|
+
return this.__map
|
|
74
|
+
}
|
|
75
|
+
|
|
74
76
|
addLayer(styleLayer, options)
|
|
75
77
|
//===========================
|
|
76
78
|
{
|
|
@@ -113,6 +115,8 @@ class MapStylingLayers
|
|
|
113
115
|
|
|
114
116
|
class MapFeatureLayers extends MapStylingLayers
|
|
115
117
|
{
|
|
118
|
+
#pathLayers = []
|
|
119
|
+
|
|
116
120
|
constructor(flatmap, layer, options)
|
|
117
121
|
{
|
|
118
122
|
super(flatmap, layer, options);
|
|
@@ -144,35 +148,46 @@ class MapFeatureLayers extends MapStylingLayers
|
|
|
144
148
|
this.setPaint(this.__layerOptions);
|
|
145
149
|
}
|
|
146
150
|
|
|
147
|
-
__addStyleLayer(styleClass, sourceLayer=FEATURES_LAYER)
|
|
148
|
-
|
|
151
|
+
__addStyleLayer(styleClass, sourceLayer=FEATURES_LAYER, path2dLayer=false)
|
|
152
|
+
//========================================================================
|
|
149
153
|
{
|
|
150
154
|
const styleLayer = new styleClass(`${this.__id}_${sourceLayer}`,
|
|
151
|
-
this.vectorSourceId(sourceLayer))
|
|
152
|
-
this.addLayer(styleLayer, this.__layerOptions)
|
|
155
|
+
this.vectorSourceId(sourceLayer))
|
|
156
|
+
this.addLayer(styleLayer, this.__layerOptions)
|
|
157
|
+
if (path2dLayer) {
|
|
158
|
+
this.#pathLayers.push(styleLayer)
|
|
159
|
+
}
|
|
153
160
|
}
|
|
154
161
|
|
|
155
162
|
__addPathwayStyleLayers()
|
|
156
163
|
//=======================
|
|
157
164
|
{
|
|
158
|
-
const pathwaysVectorSource = this.vectorSourceId(PATHWAYS_LAYER)
|
|
165
|
+
const pathwaysVectorSource = this.vectorSourceId(PATHWAYS_LAYER)
|
|
159
166
|
if (this.__map.getSource('vector-tiles')
|
|
160
167
|
.vectorLayerIds
|
|
161
168
|
.includes(pathwaysVectorSource)) {
|
|
162
|
-
this.__addStyleLayer(style.AnnotatedPathLayer, PATHWAYS_LAYER)
|
|
169
|
+
this.__addStyleLayer(style.AnnotatedPathLayer, PATHWAYS_LAYER, true)
|
|
163
170
|
|
|
164
|
-
this.__addStyleLayer(style.CentrelineEdgeLayer, PATHWAYS_LAYER)
|
|
165
|
-
this.__addStyleLayer(style.CentrelineTrackLayer, PATHWAYS_LAYER)
|
|
171
|
+
this.__addStyleLayer(style.CentrelineEdgeLayer, PATHWAYS_LAYER)
|
|
172
|
+
this.__addStyleLayer(style.CentrelineTrackLayer, PATHWAYS_LAYER)
|
|
166
173
|
|
|
167
|
-
this.__addStyleLayer(style.PathLineLayer, PATHWAYS_LAYER)
|
|
168
|
-
this.__addStyleLayer(style.PathDashlineLayer, PATHWAYS_LAYER)
|
|
174
|
+
this.__addStyleLayer(style.PathLineLayer, PATHWAYS_LAYER, true)
|
|
175
|
+
this.__addStyleLayer(style.PathDashlineLayer, PATHWAYS_LAYER, true)
|
|
169
176
|
|
|
170
|
-
this.__addStyleLayer(style.NervePolygonBorder, PATHWAYS_LAYER)
|
|
171
|
-
this.__addStyleLayer(style.NervePolygonFill, PATHWAYS_LAYER)
|
|
172
|
-
this.__addStyleLayer(style.FeatureNerveLayer, PATHWAYS_LAYER)
|
|
177
|
+
this.__addStyleLayer(style.NervePolygonBorder, PATHWAYS_LAYER, true)
|
|
178
|
+
this.__addStyleLayer(style.NervePolygonFill, PATHWAYS_LAYER, true)
|
|
179
|
+
this.__addStyleLayer(style.FeatureNerveLayer, PATHWAYS_LAYER, true)
|
|
173
180
|
|
|
174
|
-
this.__addStyleLayer(style.PathHighlightLayer, PATHWAYS_LAYER)
|
|
175
|
-
this.__addStyleLayer(style.PathDashHighlightLayer, PATHWAYS_LAYER)
|
|
181
|
+
this.__addStyleLayer(style.PathHighlightLayer, PATHWAYS_LAYER, true)
|
|
182
|
+
this.__addStyleLayer(style.PathDashHighlightLayer, PATHWAYS_LAYER, true)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
enablePaths2dLayer(visible)
|
|
187
|
+
//=========================
|
|
188
|
+
{
|
|
189
|
+
for (const layer of this.#pathLayers) {
|
|
190
|
+
this.map.setLayoutProperty(layer.id, 'visibility', visible ? 'visible' : 'none')
|
|
176
191
|
}
|
|
177
192
|
}
|
|
178
193
|
|
|
@@ -250,11 +265,14 @@ class MapRasterLayers extends MapStylingLayers
|
|
|
250
265
|
|
|
251
266
|
export class LayerManager
|
|
252
267
|
{
|
|
253
|
-
|
|
268
|
+
#featureLayers = new Map()
|
|
269
|
+
#paths3dLayer = null
|
|
270
|
+
#rasterLayer = null
|
|
271
|
+
|
|
272
|
+
constructor(flatmap, ui)
|
|
254
273
|
{
|
|
255
274
|
this.__flatmap = flatmap;
|
|
256
275
|
this.__map = flatmap.map;
|
|
257
|
-
this.__mapLayers = new Map;
|
|
258
276
|
this.__layerOptions = utils.setDefaults(flatmap.options.layerOptions, {
|
|
259
277
|
colour: true,
|
|
260
278
|
outline: true,
|
|
@@ -273,28 +291,37 @@ export class LayerManager
|
|
|
273
291
|
|
|
274
292
|
// Image layers are below all feature layers
|
|
275
293
|
const bodyLayer = flatmap.layers[0];
|
|
276
|
-
|
|
294
|
+
this.#rasterLayer = new MapRasterLayers(this.__flatmap,
|
|
277
295
|
this.__layerOptions,
|
|
278
296
|
bodyLayer.id); // body layer if not FC??
|
|
279
297
|
for (const layer of flatmap.layers) {
|
|
280
|
-
|
|
298
|
+
this.#rasterLayer.addLayer(layer);
|
|
281
299
|
}
|
|
282
|
-
this.__mapLayers.set(RASTER_LAYERS_ID, rasterLayers);
|
|
283
300
|
} else {
|
|
284
301
|
this.__layerOptions.activeRasterLayer = false;
|
|
285
302
|
}
|
|
286
303
|
for (const layer of flatmap.layers) {
|
|
287
|
-
this.
|
|
288
|
-
|
|
289
|
-
|
|
304
|
+
this.#featureLayers.set(layer.id, new MapFeatureLayers(this.__flatmap,
|
|
305
|
+
layer,
|
|
306
|
+
this.__layerOptions));
|
|
290
307
|
}
|
|
308
|
+
|
|
309
|
+
// Support 3D path view
|
|
310
|
+
this.#paths3dLayer = new Paths3DLayer(flatmap, ui)
|
|
291
311
|
}
|
|
292
312
|
|
|
293
313
|
get layers()
|
|
294
314
|
//==========
|
|
295
315
|
{
|
|
296
|
-
const layers = []
|
|
297
|
-
|
|
316
|
+
const layers = []
|
|
317
|
+
if (this.#rasterLayer) {
|
|
318
|
+
layers.push({
|
|
319
|
+
id: this.#rasterLayer.id,
|
|
320
|
+
description: this.#rasterLayer.description,
|
|
321
|
+
enabled: this.#rasterLayer.active
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
for (const mapLayer of this.#featureLayers.values()) {
|
|
298
325
|
layers.push({
|
|
299
326
|
id: mapLayer.id,
|
|
300
327
|
description: mapLayer.description,
|
|
@@ -313,26 +340,63 @@ export class LayerManager
|
|
|
313
340
|
activate(layerId, enable=true)
|
|
314
341
|
//============================
|
|
315
342
|
{
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
this.
|
|
321
|
-
|
|
322
|
-
if (mapLayer.id !== RASTER_LAYERS_ID) {
|
|
323
|
-
mapLayer.setPaint(this.__layerOptions);
|
|
324
|
-
}
|
|
343
|
+
if (layerId === RASTER_LAYERS_ID) {
|
|
344
|
+
if (this.#rasterLayer) {
|
|
345
|
+
this.#rasterLayer.activate(enable)
|
|
346
|
+
this.__layerOptions.activeRasterLayer = enable
|
|
347
|
+
for (const mapLayer of this.#featureLayers.values()) {
|
|
348
|
+
mapLayer.setPaint(this.__layerOptions)
|
|
325
349
|
}
|
|
326
350
|
}
|
|
351
|
+
} else {
|
|
352
|
+
const layer = this.#featureLayers.get(layerId)
|
|
353
|
+
if (layer) {
|
|
354
|
+
layer.activate(enable)
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
featuresAtPoint(point)
|
|
360
|
+
//====================
|
|
361
|
+
{
|
|
362
|
+
let features = []
|
|
363
|
+
if (this.#paths3dLayer) {
|
|
364
|
+
features = this.#paths3dLayer.queryFeaturesAtPoint(point)
|
|
365
|
+
}
|
|
366
|
+
if (features.length === 0) {
|
|
367
|
+
features = this.__map.queryRenderedFeatures(point)
|
|
368
|
+
}
|
|
369
|
+
return features
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
removeFeatureState(feature, key)
|
|
373
|
+
//==============================
|
|
374
|
+
{
|
|
375
|
+
if (this.#paths3dLayer) {
|
|
376
|
+
this.#paths3dLayer.removeFeatureState(feature.id, key)
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
setFeatureState(feature, state)
|
|
381
|
+
//=============================
|
|
382
|
+
{
|
|
383
|
+
if (this.#paths3dLayer) {
|
|
384
|
+
this.#paths3dLayer.setFeatureState(feature.id, state)
|
|
327
385
|
}
|
|
328
386
|
}
|
|
329
387
|
|
|
330
388
|
setPaint(options={})
|
|
331
389
|
//==================
|
|
332
390
|
{
|
|
333
|
-
this.__layerOptions = utils.setDefaults(options, this.__layerOptions)
|
|
334
|
-
|
|
335
|
-
|
|
391
|
+
this.__layerOptions = utils.setDefaults(options, this.__layerOptions)
|
|
392
|
+
if (this.#rasterLayer) {
|
|
393
|
+
this.#rasterLayer.setPaint(this.__layerOptions)
|
|
394
|
+
}
|
|
395
|
+
for (const mapLayer of this.#featureLayers.values()) {
|
|
396
|
+
mapLayer.setPaint(this.__layerOptions)
|
|
397
|
+
}
|
|
398
|
+
if (this.#paths3dLayer) {
|
|
399
|
+
this.#paths3dLayer.setPaint(options)
|
|
336
400
|
}
|
|
337
401
|
}
|
|
338
402
|
|
|
@@ -340,9 +404,32 @@ export class LayerManager
|
|
|
340
404
|
//===================
|
|
341
405
|
{
|
|
342
406
|
this.__layerOptions = utils.setDefaults(options, this.__layerOptions);
|
|
343
|
-
for (const mapLayer of this.
|
|
407
|
+
for (const mapLayer of this.#featureLayers.values()) {
|
|
344
408
|
mapLayer.setFilter(this.__layerOptions);
|
|
345
409
|
}
|
|
410
|
+
if (this.#paths3dLayer) {
|
|
411
|
+
const sckanState = options.sckan || 'valid'
|
|
412
|
+
const sckanFilter = (sckanState == 'none') ? {NOT: {HAS: 'sckan'}} :
|
|
413
|
+
(sckanState == 'valid') ? {sckan: true} :
|
|
414
|
+
(sckanState == 'invalid') ? {NOT: {sckan: true}} :
|
|
415
|
+
true
|
|
416
|
+
const featureFilter = new PropertiesFilter(sckanFilter)
|
|
417
|
+
if ('taxons' in options) {
|
|
418
|
+
featureFilter.narrow({taxons: options.taxons})
|
|
419
|
+
}
|
|
420
|
+
this.#paths3dLayer.setFilter(featureFilter)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
set3dMode(enable=true)
|
|
425
|
+
//====================
|
|
426
|
+
{
|
|
427
|
+
if (this.#paths3dLayer) {
|
|
428
|
+
this.#paths3dLayer.enable(enable)
|
|
429
|
+
for (const mapLayer of this.#featureLayers.values()) {
|
|
430
|
+
mapLayer.enablePaths2dLayer(!enable)
|
|
431
|
+
}
|
|
432
|
+
}
|
|
346
433
|
}
|
|
347
434
|
|
|
348
435
|
enableSckanPaths(sckanState, enable=true)
|