@jbrowse/bandage-core 11.8.0 → 11.10.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 (90) hide show
  1. package/dist/bubbles/bubbleHalos.js +6 -6
  2. package/dist/bubbles/classifyBubble.js +5 -5
  3. package/dist/bubbles/superbubbles.js +7 -7
  4. package/dist/chunks/{chunk-S4CH434Z.js → chunk-2A6Z2DHF.js} +1 -1
  5. package/dist/chunks/{chunk-6MD4VS2F.js → chunk-2MXFG3W7.js} +1 -1
  6. package/dist/chunks/{chunk-L2RQV23D.js → chunk-2NCZ5YYN.js} +1 -1
  7. package/dist/chunks/{chunk-ZKIH2USC.js → chunk-337LZP7C.js} +1 -1
  8. package/dist/chunks/{chunk-2RCKHCF7.js → chunk-3DHGSHC3.js} +1 -1
  9. package/dist/chunks/{chunk-3CXZUC2Y.js → chunk-3GORESBG.js} +1 -1
  10. package/dist/chunks/{chunk-R4XCTRIU.js → chunk-4BYGFDQB.js} +1 -1
  11. package/dist/chunks/{chunk-NHOXLUIL.js → chunk-4JDO7ZLN.js} +2 -2
  12. package/dist/chunks/{chunk-7GDNDQD7.js → chunk-4KBZ7WPP.js} +176 -101
  13. package/dist/chunks/{chunk-2H3ALI6L.js → chunk-53DZE3SA.js} +184 -161
  14. package/dist/chunks/{chunk-YF6T33PU.js → chunk-54C73ICS.js} +37 -17
  15. package/dist/chunks/{chunk-U6JPSXJ3.js → chunk-55DRWHBF.js} +9 -9
  16. package/dist/chunks/{chunk-4OVIUCSB.js → chunk-77O67GIB.js} +1 -1
  17. package/dist/chunks/{chunk-7PEYA3NA.js → chunk-7YSIP3O2.js} +2 -2
  18. package/dist/chunks/{chunk-LA6JHEVV.js → chunk-ALOF5SOT.js} +1 -1
  19. package/dist/chunks/{chunk-3XYLEK4H.js → chunk-ARXDNQLF.js} +1 -1
  20. package/dist/chunks/{chunk-6CXLLJ2C.js → chunk-AURNOR27.js} +3 -3
  21. package/dist/chunks/{chunk-G4WQBRDS.js → chunk-BDS5VZYZ.js} +3 -3
  22. package/dist/chunks/{chunk-MO4DIRHD.js → chunk-CHGTUO3C.js} +13 -13
  23. package/dist/chunks/{chunk-X5ULFAMM.js → chunk-HEYIAMTC.js} +2 -2
  24. package/dist/chunks/{chunk-S7BCZVRK.js → chunk-HIN56TLA.js} +1 -1
  25. package/dist/chunks/{chunk-YIWN32ZX.js → chunk-HNNP5QUN.js} +1 -1
  26. package/dist/chunks/{chunk-XOIYBEU7.js → chunk-I53QYITQ.js} +1 -1
  27. package/dist/chunks/{chunk-SDDMV2MM.js → chunk-IZKM4NY7.js} +1 -1
  28. package/dist/chunks/{chunk-SIXFXXRI.js → chunk-J7RNXBXA.js} +3 -3
  29. package/dist/chunks/{chunk-735MPLUL.js → chunk-JJV2GT2Z.js} +22 -14
  30. package/dist/chunks/{chunk-S3ICPPXC.js → chunk-JVT3XTKN.js} +3 -3
  31. package/dist/chunks/{chunk-J4PDHWP2.js → chunk-KKHXMJEE.js} +1 -1
  32. package/dist/chunks/{chunk-22ZMVREZ.js → chunk-NAYS472K.js} +1 -1
  33. package/dist/chunks/{chunk-OIOAK7BS.js → chunk-NWEVR2OQ.js} +1 -1
  34. package/dist/chunks/{chunk-VSRRIFRF.js → chunk-P2GJBFNA.js} +1 -1
  35. package/dist/chunks/{chunk-N2GAA7RB.js → chunk-RT4U3DH3.js} +1 -1
  36. package/dist/chunks/{chunk-AXE3RR7J.js → chunk-S6E3PMH7.js} +1 -1
  37. package/dist/chunks/{chunk-NQWEYJDD.js → chunk-SPEB75UH.js} +1 -1
  38. package/dist/chunks/{chunk-4YPCUVMC.js → chunk-SZYFZNCO.js} +2 -2
  39. package/dist/chunks/{chunk-G3GLGDKV.js → chunk-TQ26XEFL.js} +2 -2
  40. package/dist/chunks/{chunk-N4AJV4GH.js → chunk-UVRCXTBY.js} +37 -10
  41. package/dist/chunks/{chunk-YEDZ37PH.js → chunk-VNCHWWLG.js} +1 -1
  42. package/dist/chunks/{chunk-JKIAHYAW.js → chunk-VQ353UDK.js} +1 -1
  43. package/dist/chunks/{chunk-R3NPBUKT.js → chunk-YQAZNH37.js} +7 -7
  44. package/dist/cli/figure.js +28 -28
  45. package/dist/cli/fold.js +6 -6
  46. package/dist/deletionEdges.js +2 -2
  47. package/dist/figure.js +24 -24
  48. package/dist/figureData.js +22 -22
  49. package/dist/figureScene.js +15 -15
  50. package/dist/figureSettings.js +6 -6
  51. package/dist/foldVariants.js +2 -2
  52. package/dist/genes/genePins.js +3 -3
  53. package/dist/graphLabels.js +4 -4
  54. package/dist/index.js +38 -38
  55. package/dist/labelLayout.js +8 -8
  56. package/dist/layout/forceCache.js +6 -6
  57. package/dist/layout/mergeRuns.js +2 -2
  58. package/dist/layout/orientToReference.js +2 -2
  59. package/dist/layout/tubeMapLayout.js +7 -7
  60. package/dist/layout/walkRowDraw.js +9 -9
  61. package/dist/layout/walkStrip.js +10 -10
  62. package/dist/layoutModes.js +8 -8
  63. package/dist/pathColors.js +5 -5
  64. package/dist/pipeline.js +5 -5
  65. package/dist/referenceStrip.js +9 -9
  66. package/dist/renderer/GeometryBuilder.js +8 -8
  67. package/dist/renderer/walkLanes.js +4 -2
  68. package/dist/tubeMap/axis.js +5 -5
  69. package/dist/tubeMap/bundle.js +8 -8
  70. package/dist/tubeMap/coarsen.js +8 -8
  71. package/dist/tubeMap/deviations.js +9 -9
  72. package/dist/tubeMap/draw.js +3 -3
  73. package/dist/tubeMap/genes.js +6 -6
  74. package/dist/tubeMap/nodeColors.js +9 -9
  75. package/dist/tubeMap/reads.js +2 -2
  76. package/dist/types/renderer/walkLanes.d.ts +19 -2
  77. package/dist/types/util/geometry.d.ts +1 -1
  78. package/dist/types/version.d.ts +1 -1
  79. package/dist/types/walkEncoding.d.ts +8 -2
  80. package/dist/types/walkHighlight.d.ts +2 -0
  81. package/dist/util/SpatialIndex.js +4 -4
  82. package/dist/util/edgeCurves.js +3 -3
  83. package/dist/util/geometry.js +1 -1
  84. package/dist/util/hitDetection.js +5 -5
  85. package/dist/version.js +1 -1
  86. package/dist/viewport.js +6 -6
  87. package/dist/walkEncoding.js +13 -11
  88. package/dist/walkHighlight.js +10 -10
  89. package/dist/walkKey.js +5 -5
  90. package/package.json +1 -1
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  bubbleHalos,
3
3
  coversGraph
