@abi-software/flatmap-viewer 2.3.1-b.1 → 2.3.2-b.1
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 +1 -1
- package/package.json +1 -1
- package/src/annotation.js +14 -9
- package/src/controls/controls.js +133 -229
- package/src/controls/info.js +2 -0
- package/src/controls/paths.js +143 -0
- package/src/controls/systems.js +18 -9
- package/src/flatmap-viewer.js +14 -11
- package/src/interactions.js +110 -91
- package/src/layers.js +2 -2
- package/src/pathways.js +108 -91
- package/src/styling.js +62 -43
- package/src/systems.js +53 -36
- package/src/utils.js +18 -0
package/src/pathways.js
CHANGED
|
@@ -22,6 +22,8 @@ limitations under the License.
|
|
|
22
22
|
|
|
23
23
|
//==============================================================================
|
|
24
24
|
|
|
25
|
+
import { reverseMap } from './utils';
|
|
26
|
+
|
|
25
27
|
export const PATHWAYS_LAYER = 'pathways';
|
|
26
28
|
|
|
27
29
|
//==============================================================================
|
|
@@ -48,28 +50,11 @@ export const PATH_STYLE_RULES =
|
|
|
48
50
|
|
|
49
51
|
//==============================================================================
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
//==========================
|
|
53
|
+
export class PathManager
|
|
53
54
|
{
|
|
54
|
-
|
|
55
|
-
for (const [key, values] of Object.entries(mapping)) {
|
|
56
|
-
for (const value of values) {
|
|
57
|
-
if (value in reverse) {
|
|
58
|
-
reverse[value].add(key);
|
|
59
|
-
} else {
|
|
60
|
-
reverse[value] = new Set([key]);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return reverse;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
//==============================================================================
|
|
68
|
-
|
|
69
|
-
export class Pathways
|
|
70
|
-
{
|
|
71
|
-
constructor(flatmap)
|
|
55
|
+
constructor(flatmap, ui, enabled=true)
|
|
72
56
|
{
|
|
57
|
+
this.__ui = ui;
|
|
73
58
|
this.__connectivityModelPaths = {}; // modelId: [pathIds]
|
|
74
59
|
this.__pathToConnectivityModel = {};
|
|
75
60
|
if ('models' in flatmap.pathways) {
|
|
@@ -82,14 +67,19 @@ export class Pathways
|
|
|
82
67
|
}
|
|
83
68
|
this.__pathModelPaths = {}; // pathModelId: [pathIds]
|
|
84
69
|
this.__pathToPathModel = {};
|
|
70
|
+
|
|
71
|
+
this.__paths = {};
|
|
72
|
+
const pathLines = {}; // pathId: [lineIds]
|
|
73
|
+
const pathNerves = {}; // pathId: [nerveIds]
|
|
85
74
|
if ('paths' in flatmap.pathways) {
|
|
86
|
-
this._pathLines = {}; // pathId: [lineIds]
|
|
87
|
-
this._pathNerves = {}; // pathId: [nerveIds]
|
|
88
|
-
this._pathNodes = {}; // pathId: [nodeIds]
|
|
89
75
|
for (const [pathId, path] of Object.entries(flatmap.pathways.paths)) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this.
|
|
76
|
+
pathLines[pathId] = path.lines;
|
|
77
|
+
pathNerves[pathId] = path.nerves;
|
|
78
|
+
this.__paths[pathId] = path;
|
|
79
|
+
for (const lineId of path.lines) {
|
|
80
|
+
this.__ui.enableFeature(lineId, enabled, true);
|
|
81
|
+
}
|
|
82
|
+
this.__paths[pathId].systemCount = 0;
|
|
93
83
|
if ('models' in path) {
|
|
94
84
|
const modelId = path['models'];
|
|
95
85
|
if (!(modelId in this.__pathModelPaths)) {
|
|
@@ -99,30 +89,12 @@ export class Pathways
|
|
|
99
89
|
this.__pathToPathModel[pathId] = modelId;
|
|
100
90
|
}
|
|
101
91
|
}
|
|
102
|
-
} else {
|
|
103
|
-
// To be deprecated...
|
|
104
|
-
this._pathLines = flatmap.pathways['path-lines']; // pathId: [lineIds]
|
|
105
|
-
this._pathNerves = flatmap.pathways['path-nerves']; // pathId: [nerveIds]
|
|
106
|
-
if ('path-nodes' in flatmap.pathways) {
|
|
107
|
-
this._pathNodes = flatmap.pathways['path-nodes']; // pathId: [nodeIds]
|
|
108
|
-
} else {
|
|
109
|
-
this._pathNodes = {};
|
|
110
|
-
for (const path of Object.keys(this._pathLines)) {
|
|
111
|
-
this._pathNodes[path] = [];
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
92
|
}
|
|
115
|
-
this.
|
|
116
|
-
this.
|
|
93
|
+
this.__pathsByLine = reverseMap(pathLines); // lineId: [pathIds]
|
|
94
|
+
this.__pathsByNerve = reverseMap(pathNerves); // nerveId: [pathIds]
|
|
117
95
|
|
|
118
96
|
const nodePaths = flatmap.pathways['node-paths'];
|
|
119
|
-
|
|
120
|
-
this._nodePaths = nodePaths; // nodeId: [pathIds]
|
|
121
|
-
} else { // Original format, deprecated
|
|
122
|
-
this._nodePaths = nodePaths['start-paths'];
|
|
123
|
-
this.extendNodePaths_(nodePaths['through-paths']);
|
|
124
|
-
this.extendNodePaths_(nodePaths['end-paths']);
|
|
125
|
-
}
|
|
97
|
+
this._nodePaths = nodePaths; // nodeId: [pathIds]
|
|
126
98
|
const featureIds = new Set();
|
|
127
99
|
for (const paths of Object.values(this._nodePaths)) {
|
|
128
100
|
this.addPathsToFeatureSet_(paths, featureIds);
|
|
@@ -130,20 +102,28 @@ export class Pathways
|
|
|
130
102
|
this._allFeatureIds = featureIds;
|
|
131
103
|
|
|
132
104
|
// Construct a list of path types we know about
|
|
133
|
-
const pathTypes =
|
|
134
|
-
|
|
135
|
-
|
|
105
|
+
const pathTypes = {};
|
|
106
|
+
this.__pathtypeEnabled = {};
|
|
107
|
+
for (const pathTypeDefn of PATH_TYPES) {
|
|
108
|
+
pathTypes[pathTypeDefn.type] = pathTypeDefn;
|
|
109
|
+
this.__pathtypeEnabled[pathTypeDefn.type] = !('enabled' in pathTypeDefn) || pathTypeDefn.enabled;
|
|
136
110
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
this.
|
|
111
|
+
|
|
112
|
+
// Set path types, mapping unknown path types to ``other``
|
|
113
|
+
this.__pathsByType = {};
|
|
114
|
+
this.__pathsByType['other'] = [];
|
|
140
115
|
for (const [pathType, paths] of Object.entries(flatmap.pathways['type-paths'])) {
|
|
141
|
-
if (
|
|
142
|
-
this.
|
|
116
|
+
if (pathType in pathTypes) {
|
|
117
|
+
this.__pathsByType[pathType] = paths;
|
|
118
|
+
const pathDefn = pathTypes[pathType];
|
|
143
119
|
} else {
|
|
144
|
-
this.
|
|
120
|
+
this.__pathsByType['other'].push(...paths);
|
|
121
|
+
this.__pathtypeEnabled[pathType] = false;
|
|
145
122
|
}
|
|
146
123
|
}
|
|
124
|
+
// Assign types to individual paths
|
|
125
|
+
this.__assignPathTypes();
|
|
126
|
+
|
|
147
127
|
// Nerve centrelines are a special case with their own controls
|
|
148
128
|
this.__haveCentrelines = false;
|
|
149
129
|
}
|
|
@@ -154,44 +134,44 @@ export class Pathways
|
|
|
154
134
|
return this.__haveCentrelines;
|
|
155
135
|
}
|
|
156
136
|
|
|
137
|
+
__assignPathTypes()
|
|
138
|
+
//=================
|
|
139
|
+
{
|
|
140
|
+
for (const [pathType, paths] of Object.entries(this.__pathsByType)) {
|
|
141
|
+
for (const pathId of paths) {
|
|
142
|
+
this.__paths[pathId].pathType = pathType;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
157
147
|
pathTypes()
|
|
158
148
|
//=========
|
|
159
149
|
{
|
|
160
150
|
const pathTypes = [];
|
|
161
|
-
for (const
|
|
162
|
-
if (
|
|
163
|
-
&& this.
|
|
164
|
-
if (
|
|
151
|
+
for (const pathTypeDefn of PATH_TYPES) {
|
|
152
|
+
if (pathTypeDefn.type in this.__pathsByType
|
|
153
|
+
&& this.__pathsByType[pathTypeDefn.type].length > 0) {
|
|
154
|
+
if (pathTypeDefn.type === 'centreline') {
|
|
165
155
|
this.__haveCentrelines = true;
|
|
166
156
|
} else {
|
|
167
|
-
pathTypes.push(
|
|
157
|
+
pathTypes.push({
|
|
158
|
+
...pathTypeDefn,
|
|
159
|
+
enabled: this.__pathtypeEnabled[pathTypeDefn.type]
|
|
160
|
+
});
|
|
168
161
|
}
|
|
169
162
|
}
|
|
170
163
|
}
|
|
171
164
|
return pathTypes;
|
|
172
165
|
}
|
|
173
166
|
|
|
174
|
-
addPathsToFeatureSet_(
|
|
167
|
+
addPathsToFeatureSet_(pathIds, featureSet)
|
|
175
168
|
//======================================
|
|
176
169
|
{
|
|
177
|
-
for (const
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
extendNodePaths_(nodePaths)
|
|
187
|
-
//=========================
|
|
188
|
-
{
|
|
189
|
-
for (const [key, values] of Object.entries(nodePaths)) {
|
|
190
|
-
if (key in this._nodePaths) {
|
|
191
|
-
this._nodePaths[key].push(...values);
|
|
192
|
-
} else {
|
|
193
|
-
this._nodePaths[key] = values;
|
|
194
|
-
}
|
|
170
|
+
for (const pathId of pathIds) {
|
|
171
|
+
const path = this.__paths[pathId];
|
|
172
|
+
path.lines.forEach(lineId => featureSet.add(lineId));
|
|
173
|
+
path.nerves.forEach(nerveId => featureSet.add(nerveId));
|
|
174
|
+
path.nodes.forEach(nodeId => featureSet.add(nodeId));
|
|
195
175
|
}
|
|
196
176
|
}
|
|
197
177
|
|
|
@@ -206,8 +186,8 @@ export class Pathways
|
|
|
206
186
|
{
|
|
207
187
|
const featureIds = new Set();
|
|
208
188
|
for (const lineId of lineIds) {
|
|
209
|
-
if (lineId in this.
|
|
210
|
-
this.addPathsToFeatureSet_(this.
|
|
189
|
+
if (lineId in this.__pathsByLine) {
|
|
190
|
+
this.addPathsToFeatureSet_(this.__pathsByLine[lineId], featureIds);
|
|
211
191
|
}
|
|
212
192
|
}
|
|
213
193
|
return featureIds;
|
|
@@ -217,8 +197,8 @@ export class Pathways
|
|
|
217
197
|
//======================
|
|
218
198
|
{
|
|
219
199
|
const featureIds = new Set();
|
|
220
|
-
if (nerveId in this.
|
|
221
|
-
this.addPathsToFeatureSet_(this.
|
|
200
|
+
if (nerveId in this.__pathsByNerve) {
|
|
201
|
+
this.addPathsToFeatureSet_(this.__pathsByNerve[nerveId], featureIds);
|
|
222
202
|
}
|
|
223
203
|
return featureIds;
|
|
224
204
|
}
|
|
@@ -237,8 +217,8 @@ export class Pathways
|
|
|
237
217
|
//=====================
|
|
238
218
|
{
|
|
239
219
|
const properties = Object.assign({}, feature.properties);
|
|
240
|
-
if (feature.id in this.
|
|
241
|
-
for (const pathId of this.
|
|
220
|
+
if (feature.id in this.__pathsByLine) {
|
|
221
|
+
for (const pathId of this.__pathsByLine[feature.id]) {
|
|
242
222
|
// There should only be a single path for a line
|
|
243
223
|
if (pathId in this.__pathToConnectivityModel) {
|
|
244
224
|
properties['connectivity'] = this.__pathToConnectivityModel[pathId];
|
|
@@ -249,7 +229,7 @@ export class Pathways
|
|
|
249
229
|
}
|
|
250
230
|
/*
|
|
251
231
|
if (!('connectivity' in properties)) {
|
|
252
|
-
for (const pathId of this.
|
|
232
|
+
for (const pathId of this.__pathsByNerve[feature.id]) {
|
|
253
233
|
if (pathId in this.__pathToConnectivityModel) {
|
|
254
234
|
properties['connectivity'] = this.__pathToConnectivityModel[pathId];
|
|
255
235
|
break;
|
|
@@ -297,16 +277,53 @@ export class Pathways
|
|
|
297
277
|
return featureIds;
|
|
298
278
|
}
|
|
299
279
|
|
|
300
|
-
|
|
301
|
-
|
|
280
|
+
__typeFeatureIds(pathType)
|
|
281
|
+
//========================
|
|
302
282
|
{
|
|
303
283
|
const featureIds = new Set();
|
|
304
|
-
if (pathType in this.
|
|
305
|
-
this.addPathsToFeatureSet_(this.
|
|
284
|
+
if (pathType in this.__pathsByType) {
|
|
285
|
+
this.addPathsToFeatureSet_(this.__pathsByType[pathType], featureIds);
|
|
306
286
|
}
|
|
307
287
|
return featureIds;
|
|
308
288
|
}
|
|
309
289
|
|
|
290
|
+
enablePathsBySystem(system, enable, force=false)
|
|
291
|
+
//==============================================
|
|
292
|
+
{
|
|
293
|
+
for (const pathId of system.pathIds) {
|
|
294
|
+
const path = this.__paths[pathId];
|
|
295
|
+
if (this.__pathtypeEnabled[path.pathType]
|
|
296
|
+
&& (force
|
|
297
|
+
|| enable && path.systemCount === 0
|
|
298
|
+
|| !enable && path.systemCount == 1)) {
|
|
299
|
+
// and type(pathId) is enabled...
|
|
300
|
+
const featureIds = new Set();
|
|
301
|
+
this.addPathsToFeatureSet_([pathId], featureIds)
|
|
302
|
+
for (const featureId of featureIds) {
|
|
303
|
+
this.__ui.enableFeature(featureId, enable, force);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
path.systemCount += (enable ? 1 : -1);
|
|
307
|
+
if (path.systemCount < 0) {
|
|
308
|
+
path.systemCount = 0;
|
|
309
|
+
}
|
|
310
|
+
// TODO? Show connectors and parent components of these paths??
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
enablePathsByType(pathType, enable, force=false)
|
|
315
|
+
//==============================================
|
|
316
|
+
{
|
|
317
|
+
if (force
|
|
318
|
+
|| enable && !this.__pathtypeEnabled[pathType]
|
|
319
|
+
|| !enable && this.__pathtypeEnabled[pathType]) {
|
|
320
|
+
for (const featureId of this.__typeFeatureIds(pathType)) {
|
|
321
|
+
this.__ui.enableFeature(featureId, enable, force);
|
|
322
|
+
}
|
|
323
|
+
this.__pathtypeEnabled[pathType] = enable;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
310
327
|
nodePathModels(nodeId)
|
|
311
328
|
//====================
|
|
312
329
|
{
|
package/src/styling.js
CHANGED
|
@@ -45,6 +45,17 @@ const NERVE_SELECTED = 'red';
|
|
|
45
45
|
|
|
46
46
|
//==============================================================================
|
|
47
47
|
|
|
48
|
+
const STROKE_INTERPOLATION = [
|
|
49
|
+
'interpolate',
|
|
50
|
+
['exponential', 2],
|
|
51
|
+
['zoom'],
|
|
52
|
+
2, ["*", ['var', 'width'], ["^", 2, -0.5]],
|
|
53
|
+
7, ["*", ['var', 'width'], ["^", 2, 2.5]],
|
|
54
|
+
9, ["*", ['var', 'width'], ["^", 2, 4.0]]
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
//==============================================================================
|
|
58
|
+
|
|
48
59
|
class VectorStyleLayer
|
|
49
60
|
{
|
|
50
61
|
constructor(id, suffix, sourceLayer)
|
|
@@ -272,8 +283,7 @@ export class FeatureLineLayer extends VectorStyleLayer
|
|
|
272
283
|
constructor(id, sourceLayer, options={})
|
|
273
284
|
{
|
|
274
285
|
const dashed = ('dashed' in options && options.dashed);
|
|
275
|
-
|
|
276
|
-
super(id, `feature-${filterType}`, sourceLayer);
|
|
286
|
+
super(id, `feature-${dashed ? 'line-dash' : 'line'}`, sourceLayer);
|
|
277
287
|
this.__dashed = dashed;
|
|
278
288
|
}
|
|
279
289
|
|
|
@@ -323,14 +333,8 @@ export class FeatureLineLayer extends VectorStyleLayer
|
|
|
323
333
|
['boolean', ['feature-state', 'selected'], false], 1.2,
|
|
324
334
|
['boolean', ['feature-state', 'active'], false], 1.2,
|
|
325
335
|
options.authoring ? 0.7 : 0.5
|
|
326
|
-
],
|
|
327
|
-
|
|
328
|
-
['exponential', 2],
|
|
329
|
-
['zoom'],
|
|
330
|
-
2, ["*", ['var', 'width'], ["^", 2, -0.5]],
|
|
331
|
-
7, ["*", ['var', 'width'], ["^", 2, 2.5]],
|
|
332
|
-
9, ["*", ['var', 'width'], ["^", 2, 4.0]]
|
|
333
|
-
]
|
|
336
|
+
],
|
|
337
|
+
STROKE_INTERPOLATION
|
|
334
338
|
]
|
|
335
339
|
// Need to vary width based on zoom??
|
|
336
340
|
// Or opacity??
|
|
@@ -433,13 +437,7 @@ export class AnnotatedPathLayer extends VectorStyleLayer
|
|
|
433
437
|
['*', 1.2, ['case', ['has', 'stroke-width'], ['get', 'stroke-width'], 1.0]],
|
|
434
438
|
0.0
|
|
435
439
|
],
|
|
436
|
-
|
|
437
|
-
['exponential', 2],
|
|
438
|
-
['zoom'],
|
|
439
|
-
2, ["*", ['var', 'width'], ["^", 2, -0.5]],
|
|
440
|
-
7, ["*", ['var', 'width'], ["^", 2, 2.5]],
|
|
441
|
-
9, ["*", ['var', 'width'], ["^", 2, 4.0]]
|
|
442
|
-
]
|
|
440
|
+
STROKE_INTERPOLATION
|
|
443
441
|
]
|
|
444
442
|
};
|
|
445
443
|
return super.changedPaintStyle(paintStyle, changes);
|
|
@@ -467,9 +465,10 @@ export class PathLineLayer extends VectorStyleLayer
|
|
|
467
465
|
constructor(id, sourceLayer, options={})
|
|
468
466
|
{
|
|
469
467
|
const dashed = ('dashed' in options && options.dashed);
|
|
470
|
-
const
|
|
471
|
-
super(id, `path-${
|
|
468
|
+
const highlight = ('highlight' in options && options.highlight);
|
|
469
|
+
super(id, `path${highlight ? '-highlight' : ''}-${dashed ? 'line-dash' : 'line'}`, sourceLayer);
|
|
472
470
|
this.__dashed = dashed;
|
|
471
|
+
this.__highlight = highlight;
|
|
473
472
|
}
|
|
474
473
|
|
|
475
474
|
makeFilter(options={})
|
|
@@ -509,36 +508,45 @@ export class PathLineLayer extends VectorStyleLayer
|
|
|
509
508
|
...PATH_STYLE_RULES,
|
|
510
509
|
'#888'
|
|
511
510
|
],
|
|
512
|
-
'line-opacity': [
|
|
511
|
+
'line-opacity': this.__highlight ? [
|
|
512
|
+
'case',
|
|
513
|
+
['boolean', ['feature-state', 'hidden'], false], 0.0,
|
|
514
|
+
['boolean', ['get', 'invisible'], false], 0.0,
|
|
515
|
+
['boolean', ['feature-state', 'selected'], false], 1.0,
|
|
516
|
+
['boolean', ['feature-state', 'active'], false], 1.0,
|
|
517
|
+
0.0
|
|
518
|
+
] : [
|
|
513
519
|
'case',
|
|
514
520
|
['boolean', ['feature-state', 'hidden'], false], 0.01,
|
|
515
521
|
['==', ['get', 'type'], 'bezier'], 1.0,
|
|
516
522
|
['==', ['get', 'kind'], 'error'], 1.0,
|
|
517
523
|
['boolean', ['get', 'invisible'], false], 0.001,
|
|
518
|
-
['boolean', ['feature-state', 'selected'], false],
|
|
519
|
-
['boolean', ['feature-state', 'active'], false],
|
|
524
|
+
['boolean', ['feature-state', 'selected'], false], 0.0,
|
|
525
|
+
['boolean', ['feature-state', 'active'], false], 0.0,
|
|
520
526
|
dimmed ? 0.1 : 0.8
|
|
521
527
|
],
|
|
522
528
|
'line-width': [
|
|
523
529
|
'let',
|
|
524
|
-
'width', [
|
|
525
|
-
|
|
530
|
+
'width', [
|
|
531
|
+
"*",
|
|
532
|
+
this.__highlight ? ['case',
|
|
533
|
+
['boolean', ['get', 'invisible'], false], 0.1,
|
|
534
|
+
['boolean', ['feature-state', 'selected'], false], 0.6,
|
|
535
|
+
['boolean', ['feature-state', 'active'], false], 0.9,
|
|
536
|
+
0.0
|
|
537
|
+
] : [
|
|
538
|
+
'case',
|
|
526
539
|
['==', ['get', 'type'], 'bezier'], 0.1,
|
|
527
540
|
['==', ['get', 'kind'], 'error'], 1,
|
|
528
541
|
['==', ['get', 'kind'], 'unknown'], 1,
|
|
529
542
|
['boolean', ['get', 'invisible'], false], 0.1,
|
|
530
|
-
['boolean', ['feature-state', 'selected'], false],
|
|
531
|
-
['boolean', ['feature-state', 'active'], false], 0.
|
|
532
|
-
|
|
543
|
+
['boolean', ['feature-state', 'selected'], false], 0.0,
|
|
544
|
+
['boolean', ['feature-state', 'active'], false], 0.0,
|
|
545
|
+
0.6
|
|
533
546
|
],
|
|
534
|
-
['case', ['has', 'stroke-width'], ['get', 'stroke-width'], 1.0]
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
['zoom'],
|
|
538
|
-
2, ["*", ['var', 'width'], ["^", 2, -0.5]],
|
|
539
|
-
7, ["*", ['var', 'width'], ["^", 2, 2.5]],
|
|
540
|
-
9, ["*", ['var', 'width'], ["^", 2, 4.0]]
|
|
541
|
-
]
|
|
547
|
+
['case', ['has', 'stroke-width'], ['get', 'stroke-width'], 1.0]
|
|
548
|
+
],
|
|
549
|
+
STROKE_INTERPOLATION
|
|
542
550
|
]
|
|
543
551
|
};
|
|
544
552
|
if (this.__dashed) {
|
|
@@ -573,6 +581,24 @@ export class PathDashlineLayer extends PathLineLayer
|
|
|
573
581
|
|
|
574
582
|
//==============================================================================
|
|
575
583
|
|
|
584
|
+
export class PathHighlightLayer extends PathLineLayer
|
|
585
|
+
{
|
|
586
|
+
constructor(id, sourceLayer)
|
|
587
|
+
{
|
|
588
|
+
super(id, sourceLayer, {highlight: true});
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
export class PathDashHighlightLayer extends PathLineLayer
|
|
593
|
+
{
|
|
594
|
+
constructor(id, sourceLayer)
|
|
595
|
+
{
|
|
596
|
+
super(id, sourceLayer, {dashed: true, highlight: true});
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
//==============================================================================
|
|
601
|
+
|
|
576
602
|
class CentrelineLayer extends VectorStyleLayer
|
|
577
603
|
{
|
|
578
604
|
constructor(id, type, sourceLayer)
|
|
@@ -602,14 +628,7 @@ class CentrelineLayer extends VectorStyleLayer
|
|
|
602
628
|
'let',
|
|
603
629
|
'width',
|
|
604
630
|
(this.__type == 'edge') ? 1.6 : 1.2,
|
|
605
|
-
|
|
606
|
-
'interpolate',
|
|
607
|
-
['exponential', 2],
|
|
608
|
-
['zoom'],
|
|
609
|
-
2, ["*", ['var', 'width'], ["^", 2, -0.5]],
|
|
610
|
-
7, ["*", ['var', 'width'], ["^", 2, 2.5]],
|
|
611
|
-
9, ["*", ['var', 'width'], ["^", 2, 4.0]]
|
|
612
|
-
]
|
|
631
|
+
STROKE_INTERPOLATION
|
|
613
632
|
]
|
|
614
633
|
// Need to vary width based on zoom??
|
|
615
634
|
// Or opacity??
|
package/src/systems.js
CHANGED
|
@@ -21,46 +21,50 @@ limitations under the License.
|
|
|
21
21
|
|
|
22
22
|
export class SystemsManager
|
|
23
23
|
{
|
|
24
|
-
constructor(flatmap, ui, enabled=
|
|
24
|
+
constructor(flatmap, ui, enabled=false)
|
|
25
25
|
{
|
|
26
26
|
this.__ui = ui;
|
|
27
27
|
this.__systems = new Map();
|
|
28
28
|
this.__enabledChildren = new Map();
|
|
29
29
|
for (const [id, ann] of flatmap.annotations) {
|
|
30
30
|
if (ann['fc-class'] === 'fc-class:System') {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const systemId = ann.name.replaceAll(' ', '_');
|
|
32
|
+
if (this.__systems.has(systemId)) {
|
|
33
|
+
this.__systems.get(systemId).featureIds.push(ann.featureId)
|
|
33
34
|
} else {
|
|
34
|
-
this.__systems.set(
|
|
35
|
-
|
|
35
|
+
this.__systems.set(systemId, {
|
|
36
|
+
name: ann.name,
|
|
36
37
|
colour: ann.colour,
|
|
37
38
|
featureIds: [ ann.featureId ],
|
|
38
|
-
enabled:
|
|
39
|
+
enabled: false,
|
|
39
40
|
pathIds: ('path-ids' in ann) ? ann['path-ids'] : []
|
|
40
41
|
});
|
|
42
|
+
this.__ui.enableFeature(ann.featureId, false, true);
|
|
41
43
|
}
|
|
42
44
|
for (const childId of ann['children']) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
? this.__enabledChildren.get(childId)
|
|
46
|
-
: 0;
|
|
47
|
-
this.__enabledChildren.set(childId, enabledCount + 1);
|
|
48
|
-
} else {
|
|
49
|
-
this.__enabledChildren.set(childId, 0);
|
|
50
|
-
}
|
|
45
|
+
this.__enabledChildren.set(childId, 0);
|
|
46
|
+
this.__ui.enableFeatureWithChildren(childId, false, true);
|
|
51
47
|
}
|
|
52
48
|
}
|
|
53
49
|
}
|
|
50
|
+
for (const system of this.__systems.values()) {
|
|
51
|
+
if (enabled) {
|
|
52
|
+
this.__enableSystem(system, true);
|
|
53
|
+
} else {
|
|
54
|
+
// Disable all paths associated with the disabled system
|
|
55
|
+
this.__ui.enablePathsBySystem(system, false, true);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
get systems()
|
|
57
61
|
//===========
|
|
58
62
|
{
|
|
59
63
|
const systems = [];
|
|
60
|
-
for (const [
|
|
64
|
+
for (const [systemId, system] of this.__systems.entries()) {
|
|
61
65
|
systems.push({
|
|
62
|
-
|
|
63
|
-
|
|
66
|
+
id: systemId,
|
|
67
|
+
name: system.name,
|
|
64
68
|
colour: system.colour,
|
|
65
69
|
enabled: system.enabled
|
|
66
70
|
});
|
|
@@ -68,31 +72,44 @@ export class SystemsManager
|
|
|
68
72
|
return systems;
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
enable(
|
|
72
|
-
|
|
75
|
+
enable(systemId, enable=true)
|
|
76
|
+
//===========================
|
|
73
77
|
{
|
|
74
|
-
const system = this.__systems.get(
|
|
78
|
+
const system = this.__systems.get(systemId);
|
|
75
79
|
if (system !== undefined && enable !== system.enabled) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
this.__enableSystem(system, enable);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
__enableSystem(system, enable=true)
|
|
85
|
+
//=================================
|
|
86
|
+
{
|
|
87
|
+
for (const featureId of system.featureIds) {
|
|
88
|
+
const feature = this.__ui.mapFeature(featureId);
|
|
89
|
+
if (feature !== undefined) {
|
|
90
|
+
this.__ui.enableMapFeature(feature, enable);
|
|
91
|
+
for (const childFeatureId of feature.children) {
|
|
92
|
+
const enabledCount = this.__enabledChildren.get(childFeatureId);
|
|
93
|
+
if (enable && enabledCount === 0 || !enable && enabledCount == 1) {
|
|
94
|
+
this.__ui.enableFeatureWithChildren(childFeatureId, enable);
|
|
86
95
|
}
|
|
96
|
+
this.__enabledChildren.set(childFeatureId, enabledCount + (enable ? 1 : -1));
|
|
87
97
|
}
|
|
88
98
|
}
|
|
89
|
-
system.enabled = enable;
|
|
90
|
-
|
|
91
|
-
// Enable/disable all paths associated with the system
|
|
92
|
-
for (const pathId of system.pathIds) {
|
|
93
|
-
this.__ui.enableFeature(this.__ui.mapFeature(pathId), enable);
|
|
94
|
-
}
|
|
95
99
|
}
|
|
100
|
+
|
|
101
|
+
// Enable/disable all paths associated with the system
|
|
102
|
+
this.__ui.enablePathsBySystem(system, enable);
|
|
103
|
+
|
|
104
|
+
// Save system state
|
|
105
|
+
system.enabled = enable;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
systemEnabled(systemId)
|
|
109
|
+
//=====================
|
|
110
|
+
{
|
|
111
|
+
const system = this.__systems.get(systemId);
|
|
112
|
+
return (system !== undefined && system.enabled);
|
|
96
113
|
}
|
|
97
114
|
}
|
|
98
115
|
|
package/src/utils.js
CHANGED
|
@@ -124,3 +124,21 @@ export function setDefaults(options, defaultOptions)
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
//==============================================================================
|
|
127
|
+
|
|
128
|
+
export function reverseMap(mapping)
|
|
129
|
+
//=================================
|
|
130
|
+
{
|
|
131
|
+
const reverse = {};
|
|
132
|
+
for (const [key, values] of Object.entries(mapping)) {
|
|
133
|
+
for (const value of values) {
|
|
134
|
+
if (value in reverse) {
|
|
135
|
+
reverse[value].add(key);
|
|
136
|
+
} else {
|
|
137
|
+
reverse[value] = new Set([key]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return reverse;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
//==============================================================================
|