@abi-software/flatmap-viewer 2.5.0-a.1 → 2.5.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 +3 -2
- package/src/controls/annotation.js +351 -0
- package/src/controls/controls.js +68 -0
- package/src/controls/minimap.js +3 -8
- package/src/controls/paths3d.js +90 -0
- package/src/flatmap-viewer.js +68 -35
- package/src/interactions.js +188 -138
- package/src/{layers.js → layers/index.js} +2 -2
- package/src/layers/paths3d.js +335 -0
- package/src/{styling.js → layers/styling.js} +2 -2
- package/src/main.js +1 -0
- package/src/pathways.js +62 -5
package/src/interactions.js
CHANGED
|
@@ -22,10 +22,6 @@ limitations under the License.
|
|
|
22
22
|
|
|
23
23
|
//==============================================================================
|
|
24
24
|
|
|
25
|
-
import {colord} from "colord";
|
|
26
|
-
|
|
27
|
-
import {MapboxOverlay as DeckOverlay} from '@deck.gl/mapbox';
|
|
28
|
-
import {ArcLayer} from '@deck.gl/layers';
|
|
29
25
|
import maplibregl from 'maplibre-gl';
|
|
30
26
|
|
|
31
27
|
import {default as turfArea} from '@turf/area';
|
|
@@ -38,15 +34,19 @@ import polylabel from 'polylabel';
|
|
|
38
34
|
//==============================================================================
|
|
39
35
|
|
|
40
36
|
import {LayerManager} from './layers';
|
|
41
|
-
import {
|
|
42
|
-
import {VECTOR_TILES_SOURCE} from './styling';
|
|
37
|
+
import {PATHWAYS_LAYER, PathManager} from './pathways';
|
|
38
|
+
import {VECTOR_TILES_SOURCE} from './layers/styling';
|
|
39
|
+
import {Paths3DLayer} from './layers/paths3d'
|
|
43
40
|
import {SystemsManager} from './systems';
|
|
44
41
|
|
|
45
42
|
import {displayedProperties, InfoControl} from './controls/info';
|
|
46
|
-
import {BackgroundControl, LayerControl, NerveControl,
|
|
43
|
+
import {AnnotatorControl, BackgroundControl, LayerControl, NerveControl,
|
|
47
44
|
SCKANControl} from './controls/controls';
|
|
45
|
+
import {AnnotationDrawControl, DRAW_ANNOTATION_LAYERS} from './controls/annotation'
|
|
48
46
|
import {PathControl} from './controls/paths';
|
|
47
|
+
import {Path3DControl} from './controls/paths3d'
|
|
49
48
|
import {SearchControl} from './controls/search';
|
|
49
|
+
import {MinimapControl} from './controls/minimap';
|
|
50
50
|
import {SystemsControl} from './controls/systems';
|
|
51
51
|
import {TaxonsControl} from './controls/taxons';
|
|
52
52
|
import {latex2Svg} from './mathjax';
|
|
@@ -112,31 +112,31 @@ function labelPosition(feature)
|
|
|
112
112
|
function getRenderedLabel(properties)
|
|
113
113
|
{
|
|
114
114
|
if (!('renderedLabel' in properties)) {
|
|
115
|
-
const label = ('label' in properties) ?
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
115
|
+
const label = ('label' in properties) ? properties.label
|
|
116
|
+
: ('user_label' in properties) ? properties.user_label
|
|
117
|
+
: ''
|
|
118
|
+
const uppercaseLabel = (label !== '') ? (label.substr(0, 1).toUpperCase()
|
|
119
|
+
+ label.substr(1)).replaceAll("\n", "<br/>")
|
|
120
|
+
: ''
|
|
121
|
+
properties.renderedLabel = uppercaseLabel.replaceAll(/`\$([^\$]*)\$`/g, math => latex2Svg(math.slice(2, -2)));
|
|
119
122
|
}
|
|
120
123
|
return properties.renderedLabel;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
// Should this be in `pathways.js` ??
|
|
124
|
-
function pathColourRGB(pathType, alpha=255)
|
|
125
|
-
{
|
|
126
|
-
const rgb = colord(pathColour(pathType)).toRgb();
|
|
127
|
-
return [rgb.r, rgb.g, rgb.b, alpha];
|
|
128
|
-
}
|
|
129
|
-
|
|
130
126
|
//==============================================================================
|
|
131
127
|
|
|
132
128
|
export class UserInteractions
|
|
133
129
|
{
|
|
130
|
+
#annotationDrawControl = null
|
|
131
|
+
#minimap = null
|
|
132
|
+
#paths3dLayer = null
|
|
133
|
+
|
|
134
134
|
constructor(flatmap)
|
|
135
135
|
{
|
|
136
136
|
this._flatmap = flatmap;
|
|
137
137
|
this._map = flatmap.map;
|
|
138
138
|
|
|
139
|
-
this._activeFeatures =
|
|
139
|
+
this._activeFeatures = new Set()
|
|
140
140
|
this._selectedFeatureIds = new Map();
|
|
141
141
|
this._currentPopup = null;
|
|
142
142
|
this._infoControl = null;
|
|
@@ -146,7 +146,6 @@ export class UserInteractions
|
|
|
146
146
|
this._modal = false;
|
|
147
147
|
|
|
148
148
|
// Default colour settings
|
|
149
|
-
|
|
150
149
|
this.__colourOptions = {colour: true, outline: true};
|
|
151
150
|
|
|
152
151
|
// Marker placement and interaction
|
|
@@ -194,6 +193,29 @@ export class UserInteractions
|
|
|
194
193
|
// All taxons of connectivity paths are enabled by default
|
|
195
194
|
this.__enabledConnectivityTaxons = new Set(this._flatmap.taxonIdentifiers);
|
|
196
195
|
|
|
196
|
+
// Add a minimap if option set
|
|
197
|
+
if (flatmap.options.minimap) {
|
|
198
|
+
this.#minimap = new MinimapControl(flatmap, flatmap.options.minimap);
|
|
199
|
+
this._map.addControl(this.#minimap);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Do we want a fullscreen control?
|
|
203
|
+
if (flatmap.options.fullscreenControl === true) {
|
|
204
|
+
this._map.addControl(new maplibregl.FullscreenControl(), 'top-right');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Add navigation controls if option set
|
|
208
|
+
if (flatmap.options.navigationControl) {
|
|
209
|
+
const value = flatmap.options.navigationControl;
|
|
210
|
+
const position = ((typeof value === 'string')
|
|
211
|
+
&& ['top-left', 'top-right', 'bottom-right', 'bottom-left'].includes(value))
|
|
212
|
+
? value : 'bottom-right';
|
|
213
|
+
this._map.addControl(new NavigationControl(flatmap), position);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Support 3D path view
|
|
217
|
+
this.#paths3dLayer = new Paths3DLayer(flatmap, this)
|
|
218
|
+
|
|
197
219
|
// Add various controls when running standalone
|
|
198
220
|
if (flatmap.options.standalone) {
|
|
199
221
|
// Add a control to search annotations if option set
|
|
@@ -225,73 +247,17 @@ export class UserInteractions
|
|
|
225
247
|
// Connectivity taxon control for AC maps
|
|
226
248
|
this._map.addControl(new TaxonsControl(flatmap));
|
|
227
249
|
}
|
|
228
|
-
}
|
|
229
250
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
&& ann['geometry'] === 'LineString'
|
|
233
|
-
&& 'type' in ann && ann['type'].startsWith('line')
|
|
234
|
-
&& 'kind' in ann && !ann['kind'].includes('arterial') && !ann['kind'].includes('venous')
|
|
235
|
-
&& 'pathStartPosition' in ann
|
|
236
|
-
&& 'pathEndPosition' in ann)
|
|
237
|
-
|
|
238
|
-
/*
|
|
239
|
-
{
|
|
240
|
-
"featureId": 37,
|
|
241
|
-
"id": "ilxtr_neuron-type-keast-10",
|
|
242
|
-
"kind": "sensory",
|
|
243
|
-
"label": "L6-S1 sensory neuron innervating bladder",
|
|
244
|
-
"models": "ilxtr:neuron-type-keast-10",
|
|
245
|
-
"sckan": true,
|
|
246
|
-
"source": "https://apinatomy.org/uris/models/keast-bladder",
|
|
247
|
-
"taxons": ["NCBITaxon:10116"],
|
|
248
|
-
"tile-layer": "pathways",
|
|
249
|
-
"type": "line",
|
|
250
|
-
"bounds": [1.5454426659162825, -1.6254174813389017, 1.7478459571498208, -1.3632864333949712],
|
|
251
|
-
"markerPosition": [1.6466443115330516, -1.4943519573669364],
|
|
252
|
-
"geometry": "LineString",
|
|
253
|
-
"layer": "neural-routes",
|
|
254
|
-
"pathStartPosition": [1.7478459571498208, -1.3632864333949712],
|
|
255
|
-
"pathEndPosition": [1.5454426659162825, -1.6254174813389017]
|
|
256
|
-
}
|
|
257
|
-
*/
|
|
258
|
-
|
|
259
|
-
const deckOverlay = new DeckOverlay({
|
|
260
|
-
layers: [
|
|
261
|
-
new ArcLayer({
|
|
262
|
-
id: 'arcs',
|
|
263
|
-
data: pathData,
|
|
264
|
-
pickable: true,
|
|
265
|
-
autoHighlight: true,
|
|
266
|
-
numSegments: 100,
|
|
267
|
-
onHover: (i, e) => {
|
|
268
|
-
//console.log('hover', i, e)
|
|
269
|
-
if (i.object) {
|
|
270
|
-
const lineFeatureId = +i.object.featureId;
|
|
271
|
-
this.__activateFeature(this.mapFeature(lineFeatureId));
|
|
272
|
-
for (const featureId of this.__pathManager.lineFeatureIds([lineFeatureId])) {
|
|
273
|
-
if (+featureId !== lineFeatureId) {
|
|
274
|
-
this.__activateFeature(this.mapFeature(featureId));
|
|
275
|
-
}
|
|
251
|
+
if (flatmap.options.annotator) {
|
|
252
|
+
this._map.addControl(new AnnotatorControl(flatmap));
|
|
276
253
|
}
|
|
254
|
+
|
|
255
|
+
this._map.addControl(new Path3DControl(this));
|
|
277
256
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
// Styles
|
|
283
|
-
getSourcePosition: f => f.pathStartPosition,
|
|
284
|
-
getTargetPosition: f => f.pathEndPosition,
|
|
285
|
-
getSourceColor: f => pathColourRGB(f.kind, 160),
|
|
286
|
-
getTargetColor: f => pathColourRGB(f.kind, 160),
|
|
287
|
-
highlightColor: o => pathColourRGB(o.object.kind),
|
|
288
|
-
getWidth: 3
|
|
289
|
-
})
|
|
290
|
-
],
|
|
291
|
-
getTooltip: ({object}) => object && object.label
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
this._map.addControl(deckOverlay);
|
|
257
|
+
|
|
258
|
+
// Add an initially hidden tool for drawing on the map.
|
|
259
|
+
this.#annotationDrawControl = new AnnotationDrawControl(flatmap, false)
|
|
260
|
+
this._map.addControl(this.#annotationDrawControl)
|
|
295
261
|
|
|
296
262
|
// Handle mouse events
|
|
297
263
|
|
|
@@ -307,6 +273,12 @@ this._map.addControl(deckOverlay);
|
|
|
307
273
|
this.__pan_zoom_enabled = false;
|
|
308
274
|
}
|
|
309
275
|
|
|
276
|
+
get minimap()
|
|
277
|
+
//===========
|
|
278
|
+
{
|
|
279
|
+
return this.#minimap
|
|
280
|
+
}
|
|
281
|
+
|
|
310
282
|
get pathManager()
|
|
311
283
|
//===============
|
|
312
284
|
{
|
|
@@ -346,11 +318,40 @@ this._map.addControl(deckOverlay);
|
|
|
346
318
|
}
|
|
347
319
|
}
|
|
348
320
|
|
|
321
|
+
showAnnotator(visible=true)
|
|
322
|
+
//=========================
|
|
323
|
+
{
|
|
324
|
+
if (this.#annotationDrawControl) {
|
|
325
|
+
this.#annotationDrawControl.show(visible)
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
modifyDrawnAnnotatorFeature(operation, feature)
|
|
330
|
+
//=============================================
|
|
331
|
+
{
|
|
332
|
+
if (this.#annotationDrawControl) {
|
|
333
|
+
if (operation === 'add') {
|
|
334
|
+
this.#annotationDrawControl.addFeature(feature)
|
|
335
|
+
} else if (operation === 'remove') {
|
|
336
|
+
this.#annotationDrawControl.removeFeature(feature)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
#setPaint(options)
|
|
342
|
+
//================
|
|
343
|
+
{
|
|
344
|
+
this._layerManager.setPaint(options)
|
|
345
|
+
if (this.#paths3dLayer) {
|
|
346
|
+
this.#paths3dLayer.setPaint(options)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
349
350
|
setPaint(options)
|
|
350
351
|
//===============
|
|
351
352
|
{
|
|
352
353
|
this.__colourOptions = options;
|
|
353
|
-
this
|
|
354
|
+
this.#setPaint(options);
|
|
354
355
|
}
|
|
355
356
|
|
|
356
357
|
getLayers()
|
|
@@ -365,6 +366,14 @@ this._map.addControl(deckOverlay);
|
|
|
365
366
|
this._layerManager.activate(layerId, enable);
|
|
366
367
|
}
|
|
367
368
|
|
|
369
|
+
enable3dPaths(enable=true)
|
|
370
|
+
//========================
|
|
371
|
+
{
|
|
372
|
+
if (this.#paths3dLayer) {
|
|
373
|
+
this.#paths3dLayer.enable(enable)
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
368
377
|
getSystems()
|
|
369
378
|
//==========
|
|
370
379
|
{
|
|
@@ -394,19 +403,43 @@ this._map.addControl(deckOverlay);
|
|
|
394
403
|
return undefined;
|
|
395
404
|
}
|
|
396
405
|
|
|
406
|
+
#getFeatureState(feature)
|
|
407
|
+
//=======================
|
|
408
|
+
{
|
|
409
|
+
return this._map.getFeatureState(feature)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
#removeFeatureState(feature, key)
|
|
413
|
+
//===============================
|
|
414
|
+
{
|
|
415
|
+
this._map.removeFeatureState(feature, key)
|
|
416
|
+
if (this.#paths3dLayer) {
|
|
417
|
+
this.#paths3dLayer.removeFeatureState(feature.id, key)
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
#setFeatureState(feature, state)
|
|
422
|
+
//==============================
|
|
423
|
+
{
|
|
424
|
+
this._map.setFeatureState(feature, state)
|
|
425
|
+
if (this.#paths3dLayer) {
|
|
426
|
+
this.#paths3dLayer.setFeatureState(feature.id, state)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
397
430
|
enableMapFeature(feature, enable=true)
|
|
398
431
|
//====================================
|
|
399
432
|
{
|
|
400
433
|
if (feature !== undefined) {
|
|
401
|
-
const state = this
|
|
434
|
+
const state = this.#getFeatureState(feature);
|
|
402
435
|
if ('hidden' in state) {
|
|
403
436
|
if (enable) {
|
|
404
|
-
this
|
|
437
|
+
this.#removeFeatureState(feature, 'hidden');
|
|
405
438
|
} else if (!state.hidden) {
|
|
406
|
-
this
|
|
439
|
+
this.#setFeatureState(feature, { hidden: true });
|
|
407
440
|
}
|
|
408
441
|
} else if (!enable) {
|
|
409
|
-
this
|
|
442
|
+
this.#setFeatureState(feature, { hidden: true });
|
|
410
443
|
}
|
|
411
444
|
this.__enableFeatureMarker(feature.id, enable);
|
|
412
445
|
}
|
|
@@ -454,11 +487,11 @@ this._map.addControl(deckOverlay);
|
|
|
454
487
|
//=======================
|
|
455
488
|
{
|
|
456
489
|
if (feature.id) {
|
|
457
|
-
const state = this
|
|
490
|
+
const state = this.#getFeatureState(feature);
|
|
458
491
|
return (state !== undefined
|
|
459
492
|
&& (!('hidden' in state) || !state.hidden));
|
|
460
493
|
}
|
|
461
|
-
return
|
|
494
|
+
return DRAW_ANNOTATION_LAYERS.includes(feature.layer.id)
|
|
462
495
|
}
|
|
463
496
|
|
|
464
497
|
featureSelected_(featureId)
|
|
@@ -471,7 +504,7 @@ this._map.addControl(deckOverlay);
|
|
|
471
504
|
//================================
|
|
472
505
|
{
|
|
473
506
|
const ann = this._flatmap.annotation(featureId);
|
|
474
|
-
if ('sckan' in ann) {
|
|
507
|
+
if (ann && 'sckan' in ann) {
|
|
475
508
|
const sckanState = this._layerManager.sckanState;
|
|
476
509
|
if (sckanState === 'none'
|
|
477
510
|
|| sckanState === 'valid' && !ann.sckan
|
|
@@ -488,16 +521,16 @@ this._map.addControl(deckOverlay);
|
|
|
488
521
|
} else {
|
|
489
522
|
const feature = this.mapFeature(featureId);
|
|
490
523
|
if (feature !== undefined) {
|
|
491
|
-
const state = this
|
|
524
|
+
const state = this.#getFeatureState(feature);
|
|
492
525
|
if (state !== undefined && (!('hidden' in state) || !state.hidden)) {
|
|
493
|
-
this
|
|
526
|
+
this.#setFeatureState(feature, { selected: true });
|
|
494
527
|
this._selectedFeatureIds.set(featureId, 1);
|
|
495
528
|
result = true;
|
|
496
529
|
}
|
|
497
530
|
}
|
|
498
531
|
}
|
|
499
532
|
if (result && noSelection) {
|
|
500
|
-
this
|
|
533
|
+
this.#setPaint({...this.__colourOptions, dimmed: dim});
|
|
501
534
|
}
|
|
502
535
|
return result;
|
|
503
536
|
}
|
|
@@ -513,13 +546,13 @@ this._map.addControl(deckOverlay);
|
|
|
513
546
|
} else {
|
|
514
547
|
const feature = this.mapFeature(featureId);
|
|
515
548
|
if (feature !== undefined) {
|
|
516
|
-
this
|
|
549
|
+
this.#removeFeatureState(feature, 'selected');
|
|
517
550
|
this._selectedFeatureIds.delete(+featureId);
|
|
518
551
|
}
|
|
519
552
|
}
|
|
520
553
|
}
|
|
521
554
|
if (this._selectedFeatureIds.size === 0) {
|
|
522
|
-
this
|
|
555
|
+
this.#setPaint({...this.__colourOptions, dimmed: false});
|
|
523
556
|
}
|
|
524
557
|
}
|
|
525
558
|
|
|
@@ -529,28 +562,42 @@ this._map.addControl(deckOverlay);
|
|
|
529
562
|
for (const featureId of this._selectedFeatureIds.keys()) {
|
|
530
563
|
const feature = this.mapFeature(featureId);
|
|
531
564
|
if (feature !== undefined) {
|
|
532
|
-
this
|
|
565
|
+
this.#removeFeatureState(feature, 'selected');
|
|
533
566
|
}
|
|
534
567
|
}
|
|
535
568
|
this._selectedFeatureIds.clear();
|
|
536
|
-
this
|
|
569
|
+
this.#setPaint({...this.__colourOptions, dimmed: false});
|
|
537
570
|
}
|
|
538
571
|
|
|
539
|
-
|
|
540
|
-
|
|
572
|
+
activateFeature(feature)
|
|
573
|
+
//======================
|
|
541
574
|
{
|
|
542
575
|
if (feature !== undefined) {
|
|
543
|
-
this
|
|
544
|
-
this._activeFeatures.
|
|
576
|
+
this.#setFeatureState(feature, { active: true });
|
|
577
|
+
this._activeFeatures.add(feature);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
activateLineFeatures(lineFeatures)
|
|
582
|
+
//================================
|
|
583
|
+
{
|
|
584
|
+
for (const lineFeature of lineFeatures) {
|
|
585
|
+
const lineFeatureId = +lineFeature.properties.featureId // Ensure numeric
|
|
586
|
+
this.activateFeature(lineFeature)
|
|
587
|
+
const lineIds = new Set(lineFeatures.map(f => f.properties.featureId))
|
|
588
|
+
for (const featureId of this.__pathManager.lineFeatureIds(lineIds)) {
|
|
589
|
+
this.activateFeature(this.mapFeature(featureId))
|
|
590
|
+
}
|
|
545
591
|
}
|
|
546
592
|
}
|
|
547
593
|
|
|
548
594
|
resetActiveFeatures_()
|
|
549
595
|
//====================
|
|
550
596
|
{
|
|
551
|
-
|
|
552
|
-
this
|
|
597
|
+
for (const feature of this._activeFeatures) {
|
|
598
|
+
this.#removeFeatureState(feature, 'active');
|
|
553
599
|
}
|
|
600
|
+
this._activeFeatures.clear()
|
|
554
601
|
}
|
|
555
602
|
|
|
556
603
|
smallestAnnotatedPolygonFeature_(features)
|
|
@@ -562,7 +609,7 @@ this._map.addControl(deckOverlay);
|
|
|
562
609
|
let smallestFeature = null;
|
|
563
610
|
for (const feature of features) {
|
|
564
611
|
if (feature.geometry.type.includes('Polygon')
|
|
565
|
-
&& this
|
|
612
|
+
&& this.#getFeatureState(feature)['map-annotation']) {
|
|
566
613
|
const polygon = turf.geometry(feature.geometry.type, feature.geometry.coordinates);
|
|
567
614
|
const area = turfArea(polygon);
|
|
568
615
|
if (smallestFeature === null || smallestArea > area) {
|
|
@@ -795,7 +842,9 @@ this._map.addControl(deckOverlay);
|
|
|
795
842
|
tooltip.push(`<div class="feature-error">Warning: ${properties.warning}</div>`)
|
|
796
843
|
}
|
|
797
844
|
let renderedLabel;
|
|
798
|
-
if (('label' in properties
|
|
845
|
+
if (('label' in properties
|
|
846
|
+
|| 'hyperlink' in properties
|
|
847
|
+
|| 'user_label' in properties)
|
|
799
848
|
&& (forceLabel || !('tooltip' in properties) || properties.tooltip)) {
|
|
800
849
|
const renderedLabel = getRenderedLabel(properties);
|
|
801
850
|
if ('hyperlink' in properties) {
|
|
@@ -837,6 +886,19 @@ this._map.addControl(deckOverlay);
|
|
|
837
886
|
this.resetActiveFeatures_();
|
|
838
887
|
}
|
|
839
888
|
|
|
889
|
+
#renderedFeatures(point)
|
|
890
|
+
//======================
|
|
891
|
+
{
|
|
892
|
+
let features = []
|
|
893
|
+
if (this.#paths3dLayer) {
|
|
894
|
+
features = this.#paths3dLayer.queryFeaturesAtPoint(point)
|
|
895
|
+
}
|
|
896
|
+
if (features.length === 0) {
|
|
897
|
+
features = this._map.queryRenderedFeatures(point)
|
|
898
|
+
}
|
|
899
|
+
return features.filter(feature => this.__featureEnabled(feature));
|
|
900
|
+
}
|
|
901
|
+
|
|
840
902
|
mouseMoveEvent_(event)
|
|
841
903
|
//====================
|
|
842
904
|
{
|
|
@@ -855,8 +917,7 @@ this._map.addControl(deckOverlay);
|
|
|
855
917
|
}
|
|
856
918
|
|
|
857
919
|
// Get all the features at the current point
|
|
858
|
-
const features = this
|
|
859
|
-
.filter(feature => this.__featureEnabled(feature));
|
|
920
|
+
const features = this.#renderedFeatures(event.point)
|
|
860
921
|
if (features.length === 0) {
|
|
861
922
|
this._lastFeatureMouseEntered = null;
|
|
862
923
|
this._lastFeatureModelsMouse = null;
|
|
@@ -885,7 +946,7 @@ this._map.addControl(deckOverlay);
|
|
|
885
946
|
let tooltip = '';
|
|
886
947
|
if (displayInfo) {
|
|
887
948
|
if (!('tooltip' in features[0].properties)) {
|
|
888
|
-
this.
|
|
949
|
+
this.activateFeature(features[0]);
|
|
889
950
|
}
|
|
890
951
|
info = this._infoControl.featureInformation(features, event.lngLat);
|
|
891
952
|
}
|
|
@@ -896,19 +957,11 @@ this._map.addControl(deckOverlay);
|
|
|
896
957
|
if (lineFeatures.length > 0) {
|
|
897
958
|
tooltip = this.lineTooltip_(lineFeatures);
|
|
898
959
|
tooltipFeature = lineFeatures[0];
|
|
899
|
-
|
|
900
|
-
const lineFeatureId = +lineFeature.properties.featureId; // Ensure numeric
|
|
901
|
-
this.__activateFeature(lineFeature);
|
|
902
|
-
const lineIds = new Set(lineFeatures.map(f => f.properties.featureId));
|
|
903
|
-
for (const featureId of this.__pathManager.lineFeatureIds(lineIds)) {
|
|
904
|
-
if (+featureId !== lineFeatureId) {
|
|
905
|
-
this.__activateFeature(this.mapFeature(featureId));
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
}
|
|
960
|
+
this.activateLineFeatures(lineFeatures)
|
|
909
961
|
} else {
|
|
910
962
|
let labelledFeatures = features.filter(feature => (('hyperlink' in feature.properties
|
|
911
|
-
|| 'label' in feature.properties
|
|
963
|
+
|| 'label' in feature.properties
|
|
964
|
+
|| 'user_label' in feature.properties)
|
|
912
965
|
&& (!('tooltip' in feature.properties)
|
|
913
966
|
|| feature.properties.tooltip)))
|
|
914
967
|
.sort((a, b) => (a.properties.area - b.properties.area));
|
|
@@ -921,6 +974,9 @@ this._map.addControl(deckOverlay);
|
|
|
921
974
|
labelledFeatures = groupFeatures;
|
|
922
975
|
}
|
|
923
976
|
const feature = labelledFeatures[0];
|
|
977
|
+
if (feature.properties.user_drawn) {
|
|
978
|
+
feature.id = feature.properties.id
|
|
979
|
+
}
|
|
924
980
|
tooltip = this.tooltipHtml_(feature.properties);
|
|
925
981
|
tooltipFeature = feature;
|
|
926
982
|
if (this._flatmap.options.debug) { // Do this when Info on and not debug??
|
|
@@ -952,7 +1008,7 @@ this._map.addControl(deckOverlay);
|
|
|
952
1008
|
info = `<div id="info-control-info">${htmlList.join('\n')}</div>`;
|
|
953
1009
|
}
|
|
954
1010
|
}
|
|
955
|
-
this.
|
|
1011
|
+
this.activateFeature(feature);
|
|
956
1012
|
this.__activateRelatedFeatures(feature);
|
|
957
1013
|
if ('hyperlink' in feature.properties) {
|
|
958
1014
|
this._map.getCanvas().style.cursor = 'pointer';
|
|
@@ -1005,7 +1061,7 @@ this._map.addControl(deckOverlay);
|
|
|
1005
1061
|
//=============================
|
|
1006
1062
|
{
|
|
1007
1063
|
if (feature !== undefined) {
|
|
1008
|
-
const clickedFeatureId = feature.id;
|
|
1064
|
+
const clickedFeatureId = +feature.id;
|
|
1009
1065
|
const dim = !('properties' in feature
|
|
1010
1066
|
&& 'kind' in feature.properties
|
|
1011
1067
|
&& ['cell-type', 'scaffold', 'tissue'].includes(feature.properties.kind));
|
|
@@ -1044,9 +1100,9 @@ this._map.addControl(deckOverlay);
|
|
|
1044
1100
|
}
|
|
1045
1101
|
|
|
1046
1102
|
this.__clearActiveMarker();
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
if (clickedFeatures.length == 0){
|
|
1103
|
+
|
|
1104
|
+
const clickedFeatures = this.#renderedFeatures(event.point)
|
|
1105
|
+
if (clickedFeatures.length == 0) {
|
|
1050
1106
|
this.unselectFeatures();
|
|
1051
1107
|
return;
|
|
1052
1108
|
}
|
|
@@ -1072,25 +1128,19 @@ this._map.addControl(deckOverlay);
|
|
|
1072
1128
|
if ('nerveId' in feature.properties) {
|
|
1073
1129
|
const nerveId = feature.properties.nerveId;
|
|
1074
1130
|
if (nerveId !== feature.id) {
|
|
1075
|
-
this.
|
|
1131
|
+
this.activateFeature(this.mapFeature(nerveId));
|
|
1076
1132
|
}
|
|
1077
1133
|
for (const featureId of this.__pathManager.nerveFeatureIds(nerveId)) {
|
|
1078
|
-
this.
|
|
1134
|
+
this.activateFeature(this.mapFeature(featureId));
|
|
1079
1135
|
}
|
|
1080
1136
|
}
|
|
1081
1137
|
if ('nodeId' in feature.properties) {
|
|
1082
1138
|
for (const featureId of this.__pathManager.pathFeatureIds(feature.properties.nodeId)) {
|
|
1083
|
-
this.
|
|
1139
|
+
this.activateFeature(this.mapFeature(featureId));
|
|
1084
1140
|
}
|
|
1085
1141
|
}
|
|
1086
1142
|
}
|
|
1087
1143
|
|
|
1088
|
-
enablePath(pathId, enable=true)
|
|
1089
|
-
//=============================
|
|
1090
|
-
{
|
|
1091
|
-
this.__pathManager.enablePath(pathId, enable);
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
1144
|
enablePathsBySystem(system, enable=true, force=false)
|
|
1095
1145
|
//===================================================
|
|
1096
1146
|
{
|
|
@@ -1128,7 +1178,7 @@ this._map.addControl(deckOverlay);
|
|
|
1128
1178
|
//=========================================
|
|
1129
1179
|
{
|
|
1130
1180
|
this.__pathManager.enablePathsByType('centreline', enable, force);
|
|
1131
|
-
this
|
|
1181
|
+
this.#setPaint({showCentrelines: enable});
|
|
1132
1182
|
}
|
|
1133
1183
|
|
|
1134
1184
|
enableSckanPaths(sckanState, enable=true)
|
|
@@ -1155,7 +1205,7 @@ this._map.addControl(deckOverlay);
|
|
|
1155
1205
|
excludeAnnotated(exclude=false)
|
|
1156
1206
|
//=============================
|
|
1157
1207
|
{
|
|
1158
|
-
this
|
|
1208
|
+
this.#setPaint({excludeAnnotated: exclude});
|
|
1159
1209
|
}
|
|
1160
1210
|
|
|
1161
1211
|
//==============================================================================
|
|
@@ -1315,7 +1365,7 @@ this._map.addControl(deckOverlay);
|
|
|
1315
1365
|
if (event.type === 'mouseenter') {
|
|
1316
1366
|
// Highlight on mouse enter
|
|
1317
1367
|
this.resetActiveFeatures_();
|
|
1318
|
-
this.
|
|
1368
|
+
this.activateFeature(feature);
|
|
1319
1369
|
} else {
|
|
1320
1370
|
this.selectionEvent_(event, feature)
|
|
1321
1371
|
}
|
|
@@ -22,10 +22,10 @@ limitations under the License.
|
|
|
22
22
|
|
|
23
23
|
//==============================================================================
|
|
24
24
|
|
|
25
|
-
import {PATHWAYS_LAYER} from '
|
|
25
|
+
import {PATHWAYS_LAYER} from '../pathways.js';
|
|
26
|
+
import * as utils from '../utils.js';
|
|
26
27
|
|
|
27
28
|
import * as style from './styling.js';
|
|
28
|
-
import * as utils from './utils.js';
|
|
29
29
|
|
|
30
30
|
const FEATURES_LAYER = 'features';
|
|
31
31
|
const RASTER_LAYERS_NAME = 'Background image layer';
|