4
- } from "../chunks/chunk-4YPCUVMC.js";
5
- import "../chunks/chunk-OIOAK7BS.js";
4
+ } from "../chunks/chunk-SZYFZNCO.js";
5
+ import "../chunks/chunk-NWEVR2OQ.js";
6
6
  import "../chunks/chunk-FX4RDMDN.js";
7
- import "../chunks/chunk-6CXLLJ2C.js";
7
+ import "../chunks/chunk-AURNOR27.js";
8
8
  import "../chunks/chunk-HMXCN6PG.js";
9
9
  import "../chunks/chunk-AB35TJST.js";
10
- import "../chunks/chunk-YIWN32ZX.js";
11
- import "../chunks/chunk-3CXZUC2Y.js";
10
+ import "../chunks/chunk-HNNP5QUN.js";
11
+ import "../chunks/chunk-3GORESBG.js";
12
12
  import "../chunks/chunk-TLWXLNLY.js";
13
13
  import "../chunks/chunk-3YBP46PB.js";
14
- import "../chunks/chunk-735MPLUL.js";
14
+ import "../chunks/chunk-JJV2GT2Z.js";
15
15
  import "../chunks/chunk-CPMHA4W5.js";
16
16
  import "../chunks/chunk-ZPZ7GNBT.js";
