@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/README.rst +1 -1
- package/package.json +2 -2
- package/src/controls.js +101 -37
- package/src/flatmap-viewer.js +79 -49
- package/src/info.js +5 -5
- package/src/interactions.js +129 -134
- package/src/layers.js +105 -53
- package/src/main.js +1 -7
- package/src/minimap.js +1 -1
- package/src/pathways.js +21 -8
- package/src/search.js +0 -1
- package/src/styling.js +239 -44
- package/static/flatmap-viewer.css +3 -30
- package/src/editor.js +0 -198
- package/src/newcontrols.js +0 -617
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('
|
|
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,
|
|
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.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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,
|
|
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.
|
|
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
|
-
['
|
|
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
|
-
[
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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
|
-
['
|
|
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
|
-
|
|
540
|
+
['==', 'kind', 'centreline']
|
|
428
541
|
],
|
|
542
|
+
'paint': this.paintStyle(options),
|
|
429
543
|
'layout': {
|
|
430
|
-
'line-cap': '
|
|
431
|
-
|
|
432
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
208
|
+
.flatmap-control {
|
|
236
209
|
text-align: right;
|
|
237
210
|
}
|
|
238
|
-
.flatmap-
|
|
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-
|
|
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
|
-
}
|