@jbrowse/bandage-core 11.7.1 → 11.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +106 -48
  2. package/dist/bubbles/bubbleHalos.js +6 -6
  3. package/dist/bubbles/classifyBubble.js +5 -5
  4. package/dist/bubbles/superbubbles.js +7 -7
  5. package/dist/chunks/{chunk-3PZSBNLI.js → chunk-22ZMVREZ.js} +19 -14
  6. package/dist/chunks/{chunk-VB4IXIPM.js → chunk-2H3ALI6L.js} +223 -45
  7. package/dist/chunks/{chunk-FBPAX5K6.js → chunk-2RCKHCF7.js} +1 -1
  8. package/dist/chunks/{chunk-5NZRT7GL.js → chunk-3CXZUC2Y.js} +2 -2
  9. package/dist/chunks/{chunk-WUZH2OJ6.js → chunk-3XYLEK4H.js} +2 -2
  10. package/dist/chunks/{chunk-F7O56DVR.js → chunk-4OVIUCSB.js} +2 -2
  11. package/dist/chunks/{chunk-JGH2V54E.js → chunk-4YPCUVMC.js} +2 -2
  12. package/dist/chunks/{chunk-FU57ZNRQ.js → chunk-6CXLLJ2C.js} +3 -3
  13. package/dist/chunks/{chunk-SACSQ45G.js → chunk-6MD4VS2F.js} +1 -1
  14. package/dist/chunks/{chunk-VACK24HF.js → chunk-735MPLUL.js} +35 -9
  15. package/dist/chunks/chunk-7GDNDQD7.js +504 -0
  16. package/dist/chunks/{chunk-IN4IYSA2.js → chunk-7PEYA3NA.js} +2 -2
  17. package/dist/chunks/{chunk-CWCVQJYY.js → chunk-AXE3RR7J.js} +1 -1
  18. package/dist/chunks/{chunk-BXE3SBBN.js → chunk-C3KAPREU.js} +1 -1
  19. package/dist/chunks/{chunk-ATDVS2CW.js → chunk-G3GLGDKV.js} +2 -2
  20. package/dist/chunks/{chunk-RB2MDFQU.js → chunk-G4WQBRDS.js} +4 -4
  21. package/dist/chunks/{chunk-SDI6BVG7.js → chunk-J4PDHWP2.js} +1 -1
  22. package/dist/chunks/{chunk-3UGWYQNY.js → chunk-JKIAHYAW.js} +14 -8
  23. package/dist/chunks/{chunk-TCSV3II7.js → chunk-L2RQV23D.js} +1 -1
  24. package/dist/chunks/{chunk-6XDTAKO7.js → chunk-LA6JHEVV.js} +1 -1
  25. package/dist/chunks/{chunk-G7SG4XMK.js → chunk-LODKC7PJ.js} +7 -0
  26. package/dist/chunks/{chunk-RK7ZOFPR.js → chunk-MO4DIRHD.js} +80 -38
  27. package/dist/chunks/{chunk-PCHEUVHB.js → chunk-N2GAA7RB.js} +1 -1
  28. package/dist/chunks/{chunk-I5SGYTRM.js → chunk-N4AJV4GH.js} +25 -14
  29. package/dist/chunks/{chunk-Q7I563MH.js → chunk-NHOXLUIL.js} +2 -2
  30. package/dist/chunks/{chunk-RT4K2JMZ.js → chunk-NQWEYJDD.js} +1 -1
  31. package/dist/chunks/{chunk-3Y2EFDID.js → chunk-OIOAK7BS.js} +1 -1
  32. package/dist/chunks/{chunk-EZGNBDHD.js → chunk-R3NPBUKT.js} +8 -8
  33. package/dist/chunks/{chunk-KJDERUQF.js → chunk-R4XCTRIU.js} +45 -10
  34. package/dist/chunks/{chunk-HTF32WSW.js → chunk-S3ICPPXC.js} +3 -3
  35. package/dist/chunks/{chunk-OXW5OHYQ.js → chunk-S4CH434Z.js} +1 -1
  36. package/dist/chunks/{chunk-HMEAGAGC.js → chunk-S7BCZVRK.js} +2 -2
  37. package/dist/chunks/{chunk-UV2IJMIG.js → chunk-SDDMV2MM.js} +1 -1
  38. package/dist/chunks/{chunk-J6XHW4KI.js → chunk-SIXFXXRI.js} +3 -3
  39. package/dist/chunks/{chunk-LKQOIPGE.js → chunk-U6JPSXJ3.js} +90 -21
  40. package/dist/chunks/{chunk-SENPGW4O.js → chunk-VCUOYVLC.js} +1 -1
  41. package/dist/chunks/{chunk-XTF2VWJN.js → chunk-VSRRIFRF.js} +1 -1
  42. package/dist/chunks/{chunk-BFUS3ENH.js → chunk-X5ULFAMM.js} +2 -2
  43. package/dist/chunks/{chunk-PJWLYGRL.js → chunk-XOIYBEU7.js} +1 -1
  44. package/dist/chunks/{chunk-JLIVX2SF.js → chunk-YEDZ37PH.js} +1 -1
  45. package/dist/chunks/{chunk-APLWFV4I.js → chunk-YF6T33PU.js} +10 -2
  46. package/dist/chunks/{chunk-2VMKQKVO.js → chunk-YIWN32ZX.js} +1 -1
  47. package/dist/chunks/{chunk-3WSA4NNP.js → chunk-ZKIH2USC.js} +1 -1
  48. package/dist/cli/figure.js +31 -30
  49. package/dist/cli/fold.js +6 -6
  50. package/dist/deletionEdges.js +2 -2
  51. package/dist/figure.js +27 -26
  52. package/dist/figureData.js +25 -24
  53. package/dist/figureScene.js +18 -17
  54. package/dist/figureSettings.js +6 -6
  55. package/dist/foldVariants.js +2 -2
  56. package/dist/genes/genePins.js +3 -3
  57. package/dist/graphLabels.js +4 -4
  58. package/dist/index.js +45 -44
  59. package/dist/labelLayout.js +8 -8
  60. package/dist/layout/forceCache.js +6 -6
  61. package/dist/layout/mergeRuns.js +2 -2
  62. package/dist/layout/orientToReference.js +3 -1
  63. package/dist/layout/tubeMapLayout.js +9 -9
  64. package/dist/layout/walkRowDraw.js +9 -8
  65. package/dist/layout/walkRowLayout.js +3 -3
  66. package/dist/layout/walkRowRuns.js +1 -1
  67. package/dist/layout/walkRows.js +2 -2
  68. package/dist/layout/walkStrip.js +13 -12
  69. package/dist/layoutModes.js +11 -11
  70. package/dist/pathColors.js +5 -5
  71. package/dist/pipeline.js +5 -5
  72. package/dist/referenceStrip.js +9 -8
  73. package/dist/renderer/GeometryBuilder.js +8 -7
  74. package/dist/renderer/walkLanes.js +44 -0
  75. package/dist/tubeMap/axis.js +5 -5
  76. package/dist/tubeMap/bundle.js +10 -10
  77. package/dist/tubeMap/coarsen.js +10 -10
  78. package/dist/tubeMap/deviations.js +11 -11
  79. package/dist/tubeMap/draw.js +5 -5
  80. package/dist/tubeMap/genes.js +6 -6
  81. package/dist/tubeMap/nodeColors.js +9 -8
  82. package/dist/tubeMap/reads.js +2 -2
  83. package/dist/types/figureData.d.ts +22 -0
  84. package/dist/types/foldVariants.d.ts +3 -1
  85. package/dist/types/renderer/types.d.ts +20 -0
  86. package/dist/types/renderer/walkLanes.d.ts +60 -0
  87. package/dist/types/types.d.ts +1 -0
  88. package/dist/types/util/geometry.d.ts +13 -1
  89. package/dist/types/version.d.ts +1 -1
  90. package/dist/types/walkEncoding.d.ts +7 -5
  91. package/dist/types/walkHighlight.d.ts +3 -0
  92. package/dist/util/SpatialIndex.js +4 -4
  93. package/dist/util/edgeCurves.js +3 -3
  94. package/dist/util/geometry.js +7 -1
  95. package/dist/util/hitDetection.js +5 -5
  96. package/dist/version.js +1 -1
  97. package/dist/viewport.js +6 -6
  98. package/dist/walkEncoding.js +9 -8
  99. package/dist/walkHighlight.js +10 -9
  100. package/dist/walkKey.js +5 -5
  101. package/package.json +1 -1