17
17
  import "../chunks/chunk-BSOZW3FC.js";
@@ -3,16 +3,16 @@ import {
3
3
  BUBBLE_KIND_NAMES,
4
4
  bubbleSegmentIds,
5
5
  classifyBubble
6
- } from "../chunks/chunk-OIOAK7BS.js";
6
+ } from "../chunks/chunk-NWEVR2OQ.js";
7
7
  import "../chunks/chunk-FX4RDMDN.js";
8
- import "../chunks/chunk-6CXLLJ2C.js";
8
+ import "../chunks/chunk-AURNOR27.js";
9
9
  import "../chunks/chunk-HMXCN6PG.js";
10
10
  import "../chunks/chunk-AB35TJST.js";
11
- import "../chunks/chunk-YIWN32ZX.js";
12
- import "../chunks/chunk-3CXZUC2Y.js";
11
+ import "../chunks/chunk-HNNP5QUN.js";
12
+ import "../chunks/chunk-3GORESBG.js";
13
13
  import "../chunks/chunk-TLWXLNLY.js";
14
14
  import "../chunks/chunk-3YBP46PB.js";
15
- import "../chunks/chunk-735MPLUL.js";
15
+ import "../chunks/chunk-JJV2GT2Z.js";
16
16
  import "../chunks/chunk-CPMHA4W5.js";
17
17
  import "../chunks/chunk-ZPZ7GNBT.js";
18
18
  import "../chunks/chunk-BSOZW3FC.js";
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  graphBubbles,
3
3
  superbubblesFromGraph
4
- } from "../chunks/chunk-SIXFXXRI.js";
5
- import "../chunks/chunk-4YPCUVMC.js";
4
+ } from "../chunks/chunk-J7RNXBXA.js";
5
+ import "../chunks/chunk-SZYFZNCO.js";
6
6
  import "../chunks/chunk-RFG42VIO.js";
7
- import "../chunks/chunk-OIOAK7BS.js";
7
+ import "../chunks/chunk-NWEVR2OQ.js";
8
8
  import "../chunks/chunk-FX4RDMDN.js";
9
9
  import "../chunks/chunk-MHZTTLBU.js";
10
10
  import "../chunks/chunk-UAFATXYA.js";
11
11
  import "../chunks/chunk-VX656OAZ.js";
12
- import "../chunks/chunk-6CXLLJ2C.js";
12
+ import "../chunks/chunk-AURNOR27.js";
13
13
  import "../chunks/chunk-HMXCN6PG.js";
14
14
  import "../chunks/chunk-AB35TJST.js";
15
- import "../chunks/chunk-YIWN32ZX.js";
16
- import "../chunks/chunk-3CXZUC2Y.js";
15
+ import "../chunks/chunk-HNNP5QUN.js";
16
+ import "../chunks/chunk-3GORESBG.js";
17
17
  import "../chunks/chunk-TLWXLNLY.js";
18
18
  import "../chunks/chunk-3YBP46PB.js";
19
- import "../chunks/chunk-735MPLUL.js";
19
+ import "../chunks/chunk-JJV2GT2Z.js";
20
20
  import "../chunks/chunk-CPMHA4W5.js";
21
21
  import "../chunks/chunk-ZPZ7GNBT.js";
22
22
  import "../chunks/chunk-BSOZW3FC.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  engineKey,
3
3
  forceLayout
4
- } from "./chunk-S3ICPPXC.js";
4
+ } from "./chunk-JVT3XTKN.js";
5
5
 
6
6
  // src/layout/forceCache.ts
7
7
  var DEFAULT_SIZE = 4;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ENGINE_DEFAULTS
3
- } from "./chunk-S3ICPPXC.js";
3
+ } from "./chunk-JVT3XTKN.js";
4
4
 
5
5
  // src/figureSettings.ts
