@abi-software/flatmap-viewer 2.2.11-devel.1 → 2.2.12-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/src/styling.js CHANGED
@@ -44,6 +44,11 @@ class VectorStyleLayer
44
44
  return this.__id;
45
45
  }
46
46
 
47
+ makeFilter(options)
48
+ {
49
+ return null;
50
+ }
51
+
47
52
  paintStyle(options, changes=false)
48
53
  {
49
54
  return {};
@@ -157,7 +162,8 @@ export class FeatureFillLayer extends VectorStyleLayer
157
162
  'filter': [
158
163
  'all',
159
164
  ['==', '$type', 'Polygon'],
160
- ['!=', 'models', 'UBERON:0013702']
165
+ ['!=', 'models', 'UBERON:0013702'],
166
+ ['!has', 'node']
161
167
  ],
162
168
  'layout': {
163
169
  'fill-sort-key': ['get', 'scale']
@@ -184,7 +190,7 @@ export class FeatureBorderLayer extends VectorStyleLayer
184
190
  const activeRasterLayer = 'activeRasterLayer' in options && options.activeRasterLayer;
185
191
  const lineColour = [ 'case' ];
186
192
  lineColour.push(['boolean', ['feature-state', 'selected'], false]);
187
- lineColour.push('red');
193
+ lineColour.push('black');
188
194
  if (coloured && outlined) {
189
195
  lineColour.push(['boolean', ['feature-state', 'active'], false]);
190
196
  lineColour.push('blue');
@@ -193,7 +199,6 @@ export class FeatureBorderLayer extends VectorStyleLayer
193
199
  lineColour.push('#000');
194
200
  lineColour.push(['has', 'node']);
195
201
  lineColour.push('#AFA202');
196
- // this colour should be complement of background colour...
197
202
  lineColour.push('#444');
198
203
 
199
204
  const lineOpacity = [
@@ -240,7 +245,8 @@ export class FeatureBorderLayer extends VectorStyleLayer
240
245
  'type': 'line',
241
246
  'filter': [
242
247
  'all',
243
- ['==', '$type', 'Polygon']
248
+ ['==', '$type', 'Polygon'],
249
+ ['!has', 'node']
244
250
  ],
245
251
  'paint': this.paintStyle(options)
246
252
  };
@@ -251,33 +257,40 @@ export class FeatureBorderLayer extends VectorStyleLayer
251
257
 
252
258
  export class FeatureLineLayer extends VectorStyleLayer
253
259
  {
254
- constructor(id, sourceLayer, dashed=false)
260
+ constructor(id, sourceLayer, options={})
255
261
  {
262
+ const dashed = ('dashed' in options && options.dashed);
256
263
  const filterType = dashed ? 'line-dash' : 'line';
257
264
  super(id, `feature-${filterType}`, sourceLayer);
258
- this.__filter = dashed ?
259
- [
260
- 'any',
261
- ['==', 'type', `line-dash`]
262
- ]
263
- :
265
+ this.__dashed = dashed;
266
+ }
267
+
268
+ makeFilter(options={})
269
+ {
270
+ return this.__dashed ? [
271
+ 'all',
272
+ ['==', '$type', 'LineString'],
273
+ ['==', 'type', `line-dash`]
274
+ ] : [
275
+ 'all',
276
+ ['==', '$type', 'LineString'],
264
277
  [
265
278
  'any',
266
279
  ['==', 'type', 'bezier'],
267
280
  ['==', 'type', `line`]
268
- ];
269
- this.__dashed = dashed;
281
+ ]
282
+ ];
270
283
  }
271
284
 
272
- paintStyle(options)
285
+ paintStyle(options, changes=false)
273
286
  {
274
287
  const coloured = !('colour' in options) || options.colour;
275
288
  const paintStyle = {
276
289
  'line-color': [
277
290
  'case',
278
291
  ['boolean', ['feature-state', 'selected'], false], '#0F0',
279
- ['has', 'colour'], ['get', 'colour'],
280
292
  ['boolean', ['feature-state', 'active'], false], coloured ? '#888' : '#CCC',
293
+ ['has', 'colour'], ['get', 'colour'],
281
294
  ['==', ['get', 'type'], 'network'], '#AFA202',
282
295
  options.authoring ? '#C44' : '#444'
283
296
  ],
@@ -311,7 +324,7 @@ export class FeatureLineLayer extends VectorStyleLayer
311
324
  if (this.__dashed) {
312
325
  paintStyle['line-dasharray'] = [3, 2];
313
326
  }
314
- return paintStyle;
327
+ return super.changedPaintStyle(paintStyle, changes);
315
328
  }
316
329
 
317
330
  style(options)
@@ -319,12 +332,7 @@ export class FeatureLineLayer extends VectorStyleLayer
319
332
  return {
320
333
  ...super.style(),
321
334
  'type': 'line',
322
- 'filter': [
323
- 'all',
324
- ['==', '$type', 'LineString'],
325
- this.__filter
326
- // not for paths...
327
- ],
335
+ 'filter': this.makeFilter(options),
328
336
  'paint': this.paintStyle(options)
329
337
  };
330
338
  }
@@ -336,7 +344,7 @@ export class FeatureDashLineLayer extends FeatureLineLayer
336
344
  {
337
345
  constructor(id, sourceLayer)
338
346
  {
339
- super(id, sourceLayer, true);
347
+ super(id, sourceLayer, {dashed: true});
340
348
  }
341
349
  }
342
350
 
@@ -344,26 +352,63 @@ export class FeatureDashLineLayer extends FeatureLineLayer
344
352
 
345
353
  export class PathLineLayer extends VectorStyleLayer
346
354
  {
347
- constructor(id, sourceLayer, dashed=false)
355
+ constructor(id, sourceLayer, options={})
348
356
  {
357
+ const dashed = ('dashed' in options && options.dashed);
349
358
  const filterType = dashed ? 'line-dash' : 'line';
350
359
  super(id, `path-${filterType}`, sourceLayer);
351
- this.__filter = dashed ?
352
- [
360
+ this.__dashed = dashed;
361
+ }
362
+
363
+ makeFilter(options={})
364
+ {
365
+ const sckanState = !'sckan' in options ? 'all'
366
+ : options.sckan.toLowerCase();
367
+ const sckan_filter =
368
+ sckanState == 'none' ? [
369
+ ['!has', 'sckan']
370
+ ] :
371
+ sckanState == 'valid' ? [[
353
372
  'any',
354
- ['==', 'type', `line-dash`]
355
- ]
356
- :
373
+ ['!has', 'sckan'],
374
+ [
375
+ 'all',
376
+ ['has', 'sckan'],
377
+ ['==', 'sckan', true]
378
+ ]
379
+ ]] :
380
+ sckanState == 'invalid' ? [[
381
+ 'any',
382
+ ['!has', 'sckan'],
383
+ [
384
+ 'all',
385
+ ['has', 'sckan'],
386
+ ['!=', 'sckan', true]
387
+ ]
388
+ ]] :
389
+ [ ];
390
+
391
+ return this.__dashed ? [
392
+ 'all',
393
+ ['==', '$type', 'LineString'],
394
+ ['==', 'type', `line-dash`],
395
+ ...sckan_filter
396
+ ] : [
397
+ 'all',
398
+ ['==', '$type', 'LineString'],
357
399
  [
358
400
  'any',
359
401
  ['==', 'type', 'bezier'],
360
- ['==', 'type', 'centreline'],
361
- ['==', 'type', `line`]
362
- ];
363
- this.__dashed = dashed;
402
+ [
403
+ 'all',
404
+ ['==', 'type', `line`],
405
+ ...sckan_filter
406
+ ]
407
+ ]
408
+ ];
364
409
  }
365
410
 
366
- paintStyle(options, changes=false)
411
+ paintStyle(options={}, changes=false)
367
412
  {
368
413
  const dimmed = 'dimmed' in options && options.dimmed;
369
414
  const paintStyle = {
@@ -372,8 +417,6 @@ export class PathLineLayer extends VectorStyleLayer
372
417
  ['boolean', ['feature-state', 'selected'], false], '#0F0',
373
418
  ['boolean', ['feature-state', 'hidden'], false], '#CCC',
374
419
  ['==', ['get', 'type'], 'bezier'], 'red',
375
- ['==', ['get', 'type'], 'centreline'], '#00F',
376
- ['has', 'error'], '#FFFE0E',
377
420
  ['==', ['get', 'kind'], 'unknown'], '#888',
378
421
  ...PATH_STYLE_RULES,
379
422
  '#888'
@@ -382,10 +425,10 @@ export class PathLineLayer extends VectorStyleLayer
382
425
  'case',
383
426
  ['boolean', ['feature-state', 'hidden'], false], 0.05,
384
427
  ['==', ['get', 'type'], 'bezier'], 1.0,
428
+ ['==', ['get', 'kind'], 'error'], 1.0,
385
429
  ['boolean', ['get', 'invisible'], false], 0.001,
386
430
  ['boolean', ['feature-state', 'selected'], false], 1.0,
387
431
  ['boolean', ['feature-state', 'active'], false], 1.0,
388
- // Only dim lines when other lines are selected, not if just features selected??
389
432
  dimmed ? 0.1 : 0.8
390
433
  ],
391
434
  'line-width': [
@@ -393,7 +436,7 @@ export class PathLineLayer extends VectorStyleLayer
393
436
  'width', ["*", [
394
437
  'case',
395
438
  ['==', ['get', 'type'], 'bezier'], 0.1,
396
- ['has', 'error'], 1,
439
+ ['==', ['get', 'kind'], 'error'], 1,
397
440
  ['==', ['get', 'kind'], 'unknown'], 1,
398
441
  ['boolean', ['get', 'invisible'], false], 0.1,
399
442
  ['boolean', ['feature-state', 'selected'], false], 0.6,
@@ -416,6 +459,76 @@ export class PathLineLayer extends VectorStyleLayer
416
459
  return super.changedPaintStyle(paintStyle, changes);
417
460
  }
418
461
 
462
+ style(options={})
463
+ {
464
+ return {
465
+ ...super.style(),
466
+ 'type': 'line',
467
+ 'filter': this.makeFilter(options),
468
+ 'layout': {
469
+ 'line-cap': 'butt'
470
+ },
471
+ 'paint': this.paintStyle(options)
472
+ };
473
+ }
474
+ }
475
+
476
+ //==============================================================================
477
+
478
+ export class PathDashlineLayer extends PathLineLayer
479
+ {
480
+ constructor(id, sourceLayer)
481
+ {
482
+ super(id, sourceLayer, {dashed: true});
483
+ }
484
+ }
485
+
486
+ //==============================================================================
487
+
488
+ class CentrelineLayer extends VectorStyleLayer
489
+ {
490
+ constructor(id, type, sourceLayer)
491
+ {
492
+ super(id, `centreline-${type}`, sourceLayer);
493
+ this.__type = type;
494
+ }
495
+
496
+ paintStyle(options, changes=false)
497
+ {
498
+ const coloured = !('colour' in options) || options.colour;
499
+ const paintStyle = {
500
+ 'line-color': (this.__type == 'edge') ? '#000' : [
501
+ 'case',
502
+ ['boolean', ['feature-state', 'selected'], false], '#0F0',
503
+ ['boolean', ['feature-state', 'active'], false], '#444',
504
+ '#CCC'
505
+ ],
506
+ 'line-opacity': [
507
+ 'case',
508
+ ['boolean', ['feature-state', 'hidden'], false], 0.01,
509
+ ['boolean', ['feature-state', 'selected'], false], 1.0,
510
+ ['boolean', ['feature-state', 'active'], false], 1.0,
511
+ 0.8
512
+ ],
513
+ 'line-width': [
514
+ 'let',
515
+ 'width',
516
+ (this.__type == 'edge') ? 1.6 : 1.2,
517
+ [
518
+ 'interpolate',
519
+ ['exponential', 2],
520
+ ['zoom'],
521
+ 2, ["*", ['var', 'width'], ["^", 2, -0.5]],
522
+ 7, ["*", ['var', 'width'], ["^", 2, 2.5]],
523
+ 9, ["*", ['var', 'width'], ["^", 2, 4.0]]
524
+ ]
525
+ ]
526
+ // Need to vary width based on zoom??
527
+ // Or opacity??
528
+ };
529
+ return super.changedPaintStyle(paintStyle, changes);
530
+ }
531
+
419
532
  style(options)
420
533
  {
421
534
  return {
@@ -424,23 +537,104 @@ export class PathLineLayer extends VectorStyleLayer
424
537
  'filter': [
425
538
  'all',
426
539
  ['==', '$type', 'LineString'],
427
- this.__filter
540
+ ['==', 'kind', 'centreline']
428
541
  ],
542
+ 'paint': this.paintStyle(options),
429
543
  'layout': {
430
- 'line-cap': 'butt'
431
- },
432
- 'paint': this.paintStyle(options)
544
+ 'line-cap': 'square',
545
+ 'line-join': 'bevel'
546
+ }
433
547
  };
434
548
  }
435
549
  }
436
550
 
551
+
552
+ export class CentrelineEdgeLayer extends CentrelineLayer
553
+ {
554
+ constructor(id, sourceLayer)
555
+ {
556
+ super(id, 'edge', sourceLayer);
557
+ }
558
+
559
+ }
560
+
561
+ export class CentrelineTrackLayer extends CentrelineLayer
562
+ {
563
+ constructor(id, sourceLayer)
564
+ {
565
+ super(id, 'track', sourceLayer);
566
+ }
567
+
568
+
569
+ }
570
+
437
571
  //==============================================================================
438
572
 
439
- export class PathDashlineLayer extends PathLineLayer
573
+ export class CentrelineNodeFillLayer extends VectorStyleLayer
574
+ {
575
+ constructor(id, sourceLayer)
576
+ {
577
+ super(id, 'node-fill', sourceLayer);
578
+ }
579
+
580
+ paintStyle(options={}, changes=false)
581
+ {
582
+ const showNodes = options.showCentrelines || false;
583
+ const paintStyle = {
584
+ 'fill-color': '#AFA202',
585
+ 'fill-opacity': showNodes ? 0.7 : 0.01
586
+ }
587
+ return super.changedPaintStyle(paintStyle, changes);
588
+ }
589
+
590
+ style(options)
591
+ {
592
+ return {
593
+ ...super.style(),
594
+ 'type': 'fill',
595
+ 'filter': [
596
+ 'all',
597
+ ['==', '$type', 'Polygon'],
598
+ ['has', 'node']
599
+ ],
600
+ 'layout': {
601
+ 'fill-sort-key': ['get', 'scale']
602
+ },
603
+ 'paint': this.paintStyle(options)
604
+ };
605
+ }
606
+ }
607
+
608
+ export class CentrelineNodeBorderLayer extends VectorStyleLayer
440
609
  {
441
610
  constructor(id, sourceLayer)
442
611
  {
443
- super(id, sourceLayer, true);
612
+ super(id, 'node-border', sourceLayer);
613
+ }
614
+
615
+ paintStyle(options={}, changes=false)
616
+ {
617
+ const showNodes = options.showCentrelines || false;
618
+ const paintStyle = {
619
+ 'line-color': '#AFA202',
620
+ 'line-opacity': showNodes ? 0.7 : 0.01,
621
+ 'line-width': 0.5
622
+ }
623
+ return super.changedPaintStyle(paintStyle, changes);
624
+ }
625
+
626
+ style(options)
627
+ {
628
+ return {
629
+ ...super.style(),
630
+ 'type': 'line',
631
+ 'filter': [
632
+ 'all',
633
+ ['==', '$type', 'Polygon'],
634
+ ['has', 'node']
635
+ ],
636
+ 'paint': this.paintStyle(options)
637
+ };
444
638
  }
445
639
  }
446
640
 
@@ -461,6 +655,7 @@ export class FeatureNerveLayer extends VectorStyleLayer
461
655
  'filter': [
462
656
  'all',
463
657
  ['==', '$type', 'LineString'],
658
+ ['!=', 'kind', 'centreline'],
464
659
  ['==', 'type', 'nerve']
465
660
  ],
466
661
  'paint': {
@@ -202,40 +202,13 @@ li.flatmap-contextmenu-item:hover {
202
202
  label[for=path-all-paths] {
203
203
  font-weight: bold;
204
204
  }
205
- .nerve-cns {
206
- background: #9B1FC1;
207
- }
208
- .nerve-lcn {
209
- background: #F19E38;
210
- }
211
- .nerve-other {
212
- background: #888;
213
- }
214
- .nerve-para-pre {
215
- background: #3F8F4A;
216
- }
217
- .nerve-para-post {
218
- background: repeating-linear-gradient(to right,#3F8F4A 0,#3F8F4A 6px,transparent 6px,transparent 9px)
219
- }
220
- .nerve-sensory {
221
- background: #2A62F6;
222
- }
223
- .nerve-somatic {
224
- background: #98561D;
225
- }
226
- .nerve-symp-pre {
227
- background: #EA3423;
228
- }
229
- .nerve-symp-post {
230
- background: repeating-linear-gradient(to right,#EA3423 0,#EA3423 6px,transparent 6px,transparent 9px)
231
- }
232
205
 
233
206
  /* Layer control */
234
207
 
235
- #flatmap-layer-control {
208
+ .flatmap-control {
236
209
  text-align: right;
237
210
  }
238
- .flatmap-layer-grid {
211
+ .flatmap-control-grid {
239
212
  margin-top: 10px;
240
213
  display: grid;
241
214
  grid-template-columns: 3.8fr 0.2fr;
@@ -250,7 +223,7 @@ label[for=path-all-paths] {
250
223
  padding: 4px;
251
224
  opacity: 0.8;
252
225
  }
253
- .flatmap-layer-grid input {
226
+ .flatmap-control-grid input {
254
227
  height: 1.1em;
255
228
  }
256
229
  label[for=layer-all-layers] {
package/src/editor.js DELETED
@@ -1,198 +0,0 @@
1
- import { Bezier } from "bezier-js";
2
-
3
-
4
- class BezierCurve
5
- {
6
- constructor(id, ...points) {
7
- this.__id = id;
8
- this.__bezier = new Bezier(...points);
9
- }
10
-
11
- asGeoJSON(samples=100)
12
- {
13
- const coords = [];
14
- for (let ts = 0; ts <= samples; ts++) {
15
- const pt = this.__bezier.get(float(ts)/float(samples));
16
- coords.push([pt.x, pt.y]);
17
- }
18
- return {
19
- 'type': 'Feature',
20
- 'geometry': {
21
- 'type': 'LineString',
22
- 'coordinates': coords
23
- },
24
- 'properties': {
25
- 'bezier': this.__id
26
- }
27
- };
28
- }
29
-
30
- asPoints()
31
- {
32
- const geojson = [];
33
- for (const n of [0, 1, 2, 3]) {
34
- const pt = this.__bezier.points[n];
35
- geojson.push({
36
- 'type': 'Feature',
37
- 'geometry': {
38
- 'type': 'Point',
39
- 'coordinates': [pt.x, pt.y]
40
- },
41
- 'properties': {
42
- 'bezier': this.__id,
43
- 'point': n
44
- }
45
- });
46
- }
47
- return geojson;
48
- }
49
- }
50
-
51
-
52
- export class NetworkEditor
53
- {
54
- constructor(flatmap)
55
- {
56
- this.__map = flatmap.map;
57
- this.__canvas = this.__map.getCanvasContainer();
58
-
59
- this.__geojson = { // lines and points as separate sources???
60
- 'type': 'FeatureCollection',
61
- 'features': [
62
- {
63
- 'type': 'Feature',
64
- 'geometry': {
65
- 'type': 'Point',
66
- 'coordinates': [0, 0]
67
- },
68
- 'properties': {
69
- 'id': 0
70
- }
71
- }
72
- ]
73
- };
74
-
75
- // Add a single point to the map
76
- this.__map.addSource('curves', {
77
- 'type': 'geojson',
78
- 'data': this.__geojson
79
- });
80
-
81
- this.__map.addLayer({
82
- 'id': 'lines',
83
- 'type': 'line',
84
- 'source': 'curves',
85
- 'paint': {
86
- 'line-color': '#3887be'
87
- }
88
- });
89
- this.__map.addLayer({
90
- 'id': 'points',
91
- 'type': 'circle',
92
- 'source': 'curves',
93
- 'paint': {
94
- 'circle-radius': 10,
95
- 'circle-color': '#3887be'
96
- }
97
- });
98
-
99
- this.__currentPoint = null;
100
-
101
- this.__map.on('mouseenter', this.mouseEnter.bind(this));
102
- this.__map.on('mouseleave', this.mouseLeave.bind(this));
103
- this.__map.on('mousedown', this.mouseDown.bind(this));
104
- this.__map.on('touchstart', this.touchStart.bind(this));
105
- }
106
-
107
- addPoint(coords)
108
- {
109
- const nextId = this.__geojson.features.length;
110
- this.__geojson.features.push({
111
- 'type': 'Feature',
112
- 'geometry': {
113
- 'type': 'Point',
114
- 'coordinates': coords
115
- },
116
- 'properties': {
117
- 'id': nextId
118
- }
119
- });
120
- this.__map.getSource('curves').setData(this.__geojson);
121
- return nextId;
122
- }
123
-
124
- mouseEnter(e) {
125
- console.log('Mouse enter...');
126
-
127
- this.__map.setPaintProperty('lines', 'line-color', '#3bb2d0');
128
- this.__map.setPaintProperty('points', 'circle-color', '#3bb2d0');
129
- this.__canvas.style.cursor = 'move';
130
- }
131
-
132
-
133
- mouseLeave(e) {
134
- this.__map.setPaintProperty('lines', 'line-color', '#3887be');
135
- this.__map.setPaintProperty('points', 'circle-color', '#3887be');
136
- this.__canvas.style.cursor = '';
137
- }
138
-
139
-
140
- mouseDown(e) {
141
- console.log('Mouse down...')
142
- // Prevent the default map drag behavior.
143
- e.preventDefault();
144
-
145
-
146
- const features = this.__map.queryRenderedFeatures(e.point, {'layers': ['lines', 'points']});
147
- if (features.length === 0) {
148
- const coords = e.lngLat;
149
- this.__currentPoint = this.addPoint([coords.lng, coords.lat]);
150
- } else {
151
- const currentPoint = features[0].properties.id;
152
- if (this.__currentPoint === null) {
153
- this.__currentPoint = currentPoint;
154
- } else if (this.__currentPoint === currentPoint) {
155
- this.__currentPoint = null;
156
- }
157
- }
158
-
159
- this.__canvas.style.cursor = 'grab';
160
-
161
- this.__map.on('mousemove', this.onMove.bind(this));
162
- this.__map.once('mouseup', this.onUp.bind(this));
163
-
164
- }
165
-
166
- touchStart(e) {
167
- if (e.points.length !== 1) return;
168
-
169
- // Prevent the default map drag behavior.
170
- e.preventDefault();
171
-
172
- this.__map.on('touchmove', this.onMove.bind(this));
173
- this.__map.once('touchend', this.onUp.bind(this));
174
- }
175
-
176
- onMove(e) {
177
- console.log('Mouse move...')
178
-
179
- // Set a UI indicator for dragging.
180
- this.__canvas.style.cursor = 'grabbing'; // ????
181
-
182
- if (this.__currentPoint !== null) {
183
- const coords = e.lngLat;
184
- this.__geojson.features[this.__currentPoint].geometry.coordinates = [coords.lng, coords.lat];
185
- this.__map.getSource('curves').setData(this.__geojson);
186
- }
187
- }
188
-
189
- onUp(e) {
190
- console.log('End draw at', e.lngLat)
191
-
192
- this.__canvas.style.cursor = '';
193
-
194
- // Unbind mouse/touch events
195
- this.__map.off('mousemove', this.onMove.bind(this));
196
- this.__map.off('touchmove', this.onMove.bind(this));
197
- }
198
- }