@@ -1,3 +1,19 @@
1
+ import {
2
+ LANE_SMOOTHING_PX,
3
+ THREAD_PITCH_PX,
4
+ THREAD_PX,
5
+ THREAD_REACH_PX,
6
+ THREAD_TAPER_PX,
7
+ bandScale,
8
+ bandSpans,
9
+ bandWidthPx,
10
+ laneLines,
11
+ laneRuns,
12
+ laneSlideAt,
13
+ slotCentres,
14
+ threadsPasses,
15
+ walkThreads
16
+ } from "./chunk-7GDNDQD7.js";
1
17
  import {
2
18
  abgrToCssRgba,
3
19
  fadeAbgr,
@@ -10,13 +26,13 @@ import {
10
26
  } from "./chunk-GQZVR5DW.js";
11
27
  import {
12
28
  baseEdgeCurves
13
- } from "./chunk-XTF2VWJN.js";
29
+ } from "./chunk-VSRRIFRF.js";
14
30
  import {
15
31
  PATH_LIGHTNESS,
16
32
  PATH_SATURATION,
17
33
  nameHue,
18
34
  pathHueAt
19
- } from "./chunk-3UGWYQNY.js";
35
+ } from "./chunk-JKIAHYAW.js";
20
36
  import {
21
37
  meanDepth,
22
38
  nodeWidthPx,
@@ -26,13 +42,14 @@ import {
26
42
  referenceMidpoints
27
43
  } from "./chunk-VX656OAZ.js";
28
44
  import {
29
- dashCurves,
45
+ dashSpans,
30
46
  pathRibbonOffsets,
31
47
  polylinePx,
48
+ slideCurves,
32
49
  strandSides,
33
50
  translateCurves,
34
51
  yToXOf
35
- } from "./chunk-VACK24HF.js";
52
+ } from "./chunk-735MPLUL.js";
36
53
  import {
37
54
  pushTo
38
55
  } from "./chunk-BSOZW3FC.js";