6
6
  var FIGURE_DEFAULTS = {
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var version = "11.8.0";
2
+ var version = "11.10.0";
3
3
 
4
4
  export {
5
5
  version
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  computeColorSchemeRange,
3
3
  getNodeColor
4
- } from "./chunk-2H3ALI6L.js";
4
+ } from "./chunk-53DZE3SA.js";
5
5
  import {
6
6
  abgrToCssRgba
7
7
  } from "./chunk-G2FD7S3C.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  clampZoom
3
- } from "./chunk-S3ICPPXC.js";
3
+ } from "./chunk-JVT3XTKN.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-735MPLUL.js";
12
+ } from "./chunk-JJV2GT2Z.js";
13
13
  import {
14
14
  groupBy
15
15
  } from "./chunk-BSOZW3FC.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ownStrand
3
- } from "./chunk-735MPLUL.js";
3
+ } from "./chunk-JJV2GT2Z.js";
4
4
  import {
5
5
  groupBy
6
6
  } from "./chunk-BSOZW3FC.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  EdgeSpatialIndex,
3
3
  SpatialIndex
4
- } from "./chunk-7PEYA3NA.js";
4
+ } from "./chunk-7YSIP3O2.js";
5
5
  import {
6
6
  weakMemo
7
7
  } from "./chunk-HMXCN6PG.js";
@@ -9,7 +9,7 @@ import {
9
9
  pathRibbonOffsets,
10
10
  translateCurves,
11
11
  yToXOf
12
- } from "./chunk-735MPLUL.js";
12
+ } from "./chunk-JJV2GT2Z.js";
13
13
 
14
14
  // src/util/hitDetection.ts
15
15
  function distanceToSegment(px, py, x1, y1, x2, y2) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  slideAt
3
- } from "./chunk-735MPLUL.js";
3
+ } from "./chunk-JJV2GT2Z.js";
4
4
 
5
5
  // src/renderer/walkLanes.ts
6
6
  var THREAD_PX = 2;
@@ -53,9 +53,9 @@ function laneSlideAt(start, end, along) {
53
53
  }
54
54
  var gapOf = (a, b) => Math.hypot(b.x - a.x, b.y - a.y);
55
55
  function arcOf(run) {
56
- const s = [0];
56
+ const s = new Float64Array(run.length);
57
57
  for (let i = 1; i < run.length; i++) {
58
- s.push(s[i - 1] + gapOf(run[i - 1], run[i]));
58
+ s[i] = s[i - 1] + gapOf(run[i - 1], run[i]);
59
59
  }
60
60
  return s;
61
61
  }
@@ -63,9 +63,11 @@ function laneRuns(routes, nodePositions, yToX, jump) {
63
63
  const seen = /* @__PURE__ */ new Set();
64
64
  const owns = routes.map(
65
65
  (route) => route.map((id) => {
66
- const first = !!nodePositions[id]?.length && !seen.has(id);
66
+ if (seen.has(id)) {
67
+ return false;
68
+ }
67
69
  seen.add(id);
68
- return first;
70
+ return !!nodePositions[id]?.length;
69
71
  })
70
72
  );
71
73
  const gap = (a, b) => Math.hypot(b.x - a.x, b.y * yToX - a.y);
@@ -221,43 +223,46 @@ function cutCurls(run, close, length) {
221
223
  return out;
222
224
  }
223
225
  function rounded(run, half) {
226
+ const n = run.length;
224
227
  const s = arcOf(run);
225
- const end = s.at(-1);
226
- const sums = [{ w: 0, x: 0, y: 0 }];
227
- run.forEach((p, i) => {
228
- const w = (s[Math.min(i + 1, run.length - 1)] - s[Math.max(i - 1, 0)]) / 2;
229
- const last = sums[i];
230
- sums.push({ w: last.w + w, x: last.x + w * p.x, y: last.y + w * p.y });
231
- });
232
- const firstAtOrAfter = (at) => {
233
- let lo = 0;
234
- let hi = s.length;
235
- while (lo < hi) {
236
- const mid = lo + hi >> 1;
237
- if (s[mid] < at) {
238
- lo = mid + 1;
239
- } else {
240
- hi = mid;
241
- }
242
- }
243
- return lo;
244
- };
245
- return run.map((p, i) => {
228
+ const end = s[n - 1];
229
+ const sumW = new Float64Array(n + 1);
230
+ const sumX = new Float64Array(n + 1);
231
+ const sumY = new Float64Array(n + 1);
232
+ for (let i = 0; i < n; i++) {
233
+ const p = run[i];
234
+ const w = (s[Math.min(i + 1, n - 1)] - s[Math.max(i - 1, 0)]) / 2;
235
+ sumW[i + 1] = sumW[i] + w;
236
+ sumX[i + 1] = sumX[i] + w * p.x;
237
+ sumY[i + 1] = sumY[i] + w * p.y;
238
+ }
239
+ const out = new Array(n);
240
+ let lo = 0;
241
+ let hi = 0;
242
+ for (let i = 0; i < n; i++) {
243
+ const p = run[i];
246
244
  const reach = Math.min(half, s[i], end - s[i]);
247
- const lo = firstAtOrAfter(s[i] - reach);
248
- const hi = firstAtOrAfter(s[i] + reach + 1e-9 * (1 + end));
249
- const w = sums[hi].w - sums[lo].w;
250
- return w > 0 ? {
251
- x: (sums[hi].x - sums[lo].x) / w,
252
- y: (sums[hi].y - sums[lo].y) / w
253
- } : { x: p.x, y: p.y };
254
- });
245
+ const from = s[i] - reach;
246
+ const to = s[i] + reach + 1e-9 * (1 + end);
247
+ while (lo < n && s[lo] < from) {
248
+ lo++;
249
+ }
250
+ while (hi < n && s[hi] < to) {
251
+ hi++;
252
+ }
253
+ const w = sumW[hi] - sumW[lo];
254
+ out[i] = w > 0 ? { x: (sumX[hi] - sumX[lo]) / w, y: (sumY[hi] - sumY[lo]) / w } : { x: p.x, y: p.y };
255
+ }
256
+ return out;
255
257
  }
256
258
  function fieldSetter(field, nodePositions) {
257
259
  return ({ id, index }, value) => {
258
- const own = field.get(id) ?? new Array(nodePositions[id].length);
260
+ let own = field.get(id);
261
+ if (!own) {
262
+ own = new Array(nodePositions[id].length);
263
+ field.set(id, own);
264
+ }
259
265
  own[index] = value;
260
- field.set(id, own);
261
266
  };
262
267
  }
263
268
  function laneLines(lanes, nodePositions, yToX, reach, band, smooth = true) {
@@ -351,17 +356,44 @@ function windowMean(s, v, half, counted = () => true) {
351
356
  return w > 0 ? (sumWV[hi] - sumWV[lo]) / w : value;
352
357
  });
353
358
  }