@@ -149,13 +166,16 @@ function arrowheadFor({
149
166
  color
150
167
  };
151
168
  }
152
- function leavesStart(edge, segments, first, stranded, yToX) {
153
- if (stranded) {
154
- return strandSides(edge).from === "start";
155
- }
156
- const gap = (p) => Math.hypot(p.x - first.x0, (p.y - first.y0) * yToX);
169
+ var FIRST_THREADS = [[0, 0]];
170
+ var ONE_PASS = [0];
171
+ var NO_SHIFT = { dx: 0, dy: 0 };
172
+ function nearerStart(at, segments, yToX) {
173
+ const gap = (p) => Math.hypot(p.x - at.x, (p.y - at.y) * yToX);
157
174
  return gap(segments[0]) < gap(segments.at(-1));
158
175
  }
176
+ function leavesStart(edge, segments, first, stranded, yToX) {
177
+ return stranded ? strandSides(edge).from === "start" : nearerStart({ x: first.x0, y: first.y0 }, segments, yToX);
178
+ }
159
179
  function intoDirection(last, toSegments) {
160
180
  if (toSegments.length < 2) {
161
181
  return void 0;
@@ -496,6 +516,74 @@ function buildGeometry(options) {
496
516
  const { pathColorByIndex, pathIndexByName } = pathPaletteOf(graph);
497
517
  const pathColorByName = (name) => pathColorByIndex[pathIndexByName.get(name) ?? -1] ?? EDGE_PATH_FALLBACK_COLOR;
498
518
  const nodePathSlots = drawPaths && pathCount > 1 ? pathSlotsOf(graph) : NO_SLOTS;
519
+ const liftedWalks = highlight?.walks ?? [];
520
+ const threaded = threadsPasses(liftedWalks);
521
+ const lanePasses = liftedWalks.map((w) => w.mostPasses);
522
+ const thinned = threaded ? bandScale(lanePasses) : 1;
523
+ const runs = liftedWalks.length > 1 ? laneRuns(
524
+ liftedWalks.flatMap((w) => w.route),
525
+ nodePositions,
526
+ yToX,
527
+ LANE_SMOOTHING_PX * worldPerScreenPx
528
+ ) : void 0;
529
+ const lines = runs ? laneLines(
530
+ runs,
531
+ nodePositions,
532
+ yToX,
533
+ LANE_SMOOTHING_PX * worldPerScreenPx,
534
+ bandWidthPx(lanePasses) * thinned * worldPerScreenPx,
535
+ threaded
536
+ ) : void 0;
537
+ const threads = threaded ? liftedWalks.map(
538
+ (w) => walkThreads(
539
+ w.route,
540
+ w.passes,
541
+ nodePositions,
542
+ yToX,
543
+ THREAD_REACH_PX * worldPerScreenPx
544
+ )
545
+ ) : void 0;
546
+ const spanField = runs && threads ? bandSpans(
547
+ runs,
548
+ threads.map((t) => t.span),
549
+ {
550
+ reach: THREAD_REACH_PX * worldPerScreenPx,
551
+ taper: THREAD_TAPER_PX * worldPerScreenPx
552
+ }
553
+ ) : void 0;
554
+ const edgeKeys = new Set(
555
+ threads ? graph.edges.map((e) => `${e.from}>${e.to}`) : []
556
+ );
557
+ const centresByNode = /* @__PURE__ */ new Map();
558
+ const laneOffset = (nodeId, laneWidth, lane, pass) => {
559
+ if (!threaded) {
560
+ return (lane - (liftedWalks.length - 1) / 2) * laneWidth;
561
+ }
562
+ let centres = centresByNode.get(nodeId);
563
+ if (!centres) {
564
+ const spans = spanField?.get(nodeId);
565
+ centres = slotCentres(spans?.slot ?? lanePasses, lanePasses, spans?.held);
566
+ centresByNode.set(nodeId, centres);
567
+ }
568
+ return (centres[lane] + pass * THREAD_PITCH_PX) * thinned;
569
+ };
570
+ const laneHalfWidth = (laneWidth) => threaded ? THREAD_PX / 2 * thinned : laneWidth / 2;
571
+ const laneNormals = /* @__PURE__ */ new Map();
572
+ const laneNormalsOf = (nodeId, segments) => {
573
+ let normals = laneNormals.get(nodeId);
574
+ if (!normals) {
575
+ const smoothed = lines?.normals.get(nodeId);
576
+ normals = smoothed ? pointNormalsOf(segments, yToX).map((n, i) => smoothed[i] ?? n) : pointNormalsOf(segments, yToX);
577
+ laneNormals.set(nodeId, normals);
578
+ }
579
+ return normals;
580
+ };
581
+ const laneWidths = /* @__PURE__ */ new Map();
582
+ const laneShiftOf = (nodeId, index) => lines?.shifts.get(nodeId)?.[index] ?? NO_SHIFT;
583
+ const lanePointsOf = (nodeId, segments) => lines?.shifts.has(nodeId) ? segments.map((p, i) => {
584
+ const { dx, dy } = laneShiftOf(nodeId, i);
585
+ return { ...p, x: p.x + dx, y: p.y + dy };
586
+ }) : segments;
499
587
  const showArrows = scale > (linearLayout ? 1 : MIN_ARROW_SCALE);
500
588
  for (let ei = 0; ei < graph.edges.length; ei++) {
501
589
  const edge = graph.edges[ei];
@@ -516,18 +604,37 @@ function buildGeometry(options) {
516
604
  const toNode = nodeById.get(edge.to);
517
605
  const intoHalfWidth = (toNode ? nodeWidthPx(toNode, contigThickness, nodeWidth, depthNorm) : contigThickness) / 2;
518
606
  const inView = (curves) => !viewportBounds || isBezierInBounds(curves, viewportBounds);
519
- const stroke = (curves, thickness, color) => {
520
- if (isDeletion) {
521
- for (const dash of dashCurves(
522
- curves,
523
- DELETION_DASH_PX / scale,
524
- yToX,
525
- viewportBounds
526
- )) {
527
- edgeCurves.push({ curves: dash, thickness, color });
607
+ const stroke = (curves, thickness, color, lane) => {
608
+ const push = (pieces, from = 0, to = 1) => {
609
+ if (!lane) {
610
+ edgeCurves.push({ curves: pieces, thickness, color });
611
+ return;
528
612
  }
529
- } else {
530
- edgeCurves.push({ curves, thickness, color });
613
+ const start = from === 0 ? lane.start : laneSlideAt(lane.start, lane.end, from);
614
+ const end = to === 1 ? lane.end : laneSlideAt(lane.start, lane.end, to);
615
+ edgeCurves.push({
616
+ curves: pieces,
617
+ thickness,
618
+ color,
619
+ walk: lane.walk,
620
+ pass: lane.pass,
621
+ normal: start.normal,
622
+ offsetX: start.offsetX,
623
+ endNormal: end.normal,
624
+ endOffsetX: end.offsetX
625
+ });
626
+ };
627
+ if (!isDeletion) {
628
+ push(curves);
629
+ return;
630
+ }
631
+ for (const dash of dashSpans(
632
+ curves,
633
+ DELETION_DASH_PX / scale,
634
+ yToX,
635
+ viewportBounds
636
+ )) {
637
+ push(dash.curves, dash.startAlong, dash.endAlong);
531
638
  }
532
639
  };
533
640
  const arrowOn = (curves) => {
@@ -549,32 +656,86 @@ function buildGeometry(options) {
549
656
  const arrowStart = arrows.length;
550
657
  const laneWalks = highlight?.walks.length && onWalk && !ribbons ? highlight.walks : void 0;
551
658
  if (laneWalks) {
552
- const fromNode = nodeById.get(edge.from);
553
- const width = fromNode ? nodeWidthPx(fromNode, contigThickness, nodeWidth, depthNorm) : contigThickness;
554
- const laneWidth = walkLaneWidthPx(width, laneWalks.length);
555
- const normals = pointNormalsOf(fromSegments, yToX);
556
- const { nx, ny } = (leavesStart(
557
- edge,
659
+ const laneWidthOf = (id) => {
660
+ let width = laneWidths.get(id);
661
+ if (width === void 0) {
662
+ const node = nodeById.get(id);
663
+ width = walkLaneWidthPx(
664
+ node ? nodeWidthPx(node, contigThickness, nodeWidth, depthNorm) : contigThickness,
665
+ laneWalks.length
666
+ );
667
+ laneWidths.set(id, width);
668
+ }
669
+ return width;
670
+ };
671
+ const endOf = (id, segments, atStart) => {
672
+ const at = atStart ? 0 : segments.length - 1;
673
+ return {
674
+ id,
675
+ laneWidth: laneWidthOf(id),
676
+ normal: laneNormalsOf(id, segments)[at] ?? { nx: 0, ny: 0 },
677
+ shift: laneShiftOf(id, at)
678
+ };
679
+ };
680
+ const from = endOf(
681
+ edge.from,
558
682
  fromSegments,
559
- baseCurves[0],
560
- stranded,
561
- yToX
562
- ) ? normals[0] : normals.at(-1)) ?? {
563
- nx: 0,
564
- ny: 0
683
+ leavesStart(edge, fromSegments, baseCurves[0], stranded, yToX)
684
+ );
685
+ const last = baseCurves.at(-1);
686
+ const to = threaded ? endOf(
687
+ edge.to,
688
+ toSegments,
689
+ nearerStart({ x: last.x1, y: last.y1 }, toSegments, yToX)
690
+ ) : from;
691
+ const slideOf = (end, offsetX) => ({
692
+ dx: end.shift.dx + end.normal.nx * offsetX,
693
+ dy: end.shift.dy + end.normal.ny * offsetX / yToX
694
+ });
695
+ const aheadKey = threads ? `${edge.from}>${edge.to}` : "";
696
+ const backKey = threads ? `${edge.to}>${edge.from}` : "";
697
+ const pairsOf = (lane) => {
698
+ const own = threads?.[lane]?.linkThreads;
699
+ if (!own?.size) {
700
+ return FIRST_THREADS;
701
+ }
702
+ const ahead = own.get(aheadKey);
703
+ const back = edgeKeys.has(backKey) ? void 0 : own.get(backKey);
704
+ if (!back) {
705
+ return ahead ?? FIRST_THREADS;
706
+ }
707
+ const turned = back.map(([a, b]) => [b, a]);
708
+ return ahead ? [...ahead, ...turned] : turned;
565
709
  };
710
+ const single = laneWalks.length === 1;
566
711
  laneWalks.forEach((walk, lane) => {
567
712
  if (!walk.edgeIndexes.has(ei)) {
568
713
  return;
569
714
  }
570
- const offset = (lane - (laneWalks.length - 1) / 2) * laneWidth * worldPerScreenPx;
571
- const curves = offset === 0 ? baseCurves : translateCurves(baseCurves, nx * offset, ny * offset / yToX);
572
- if (inView(curves)) {
573
- stroke(
574
- curves,
575
- laneWidth / 2,
576
- walk.colors.get(edge.from) ?? walk.colors.get(edge.to) ?? plainEdgeColor
715
+ for (const [pass, toPass] of pairsOf(lane)) {
716
+ const offsetX = single ? 0 : laneOffset(from.id, from.laneWidth, lane, pass) * worldPerScreenPx;
717
+ const start = { normal: from.normal, offsetX };
718
+ const end = threaded ? {
719
+ normal: to.normal,
720
+ offsetX: laneOffset(to.id, to.laneWidth, lane, toPass) * worldPerScreenPx
721
+ } : start;
722
+ const curves = threaded ? slideCurves(
723
+ baseCurves,
724
+ slideOf(from, start.offsetX),
725
+ slideOf(to, end.offsetX)
726
+ ) : offsetX === 0 ? baseCurves : translateCurves(
727
+ baseCurves,
728
+ from.normal.nx * offsetX,
729
+ from.normal.ny * offsetX / yToX
577
730
  );
731
+ if (inView(curves)) {
732
+ stroke(
733
+ curves,
734
+ laneHalfWidth(from.laneWidth),
735
+ walk.colors.get(edge.from) ?? walk.colors.get(edge.to) ?? plainEdgeColor,
736
+ { walk: lane, pass, start, end }
737
+ );
738
+ }
578
739
  }
579
740
  });
580
741
  if (edgeCurves.length > edgeCurveStart) {
@@ -644,17 +805,34 @@ function buildGeometry(options) {
644
805
  const lanes = highlight?.walks.length && !faded && !slots?.length ? highlight.walks : void 0;
645
806
  if (drawable && lanes) {
646
807
  const laneWidth = walkLaneWidthPx(width, lanes.length);
647
- const normals = pointNormalsOf(segments, yToX);
808
+ const normals = lanes.length > 1 ? laneNormalsOf(nodeId, segments) : [];
809
+ const points = lanes.length > 1 ? lanePointsOf(nodeId, segments) : segments;
648
810
  lanes.forEach((walk, lane) => {
649
811
  const laneColor = walk.colors.get(nodeId);
650
812
  if (laneColor === void 0) {
651
813
  return;
652
814
  }
653
- const offset = (lane - (lanes.length - 1) / 2) * laneWidth * worldPerScreenPx;
654
- nodeStrokes.push({
655
- points: lanes.length === 1 ? segments : offsetPolyline(segments, normals, offset, yToX),
656
- thickness: laneWidth / 2,
657
- color: laneColor
815
+ const onThreads = threads?.[lane]?.nodeThreads.get(nodeId) ?? ONE_PASS;
816
+ const thickness = laneHalfWidth(laneWidth);
817
+ onThreads.forEach((pass) => {
818
+ const offsetX = lanes.length === 1 ? 0 : laneOffset(nodeId, laneWidth, lane, pass) * worldPerScreenPx;
819
+ nodeStrokes.push(
820
+ lanes.length === 1 ? {
821
+ points: segments,
822
+ thickness,
823
+ color: laneColor,
824
+ walk: lane,
825
+ pass
826
+ } : {
827
+ points: offsetPolyline(points, normals, offsetX, yToX),
828
+ thickness,
829
+ color: laneColor,
830
+ walk: lane,
831
+ pass,
832
+ normals,
833
+ offsetX
834
+ }
835
+ );
658
836
  });
659
837
  });
660
838
  } else if (drawable && slots?.length && slotWidth >= MIN_PATH_STRIPE_PX) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clampZoom
3
- } from "./chunk-HTF32WSW.js";
3
+ } from "./chunk-S3ICPPXC.js";
4
4
 
5
5
  // src/viewport.ts
6
6
  function axisScaleOf(scale, pixelRows) {
@@ -9,7 +9,7 @@ import {
9
9
  edgeJoinOf,
10
10
  routedEdgeCurves,
11
11
  strandSides
12
- } from "./chunk-VACK24HF.js";
12
+ } from "./chunk-735MPLUL.js";
13
13
  import {
14
14
  groupBy
15
15
  } from "./chunk-BSOZW3FC.js";
@@ -131,7 +131,7 @@ function deletionEdges(cut) {
131
131
  const edge = graph.edges[edgeIndex];
132
132
  const from = byId.get(edge.from);
133
133
  const to = byId.get(edge.to);
134
- if (from !== void 0 && to !== void 0 && isBackbone(from) && isBackbone(to) && from.stable.refName === to.stable.refName) {
134
+ if (!edge.foldBridge && from !== void 0 && to !== void 0 && isBackbone(from) && isBackbone(to) && from.stable.refName === to.stable.refName) {
135
135
  const span = skippedSpan(edge, from, to, startsOf);
136
136
  const refName = from.stable.refName;
137
137
  const bp = span ? span.end - span.start : 0;
@@ -3,7 +3,7 @@ import {
3
3
  hasTubeMapPaths,
4
4
  tubeMapLayout,
5
5
  tubeMapReferenceLayout
6
- } from "./chunk-RB2MDFQU.js";
6
+ } from "./chunk-G4WQBRDS.js";
7
7
  import {
8
8
  sampleRowLayout
9
9
  } from "./chunk-XR2HMGAS.js";
@@ -15,7 +15,7 @@ import {
15
15
  } from "./chunk-UAFATXYA.js";
16
16
  import {
17
17
  walkRowLayout
18
- } from "./chunk-SENPGW4O.js";
18
+ } from "./chunk-VCUOYVLC.js";
19
19
  import {
20
20
  isBackbone,
21
21
  isOffReference
@@ -3,14 +3,14 @@ import {
3
3
  boxesGenes,
4
4
  rowPitch,
5
5
  rowSpan
6
- } from "./chunk-6XDTAKO7.js";
6
+ } from "./chunk-LA6JHEVV.js";
7
7
  import {
8
8
  el
9
9
  } from "./chunk-H2H4Y3TV.js";
10
10
  import {
11
11
  READOUT_ROOM,
12
12
  longestBar
13
- } from "./chunk-SENPGW4O.js";
13
+ } from "./chunk-VCUOYVLC.js";
14
14
  import {
15
15
  LABEL_CHAR_PX
16
16
  } from "./chunk-AB35TJST.js";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  bubbleSegmentIds,
3
3
  classifyBubble
4
- } from "./chunk-3Y2EFDID.js";
4
+ } from "./chunk-OIOAK7BS.js";
5
5
  import {
6
6
  svgPath
7
- } from "./chunk-VACK24HF.js";
7
+ } from "./chunk-735MPLUL.js";
8
8
  import {
9
9
  isBackbone
10
10
  } from "./chunk-RJWPJCIB.js";
@@ -7,15 +7,15 @@ import {
7
7
  } from "./chunk-AB35TJST.js";
8
8
  import {
9
9
  polylineMidpoint
10
- } from "./chunk-2VMKQKVO.js";
10
+ } from "./chunk-YIWN32ZX.js";
11
11
  import {
12
12
  edgeCurvesOf
13
- } from "./chunk-5NZRT7GL.js";
13
+ } from "./chunk-3CXZUC2Y.js";
14
14
  import {
15
15
  curveBounds,
16
16
  curveMidpoint,
17
17
  polylinePx
18
- } from "./chunk-VACK24HF.js";
18
+ } from "./chunk-735MPLUL.js";
19
19
 
20
20
  // src/graphLabels.ts
21
21
  var MIN_DELETION_LABEL_PX = 26;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ENGINE_DEFAULTS
3
- } from "./chunk-HTF32WSW.js";
3
+ } from "./chunk-S3ICPPXC.js";
4
4
 
5
5
  // src/figureSettings.ts
6
6
  var FIGURE_DEFAULTS = {
@@ -97,7 +97,8 @@ function visibleStretches(curves, lengths, bounds, yToX) {
97
97
  });
98
98
  return stretches;
99
99
  }
100
- function dashCurves(curves, dashWorld, yToX = 1, bounds) {
100
+ var dashCurves = (curves, dashWorld, yToX = 1, bounds) => dashSpans(curves, dashWorld, yToX, bounds).map((d) => d.curves);
101
+ function dashSpans(curves, dashWorld, yToX = 1, bounds) {
101
102
  const lengths = curves.map(
102
103
  (c) => Math.hypot(c.cx0 - c.x0, (c.cy0 - c.y0) * yToX) + Math.hypot(c.cx1 - c.cx0, (c.cy1 - c.cy0) * yToX) + Math.hypot(c.x1 - c.cx1, (c.y1 - c.cy1) * yToX)
103
104
  );
@@ -122,27 +123,49 @@ function dashCurves(curves, dashWorld, yToX = 1, bounds) {
122
123
  }
123
124
  }
124
125
  const dash = [];
126
+ const along = [];
125
127
  let start = 0;
126
128
  curves.forEach((c, k) => {
127
129
  const length = lengths[k];
128
130
  const end = start + length;
129
131
  if (length > 0 && end > from && start < to) {
130
- dash.push(
131
- subCurve(
132
- c,
133
- Math.max(0, (from - start) / length),
134
- Math.min(1, (to - start) / length)
135
- )
136
- );
132
+ const t0 = Math.max(0, (from - start) / length);
133
+ const t1 = Math.min(1, (to - start) / length);
134
+ dash.push(subCurve(c, t0, t1));
135
+ along.push((k + t0) / curves.length, (k + t1) / curves.length);
137
136
  }
138
137
  start = end;
139
138
  });
140
139
  if (dash.length) {
141
- out.push(dash);
140
+ out.push({
141
+ curves: dash,
142
+ startAlong: along[0],
143
+ endAlong: along.at(-1)
144
+ });
142
145
  }
143
146
  }
144
147
  return out;
145
148
  }
149
+ var slideAt = (from, to, along) => ({
150
+ dx: from.dx + (to.dx - from.dx) * along,
151
+ dy: from.dy + (to.dy - from.dy) * along
152
+ });
153
+ function slideCurves(curves, from, to) {
154
+ return curves.map((c, i) => {
155
+ const a = slideAt(from, to, i / curves.length);
156
+ const b = slideAt(from, to, (i + 1) / curves.length);
157
+ return {
158
+ x0: c.x0 + a.dx,
159
+ y0: c.y0 + a.dy,
160
+ cx0: c.cx0 + a.dx,
161
+ cy0: c.cy0 + a.dy,
162
+ cx1: c.cx1 + b.dx,
163
+ cy1: c.cy1 + b.dy,
164
+ x1: c.x1 + b.dx,
165
+ y1: c.y1 + b.dy
166
+ };
167
+ });
168
+ }
146
169
  function translateCurves(curves, dx, dy) {
147
170
  const out = new Array(curves.length);
148
171
  for (let i = 0; i < curves.length; i++) {
@@ -555,6 +578,9 @@ export {
555
578
  curveMidpoint,
556
579
  curveBounds,
557
580
  dashCurves,
581
+ dashSpans,
582
+ slideAt,
583
+ slideCurves,
558
584
  translateCurves,
559
585
  ownStrand,
560
586
  strandSides,