359
+ var ONE_THREAD = [0];
360
+ function repeats(passes) {
361
+ for (const p of passes.values()) {
362
+ if (p > 1) {
363
+ return true;
364
+ }
365
+ }
366
+ return false;
367
+ }
354
368
  function walkThreads(route, passes, nodePositions, yToX, reach) {
355
- if (![...passes.values()].some((p) => p > 1)) {
356
- return { span: passes, nodeThreads: /* @__PURE__ */ new Map(), linkThreads: /* @__PURE__ */ new Map() };
369
+ if (!repeats(passes)) {
370
+ return {
371
+ span: passes,
372
+ nodeThreads: /* @__PURE__ */ new Map(),
373
+ threadPasses: /* @__PURE__ */ new Map(),
374
+ linkThreads: /* @__PURE__ */ new Map()
375
+ };
357
376
  }
358
- const span = /* @__PURE__ */ new Map();
359
- const visits = /* @__PURE__ */ new Map();
360
- const wanted = /* @__PURE__ */ new Map();
377
+ const index = /* @__PURE__ */ new Map();
378
+ const ids = [];
379
+ const widths = [];
380
+ const visits = [];
361
381
  const steps = [];
382
+ const stepVisits = [];
383
+ const stepWants = [];
362
384
  for (const piece of route) {
363
385
  const points = [];
386
+ const nodes = [];
364
387
  for (const id of piece) {
388
+ let k = index.get(id);
389
+ if (k === void 0) {
390
+ k = ids.length;
391
+ index.set(id, k);
392
+ ids.push(id);
393
+ widths.push(0);
394
+ visits.push(0);
395
+ }
396
+ nodes.push(k);
365
397
  const segments = nodePositions[id];
366
398
  const mid = segments?.[Math.floor(segments.length / 2)];
367
399
  points.push(
@@ -371,85 +403,94 @@ function walkThreads(route, passes, nodePositions, yToX, reach) {
371
403
  const s = arcOf(points);
372
404
  const p = piece.map((id) => passes.get(id) ?? 1);
373
405
  const most = windowed(s, p, reach / 2, 1);
374
- const copy = piece.map((id) => {
375
- const visit = (visits.get(id) ?? 0) + 1;
376
- visits.set(id, visit);
377
- return visit;
378
- });
379
- const full = p.map((v, i) => v === most[i]);
380
- const before = [];
406
+ const copy = nodes.map((k) => ++visits[k]);
407
+ const n = piece.length;
408
+ const before = new Int32Array(n);
381
409
  let last = -1;
382
- for (let i = 0; i < piece.length; i++) {
383
- last = full[i] ? i : last;
384
- before.push(last);
410
+ for (let i = 0; i < n; i++) {
411
+ last = p[i] === most[i] ? i : last;
412
+ before[i] = last;
385
413
  }
386
- const after = new Array(piece.length);
414
+ const after = new Int32Array(n);
387
415
  last = -1;
388
- for (let i = piece.length - 1; i >= 0; i--) {
389
- last = full[i] ? i : last;
416
+ for (let i = n - 1; i >= 0; i--) {
417
+ last = p[i] === most[i] ? i : last;
390
418
  after[i] = last;
391
419
  }
392
- const own = [];
393
- piece.forEach((id, i) => {
420
+ const wants = new Array(n);
421
+ for (let i = 0; i < n; i++) {
394
422
  const b = before[i];
395
423
  const a = after[i];
396
424
  const nearest = b < 0 ? a : a < 0 ? b : s[i] - s[b] <= s[a] - s[i] ? b : a;
397
- const thread = Math.min(copy[nearest], most[i]) - 1;
398
- span.set(id, Math.max(span.get(id) ?? 0, most[i]));
399
- const list = wanted.get(id) ?? [];
400
- list.push({ visit: copy[i], thread });
401
- wanted.set(id, list);
402
- own.push({ id, visit: copy[i] });
403
- });
404
- steps.push(own);
425
+ wants[i] = Math.min(copy[nearest], most[i]) - 1;
426
+ widths[nodes[i]] = Math.max(widths[nodes[i]], most[i]);
427
+ }
428
+ steps.push(nodes);
429
+ stepVisits.push(copy);
430
+ stepWants.push(wants);
405
431
  }
406
- const threadOf = /* @__PURE__ */ new Map();
407
- const nodeThreads = /* @__PURE__ */ new Map();
408
- for (const [id, list] of wanted) {
409
- const width = span.get(id);
410
- const taken = /* @__PURE__ */ new Set();
411
- const free = (want) => {
412
- for (let d = 0; d < width; d++) {
413
- for (const c of [want - d, want + d]) {
414
- if (c >= 0 && c < width && !taken.has(c)) {
415
- return c;
416
- }
432
+ const taken = [];
433
+ const threadOf = [];
434
+ const free = (k, want) => {
435
+ const width = widths[k];
436
+ const own = taken[k] ??= /* @__PURE__ */ new Set();
437
+ for (let d = 0; d < width; d++) {
438
+ for (const c of [want - d, want + d]) {
439
+ if (c >= 0 && c < width && !own.has(c)) {
440
+ return c;
417
441
  }
418
442
  }
419
- return want;
420
- };
421
- const byVisit = [];
422
- for (const { visit, thread } of list) {
423
- const t = free(thread);
424
- taken.add(t);
425
- byVisit[visit] = t;
426
443
  }
427
- threadOf.set(id, byVisit);
444
+ return want;
445
+ };
446
+ steps.forEach((nodes, piece) => {
447
+ nodes.forEach((k, i) => {
448
+ if (widths[k] > 1) {
449
+ const t = free(k, stepWants[piece][i]);
450
+ taken[k].add(t);
451
+ (threadOf[k] ??= [])[stepVisits[piece][i]] = t;
452
+ }
453
+ });
454
+ });
455
+ const span = /* @__PURE__ */ new Map();
456
+ const nodeThreads = /* @__PURE__ */ new Map();
457
+ const threadPasses = /* @__PURE__ */ new Map();
458
+ ids.forEach((id, k) => {
459
+ span.set(id, widths[k]);
428
460
  nodeThreads.set(
429
461
  id,
430
- [...taken].sort((a, b) => a - b)
462
+ taken[k] ? [...taken[k]].sort((a, b) => a - b) : ONE_THREAD
431
463
  );
432
- }
464
+ const passOf = [];
465
+ threadOf[k]?.forEach((thread, visit) => {
466
+ passOf[thread] = visit - 1;
467
+ });
468
+ threadPasses.set(id, passOf);
469
+ });
433
470
  const linkThreads = /* @__PURE__ */ new Map();
434
- for (const own of steps) {
435
- own.forEach((cur, i) => {
436
- const prev = own[i - 1];
437
- if (!prev) {
438
- return;
439
- }
440
- const key = `${prev.id}>${cur.id}`;
471
+ steps.forEach((nodes, piece) => {
472
+ const visit = stepVisits[piece];
473
+ for (let i = 1; i < nodes.length; i++) {
474
+ const from = nodes[i - 1];
475
+ const to = nodes[i];
441
476
  const pair = [
442
- threadOf.get(prev.id)[prev.visit],
443
- threadOf.get(cur.id)[cur.visit]
477
+ threadOf[from]?.[visit[i - 1]] ?? 0,
478
+ threadOf[to]?.[visit[i]] ?? 0
444
479
  ];
445
- const list = linkThreads.get(key) ?? [];
446
- if (!list.some(([a, b]) => a === pair[0] && b === pair[1])) {
480
+ let ahead = linkThreads.get(ids[from]);
481
+ if (!ahead) {
482
+ ahead = /* @__PURE__ */ new Map();
483
+ linkThreads.set(ids[from], ahead);
484
+ }
485
+ const list = ahead.get(ids[to]);
486
+ if (!list) {
487
+ ahead.set(ids[to], [pair]);
488
+ } else if (!list.some(([a, b]) => a === pair[0] && b === pair[1])) {
447
489
  list.push(pair);
448
490
  }
449
- linkThreads.set(key, list);
450
- });
451
- }
452
- return { span, nodeThreads, linkThreads };
491
+ }
492
+ });
493
+ return { span, nodeThreads, threadPasses, linkThreads };
453
494
  }
454
495
  function bandSpans(lanes, spans, { reach, taper }) {
455
496
  const out = /* @__PURE__ */ new Map();
@@ -480,6 +521,39 @@ function bandSpans(lanes, spans, { reach, taper }) {
480
521
  });
481
522
  return out;
482
523
  }
524
+ function liftLanes(walks, nodePositions, yToX, worldPerScreenPx) {
525
+ const threaded = threadsPasses(walks);
526
+ const passes = walks.map((w) => w.mostPasses);
527
+ const reach = THREAD_REACH_PX * worldPerScreenPx;
528
+ const runs = laneRuns(
529
+ walks.flatMap((w) => w.route),
530
+ nodePositions,
531
+ yToX,
532
+ LANE_SMOOTHING_PX * worldPerScreenPx
533
+ );
534
+ const lines = laneLines(
535
+ runs,
536
+ nodePositions,
537
+ yToX,
538
+ LANE_SMOOTHING_PX * worldPerScreenPx,
539
+ bandWidthPx(passes) * (threaded ? bandScale(passes) : 1) * worldPerScreenPx,
540
+ threaded
541
+ );
542
+ const threads = threaded ? walks.map((w) => walkThreads(w.route, w.passes, nodePositions, yToX, reach)) : void 0;
543
+ const spans = threads ? bandSpans(
544
+ runs,
545
+ threads.map((t) => t.span),
546
+ { reach, taper: THREAD_TAPER_PX * worldPerScreenPx }
547
+ ) : void 0;
548
+ const furthestShift = { dx: 0, dy: 0 };
549
+ for (const own of lines.shifts.values()) {
550
+ for (const shift of own) {
551
+ furthestShift.dx = Math.max(furthestShift.dx, Math.abs(shift?.dx ?? 0));
552
+ furthestShift.dy = Math.max(furthestShift.dy, Math.abs(shift?.dy ?? 0));
553
+ }
554
+ }
555
+ return { lines, threads, spans, furthestShift };
556
+ }
483
557
 
484
558
  export {
485
559
  THREAD_PX,
@@ -500,5 +574,6 @@ export {
500
574
  laneRuns,
501
575
  laneLines,
502
576
  walkThreads,
503
- bandSpans
577
+ bandSpans,
578
+ liftLanes
504
579
  };